@platforma-sdk/workflow-tengo 2.9.6 → 2.9.8

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