@platforma-sdk/workflow-tengo 2.8.1 → 2.8.2

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 (59) hide show
  1. package/dist/tengo/lib/assets.lib.tengo +76 -82
  2. package/dist/tengo/lib/constants.lib.tengo +28 -31
  3. package/dist/tengo/lib/exec.R.internal.lib.tengo +14 -14
  4. package/dist/tengo/lib/exec.R.lib.tengo +158 -167
  5. package/dist/tengo/lib/exec.internal.lib.tengo +222 -234
  6. package/dist/tengo/lib/exec.lib.tengo +647 -714
  7. package/dist/tengo/lib/exec.package.lib.tengo +229 -238
  8. package/dist/tengo/lib/exec.python.internal.lib.tengo +5 -6
  9. package/dist/tengo/lib/exec.python.lib.tengo +138 -146
  10. package/dist/tengo/lib/exec.runcmd.lib.tengo +234 -253
  11. package/dist/tengo/lib/exec.runenv.lib.tengo +88 -92
  12. package/dist/tengo/lib/exec.stream.lib.tengo +36 -40
  13. package/dist/tengo/lib/file.internal.lib.tengo +70 -77
  14. package/dist/tengo/lib/file.lib.tengo +54 -57
  15. package/dist/tengo/lib/ll.lib.tengo +217 -241
  16. package/dist/tengo/lib/maps.lib.tengo +98 -106
  17. package/dist/tengo/lib/objects.lib.tengo +11 -13
  18. package/dist/tengo/lib/oop.lib.tengo +16 -19
  19. package/dist/tengo/lib/path.lib.tengo +116 -125
  20. package/dist/tengo/lib/pframes.constants.lib.tengo +25 -28
  21. package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +28 -33
  22. package/dist/tengo/lib/pframes.lib.tengo +38 -43
  23. package/dist/tengo/lib/pframes.ll.lib.tengo +70 -73
  24. package/dist/tengo/lib/pframes.pcolumn.lib.tengo +45 -51
  25. package/dist/tengo/lib/pframes.spec.lib.tengo +70 -96
  26. package/dist/tengo/lib/pframes.util.lib.tengo +154 -289
  27. package/dist/tengo/lib/pframes.xsv.lib.tengo +260 -273
  28. package/dist/tengo/lib/render.lib.tengo +65 -76
  29. package/dist/tengo/lib/sets.lib.tengo +61 -68
  30. package/dist/tengo/lib/slices.lib.tengo +169 -180
  31. package/dist/tengo/lib/smart.lib.tengo +956 -1069
  32. package/dist/tengo/lib/test.lib.tengo +129 -161
  33. package/dist/tengo/lib/tpl.lib.tengo +448 -516
  34. package/dist/tengo/lib/tpl.state-await.lib.tengo +226 -241
  35. package/dist/tengo/lib/tpl.util.lib.tengo +4 -9
  36. package/dist/tengo/lib/validation.lib.tengo +334 -379
  37. package/dist/tengo/lib/workdir.lib.tengo +309 -332
  38. package/dist/tengo/lib/workdir.proc.lib.tengo +126 -144
  39. package/dist/tengo/lib/workdir.save.lib.tengo +113 -130
  40. package/dist/tengo/lib/workflow.bobject.lib.tengo +21 -26
  41. package/dist/tengo/lib/workflow.bquery.lib.tengo +140 -166
  42. package/dist/tengo/lib/workflow.constants.lib.tengo +1 -2
  43. package/dist/tengo/lib/workflow.context.lib.tengo +27 -32
  44. package/dist/tengo/lib/workflow.lib.tengo +167 -207
  45. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  46. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  47. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  48. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  49. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  50. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  51. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  52. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  53. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  54. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  55. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  56. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  57. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  58. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  59. package/package.json +5 -5
@@ -1,12 +1,10 @@
1
- /**
2
- * Library providing xsv <> p-frames conversion utils.
3
- */
1
+
2
+
4
3
 
5
4
  validation := import("@platforma-sdk/workflow-tengo:validation")
