@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.
- package/README.md +6 -0
- package/dist/tengo/lib/assets.lib.tengo +64 -0
- package/dist/tengo/lib/constants.lib.tengo +75 -0
- package/dist/tengo/lib/exec.internal.lib.tengo +211 -0
- package/dist/tengo/lib/exec.lib.tengo +516 -0
- package/dist/tengo/lib/exec.package.lib.tengo +296 -0
- package/dist/tengo/lib/exec.runcmd.lib.tengo +275 -0
- package/dist/tengo/lib/exec.runenv.lib.tengo +221 -0
- package/dist/tengo/lib/exec.stream.lib.tengo +64 -0
- package/dist/tengo/lib/file.lib.tengo +112 -0
- package/dist/tengo/lib/ll.lib.tengo +233 -0
- package/dist/tengo/lib/maps.lib.tengo +102 -0
- package/dist/tengo/lib/objects.lib.tengo +22 -0
- package/dist/tengo/lib/oop.lib.tengo +29 -0
- package/dist/tengo/lib/path.lib.tengo +165 -0
- package/dist/tengo/lib/pframes.constants.lib.tengo +53 -0
- package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +47 -0
- package/dist/tengo/lib/pframes.lib.tengo +84 -0
- package/dist/tengo/lib/pframes.ll.lib.tengo +86 -0
- package/dist/tengo/lib/pframes.util.lib.tengo +244 -0
- package/dist/tengo/lib/pframes.xsv.lib.tengo +178 -0
- package/dist/tengo/lib/render.lib.tengo +100 -0
- package/dist/tengo/lib/sets.lib.tengo +93 -0
- package/dist/tengo/lib/slices.lib.tengo +202 -0
- package/dist/tengo/lib/smart.lib.tengo +1005 -0
- package/dist/tengo/lib/tpl.lib.tengo +535 -0
- package/dist/tengo/lib/tpl.state-await.lib.tengo +255 -0
- package/dist/tengo/lib/tpl.util.lib.tengo +19 -0
- package/dist/tengo/lib/validation.lib.tengo +428 -0
- package/dist/tengo/lib/workdir.lib.tengo +300 -0
- package/dist/tengo/lib/workdir.proc.lib.tengo +158 -0
- package/dist/tengo/lib/workdir.save.lib.tengo +158 -0
- package/dist/tengo/lib/workflow.bobject.lib.tengo +51 -0
- package/dist/tengo/lib/workflow.bquery.lib.tengo +208 -0
- package/dist/tengo/lib/workflow.constants.lib.tengo +8 -0
- package/dist/tengo/lib/workflow.context.lib.tengo +56 -0
- package/dist/tengo/lib/workflow.lib.tengo +298 -0
- package/dist/tengo/tpl/exec.create-python-venv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.import-xsv-map.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
- package/index.d.ts +4 -0
- package/index.js +13 -0
- package/package.json +25 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
3
|
+
constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
4
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
5
|
+
json := import("json")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_CONTEXT_FIELD_NAME := "ctx"
|
|
9
|
+
|
|
10
|
+
// options scheme for query
|
|
11
|
+
_OPTIONS_SCHEME := {
|
|
12
|
+
"spec,omitempty": `bool`,
|
|
13
|
+
"data,omitempty": `bool`,
|
|
14
|
+
"single,omitempty": `bool`,
|
|
15
|
+
"first,omitempty": `bool`,
|
|
16
|
+
"errIfMissing,omitempty": `bool`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// default query options
|
|
20
|
+
_DEFAULT_OPTIONS := {
|
|
21
|
+
/** Return specs in the results */
|
|
22
|
+
spec: true,
|
|
23
|
+
/** Return data in the results */
|
|
24
|
+
data: true,
|
|
25
|
+
/** Asserts that the resulting list has one element and returns it */
|
|
26
|
+
single: false,
|
|
27
|
+
/** Returns first available result of the query */
|
|
28
|
+
first: false,
|
|
29
|
+
/** Throw error if no results found */
|
|
30
|
+
errIfMissing: false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Query results pool.
|
|
35
|
+
*
|
|
36
|
+
* @param spec: query spec
|
|
37
|
+
* @param ctx: results pool (context) to query
|
|
38
|
+
* @param options: an options map
|
|
39
|
+
* @return result: a list of {ref: spec: data:} objects (data will be absent if not requested)
|
|
40
|
+
*/
|
|
41
|
+
create := func(spec, ctx, ...options) {
|
|
42
|
+
|
|
43
|
+
// @TODO validate spec
|
|
44
|
+
|
|
45
|
+
ops := copy(_DEFAULT_OPTIONS)
|
|
46
|
+
if len(options) > 0 {
|
|
47
|
+
ll.assert(len(options) == 1, "expected map, got array: ", options)
|
|
48
|
+
|
|
49
|
+
// @TODO validate options
|
|
50
|
+
|
|
51
|
+
// override defaults
|
|
52
|
+
for k, v in options[0]{
|
|
53
|
+
ops[k] = v
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
query := json.encode({
|
|
58
|
+
query: spec,
|
|
59
|
+
setErrorIfMissing: ops.errIfMissing
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
builder := undefined
|
|
64
|
+
if ops.first {
|
|
65
|
+
builder = smart.ephemeralBuilder(constants.RTYPE_BRESOLVE_FIRST, query)
|
|
66
|
+
} else {
|
|
67
|
+
// return all query results
|
|
68
|
+
builder = smart.ephemeralBuilder(constants.RTYPE_BRESOLVE_CHOICE, query)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
builder.createInputField(_CONTEXT_FIELD_NAME).set(ctx)
|
|
72
|
+
resolve := builder.lockInputsAndBuild()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// create a special type to store query results
|
|
76
|
+
|
|
77
|
+
rb := smart.structBuilder(constants.RTYPE_QUERY_RESULT)
|
|
78
|
+
|
|
79
|
+
// save options
|
|
80
|
+
rb.createInputField("ops").setJson(ops)
|
|
81
|
+
|
|
82
|
+
if ops.spec {
|
|
83
|
+
rb.createInputField("spec").set(resolve.getFutureOutputField("spec"))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// pass data only if needed, otherwise we are not waiting for data to complete
|
|
87
|
+
if ops.data {
|
|
88
|
+
rb.createInputField("data").set(resolve.getFutureOutputField("data"))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// the data structure differs in this case; the single ref, data and spec are stored
|
|
92
|
+
// directly as result fields
|
|
93
|
+
if ops.first {
|
|
94
|
+
rb.createInputField("ref").set(resolve.getFutureOutputField("address"))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return rb.lockAndBuild()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Inputs preprocessor used to convert query result into array of {ref: spec: data:} objects
|
|
102
|
+
*/
|
|
103
|
+
resultUnmarshaller := func() {
|
|
104
|
+
return {
|
|
105
|
+
canParse: func(r) {
|
|
106
|
+
return smart.isResource(r) && r.info().Type.Name == constants.RTYPE_QUERY_RESULT.Name
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
parse: func(resource, parser) {
|
|
110
|
+
|
|
111
|
+
ops := resource.get("ops").getDataAsJson()
|
|
112
|
+
|
|
113
|
+
if ops.first {
|
|
114
|
+
// special case, single element
|
|
115
|
+
|
|
116
|
+
// is no result
|
|
117
|
+
isNR := func(r) {
|
|
118
|
+
return r.info().Type.Name == constants.RTYPE_BRESOLVE_NO_RESULT.Name
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if isNR(resource.get("ref")) {
|
|
122
|
+
return undefined
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
result := {
|
|
126
|
+
ref: resource.get("ref").getDataAsJson(),
|
|
127
|
+
spec: resource.get("spec").getDataAsJson()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// only if the data is there
|
|
131
|
+
if resource.hasInputField("data") {
|
|
132
|
+
|
|
133
|
+
// even if spec is present, the data may be still not available
|
|
134
|
+
if isNR(resource.get("data")) {
|
|
135
|
+
result["data"] = undefined
|
|
136
|
+
} else {
|
|
137
|
+
result["data"] = parser(resource.get("data"))
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result
|
|
142
|
+
} else {
|
|
143
|
+
// format list of results
|
|
144
|
+
|
|
145
|
+
spec := resource.get("spec").inputs()
|
|
146
|
+
data := undefined
|
|
147
|
+
if resource.hasInputField("data") {
|
|
148
|
+
data = resource.get("data").inputs()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
result := []
|
|
152
|
+
for ref, s in spec {
|
|
153
|
+
r := {
|
|
154
|
+
ref: json.decode(ref),
|
|
155
|
+
spec: s.getValueAsJson()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// only if the data is there
|
|
159
|
+
if !is_undefined(data) {
|
|
160
|
+
r["data"] = parser(data[ref].getValue())
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
result = append(result, r)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if ops.single {
|
|
167
|
+
ll.assert(len(result) == 1, "expected single element, got ", len(result))
|
|
168
|
+
|
|
169
|
+
result = result[0]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return result
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Query results pool to find spec & data for a given ref.
|
|
180
|
+
*
|
|
181
|
+
* @param ref: a ref object ({blockId: name:})
|
|
182
|
+
* @param ctx: results pool (context) to query
|
|
183
|
+
* @return result: a {ref: spec: data:} object
|
|
184
|
+
*/
|
|
185
|
+
resolve := func(ref, ctx, ...options) {
|
|
186
|
+
|
|
187
|
+
spec := {
|
|
188
|
+
type: "Direct",
|
|
189
|
+
block_id: ref.blockId, // @TODO use consistent naming in pl
|
|
190
|
+
output_name: ref.name // @TODO use consistent naming in pl
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
ops := {}
|
|
194
|
+
|
|
195
|
+
if len(options) > 0 {
|
|
196
|
+
ops = options[0]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
ops.first = true
|
|
200
|
+
|
|
201
|
+
return create(spec, ctx, ops)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export ll.toStrict({
|
|
205
|
+
create: create,
|
|
206
|
+
resolve: resolve,
|
|
207
|
+
resultUnmarshaller: resultUnmarshaller
|
|
208
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Library to work with context resources */
|
|
2
|
+
|
|
3
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
4
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
5
|
+
constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
6
|
+
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
7
|
+
|
|
8
|
+
_BLOCK_ID_FIELD := "id"
|
|
9
|
+
_PARENT_CTX_FIELD := "parent"
|
|
10
|
+
_EXPORTS_OUTPUT_PREFIX := "values/"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a new context builder
|
|
14
|
+
*
|
|
15
|
+
* @param block block (smart.Resource)
|
|
16
|
+
* @param parentContext parent context (smart.Resource)
|
|
17
|
+
*/
|
|
18
|
+
builder := func(block, parentContext) {
|
|
19
|
+
|
|
20
|
+
super := smart.ephemeralBuilder(constants.RTYPE_CONTEXT)
|
|
21
|
+
|
|
22
|
+
// set blockId associated with this context
|
|
23
|
+
super.createInputField(_BLOCK_ID_FIELD).setRefOrJson(block)
|
|
24
|
+
|
|
25
|
+
// set parent context
|
|
26
|
+
super.createInputField(_PARENT_CTX_FIELD).set(parentContext)
|
|
27
|
+
|
|
28
|
+
self := undefined
|
|
29
|
+
self = ll.toStrict(oop.inherit(super, {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Add export to the context
|
|
33
|
+
*
|
|
34
|
+
* @param name string name of the export field
|
|
35
|
+
* @param value resource/field value
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
add: func(name, value) {
|
|
39
|
+
field := super.createInputField(_EXPORTS_OUTPUT_PREFIX + name)
|
|
40
|
+
|
|
41
|
+
field.setRefOrJson(value)
|
|
42
|
+
|
|
43
|
+
return self
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
build: func() {
|
|
47
|
+
return super.lockAndBuild()
|
|
48
|
+
}
|
|
49
|
+
}))
|
|
50
|
+
|
|
51
|
+
return self
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export ll.toStrict({
|
|
55
|
+
builder: builder
|
|
56
|
+
})
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Library provides development kit for workflows
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
tx := import("tx")
|
|
6
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
7
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
8
|
+
text := import("text")
|
|
9
|
+
json := import("json")
|
|
10
|
+
|
|
11
|
+
constants := import("@platforma-sdk/workflow-tengo:workflow.constants")
|
|
12
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
13
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
14
|
+
maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
15
|
+
sets := import("@platforma-sdk/workflow-tengo:sets")
|
|
16
|
+
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
17
|
+
bobject := import("@platforma-sdk/workflow-tengo:workflow.bobject")
|
|
18
|
+
bquery := import("@platforma-sdk/workflow-tengo:workflow.bquery")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
// instance of this
|
|
22
|
+
self := import("@platforma-sdk/workflow-tengo:tpl")
|
|
23
|
+
|
|
24
|
+
// renderer's output field storing a map with the results
|
|
25
|
+
_RESULTS_FIELD_NAME := "result"
|
|
26
|
+
|
|
27
|
+
// renderer's inputs map field with the context resource
|
|
28
|
+
_INPUT_CONTEXT_FIELD_NAME := "context"
|
|
29
|
+
|
|
30
|
+
// renderer's output field with the context resource
|
|
31
|
+
_OUTPUT_CONTEXT_FIELD_NAME := "context"
|
|
32
|
+
|
|
33
|
+
// a field name prefix used in the renderer's inputs map fields
|
|
34
|
+
// that store prepared resources (aka requested in the 'prepare()' method)
|
|
35
|
+
_PREPARED_INPUTS_PREFIX := "prepared/"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// define outputs as we know them
|
|
39
|
+
// this is important to unlock 'prepare' functionality
|
|
40
|
+
// as workflow is an eph template
|
|
41
|
+
self.defineOutputs([_RESULTS_FIELD_NAME, _OUTPUT_CONTEXT_FIELD_NAME])
|
|
42
|
+
|
|
43
|
+
_isProduction := func() {
|
|
44
|
+
// using low level api to avoid unnecessary unmarshalling etc
|
|
45
|
+
return self.rawInputs().isProduction.getValueAsJson() == true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_isStaging := func() {
|
|
49
|
+
return !_isProduction()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// register standard inputs preprocessors
|
|
53
|
+
self.registerUnmarshaller(bquery.resultUnmarshaller())
|
|
54
|
+
|
|
55
|
+
_args := undefined
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Block arguments map
|
|
59
|
+
*/
|
|
60
|
+
args := func() {
|
|
61
|
+
if is_undefined(_args) {
|
|
62
|
+
// template inputs
|
|
63
|
+
inputs := self.inputs()
|
|
64
|
+
|
|
65
|
+
// original args from inputs
|
|
66
|
+
_args = inputs.args
|
|
67
|
+
if is_undefined(_args) || smart.isReference(_args) {
|
|
68
|
+
ll.panic("Unexpected args type: %v", _args)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// add all prepared 'extra' inputs to the args
|
|
72
|
+
for k, v in inputs {
|
|
73
|
+
// those extra inputs are prefixed
|
|
74
|
+
if text.has_prefix(k, _PREPARED_INPUTS_PREFIX) {
|
|
75
|
+
|
|
76
|
+
name := text.trim_prefix(k, _PREPARED_INPUTS_PREFIX)
|
|
77
|
+
|
|
78
|
+
ll.assert(is_undefined(_args[name]), "prepare name is already in use in inputs: ", name)
|
|
79
|
+
|
|
80
|
+
_args[name] = v
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return _args
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_blockId := undefined
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Id of this block
|
|
91
|
+
*/
|
|
92
|
+
blockId := func() {
|
|
93
|
+
if _blockId == undefined {
|
|
94
|
+
_blockId = self.inputs().blockId
|
|
95
|
+
ll.assert(!is_undefined(_blockId), "block id is not set in workflow inputs")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return _blockId
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
__parentContext := undefined
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Parent context
|
|
105
|
+
*/
|
|
106
|
+
_parentContext := func() {
|
|
107
|
+
if __parentContext == undefined {
|
|
108
|
+
__parentContext = self.inputs()[_INPUT_CONTEXT_FIELD_NAME]
|
|
109
|
+
if __parentContext == undefined {
|
|
110
|
+
ll.panic("parent context is not set in inputs")
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return __parentContext
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Utility function to build final template outputs given block results
|
|
118
|
+
*/
|
|
119
|
+
_buildOutputs := func(results) {
|
|
120
|
+
ll.assert(ll.isMap(results), "expected to see map result from body function")
|
|
121
|
+
ll.assert(
|
|
122
|
+
sets.fromSlice(["outputs", "exports"]) == sets.fromMapKeys(results),
|
|
123
|
+
"expected only results and exports in the returned map, found", sets.fromMapKeys(results)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
ll.assert(!is_undefined(results.outputs), "outputs are not defined in the results")
|
|
127
|
+
ll.assert(!is_undefined(results.exports), "exports are not defined in the results")
|
|
128
|
+
|
|
129
|
+
ll.assert(ll.isMap(results.outputs), "expected a map in outputs returned from workflow.body")
|
|
130
|
+
ll.assert(ll.isMap(results.exports), "expected a map in exports returned from workflow.body")
|
|
131
|
+
|
|
132
|
+
// block outputs
|
|
133
|
+
o := results.outputs
|
|
134
|
+
// block exports
|
|
135
|
+
e := results.exports
|
|
136
|
+
|
|
137
|
+
// create results map
|
|
138
|
+
resBuilder := smart.mapBuilder()
|
|
139
|
+
for name, value in o {
|
|
140
|
+
ll.assert(!is_undefined(value), "value is undefined for output ", name)
|
|
141
|
+
resBuilder.add(name, value)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// data to pass to ctx builder template
|
|
145
|
+
eData := {}
|
|
146
|
+
eData[constants.NO_PREFIX_EXPORT] = {}
|
|
147
|
+
|
|
148
|
+
for name, value in e {
|
|
149
|
+
// pass resource to flatten in ctx builder
|
|
150
|
+
if smart.isReference(value) {
|
|
151
|
+
eData[name] = value
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// check that value has spec and data
|
|
156
|
+
ll.assert(
|
|
157
|
+
sets.fromSlice(["spec", "data"]) == sets.fromMapKeys(value),
|
|
158
|
+
"expected spec and data export structure"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
spec := value.spec
|
|
162
|
+
ll.assert(!is_undefined(spec), "spec must be defined")
|
|
163
|
+
|
|
164
|
+
if !smart.isReference(spec) {
|
|
165
|
+
spec = bobject.createSpec(spec)
|
|
166
|
+
}
|
|
167
|
+
eData[constants.NO_PREFIX_EXPORT][name + ".spec"] = spec
|
|
168
|
+
eData[constants.NO_PREFIX_EXPORT][name + ".data"] = value.data
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// create ctx and save exports
|
|
172
|
+
ctxBuilder := render.createEphemeral(
|
|
173
|
+
assets.importTemplate("@platforma-sdk/workflow-tengo:workflow.build-ctx"),
|
|
174
|
+
{
|
|
175
|
+
blockId: blockId(),
|
|
176
|
+
parentContext: _parentContext(),
|
|
177
|
+
data: eData
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
// final template outputs
|
|
182
|
+
tplOutputs := {}
|
|
183
|
+
tplOutputs[_RESULTS_FIELD_NAME] = resBuilder.build()
|
|
184
|
+
tplOutputs[_OUTPUT_CONTEXT_FIELD_NAME] = ctxBuilder.output("ctx")
|
|
185
|
+
|
|
186
|
+
return tplOutputs
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Query results pool.
|
|
191
|
+
*
|
|
192
|
+
* @param spec: query spec
|
|
193
|
+
* @return result: an array of {ref: spec: data:} objects (data will be absent if not requested)
|
|
194
|
+
*/
|
|
195
|
+
query := func(spec, ...options) {
|
|
196
|
+
return bquery.create(spec, _parentContext(), options...)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Query results pool to find spec & data for a given ref.
|
|
201
|
+
*
|
|
202
|
+
* @param ref: a ref object ({blockId: name:})
|
|
203
|
+
* @return result: a {ref: spec: data:} object
|
|
204
|
+
*/
|
|
205
|
+
resolve := func(ref, ...options) {
|
|
206
|
+
r := bquery.resolve(ref, _parentContext(), options...)
|
|
207
|
+
|
|
208
|
+
return ll.toStrict(oop.inherit(r, {
|
|
209
|
+
spec: r.getFutureInputField("spec"),
|
|
210
|
+
data: r.getFutureInputField("data")
|
|
211
|
+
}))
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
// template for prerun
|
|
216
|
+
_preRunTpl := undefined
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Prepare additional resources for the workflow body. The body function of the workflow will be executed only when the references will be
|
|
220
|
+
* returned by the prepare method will ve resolved into a ready resources. The resulting resources will be passed as an input to the body function.
|
|
221
|
+
*
|
|
222
|
+
* @param cb: a callback function returning a map of references to be resolved
|
|
223
|
+
*/
|
|
224
|
+
prepare := func(cb) {
|
|
225
|
+
self.prepare(func(_){
|
|
226
|
+
raw := cb(args())
|
|
227
|
+
prefixed := {}
|
|
228
|
+
// mark prepared inputs
|
|
229
|
+
for k, v in raw {
|
|
230
|
+
prefixed[_PREPARED_INPUTS_PREFIX + k] = v
|
|
231
|
+
}
|
|
232
|
+
return prefixed
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Defines a pre run entry point for a current workflow
|
|
238
|
+
*/
|
|
239
|
+
setPreRun := func(tplId) {
|
|
240
|
+
ll.assert(is_undefined(_preRunTpl), "pre run template is already set")
|
|
241
|
+
|
|
242
|
+
ll.assert(!is_undefined(tplId), "prerun template is undefined")
|
|
243
|
+
_preRunTpl = tplId
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Validate that arguments fulfil the desired schema
|
|
248
|
+
*/
|
|
249
|
+
validateArgs := func(argsSchema) {
|
|
250
|
+
self.validateInputs({
|
|
251
|
+
args: argsSchema
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Defines main entry point for current workflow
|
|
257
|
+
*/
|
|
258
|
+
body := func(bodyFn) {
|
|
259
|
+
|
|
260
|
+
if _isProduction() {
|
|
261
|
+
|
|
262
|
+
self.body(func(_) {
|
|
263
|
+
|
|
264
|
+
workflowInputArgs := args()
|
|
265
|
+
result := bodyFn(workflowInputArgs)
|
|
266
|
+
|
|
267
|
+
return _buildOutputs(result)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
} else if !is_undefined(_preRunTpl) {
|
|
271
|
+
|
|
272
|
+
// staging; render pre-run template
|
|
273
|
+
|
|
274
|
+
self.delegate(_preRunTpl, { isProduction: true }, [_RESULTS_FIELD_NAME, _OUTPUT_CONTEXT_FIELD_NAME])
|
|
275
|
+
|
|
276
|
+
} else {
|
|
277
|
+
|
|
278
|
+
// staging; pre-run template not specified; noop
|
|
279
|
+
|
|
280
|
+
self.body(func(_) {
|
|
281
|
+
return _buildOutputs({
|
|
282
|
+
outputs: {},
|
|
283
|
+
exports: {}
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export ll.toStrict({
|
|
291
|
+
query: query,
|
|
292
|
+
resolve: resolve,
|
|
293
|
+
prepare: prepare,
|
|
294
|
+
body: body,
|
|
295
|
+
setPreRun: setPreRun,
|
|
296
|
+
blockId: blockId,
|
|
297
|
+
validateArgs: validateArgs
|
|
298
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare type TemplateFromFile = { readonly type: "from-file"; readonly path: string; };
|
|
2
|
+
declare type TplName = "pframes.aggregate" | "pframes.export-single-pcolumn" | "pframes.import-dir" | "pframes.map-pframe" | "workdir.save" | "workflow.build-ctx" | "exec.create-python-venv" | "exec.exec" | "pframes.export-multiple-pcolumns" | "pframes.export-pframe" | "pframes.import-xsv-map";
|
|
3
|
+
declare const Templates: Record<TplName, TemplateFromFile>;
|
|
4
|
+
export { Templates };
|
package/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = { Templates: {
|
|
2
|
+
'pframes.aggregate': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.aggregate.plj.gz') },
|
|
3
|
+
'pframes.export-single-pcolumn': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz') },
|
|
4
|
+
'pframes.import-dir': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.import-dir.plj.gz') },
|
|
5
|
+
'pframes.map-pframe': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.map-pframe.plj.gz') },
|
|
6
|
+
'workdir.save': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/workdir.save.plj.gz') },
|
|
7
|
+
'workflow.build-ctx': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/workflow.build-ctx.plj.gz') },
|
|
8
|
+
'exec.create-python-venv': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/exec.create-python-venv.plj.gz') },
|
|
9
|
+
'exec.exec': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/exec.exec.plj.gz') },
|
|
10
|
+
'pframes.export-multiple-pcolumns': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz') },
|
|
11
|
+
'pframes.export-pframe': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.export-pframe.plj.gz') },
|
|
12
|
+
'pframes.import-xsv-map': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/pframes.import-xsv-map.plj.gz') }
|
|
13
|
+
}}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@platforma-sdk/workflow-tengo",
|
|
3
|
+
"version": "1.2.6",
|
|
4
|
+
"description": "Tengo SDK library",
|
|
5
|
+
"files": [
|
|
6
|
+
"./dist/**/*",
|
|
7
|
+
"./index.d.ts",
|
|
8
|
+
"./index.js"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@milaboratories/software-pframes-conv": "^1.5.1"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@milaboratories/tengo-template-builder": "^1.14.7"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"type-check": "pl-tengo check",
|
|
18
|
+
"build": "rm -rf dist && pl-tengo check && pl-tengo build",
|
|
19
|
+
"test": "pl-tengo test",
|
|
20
|
+
"format": "/usr/bin/env emacs --quick --script ./format.el",
|
|
21
|
+
"format-stdin": "/usr/bin/env emacs --quick --script ./format-stdin.el",
|
|
22
|
+
"vscode-tags": "./create_tags.sh .tags false",
|
|
23
|
+
"emacs-tags": "./create_tags.sh ../TAGS false -e"
|
|
24
|
+
}
|
|
25
|
+
}
|