@@ -28,29 +28,32 @@ import {
2828  ReadAuthorizationModelResponse , 
2929  ReadAuthorizationModelsResponse , 
3030  ReadChangesResponse , 
31+   ReadRequest , 
3132  ReadResponse , 
3233  TupleKey  as  ApiTupleKey , 
3334  WriteAuthorizationModelRequest , 
3435  WriteAuthorizationModelResponse , 
36+   WriteRequest , 
3537}  from  "./apiModel" ; 
3638import  {  BaseAPI  }  from  "./base" ; 
3739import  {  CallResult ,  PromiseResult  }  from  "./common" ; 
3840import  {  Configuration ,  RetryParams ,  UserConfigurationParams  }  from  "./configuration" ; 
39- import  {  FgaError  }  from  "./errors" ; 
41+ import  {  FgaError ,   FgaRequiredParamError  }  from  "./errors" ; 
4042import  { 
4143  chunkSequentialCall , 
4244  generateRandomIdWithNonUniqueFallback , 
4345  setHeaderIfNotSet , 
4446  setNotEnumerableProperty , 
4547}  from  "./utils" ; 
4648
47- export  type  OpenFgaClientConfig  =  ( UserConfigurationParams  |  Configuration )  &  { 
49+ export  type  ClientConfiguration  =  ( UserConfigurationParams  |  Configuration )  &  { 
4850  authorizationModelId ?: string ; 
4951} 
5052
51- type  TupleKey  =  Required < ApiTupleKey > ; 
53+ export   type  ClientTupleKey  =  Required < ApiTupleKey > ; 
5254
5355const  DEFAULT_MAX_METHOD_PARALLEL_REQS  =  10 ; 
56+ const  DEFAULT_WAIT_TIME_BETWEEN_CHUNKS_IN_MS  =  100 ; 
5457const  DEFAULT_MAX_RETRY_OVERRIDE  =  15 ; 
5558const  CLIENT_METHOD_HEADER  =  "X-OpenFGA-Client-Method" ; 
5659const  CLIENT_BULK_REQUEST_ID_HEADER  =  "X-OpenFGA-Client-Bulk-Request-Id" ; 
@@ -68,7 +71,7 @@ export type ClientRequestOptsWithAuthZModelId = ClientRequestOpts  & Authorizati
6871
6972export  type  PaginationOptions  =  {  pageSize ?: number ,  continuationToken ?: string ;  } ; 
7073
71- export  type  ClientCheckRequest  =  TupleKey  &  {  contextualTuples ?: TupleKey [ ]  } ; 
74+ export  type  ClientCheckRequest  =  ClientTupleKey  &  {  contextualTuples ?: ClientTupleKey [ ]  } ; 
7275
7376export  type  ClientBatchCheckRequest  =  ClientCheckRequest [ ] ; 
7477
@@ -90,16 +93,18 @@ export interface ClientWriteRequestOpts {
9093  transaction ?: { 
9194    disable ?: boolean ; 
9295    maxPerChunk ?: number ; 
96+     waitTimeBetweenChunksInMs ?: number ; 
9397  } 
9498} 
9599
96100export  interface  BatchCheckRequestOpts  { 
97101  maxParallelRequests ?: number ; 
102+   waitTimeBetweenChunksInMs ?: number ; 
98103} 
99104
100105export  interface  ClientWriteRequest  { 
101-   writes ?: TupleKey [ ] ; 
102-   deletes ?: TupleKey [ ] ; 
106+   writes ?: ClientTupleKey [ ] ; 
107+   deletes ?: ClientTupleKey [ ] ; 
103108} 
104109
105110export  enum  ClientWriteStatus  { 
@@ -108,18 +113,18 @@ export enum ClientWriteStatus {
108113} 
109114
110115export  interface  ClientWriteResponse  { 
111-   writes : {  tuple_key : TupleKey ,  status : ClientWriteStatus ,  err ?: Error  } [ ] ; 
112-   deletes : {  tuple_key : TupleKey ,  status : ClientWriteStatus ,  err ?: Error  } [ ] ; 
116+   writes : {  tuple_key : ClientTupleKey ,  status : ClientWriteStatus ,  err ?: Error  } [ ] ; 
117+   deletes : {  tuple_key : ClientTupleKey ,  status : ClientWriteStatus ,  err ?: Error  } [ ] ; 
113118} 
114119
115120export  interface  ClientReadChangesRequest  { 
116121  type : string ; 
117122} 
118123
119- export  type  ClientExpandRequest  =  Pick < TupleKey ,  "relation"  |  "object" > ; 
124+ export  type  ClientExpandRequest  =  Pick < ClientTupleKey ,  "relation"  |  "object" > ; 
120125export  type  ClientReadRequest  =  ApiTupleKey ; 
121- export  type  ClientListObjectsRequest  =  Omit < ListObjectsRequest ,  "authorization_model_id"  |  "contextual_tuples" >  &  {  contextualTuples ?: TupleKey [ ]  } ; 
122- export  type  ClientWriteAssertionsRequest  =  ( TupleKey  &  Pick < Assertion ,  "expectation" > ) [ ] ; 
126+ export  type  ClientListObjectsRequest  =  Omit < ListObjectsRequest ,  "authorization_model_id"  |  "contextual_tuples" >  &  {  contextualTuples ?: ClientTupleKey [ ]  } ; 
127+ export  type  ClientWriteAssertionsRequest  =  ( ClientTupleKey  &  Pick < Assertion ,  "expectation" > ) [ ] ; 
123128
124129function  getObjectFromString ( objectString : string ) : {  type : string ;  id : string  }  { 
125130  const  [ type ,  id ]  =  objectString . split ( ":" ) ; 
@@ -130,14 +135,14 @@ export class OpenFgaClient extends BaseAPI {
130135  public  api : OpenFgaApi ; 
131136  public  authorizationModelId ?: string ; 
132137
133-   constructor ( configuration : OpenFgaClientConfig ,  protected  axios ?: AxiosStatic )  { 
138+   constructor ( configuration : ClientConfiguration ,  protected  axios ?: AxiosStatic )  { 
134139    super ( configuration ,  axios ) ; 
135140
136141    this . api  =  new  OpenFgaApi ( this . configuration ) ; 
137142    this . authorizationModelId  =  configuration . authorizationModelId ; 
138143  } 
139144
140-   private  getAuthorizationModelId ( options : AuthorizationModelIdOpts  =  { } )  { 
145+   protected  getAuthorizationModelId ( options : AuthorizationModelIdOpts  =  { } )  { 
141146    return  options ?. authorizationModelId  ||  this . authorizationModelId ; 
142147  } 
143148
@@ -241,7 +246,7 @@ export class OpenFgaClient extends BaseAPI {
241246  async  readAuthorizationModel ( options : ClientRequestOptsWithAuthZModelId  =  { } ) : PromiseResult < ReadAuthorizationModelResponse >  { 
242247    const  authorizationModelId  =  this . getAuthorizationModelId ( options ) ; 
243248    if  ( ! authorizationModelId )  { 
244-       throw  new  Error ( "authorization_model_id_required ") ; 
249+       throw  new  FgaRequiredParamError ( "ClientConfiguration" ,   "authorizationModelId ") ; 
245250    } 
246251    return  this . api . readAuthorizationModel ( authorizationModelId ,  options ) ; 
247252  } 
@@ -294,8 +299,15 @@ export class OpenFgaClient extends BaseAPI {
294299   * @param  {number } [options.retryParams.maxRetry] - Override the max number of retries on each API request 
295300   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
296301   */ 
297-   async  read ( body : ClientReadRequest ,  options : ClientRequestOpts  =  { } ) : PromiseResult < ReadResponse >  { 
298-     return  this . api . read ( {  tuple_key : body  } ,  options ) ; 
302+   async  read ( body : ClientReadRequest  =  { } ,  options : ClientRequestOpts  &  PaginationOptions  =  { } ) : PromiseResult < ReadResponse >  { 
303+     const  readRequest : ReadRequest  =  { 
304+       page_size : options . pageSize , 
305+       continuation_token : options . continuationToken , 
306+     } ; 
307+     if  ( body . user  ||  body . object  ||  body . relation )  { 
308+       readRequest . tuple_key  =  body ; 
309+     } 
310+     return  this . api . read ( readRequest ,  options ) ; 
299311  } 
300312
301313  /** 
@@ -306,23 +318,32 @@ export class OpenFgaClient extends BaseAPI {
306318   * @param  {object } [options.transaction] 
307319   * @param  {boolean } [options.transaction.disable] - Disables running the write in a transaction mode. Defaults to `false` 
308320   * @param  {number } [options.transaction.maxPerChunk] - Max number of items to send in a single transaction chunk. Defaults to `1` 
321+    * @param  {number } [options.transaction.waitTimeBetweenChunksInMs] - Time to wait between chunks. Defaults to `100` 
309322   * @param  {object } [options.headers] - Custom headers to send alongside the request 
310323   * @param  {object } [options.retryParams] - Override the retry parameters for this request 
311324   * @param  {number } [options.retryParams.maxRetry] - Override the max number of retries on each API request 
312325   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
313326   */ 
314327  async  write ( body : ClientWriteRequest ,  options : ClientRequestOptsWithAuthZModelId  &  ClientWriteRequestOpts  =  { } ) : Promise < ClientWriteResponse >  { 
315328    const  {  transaction =  { } ,  headers =  { }  }  =  options ; 
316-     const  {  maxPerChunk =  1  }  =  transaction ;  // 1 has to be the default otherwise the chunks will be sent in transactions 
329+     const  { 
330+       maxPerChunk =  1 ,  // 1 has to be the default otherwise the chunks will be sent in transactions 
331+       waitTimeBetweenChunksInMs =  DEFAULT_WAIT_TIME_BETWEEN_CHUNKS_IN_MS , 
332+     }  =  transaction ; 
317333    const  {  writes,  deletes }  =  body ; 
318334    const  authorizationModelId  =  this . getAuthorizationModelId ( options ) ; 
319335
320336    if  ( ! transaction ?. disable )  { 
321-       await  this . api . write ( { 
322-         writes : {  tuple_keys : writes  ||  [ ]  } , 
323-         deletes : {  tuple_keys : deletes  ||  [ ]  } , 
337+       const  apiBody : WriteRequest  =  { 
324338        authorization_model_id : authorizationModelId , 
325-       } ,  options ) ; 
339+       } ; 
340+       if  ( writes ?. length )  { 
341+         apiBody . writes  =  {  tuple_keys : writes  } ; 
342+       } 
343+       if  ( deletes ?. length )  { 
344+         apiBody . deletes  =  {  tuple_keys : deletes  } ; 
345+       } 
346+       await  this . api . write ( apiBody ,  options ) ; 
326347      return  { 
327348        writes : writes ?. map ( tuple  =>  ( { 
328349          tuple_key : tuple , 
@@ -338,61 +359,63 @@ export class OpenFgaClient extends BaseAPI {
338359    setHeaderIfNotSet ( headers ,  CLIENT_METHOD_HEADER ,  "Write" ) ; 
339360    setHeaderIfNotSet ( headers ,  CLIENT_BULK_REQUEST_ID_HEADER ,  generateRandomIdWithNonUniqueFallback ( ) ) ; 
340361    const  results : ClientWriteResponse  =  {  writes : [ ] ,  deletes : [ ]  } ; 
341-     await  chunkSequentialCall < TupleKey ,  void > ( 
362+     await  chunkSequentialCall < ClientTupleKey ,  void > ( 
342363      ( chunk )  =>  this . api . write ( 
343364        {  writes : {  tuple_keys : chunk } ,  authorization_model_id : authorizationModelId  } , 
344365        {  retryParams : {  maxRetry : DEFAULT_MAX_RETRY_OVERRIDE  } ,  headers } ) 
345366        . then ( ( )  =>  {  results . writes . push ( ...chunk . map ( tuple  =>  ( {  tuple_key : tuple ,  status : ClientWriteStatus . SUCCESS  } ) ) ) ;  } ) 
346367        . catch ( ( err )  =>  {  results . writes . push ( ...chunk . map ( tuple  =>  ( {  tuple_key : tuple ,  status : ClientWriteStatus . FAILURE ,  err } ) ) ) ;  } ) , 
347368      writes  ||  [ ] , 
348-       maxPerChunk , 
369+       {   maxPerChunk,  waitTimeBetweenChunksInMs  } , 
349370    ) ; 
350-     await  chunkSequentialCall < TupleKey ,  void > ( 
371+     await  chunkSequentialCall < ClientTupleKey ,  void > ( 
351372      ( chunk )  =>  this . api . write ( 
352373        {  deletes : {  tuple_keys : chunk  } ,  authorization_model_id : authorizationModelId  } , 
353374        {  retryParams : {  maxRetry : DEFAULT_MAX_RETRY_OVERRIDE  } ,  headers } ) 
354375        . then ( ( )  =>  {  results . deletes . push ( ...chunk . map ( tuple  =>  ( {  tuple_key : tuple ,  status : ClientWriteStatus . SUCCESS  } ) ) ) ;  } ) 
355376        . catch ( ( err )  =>  {  results . deletes . push ( ...chunk . map ( tuple  =>  ( {  tuple_key : tuple ,  status : ClientWriteStatus . FAILURE ,  err } ) ) ) ;  } ) , 
356377      deletes  ||  [ ] , 
357-       maxPerChunk , 
378+       {   maxPerChunk,  waitTimeBetweenChunksInMs  } , 
358379    ) ; 
359380
360381    return  results ; 
361382  } 
362383
363384  /** 
364385   * WriteTuples - Utility method to write tuples, wraps Write 
365-    * @param  {TupleKey } tuples 
386+    * @param  {ClientTupleKey[] } tuples 
366387   * @param  {ClientRequestOptsWithAuthZModelId & ClientWriteRequestOpts } [options] 
367388   * @param  {string } [options.authorizationModelId] - Overrides the authorization model id in the configuration 
368389   * @param  {object } [options.transaction] 
369390   * @param  {boolean } [options.transaction.disable] - Disables running the write in a transaction mode. Defaults to `false` 
370391   * @param  {number } [options.transaction.maxPerChunk] - Max number of items to send in a single transaction chunk. Defaults to `1` 
392+    * @param  {number } [options.transaction.waitTimeBetweenChunksInMs] - Time to wait between chunks. Defaults to `100` 
371393   * @param  {object } [options.headers] - Custom headers to send alongside the request 
372394   * @param  {object } [options.retryParams] - Override the retry parameters for this request 
373395   * @param  {number } [options.retryParams.maxRetry] - Override the max number of retries on each API request 
374396   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
375397   */ 
376-   async  writeTuples ( tuples : TupleKey [ ] ,  options : ClientRequestOptsWithAuthZModelId  &  ClientWriteRequestOpts  =  { } ) : Promise < ClientWriteResponse >  { 
398+   async  writeTuples ( tuples : ClientTupleKey [ ] ,  options : ClientRequestOptsWithAuthZModelId  &  ClientWriteRequestOpts  =  { } ) : Promise < ClientWriteResponse >  { 
377399    const  {  headers =  { }  }  =  options ; 
378400    setHeaderIfNotSet ( headers ,  CLIENT_METHOD_HEADER ,  "WriteTuples" ) ; 
379401    return  this . write ( {  writes : tuples  } ,  {  ...options ,  headers } ) ; 
380402  } 
381403
382404  /** 
383405   * DeleteTuples - Utility method to delete tuples, wraps Write 
384-    * @param  {TupleKey } tuples 
406+    * @param  {ClientTupleKey[] } tuples 
385407   * @param  {ClientRequestOptsWithAuthZModelId & ClientWriteRequestOpts } [options] 
386408   * @param  {string } [options.authorizationModelId] - Overrides the authorization model id in the configuration 
387409   * @param  {object } [options.transaction] 
388410   * @param  {boolean } [options.transaction.disable] - Disables running the write in a transaction mode. Defaults to `false` 
389411   * @param  {number } [options.transaction.maxPerChunk] - Max number of items to send in a single transaction chunk. Defaults to `1` 
412+    * @param  {number } [options.transaction.waitTimeBetweenChunksInMs] - Time to wait between chunks. Defaults to `100` 
390413   * @param  {object } [options.headers] - Custom headers to send alongside the request 
391414   * @param  {object } [options.retryParams] - Override the retry parameters for this request 
392415   * @param  {number } [options.retryParams.maxRetry] - Override the max number of retries on each API request 
393416   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
394417   */ 
395-   async  deleteTuples ( tuples : TupleKey [ ] ,  options : ClientRequestOptsWithAuthZModelId  &  ClientWriteRequestOpts  =  { } ) : Promise < ClientWriteResponse >  { 
418+   async  deleteTuples ( tuples : ClientTupleKey [ ] ,  options : ClientRequestOptsWithAuthZModelId  &  ClientWriteRequestOpts  =  { } ) : Promise < ClientWriteResponse >  { 
396419    const  {  headers =  { }  }  =  options ; 
397420    setHeaderIfNotSet ( headers ,  CLIENT_METHOD_HEADER ,  "DeleteTuples" ) ; 
398421    return  this . write ( {  deletes : tuples  } ,  {  ...options ,  headers } ) ; 
@@ -431,19 +454,20 @@ export class OpenFgaClient extends BaseAPI {
431454   * BatchCheck - Run a set of checks (evaluates) 
432455   * @param  {ClientBatchCheckRequest } body 
433456   * @param  {ClientRequestOptsWithAuthZModelId & BatchCheckRequestOpts } [options] 
434-    * @param  {number } [options.maxParallelRequests] - Max number of requests to issue in parallel 
457+    * @param  {number } [options.maxParallelRequests] - Max number of requests to issue in parallel. Defaults to `10` 
458+    * @param  {number } [options.waitTimeBetweenChunksInMs] - Time to wait between chunks. Defaults to `100` 
435459   * @param  {string } [options.authorizationModelId] - Overrides the authorization model id in the configuration 
436460   * @param  {object } [options.headers] - Custom headers to send alongside the request 
437461   * @param  {object } [options.retryParams] - Override the retry parameters for this request 
438462   * @param  {number } [options.retryParams.maxRetry] - Override the max number of retries on each API request 
439463   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
440464   */ 
441465  async  batchCheck ( body : ClientBatchCheckRequest ,  options : ClientRequestOptsWithAuthZModelId  &  BatchCheckRequestOpts  =  { } ) : Promise < ClientBatchCheckResponse >  { 
442-     const  {  headers =  { } ,  maxParallelRequests =  DEFAULT_MAX_METHOD_PARALLEL_REQS  }  =  options ; 
466+     const  {  headers =  { } ,  maxParallelRequests =  DEFAULT_MAX_METHOD_PARALLEL_REQS ,  waitTimeBetweenChunksInMs  =   DEFAULT_WAIT_TIME_BETWEEN_CHUNKS_IN_MS  }  =  options ; 
443467    setHeaderIfNotSet ( headers ,  CLIENT_METHOD_HEADER ,  "BatchCheck" ) ; 
444468    setHeaderIfNotSet ( headers ,  CLIENT_BULK_REQUEST_ID_HEADER ,  generateRandomIdWithNonUniqueFallback ( ) ) ; 
445469
446-     const  responses  =  ( await  chunkSequentialCall < TupleKey ,  any > ( async  ( tuples )  => 
470+     const  responses  =  ( await  chunkSequentialCall < ClientTupleKey ,  any > ( async  ( tuples )  => 
447471      Promise . all ( tuples . map ( tuple  =>  this . check ( tuple ,  {  ...options ,  retryParams : {  maxRetry : DEFAULT_MAX_RETRY_OVERRIDE  } ,  headers } ) 
448472        . then ( ( {  allowed,  $response : response  } )  =>  { 
449473          const  result  =  { 
@@ -457,7 +481,7 @@ export class OpenFgaClient extends BaseAPI {
457481          error : err , 
458482          _request : tuple , 
459483        } ) ) 
460-       ) ) ,  body ,  maxParallelRequests ) . then ( results  =>  results . flat ( ) ) )  as  ClientBatchCheckSingleResponse [ ] ; 
484+       ) ) ,  body ,  {   maxPerChunk :  maxParallelRequests ,  waitTimeBetweenChunksInMs  } ) . then ( results  =>  results . flat ( ) ) )  as  ClientBatchCheckSingleResponse [ ] ; 
461485
462486    return  {  responses } ; 
463487  } 
@@ -492,9 +516,8 @@ export class OpenFgaClient extends BaseAPI {
492516   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
493517   */ 
494518  async  listObjects ( body : ClientListObjectsRequest ,  options : ClientRequestOptsWithAuthZModelId  =  { } ) : PromiseResult < ListObjectsResponse >  { 
495-     const  authorizationModelId  =  this . getAuthorizationModelId ( options ) ; 
496519    return  this . api . listObjects ( { 
497-       authorization_model_id : authorizationModelId , 
520+       authorization_model_id : this . getAuthorizationModelId ( options ) , 
498521      user : body . user , 
499522      relation : body . relation , 
500523      type : body . type , 
@@ -516,9 +539,7 @@ export class OpenFgaClient extends BaseAPI {
516539   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
517540   */ 
518541  async  readAssertions ( options : ClientRequestOptsWithAuthZModelId  =  { } ) : PromiseResult < ReadAssertionsResponse >  { 
519-     const  authorizationModelId  =  this . getAuthorizationModelId ( options ) ; 
520-     // Note: authorization model id is validated later 
521-     return  this . api . readAssertions ( authorizationModelId ! ,  options ) ; 
542+     return  this . api . readAssertions ( this . getAuthorizationModelId ( options ) ! ,  options ) ; 
522543  } 
523544
524545  /** 
@@ -532,8 +553,7 @@ export class OpenFgaClient extends BaseAPI {
532553   * @param  {number } [options.retryParams.minWaitInMs] - Override the minimum wait before a retry is initiated 
533554   */ 
534555  async  writeAssertions ( assertions : ClientWriteAssertionsRequest ,  options : ClientRequestOptsWithAuthZModelId  =  { } ) : PromiseResult < void >  { 
535-     const  authorizationModelId  =  this . getAuthorizationModelId ( options ) ; 
536-     return  this . api . writeAssertions ( authorizationModelId ! ,  { 
556+     return  this . api . writeAssertions ( this . getAuthorizationModelId ( options ) ! ,  { 
537557      assertions : assertions . map ( assertion  =>  ( { 
538558        tuple_key : { 
539559          user : assertion . user , 
0 commit comments