6
5
  constants := import("@platforma-sdk/workflow-tengo:pframes.constants")
7
6
  objects := import("@platforma-sdk/workflow-tengo:objects")
8
7
  render := import("@platforma-sdk/workflow-tengo:render")
9
- smart := import("@platforma-sdk/workflow-tengo:smart")
10
8
  exec := import("@platforma-sdk/workflow-tengo:exec")
11
9
  json := import("json")
12
10
  text := import("text")
@@ -17,289 +15,278 @@ assets := import("@platforma-sdk/workflow-tengo:assets")
17
15
  transposeXsvSw := assets.importSoftware("@platforma-open/milaboratories.software-small-binaries:table-converter")
18
16
  pfconvSw := assets.importSoftware("@milaboratories/software-pframes-conv:main")
19
17
 
20
- /**
21
- * Calculate axes spec from pfconv spec
22
- */
18
+
19
+
23
20
  getAxesSpec := func(spec) {
24
- axes := []
25
- for ax in spec.axes {
26
- axes = append(axes, ax.spec)
27
- }
28
- return axes
21
+ axes := []
22
+ for ax in spec.axes {
23
+ axes = append(axes, ax.spec)
24
+ }
25
+ return axes
29
26
  }
30
27
 
31
28
  renderOps := func(defaults, ...ops) {
32
- o := { }
29
+ o := { }
33
30
 
34
- for k, v in defaults {
35
- o[k] = v
36
- }
31
+ for k, v in defaults {
32
+ o[k] = v
33
+ }
37
34
 
38
- if len(ops) > 0 {
39
- for k, v in ops[0] {
40
- o[k] = v
41
- }
42
- }
43
- return o
35
+ if len(ops) > 0 {
36
+ for k, v in ops[0] {
37
+ o[k] = v
38
+ }
39
+ }
40
+ return o
44
41
  }
45
42
 
