@platforma-sdk/workflow-tengo 1.2.6

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 (51) hide show
  1. package/README.md +6 -0
  2. package/dist/tengo/lib/assets.lib.tengo +64 -0
  3. package/dist/tengo/lib/constants.lib.tengo +75 -0
  4. package/dist/tengo/lib/exec.internal.lib.tengo +211 -0
  5. package/dist/tengo/lib/exec.lib.tengo +516 -0
  6. package/dist/tengo/lib/exec.package.lib.tengo +296 -0
  7. package/dist/tengo/lib/exec.runcmd.lib.tengo +275 -0
  8. package/dist/tengo/lib/exec.runenv.lib.tengo +221 -0
  9. package/dist/tengo/lib/exec.stream.lib.tengo +64 -0
  10. package/dist/tengo/lib/file.lib.tengo +112 -0
  11. package/dist/tengo/lib/ll.lib.tengo +233 -0
  12. package/dist/tengo/lib/maps.lib.tengo +102 -0
  13. package/dist/tengo/lib/objects.lib.tengo +22 -0
  14. package/dist/tengo/lib/oop.lib.tengo +29 -0
  15. package/dist/tengo/lib/path.lib.tengo +165 -0
  16. package/dist/tengo/lib/pframes.constants.lib.tengo +53 -0
  17. package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +47 -0
  18. package/dist/tengo/lib/pframes.lib.tengo +84 -0
  19. package/dist/tengo/lib/pframes.ll.lib.tengo +86 -0
  20. package/dist/tengo/lib/pframes.util.lib.tengo +244 -0
  21. package/dist/tengo/lib/pframes.xsv.lib.tengo +178 -0
  22. package/dist/tengo/lib/render.lib.tengo +100 -0
  23. package/dist/tengo/lib/sets.lib.tengo +93 -0
  24. package/dist/tengo/lib/slices.lib.tengo +202 -0
  25. package/dist/tengo/lib/smart.lib.tengo +1005 -0
  26. package/dist/tengo/lib/tpl.lib.tengo +535 -0
  27. package/dist/tengo/lib/tpl.state-await.lib.tengo +255 -0
  28. package/dist/tengo/lib/tpl.util.lib.tengo +19 -0
  29. package/dist/tengo/lib/validation.lib.tengo +428 -0
  30. package/dist/tengo/lib/workdir.lib.tengo +300 -0
  31. package/dist/tengo/lib/workdir.proc.lib.tengo +158 -0
  32. package/dist/tengo/lib/workdir.save.lib.tengo +158 -0
  33. package/dist/tengo/lib/workflow.bobject.lib.tengo +51 -0
  34. package/dist/tengo/lib/workflow.bquery.lib.tengo +208 -0
  35. package/dist/tengo/lib/workflow.constants.lib.tengo +8 -0
  36. package/dist/tengo/lib/workflow.context.lib.tengo +56 -0
  37. package/dist/tengo/lib/workflow.lib.tengo +298 -0
  38. package/dist/tengo/tpl/exec.create-python-venv.plj.gz +0 -0
  39. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  40. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  41. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  42. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  43. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  44. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  45. package/dist/tengo/tpl/pframes.import-xsv-map.plj.gz +0 -0
  46. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  47. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  48. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  49. package/index.d.ts +4 -0
  50. package/index.js +13 -0
  51. package/package.json +25 -0
