@platforma-sdk/workflow-tengo 2.8.8 → 2.9.0

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 (32) hide show
  1. package/dist/tengo/lib/assets.lib.tengo +12 -46
  2. package/dist/tengo/lib/assets.swinfo.lib.tengo +65 -0
  3. package/dist/tengo/lib/exec.R.internal.lib.tengo +11 -7
  4. package/dist/tengo/lib/exec.R.lib.tengo +5 -2
  5. package/dist/tengo/lib/exec.constants.lib.tengo +11 -0
  6. package/dist/tengo/lib/exec.descriptor.lib.tengo +54 -0
  7. package/dist/tengo/lib/exec.internal.lib.tengo +65 -35
  8. package/dist/tengo/lib/exec.lib.tengo +3 -1
  9. package/dist/tengo/lib/exec.monetization.lib.tengo +21 -6
  10. package/dist/tengo/lib/exec.package.lib.tengo +2 -40
  11. package/dist/tengo/lib/exec.python.internal.lib.tengo +2 -2
  12. package/dist/tengo/lib/exec.python.lib.tengo +5 -2
  13. package/dist/tengo/lib/exec.runcmd.lib.tengo +132 -8
  14. package/dist/tengo/lib/ll.lib.tengo +40 -36
  15. package/dist/tengo/lib/maps.lib.tengo +1 -0
  16. package/dist/tengo/lib/smart.lib.tengo +2 -2
  17. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  18. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  19. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  22. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  23. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  24. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  25. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  26. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  27. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  28. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  29. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  30. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  31. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  32. package/package.json +1 -1
@@ -4,6 +4,8 @@ plapi := import("plapi")
4
4
  json := import("json")
5
5
  ll := import("@platforma-sdk/workflow-tengo:ll")
6
6
  smart := import("@platforma-sdk/workflow-tengo:smart")
7
+ swinfo := import("@platforma-sdk/workflow-tengo:assets.swinfo")
8
+ maps := import("@platforma-sdk/workflow-tengo:maps")
7
9
 
8
10
 
9
11
 
@@ -29,46 +31,6 @@ return smart.resource(plapi.getTemplateId(tplName))
29
31
 
30
32
 
31
33
 
