@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,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gives an interface for working with workdirs.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
json := import("json")
|
|
6
|
+
|
|
7
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
8
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
9
|
+
constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
10
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
11
|
+
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
12
|
+
sets := import("@platforma-sdk/workflow-tengo:sets")
|
|
13
|
+
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
14
|
+
path := import("@platforma-sdk/workflow-tengo:path")
|
|
15
|
+
enum := import("enum")
|
|
16
|
+
validation := import("@platforma-sdk/workflow-tengo:validation")
|
|
17
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
18
|
+
|
|
19
|
+
create := func() {
|
|
20
|
+
wd := smart.ephemeralBuilder(constants.RTYPE_WORKDIR_CREATE).lockAndBuild()
|
|
21
|
+
return wd.getField("workdir")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_getFileFillRule := func(filePath, extension) {
|
|
25
|
+
return {
|
|
26
|
+
path: filePath,
|
|
27
|
+
type: "file",
|
|
28
|
+
permissions: 0o600,
|
|
29
|
+
pathKey: filePath,
|
|
30
|
+
blobKey: filePath,
|
|
31
|
+
copyOptional: true,
|
|
32
|
+
fileExtension: extension
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generates a value fill rule for a given file path.
|
|
38
|
+
*
|
|
39
|
+
* @param filePath: string - the path of the file.
|
|
40
|
+
* @return rule: map - the value fill rule.
|
|
41
|
+
*/
|
|
42
|
+
_getValueFillRule := func(filePath) {
|
|
43
|
+
return {
|
|
44
|
+
path: filePath,
|
|
45
|
+
type: "value",
|
|
46
|
+
permissions: 0o600,
|
|
47
|
+
pathKey: filePath,
|
|
48
|
+
valueKey: filePath
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Generates a directory fill rule for a given directory.
|
|
54
|
+
*
|
|
55
|
+
* @param dir: string - the path of the directory.
|
|
56
|
+
* @return rule: map - the directory fill rule.
|
|
57
|
+
*/
|
|
58
|
+
_getDirFillRule := func(dir) {
|
|
59
|
+
return {
|
|
60
|
+
path: dir,
|
|
61
|
+
type: "dir",
|
|
62
|
+
permissions: 0o700,
|
|
63
|
+
pathKey: ""
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Fills a workdir with files, values, and directories.
|
|
69
|
+
*
|
|
70
|
+
* @param workdir: reference - a reference to the workdir to fill.
|
|
71
|
+
* @return self: builder - a builder that adds files and directories to the workdir. */
|
|
72
|
+
_fill := func(workdir) {
|
|
73
|
+
ll.assert(smart.isReference(workdir), "workdir must be a reference to a resource or field")
|
|
74
|
+
|
|
75
|
+
wd := smart.ephemeralBuilder(constants.RTYPE_WORKDIR_FILL)
|
|
76
|
+
wd.getField("workdirIn").set(workdir)
|
|
77
|
+
|
|
78
|
+
files := {}
|
|
79
|
+
values := {}
|
|
80
|
+
dirs := {}
|
|
81
|
+
|
|
82
|
+
self := undefined
|
|
83
|
+
self = ll.toStrict(oop.inherit(wd, {
|
|
84
|
+
_getAllDirs: func(fileName) {
|
|
85
|
+
dirsWithFileName := path.getBasenameDirs(fileName)
|
|
86
|
+
return slices.slice(dirsWithFileName, 0, -1)
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
_addDirs: func(fileName) {
|
|
90
|
+
newDirs := self._getAllDirs(fileName)
|
|
91
|
+
sets.add(dirs, newDirs...)
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds a file to the workdir.
|
|
96
|
+
*
|
|
97
|
+
* @param fileName: string - the name of the file.
|
|
98
|
+
* @param fileResource: reference - the file to add.
|
|
99
|
+
*/
|
|
100
|
+
addFile: func(fileName, fileResource) {
|
|
101
|
+
validation.assertJsonSchema(fileName, "string")
|
|
102
|
+
validation.assertJsonSchema(fileResource, validation.reference)
|
|
103
|
+
|
|
104
|
+
files[fileName] = fileResource
|
|
105
|
+
self._addDirs(fileName)
|
|
106
|
+
|
|
107
|
+
return self
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Adds multiple files to the workdir.
|
|
112
|
+
*
|
|
113
|
+
* @param fileMap: map[string]reference - a map of files.
|
|
114
|
+
*/
|
|
115
|
+
addFiles: func(fileMap) {
|
|
116
|
+
enum.each(fileMap, self.addFile)
|
|
117
|
+
return self
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Adds a file with a content to the workdir.
|
|
122
|
+
*
|
|
123
|
+
* @param fileName: string - the name of the file.
|
|
124
|
+
* @param contentRef: reference|any - the content as a reference to add or the content itself.
|
|
125
|
+
*/
|
|
126
|
+
writeFile: func(fileName, contentRef) {
|
|
127
|
+
validation.assertJsonSchema(fileName, "string")
|
|
128
|
+
values[fileName] = contentRef
|
|
129
|
+
self._addDirs(fileName)
|
|
130
|
+
|
|
131
|
+
return self
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Adds multiple files with contents to the workdir.
|
|
136
|
+
*
|
|
137
|
+
* @param contentMap: map[string]any|reference - a map of references to a content or to a content itself.
|
|
138
|
+
*/
|
|
139
|
+
writeFiles: func(contentRefMap) {
|
|
140
|
+
enum.each(contentRefMap, self.writeFile)
|
|
141
|
+
return self
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Creates a possibly nested directory in the workdir.
|
|
146
|
+
*
|
|
147
|
+
* @param dir: string - the path of the directory.
|
|
148
|
+
*/
|
|
149
|
+
mkDir: func(dir) {
|
|
150
|
+
sets.add(dirs, path.getBasenameDirs(dir))
|
|
151
|
+
return self
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Builds the filled workdir.
|
|
156
|
+
*
|
|
157
|
+
* @return wd: reference - a reference to the filled workdir.
|
|
158
|
+
*/
|
|
159
|
+
build: func() {
|
|
160
|
+
rules := []
|
|
161
|
+
for dir, _ in dirs {
|
|
162
|
+
rules = append(rules, _getDirFillRule(dir))
|
|
163
|
+
}
|
|
164
|
+
for fileName, _ in files {
|
|
165
|
+
rules = append(rules, _getFileFillRule(fileName, path.getExtension(fileName)))
|
|
166
|
+
}
|
|
167
|
+
for fileName, _ in values {
|
|
168
|
+
rules = append(rules, _getValueFillRule(fileName))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
rulesRes := smart.createValueResource(
|
|
172
|
+
constants.RTYPE_WORKDIR_FILL_RULES,
|
|
173
|
+
json.encode(rules)
|
|
174
|
+
)
|
|
175
|
+
self.getField("rules").set(rulesRes)
|
|
176
|
+
|
|
177
|
+
self.getField("dataIn").set(smart.createBinaryMapResource(values))
|
|
178
|
+
self.getField("blobsIn").set(smart.createBlobMapResource(files))
|
|
179
|
+
|
|
180
|
+
return self.lockAndBuild().outputs().workdirOut
|
|
181
|
+
}
|
|
182
|
+
}))
|
|
183
|
+
|
|
184
|
+
return self
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Creates and fills a workdir with files, contents, and directories. See _fill for futher documentation.
|
|
189
|
+
*
|
|
190
|
+
* @return self: builder - a builder that adds files and directories to the workdir.
|
|
191
|
+
*/
|
|
192
|
+
builder := func() {
|
|
193
|
+
return _fill(create())
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Saves a workdir.
|
|
198
|
+
*
|
|
199
|
+
* @param workdir: reference - a reference to the workdir to save.
|
|
200
|
+
* @return self: builder - the builder that helps adding save rules to the save workdir.
|
|
201
|
+
*/
|
|
202
|
+
save := func(workdir) {
|
|
203
|
+
ll.assert(smart.isReference(workdir), "workdir must be a reference to a resource or field")
|
|
204
|
+
|
|
205
|
+
// files to save
|
|
206
|
+
files := {}
|
|
207
|
+
// files to save their content
|
|
208
|
+
filesContent := {}
|
|
209
|
+
// file sets to save by regex
|
|
210
|
+
fileSets := {}
|
|
211
|
+
// file sets to save their content by regex
|
|
212
|
+
fileSetsContent := {}
|
|
213
|
+
|
|
214
|
+
self := undefined
|
|
215
|
+
self = ll.toStrict({
|
|
216
|
+
/**
|
|
217
|
+
* Saves a file from the workdir.
|
|
218
|
+
*
|
|
219
|
+
* @param fileName: string - the name of the file.
|
|
220
|
+
*/
|
|
221
|
+
saveFile: func(fileName) {
|
|
222
|
+
validation.assertJsonSchema(fileName, "string")
|
|
223
|
+
sets.add(files, fileName)
|
|
224
|
+
return self
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Saves a file to a value resource from the workdir.
|
|
229
|
+
*
|
|
230
|
+
* @param fileName: string - the name of the file.
|
|
231
|
+
*/
|
|
232
|
+
saveFileContent: func(fileName) {
|
|
233
|
+
validation.assertJsonSchema(fileName, "string")
|
|
234
|
+
sets.add(filesContent, fileName)
|
|
235
|
+
return self
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Save files which names satisfy given regex rule
|
|
240
|
+
*
|
|
241
|
+
* @param name: string - a name to refer this file set in the outputs
|
|
242
|
+
* @param regex: string - regex
|
|
243
|
+
*/
|
|
244
|
+
saveFileSet: func(name, regex) {
|
|
245
|
+
validation.assertJsonSchema(regex, "string")
|
|
246
|
+
ll.assert(is_undefined(fileSets[name]), "file set with name '", name, "' is already in added")
|
|
247
|
+
fileSets[name] = regex
|
|
248
|
+
return self
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Save files content which names satisfy given regex rule
|
|
253
|
+
*
|
|
254
|
+
* @param name: string - a name to refer this file set in the outputs
|
|
255
|
+
* @param regex: string - regex
|
|
256
|
+
*/
|
|
257
|
+
saveFileSetContent: func(name, regex) {
|
|
258
|
+
validation.assertJsonSchema(regex, "string")
|
|
259
|
+
ll.assert(is_undefined(fileSetsContent[name]), "file set content with name '", name, "' is already in added")
|
|
260
|
+
sets.add(fileSetsContent, regex)
|
|
261
|
+
return self
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Builds the saved workdir.
|
|
266
|
+
*
|
|
267
|
+
* @return wd: reference - the saved workdir with additional fields.
|
|
268
|
+
*/
|
|
269
|
+
build: func() {
|
|
270
|
+
|
|
271
|
+
tpl := assets.importTemplate("@platforma-sdk/workflow-tengo:workdir.save")
|
|
272
|
+
inputs := {
|
|
273
|
+
workdir: workdir,
|
|
274
|
+
files: files,
|
|
275
|
+
filesContent: filesContent,
|
|
276
|
+
fileSets: fileSets,
|
|
277
|
+
fileSetsContent: fileSetsContent
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
wds := render.createEphemeral(tpl, inputs)
|
|
281
|
+
|
|
282
|
+
return ll.toStrict({
|
|
283
|
+
files: wds.output("files"),
|
|
284
|
+
filesContent: wds.output("filesContent"),
|
|
285
|
+
fileSets : wds.output("fileSets"),
|
|
286
|
+
fileSetsContent : wds.output("fileSetsContent"),
|
|
287
|
+
workdir: wds.output("workdir"),
|
|
288
|
+
progress: wds.output("progress")
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
return self
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export ll.toStrict({
|
|
297
|
+
builder: builder,
|
|
298
|
+
create: create,
|
|
299
|
+
save: save
|
|
300
|
+
})
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/** Library for workdir processor templates */
|
|
2
|
+
|
|
3
|
+
tpl := import("@platforma-sdk/workflow-tengo:tpl")
|
|
4
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
5
|
+
wdSave := import("@platforma-sdk/workflow-tengo:workdir.save")
|
|
6
|
+
|
|
7
|
+
// the template has a defined outputs
|
|
8
|
+
tpl.defineOutputs(["result", "workdir"])
|
|
9
|
+
|
|
10
|
+
proc := func() {
|
|
11
|
+
self := undefined
|
|
12
|
+
|
|
13
|
+
self = {
|
|
14
|
+
|
|
15
|
+
_wdBefore: undefined,
|
|
16
|
+
/**
|
|
17
|
+
* @return wd: resource - initial working directory resource
|
|
18
|
+
*/
|
|
19
|
+
wdBefore: func() {
|
|
20
|
+
if is_undefined(self._wdBefore) {
|
|
21
|
+
self._wdBefore = tpl.inputs().workdir
|
|
22
|
+
}
|
|
23
|
+
return self._wdBefore
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
_filesInWd: undefined,
|
|
27
|
+
/**
|
|
28
|
+
* @return fileNames: string[] - list of file paths currently existing in the working directory
|
|
29
|
+
*/
|
|
30
|
+
filesInWd: func() {
|
|
31
|
+
if is_undefined(self._filesInWd) {
|
|
32
|
+
self._filesInWd = self.wdBefore().getDataAsJson().files
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return self._filesInWd
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
_wdAfterReadFiles: undefined,
|
|
39
|
+
/**
|
|
40
|
+
* @return wd: resource - working directory resource after "readFiles" is done
|
|
41
|
+
*/
|
|
42
|
+
wdAfterReadFiles: func() {
|
|
43
|
+
if is_undefined(self._wdAfterReadFiles) {
|
|
44
|
+
|
|
45
|
+
if !is_undefined(tpl.inputs().wdAfterReadFiles) {
|
|
46
|
+
|
|
47
|
+
//
|
|
48
|
+
// this means readFiles was used and we are actually
|
|
49
|
+
// in the 'prepare' render
|
|
50
|
+
//
|
|
51
|
+
self._wdAfterReadFiles = tpl.inputs().wdAfterReadFiles
|
|
52
|
+
} else {
|
|
53
|
+
|
|
54
|
+
// no readFiles
|
|
55
|
+
self._wdAfterReadFiles = self.wdBefore()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return self._wdAfterReadFiles
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Select files to read their content and pass it to the body function
|
|
64
|
+
*
|
|
65
|
+
* @param cb: callback - a callback which takes a list of file names (paths) existing in the working directory and
|
|
66
|
+
* returning a map of key -> file name containing files to get content from; each file content will be available in
|
|
67
|
+
* the body inputs with the corresponding key
|
|
68
|
+
*/
|
|
69
|
+
readFiles: func(cb) {
|
|
70
|
+
tpl.prepare(func(inputs){
|
|
71
|
+
inputs.files = self.filesInWd()
|
|
72
|
+
// key -> file name
|
|
73
|
+
files := cb(inputs)
|
|
74
|
+
|
|
75
|
+
wdBuilder := wdSave.builder(self.wdBefore())
|
|
76
|
+
for _, fName in files {
|
|
77
|
+
wdBuilder.saveFileContent(fName)
|
|
78
|
+
}
|
|
79
|
+
wd := wdBuilder.build()
|
|
80
|
+
|
|
81
|
+
// run prepare to get file contents in the inputs
|
|
82
|
+
preps := {}
|
|
83
|
+
for key, fName in files {
|
|
84
|
+
preps[key] = wd.getSavedFileContent(fName)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
preps.wdAfterReadFiles = wd.getWorkdirAfter()
|
|
88
|
+
|
|
89
|
+
return preps
|
|
90
|
+
})
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
_wdFinalBuilder: undefined,
|
|
94
|
+
/**
|
|
95
|
+
* Final workdir builder, after prepare
|
|
96
|
+
*/
|
|
97
|
+
wdFinalBuilder: func() {
|
|
98
|
+
if is_undefined(self._wdFinalBuilder) {
|
|
99
|
+
self._wdFinalBuilder = wdSave.builder(self.wdAfterReadFiles())
|
|
100
|
+
}
|
|
101
|
+
return self._wdFinalBuilder
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Save given file.
|
|
106
|
+
*
|
|
107
|
+
* @return ref: reference - a reference to saved file resource
|
|
108
|
+
*/
|
|
109
|
+
saveFile: func(fName) {
|
|
110
|
+
self.wdFinalBuilder().saveFile(fName)
|
|
111
|
+
return self.wdFinalBuilder().getSavedFile(fName)
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Save content of a given file.
|
|
116
|
+
*
|
|
117
|
+
* @return ref: reference - a reference to saved file content value resource
|
|
118
|
+
*/
|
|
119
|
+
saveFileContent: func(fName) {
|
|
120
|
+
self.wdFinalBuilder().saveFileContent(fName)
|
|
121
|
+
return self.wdFinalBuilder().getSavedFileContent(fName)
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Template body function
|
|
126
|
+
*
|
|
127
|
+
* @param cb: func - a callback function to run in template body; the inputs passed to the body will have the following fields:
|
|
128
|
+
* files: string[] - list of files in workdir
|
|
129
|
+
* args: map - additional arguments of the template processor
|
|
130
|
+
* ...filesContent: resources - fields with the content of files specified in 'readFiles'
|
|
131
|
+
*/
|
|
132
|
+
body: func(cb) {
|
|
133
|
+
tpl.body(func(inputs) {
|
|
134
|
+
|
|
135
|
+
inputs.files = self.filesInWd()
|
|
136
|
+
result := cb(inputs)
|
|
137
|
+
wd := self.wdFinalBuilder().build()
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
result: result,
|
|
141
|
+
workdir: wd.getWorkdirAfter()
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return ll.toStrict(self)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** singleton instance */
|
|
151
|
+
instance := proc()
|
|
152
|
+
|
|
153
|
+
export ll.toStrict({
|
|
154
|
+
readFiles: instance.readFiles,
|
|
155
|
+
saveFile: instance.saveFile,
|
|
156
|
+
saveFileContent: instance.saveFileContent,
|
|
157
|
+
body: instance.body
|
|
158
|
+
})
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/** A library providing workdir save resource builder */
|
|
2
|
+
|
|
3
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
4
|
+
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
5
|
+
json := import("json")
|
|
6
|
+
sets := import("@platforma-sdk/workflow-tengo:sets")
|
|
7
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
8
|
+
constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
9
|
+
|
|
10
|
+
_WORKDIR_IN_FIELD := "workdirIn"
|
|
11
|
+
_RULES_FIELD := "rules"
|
|
12
|
+
_SAVED_FILES_FIELD := "blobsOut"
|
|
13
|
+
_SAVED_CONTENT_FIELD := "dataOut"
|
|
14
|
+
_WORKDIR_AFTER_FIELD := "workdirOut"
|
|
15
|
+
_PROGRESS_FIELD := "progress"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generates a file save rule for a given file name.
|
|
20
|
+
*
|
|
21
|
+
* @param fileName: string - the name of the file.
|
|
22
|
+
* @return rule: map - the file save rule.
|
|
23
|
+
*/
|
|
24
|
+
getFileSaveRule := func(fileName) {
|
|
25
|
+
return {
|
|
26
|
+
blobKey: fileName,
|
|
27
|
+
type: "file",
|
|
28
|
+
filePath: fileName
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Generates a value save rule for a given file name.
|
|
34
|
+
*
|
|
35
|
+
* @param fileName: string - the name of the file.
|
|
36
|
+
* @return rule: map - the value save rule.
|
|
37
|
+
*/
|
|
38
|
+
getContentSaveRule := func(fileName) {
|
|
39
|
+
return {
|
|
40
|
+
blobKey: fileName,
|
|
41
|
+
type: "content",
|
|
42
|
+
contentPath: fileName
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a builder for workdir save resource
|
|
48
|
+
*/
|
|
49
|
+
builder := func(wdBefore) {
|
|
50
|
+
|
|
51
|
+
super := smart.ephemeralBuilder(constants.RTYPE_WORKDIR_SAVE)
|
|
52
|
+
// set input wd
|
|
53
|
+
super.getField(_WORKDIR_IN_FIELD).set(wdBefore)
|
|
54
|
+
|
|
55
|
+
// file save rules
|
|
56
|
+
fRules := {}
|
|
57
|
+
// content save rules
|
|
58
|
+
cRules := {}
|
|
59
|
+
|
|
60
|
+
self := undefined
|
|
61
|
+
self = ll.toStrict(oop.inherit(super, {
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Save file.
|
|
65
|
+
*
|
|
66
|
+
* @param fName: string - file name
|
|
67
|
+
*
|
|
68
|
+
*/
|
|
69
|
+
saveFile: func(fName) {
|
|
70
|
+
fRules = sets.add(fRules, fName)
|
|
71
|
+
return self
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Save file content.
|
|
76
|
+
*
|
|
77
|
+
* @param fName: string - file name
|
|
78
|
+
*
|
|
79
|
+
*/
|
|
80
|
+
saveFileContent: func(fName) {
|
|
81
|
+
cRules = sets.add(cRules, fName)
|
|
82
|
+
return self
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get field pointing to saved files map resource
|
|
87
|
+
*/
|
|
88
|
+
getSavedFiles: func() {
|
|
89
|
+
return self.getField(_SAVED_FILES_FIELD)
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get field pointing to saved files content map resource
|
|
94
|
+
*/
|
|
95
|
+
getSavedFilesContent: func() {
|
|
96
|
+
return self.getField(_SAVED_CONTENT_FIELD)
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get field pointing to workdir after resource
|
|
101
|
+
*/
|
|
102
|
+
getWorkdirAfter: func() {
|
|
103
|
+
return self.getField(_WORKDIR_AFTER_FIELD)
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get field pointing to progress resource
|
|
108
|
+
*/
|
|
109
|
+
getProgress: func() {
|
|
110
|
+
return self.getField(_PROGRESS_FIELD)
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get future field pointing to saved file resource
|
|
115
|
+
*/
|
|
116
|
+
getSavedFile: func(fName) {
|
|
117
|
+
return self.getSavedFiles().getFutureInputField(fName)
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get future field pointing to saved file content value resource
|
|
122
|
+
*/
|
|
123
|
+
getSavedFileContent: func(fName) {
|
|
124
|
+
return self.getSavedFilesContent().getFutureInputField(fName)
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Build resource
|
|
129
|
+
*/
|
|
130
|
+
build: func() {
|
|
131
|
+
rules := []
|
|
132
|
+
for fName, _ in fRules {
|
|
133
|
+
rules = append(rules, getFileSaveRule(fName))
|
|
134
|
+
}
|
|
135
|
+
for fName, _ in cRules {
|
|
136
|
+
rules = append(rules, getContentSaveRule(fName))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
super.getField(_RULES_FIELD).set(
|
|
140
|
+
smart.createValueResource(
|
|
141
|
+
constants.RTYPE_WORKDIR_SAVE_RULES,
|
|
142
|
+
json.encode(rules)
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
resource := super.lockAndBuild()
|
|
147
|
+
|
|
148
|
+
// still return self to have all the methods
|
|
149
|
+
return self
|
|
150
|
+
}
|
|
151
|
+
}))
|
|
152
|
+
|
|
153
|
+
return self
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export ll.toStrict({
|
|
157
|
+
builder: builder
|
|
158
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions to work with export objects & p-frames
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
6
|
+
constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
7
|
+
json := import("json")
|
|
8
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
9
|
+
validation := import("@platforma-sdk/workflow-tengo:validation")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
//
|
|
13
|
+
_pObjectSpecSchema := {
|
|
14
|
+
"__options__,closed": "",
|
|
15
|
+
|
|
16
|
+
"kind": "string",
|
|
17
|
+
|
|
18
|
+
"valueType,omitempty": `string,regex=json|File|DynamicFile|String|Double|Long|Int`,
|
|
19
|
+
|
|
20
|
+
"name,omitempty": {",any": "string"},
|
|
21
|
+
|
|
22
|
+
"domain,omitempty": {",any": "string"},
|
|
23
|
+
|
|
24
|
+
"axesSpec,omitempty": [{
|
|
25
|
+
"type": "string,regex=String",
|
|
26
|
+
"name": "string",
|
|
27
|
+
"domain,omitempty": {",any": "string"},
|
|
28
|
+
"annotations,omitempty": {",any": "string"}
|
|
29
|
+
}],
|
|
30
|
+
|
|
31
|
+
"annotations,omitempty": {",any": "string"}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates export object spec from a given map
|
|
37
|
+
*
|
|
38
|
+
* @param spec: map
|
|
39
|
+
*/
|
|
40
|
+
createSpec := func(spec) {
|
|
41
|
+
ll.assert(ll.isMap(spec), "expected map got %v", spec)
|
|
42
|
+
|
|
43
|
+
// @TODO fix validation
|
|
44
|
+
// validation.assertValidJson(spec, _pObjectSpecSchema)
|
|
45
|
+
|
|
46
|
+
return smart.createValueResource(constants.RTYPE_BOBJECT_SPEC, json.encode(spec))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export ll.toStrict({
|
|
50
|
+
createSpec: createSpec
|
|
51
|
+
})
|