@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,296 @@
1
+ ll := import("@platforma-sdk/workflow-tengo:ll")
2
+ smart := import("@platforma-sdk/workflow-tengo:smart")
3
+ workdir := import("@platforma-sdk/workflow-tengo:workdir")
4
+ oop := import("@platforma-sdk/workflow-tengo:oop")
5
+ sets := import("@platforma-sdk/workflow-tengo:sets")
6
+ validation := import("@platforma-sdk/workflow-tengo:validation")
7
+ json := import("json")
8
+
9
+ runEnvDescriptorScheme := {
10
+ registry: "string",
11
+ package: "string",
12
+ type: "string",
13
+ binDir: "string"
14
+ }
15
+
16
+ binaryDescriptorScheme := {
17
+ registry: "string",
18
+ package: "string",
19
+ cmd: ["string"],
20
+ runEnv: runEnvDescriptorScheme
21
+ }
22
+
23
+ localDescriptorScheme := {
24
+ hash: "string",
25
+ path: "string",
26
+ cmd: ["string"],
27
+ runEnv: runEnvDescriptorScheme
28
+ }
29
+
30
+ descriptorScheme := {
31
+ "isDev,omitempty": "bool",
32
+ "binary,omitempty": binaryDescriptorScheme,
33
+ "local,omitempty": localDescriptorScheme
34
+ }
35
+
36
+ softwareInfoScheme := {
37
+ "name": "string",
38
+ "version": "string",
39
+ "descriptor": descriptorScheme
40
+ }
41
+
42
+ META_KEY_DESCRIPTOR := "ctl/runner/package/descriptor"
43
+
44
+ _RTYPE_PACKAGE_GET := { Name: "PackageGet", Version: "1" }
45
+ _INPUT_PACKAGE_NAME := "packageName"
46
+ _INPUT_REGISTRY := "registry"
47
+ _OUTPUT_ARCHIVE := "archive"
48
+
49
+ get := func(registryName, pkgName) {
50
+ res := smart.structBuilder(_RTYPE_PACKAGE_GET)
51
+
52
+ res.getField(_INPUT_REGISTRY).setRefOrJson(registryName)
53
+ res.getField(_INPUT_PACKAGE_NAME).setRefOrJson(pkgName)
54
+
55
+ self := undefined
56
+ self = oop.inherit(res, {
57
+ /**
58
+ * Reference to the software package archive downloaded by 'get'
59
+ *
60
+ * @return archive: field - output field, where info on downloaded archive will appear
61
+ */
62
+ archive: func() {
63
+ return res.outputs()[_OUTPUT_ARCHIVE]
64
+ }
65
+ })
66
+
67
+ return self
68
+ }
69
+
70
+ _RTYPE_PACKAGE_INSTALL := { Name: "PackageInstall", Version: "1" }
71
+ _INPUT_ARCHIVE := "archive"
72
+ _OUTPUT_PACKAGE := "package"
73
+
74
+ install := func(archive) {
75
+ ll.assert(smart.isReference(archive),
76
+ "package.install: <archive> must be reference to package archive. It is usually obtained from package.get().archive")
77
+
78
+ res := smart.structBuilder(_RTYPE_PACKAGE_INSTALL)
79
+
80
+ res.getField(_INPUT_ARCHIVE).set(archive)
81
+
82
+ self := undefined
83
+ self = oop.inherit(res, {
84
+ /**
85
+ * Reference to installed package
86
+ *
87
+ * @return package: smart.field - output field, where installed package will appear
88
+ */
89
+ package: func() {
90
+ return res.getField(_OUTPUT_PACKAGE)
91
+ }
92
+ })
93
+
94
+ return self
95
+ }
96
+
97
+ _RTYPE_PACKAGE_USE := { Name: "PackageUse", Version: "1" }
98
+ _INPUT_PACKAGE_USE_SETTINGS := "settings"
99
+
100
+ _useSettingsSchema := {
101
+ hash: ["or", "bytes", "string"],
102
+ path: "string",
103
+ descriptor: "any",
104
+ origin: {
105
+ registry: "string",
106
+ url: "string",
107
+ packageName: "string"
108
+ }
109
+ }
110
+
111
+ use := func(settings) {
112
+ res := smart.structBuilder(_RTYPE_PACKAGE_USE)
113
+
114
+ validation.assertJsonSchema(settings, _useSettingsSchema, "package.use(<settings>): settings have invalid format")
115
+ settingsRes := smart.createJsonResource(settings)
116
+
117
+ res.getField(_INPUT_PACKAGE_USE_SETTINGS).set(settingsRes)
118
+
119
+ self := undefined
120
+ self = oop.inherit(res, {
121
+ /**
122
+ * Reference to installed package
123
+ *
124
+ * @return package: field - output field, where installed package will appear
125
+ */
126
+ package: func() {
127
+ return res.outputs()[_OUTPUT_PACKAGE]
128
+ }
129
+ })
130
+
131
+ return self
132
+ }
133
+
134
+
135
+ _RTYPE_PACKAGE_PUT_ASSET := { Name: "PackagePutAssetsToWD", Version: "1" }
136
+ _INPUT_PACKAGE := "package"
137
+ _INPUT_WD_IN := "workdirIn"
138
+ _OUTPUT_WD_OUT := "workdirOut"
139
+
140
+ /**
141
+ * Load assets and provide them as files or raw content.
142
+ *
143
+ * @param pkg: package - installed package (usually from package.install(<archive>))
144
+ *
145
+ * @return loader: assetsLoader - builder that provides requested files and content after load() call
146
+ */
147
+ assetsLoader := func(pkg) {
148
+ ll.assert(smart.isReference(pkg),
149
+ "package.loadAssets: <pkg> must be reference to installed package. It is usually obtained from package.install().package")
150
+
151
+ filePaths := []
152
+ fileContentPaths := []
153
+
154
+ self := undefined
155
+
156
+ self = {
157
+ saveFile: func(path) {
158
+ validation.assertJsonSchema(path, "string", "package.assetsLoader.saveFile: <path> must be string")
159
+ filePaths = append(filePaths, path)
160
+
161
+ return self
162
+ },
163
+
164
+ saveFiles: func(paths) {
165
+ validation.assertJsonSchema(paths, ["string"], "package.assetsLoader.saveFiles: <paths> must be array of strings")
166
+ for p in paths {
167
+ self.saveFile(p)
168
+ }
169
+
170
+ return self
171
+ },
172
+
173
+ saveFileContent: func(path) {
174
+ validation.assertJsonSchema(path, "string", "package.assetsLoader.saveFileContent: <path> must be string")
175
+ fileContentPaths = append(fileContentPaths, path)
176
+ return self
177
+ },
178
+
179
+ saveFilesContent: func(paths) {
180
+ validation.assertJsonSchema(paths, ["string"], "package.assetsLoader.saveFilesContent: <paths> must be array of strings")
181
+ for p in paths {
182
+ self.saveFileContent(p)
183
+ }
184
+
185
+ return self
186
+ },
187
+
188
+ load: func() {
189
+ wd := workdir.create()
190
+
191
+ allPaths := sets.fromSlice(filePaths)
192
+ allPaths = sets.add(allPaths, fileContentPaths...)
193
+
194
+ res := smart.ephemeralBuilder(_RTYPE_PACKAGE_PUT_ASSET, json.encode({
195
+ paths: sets.toSlice(allPaths)
196
+ }))
197
+
198
+ res.getField(_INPUT_PACKAGE).set(pkg)
199
+ res.getField(_INPUT_WD_IN).set(wd)
200
+
201
+ wdAfter := res.getField(_OUTPUT_WD_OUT)
202
+
203
+ wdSaveBuilder := workdir.save(wdAfter)
204
+ for p in filePaths {
205
+ wdSaveBuilder.saveFile(p)
206
+ }
207
+ for p in fileContentPaths {
208
+ wdSaveBuilder.saveFileContent(p)
209
+ }
210
+ wdSave := wdSaveBuilder.build()
211
+
212
+ return {
213
+ files: wdSave.files,
214
+ filesContent: wdSave.filesContent,
215
+ progress: wdSave.progress,
216
+
217
+ /**
218
+ * Retrieves selected asset file by its path (use saveFile() to provide asset as file)
219
+ *
220
+ * @param fileName: string
221
+ * @return file: smart.field - a reference to the file resource.
222
+ */
223
+ getFile: func(fileName) {
224
+ return wdSave.files.getFutureInputField(fileName)
225
+ },
226
+
227
+ /**
228
+ * Retrieves selected asset data by its path (use saveFileContent() to provide asset's data)
229
+ *
230
+ * @param fileName: string
231
+ * @return file: smart.field - a reference to the file resource.
232
+ */
233
+ getFileContent: func(fileName) {
234
+ return wdSave.filesContent.getFutureInputField(fileName)
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ return ll.toStrict(self)
241
+ }
242
+
243
+ /**
244
+ * Load single asset by its path inside package, providing it as file.
245
+ *
246
+ * @param pkg: package - installed package (usually from package.install(<archive>))
247
+ * @param assetPath: string - path to asset inside package <pkg>
248
+ *
249
+ * @return file: singleAsset - object with reference to the file resource and progress report
250
+ */
251
+ loadAssetFile := func(pkg, assetPath) {
252
+ assets := assetsLoader(pkg).
253
+ saveFile(assetPath).
254
+ load()
255
+
256
+ return {
257
+ file: assets.getFile(assetPath),
258
+ progress: assets.progress
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Load single asset by its path inside package, providing its raw content.
264
+ *
265
+ * @param pkg: package - installed package (usually from package.install(<archive>))
266
+ * @param assetPath: string - path to asset inside package <pkg>
267
+ *
268
+ * @return content: singleAsset - object with reference to the asset content resource and progress report
269
+ */
270
+ loadAssetContent := func(pkg, assetPath) {
271
+ assets := assetsLoader(pkg).
272
+ saveFileContent(assetPath).
273
+ load()
274
+
275
+ return {
276
+ content: assets.getFileContent(assetPath),
277
+ progress: assets.progress
278
+ }
279
+ }
280
+
281
+
282
+ export ll.toStrict({
283
+ softwareInfoScheme : softwareInfoScheme,
284
+ binaryDescriptorScheme : binaryDescriptorScheme,
285
+ localDescriptorScheme : localDescriptorScheme,
286
+ runEnvDescriptorScheme : runEnvDescriptorScheme,
287
+
288
+ META_KEY_DESCRIPTOR : META_KEY_DESCRIPTOR,
289
+
290
+ get : get,
291
+ install : install,
292
+ use : use,
293
+ assetsLoader : assetsLoader,
294
+ loadAssetFile : loadAssetFile,
295
+ loadAssetContent : loadAssetContent
296
+ })
@@ -0,0 +1,275 @@
1
+ /** A library that creates RunCommand resource. */
2
+
3
+ ll := import("@platforma-sdk/workflow-tengo:ll")
4
+ maps := import("@platforma-sdk/workflow-tengo:maps")
5
+ oop := import("@platforma-sdk/workflow-tengo:oop")
6
+ smart := import("@platforma-sdk/workflow-tengo:smart")
7
+ json := import("json")
8
+
9
+ _RTYPE_RUN_COMMAND := { Name: "RunCommand/executor", Version: "1" }
10
+ _RTYPE_RUN_COMMAND_CMD := { Name: "RunCommandCmd", Version: "1" }
11
+ _RTYPE_RUN_COMMAND_ARGS := { Name: "RunCommandArgs", Version: "1" }
12
+ _RTYPE_RUN_COMMAND_OPTIONS := { Name: "run-command/options", Version: "1" }
13
+ _RTYPE_RUN_COMMAND_REFS := { Name: "RunCommandRefs", Version: "1" }
14
+
15
+ /**
16
+ * Creates a simple argument for the command.
17
+ *
18
+ * @param argument: string - the argument to create.
19
+ */
20
+ _createSimpleArg := func(argument) {
21
+ return {
22
+ type: "string",
23
+ value: argument
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Creates 'variableRef' argument.
29
+ * @param argTpl: string - argument value in any form with variables inside (e.g. "file://{pkg}/some-file" or "o-{java}-o")
30
+ */
31
+ _createVariableArg := func(argTpl) {
32
+ return {
33
+ type: "variableRef",
34
+ value: argTpl
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Builder function for creating a RunCommand resource.
40
+ *
41
+ * @param workdir: string - the working directory for the command.
42
+ * @return builder - the builder object with methods for configuring and building the RunCommand resource.
43
+ */
44
+ builder := func(workdir) {
45
+ res := smart.ephemeralBuilder(_RTYPE_RUN_COMMAND)
46
+ res.getField("workdirIn").set(workdir)
47
+
48
+ self := undefined
49
+
50
+ cmd := undefined
51
+ args := []
52
+ envs := {}
53
+ queue := ""
54
+ refs := {}
55
+
56
+ substRules := {}
57
+ hasPatternArgs := false
58
+ customPaths := []
59
+
60
+ stdout := "stdout.txt"
61
+ stderr := "stderr.txt"
62
+ nErrorLines := 200
63
+
64
+ self = ll.toStrict(oop.inherit(res, {
65
+ /**
66
+ * Sets the command, e.g. /usr/bin/env or sh.
67
+ *
68
+ * @param commandName: string - the name of the command.
69
+ */
70
+ cmd: func(commandName) {
71
+ cmd = _createSimpleArg(commandName)
72
+ return self
73
+ },
74
+
75
+ /**
76
+ * Sets the command with variables inside to be rendered using rules
77
+ * from .substitutionRules().
78
+ *
79
+ * @param commandTpl: string - string with '{varName}' substitutions to be replaced with
80
+ * software paths. Replace rules are defined by .substitutionRule()
81
+ * and .substitutionRules(),
82
+ */
83
+ cmdVar: func(commandTpl) {
84
+ cmd = _createVariableArg(commandTpl)
85
+ hasPatternArgs = true
86
+ return self
87
+ },
88
+
89
+ /**
90
+ * Adds an argument to the command.
91
+ *
92
+ * @param arg: string - the argument to add.
93
+ */
94
+ arg: func(arg) {
95
+ args = append(args, _createSimpleArg(arg))
96
+ return self
97
+ },
98
+
99
+ /**
100
+ * Adds an argument with variables inside to be rendered using rules
101
+ * from .substitutionRules().
102
+ *
103
+ * @param argTpl: string - string with '{varName}' substitutions to be replaced with
104
+ * software paths. Replace rules are defined by .substitutionRule()
105
+ * and .substitutionRules(),
106
+ */
107
+ argVar: func(argTpl) {
108
+ args = append(args, _createVariableArg(argTpl))
109
+ hasPatternArgs = true
110
+ return self
111
+ },
112
+
113
+ ref: func(refKey, ref) {
114
+ ll.assert(smart.isReference(ref),
115
+ "runcmd.builder().ref() must be a reference (valid field or resource)")
116
+
117
+ ll.assert(!maps.containsKey(refs, refKey),
118
+ "attempt to override existing reference %q", refKey)
119
+
120
+ refs[refKey] = ref
121
+ return self
122
+ },
123
+
124
+ /**
125
+ * Sets an environment variable for the command.
126
+ *
127
+ * @param name: string - the name of the environment variable.
128
+ * @param value: string - the value of the environment variable.
129
+ */
130
+ env: func(name, value) {
131
+ envs[name] = value
132
+ return self
133
+ },
134
+
135
+ /**
136
+ * Sets environment variable with substitution inside value, to be rendered
137
+ * using rules from .substitutionRules().
138
+ *
139
+ * @param name: string - the name of the environment variable.
140
+ * @param valueTpl: string - the value of the environment variable.
141
+ */
142
+ envVar: func(name, valueTpl) {
143
+ envs[name] = _createVariableArg(valueTpl)
144
+ hasPatternArgs = true
145
+ return self
146
+ },
147
+
148
+ /*
149
+ * Patch 'PATH' environment variable, adding software path to it.
150
+ *
151
+ * @param value: string - the value of the environment variable with variables to be replaced to software path.
152
+ * @param hasVars: boolean - wether Platforma Backend should try to substitute variables inside <value> on server side
153
+ */
154
+ addToPath: func(value, hasVars) {
155
+ if hasVars {
156
+ customPaths = append(customPaths, _createVariableArg(value))
157
+ hasPatternArgs = true
158
+ } else {
159
+ customPaths = append(customPaths, _createSimpleArg(value))
160
+ }
161
+ return self
162
+ },
163
+
164
+ /**
165
+ * Define substitution variable for software args.
166
+ *
167
+ * @param varName: string - variable to be substituted in arg value ("var1" would be
168
+ * substituted in place of {var1} of arg value)
169
+ * @param refKey: string - key of ref (added with .ref()) that points to installed software.
170
+ */
171
+ substitutionRule: func(varName, refKey) {
172
+ substRules[varName] = refKey
173
+ return self
174
+ },
175
+
176
+ /**
177
+ * Batched .substitutionRule() call (add several rules in single call)
178
+ *
179
+ * @param rules: map[string]string - <var name> -> <ref key> pairs to be added to substitution rules.
180
+ */
181
+ substitutionRules: func(rules) {
182
+ for k, v in rules {
183
+ substRules[k] = v
184
+ }
185
+ return self
186
+ },
187
+
188
+ /**
189
+ * Sets the queue name for the command.
190
+ *
191
+ * @param queueName: string - the name of the queue.
192
+ */
193
+ inQueue: func(queueName) {
194
+ queue = queueName
195
+ return self
196
+ },
197
+
198
+ /**
199
+ * Sets the stdout file name for the command.
200
+ *
201
+ * @param fileName: string - the name of the stdout file.
202
+ */
203
+ stdout: func(fileName) {
204
+ stdout = fileName
205
+ return self
206
+ },
207
+
208
+ /**
209
+ * Sets the stderr file name for the command.
210
+ *
211
+ * @param fileName: string - the name of the stderr file.
212
+ */
213
+ stderr: func(fileName) {
214
+ stderr = fileName
215
+ return self
216
+ },
217
+
218
+ /**
219
+ * Sets the number of error lines for the command.
220
+ *
221
+ * @param number: int - the number of error lines.
222
+ */
223
+ nErrorLines: func(number) {
224
+ nErrorLines = number
225
+ return self
226
+ },
227
+
228
+ /**
229
+ * Builds the RunCommand resource.
230
+ *
231
+ * @return object - the built RunCommand resource.
232
+ */
233
+ build: func() {
234
+ // TODO: add assertions about the state
235
+
236
+ ll.assert(!hasPatternArgs || len(substRules) != 0,
237
+ "found pattern argument, but no substitution rules were set")
238
+
239
+ refsRes := smart.createMapResourceWithType(_RTYPE_RUN_COMMAND_REFS, refs)
240
+ self.getField("refs").set(refsRes)
241
+
242
+ cmdRes := smart.createValueResource(_RTYPE_RUN_COMMAND_CMD, json.encode(cmd))
243
+ self.getField("cmd").set(cmdRes)
244
+
245
+ options := {
246
+ queueName: queue,
247
+ errorLines: nErrorLines,
248
+ redirectStdout: stdout,
249
+ redirectStderr: stderr,
250
+ env: envs,
251
+ additionalPaths: customPaths,
252
+ substitutions: substRules
253
+ }
254
+
255
+ optionsRes := smart.createValueResource(_RTYPE_RUN_COMMAND_OPTIONS, json.encode(options))
256
+ self.getField("options").set(optionsRes)
257
+
258
+ argsRes := smart.createValueResource(_RTYPE_RUN_COMMAND_ARGS, json.encode(args))
259
+ self.getField("args").set(argsRes)
260
+
261
+ res := ll.toStrict(oop.inherit(self.lockAndBuild(), {
262
+ "workdir": self.outputs().workdirOut,
263
+ "options": options
264
+ }))
265
+
266
+ return res
267
+ }
268
+ }))
269
+
270
+ return self
271
+ }
272
+
273
+ export ll.toStrict({
274
+ builder: builder
275
+ })