@platforma-sdk/workflow-tengo 5.17.0 → 5.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/tengo/lib/pframes.spec.lib.tengo +12 -1
  2. package/dist/tengo/lib/pframes.table-builder.lib.tengo +112 -19
  3. package/dist/tengo/lib/pt.lib.tengo +31 -0
  4. package/dist/tengo/tpl/annotations.compute.plj.gz +0 -0
  5. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  6. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  7. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  8. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  9. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  10. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  11. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  12. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  13. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  14. package/dist/tengo/tpl/exec.conda.create-env.plj.gz +0 -0
  15. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  16. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  17. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  18. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  19. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  22. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  23. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  24. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  25. package/dist/tengo/tpl/pframes.build-table.plj.gz +0 -0
  26. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  27. package/dist/tengo/tpl/pframes.export-parquet-pcolumn-chunk.plj.gz +0 -0
  28. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  29. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  30. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  31. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  32. package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
  33. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  34. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  35. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  36. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  37. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  38. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  39. package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
  40. package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
  41. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  42. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  43. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  44. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  45. package/dist/tengo/tpl/workflow.query-context-filter.plj.gz +0 -0
  46. package/package.json +3 -3
@@ -70,6 +70,8 @@ D_BLOCK := "pl7.app/block"
70
70
 
71
71
  A_LABEL := "pl7.app/label"
72
72
 
73
+ A_IS_LINKER_COLUMN := "pl7.app/isLinkerColumn"
74
+
73
75
 
74
76
 
75
77
 
