6
6
type ServerError ,
7
7
BatchMixedResults ,
8
8
BatchSuccessfulPolicyEvaluation ,
9
+ SuccessfulPolicyResponse ,
9
10
} from "./sdk/models/components/index.js" ;
10
11
import {
11
12
ExecutePolicyWithInputResponse ,
@@ -151,7 +152,7 @@ export class OPAClient {
151
152
* @param inputs - The inputs to the policy.
152
153
* @param opts - Per-request options to control how the policy evaluation result is to be transformed
153
154
* into `Res` (via `fromResult`), if any failures in the batch result should reject the promose (via
154
- * `rejectErrors `), and low-level fetch options.
155
+ * `rejectMixed `), and low-level fetch options.
155
156
*/
156
157
async evaluateBatch < In extends Input | ToInput , Res > (
157
158
path : string ,
@@ -174,41 +175,51 @@ export class OPAClient {
174
175
175
176
res = resp . batchMixedResults || resp . batchSuccessfulPolicyEvaluation ;
176
177
} catch ( err ) {
178
+ // TODO(sr): memoize fallback
177
179
if (
178
180
err instanceof SDKError &&
179
181
err . httpMeta . response . status == 404 &&
180
182
opts ?. fallback
181
183
) {
182
- // run a sequence of evaluatePolicyWithInput() instead
183
- const responses : {
184
- [ k : string ] : ResponsesSuccessfulPolicyResponse | ServerError ;
185
- } = { } ;
186
- for ( const [ k , input ] of Object . entries ( inps ) ) {
187
- try {
188
- const result = await this . opa . executePolicyWithInput (
189
- {
190
- path,
191
- requestBody : { input } ,
192
- } ,
193
- opts ,
194
- ) ;
195
- if ( result . successfulPolicyResponse )
196
- responses [ k ] = result . successfulPolicyResponse ;
197
- } catch ( err ) {
198
- if ( err instanceof ServerError_ ) {
199
- responses [ k ] = {
200
- ...err . data$ ,
201
- httpStatusCode : "500" ,
202
- } ;
203
- } else {
204
- throw err ;
205
- }
206
- }
207
- if ( ! responses [ k ] ) throw `no result in API response` ;
184
+ // run a sequence of evaluatePolicyWithInput() instead, via Promise.all
185
+ let items : [ string , ServerError | SuccessfulPolicyResponse ] [ ] ;
186
+ const inputs = Object . values ( inps ) ;
187
+ const keys = Object . keys ( inps ) ;
188
+ const ps = inputs . map ( ( input ) =>
189
+ this . opa
190
+ . executePolicyWithInput ( { path, requestBody : { input } } )
191
+ . then ( ( { successfulPolicyResponse : res } ) => res ) ,
192
+ ) ;
193
+ if ( opts ?. rejectMixed ) {
194
+ items = await Promise . all ( ps ) . then ( ( results ) =>
195
+ results . map ( ( result , i ) => {
196
+ if ( ! result ) throw `no result in API response` ;
197
+ return [
198
+ keys [ i ] as string , // can't be undefined
199
+ result ,
200
+ ] ;
201
+ } ) ,
202
+ ) ;
203
+ } else {
204
+ const settled = await Promise . allSettled ( ps ) . then ( ( results ) => {
205
+ return results . map ( ( res , i ) => {
206
+ if ( res . status === "rejected" ) {
207
+ return [
208
+ keys [ i ] ,
209
+ {
210
+ ...( res . reason as ServerError_ ) . data$ ,
211
+ httpStatusCode : "500" ,
212
+ } ,
213
+ ] as [ string , ServerError ] ;
214
+ }
215
+ return [ keys [ i ] , res . value ] as [ string , SuccessfulPolicyResponse ] ;
216
+ } ) ;
217
+ } ) ;
218
+ items = settled ;
208
219
}
209
- res = { responses } ;
220
+ res = { responses : Object . fromEntries ( items ) } ;
210
221
} else {
211
- return Promise . reject ( err ) ;
222
+ throw err ;
212
223
}
213
224
}
214
225
0 commit comments