@platforma-sdk/workflow-tengo 2.9.6 → 2.9.7

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 (64) hide show
  1. package/dist/tengo/lib/assets.lib.tengo +52 -52
  2. package/dist/tengo/lib/assets.swinfo.lib.tengo +45 -45
  3. package/dist/tengo/lib/constants.lib.tengo +32 -32
  4. package/dist/tengo/lib/exec.R.internal.lib.tengo +29 -29
  5. package/dist/tengo/lib/exec.R.lib.tengo +166 -166
  6. package/dist/tengo/lib/exec.constants.lib.tengo +4 -4
  7. package/dist/tengo/lib/exec.descriptor.lib.tengo +31 -31
  8. package/dist/tengo/lib/exec.internal.lib.tengo +297 -297
  9. package/dist/tengo/lib/exec.lib.tengo +815 -815
  10. package/dist/tengo/lib/exec.monetization.lib.tengo +130 -130
  11. package/dist/tengo/lib/exec.package.lib.tengo +212 -212
  12. package/dist/tengo/lib/exec.python.internal.lib.tengo +6 -6
  13. package/dist/tengo/lib/exec.python.lib.tengo +146 -146
  14. package/dist/tengo/lib/exec.runcmd.lib.tengo +371 -371
  15. package/dist/tengo/lib/exec.runenv.lib.tengo +92 -92
  16. package/dist/tengo/lib/exec.stream.lib.tengo +40 -40
  17. package/dist/tengo/lib/file.internal.lib.tengo +77 -77
  18. package/dist/tengo/lib/file.lib.tengo +57 -57
  19. package/dist/tengo/lib/ll.lib.tengo +244 -244
  20. package/dist/tengo/lib/maps.lib.tengo +152 -152
  21. package/dist/tengo/lib/objects.lib.tengo +13 -13
  22. package/dist/tengo/lib/oop.lib.tengo +19 -19
  23. package/dist/tengo/lib/path.lib.tengo +125 -125
  24. package/dist/tengo/lib/pframes.constants.lib.tengo +28 -28
  25. package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +33 -33
  26. package/dist/tengo/lib/pframes.lib.tengo +43 -43
  27. package/dist/tengo/lib/pframes.ll.lib.tengo +72 -72
  28. package/dist/tengo/lib/pframes.pcolumn.lib.tengo +49 -49
  29. package/dist/tengo/lib/pframes.spec.lib.tengo +96 -96
  30. package/dist/tengo/lib/pframes.util.lib.tengo +288 -288
  31. package/dist/tengo/lib/pframes.xsv.lib.tengo +272 -272
  32. package/dist/tengo/lib/render.lib.tengo +75 -75
  33. package/dist/tengo/lib/sets.lib.tengo +68 -68
  34. package/dist/tengo/lib/slices.lib.tengo +258 -155
  35. package/dist/tengo/lib/smart.lib.tengo +1069 -1069
  36. package/dist/tengo/lib/test.lib.tengo +161 -161
  37. package/dist/tengo/lib/tpl.lib.tengo +515 -515
  38. package/dist/tengo/lib/tpl.state-await.lib.tengo +240 -240
  39. package/dist/tengo/lib/tpl.util.lib.tengo +9 -9
  40. package/dist/tengo/lib/validation.lib.tengo +378 -378
  41. package/dist/tengo/lib/workdir.lib.tengo +331 -331
  42. package/dist/tengo/lib/workdir.proc.lib.tengo +144 -144
  43. package/dist/tengo/lib/workdir.save.lib.tengo +130 -130
  44. package/dist/tengo/lib/workflow.bobject.lib.tengo +26 -26
  45. package/dist/tengo/lib/workflow.bquery.lib.tengo +165 -165
  46. package/dist/tengo/lib/workflow.constants.lib.tengo +2 -2
  47. package/dist/tengo/lib/workflow.context.lib.tengo +32 -32
  48. package/dist/tengo/lib/workflow.lib.tengo +206 -206
  49. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  50. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  51. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  52. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  53. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  54. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  55. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  56. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  57. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  58. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  59. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  60. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  61. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  62. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  63. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  64. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
-
2
-
3
-
1
+ /**
2
+ * A builder for executing commands.
3
+ */
4
4
 
5
5
  ll := import("@platforma-sdk/workflow-tengo:ll")
6
6
  assets := import("@platforma-sdk/workflow-tengo:assets")
@@ -24,820 +24,820 @@ _MEDIUM_QUEUE := "medium"
24
24
  _LIGHT_QUEUE := "light"
25
25
  _UI_TASKS_QUEUE := "ui-tasks"
26
26
 