32
-
33
- importSoftware := func(swName) {
34
- sw := plapi.getSoftwareInfo(swName)
35
- return ll.toStrict({
36
- _type: "softwareDescriptor",
37
- _id: sw.id,
38
-
39
- resource: smart.resource(sw.id),
40
- name: sw.name,
41
- version: sw.version,
42
- blobRef: sw.blobRef,
43
- descriptor: ll.toStrict(json.decode(sw.descriptor)) // raw sw.json data with software entrypoint descriptor
44
- })
45
- }
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
- isSoftwareInfo := func(toCheck) {
55
- if !ll.isMap(toCheck) {
56
- return false
57
- }
58
-
59
- return (ll.fromStrict(toCheck)._type) == "softwareDescriptor"
60
- }
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
34
  importAsset := func(assetName) {
73
35
  asset := plapi.getSoftwareInfo(assetName)
74
36
  return ll.toStrict({
@@ -95,13 +57,17 @@ if !ll.isMap(toCheck) {
95
57
  return false
96
58
  }
97
59
 
98
- return (ll.fromStrict(toCheck)._type) == "assetDescriptor"
60
+ if !maps.containsKey(toCheck, "_type") {
61
+ return false
62
+ }
63
+
64
+ return toCheck._type == "assetDescriptor"
99
65
  }
100
66
 
101
67
  export ll.toStrict({
102
- importTemplate: importTemplate,
103
- importSoftware: importSoftware,
104
- isSoftwareInfo: isSoftwareInfo,
105
- importAsset: importAsset,
106
- isAssetInfo: isAssetInfo
68
+ importTemplate : importTemplate,
69
+ importSoftware : swinfo.importSoftware,
70
+ isSoftwareInfo : swinfo.isSoftwareInfo,
71
+ importAsset : importAsset,
72
+ isAssetInfo : isAssetInfo
107
73
  })
@@ -0,0 +1,65 @@
1
+
2
+
3
+
4
+
5
+ plapi := import("plapi")
6
+ ll := import("@platforma-sdk/workflow-tengo:ll")
7
+ maps := import("@platforma-sdk/workflow-tengo:maps")
8
+ smart := import("@platforma-sdk/workflow-tengo:smart")
9
+ json := import("json")
10
+
11
+
12
+
13
+
14
+ newSoftwareInfo := func(sw) {
15
+ return ll.toStrict({
16
+ _type: "softwareDescriptor",
17
+ _id: sw.id,
18
+
19
+ resource: smart.resource(sw.id),
20
+ name: sw.name,
21
+ version: sw.version,
22
+ blobRef: sw.blobRef,
23
+ descriptor: ll.toStrict(json.decode(sw.descriptor)) // raw sw.json data with software entrypoint descriptor
24
+ })
25
+ }
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+ importSoftware := func(swName) {
39
+ return newSoftwareInfo(plapi.getSoftwareInfo(swName))
40
+ }
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+ isSoftwareInfo := func(toCheck) {
50
+ if !ll.isMap(toCheck) {
51
+ return false
52
+ }
53
+
54
+ if !maps.containsKey(toCheck, "_type") {
55
+ return false
56
+ }
57
+
58
+ return toCheck._type == "softwareDescriptor"
59
+ }
60
+
61
+ export ll.toStrict({
62
+ newSoftwareInfo: newSoftwareInfo,
63
+ importSoftware: importSoftware,
64
+ isSoftwareInfo: isSoftwareInfo
65
+ })
@@ -1,8 +1,9 @@
1
1
  ll := import("@platforma-sdk/workflow-tengo:ll")
2
2
  validation := import("@platforma-sdk/workflow-tengo:validation")
3
3
  runcmd := import("@platforma-sdk/workflow-tengo:exec.runcmd")
4
- pkg := import("@platforma-sdk/workflow-tengo:exec.package")
5
4
  path := import("@platforma-sdk/workflow-tengo:path")
5
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
6
+ constants := import("@platforma-sdk/workflow-tengo:exec.constants")
6
7
 
7
8
  rVenvInputSchema := {
8
9
  operationMode: "string",
@@ -10,18 +11,21 @@ toolset: "string",
10
11
  dependencies: {"any": "string"},
11
12
  software: validation.reference,
12
13
 
13
- rDescriptor: pkg.runEnvDescriptorScheme,
14
+ rDescriptor: desc.runEnvScheme,
14
15
  R: validation.reference
15
16
  }
16
17
 
17
18
  runRBuilder := func(wd, rPackage, rDescriptor) {
19
+ t := desc.canBackendUseExpressions() ? constants.ARG_TYPE_EXPRESSION : constants.ARG_TYPE_VAR
20
+ rule := desc.canBackendUseExpressions() ? "R" : "{R}"
21
+
18
22
  return runcmd.builder(wd).
19
23
  ref("r-run-environment", rPackage).
20
- substitutionRule("{R}", "r-run-environment").
21
- addToPath(path.join("{R}", rDescriptor.binDir), true).
22
- envVar("R_HOME_DIR", "{R}").
23
- envVar("RHOME", "{R}").
24
- envVar("RENV_PATHS_ROOT", path.join("{R}", "renv-root"))
24
+ substitutionRule(rule, "r-run-environment").
25
+ addToPath(t, path.join("{R}", rDescriptor.binDir)).
26
+ envTyped("R_HOME_DIR", t, "{R}").
27
+ envTyped("RHOME", t, "{R}").
28
+ envTyped("RENV_PATHS_ROOT", t, path.join("{R}", "renv-root"))
25
29
  }
26
30
 
27
31
  export ll.toStrict({
@@ -8,9 +8,12 @@ smart := import("@platforma-sdk/workflow-tengo:smart")
8
8
  render := import("@platforma-sdk/workflow-tengo:render")
9
9
  pkg := import("@platforma-sdk/workflow-tengo:exec.package")
10
10
  internal := import("@platforma-sdk/workflow-tengo:exec.R.internal")
11
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
11
12
 
12
13
  _OUTPUT_RUN_ENV := "runEnv"
13
14
 
15
+ createRenvTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:exec.R.create-renv")
16
+
14
17
  rVenvBuilder := func() {
15
18
  self := undefined
16
19
 
@@ -43,7 +46,7 @@ return self
43
46
  },
44
47
 
45
48
  runEnvDescriptor: func(descriptor) {
46
- validation.assertJsonSchema(descriptor, pkg.runEnvDescriptorScheme, "exec.R.runEnvDescriptor: <descriptor> must be run environment specification")
49
+ validation.assertJsonSchema(descriptor, desc.runEnvScheme, "exec.R.runEnvDescriptor: <descriptor> must be run environment specification")
47
50
  ll.assert(descriptor.type == "R", "exec.R.runEnvDescriptor: not a 'R' run environment: %q", descriptor.type)
48
51
 
49
52
  rDescriptor = ll.fromStrict(descriptor)
@@ -149,7 +152,7 @@ R: rPkg
149
152
 
150
153
  validation.assertJsonSchema(rVenvInputs, internal.rVenvInputSchema, "incomplete R runenv configuration")
151
154
 
152
- tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.R.create-renv"), rVenvInputs)
155
+ tpl := render.create(createRenvTpl, rVenvInputs)
153
156
 
154
157
  self := undefined
155
158
  self = ll.toStrict(oop.inherit(tpl, {
@@ -0,0 +1,11 @@
1
+ ARG_TYPE_STRING := "string"
2
+ ARG_TYPE_EXPRESSION := "expressionRef"
3
+ ARG_TYPE_VAR := "variableRef" // TODO: deprecated, remove after 15 Mar 2025
4
+ ARG_TYPES := [ARG_TYPE_STRING, ARG_TYPE_EXPRESSION, ARG_TYPE_VAR]
5
+
6
+ export {
7
+ ARG_TYPE_STRING: ARG_TYPE_STRING,
8
+ ARG_TYPE_EXPRESSION: ARG_TYPE_EXPRESSION,
9
+ ARG_TYPE_VAR: ARG_TYPE_VAR,
10
+ ARG_TYPES: ARG_TYPES
11
+ }
@@ -0,0 +1,54 @@
1
+
2
+
3
+
4
+
5
+ ll := import("@platforma-sdk/workflow-tengo:ll")
6
+
7
+ runEnvScheme := {
8
+ registry: "string",
9
+ package: "string",
10
+ type: "string",
11
+ binDir: "string"
12
+ }
13
+
14
+ binaryScheme := {
15
+ registry: "string",
16
+ package: "string",
17
+ cmd: ["string"],
18
+ "runEnv,?": runEnvScheme
19
+ }
20
+
21
+ assetScheme := {
22
+ registry: "string",
23
+ package: "string",
24
+ url: "string"
25
+ }
26
+
27
+ localScheme := {
28
+ hash: "string",
29
+ path: "string",
30
+ cmd: ["string"],
31
+ runEnv: runEnvScheme
32
+ }
33
+
34
+ scheme := {
35
+ "isDev,?": "bool",
36
+ "schemaVersion,?": "number",
37
+ "binary,?": binaryScheme,
38
+ "asset,?": assetScheme,
39
+ "local,?": localScheme
40
+ }
41
+
42
+
43
+ canBackendUseExpressions := func() {
44
+ return ll.apiVersion() >= 2
45
+ }
46
+
47
+ export {
48
+ runEnvScheme: runEnvScheme,
49
+ binaryScheme: binaryScheme,
50
+ assetScheme: assetScheme,
51
+ localScheme: localScheme,
52
+ scheme: scheme,
53
+ canBackendUseExpressions: canBackendUseExpressions
54
+ }
@@ -16,29 +16,59 @@ pkg := import("@platforma-sdk/workflow-tengo:exec.package")
16
16
  runcmd := import("@platforma-sdk/workflow-tengo:exec.runcmd")
17
17
  python := import("@platforma-sdk/workflow-tengo:exec.python")
18
18
  R := import("@platforma-sdk/workflow-tengo:exec.R")
19
+ constants := import("@platforma-sdk/workflow-tengo:exec.constants")
20
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
19
21
  validation := import("@platforma-sdk/workflow-tengo:validation")
20
22
 
21
23
 
22
- _ARG_VAR_PKG := "{pkg}" // abs path to software package
23
- _ARG_VAR_JAVA := "{java}" // abs path to 'java' run environment
24
- _ARG_VAR_PYTHON := "{python}" // abs path to 'python' run environment
25
- _ARG_VAR_R := "{R}" // abs path to 'R' run environment runtime
26
- _ARG_VAR_R_VENV := "{rVenv}" // abs path to 'R' portable virtual environment
27
- _ARG_VAR_MNZ := "{monetization}" // monetization env value
24
+ _ARG_VAR_PKG := "pkg" // abs path to software package
25
+ _ARG_VAR_JAVA := "java" // abs path to 'java' run environment
26
+ _ARG_VAR_PYTHON := "python" // abs path to 'python' run environment
27
+ _ARG_VAR_R := "R" // abs path to 'R' run environment runtime
28
+ _ARG_VAR_R_VENV := "rVenv" // abs path to 'R' portable virtual environment
29
+ _ARG_VAR_MNZ := "monetization" // monetization env value
30
+
31
+
32
+ _expr := func(varName) {
33
+ return "{" + varName + "}"
34
+ }
28
35
 
29
36
 
30
37
 
31
38
 
32
39
 
33
40
 
34
- _newArg := func(hasVariables, value) {
41
+
42
+
43
+ _newArg := func(isString, value) {
44
+ if isString {
45
+ return ll.toStrict({
46
+ type: constants.ARG_TYPE_STRING,
47
+ value: value
48
+ })
49
+ }
50
+ if desc.canBackendUseExpressions() {
51
+ return ll.toStrict({
52
+ type: constants.ARG_TYPE_EXPRESSION,
53
+ value: value
54
+ })
55
+ }
35
56
  return ll.toStrict({
36
- hasVars: hasVariables,
57
+ type: constants.ARG_TYPE_VAR,
37
58
  value: value
38
59
  })
39
60
  }
40
61
 
41
62
  _newRefVar := func(varName, refName, reference) {
63
+
64
+ if !desc.canBackendUseExpressions() {
65
+ return ll.toStrict({
66
+ varName: "{" + varName + "}",
67
+ refName: refName,
68
+ reference: reference
69
+ })
70
+ }
71
+
42
72
  return ll.toStrict({
43
73
  varName: varName,
44
74
  refName: refName,
@@ -58,7 +88,7 @@ _directCallOptions := func(runOptions) {
58
88
  return ll.toStrict({
59
89
  variables: [],
60
90
  customPaths: [],
61
- cmd: _newArg(false, runOptions.cmd),
91
+ cmd: _newArg(true, runOptions.cmd),
62
92
  args: [],
63
93
  envs: {}
64
94
  })
@@ -72,7 +102,7 @@ return ll.toStrict({
72
102
  runEnvType: "java",
73
103
 
74
104
  variables: [ javaRefVar ],
75
- customPaths: [ _newArg(true, path.join(_ARG_VAR_JAVA, descriptor.runEnv.binDir)) ],
105
+ customPaths: [ _newArg(false, path.join(_expr(_ARG_VAR_JAVA), descriptor.runEnv.binDir)) ],
76
106
  envs: {}
77
107
  })
78
108
  }
@@ -92,7 +122,7 @@ cacheDays(7).
92
122
  build().
93
123
  venv()
94
124
 
95
- venvRoot := path.join(_ARG_VAR_PYTHON, "venv")
125
+ venvRoot := path.join(_expr(_ARG_VAR_PYTHON), "venv")
96
126
  venvRefKey := softName + "/venv"
97
127
 
98
128
  pythonRefVar := _newRefVar(_ARG_VAR_PYTHON, venvRefKey, venv)
@@ -101,9 +131,9 @@ return ll.toStrict({
101
131
  runEnvType: "python",
102
132
 
103
133
  variables: [ pythonRefVar ],
104
- customPaths: [ _newArg(true, path.join(venvRoot, "bin")) ],
134
+ customPaths: [ _newArg(false, path.join(venvRoot, "bin")) ],
105
135
  envs: {
106
- "VIRTUAL_ENV": _newArg(true, venvRoot)
136
+ "VIRTUAL_ENV": _newArg(false, venvRoot)
107
137
  }
108
138
  })
109
139
  }
@@ -126,7 +156,7 @@ build()
126
156
  rEnv := rRuntime.venv()
127
157
  rPackage := rRuntime.R()
128
158
 
129
- rBinDir := path.join(_ARG_VAR_R, descriptor.runEnv.binDir)
159
+ rBinDir := path.join(_expr(_ARG_VAR_R), descriptor.runEnv.binDir)
130
160
 
131
161
  rRefKey := softName + "/R-runtime"
132
162
  rRefVar := _newRefVar(_ARG_VAR_R, rRefKey, rPackage)
@@ -138,15 +168,15 @@ return ll.toStrict({
138
168
  runEnvType: "R",
139
169
 
140
170
  variables: [ rRefVar, rEnvRefVar ],
141
- customPaths: [ _newArg(true, rBinDir) ],
171
+ customPaths: [ _newArg(false, rBinDir) ],
142
172
  envs: {
143
- "R_HOME_DIR": _newArg(true, _ARG_VAR_R),
144
- "RHOME": _newArg(true, _ARG_VAR_R),
145
- "RENV_PATHS_ROOT": _newArg(true, path.join(_ARG_VAR_R, "renv-root")),
146
- "RENV_PATHS_RENV": _newArg(true, path.join(_ARG_VAR_R_VENV, "renv")),
147
- "RENV_PATHS_LOCKFILE": _newArg(true, path.join(_ARG_VAR_PKG, descriptor.dependencies.lockFile)),
148
- "RENV_CONFIG_AUTO_SNAPSHOT": _newArg(false, "FALSE"),
149
- "RENV_CONFIG_SYNCHRONIZED_CHECK": _newArg(false, "FALSE")
173
+ "R_HOME_DIR": _newArg(false, _expr(_ARG_VAR_R)),
174
+ "RHOME": _newArg(false, _expr(_ARG_VAR_R)),
175
+ "RENV_PATHS_ROOT": _newArg(false, path.join(_expr(_ARG_VAR_R), "renv-root")),
176
+ "RENV_PATHS_RENV": _newArg(false, path.join(_expr(_ARG_VAR_R_VENV), "renv")),
177
+ "RENV_PATHS_LOCKFILE": _newArg(false, path.join(_expr(_ARG_VAR_PKG), descriptor.dependencies.lockFile)),
178
+ "RENV_CONFIG_AUTO_SNAPSHOT": _newArg(true, "FALSE"),
179
+ "RENV_CONFIG_SYNCHRONIZED_CHECK": _newArg(true, "FALSE")
150
180
  }
151
181
  })
152
182
  }
@@ -194,12 +224,14 @@ envs[n] = v
194
224
  }
195
225
  }
196
226
 
197
- ll.assert(len(descriptor.cmd) != 0, "cannot render final command for software: empty 'cmd' in software descritor")
227
+ ll.assert(
228
+ len(descriptor.cmd) != 0,
229
+ "cannot render final command for software: empty 'cmd' and 'command' in software descriptor")
198
230
 
199
- cmd := _newArg(true, descriptor.cmd[0])
231
+ cmd := _newArg(false, descriptor.cmd[0])
200
232
 
201
233
  for arg in splice(descriptor.cmd, 1) {
202
- args = append(args, _newArg(true, arg))
234
+ args = append(args, _newArg(false, arg))
203
235
  }
204
236
 
205
237
  return ll.toStrict({
@@ -246,7 +278,7 @@ ll.assert(is_string(softwareName),
246
278
  "exec.internal.swToRunCmdOptions: software name must be a string, got %v", softwareName)
247
279
  ll.assert(is_string(softwareVersion),
248
280
  "exec.internal.swToRunCmdOptions: software version must be a string, got %v", softwareVersion)
249
- validation.assertJsonSchema(softwareDescriptor, pkg.descriptorScheme,
281
+ validation.assertJsonSchema(softwareDescriptor, desc.scheme,
250
282
  "exec.internal.swToRunCmdOptions: descriptor does not fit schema")
251
283
 
252
284
  result := undefined
@@ -276,11 +308,13 @@ binaryRunOptions := func(runOptions, mnzEnvs) {
276
308
  validation.assertJsonSchema(mnzEnvs, {"any": validation.reference})
277
309
 
278
310
  runCmdOpts := undefined
311
+ onlyStrings := false
279
312
  if (is_undefined(ll.fromStrict(runOptions).software)) {
280
313
 
281
314
 
282
315
 
283
316
  runCmdOpts = _directCallOptions(runOptions)
317
+ onlyStrings = true
284
318
  } else {
285
319
  software := runOptions.software
286
320
  descriptor := software.descriptor
@@ -290,16 +324,16 @@ runCmdOpts = swToRunCmdOptions(software.name, software.version, descriptor)
290
324
 
291
325
 
292
326
  for arg in runOptions.args {
293
- runCmdOpts.args = append(runCmdOpts.args, _newArg(false, arg))
327
+ runCmdOpts.args = append(runCmdOpts.args, _newArg(onlyStrings, arg))
294
328
  }
295
329
  for name, val in runOptions.envs {
296
- runCmdOpts.envs[name] = _newArg(false, val)
330
+ runCmdOpts.envs[name] = _newArg(onlyStrings, val)
297
331
  }
298
332
 
299
333
  for name, val in mnzEnvs { // can be empty
300
334
 
301
335
 
302
- runCmdOpts.envs[name] = _newArg(true, _ARG_VAR_MNZ)
336
+ runCmdOpts.envs[name] = _newArg(false, _expr(_ARG_VAR_MNZ))
303
337
 
304
338
  runCmdOpts.variables = append(runCmdOpts.variables,
305
339
  _newRefVar(_ARG_VAR_MNZ, "monetization", val))
@@ -320,16 +354,12 @@ runBuilder.substitutionRule(varInfo.varName, varInfo.refName)
320
354
 
321
355
 
322
356
  for p in opts.customPaths {
323
- runBuilder.addToPath(p.value, p.hasVars)
357
+ runBuilder.addToPath(p.type, p.value)
324
358
  }
325
359
 
326
360
 
327
361
  for name, value in opts.envs {
328
- if value.hasVars {
329
- runBuilder.envVar(name, value.value)
330
- } else {
331
- runBuilder.env(name, value.value)
332
- }
362
+ runBuilder.envTyped(name, value.type, value.value)
333
363
  }
334
364
 
335
365
  return runBuilder
@@ -15,6 +15,7 @@ enum := import("enum")
15
15
  oop := import("@platforma-sdk/workflow-tengo:oop")
16
16
  validation := import("@platforma-sdk/workflow-tengo:validation")
17
17
  constants := import("@platforma-sdk/workflow-tengo:constants")
18
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
18
19
  monetization := import("@platforma-sdk/workflow-tengo:exec.monetization")
19
20
 
20
21
  _HEAVY_QUEUE := "heavy"
@@ -779,5 +780,6 @@ return self
779
780
  }
780
781
 
781
782
  export ll.toStrict({
782
- builder: builder
783
+ builder: builder,
784
+ canBackendUseExpressions: desc.canBackendUseExpressions
783
785
  })
@@ -9,6 +9,8 @@ text := import("text")
9
9
  runcmd := import("@platforma-sdk/workflow-tengo:exec.runcmd")
10
10
  workdir := import("@platforma-sdk/workflow-tengo:workdir")
11
11
  render := import("@platforma-sdk/workflow-tengo:render")
12
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
13
+ constants := import("@platforma-sdk/workflow-tengo:exec.constants")
12
14
 
13
15
  _JWT_TOKEN_RESULT_ENV := "PLATFORMA_MNZ_JWT"
14
16
 
@@ -36,7 +38,15 @@ schema := {
36
38
  "fileParams": {"any": fileParamsSchema}
37
39
  }
38
40
 
39
- _assertIsReady := func(mnz) {
41
+
42
+
43
+ _validateParams := func(params) {
44
+ ll.assert(ll.isMap(params), "monetization.validateParams(): mnz params must be a map")
45
+ ll.assert(is_string(params.arg), "monetization.validateParams(): 'arg' in {\"mnz\": {...}} param must be a string")
46
+ ll.assert(is_array(params.collect) && len(params.collect) > 0, "monetization.validateParams(): 'collect' in {\"mnz\": {...}} param must be non-empty an array")
47
+ }
48
+
49
+ _validateIsReady := func(mnz) {
40
50
  validation.assertJsonSchema(mnz, schema,
41
51
  "monetization.assertIsReady(): monetization does not fit schema")
42
52
  ll.assert(len(mnz.productName) > 0,
@@ -60,7 +70,7 @@ mnz.productName = productName
60
70
 
61
71
  shouldRun := func(mnz) {
62
72
  if mnz.enabled {
63
- _assertIsReady(mnz)
73
+ _validateIsReady(mnz)
64
74
  return true
65
75
  }
66
76
 
@@ -79,6 +89,8 @@ addFileParams := func(mnz, fileName, params) {
79
89
  validation.assertJsonSchema(mnz, schema,
80
90
  "monetization.addFileParams(): monetization object does not fit json schema")
81
91
 
92
+ _validateParams(params)
93
+
82
94
  validation.assertJsonSchema(params, fileParamsSchema,
83
95
  "monetization.addFileParams(): file params does not fit json schema")
84
96
 
@@ -99,12 +111,15 @@ mnz.fileParams[fileName] = params
99
111
 
100
112
 
101
113
  run := func(mnz, wd, queue) {
102
- _assertIsReady(mnz)
114
+ _validateIsReady(mnz)
103
115
 
104
116
  mnzSw := assets.importSoftware("@platforma-open/milaboratories.software-small-binaries:mnz-client")
105
117
 
106
118
  builder := runcmd.builder(wd)
107
- builder.envVar("MI_LICENSE", "{secrets.MI_LICENSE}")
119
+
120
+ exprType := desc.canBackendUseExpressions() ? constants.ARG_TYPE_EXPRESSION : constants.ARG_TYPE_VAR
121
+
122
+ builder.envTyped("MI_LICENSE", exprType, "{secrets.MI_LICENSE}")
108
123
 
109
124
  opts := internal.swToRunCmdOptions(mnzSw.name, mnzSw.version, mnzSw.descriptor)
110
125
 
@@ -113,10 +128,10 @@ builder.ref(varInfo.refName, varInfo.reference)
113
128
  builder.substitutionRule(varInfo.varName, varInfo.refName)
114
129
  }
115
130
 
116
- builder.cmdVar(opts.cmd.value)
131
+ builder.cmdTyped(exprType, opts.cmd.value)
117
132
  for _, arg in opts.args {
118
133
 
119
- builder.argVar(arg)
134
+ builder.argTyped(exprType, arg)
120
135
  }
121
136
  builder.arg("-productName").arg(mnz.productName)
122
137
 
@@ -9,45 +9,12 @@ oop := import("@platforma-sdk/workflow-tengo:oop")
9
9
  sets := import("@platforma-sdk/workflow-tengo:sets")
10
10
  validation := import("@platforma-sdk/workflow-tengo:validation")
11
11
  json := import("json")
12
-
13
- runEnvDescriptorScheme := {
14
- registry: "string",
15
- package: "string",
16
- type: "string",
17
- binDir: "string"
18
- }
19
-
20
- binaryDescriptorScheme := {
21
- registry: "string",
22
- package: "string",
23
- cmd: ["string"],
24
- "runEnv,?": runEnvDescriptorScheme
25
- }
26
-
27
- assetDescriptorScheme := {
28
- registry: "string",
29
- package: "string",
30
- url: "string"
31
- }
32
-
33
- localDescriptorScheme := {
34
- hash: "string",
35
- path: "string",
36
- cmd: ["string"],
37
- runEnv: runEnvDescriptorScheme
38
- }
39
-
40
- descriptorScheme := {
41
- "isDev,?": "bool",
42
- "binary,?": binaryDescriptorScheme,
43
- "asset,?": assetDescriptorScheme,
44
- "local,?": localDescriptorScheme
45
- }
12
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
46
13
 
47
14
  softwareInfoScheme := {
48
15
  "name": "string",
49
16
  "version": "string",
50
- "descriptor": descriptorScheme
17
+ "descriptor": desc.scheme
51
18
  }
52
19
 
53
20
  META_KEY_DESCRIPTOR := "ctl/runner/package/descriptor"
@@ -291,11 +258,6 @@ progress: assets.progress
291
258
 
292
259
  export ll.toStrict({
293
260
  softwareInfoScheme : softwareInfoScheme,
294
- descriptorScheme : descriptorScheme,
295
- assetDescriptorScheme : assetDescriptorScheme,
296
- binaryDescriptorScheme : binaryDescriptorScheme,
297
- localDescriptorScheme : localDescriptorScheme,
298
- runEnvDescriptorScheme : runEnvDescriptorScheme,
299
261
 
300
262
  META_KEY_DESCRIPTOR : META_KEY_DESCRIPTOR,
301
263
 
@@ -1,13 +1,13 @@
1
1
  ll := import("@platforma-sdk/workflow-tengo:ll")
2
2
  validation := import("@platforma-sdk/workflow-tengo:validation")
3
- pkg := import("@platforma-sdk/workflow-tengo:exec.package")
3
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
4
4
 
5
5
  pythonVenvInputSchema := {
6
6
  toolset: "string",
7
7
  dependencies: {"any": validation.reference},
8
8
 
9
9
 
10
- pythonDescriptor: pkg.runEnvDescriptorScheme,
10
+ pythonDescriptor: desc.runEnvScheme,
11
11
  python: validation.reference
12
12
  }
13
13
 
@@ -9,9 +9,12 @@ render := import("@platforma-sdk/workflow-tengo:render")
9
9
  pkg := import("@platforma-sdk/workflow-tengo:exec.package")
10
10
  internal := import("@platforma-sdk/workflow-tengo:exec.python.internal")
11
11
  runenv := import("@platforma-sdk/workflow-tengo:exec.runenv")
12
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
12
13
 
13
14
  _OUTPUT_RUN_ENV := "runEnv"
14
15
 
16
+ createVenvTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:exec.python.create-venv")
17
+
15
18
  pythonVenvBuilder := func() {
16
19
  self := undefined
17
20
 
@@ -32,7 +35,7 @@ return self
32
35
  },
33
36
 
34
37
  runEnvDescriptor: func(descriptor) {
35
- validation.assertJsonSchema(descriptor, pkg.runEnvDescriptorScheme, "exec.python.runEnvDescriptor: <descriptor> must be run environment specification")
38
+ validation.assertJsonSchema(descriptor, desc.runEnvScheme, "exec.python.runEnvDescriptor: <descriptor> must be run environment specification")
36
39
  ll.assert(descriptor.type == "python", "exec.python.runEnvDescriptor: not a 'python' run environment: %q", descriptor.type)
37
40
 
38
41
  pythonDescriptor = ll.fromStrict(descriptor)
@@ -139,7 +142,7 @@ python: pythonPkg
139
142
 
140
143
  validation.assertJsonSchema(pyVenvInputs, internal.pythonVenvInputSchema, "incomplete python runenv configuration")
141
144
 
142
- tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.python.create-venv"), pyVenvInputs)
145
+ tpl := render.create(createVenvTpl, pyVenvInputs)
143
146
 
144
147
  self := undefined
145
148
  self = ll.toStrict(oop.inherit(tpl, {
@@ -7,6 +7,9 @@ maps := import("@platforma-sdk/workflow-tengo:maps")
7
7
  oop := import("@platforma-sdk/workflow-tengo:oop")
8
8
  smart := import("@platforma-sdk/workflow-tengo:smart")
9
9
  json := import("json")
10
+ constants := import("@platforma-sdk/workflow-tengo:exec.constants")
11
+ slices := import("@platforma-sdk/workflow-tengo:slices")
12
+ desc := import("@platforma-sdk/workflow-tengo:exec.descriptor")
10
13
 
11
14
  _RTYPE_RUN_COMMAND := { Name: "RunCommand/executor", Version: "1" }
12
15
  _RTYPE_RUN_COMMAND_CMD := { Name: "RunCommandCmd", Version: "1" }
@@ -21,7 +24,7 @@ _RTYPE_RUN_COMMAND_REFS := { Name: "RunCommandRefs", Version: "1" }
21
24
 
22
25
  _createSimpleArg := func(argument) {
23
26
  return {
24
- type: "string",
27
+ type: constants.ARG_TYPE_STRING,
25
28
  value: argument
26
29
  }
27
30
  }
@@ -30,9 +33,24 @@ value: argument
30
33
 
31
34
 
32
35
 
36
+
33
37
  _createVariableArg := func(argTpl) {
34
38
  return {
35
- type: "variableRef",
39
+ type: constants.ARG_TYPE_VAR,
40
+ value: argTpl
41
+ }
42
+ }
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+ _createExpressionArg := func(argTpl) {
52
+ return {
53
+ type: constants.ARG_TYPE_EXPRESSION,
36
54
  value: argTpl
37
55
  }
38
56
  }
@@ -56,7 +74,8 @@ queue := ""
56
74
  refs := {}
57
75
 
58
76
  substRules := {}
59
- hasPatternArgs := false
77
+ hasPatternArgs := false // TODO: deprecated, remove after a month of expressionRefs in prod.
78
+ hasExpressionArgs := false
60
79
  customPaths := []
61
80
 
62
81
  stdout := "stdout.txt"
@@ -93,6 +112,35 @@ return self
93
112
 
94
113
 
95
114
 
115
+
116
+
117
+
118
+ cmdExpression: func(commandTpl) {
119
+ cmd = _createExpressionArg(commandTpl)
120
+ hasExpressionArgs = true
121
+ return self
122
+ },
123
+
124
+ cmdTyped: func(type, value) {
125
+ ll.assert(slices.hasElement(constants.ARG_TYPES, type),
126
+ "runcmd.builder().cmdTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
127
+
128
+ if type == constants.ARG_TYPE_STRING {
129
+ return self.cmd(value)
130
+ } else if type == constants.ARG_TYPE_EXPRESSION {
131
+ return self.cmdExpression(value)
132
+ } else if type == constants.ARG_TYPE_VAR {
133
+ return self.cmdVar(value)
134
+ }
135
+
136
+ ll.panic("runcmd.builder().cmdTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
137
+ },
138
+
139
+
140
+
141
+
142
+
143
+
96
144
  arg: func(arg) {
97
145
  args = append(args, _createSimpleArg(arg))
98
146
  return self
@@ -112,6 +160,41 @@ hasPatternArgs = true
112
160
  return self
113
161
  },
114
162
 
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+ argExpression: func(argTpl) {
172
+ args = append(args, _createExpressionArg(argTpl))
173
+ hasExpressionArgs = true
174
+ return self
175
+ },
176
+
177
+ argTyped: func(type, value) {
178
+ ll.assert(slices.hasElement(constants.ARG_TYPES, type),
179
+ "runcmd.builder().argTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
180
+
181
+ if type == constants.ARG_TYPE_STRING {
182
+ return self.arg(value)
183
+ } else if type == constants.ARG_TYPE_EXPRESSION {
184
+ return self.argExpression(value)
185
+ } else if type == constants.ARG_TYPE_VAR {
186
+ return self.argVar(value)
187
+ }
188
+
189
+ ll.panic("runcmd.builder().argTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
190
+ },
191
+
192
+
193
+
194
+
195
+
196
+
197
+
115
198
  ref: func(refKey, ref) {
116
199
  ll.assert(smart.isReference(ref),
117
200
  "runcmd.builder().ref() must be a reference (valid field or resource)")
@@ -153,13 +236,50 @@ return self
153
236
 
154
237
 
155
238
 
156
- addToPath: func(value, hasVars) {
157
- if hasVars {
239
+
240
+ envExpression: func(name, valueTpl) {
241
+ envs[name] = _createExpressionArg(valueTpl)
242
+ hasExpressionArgs = true
243
+ return self
244
+ },
245
+
246
+ envTyped: func(name, type, value) {
247
+ ll.assert(slices.hasElement(constants.ARG_TYPES, type),
248
+ "runcmd.builder().envTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
249
+
250
+ if type == constants.ARG_TYPE_STRING {
251
+ return self.env(name, value)
252
+ } else if type == constants.ARG_TYPE_EXPRESSION {
253
+ return self.envExpression(name, value)
254
+ } else if type == constants.ARG_TYPE_VAR {
255
+ return self.envVar(name, value)
256
+ }
257
+
258
+ ll.panic("runcmd.builder().envTyped: unknown type %s, expect: %v", type, constants.ARG_TYPES)
259
+ },
260
+
261
+
262
+
263
+
264
+
265
+
266
+
267
+ addToPath: func(type, value) {
268
+ ll.assert(slices.hasElement(constants.ARG_TYPES, type),
269
+ "runcmd.builder().addToPath: unknown type %s, expect: %v", type, constants.ARG_TYPES)
270
+
271
+ if type == constants.ARG_TYPE_STRING {
272
+ customPaths = append(customPaths, _createSimpleArg(value))
273
+ } else if type == constants.ARG_TYPE_EXPRESSION {
274
+ customPaths = append(customPaths, _createExpressionArg(value))
275
+ hasExpressionArgs = true
276
+ } else if type == constants.ARG_TYPE_VAR {
158
277
  customPaths = append(customPaths, _createVariableArg(value))
159
278
  hasPatternArgs = true
160
279
  } else {
161
- customPaths = append(customPaths, _createSimpleArg(value))
280
+ ll.panic("runcmd.builder().addToPath: unknown type %s, expect: %v", type, constants.ARG_TYPES)
162
281
  }
282
+
163
283
  return self
164
284
  },
165
285
 
@@ -235,8 +355,12 @@ return self
235
355
  build: func() {
236
356
 
237
357
 
238
- ll.assert(!hasPatternArgs || len(substRules) != 0,
239
- "found pattern argument, but no substitution rules were set")
358
+ ll.assert(!(hasPatternArgs || hasExpressionArgs) || len(substRules) != 0,
359
+ "found pattern argument, but no substitution rules were set: hasPatternArgs: %v, substRules: %v, cmd: %v, args: %v, envs: %v",
360
+ hasPatternArgs, substRules, cmd, args, envs)
361
+ ll.assert(!hasExpressionArgs || desc.canBackendUseExpressions(),
362
+ "runcmd.builder().build: expression arguments must be enabled only if platforma backend supports expressions, found: %v",
363
+ hasExpressionArgs)
240
364
 
241
365
  refsRes := smart.createMapResourceWithType(_RTYPE_RUN_COMMAND_REFS, refs)
242
366
  self.getField("refs").set(refsRes)
@@ -8,13 +8,6 @@ text := import("text")
8
8
 
9
9
 
10
10
 
11
- apiVersion := func() {
12
- return 0 // stub code. Real API checker will appear here.
13
- }
14
-
15
-
16
-
17
-
18
11
  print := func(txt, ...args) {
19
12
  plapi.print(txt, args...)
20
13
  }
@@ -86,35 +79,6 @@ return plapi.strictToMap(r)
86
79
 
87
80
 
88
81
 
89
-
90
-
91
- methodExists := func(module, methodName) {
92
- if isStrict(module) {
93
- if !is_callable(plapi.mapHasKey) {
94
- module = fromStrict(module)
95
-
96
- } else {
97
- if !plapi.mapHasKey(module, methodName) {
98
- return false
99
- }
100
- }
101
- }
102
-
103
- method := module[methodName]
104
-
105
- if is_undefined(method) {
106
- return false
107
- }
108
-
109
- return is_callable(method)
110
- }
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
82
  ensureNonStrict := func(r) {
119
83
  if isStrict(r) {
120
84
  return fromStrict(r)
@@ -164,6 +128,46 @@ return plapi.mapToStrict(v)
164
128
 
165
129
 
166
130
 
131
+
132
+
133
+
134
+
135
+
136
+ methodExists := func(module, methodName) {
137
+ if isStrict(module) {
138
+ if !is_callable(plapi.mapHasKey) {
139
+ module = fromStrict(module)
140
+
141
+ } else {
142
+ if !plapi.mapHasKey(module, methodName) {
143
+ return false
144
+ }
145
+ }
146
+ }
147
+
148
+ method := module[methodName]
149
+
150
+ if is_undefined(method) {
151
+ return false
152
+ }
153
+
154
+ return true
155
+ }
156
+
157
+
158
+
159
+
160
+ apiVersion := func() {
161
+ if !methodExists(plapi, "apiVersion") {
162
+ return 0 // before we introduced apiVersion
163
+ }
164
+
165
+ return plapi.apiVersion
166
+ }
167
+
168
+
169
+
170
+
167
171
  fieldId := func(resourceId, fieldName) {
168
172
  return plapi.newFieldID(resourceId, fieldName)
169
173
  }
@@ -19,6 +19,7 @@ return slices.sortByFn(res, func(elem) { return elem })
19
19
 
20
20
 
21
21
 
22
+
22
23
  containsKey := func(map, key) {
23
24
  for k, _ in map {
24
25
  if key == k {
@@ -96,14 +96,14 @@ createBlobMapResource := undefined
96
96
 
97
97
 
98
98
  isResource := func(f) {
99
- return ll.isStrict(f) && ll.fromStrict(f)["_type"] == "resource"
99
+ return ll.isStrict(f) && maps.containsKey(f, "_type") && f["_type"] == "resource"
100
100
  }
101
101
 
102
102
 
103
103
 
104
104
 
105
105
  isField := func(f) {
106
- return ll.isStrict(f) && ll.fromStrict(f)["_type"] == "field"
106
+ return ll.isStrict(f) && maps.containsKey(f, "_type") && f["_type"] == "field"
107
107
  }
108
108
 
109
109
 
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/workflow-tengo",
3
- "version": "2.8.8",
3
+ "version": "2.9.0",
4
4
  "description": "Tengo SDK library",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",