@@ -424,8 +426,17 @@ createSpecDistiller := func(specs) {
424
426
  distillEntity := func(entity, entityName) {
425
427
  result := maps.clone(entity)
426
428
 
429
+
430
+
427
431
  if !is_undefined(result.annotations) {
428
- delete(result, "annotations")
432
+ linkerVal := result.annotations[A_IS_LINKER_COLUMN]
433
+ if is_undefined(linkerVal) {
434
+ delete(result, "annotations")
435
+ } else {
436
+ keptAnnotations := {}
437
+ keptAnnotations[A_IS_LINKER_COLUMN] = linkerVal
438
+ result.annotations = keptAnnotations
439
+ }
429
440
  }
430
441
 
431
442
 
@@ -28,6 +28,7 @@
28
28
 
29
29
 
30
30
  ll := import("@platforma-sdk/workflow-tengo:ll")
31
+ json := import("json")
31
32
  render := import("@platforma-sdk/workflow-tengo:render")
32
33
  assets := import("@platforma-sdk/workflow-tengo:assets")
33
34
  maps := import("@platforma-sdk/workflow-tengo:maps")
@@ -82,6 +83,42 @@ isPrimaryRef := func(value) {
82
83
  return ll.isMap(value) && value.__isPrimaryRef == "v1"
83
84
  }
84
85
 
86
+ isEnrichmentRef := func(value) {
87
+ return ll.isMap(value) && value.__isEnrichment == "v1"
88
+ }
89
+
90
+
91
+
92
+ isLabeledEnrichment := func(value) {
93
+ return ll.isMap(value) &&
94
+ is_string(value.label) &&
95
+ isEnrichmentRef(value.ref)
96
+ }
97
+
98
+ decodeGlobalPObjectId := func(id) {
99
+ ll.assert(is_string(id),
100
+ "expected PObjectId string, got %v", id)
101
+ decoded := json.decode(id)
102
+ ll.assert(ll.isMap(decoded) && is_string(decoded.blockId) && is_string(decoded.name),
103
+ "EnrichmentRef id is not a global PlRef; local-form ids must be " +
104
+ "pre-resolved to {spec, data} on the model side. Got: %v", decoded)
105
+ return { __isRef: true, blockId: decoded.blockId, name: decoded.name }
106
+ }
107
+
108
+
109
+ enrichmentStepColumn := func(step) {
110
+ ll.assert(step.type == "linker",
111
+ "unsupported enrichment step type %q (only \"linker\" is allowed)", step.type)
112
+ ll.assert(!is_undefined(step.linker),
113
+ "linker step missing 'linker' field: %v", step)
114
+ return step.linker
115
+ }
116
+
117
+
118
+ isQuerySpec := func(q) {
119
+ return !isUnresolved(q) && !isResolvedColumn(q) && !isEnrichmentRef(q)
120
+ }
121
+
85
122
 
86
123
 
87
124
 
@@ -163,7 +200,7 @@ tableBuilder := func(format, ...ctxArg) {
163
200
  if len(opts) > 0 && ll.isMap(opts[0]) {
164
201
  header = opts[0].header
165
202
  }
166
- if isUnresolved(query) {
203
+ if isUnresolved(query) || isEnrichmentRef(query) {
167
204
  _hasUnresolved = true
168
205
  }
169
206
  _columns = append(_columns, {
@@ -191,21 +228,39 @@ tableBuilder := func(format, ...ctxArg) {
191
228
  }
192
229
 
193
230
 
231
+
194
232
  if is_array(query) {
195
233
  for col in query {
196
- ll.assert(isResolvedColumn(col),
197
- "array elements must be resolved columns {spec, data}")
234
+ ll.assert(isResolvedColumn(col) || isEnrichmentRef(col) || isLabeledEnrichment(col),
235
+ "array elements must be resolved columns {spec, data}, EnrichmentRefs, " +
236
+ "or labeled enrichments {ref, label}; got: %v", col)
237
+
238
+ entryQuery := col
239
+ entryHeader := undefined
240
+ entryPrefix := headerPrefix
241
+ entrySuffix := headerSuffix
242
+ if isLabeledEnrichment(col) {
243
+ entryQuery = col.ref
244
+ entryHeader = col.label
245
+ entryPrefix = undefined
246
+ entrySuffix = undefined
247
+ }
248
+
249
+ if isUnresolved(entryQuery) || isEnrichmentRef(entryQuery) {
250
+ _hasUnresolved = true
251
+ }
198
252
  _columns = append(_columns, {
199
- query: col,
200
- headerPrefix: headerPrefix,
201
- headerSuffix: headerSuffix,
253
+ query: entryQuery,
254
+ header: entryHeader,
255
+ headerPrefix: entryPrefix,
256
+ headerSuffix: entrySuffix,
202
257
  mode: "multi"
203
258
  })
204
259
  }
205
260
  return self
206
261
  }
207
262
 
208
- if isUnresolved(query) {
263
+ if isUnresolved(query) || isEnrichmentRef(query) {
209
264
  _hasUnresolved = true
210
265
  }
211
266
  _columns = append(_columns, {
@@ -273,9 +328,6 @@ tableBuilder := func(format, ...ctxArg) {
273
328
 
274
329
 
275
330
 
276
-
277
-
278
-
279
331
  cacheInputs: func(time) {
280
332
  ll.assert(is_int(time),
281
333
  "time must be an integer duration " +
@@ -296,7 +348,7 @@ tableBuilder := func(format, ...ctxArg) {
296
348
 
297
349
  hasQuerySpec := false
298
350
  for _, c in _columns {
299
- if !isUnresolved(c.query) && !isResolvedColumn(c.query) {
351
+ if isQuerySpec(c.query) {
300
352
  hasQuerySpec = true
301
353
  break
302
354
  }
@@ -308,7 +360,16 @@ tableBuilder := func(format, ...ctxArg) {
308
360
  }
309
361
 
310
362
 
363
+
311
364
  resolveColumn := func(value) {
365
+ if is_string(value) {
366
+ ref := decodeGlobalPObjectId(value)
367
+ r := bquery.resolve(ref, _ctx)
368
+ return {
369
+ spec: r.getFutureInputField("spec"),
370
+ data: r.getFutureInputField("data")
371
+ }
372
+ }
312
373
  if isUnresolved(value) {
313
374
  r := bquery.resolve(value, _ctx)
314
375
  return {
@@ -323,8 +384,6 @@ tableBuilder := func(format, ...ctxArg) {
323
384
 
324
385
 
325
386
 
326
-
327
-
328
387
  primaryEntries := []
329
388
  primaryPlRefs := {}
330
389
  for _, p in _primaries {
@@ -363,13 +422,11 @@ tableBuilder := func(format, ...ctxArg) {
363
422
 
364
423
 
365
424
 
366
-
367
-
368
425
  singleQueryByIdx := {}
369
426
  multiQueryResultByIdx := {}
370
427
  qMap := {}
371
428
  for idx, c in _columns {
372
- if !isUnresolved(c.query) && !isResolvedColumn(c.query) {
429
+ if isQuerySpec(c.query) {
373
430
  strategy := "expectSingle"
374
431
  if c.mode == "multi" { strategy = "expectMultiple" }
375
432
  qMap["q" + string(idx)] = maps.deepMerge(c.query, {
@@ -384,7 +441,7 @@ tableBuilder := func(format, ...ctxArg) {
384
441
 
385
442
  qResult := bquery.anchoredQuery(_ctx, primaryPlRefs, qMap)
386
443
  for idx, c in _columns {
387
- if !isUnresolved(c.query) && !isResolvedColumn(c.query) {
444
+ if isQuerySpec(c.query) {
388
445
  r := qResult.getResult("q" + string(idx))
389
446
  if c.mode == "multi" {
390
447
 
@@ -402,6 +459,7 @@ tableBuilder := func(format, ...ctxArg) {
402
459
 
403
460
 
404
461
 
462
+
405
463
  columnEntries := []
406
464
  for idx, c in _columns {
407
465
  entry := {
@@ -410,7 +468,26 @@ tableBuilder := func(format, ...ctxArg) {
410
468
  headerPrefix: c.headerPrefix,
411
469
  headerSuffix: c.headerSuffix
412
470
  }
413
- if isResolvedColumn(c.query) {
471
+ if isEnrichmentRef(c.query) {
472
+ resolvedHit := resolveColumn(c.query.hit)
473
+ entry.spec = resolvedHit.spec
474
+ entry.data = resolvedHit.data
475
+ steps := []
476
+ if !is_undefined(c.query.path) {
477
+ for _, step in c.query.path {
478
+ resolvedStep := resolveColumn(enrichmentStepColumn(step))
479
+ steps = append(steps, {
480
+ type: step.type,
481
+ spec: resolvedStep.spec,
482
+ data: resolvedStep.data
483
+ })
484
+ }
485
+ }
486
+ entry.path = steps
487
+ if !is_undefined(c.query.qualifications) && len(c.query.qualifications) > 0 {
488
+ entry.qualifications = c.query.qualifications
489
+ }
490
+ } else if isResolvedColumn(c.query) {
414
491
  entry.spec = c.query.spec
415
492
  entry.data = c.query.data
416
493
  } else if isUnresolved(c.query) {
@@ -431,7 +508,6 @@ tableBuilder := func(format, ...ctxArg) {
431
508
 
432
509
 
433
510
 
434
-
435
511
  primariesMap := {}
436
512
  for idx, p in primaryEntries {
437
513
  entry := {
@@ -461,6 +537,23 @@ tableBuilder := func(format, ...ctxArg) {
461
537
  entry.spec = c.spec
462
538
  entry.data = c.data
463
539
  }
540
+ if !is_undefined(c.path) && len(c.path) > 0 {
541
+
542
+
543
+ steps := {}
544
+ for stepIdx, step in c.path {
545
+ steps[string(stepIdx)] = {
546
+ type: step.type,
547
+ spec: step.spec,
548
+ data: step.data
549
+ }
550
+ }
551
+ entry.path = steps
552
+ entry.pathLength = len(c.path)
553
+ }
554
+ if !is_undefined(c.qualifications) && len(c.qualifications) > 0 {
555
+ entry.qualifications = c.qualifications
556
+ }
464
557
  if !is_undefined(c.header) { entry.header = c.header }
465
558
  if !is_undefined(c.headerPrefix) { entry.headerPrefix = c.headerPrefix }
466
559
  if !is_undefined(c.headerSuffix) { entry.headerSuffix = c.headerSuffix }
@@ -278,12 +278,43 @@ p := ll.toStrict({
278
278
  ll.assert(ll.isMap(linkerQuery) && linkerQuery.type == "column",
279
279
  "linkerJoin: linker entry must be a plain p.column(...) result, got: %v", linkerQuery)
280
280
 
281
+
282
+
283
+ linkerSpec := linkerColumnEntry._getColumnsMap()[linkerQuery.column].spec
284
+ if ll.isMap(linkerSpec) {
285
+ annotations := linkerSpec.annotations
286
+ isLinker := ll.isMap(annotations) && annotations[pframesSpec.A_IS_LINKER_COLUMN] == "true"
287
+ ll.assert(isLinker,
288
+ "linkerJoin: linker column %q must carry annotation %q == \"true\", got spec: %v",
289
+ linkerQuery.column, pframesSpec.A_IS_LINKER_COLUMN, linkerSpec)
290
+ }
291
+
281
292
  merged := _mergePEntries([linkerColumnEntry, secondaryEntry])
282
293
  return _newPEntry(merged.columns, {
283
294
  type: "linkerJoin",
284
295
  linker: { column: linkerQuery.column },
285
296
  secondary: [_asJoinEntry(merged.specQueries[1])]
286
297
  })
298
+ },
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+ _rawQueryEntry: func(columnsByName, joinEntry) {
311
+ ll.assert(ll.isMap(columnsByName), "columnsByName must be a map")
312
+ ll.assert(ll.isMap(joinEntry) && !is_undefined(joinEntry.entry),
313
+ "joinEntry must be a SpecQueryJoinEntry { entry, qualifications? }, got: %v", joinEntry)
314
+ for name, info in columnsByName {
315
+ _validateColumn(name, info)
316
+ }
317
+ return _newPEntry(columnsByName, joinEntry.entry)
287
318
  }
288
319
  })
289
320
 
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/workflow-tengo",
3
- "version": "5.17.0",
3
+ "version": "5.19.0",
4
4
  "description": "Tengo SDK library",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -18,11 +18,11 @@
18
18
  "dependencies": {
19
19
  "@milaboratories/software-pframes-conv": "2.2.9",
20
20
  "@platforma-open/milaboratories.software-small-binaries": "^2.0.3",
21
- "@platforma-open/milaboratories.software-ptabler": "1.16.0",
21
+ "@platforma-open/milaboratories.software-ptabler": "1.16.1",
22
22
  "@platforma-open/milaboratories.software-ptexter": "1.2.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@platforma-sdk/tengo-builder": "2.5.18"
25
+ "@platforma-sdk/tengo-builder": "2.5.20"
26
26
  },
27
27
  "scripts": {
28
28
  "type-check": "pl-tengo check",