46
43
  getColumnSpec := func(axesSpec, col) {
47
- spec := {
48
- kind: constants.KIND_P_COLUMN,
49
- axesSpec: axesSpec
50
- }
51
-
52
- for k, v in col.spec {
53
- spec[k] = v
54
- }
55
-
56
- return objects.deleteUndefined(spec)
57
- }
58
-
59
- /**
60
- * Imports xsv data into p-frame. The resulting map resource contains all columns specified in the params (column identifiers as
61
- * provided by the spec used as map keys). Resulting p-columns will be always single-partitioned at most.
62
- *
63
- * @param xsvFile: reference - a reference to a file
64
- * @param xsvType: string - either csv or tsv
65
- * @param spec: object - xsv conversion specification
66
- * @param ops: object - additional options
67
- * {
68
- * dataOnly: boolean - set to true to completely skip creation of specs
69
- * splitDataAndSpec: boolean - if true, resulting map will have nested structures,
70
- * with "spec" + "data" fields in nested maps
71
- * transpose: object - if specified, then the input table will be transposed
72
- * {
73
- * separator: string - (optional) use separator instead of inferring from the file extension
74
- * pAxisIdx: index - (optional) the index of the primary axis (column in the input xsv); default 0
75
- * pAxisName: string - (optional) the name of the primary axis (column name in the input xsv); default undefined
76
- * pAxisSearch: regex - (optional) the regex pattern of the name of the primary axis (column name in the input xsv); default undefined
77
- * pAxisNameOverride: string - (optional) override primary axis header in the output; default undefined
78
- * sAxisSearch: string - (optional) regex to filter secondary axis columns in the input table;
79
- * sAxisName: string - (optional) the name of the secondary axis (column name in the output xsv); default "Metric"
80
- * valueName: string - (optional) the name of the value column; default "Value"
81
- * separatorOverride: string - (optional) specify separator in the output (optional)
82
- * }
83
- * }
84
- * @return map: reference - a reference to a map resource storing imported data.
85
- */
44
+ spec := {
45
+ kind: constants.KIND_P_COLUMN,
46
+ axesSpec: axesSpec
47
+ }
48
+
49
+ for k, v in col.spec {
50
+ spec[k] = v
51
+ }
52
+
53
+ return objects.deleteUndefined(spec)
54
+ }
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
86
82
  importFile := func(xsvFile, xsvType, spec, ...ops) {
87
- ll.assert(xsvType == "csv" || xsvType == "tsv", "expected one of [tsv, csv] types")
88
-
89
- validation.assertJsonSchema(spec, util.PFCONV_IMPORT_CFG_SCHEMA)
90
-
91
- xsvFileName := "file." + xsvType
92
-
93
- ops := renderOps({ dataOnly: false, splitDataAndSpec: false }, ops...)
94
-
95
- if ops.transpose != undefined {
96
-
97
- tops := ops.transpose
98
-
99
- transposedFileName := "fileTransposed." + xsvType
100
-
101
- // convert csv to p-frame and read resulting data
102
- transposeXsv := exec.builder().
103
- software(transposeXsvSw).
104
- printErrStreamToStdout().
105
- inLightQueue()
106
-
107
- if (tops.separator != undefined) {
108
- transposeXsv = transposeXsv.arg("-input-separator").arg(tops.separator)
109
- }
110
- if (tops.pAxisIdx != undefined) {
111
- transposeXsv = transposeXsv.arg("-sample-column-i").arg("" + tops.pAxisIdx) // always convert to string
112
- }
113
- if (tops.pAxisName != undefined) {
114
- transposeXsv = transposeXsv.arg("-sample-column-name").arg(tops.pAxisName)
115
- }
116
- if (tops.pAxisSearch != undefined) {
117
- transposeXsv = transposeXsv.arg("-sample-column-search").arg(tops.pAxisSearch)
118
- }
119
- if (tops.pAxisNameOverride != undefined) {
120
- transposeXsv = transposeXsv.arg("-sample-label").arg(tops.pAxisNameOverride)
121
- }
122
- if (tops.sAxisSearch != undefined) {
123
- transposeXsv = transposeXsv.arg("-metric-columns-search").arg(tops.sAxisSearch)
124
- }
125
- if (tops.sAxisName != undefined) {
126
- transposeXsv = transposeXsv.arg("-metric-label").arg(tops.sAxisName)
127
- }
128
- if (tops.valueName != undefined) {
129
- transposeXsv = transposeXsv.arg("-value-label").arg(tops.valueName)
130
- }
131
- if (tops.separatorOverride != undefined) {
132
- transposeXsv = transposeXsv.arg("-separator").arg(tops.separatorOverride)
133
- }
134
-
135
- transposeXsv = transposeXsv.
136
- arg(xsvFileName).
137
- arg(transposedFileName).
138
- addFile(xsvFileName, xsvFile).
139
- saveFile(transposedFileName).
140
- run()
141
-
142
- xsvFile = transposeXsv.getFile(transposedFileName)
143
- }
144
-
145
- // import p-frame from directory tpl
146
- importDirTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.import-dir")
147
-
148
- // spec without any metadata (for caching purposes)
149
- pureSpec := util.purifySpec(spec)
150
-
151
- // convert csv to p-frame and read resulting data
152
- pfconv := exec.builder().
153
- software(pfconvSw).
154
- printErrStreamToStdout().
155
- inLightQueue().
156
- arg("importCsv").
157
- arg(xsvFileName).
158
- arg("-p").arg("spec.json").
159
- arg("-o").arg("out").
160
- addFile(xsvFileName, xsvFile).
161
- writeFile("spec.json", json.encode(pureSpec)).
162
- processWorkdir("pf", importDirTpl, pureSpec).
163
- run()
164
-
165
- // p-columns data
166
- pf := pfconv.getProcessorResult("pf")
167
- if ops.dataOnly {
168
- return pf
169
- }
170
-
171
- axesSpec := getAxesSpec(spec)
172
-
173
- result := {}
174
- for col in spec.columns {
175
- id := util.xsvColumnId(col)
176
-
177
- if ops.splitDataAndSpec {
178
- result[id] = {
179
- data: pf.getFutureInputField(id),
180
- spec: getColumnSpec(axesSpec, col)
181
- }
182
- } else {
183
- result[id + ".data"] = pf.getFutureInputField(id)
184
- result[id + ".spec"] = getColumnSpec(axesSpec, col)
185
- }
186
- }
187
-
188
- return result
189
- }
190
-
191
- /**
192
- * Imports a map with xsv files into a p-frame. The resulting map resource contains all columns specified in the params (column identifiers as
193
- * provided by the spec used as map keys). Resulting p-columns may be double-partitioned.
194
- *
195
- * @param xsvMap: reference - a reference to a p-column resource map with xsv files
196
- * @param xsvType: string - either csv or tsv
197
- * @param spec: object - xsv conversion specification
198
- * @param ops: object - additional options
199
- * {
200
- * dataOnly: boolean - set to true to completely skip creation of specs
201
- * splitDataAndSpec: boolean - if true, resulting map will have nested structures,
202
- * with "spec" + "data" fields in nested maps
203
- * additionalAxesSpec: AxisSpec[] - array of additional axes spec to prepend to
204
- * each column spec
205
- * transpose: object - if specified, then the input table will be transposed
206
- * {
207
- * separator: string - (optional) use separator instead of inferring from the file extension
208
- * pAxisIdx: index - (optional) the index of the primary axis (column in the input xsv); default 0
209
- * pAxisName: string - (optional) the name of the primary axis (column name in the input xsv); default undefined
210
- * pAxisSearch: regex - (optional) the regex pattern of the name of the primary axis (column name in the input xsv); default undefined
211
- * pAxisNameOverride: string - (optional) override primary axis header in the output; default undefined
212
- * sAxisSearch: string - (optional) regex to filter secondary axis columns in the input table;
213
- * sAxisName: string - (optional) the name of the secondary axis (column name in the output xsv); default "Metric"
214
- * valueName: string - (optional) the name of the value column; default "Value"
215
- * separatorOverride: string - (optional) specify separator in the output (optional)
216
- * }
217
- * }
218
- * @return map: reference - a reference to a map resource storing imported data.
219
- */
83
+ ll.assert(xsvType == "csv" || xsvType == "tsv", "expected one of [tsv, csv] types")
84
+
85
+ validation.assertJsonSchema(spec, util.PFCONV_IMPORT_CFG_SCHEMA)
86
+
87
+ xsvFileName := "file." + xsvType
88
+
89
+ ops := renderOps({ dataOnly: false, splitDataAndSpec: false }, ops...)
90
+
91
+ if ops.transpose != undefined {
92
+
93
+ tops := ops.transpose
94
+
95
+ transposedFileName := "fileTransposed." + xsvType
96
+
97
+ transposeXsv := exec.builder().
98
+ software(transposeXsvSw).
99
+ printErrStreamToStdout().
100
+ inLightQueue()
101
+
102
+ if (tops.separator != undefined) {
103
+ transposeXsv = transposeXsv.arg("-input-separator").arg(tops.separator)
104
+ }
105
+ if (tops.pAxisIdx != undefined) {
106
+ transposeXsv = transposeXsv.arg("-sample-column-i").arg("" + tops.pAxisIdx) // always convert to string
107
+ }
108
+ if (tops.pAxisName != undefined) {
109
+ transposeXsv = transposeXsv.arg("-sample-column-name").arg(tops.pAxisName)
110
+ }
111
+ if (tops.pAxisSearch != undefined) {
112
+ transposeXsv = transposeXsv.arg("-sample-column-search").arg(tops.pAxisSearch)
113
+ }
114
+ if (tops.pAxisNameOverride != undefined) {
115
+ transposeXsv = transposeXsv.arg("-sample-label").arg(tops.pAxisNameOverride)
116
+ }
117
+ if (tops.sAxisSearch != undefined) {
118
+ transposeXsv = transposeXsv.arg("-metric-columns-search").arg(tops.sAxisSearch)
119
+ }
120
+ if (tops.sAxisName != undefined) {
121
+ transposeXsv = transposeXsv.arg("-metric-label").arg(tops.sAxisName)
122
+ }
123
+ if (tops.valueName != undefined) {
124
+ transposeXsv = transposeXsv.arg("-value-label").arg(tops.valueName)
125
+ }
126
+ if (tops.separatorOverride != undefined) {
127
+ transposeXsv = transposeXsv.arg("-separator").arg(tops.separatorOverride)
128
+ }
129
+
130
+ transposeXsv = transposeXsv.
131
+ arg(xsvFileName).
132
+ arg(transposedFileName).
133
+ addFile(xsvFileName, xsvFile).
134
+ saveFile(transposedFileName).
135
+ run()
136
+
137
+ xsvFile = transposeXsv.getFile(transposedFileName)
138
+ }
139
+
140
+ importDirTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.import-dir")
141
+
142
+ pureSpec := util.purifySpec(spec)
143
+
144
+ pfconv := exec.builder().
145
+ software(pfconvSw).
146
+ printErrStreamToStdout().
147
+ inLightQueue().
148
+ arg("importCsv").
149
+ arg(xsvFileName).
150
+ arg("-p").arg("spec.json").
151
+ arg("-o").arg("out").
152
+ addFile(xsvFileName, xsvFile).
153
+ writeFile("spec.json", json.encode(pureSpec)).
154
+ processWorkdir("pf", importDirTpl, pureSpec).
155
+ run()
156
+
157
+ pf := pfconv.getProcessorResult("pf")
158
+ if ops.dataOnly {
159
+ return pf
160
+ }
161
+
162
+ axesSpec := getAxesSpec(spec)
163
+
164
+ result := {}
165
+ for col in spec.columns {
166
+ id := util.xsvColumnId(col)
167
+
168
+ if ops.splitDataAndSpec {
169
+ result[id] = {
170
+ data: pf.getFutureInputField(id),
171
+ spec: getColumnSpec(axesSpec, col)
172
+ }
173
+ } else {
174
+ result[id + ".data"] = pf.getFutureInputField(id)
175
+ result[id + ".spec"] = getColumnSpec(axesSpec, col)
176
+ }
177
+ }
178
+
179
+ return result
180
+ }
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
220
210
  importFileMap := func(xsvMap, xsvType, spec, ...ops) {
221
211
 
222
- importXsvMapTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.xsv-import-map")
223
-
224
- ops := renderOps({
225
- dataOnly: false,
226
- splitDataAndSpec: false,
227
- additionalAxesSpec: [],
228
- transpose: undefined
229
- }, ops...)
230
-
231
- // spec without any metadata (for caching purposes)
232
- decomposedSpec := util.decomposePfconvImportCfg(spec, { additionalAxesSpec: ops.additionalAxesSpec })
233
- pureSpec := decomposedSpec.purifiedCfg
234
- columnsSpec := decomposedSpec.columnsSpec
235
-
236
- r := render.createEphemeral(importXsvMapTpl, {
237
- xsvMap: xsvMap,
238
- xsvType: xsvType,
239
- spec: pureSpec,
240
- ops: { dataOnly: true, transpose: ops.transpose }
241
- })
242
-
243
- if ops.dataOnly && ops.splitDataAndSpec {
244
- ll.panic("Can't use both options dataOnly and splitDataAndSpec at the same time.")
245
- }
246
-
247
- result := {}
248
- axesSpec := getAxesSpec(spec)
249
- for c in spec.columns {
250
- id := util.xsvColumnId(c)
251
- if ops.dataOnly {
252
- result[id] = r.output(id)
253
- } else if ops.splitDataAndSpec {
254
- result[id] = {
255
- data: r.output(id),
256
- spec: columnsSpec[id]
257
- }
258
- } else {
259
- result[id + ".data"] = r.output(id)
260
- result[id + ".spec"] = columnsSpec[id]
261
- }
262
- }
263
-
264
- return result
265
- }
266
-
267
- /**
268
- * Export p-frame into xsv file
269
- *
270
- * @param pf: p-frame - a list of p-columns ({data, spec}) or a frame-like map of col.data col.spec entries
271
- * @param xsvType: string - "csv" or "tsv"
272
- * @param params: map - export params
273
- */
212
+ importXsvMapTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.xsv-import-map")
213
+
214
+ ops := renderOps({
215
+ dataOnly: false,
216
+ splitDataAndSpec: false,
217
+ additionalAxesSpec: [],
218
+ transpose: undefined
219
+ }, ops...)
220
+
221
+ decomposedSpec := util.decomposePfconvImportCfg(spec, { additionalAxesSpec: ops.additionalAxesSpec })
222
+ pureSpec := decomposedSpec.purifiedCfg
223
+ columnsSpec := decomposedSpec.columnsSpec
224
+
225
+ r := render.createEphemeral(importXsvMapTpl, {
226
+ xsvMap: xsvMap,
227
+ xsvType: xsvType,
228
+ spec: pureSpec,
229
+ ops: { dataOnly: true, transpose: ops.transpose }
230
+ })
231
+
232
+ if ops.dataOnly && ops.splitDataAndSpec {
233
+ ll.panic("Can't use both options dataOnly and splitDataAndSpec at the same time.")
234
+ }
235
+
236
+ result := {}
237
+ axesSpec := getAxesSpec(spec)
238
+ for c in spec.columns {
239
+ id := util.xsvColumnId(c)
240
+ if ops.dataOnly {
241
+ result[id] = r.output(id)
242
+ } else if ops.splitDataAndSpec {
243
+ result[id] = {
244
+ data: r.output(id),
245
+ spec: columnsSpec[id]
246
+ }
247
+ } else {
248
+ result[id + ".data"] = r.output(id)
249
+ result[id + ".spec"] = columnsSpec[id]
250
+ }
251
+ }
252
+
253
+ return result
254
+ }
255
+
256
+
257
+
258
+
259
+
260
+
261
+
274
262
  exportFrame := func(pf, xsvType, params) {
275
- exportPfTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.xsv-export-pframe")
276
-
277
- if is_array(pf) {
278
- // transform into .data .spec map
279
-
280
- pfm := {}
281
- i := 0
282
- for col in pf {
283
- ll.assert(!is_undefined(col.spec), "expected array of {spec, data} maps as a list of columns, but spec is undefined for: ", col)
284
- ll.assert(!is_undefined(col.data), "expected array of {spec, data} maps as a list of columns, but data is undefined for: ", col)
285
- pfm["" + i + ".spec"] = col.spec
286
- pfm["" + i + ".data"] = col.data
287
- i = i + 1
288
- }
289
- pf = pfm
290
- }
291
-
292
- r := render.create(exportPfTpl, {
293
- pf: pf,
294
- xsvType: xsvType,
295
- params: params
296
- })
297
-
298
- return r.output("result")
263
+ exportPfTpl := assets.importTemplate("@platforma-sdk/workflow-tengo:pframes.xsv-export-pframe")
264
+
265
+ if is_array(pf) {
266
+
267
+ pfm := {}
268
+ i := 0
269
+ for col in pf {
270
+ ll.assert(!is_undefined(col.spec), "expected array of {spec, data} maps as a list of columns, but spec is undefined for: ", col)
271
+ ll.assert(!is_undefined(col.data), "expected array of {spec, data} maps as a list of columns, but data is undefined for: ", col)
272
+ pfm["" + i + ".spec"] = col.spec
273
+ pfm["" + i + ".data"] = col.data
274
+ i = i + 1
275
+ }
276
+ pf = pfm
277
+ }
278
+
279
+ r := render.create(exportPfTpl, {
280
+ pf: pf,
281
+ xsvType: xsvType,
282
+ params: params
283
+ })
284
+
285
+ return r.output("result")
299
286
  }
300
287
 
301
288
  export ll.toStrict({
302
- importFile: importFile,
303
- importFileMap: importFileMap,
304
- exportFrame: exportFrame
289
+ importFile: importFile,
290
+ importFileMap: importFileMap,
291
+ exportFrame: exportFrame
305
292
  })