27
-
28
-
29
-
30
-
31
-
27
+ /**
28
+ * Creates a new builder for constructing and executing commands.
29
+ *
30
+ * @return builder - a new builder instance.
31
+ */
32
32
  builder := func() {
33
- self := undefined
34
-
35
- soft := undefined
36
- cmd := undefined
37
- args := [] // list of strings
38
- argsTyped := [] // list of {type: expression|string, value: string}
39
- typedArgSet := false
40
- typedEnvSet := false
41
- envs := {} // map of names to values-strings
42
- envsTyped := {} // map of names to {type: expression|string, value: string}
43
- secrets := {} // { "env_name": "{secrets.secret_name}", ... }
44
-
45
- entrypointSet := false
46
-
47
- assertEntrypointNotSet := func() {
48
- ll.assert(!entrypointSet,
49
- "either a command with arguments or a software were already set.")
50
- }
51
-
52
- queue := _HEAVY_QUEUE
53
- cache := 0
54
- nErrorLines := 200
55
-
56
-
57
- filesToAdd := {}
58
-
59
- filesToWrite := {}
60
-
61
- dirsToCreate := {}
62
-
63
-
64
- filesToSave := {}
65
-
66
- filesContentToSave := {}
67
-
68
- fileSetsToSave := {}
69
-
70
- fileSetsContentToSave := {}
71
-
72
- filesToStream := {}
73
-
74
- wdProcessors := {}
75
-
76
-
77
- assetInfos := {}
78
- assetDescriptors := {}
79
- assetRules := {}
80
- assetCache := {}
81
-
82
- mnz := monetization.init()
83
-
84
-
85
- _getMnzOption := func(...opts) {
86
- if slices.length(opts) < 1 {
87
- return undefined
88
- }
89
- opt := opts[0]["mnz"]
90
-
91
-
92
- return is_undefined(opt) ? undefined : opt
93
- }
94
-
95
-
96
- _addMnzOption := func(fileName, ...opts) {
97
- opt := _getMnzOption(opts...)
98
- if !is_undefined(opt) {
99
- monetization.addFileParams(mnz, fileName, opt)
100
- }
101
- }
102
-
103
- stdout := "stdout.txt"
104
- stderr := "stderr.txt"
105
-
106
- stdoutToValue := false
107
- stderrToValue := false
108
- stderrToStdout := false
109
-
110
- self = ll.toStrict({
111
-
112
-
113
-
114
-
115
-
116
- cmd: func(commandName) {
117
- assertEntrypointNotSet()
118
-
119
- cmd = commandName
120
- entrypointSet = true
121
- return self
122
- },
123
-
124
-
125
-
126
-
127
-
128
-
129
- software: func(sw) {
130
- assertEntrypointNotSet()
131
- ll.assert(assets.isSoftwareInfo(sw),
132
- "exec.builder.software: <software> parameter is not a software info. Provide the value obtained from assets.importSoftware() here"
133
- )
134
-
135
- soft = sw
136
- entrypointSet = true
137
- return self
138
- },
139
-
140
-
141
-
142
-
143
-
144
-
145
- arg: func(arg) {
146
- ll.assert(is_string(arg), "exec.arg(): argument must be a string, got: %v", arg)
147
- args = append(args, arg)
148
- argsTyped = append(argsTyped, {
149
- type: execConstants.ARG_TYPE_STRING,
150
- value: arg
151
- })
152
- return self
153
- },
154
-
155
-
156
-
157
-
158
-
159
-
160
- argWithVar: func(arg) {
161
- ll.assert(is_string(arg), "exec.argWithVar(): argument with var must be a string, got: %v", arg)
162
-
163
-
164
- t := desc.canBackendUseExpressions() ? execConstants.ARG_TYPE_EXPRESSION : execConstants.ARG_TYPE_VAR
165
- argsTyped = append(argsTyped, {
166
- type: t,
167
- value: arg
168
- })
169
- typedArgSet = true
170
-
171
- return self
172
- },
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
- env: func(name, value) {
181
- validation.assertJsonSchema([name, value], ["string"])
182
- envs[name] = value
183
- envsTyped[name] = {
184
- type: execConstants.ARG_TYPE_STRING,
185
- value: value
186
- }
187
- return self
188
- },
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
- envWithVar: func(name, value) {
197
- validation.assertJsonSchema([name, value], ["string"])
198
-
199
-
200
- t := desc.canBackendUseExpressions() ? execConstants.ARG_TYPE_EXPRESSION : execConstants.ARG_TYPE_VAR
201
- envsTyped[name] = {
202
- type: t,
203
- value: value
204
- }
205
- typedEnvSet = true
206
-
207
- return self
208
- },
209
-
210
-
211
-
212
-
213
-
214
-
215
- envMap: func(envMap) {
216
- enum.each(envMap, self.env)
217
- return self
218
- },
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
- secret: func(secretName, envName) {
227
- validation.assertJsonSchema([secretName, envName], ["string"])
228
- secrets[envName] = "{secrets."+secretName+"}"
229
- return self
230
- },
231
-
232
-
233
-
234
-
235
- inHeavyQueue: func() {
236
- queue = _HEAVY_QUEUE
237
- return self
238
- },
239
-
240
-
241
-
242
-
243
- inMediumQueue: func() {
244
- queue = _MEDIUM_QUEUE
245
- return self
246
- },
247
-
248
-
249
-
250
-
251
- inLightQueue: func() {
252
- queue = _LIGHT_QUEUE
253
- return self
254
- },
255
-
256
-
257
-
258
-
259
- inUiQueue: func() {
260
- queue = _UI_TASKS_QUEUE
261
- return self
262
- },
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
- cache: func(time) {
271
- ll.assert(
272
- is_int(time),
273
- "cache time must be an integer. " +
274
- "Did you forget to import a standard tengo library 'times'?")
275
- cache = time
276
- return self
277
- },
278
-
279
-
280
-
281
-
282
-
283
-
284
- cacheMillis: func(millis) {
285
- ll.assert(is_int(millis) && millis > 0, "cache time must be a number of milliseconds")
286
- cache = millis * times.millisecond
287
- return self
288
- },
289
-
290
-
291
-
292
-
293
-
294
-
295
- cacheSeconds: func(seconds) {
296
- ll.assert(is_int(seconds) && seconds > 0, "cache time must be a number of seconds")
297
- cache = seconds * times.second
298
- return self
299
- },
300
-
301
-
302
-
303
-
304
-
305
-
306
- cacheMinutes: func(minutes) {
307
- ll.assert(is_int(minutes) && minutes > 0, "cache time must be a number of minutes")
308
- cache = minutes * times.minute
309
- return self
310
- },
311
-
312
-
313
-
314
-
315
-
316
-
317
- cacheHours: func(hours) {
318
- ll.assert(is_int(hours) && hours > 0, "cache time must be a number of hours")
319
- cache = hours * times.hour
320
- return self
321
- },
322
-
323
-
324
-
325
-
326
-
327
-
328
- cacheDays: func(days) {
329
- ll.assert(is_int(days) && days > 0, "cache time must be a number of days")
330
- cache = days * times.hour * 24
331
- return self
332
- },
333
-
334
-
335
-
336
-
337
-
338
-
339
- nErrorLines: func(lines) {
340
- ll.assert(
341
- is_int(lines) && lines >= 0,
342
- "lines must be integer")
343
-
344
- nErrorLines = lines
345
- return self
346
- },
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
- addAsset: func(asset, destinationDir, ...pathsInArchive) {
357
- if (len(pathsInArchive) == 1 && is_array(pathsInArchive[0])) {
358
-
359
- pathsInArchive = pathsInArchive[0]
360
- }
361
- if len(pathsInArchive) == 0 {
362
-
363
- pathsInArchive = []
364
- }
365
-
366
- ll.assert(assets.isAssetInfo(asset),
367
- "exec.builder.addAsset: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
368
- validation.assertJsonSchema(destinationDir, "string", "exec.builder.addAsset: <destinationDir> is not a string. It must be a path inside working directory")
369
- validation.assertJsonSchema(pathsInArchive, ["string"], "exec.builder.addAsset: <pathsInArchive> must contain list of strings with paths inside archive")
370
-
371
- assetIdKey := ll.idToString(asset._id)
372
- if is_undefined(assetRules[assetIdKey]) {
373
- assetInfos[assetIdKey] = asset.resource
374
- assetDescriptors[assetIdKey] = ll.fromStrict(asset.descriptor)
375
- assetRules[assetIdKey] = {}
376
- }
377
-
378
- if len(pathsInArchive) == 0 || is_undefined(assetRules[assetIdKey][destinationDir]) {
379
- assetRules[assetIdKey][destinationDir] = []
380
- }
381
-
382
- if (len(pathsInArchive) > 0) {
383
- assetRules[assetIdKey][destinationDir] = append(assetRules[assetIdKey][destinationDir], pathsInArchive...)
384
- }
385
-
386
- return self
387
- },
388
-
389
-
390
-
391
-
392
-
393
- cacheAssetMillis: func (asset, millis) {
394
- ll.assert(assets.isAssetInfo(asset),
395
- "exec.builder.cacheAssetMillis: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
396
- ll.assert(is_int(millis),
397
- "exec.builder.cacheAssetMillis: asset cache time must be a number of milliseconds.")
398
-
399
- assetIdKey := ll.idToString(asset._id)
400
- assetCache[assetIdKey] = millis * times.millisecond
401
-
402
- return self
403
- },
404
-
405
-
406
-
407
-
408
-
409
- cacheAssetSeconds: func (asset, seconds) {
410
- ll.assert(assets.isAssetInfo(asset),
411
- "exec.builder.cacheAssetSeconds: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
412
- ll.assert(is_int(seconds),
413
- "exec.builder.cacheAssetSeconds: asset cache time must be a number of seconds.")
414
-
415
- assetIdKey := ll.idToString(asset._id)
416
- assetCache[assetIdKey] = seconds * times.second
417
-
418
- return self
419
- },
420
-
421
-
422
-
423
-
424
-
425
- cacheAssetMinutes: func (asset, minutes) {
426
- ll.assert(assets.isAssetInfo(asset),
427
- "exec.builder.cacheAssetMinutes: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
428
- ll.assert(is_int(minutes),
429
- "exec.builder.cacheAssetMinutes: asset cache time must be a number of minutes.")
430
-
431
- assetIdKey := ll.idToString(asset._id)
432
- assetCache[assetIdKey] = minutes * times.minute
433
-
434
- return self
435
- },
436
-
437
-
438
-
439
-
440
-
441
- cacheAssetHours: func (asset, hours) {
442
- ll.assert(assets.isAssetInfo(asset),
443
- "exec.builder.cacheAssetHours: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
444
- ll.assert(is_int(hours),
445
- "exec.builder.cacheAssetHours: asset cache time must be a number of hours.")
446
-
447
- assetIdKey := ll.idToString(asset._id)
448
- assetCache[assetIdKey] = hours * times.hour
449
-
450
- return self
451
- },
452
-
453
-
454
-
455
-
456
-
457
- cacheAssetDays: func (asset, days) {
458
- ll.assert(assets.isAssetInfo(asset),
459
- "exec.builder.cacheAssetHours: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
460
- ll.assert(is_int(days),
461
- "exec.builder.cacheAssetHours: asset cache time must be a number of days.")
462
-
463
- assetIdKey := ll.idToString(asset._id)
464
- assetCache[assetIdKey] = days * 24 * times.hour
465
-
466
- return self
467
- },
468
-
469
- enableMnz: func(productName) {
470
- monetization.enable(mnz, productName)
471
- return self
472
- },
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
- addFile: func(fileName, file, ...opts) {
481
- ll.assert(is_string(fileName), "exec.builder().addFile: fileName must be a string")
482
- ll.assert(smart.isReference(file), "exec.builder().addFile: file must be a reference")
483
-
484
- fileName = path.canonize(fileName)
485
- filesToAdd[fileName] = file
486
- _addMnzOption(fileName, opts...)
487
- return self
488
- },
489
-
490
-
491
-
492
-
493
-
494
-
495
- addFiles: func(filesMap, ...opts) {
496
- ll.assert(ll.isMap(filesMap), "exec.builder().addFiles: filesMap must be map of file names to file resources")
497
- for fileName, file in filesMap {
498
- self.addFile(fileName, file, opts...)
499
- }
500
- return self
501
- },
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
- writeFile: func(fileName, data, ...opts) {
511
- validation.assertJsonSchema(data, ["or",
512
- "string",
513
- "bytes",
514
- validation.reference])
515
-
516
- fileName = path.canonize(fileName)
517
-
518
- filesToWrite[fileName] = data
519
- _addMnzOption(fileName, opts...)
520
-
521
- return self
522
- },
523
-
524
-
525
-
526
-
527
-
528
-
529
- mkDir: func(dir) {
530
- dir = path.canonize(dir)
531
- dirsToCreate = sets.add(dirsToCreate, dir)
532
- return self
533
- },
534
-
535
-
536
-
537
-
538
-
539
-
540
- saveFile: func(fileName) {
541
- fileName = path.canonize(fileName)
542
- sets.add(filesToSave, fileName)
543
- return self
544
- },
545
-
546
-
547
-
548
-
549
-
550
-
551
- saveFileContent: func(fileName) {
552
- fileName = path.canonize(fileName)
553
- sets.add(filesContentToSave, fileName)
554
- return self
555
- },
556
-
557
-
558
-
559
-
560
-
561
-
562
-
563
- saveFileSet: func(name, regex) {
564
- fileSetsToSave[name] = regex
565
- return self
566
- },
567
-
568
-
569
-
570
-
571
- processWorkdir: func(name, tpl, tplArgs) {
572
- wdProcessors[name] = {
573
- tpl: tpl,
574
- tplArgs: tplArgs
575
- }
576
- return self
577
- },
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
- saveFileSetContent: func(name, regex) {
586
- fileSetsContentToSave[name] = regex
587
- return self
588
- },
589
-
590
-
591
-
592
-
593
-
594
-
595
- streamFile: func(fileName) {
596
- fileName = path.canonize(fileName)
597
- sets.add(filesToStream, fileName)
598
-
599
- return self
600
- },
601
-
602
-
603
-
604
-
605
- stdoutFileName: func(fileName) {
606
- fileName = path.canonize(fileName)
607
- stdout = fileName
608
- return self
609
- },
610
-
611
-
612
-
613
-
614
- stderrFileName: func(fileName) {
615
- fileName = path.canonize(fileName)
616
- stderr = fileName
617
- return self
618
- },
619
-
620
-
621
-
622
-
623
- saveStdoutContent: func() {
624
- stdoutToValue = true
625
- return self
626
- },
627
-
628
-
629
-
630
-
631
- saveStderrContent: func() {
632
- stderrToValue = true
633
- return self
634
- },
635
-
636
-
637
-
638
-
639
- printErrStreamToStdout: func() {
640
- stderrToStdout = true
641
- return self
642
- },
643
-
644
-
645
-
646
-
647
-
648
-
649
- run: func() {
650
- if stderrToStdout {
651
- stderr = stdout
652
- }
653
- sets.add(filesToStream, stdout)
654
- sets.add(filesToStream, stderr)
655
- sets.add(filesToSave, stdout)
656
- sets.add(filesToSave, stderr)
657
- if stdoutToValue {
658
- sets.add(filesContentToSave, stdout)
659
- }
660
- if stderrToValue {
661
- sets.add(filesContentToSave, stderr)
662
- }
663
-
664
-
665
-
666
-
667
- filesToWriteRefs := maps.mapValues(filesToWrite, func(v) {
668
- if smart.isReference(v) { return v }
669
- return smart.createValueResource(constants.RTYPE_BINARY_VALUE, v)
670
- })
671
-
672
- ll.assert(entrypointSet,
673
- "incomplete command: cmd() or software() must be provided to exec.builder")
674
-
675
- runOptions := {
676
- cmd: cmd,
677
- args: args,
678
- envs: envs,
679
- secrets: secrets,
680
- queue: queue,
681
- stdout: stdout,
682
- stderr: stderr,
683
- nErrorLines: nErrorLines
684
- }
685
-
686
- execInputs := {
687
- filesToAdd: smart.createMapResource(filesToAdd),
688
- filesToWrite: smart.createMapResource(filesToWriteRefs),
689
- dirsToCreate: slices.fromSet(dirsToCreate),
690
- runOptions: runOptions,
691
- filesToSave: slices.fromSet(filesToSave),
692
- filesContentToSave: slices.fromSet(filesContentToSave),
693
- fileSetsToSave: fileSetsToSave,
694
- fileSetsContentToSave: fileSetsContentToSave,
695
- filesToStream: slices.fromSet(filesToStream),
696
- wdProcessors: wdProcessors,
697
- assets: smart.createMapResource(assetInfos),
698
- assetDescriptors: assetDescriptors,
699
- assetRules: assetRules,
700
- assetCache: assetCache
701
- }
702
-
703
-
704
-
705
-
706
- if monetization.shouldRun(mnz) {
707
- execInputs.runOptions.monetization = monetization.toJson(mnz)
708
- }
709
-
710
-
711
-
712
- if typedArgSet || typedEnvSet {
713
- execInputs.runOptions.argsTyped = argsTyped
714
- execInputs.runOptions.envsTyped = envsTyped
715
- }
716
-
717
- if !is_undefined(soft) {
718
- execInputs.softwareInfo = soft.resource
719
- execInputs.runOptions.software = {
720
- name: soft.name,
721
- version: soft.version,
722
- descriptor: ll.fromStrict(soft.descriptor)
723
- }
724
- }
725
-
726
- tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.exec"), execInputs)
727
-
728
- self := undefined
729
- self = ll.toStrict(oop.inherit(tpl, {
730
-
731
-
732
-
733
-
734
-
735
-
736
- getFile: func(fileName) {
737
- return tpl.output("files", cache).getFutureInputField(fileName)
738
- },
739
-
740
-
741
-
742
-
743
-
744
-
745
-
746
- getFileContent: func(fileName) {
747
- return tpl.output("filesContent", cache).getFutureInputField(fileName)
748
- },
749
-
750
-
751
-
752
-
753
-
754
-
755
-
756
- getFileStream: func(fileName) {
757
- return tpl.output("fileStreams", cache).getFutureInputField(fileName, true)
758
- },
759
-
760
-
761
-
762
-
763
-
764
-
765
-
766
- getFileSet: func(fileSetName) {
767
- return tpl.output("fileSets", cache).getFutureInputField(fileSetName)
768
- },
769
-
770
-
771
-
772
-
773
-
774
-
775
-
776
- getFileSetContent: func(fileSetName) {
777
- return tpl.output("fileSetsContent", cache).getFutureInputField(fileSetName)
778
- },
779
-
780
- getProcessorResult: func(procName) {
781
- return tpl.output("wdProcessors", cache).getFutureInputField(procName)
782
- },
783
-
784
-
785
-
786
-
787
- getStdoutStream: func() {
788
- return self.getFileStream(stdout)
789
- },
790
-
791
-
792
-
793
-
794
- getStderrStream: func() {
795
- return self.getFileStream(stderr)
796
- },
797
-
798
-
799
-
800
-
801
- getStdoutFile: func() {
802
- return self.getFile(stdout)
803
- },
804
-
805
-
806
-
807
-
808
- getStderrFile: func() {
809
- return self.getFile(stderr)
810
- },
811
-
812
-
813
-
814
-
815
- getStdoutFileContent: func() {
816
- if stdoutToValue {
817
- return self.getFileContent(stdout)
818
- }
819
- ll.panic("stdout was not saved as a content")
820
- },
821
-
822
-
823
-
824
-
825
- getStderrFileContent: func() {
826
- if stderrToValue {
827
- return self.getFileContent(stderr)
828
- }
829
- ll.panic("stderr was not saved as a content")
830
- }
831
- }))
832
-
833
- return self
834
- }
835
- })
836
-
837
- return self
33
+ self := undefined
34
+
35
+ soft := undefined
36
+ cmd := undefined
37
+ args := [] // list of strings
38
+ argsTyped := [] // list of {type: expression|string, value: string}
39
+ typedArgSet := false
40
+ typedEnvSet := false
41
+ envs := {} // map of names to values-strings
42
+ envsTyped := {} // map of names to {type: expression|string, value: string}
43
+ secrets := {} // { "env_name": "{secrets.secret_name}", ... }
44
+
45
+ entrypointSet := false
46
+
47
+ assertEntrypointNotSet := func() {
48
+ ll.assert(!entrypointSet,
49
+ "either a command with arguments or a software were already set.")
50
+ }
51
+
52
+ queue := _HEAVY_QUEUE
53
+ cache := 0
54
+ nErrorLines := 200
55
+
56
+ // files to be added in workdir
57
+ filesToAdd := {}
58
+ // files to be created in the workdir with the content from resources
59
+ filesToWrite := {}
60
+ // directories to create in the workdir
61
+ dirsToCreate := {}
62
+
63
+ // files to save from the workdir
64
+ filesToSave := {}
65
+ // files which content to save from the workdir
66
+ filesContentToSave := {}
67
+ // file sets to save by regex
68
+ fileSetsToSave := {}
69
+ // file sets to save by regex (save file content)
70
+ fileSetsContentToSave := {}
71
+ // files to stream from the workdir
72
+ filesToStream := {}
73
+ // workdir processors
74
+ wdProcessors := {}
75
+
76
+ // assets to be extracted into workdir before execution
77
+ assetInfos := {}
78
+ assetDescriptors := {}
79
+ assetRules := {}
80
+ assetCache := {}
81
+
82
+ mnz := monetization.init()
83
+
84
+ /** Gets mnz key from opts or undefined. */
85
+ _getMnzOption := func(...opts) {
86
+ if slices.length(opts) < 1 {
87
+ return undefined
88
+ }
89
+ opt := opts[0]["mnz"]
90
+
91
+ // readability if: we can return undefined here
92
+ return is_undefined(opt) ? undefined : opt
93
+ }
94
+
95
+ /** Adds a monetization option if it's defined into mnzFileParams. */
96
+ _addMnzOption := func(fileName, ...opts) {
97
+ opt := _getMnzOption(opts...)
98
+ if !is_undefined(opt) {
99
+ monetization.addFileParams(mnz, fileName, opt)
100
+ }
101
+ }
102
+
103
+ stdout := "stdout.txt"
104
+ stderr := "stderr.txt"
105
+
106
+ stdoutToValue := false
107
+ stderrToValue := false
108
+ stderrToStdout := false
109
+
110
+ self = ll.toStrict({
111
+ /**
112
+ * Sets the command to be executed, e.g. /usr/bin/env or sh.
113
+ *
114
+ * @param commandName: string - the name of the command.
115
+ */
116
+ cmd: func(commandName) {
117
+ assertEntrypointNotSet()
118
+
119
+ cmd = commandName
120
+ entrypointSet = true
121
+ return self
122
+ },
123
+
124
+ /**
125
+ * Sets the software to be executed.
126
+ *
127
+ * @param software: softwareInfo - the software to execute.
128
+ */
129
+ software: func(sw) {
130
+ assertEntrypointNotSet()
131
+ ll.assert(assets.isSoftwareInfo(sw),
132
+ "exec.builder.software: <software> parameter is not a software info. Provide the value obtained from assets.importSoftware() here"
133
+ )
134
+
135
+ soft = sw
136
+ entrypointSet = true
137
+ return self
138
+ },
139
+
140
+ /**
141
+ * Adds an argument to the command.
142
+ *
143
+ * @param arg: string - the argument to add.
144
+ */
145
+ arg: func(arg) {
146
+ ll.assert(is_string(arg), "exec.arg(): argument must be a string, got: %v", arg)
147
+ args = append(args, arg)
148
+ argsTyped = append(argsTyped, {
149
+ type: execConstants.ARG_TYPE_STRING,
150
+ value: arg
151
+ })
152
+ return self
153
+ },
154
+
155
+ /**
156
+ * Adds an argument that will be evaluated as expression in the command.
157
+ *
158
+ * @param arg: string - e.g. -Xms{system.memory_mb * 80 / 100}m
159
+ */
160
+ argWithVar: func(arg) {
161
+ ll.assert(is_string(arg), "exec.argWithVar(): argument with var must be a string, got: %v", arg)
162
+
163
+ // deprecated: remove ARG_TYPE_VAR and this check after 15 Mar 2025
164
+ t := desc.canBackendUseExpressions() ? execConstants.ARG_TYPE_EXPRESSION : execConstants.ARG_TYPE_VAR
165
+ argsTyped = append(argsTyped, {
166
+ type: t,
167
+ value: arg
168
+ })
169
+ typedArgSet = true
170
+
171
+ return self
172
+ },
173
+
174
+ /**
175
+ * Sets an environment variable.
176
+ *
177
+ * @param name: string - the name of the environment variable.
178
+ * @param value: string - the value of the environment variable.
179
+ */
180
+ env: func(name, value) {
181
+ validation.assertJsonSchema([name, value], ["string"])
182
+ envs[name] = value
183
+ envsTyped[name] = {
184
+ type: execConstants.ARG_TYPE_STRING,
185
+ value: value
186
+ }
187
+ return self
188
+ },
189
+
190
+ /**
191
+ * Sets an environment variable.
192
+ *
193
+ * @param name: string - the name of the environment variable.
194
+ * @param value: string - the value of the environment variable.
195
+ */
196
+ envWithVar: func(name, value) {
197
+ validation.assertJsonSchema([name, value], ["string"])
198
+
199
+ // deprecated: remove ARG_TYPE_VAR and this check after 15 Mar 2025
200
+ t := desc.canBackendUseExpressions() ? execConstants.ARG_TYPE_EXPRESSION : execConstants.ARG_TYPE_VAR
201
+ envsTyped[name] = {
202
+ type: t,
203
+ value: value
204
+ }
205
+ typedEnvSet = true
206
+
207
+ return self
208
+ },
209
+
210
+ /**
211
+ * Sets multiple environment variables.
212
+ *
213
+ * @param envMap: map[string]string - a map of environment variables.
214
+ */
215
+ envMap: func(envMap) {
216
+ enum.each(envMap, self.env)
217
+ return self
218
+ },
219
+
220
+ /**
221
+ * Set environment variable to value of given secret.
222
+ *
223
+ * @param secretName: string - name of secret to pass as environment variable.
224
+ * @param envName: string - name of environment variable to set with value of secret.
225
+ */
226
+ secret: func(secretName, envName) {
227
+ validation.assertJsonSchema([secretName, envName], ["string"])
228
+ secrets[envName] = "{secrets."+secretName+"}"
229
+ return self
230
+ },
231
+
232
+ /**
233
+ * Execute command in the 'heavy' queue.
234
+ */
235
+ inHeavyQueue: func() {
236
+ queue = _HEAVY_QUEUE
237
+ return self
238
+ },
239
+
240
+ /**
241
+ * Execute command in the 'medium' queue.
242
+ */
243
+ inMediumQueue: func() {
244
+ queue = _MEDIUM_QUEUE
245
+ return self
246
+ },
247
+
248
+ /**
249
+ * Execute command in the 'light' queue.
250
+ */
251
+ inLightQueue: func() {
252
+ queue = _LIGHT_QUEUE
253
+ return self
254
+ },
255
+
256
+ /**
257
+ * Execute command in the 'ui-tasks' queue.
258
+ */
259
+ inUiQueue: func() {
260
+ queue = _UI_TASKS_QUEUE
261
+ return self
262
+ },
263
+
264
+ /**
265
+ * Use cacheMillis, cacheSeconds, cacheMinutes, cacheHours and cacheDays to not make hidden mistakes in cache time ranges.
266
+ * Sets the cache time.
267
+ *
268
+ * @param time: duration - the cache time from 'times' library.
269
+ */
270
+ cache: func(time) {
271
+ ll.assert(
272
+ is_int(time),
273
+ "cache time must be an integer. " +
274
+ "Did you forget to import a standard tengo library 'times'?")
275
+ cache = time
276
+ return self
277
+ },
278
+
279
+ /**
280
+ * Sets the cache time in milliseconds.
281
+ *
282
+ * @param millis: number
283
+ */
284
+ cacheMillis: func(millis) {
285
+ ll.assert(is_int(millis) && millis > 0, "cache time must be a number of milliseconds")
286
+ cache = millis * times.millisecond
287
+ return self
288
+ },
289
+
290
+ /**
291
+ * Sets the cache time in seconds.
292
+ *
293
+ * @param seconds: number
294
+ */
295
+ cacheSeconds: func(seconds) {
296
+ ll.assert(is_int(seconds) && seconds > 0, "cache time must be a number of seconds")
297
+ cache = seconds * times.second
298
+ return self
299
+ },
300
+
301
+ /**
302
+ * Sets the cache time in minutes.
303
+ *
304
+ * @param minutes: number
305
+ */
306
+ cacheMinutes: func(minutes) {
307
+ ll.assert(is_int(minutes) && minutes > 0, "cache time must be a number of minutes")
308
+ cache = minutes * times.minute
309
+ return self
310
+ },
311
+
312
+ /**
313
+ * Sets the cache time in hours.
314
+ *
315
+ * @param hours: number
316
+ */
317
+ cacheHours: func(hours) {
318
+ ll.assert(is_int(hours) && hours > 0, "cache time must be a number of hours")
319
+ cache = hours * times.hour
320
+ return self
321
+ },
322
+
323
+ /**
324
+ * Sets the cache time in days
325
+ *
326
+ * @param days: number
327
+ */
328
+ cacheDays: func(days) {
329
+ ll.assert(is_int(days) && days > 0, "cache time must be a number of days")
330
+ cache = days * times.hour * 24
331
+ return self
332
+ },
333
+
334
+ /**
335
+ * Sets the number of error lines to be captured.
336
+ *
337
+ * @param lines: number - the number of error lines.
338
+ */
339
+ nErrorLines: func(lines) {
340
+ ll.assert(
341
+ is_int(lines) && lines >= 0,
342
+ "lines must be integer")
343
+
344
+ nErrorLines = lines
345
+ return self
346
+ },
347
+
348
+ /**
349
+ * Adds files from given asset into working directory.
350
+ *
351
+ * @param asset: assetInfo - asset info loaded from assets.importAsset()
352
+ * @param destinationDir: string - path inside working directory for files to be extracted from archive. Use "." for root of the workdir.
353
+ * @param pathsInArchive: string[] - paths inside the archive to be extracted into destinationDir.
354
+ * Empty array means 'unpack full archive'.
355
+ */
356
+ addAsset: func(asset, destinationDir, ...pathsInArchive) {
357
+ if (len(pathsInArchive) == 1 && is_array(pathsInArchive[0])) {
358
+ // support [<paths>] single argument
359
+ pathsInArchive = pathsInArchive[0]
360
+ }
361
+ if len(pathsInArchive) == 0 {
362
+ // default for 'no paths' is to extract all
363
+ pathsInArchive = []
364
+ }
365
+
366
+ ll.assert(assets.isAssetInfo(asset),
367
+ "exec.builder.addAsset: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
368
+ validation.assertJsonSchema(destinationDir, "string", "exec.builder.addAsset: <destinationDir> is not a string. It must be a path inside working directory")
369
+ validation.assertJsonSchema(pathsInArchive, ["string"], "exec.builder.addAsset: <pathsInArchive> must contain list of strings with paths inside archive")
370
+
371
+ assetIdKey := ll.idToString(asset._id)
372
+ if is_undefined(assetRules[assetIdKey]) {
373
+ assetInfos[assetIdKey] = asset.resource
374
+ assetDescriptors[assetIdKey] = ll.fromStrict(asset.descriptor)
375
+ assetRules[assetIdKey] = {}
376
+ }
377
+
378
+ if len(pathsInArchive) == 0 || is_undefined(assetRules[assetIdKey][destinationDir]) {
379
+ assetRules[assetIdKey][destinationDir] = []
380
+ }
381
+
382
+ if (len(pathsInArchive) > 0) {
383
+ assetRules[assetIdKey][destinationDir] = append(assetRules[assetIdKey][destinationDir], pathsInArchive...)
384
+ }
385
+
386
+ return self
387
+ },
388
+
389
+ /**
390
+ * Set custom cache time for given asset. By default, cache time of 1 day is applied to all assets.
391
+ * This allows to customize cache time on per-asset basis
392
+ */
393
+ cacheAssetMillis: func (asset, millis) {
394
+ ll.assert(assets.isAssetInfo(asset),
395
+ "exec.builder.cacheAssetMillis: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
396
+ ll.assert(is_int(millis),
397
+ "exec.builder.cacheAssetMillis: asset cache time must be a number of milliseconds.")
398
+
399
+ assetIdKey := ll.idToString(asset._id)
400
+ assetCache[assetIdKey] = millis * times.millisecond
401
+
402
+ return self
403
+ },
404
+
405
+ /**
406
+ * Set custom cache time for given asset. By default, cache time of 1 day is applied to all assets.
407
+ * This allows to customize cache time on per-asset basis
408
+ */
409
+ cacheAssetSeconds: func (asset, seconds) {
410
+ ll.assert(assets.isAssetInfo(asset),
411
+ "exec.builder.cacheAssetSeconds: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
412
+ ll.assert(is_int(seconds),
413
+ "exec.builder.cacheAssetSeconds: asset cache time must be a number of seconds.")
414
+
415
+ assetIdKey := ll.idToString(asset._id)
416
+ assetCache[assetIdKey] = seconds * times.second
417
+
418
+ return self
419
+ },
420
+
421
+ /**
422
+ * Set custom cache time for given asset. By default, cache time of 1 day is applied to all assets.
423
+ * This allows to customize cache time on per-asset basis
424
+ */
425
+ cacheAssetMinutes: func (asset, minutes) {
426
+ ll.assert(assets.isAssetInfo(asset),
427
+ "exec.builder.cacheAssetMinutes: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
428
+ ll.assert(is_int(minutes),
429
+ "exec.builder.cacheAssetMinutes: asset cache time must be a number of minutes.")
430
+
431
+ assetIdKey := ll.idToString(asset._id)
432
+ assetCache[assetIdKey] = minutes * times.minute
433
+
434
+ return self
435
+ },
436
+
437
+ /**
438
+ * Set custom cache time for given asset. By default, cache time of 1 day is applied to all assets.
439
+ * This allows to customize cache time on per-asset basis
440
+ */
441
+ cacheAssetHours: func (asset, hours) {
442
+ ll.assert(assets.isAssetInfo(asset),
443
+ "exec.builder.cacheAssetHours: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
444
+ ll.assert(is_int(hours),
445
+ "exec.builder.cacheAssetHours: asset cache time must be a number of hours.")
446
+
447
+ assetIdKey := ll.idToString(asset._id)
448
+ assetCache[assetIdKey] = hours * times.hour
449
+
450
+ return self
451
+ },
452
+
453
+ /**
454
+ * Set custom cache time for given asset. By default, cache time of 1 day is applied to all assets.
455
+ * This allows to customize cache time on per-asset basis
456
+ */
457
+ cacheAssetDays: func (asset, days) {
458
+ ll.assert(assets.isAssetInfo(asset),
459
+ "exec.builder.cacheAssetHours: <asset> parameter is not an asset info. Provide the value obtained from assets.importAsset() here")
460
+ ll.assert(is_int(days),
461
+ "exec.builder.cacheAssetHours: asset cache time must be a number of days.")
462
+
463
+ assetIdKey := ll.idToString(asset._id)
464
+ assetCache[assetIdKey] = days * 24 * times.hour
465
+
466
+ return self
467
+ },
468
+
469
+ enableMnz: func(productName) {
470
+ monetization.enable(mnz, productName)
471
+ return self
472
+ },
473
+
474
+ /**
475
+ * Adds a file to the working directory
476
+ *
477
+ * @param fileName: string - the name of the input file.
478
+ * @param file: reference - a resource id of the file or a field that points to it.
479
+ */
480
+ addFile: func(fileName, file, ...opts) {
481
+ ll.assert(is_string(fileName), "exec.builder().addFile: fileName must be a string")
482
+ ll.assert(smart.isReference(file), "exec.builder().addFile: file must be a reference")
483
+
484
+ fileName = path.canonize(fileName)
485
+ filesToAdd[fileName] = file
486
+ _addMnzOption(fileName, opts...)
487
+ return self
488
+ },
489
+
490
+ /**
491
+ * Adds multiple files to the working directory.
492
+ *
493
+ * @param filesMap: map[string]reference - a map of file names to files' references.
494
+ */
495
+ addFiles: func(filesMap, ...opts) {
496
+ ll.assert(ll.isMap(filesMap), "exec.builder().addFiles: filesMap must be map of file names to file resources")
497
+ for fileName, file in filesMap {
498
+ self.addFile(fileName, file, opts...)
499
+ }
500
+ return self
501
+ },
502
+
503
+ /**
504
+ * Writes a file with a given content.
505
+ *
506
+ * @param fileName: string - the name of the content.
507
+ * @param data: bytes|reference - a primitive tengo value (map or array) or a reference to
508
+ * a resource from which data we create a file.
509
+ */
510
+ writeFile: func(fileName, data, ...opts) {
511
+ validation.assertJsonSchema(data, ["or",
512
+ "string",
513
+ "bytes",
514
+ validation.reference])
515
+
516
+ fileName = path.canonize(fileName)
517
+
518
+ filesToWrite[fileName] = data
519
+ _addMnzOption(fileName, opts...)
520
+
521
+ return self
522
+ },
523
+
524
+ /**
525
+ * Creates a directory.
526
+ *
527
+ * @param dir: string - the directory to create.
528
+ */
529
+ mkDir: func(dir) {
530
+ dir = path.canonize(dir)
531
+ dirsToCreate = sets.add(dirsToCreate, dir)
532
+ return self
533
+ },
534
+
535
+ /**
536
+ * Saves a file.
537
+ *
538
+ * @param fileName: string - the name of the output file.
539
+ */
540
+ saveFile: func(fileName) {
541
+ fileName = path.canonize(fileName)
542
+ sets.add(filesToSave, fileName)
543
+ return self
544
+ },
545
+
546
+ /**
547
+ * Saves a file's content to a value resource.
548
+ *
549
+ * @param fileName: string - the name of the output value.
550
+ */
551
+ saveFileContent: func(fileName) {
552
+ fileName = path.canonize(fileName)
553
+ sets.add(filesContentToSave, fileName)
554
+ return self
555
+ },
556
+
557
+ /**
558
+ * Saves files from the exec workdir using regex.
559
+ *
560
+ * @param name: string - a name to refer this file set in the outputs
561
+ * @param regex: string - regex pattern
562
+ */
563
+ saveFileSet: func(name, regex) {
564
+ fileSetsToSave[name] = regex
565
+ return self
566
+ },
567
+
568
+ /**
569
+ * Run specified
570
+ */
571
+ processWorkdir: func(name, tpl, tplArgs) {
572
+ wdProcessors[name] = {
573
+ tpl: tpl,
574
+ tplArgs: tplArgs
575
+ }
576
+ return self
577
+ },
578
+
579
+ /**
580
+ * Saves files content from the exec workdir using regex.
581
+ *
582
+ * @param name: string - a name to refer this file set in the outputs
583
+ * @param regex: string - regex pattern
584
+ */
585
+ saveFileSetContent: func(name, regex) {
586
+ fileSetsContentToSave[name] = regex
587
+ return self
588
+ },
589
+
590
+ /**
591
+ * A command to stream a file by a given file name.
592
+ *
593
+ * @param fileName: string - the name of the file to stream.
594
+ */
595
+ streamFile: func(fileName) {
596
+ fileName = path.canonize(fileName)
597
+ sets.add(filesToStream, fileName)
598
+
599
+ return self
600
+ },
601
+
602
+ /**
603
+ * Set stdout file name
604
+ */
605
+ stdoutFileName: func(fileName) {
606
+ fileName = path.canonize(fileName)
607
+ stdout = fileName
608
+ return self
609
+ },
610
+
611
+ /**
612
+ * Set stderr file name
613
+ */
614
+ stderrFileName: func(fileName) {
615
+ fileName = path.canonize(fileName)
616
+ stderr = fileName
617
+ return self
618
+ },
619
+
620
+ /**
621
+ * Sets stdout to be captured as a value resource.
622
+ */
623
+ saveStdoutContent: func() {
624
+ stdoutToValue = true
625
+ return self
626
+ },
627
+
628
+ /**
629
+ * Sets stderr to be captured as a value resource.
630
+ */
631
+ saveStderrContent: func() {
632
+ stderrToValue = true
633
+ return self
634
+ },
635
+
636
+ /**
637
+ * Redirects stderr output to stdout.
638
+ */
639
+ printErrStreamToStdout: func() {
640
+ stderrToStdout = true
641
+ return self
642
+ },
643
+
644
+ /**
645
+ * Executes the command.
646
+ *
647
+ * @return A map containing the execution results.
648
+ */
649
+ run: func() {
650
+ if stderrToStdout {
651
+ stderr = stdout
652
+ }
653
+ sets.add(filesToStream, stdout)
654
+ sets.add(filesToStream, stderr)
655
+ sets.add(filesToSave, stdout)
656
+ sets.add(filesToSave, stderr)
657
+ if stdoutToValue {
658
+ sets.add(filesContentToSave, stdout)
659
+ }
660
+ if stderrToValue {
661
+ sets.add(filesContentToSave, stderr)
662
+ }
663
+
664
+ // We don't want these values to be encoded as JSON's since
665
+ // values are pure bytes.
666
+ // Thus, we create a resource with a custom type here manually.
667
+ filesToWriteRefs := maps.mapValues(filesToWrite, func(v) {
668
+ if smart.isReference(v) { return v }
669
+ return smart.createValueResource(constants.RTYPE_BINARY_VALUE, v)
670
+ })
671
+
672
+ ll.assert(entrypointSet,
673
+ "incomplete command: cmd() or software() must be provided to exec.builder")
674
+
675
+ runOptions := {
676
+ cmd: cmd,
677
+ args: args,
678
+ envs: envs,
679
+ secrets: secrets,
680
+ queue: queue,
681
+ stdout: stdout,
682
+ stderr: stderr,
683
+ nErrorLines: nErrorLines
684
+ }
685
+
686
+ execInputs := {
687
+ filesToAdd: smart.createMapResource(filesToAdd),
688
+ filesToWrite: smart.createMapResource(filesToWriteRefs),
689
+ dirsToCreate: slices.fromSet(dirsToCreate),
690
+ runOptions: runOptions,
691
+ filesToSave: slices.fromSet(filesToSave),
692
+ filesContentToSave: slices.fromSet(filesContentToSave),
693
+ fileSetsToSave: fileSetsToSave,
694
+ fileSetsContentToSave: fileSetsContentToSave,
695
+ filesToStream: slices.fromSet(filesToStream),
696
+ wdProcessors: wdProcessors,
697
+ assets: smart.createMapResource(assetInfos),
698
+ assetDescriptors: assetDescriptors,
699
+ assetRules: assetRules,
700
+ assetCache: assetCache
701
+ }
702
+
703
+ // We add monetization only if it's enabled
704
+ // to not break a deduplication of exec's
705
+ // that were created before this feature existed.
706
+ if monetization.shouldRun(mnz) {
707
+ execInputs.runOptions.monetization = monetization.toJson(mnz)
708
+ }
709
+
710
+ // We add new argsTyped and envsTyped only when they were added
711
+ // to not break a deduplication on old pl backend.
712
+ if typedArgSet || typedEnvSet {
713
+ execInputs.runOptions.argsTyped = argsTyped
714
+ execInputs.runOptions.envsTyped = envsTyped
715
+ }
716
+
717
+ if !is_undefined(soft) {
718
+ execInputs.softwareInfo = soft.resource
719
+ execInputs.runOptions.software = {
720
+ name: soft.name,
721
+ version: soft.version,
722
+ descriptor: ll.fromStrict(soft.descriptor)
723
+ }
724
+ }
725
+
726
+ tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.exec"), execInputs)
727
+
728
+ self := undefined
729
+ self = ll.toStrict(oop.inherit(tpl, {
730
+ /**
731
+ * Retrieves a file.
732
+ *
733
+ * @param fileName: string
734
+ * @return field - a reference to the file resource.
735
+ */
736
+ getFile: func(fileName) {
737
+ return tpl.output("files", cache).getFutureInputField(fileName)
738
+ },
739
+
740
+ /**
741
+ * Retrieves the content of a file.
742
+ *
743
+ * @param fileName: string
744
+ * @return field - a reference to the file content resource.
745
+ */
746
+ getFileContent: func(fileName) {
747
+ return tpl.output("filesContent", cache).getFutureInputField(fileName)
748
+ },
749
+
750
+ /**
751
+ * Retrieves a file stream.
752
+ *
753
+ * @param fileName: string
754
+ * @return field - a reference to the file stream resource.
755
+ */
756
+ getFileStream: func(fileName) {
757
+ return tpl.output("fileStreams", cache).getFutureInputField(fileName, true)
758
+ },
759
+
760
+ /**
761
+ * Retrieves a file set resource.
762
+ *
763
+ * @param fileSetName: string - name of a file set
764
+ * @return field - a reference to the map resource with files
765
+ */
766
+ getFileSet: func(fileSetName) {
767
+ return tpl.output("fileSets", cache).getFutureInputField(fileSetName)
768
+ },
769
+
770
+ /**
771
+ * Retrieves a file set content resource.
772
+ *
773
+ * @param fileSetName: string - name of a file set
774
+ * @return field - a reference to the map resource with files
775
+ */
776
+ getFileSetContent: func(fileSetName) {
777
+ return tpl.output("fileSetsContent", cache).getFutureInputField(fileSetName)
778
+ },
779
+
780
+ getProcessorResult: func(procName) {
781
+ return tpl.output("wdProcessors", cache).getFutureInputField(procName)
782
+ },
783
+
784
+ /**
785
+ * Retrieves the stdout stream.
786
+ */
787
+ getStdoutStream: func() {
788
+ return self.getFileStream(stdout)
789
+ },
790
+
791
+ /**
792
+ * Retrieves the stderr stream.
793
+ */
794
+ getStderrStream: func() {
795
+ return self.getFileStream(stderr)
796
+ },
797
+
798
+ /**
799
+ * Retrieves the stdout file.
800
+ */
801
+ getStdoutFile: func() {
802
+ return self.getFile(stdout)
803
+ },
804
+
805
+ /**
806
+ * Retrieves the stderr file.
807
+ */
808
+ getStderrFile: func() {
809
+ return self.getFile(stderr)
810
+ },
811
+
812
+ /**
813
+ * Retrieves the content of the stdout file.
814
+ */
815
+ getStdoutFileContent: func() {
816
+ if stdoutToValue {
817
+ return self.getFileContent(stdout)
818
+ }
819
+ ll.panic("stdout was not saved as a content")
820
+ },
821
+
822
+ /**
823
+ * Retrieves the content of the stderr file.
824
+ */
825
+ getStderrFileContent: func() {
826
+ if stderrToValue {
827
+ return self.getFileContent(stderr)
828
+ }
829
+ ll.panic("stderr was not saved as a content")
830
+ }
831
+ }))
832
+
833
+ return self
834
+ }
835
+ })
836
+
837
+ return self
838
838
  }
839
839
 
840
840
  export ll.toStrict({
841
- builder: builder,
842
- canBackendUseExpressions: desc.canBackendUseExpressions
841
+ builder: builder,
842
+ canBackendUseExpressions: desc.canBackendUseExpressions
843
843
  })