@@ -122,7 +122,7 @@ export class JQ extends Directive {
122
122
rawValue : ( val : JQCompatible ) => ( { future_id : null , val } ) ,
123
123
} ;
124
124
125
- override next ( ...items : TraceProp [ ] ) {
125
+ override next ( ..._items : TraceProp [ ] ) {
126
126
return new JQ ( this . query , this . target ) ;
127
127
}
128
128
@@ -189,6 +189,84 @@ export class StringConcat extends Directive {
189
189
}
190
190
}
191
191
192
+ type JinjaTemplate =
193
+ | {
194
+ future_id : string ;
195
+ val : null ;
196
+ }
197
+ | { val : string ; future_id : null } ;
198
+
199
+ export type JinjaVariables = {
200
+ [ key : string ] :
201
+ | string
202
+ | number
203
+ | boolean
204
+ | ( string | number | boolean ) [ ]
205
+ | JinjaVariables
206
+ | Future < any > ;
207
+ } ;
208
+
209
+ export class Jinja extends Directive {
210
+ template : string | Future < string > ;
211
+ variables : JinjaVariables ;
212
+ items : Future < any > [ ] ;
213
+
214
+ static templateJSON ( template : string | Future < string > ) : JinjaTemplate {
215
+ return template instanceof Future
216
+ ? // @ts -ignore
217
+ { val : null , future_id : template . _id }
218
+ : { val : template , future_id : null } ;
219
+ }
220
+
221
+ constructor ( template : string | Future < string > , variables : JinjaVariables ) {
222
+ super ( ) ;
223
+ this . template = template ;
224
+ this . variables = variables ;
225
+
226
+ // use items to contain all of the futures from the inputs
227
+ const futures = new Set < Future < any > > ( ) ;
228
+ const collectFutures = ( obj : any ) => {
229
+ if ( Array . isArray ( obj ) ) {
230
+ for ( let item of obj ) {
231
+ collectFutures ( item ) ;
232
+ }
233
+ }
234
+
235
+ if ( obj instanceof Future ) {
236
+ futures . add ( obj ) ;
237
+ return ;
238
+ }
239
+
240
+ if ( obj && typeof obj === "object" ) {
241
+ for ( let key of Object . keys ( obj ) ) {
242
+ collectFutures ( obj [ key ] ) ;
243
+ }
244
+ }
245
+ } ;
246
+ collectFutures ( [ template , variables ] ) ;
247
+ this . items = Array . from ( futures )
248
+ }
249
+
250
+ override next ( ..._items : any [ ] ) {
251
+ return new Jinja ( this . template , this . variables ) ;
252
+ }
253
+
254
+ override async result ( ) : Promise < string > {
255
+ return this . template instanceof Future
256
+ ? // @ts -ignore
257
+ await this . template . _result ( )
258
+ : this . template ;
259
+ }
260
+
261
+ override toJSON ( ) : any {
262
+ return {
263
+ type : "jinja" ,
264
+ template : Jinja . templateJSON ( this . template ) ,
265
+ variables : replaceWithPlaceholders ( this . variables ) ,
266
+ } ;
267
+ }
268
+ }
269
+
192
270
export abstract class Future < T > {
193
271
protected _directive : Directive ;
194
272
protected _id : string = "" ;
@@ -263,6 +341,13 @@ export class FutureString extends Future<string> {
263
341
return FutureString . concat ( ...[ this , ...items ] ) ;
264
342
}
265
343
344
+ static jinja (
345
+ template : string | FutureString ,
346
+ variables : JinjaVariables ,
347
+ ) : FutureString {
348
+ return new FutureString ( new Jinja ( template , variables ) ) ;
349
+ }
350
+
266
351
protected override async _result ( ) : Promise < string > {
267
352
return super . _result ( ) ;
268
353
}
@@ -315,3 +400,27 @@ export class FutureAnyObject extends Future<Object> {
315
400
return super . _result ( ) ;
316
401
}
317
402
}
403
+
404
+ /**
405
+ * @internal
406
+ * Given some value, recursively replace `Future` instances with SB Placeholder
407
+ */
408
+ export const replaceWithPlaceholders = ( val : any ) : any => {
409
+ if ( Array . isArray ( val ) ) {
410
+ return val . map ( ( item ) => replaceWithPlaceholders ( item ) ) ;
411
+ }
412
+
413
+ if ( val instanceof Future ) {
414
+ // @ts -expect-error (accessing protected method toPlaceholder)
415
+ return val . toPlaceholder ( ) ;
416
+ }
417
+
418
+ if ( val && typeof val === "object" ) {
419
+ return Object . keys ( val ) . reduce ( ( acc : any , k : any ) => {
420
+ acc [ k ] = replaceWithPlaceholders ( val [ k ] ) ;
421
+ return acc ;
422
+ } , { } ) ;
423
+ }
424
+
425
+ return val ;
426
+ } ;
0 commit comments