@@ -0,0 +1,516 @@
1
+ /**
2
+ * A builder for executing commands.
3
+ */
4
+ ll := import("@platforma-sdk/workflow-tengo:ll")
5
+ assets := import("@platforma-sdk/workflow-tengo:assets")
6
+ smart := import("@platforma-sdk/workflow-tengo:smart")
7
+ times := import("times")
8
+ maps := import("@platforma-sdk/workflow-tengo:maps")
9
+ sets := import("@platforma-sdk/workflow-tengo:sets")
10
+ slices := import("@platforma-sdk/workflow-tengo:slices")
11
+ path := import("@platforma-sdk/workflow-tengo:path")
12
+ render := import("@platforma-sdk/workflow-tengo:render")
13
+ enum := import("enum")
14
+ oop := import("@platforma-sdk/workflow-tengo:oop")
15
+ validation := import("@platforma-sdk/workflow-tengo:validation")
16
+ constants := import("@platforma-sdk/workflow-tengo:constants")
17
+
18
+ _HEAVY_QUEUE := "heavy"
19
+ _UI_TASKS_QUEUE := "ui-tasks"
20
+
21
+ /**
22
+ * Creates a new builder for constructing and executing commands.
23
+ *
24
+ * @return builder - a new builder instance.
25
+ */
26
+ builder := func() {
27
+ self := undefined
28
+
29
+ soft := undefined
30
+ cmd := undefined
31
+ args := []
32
+ entrypointSet := false
33
+
34
+ assertEntrypointNotSet := func() {
35
+ ll.assert(!entrypointSet,
36
+ "either a command with arguments or a software were already set.")
37
+ }
38
+
39
+ envs := {}
40
+ queue := _HEAVY_QUEUE
41
+ cache := 0
42
+ nErrorLines := 200
43
+
44
+ // files to be added in workdir
45
+ filesToAdd := {}
46
+ // files to be created in the workdir with the content from resources
47
+ filesToWrite := {}
48
+ // directories to create in the workdir
49
+ dirsToCreate := {}
50
+
51
+ // files to save from the workdir
52
+ filesToSave := {}
53
+ // files which content to save from the workdir
54
+ filesContentToSave := {}
55
+ // file sets to save by regex
56
+ fileSetsToSave := {}
57
+ // file sets to save by regex (save file content)
58
+ fileSetsContentToSave := {}
59
+ // files to stream from the workdir
60
+ filesToStream := {}
61
+ // workdir processors
62
+ wdProcessors := {}
63
+
64
+ stdout := "stdout.txt"
65
+ stderr := "stderr.txt"
66
+
67
+ stdoutToValue := false
68
+ stderrToValue := false
69
+ stderrToStdout := false
70
+
71
+ self = ll.toStrict({
72
+ /**
73
+ * Sets the command to be executed, e.g. /usr/bin/env or sh.
74
+ *
75
+ * @param commandName: string - the name of the command.
76
+ */
77
+ cmd: func(commandName) {
78
+ assertEntrypointNotSet()
79
+
80
+ cmd = commandName
81
+ entrypointSet = true
82
+ return self
83
+ },
84
+
85
+ /**
86
+ * Sets the software to be executed.
87
+ *
88
+ * @param software: softwareInfo - the software to execute.
89
+ */
90
+ software: func(sw) {
91
+ assertEntrypointNotSet()
92
+ ll.assert(assets.isSoftwareInfo(sw),
93
+ "exec.builder.software: <software> parameter is not a software info. Provide the value obtained from ll.importSoftware() here"
94
+ )
95
+
96
+ soft = sw
97
+ entrypointSet = true
98
+ return self
99
+ },
100
+
101
+ /**
102
+ * Adds an argument to the command.
103
+ *
104
+ * @param arg: string - the argument to add.
105
+ */
106
+ arg: func(arg) {
107
+ args = append(args, arg)
108
+ return self
109
+ },
110
+
111
+ /**
112
+ * Sets an environment variable.
113
+ *
114
+ * @param name: string - the name of the environment variable.
115
+ * @param value: string - the value of the environment variable.
116
+ */
117
+ env: func(name, value) {
118
+ validation.assertJsonSchema([name, value], ["string"])
119
+ envs[name] = value
120
+ return self
121
+ },
122
+
123
+ /**
124
+ * Sets multiple environment variables.
125
+ *
126
+ * @param envMap: map[string]string - a map of environment variables.
127
+ */
128
+ envMap: func(envMap) {
129
+ enum.each(envMap, self.env)
130
+ return self
131
+ },
132
+
133
+ /**
134
+ * Sets the execution queue to the heavy queue.
135
+ */
136
+ inHeavyQueue: func() {
137
+ queue = _HEAVY_QUEUE
138
+ return self
139
+ },
140
+
141
+ /**
142
+ * Sets the execution queue to the UI tasks queue.
143
+ */
144
+ inUiQueue: func() {
145
+ queue = _UI_TASKS_QUEUE
146
+ return self
147
+ },
148
+
149
+ /**
150
+ * Sets the cache time.
151
+ *
152
+ * @param time: duration - the cache time from 'times' library.
153
+ */
154
+ cache: func(time) {
155
+ ll.assert(
156
+ is_int(time),
157
+ "cache time must be an integer. " +
158
+ "Did you forget to import a standard tengo library 'time'?")
159
+ cache = time
160
+ return self
161
+ },
162
+
163
+ /**
164
+ * Sets the number of error lines to be captured.
165
+ *
166
+ * @param lines: number - the number of error lines.
167
+ */
168
+ nErrorLines: func(lines) {
169
+ ll.assert(
170
+ is_int(lines) && lines >= 0,
171
+ "lines must be integer")
172
+
173
+ nErrorLines = lines
174
+ return self
175
+ },
176
+
177
+ /**
178
+ * Adds a file to the working directory
179
+ *
180
+ * @param fileName: string - the name of the input file.
181
+ * @param file: reference - a resource id of the file or a field that points to it.
182
+ */
183
+ addFile: func(fileName, file) {
184
+ fileName = path.canonize(fileName)
185
+ filesToAdd[fileName] = file
186
+ return self
187
+ },
188
+
189
+ /**
190
+ * Adds multiple files to the working directory.
191
+ *
192
+ * @param filesMap: map[string]reference - a map of file names to files' references.
193
+ */
194
+ addFiles: func(filesMap) {
195
+ enum.each(filesMap, self.addFile)
196
+ return self
197
+ },
198
+
199
+ /**
200
+ * Writes a file with a given content.
201
+ *
202
+ * @param fileName: string - the name of the content.
203
+ * @param data: bytes|reference - a primitive tengo value (map or array) or a reference to
204
+ * a resource from which data we create a file.
205
+ */
206
+ writeFile: func(fileName, data) {
207
+ validation.assertJsonSchema(data, ["or",
208
+ "string",
209
+ "bytes",
210
+ validation.reference])
211
+
212
+ fileName = path.canonize(fileName)
213
+
214
+ filesToWrite[fileName] = data
215
+
216
+ return self
217
+ },
218
+
219
+ /**
220
+ * Creates a directory.
221
+ *
222
+ * @param dir: string - the directory to create.
223
+ */
224
+ mkDir: func(dir) {
225
+ dir = path.canonize(dir)
226
+ dirsToCreate = sets.add(dirsToCreate, dir)
227
+ return self
228
+ },
229
+
230
+ /**
231
+ * Saves a file.
232
+ *
233
+ * @param fileName: string - the name of the output file.
234
+ */
235
+ saveFile: func(fileName) {
236
+ fileName = path.canonize(fileName)
237
+ sets.add(filesToSave, fileName)
238
+ return self
239
+ },
240
+
241
+ /**
242
+ * Saves a file's content to a value resource.
243
+ *
244
+ * @param fileName: string - the name of the output value.
245
+ */
246
+ saveFileContent: func(fileName) {
247
+ fileName = path.canonize(fileName)
248
+ sets.add(filesContentToSave, fileName)
249
+ return self
250
+ },
251
+
252
+ /**
253
+ * Saves files from the exec workdir using regex.
254
+ *
255
+ * @param name: string - a name to refer this file set in the outputs
256
+ * @param regex: string - regex pattern
257
+ */
258
+ saveFileSet: func(name, regex) {
259
+ fileSetsToSave[name] = regex
260
+ return self
261
+ },
262
+
263
+ /**
264
+ * Run specified
265
+ */
266
+ processWorkdir: func(name, tpl, tplArgs) {
267
+ wdProcessors[name] = {
268
+ tpl: tpl,
269
+ tplArgs: tplArgs
270
+ }
271
+ return self
272
+ },
273
+
274
+ /**
275
+ * Saves files content from the exec workdir using regex.
276
+ *
277
+ * @param name: string - a name to refer this file set in the outputs
278
+ * @param regex: string - regex pattern
279
+ */
280
+ saveFileSetContent: func(name, regex) {
281
+ fileSetsContentToSave[name] = regex
282
+ return self
283
+ },
284
+
285
+ /**
286
+ * A command to stream a file by a given file name.
287
+ *
288
+ * @param fileName: string - the name of the file to stream.
289
+ */
290
+ streamFile: func(fileName) {
291
+ fileName = path.canonize(fileName)
292
+ sets.add(filesToStream, fileName)
293
+
294
+ return self
295
+ },
296
+
297
+ /**
298
+ * Set stdout file name
299
+ */
300
+ stdoutFileName: func(fileName) {
301
+ fileName = path.canonize(fileName)
302
+ stdout = fileName
303
+ return self
304
+ },
305
+
306
+ /**
307
+ * Set stderr file name
308
+ */
309
+ stderrFileName: func(fileName) {
310
+ fileName = path.canonize(fileName)
311
+ stderr = fileName
312
+ return self
313
+ },
314
+
315
+ /**
316
+ * Sets stdout to be captured as a value resource.
317
+ */
318
+ saveStdoutContent: func() {
319
+ stdoutToValue = true
320
+ return self
321
+ },
322
+
323
+ /**
324
+ * Sets stderr to be captured as a value resource.
325
+ */
326
+ saveStderrContent: func() {
327
+ stderrToValue = true
328
+ return self
329
+ },
330
+
331
+ /**
332
+ * Redirects stderr output to stdout.
333
+ */
334
+ printErrStreamToStdout: func() {
335
+ stderrToStdout = true
336
+ return self
337
+ },
338
+
339
+ /**
340
+ * Executes the command.
341
+ *
342
+ * @return A map containing the execution results.
343
+ */
344
+ run: func() {
345
+ if stderrToStdout {
346
+ stderr = stdout
347
+ }
348
+ sets.add(filesToStream, stdout)
349
+ sets.add(filesToStream, stderr)
350
+ sets.add(filesToSave, stdout)
351
+ sets.add(filesToSave, stderr)
352
+ if stdoutToValue {
353
+ sets.add(filesContentToSave, stdout)
354
+ }
355
+ if stderrToValue {
356
+ sets.add(filesContentToSave, stderr)
357
+ }
358
+
359
+ // We don't want these values to be encoded as JSON's since
360
+ // values are pure bytes.
361
+ // Thus, we create a resource with a custom type here manually.
362
+ filesToWriteRefs := maps.mapValues(filesToWrite, func(v) {
363
+ if smart.isReference(v) { return v }
364
+ return smart.createValueResource(constants.RTYPE_BINARY_VALUE, v)
365
+ })
366
+
367
+ ll.assert(entrypointSet,
368
+ "incomplete command: cmd() or software() must be provided to exec.builder")
369
+
370
+ execInputs := {
371
+ filesToAdd: smart.createMapResource(filesToAdd),
372
+ filesToWrite: smart.createMapResource(filesToWriteRefs),
373
+ dirsToCreate: slices.fromSet(dirsToCreate),
374
+ runOptions: {
375
+ cmd: cmd,
376
+ args: args,
377
+ envs: envs,
378
+ queue: queue,
379
+ stdout: stdout,
380
+ stderr: stderr,
381
+ nErrorLines: nErrorLines
382
+ },
383
+ filesToSave: slices.fromSet(filesToSave),
384
+ filesContentToSave: slices.fromSet(filesContentToSave),
385
+ fileSetsToSave: fileSetsToSave,
386
+ fileSetsContentToSave: fileSetsContentToSave,
387
+ filesToStream: slices.fromSet(filesToStream),
388
+ wdProcessors: wdProcessors
389
+ }
390
+
391
+ if !is_undefined(soft) {
392
+ execInputs.softwareInfo = soft.resource
393
+ execInputs.runOptions.software = {
394
+ name: soft.name,
395
+ version: soft.version,
396
+ descriptor: ll.fromStrict(soft.descriptor)
397
+ }
398
+ }
399
+
400
+ tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.exec"), execInputs)
401
+
402
+ self := undefined
403
+ self = ll.toStrict(oop.inherit(tpl, {
404
+ /**
405
+ * Retrieves a file.
406
+ *
407
+ * @param fileName: string
408
+ * @return field - a reference to the file resource.
409
+ */
410
+ getFile: func(fileName) {
411
+ return tpl.output("files", cache).getFutureInputField(fileName)
412
+ },
413
+
414
+ /**
415
+ * Retrieves the content of a file.
416
+ *
417
+ * @param fileName: string
418
+ * @return field - a reference to the file content resource.
419
+ */
420
+ getFileContent: func(fileName) {
421
+ return tpl.output("filesContent", cache).getFutureInputField(fileName)
422
+ },
423
+
424
+ /**
425
+ * Retrieves a file stream.
426
+ *
427
+ * @param fileName: string
428
+ * @return field - a reference to the file stream resource.
429
+ */
430
+ getFileStream: func(fileName) {
431
+ return tpl.output("fileStreams", cache).getFutureInputField(fileName)
432
+ },
433
+
434
+ /**
435
+ * Retrieves a file set resource.
436
+ *
437
+ * @param fileSetName: string - name of a file set
438
+ * @return field - a reference to the map resource with files
439
+ */
440
+ getFileSet: func(fileSetName) {
441
+ return tpl.output("fileSets", cache).getFutureInputField(fileSetName)
442
+ },
443
+
444
+ /**
445
+ * Retrieves a file set content resource.
446
+ *
447
+ * @param fileSetName: string - name of a file set
448
+ * @return field - a reference to the map resource with files
449
+ */
450
+ getFileSetContent: func(fileSetName) {
451
+ return tpl.output("fileSetsContent", cache).getFutureInputField(fileSetName)
452
+ },
453
+
454
+ getProcessorResult: func(procName) {
455
+ return tpl.output("wdProcessors", cache).getFutureInputField(procName)
456
+ },
457
+
458
+ /**
459
+ * Retrieves the stdout stream.
460
+ */
461
+ getStdoutStream: func() {
462
+ return self.getFileStream(stdout)
463
+ },
464
+
465
+ /**
466
+ * Retrieves the stderr stream.
467
+ */
468
+ getStderrStream: func() {
469
+ return self.getFileStream(stderr)
470
+ },
471
+
472
+ /**
473
+ * Retrieves the stdout file.
474
+ */
475
+ getStdoutFile: func() {
476
+ return self.getFile(stdout)
477
+ },
478
+
479
+ /**
480
+ * Retrieves the stderr file.
481
+ */
482
+ getStderrFile: func() {
483
+ return self.getFile(stderr)
484
+ },
485
+
486
+ /**
487
+ * Retrieves the content of the stdout file.
488
+ */
489
+ getStdoutFileContent: func() {
490
+ if stdoutToValue {
491
+ return self.getFileContent(stdout)
492
+ }
493
+ ll.panic("stdout was not saved as a content")
494
+ },
495
+
496
+ /**
497
+ * Retrieves the content of the stderr file.
498
+ */
499
+ getStderrFileContent: func() {
500
+ if stderrToValue {
501
+ return self.getFileContent(stderr)
502
+ }
503
+ ll.panic("stderr was not saved as a content")
504
+ }
505
+ }))
506
+
507
+ return self
508
+ }
509
+ })
510
+
511
+ return self
512
+ }
513
+
514
+ export ll.toStrict({
515
+ builder: builder
516
+ })