@milaboratories/pl-middle-layer 1.36.4 → 1.37.1

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 (44) hide show
  1. package/dist/index.js +19 -19
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +2031 -1918
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/js_render/computable_context.d.ts +68 -0
  6. package/dist/js_render/computable_context.d.ts.map +1 -0
  7. package/dist/js_render/context.d.ts +22 -64
  8. package/dist/js_render/context.d.ts.map +1 -1
  9. package/dist/js_render/index.d.ts +2 -0
  10. package/dist/js_render/index.d.ts.map +1 -1
  11. package/dist/middle_layer/block.d.ts.map +1 -1
  12. package/dist/middle_layer/block_ctx.d.ts +5 -0
  13. package/dist/middle_layer/block_ctx.d.ts.map +1 -1
  14. package/dist/middle_layer/middle_layer.d.ts +2 -0
  15. package/dist/middle_layer/middle_layer.d.ts.map +1 -1
  16. package/dist/middle_layer/project.d.ts.map +1 -1
  17. package/dist/middle_layer/project_overview.d.ts.map +1 -1
  18. package/dist/middle_layer/util.d.ts +2 -0
  19. package/dist/middle_layer/util.d.ts.map +1 -1
  20. package/dist/model/args.d.ts +4 -2
  21. package/dist/model/args.d.ts.map +1 -1
  22. package/dist/model/project_helper.d.ts +14 -0
  23. package/dist/model/project_helper.d.ts.map +1 -0
  24. package/dist/model/project_model_util.d.ts +14 -4
  25. package/dist/model/project_model_util.d.ts.map +1 -1
  26. package/dist/mutator/project.d.ts +16 -10
  27. package/dist/mutator/project.d.ts.map +1 -1
  28. package/package.json +14 -14
  29. package/src/js_render/computable_context.ts +753 -0
  30. package/src/js_render/context.ts +32 -720
  31. package/src/js_render/index.ts +37 -3
  32. package/src/middle_layer/block.ts +2 -0
  33. package/src/middle_layer/block_ctx.ts +6 -0
  34. package/src/middle_layer/middle_layer.ts +7 -2
  35. package/src/middle_layer/project.ts +15 -17
  36. package/src/middle_layer/project_overview.ts +13 -4
  37. package/src/middle_layer/util.ts +3 -1
  38. package/src/model/args.ts +12 -6
  39. package/src/model/project_helper.ts +41 -0
  40. package/src/model/project_model_util.test.ts +13 -4
  41. package/src/model/project_model_util.ts +37 -12
  42. package/src/mutator/project.test.ts +18 -12
  43. package/src/mutator/project.ts +159 -61
  44. package/src/mutator/template/template_render.test.ts +2 -2
@@ -1,45 +1,16 @@
1
1
  import type { ComputableCtx } from '@milaboratories/computable';
2
- import { Computable } from '@milaboratories/computable';
3
- import type { PlTreeNodeAccessor } from '@milaboratories/pl-tree';
4
- import type {
5
- ArchiveFormat,
6
- CommonFieldTraverseOps as CommonFieldTraverseOpsFromSDK,
7
- DataInfo,
8
- FieldTraversalStep as FieldTraversalStepFromSDK,
9
- Option,
10
- PColumn,
11
- PColumnValues,
12
- PFrameDef,
13
- PFrameHandle,
14
- PObject,
15
- PObjectSpec,
16
- PSpecPredicate,
17
- PTableDef,
18
- PTableHandle,
19
- ResourceType as ResourceTypeFromSDK,
20
- ResultCollection,
21
- ValueOrError,
22
- } from '@platforma-sdk/model';
23
2
  import {
24
- isDataInfo,
25
3
  JsRenderInternal,
26
- mapDataInfo,
27
- mapPObjectData,
28
- mapPTableDef,
29
- mapValueInVOE,
30
4
  } from '@platforma-sdk/model';
31
5
  import { notEmpty } from '@milaboratories/ts-helpers';
32
6
  import { randomUUID } from 'node:crypto';
33
- import type { QuickJSContext, QuickJSHandle, VmFunctionImplementation } from 'quickjs-emscripten';
7
+ import type { QuickJSContext, QuickJSHandle } from 'quickjs-emscripten';
34
8
  import { Scope, errors } from 'quickjs-emscripten';
35
- import type { Optional } from 'utility-types';
36
9
  import type { BlockContextAny } from '../middle_layer/block_ctx';
37
10
  import type { MiddleLayerEnvironment } from '../middle_layer/middle_layer';
38
- import type { Block } from '../model/project_model';
39
- import { parseFinalPObjectCollection } from '../pool/p_object_collection';
40
- import type { ResultPool } from '../pool/result_pool';
41
11
  import { stringifyWithResourceId } from '@milaboratories/pl-client';
42
12
  import { PlQuickJSError } from '@milaboratories/pl-errors';
13
+ import { ComputableContextHelper } from './computable_context';
43
14
 
44
15
  export type DeadlineSettings = {
45
16
  currentExecutionTarget: string;
@@ -56,34 +27,34 @@ function isArrayBufferOrView(obj: unknown): obj is ArrayBufferLike {
56
27
  return obj instanceof ArrayBuffer || ArrayBuffer.isView(obj);
57
28
  }
58
29
 
59
- function bytesToBase64(data: Uint8Array | undefined): string | undefined {
60
- return data !== undefined ? Buffer.from(data).toString('base64') : undefined;
61
- }
30
+ /**
31
+ * Contains references to objects needed to execute lambda within computable,
32
+ * providing access to:
33
+ * - block context
34
+ * - computable context
35
+ * - middle layer environment
36
+ * */
37
+ export type ComputableEnv = {
38
+ readonly blockCtx: BlockContextAny;
39
+ readonly mlEnv: MiddleLayerEnvironment;
40
+ computableCtx: ComputableCtx;
41
+ };
62
42
 
63
- export class JsExecutionContext
64
- implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
43
+ export class JsExecutionContext {
65
44
  private readonly callbackRegistry: QuickJSHandle;
66
45
  private readonly fnJSONStringify: QuickJSHandle;
67
46
  private readonly fnJSONParse: QuickJSHandle;
68
47
 
69
- public readonly computablesToResolve: Record<string, Computable<unknown>> = {};
48
+ public readonly errorRepo = new ErrorRepository();
70
49
 
71
- private computableCtx: ComputableCtx | undefined;
72
- private readonly accessors = new Map<string, PlTreeNodeAccessor | undefined>();
73
-
74
- private readonly meta: Map<string, Block>;
75
-
76
- private readonly errorRepo = new ErrorRepository();
50
+ public readonly computableHelper: ComputableContextHelper | undefined;
77
51
 
78
52
  constructor(
79
- private readonly scope: Scope,
80
- private readonly vm: QuickJSContext,
81
- private readonly blockCtx: BlockContextAny,
82
- private readonly env: MiddleLayerEnvironment,
53
+ public readonly scope: Scope,
54
+ public readonly vm: QuickJSContext,
83
55
  private readonly deadlineSetter: DeadlineSetter,
84
- computableCtx: ComputableCtx,
56
+ computableEnv?: ComputableEnv,
85
57
  ) {
86
- this.computableCtx = computableCtx;
87
58
  this.callbackRegistry = this.scope.manage(this.vm.newObject());
88
59
 
89
60
  this.fnJSONStringify = scope.manage(
@@ -97,14 +68,14 @@ implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
97
68
  );
98
69
  if (vm.typeof(this.fnJSONParse) !== 'function') throw new Error(`JSON.parse() not found.`);
99
70
 
100
- this.meta = blockCtx.blockMeta(computableCtx);
71
+ if (computableEnv !== undefined)
72
+ this.computableHelper = new ComputableContextHelper(this, computableEnv.blockCtx, computableEnv.mlEnv, computableEnv.computableCtx);
101
73
 
102
74
  this.injectCtx();
103
75
  }
104
76
 
105
77
  public resetComputableCtx() {
106
- this.computableCtx = undefined;
107
- this.accessors.clear();
78
+ notEmpty(this.computableHelper, 'Computable context helper is not initialized').resetComputableCtx();
108
79
  }
109
80
 
110
81
  private static cleanErrorContext(error: unknown): void {
@@ -151,389 +122,11 @@ implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
151
122
  }
152
123
  }
153
124
 
154
- //
155
- // Methods for injected ctx object
156
- //
157
-
158
- getAccessorHandleByName(name: string): string | undefined {
159
- if (this.computableCtx === undefined)
160
- throw new Error('Accessors can\'t be used in this context');
161
- const wellKnownAccessor = (name: string, ctxKey: 'staging' | 'prod'): string | undefined => {
162
- if (!this.accessors.has(name)) {
163
- const lambda = this.blockCtx[ctxKey];
164
- if (lambda === undefined) throw new Error('Staging context not available');
165
- const entry = lambda(this.computableCtx!);
166
- if (!entry) this.accessors.set(name, undefined);
167
- else
168
- this.accessors.set(name, this.computableCtx!.accessor(entry).node({ ignoreError: true }));
169
- }
170
- return this.accessors.get(name) ? name : undefined;
171
- };
172
- if (name === 'staging') return wellKnownAccessor('staging', 'staging');
173
- else if (name === 'main') return wellKnownAccessor('main', 'prod');
174
- return undefined;
175
- }
176
-
177
- //
178
- // Accessors
179
- //
180
-
181
- resolveWithCommon(
182
- handle: string,
183
- commonOptions: CommonFieldTraverseOpsFromSDK,
184
- ...steps: (FieldTraversalStepFromSDK | string)[]
185
- ): string | undefined {
186
- return this.wrapAccessor(this.getAccessor(handle).traverseWithCommon(commonOptions, ...steps));
187
- }
188
-
189
- getResourceType(handle: string): ResourceTypeFromSDK {
190
- return this.getAccessor(handle).resourceType;
191
- }
192
-
193
- getInputsLocked(handle: string): boolean {
194
- return this.getAccessor(handle).getInputsLocked();
195
- }
196
-
197
- getOutputsLocked(handle: string): boolean {
198
- return this.getAccessor(handle).getOutputsLocked();
199
- }
200
-
201
- getIsReadyOrError(handle: string): boolean {
202
- return this.getAccessor(handle).getIsReadyOrError();
203
- }
204
-
205
- getIsFinal(handle: string): boolean {
206
- return this.getAccessor(handle).getIsFinal();
207
- }
208
-
209
- getError(handle: string): string | undefined {
210
- return this.wrapAccessor(this.getAccessor(handle).getError());
211
- }
212
-
213
- listInputFields(handle: string): string[] {
214
- return this.getAccessor(handle).listInputFields();
215
- }
216
-
217
- listOutputFields(handle: string): string[] {
218
- return this.getAccessor(handle).listOutputFields();
219
- }
220
-
221
- listDynamicFields(handle: string): string[] {
222
- return this.getAccessor(handle).listDynamicFields();
223
- }
224
-
225
- getKeyValueBase64(handle: string, key: string): string | undefined {
226
- return bytesToBase64(this.getAccessor(handle).getKeyValue(key));
227
- }
228
-
229
- getKeyValueAsString(handle: string, key: string): string | undefined {
230
- return this.getAccessor(handle).getKeyValueAsString(key);
231
- }
232
-
233
- getDataBase64(handle: string): string | undefined {
234
- return bytesToBase64(this.getAccessor(handle).getData());
235
- }
236
-
237
- getDataAsString(handle: string): string | undefined {
238
- return this.getAccessor(handle).getDataAsString();
239
- }
240
-
241
- //
242
- // Accessor helpers
243
- //
244
-
245
- parsePObjectCollection(
246
- handle: string,
247
- errorOnUnknownField: boolean,
248
- prefix: string,
249
- ...resolveSteps: string[]
250
- ): Record<string, PObject<string>> | undefined {
251
- const acc = this.getAccessor(handle);
252
- if (!acc.getIsReadyOrError()) return undefined;
253
- const accResult = parseFinalPObjectCollection(acc, errorOnUnknownField, prefix, resolveSteps);
254
- const result: Record<string, PObject<string>> = {};
255
- for (const [key, obj] of Object.entries(accResult)) {
256
- result[key] = mapPObjectData(obj, (d) => this.wrapAccessor(d));
257
- }
258
- return result;
259
- }
260
-
261
- //
262
- // Blobs
263
- //
264
-
265
- private registerComputable(hPrefix: string, computable: Computable<unknown>): string {
266
- const fHandle = `${hPrefix}_${randomUUID()}`;
267
- this.computablesToResolve[fHandle] = computable;
268
- return fHandle;
269
- }
270
-
271
- public getBlobContentAsString(handle: string): string {
272
- const resourceInfo = this.getAccessor(handle).resourceInfo;
273
- return this.registerComputable(
274
- 'getBlobContentAsString',
275
- Computable.make((ctx) => this.env.driverKit.blobDriver.getDownloadedBlob(resourceInfo, ctx), {
276
- postprocessValue: async (value) => {
277
- if (value === undefined) return undefined;
278
- return Buffer.from(await this.env.driverKit.blobDriver.getContent(value.handle)).toString(
279
- 'utf-8',
280
- );
281
- },
282
- }),
283
- );
284
- }
285
-
286
- public getBlobContentAsBase64(handle: string): string {
287
- const resourceInfo = this.getAccessor(handle).resourceInfo;
288
- return this.registerComputable(
289
- 'getBlobContentAsBase64',
290
- Computable.make((ctx) => this.env.driverKit.blobDriver.getDownloadedBlob(resourceInfo, ctx), {
291
- postprocessValue: async (value) => {
292
- if (value === undefined) return undefined;
293
- return Buffer.from(await this.env.driverKit.blobDriver.getContent(value.handle)).toString(
294
- 'base64',
295
- );
296
- },
297
- }),
298
- );
299
- }
300
-
301
- public getDownloadedBlobContentHandle(handle: string): string {
302
- const resourceInfo = this.getAccessor(handle).resourceInfo;
303
- return this.registerComputable(
304
- 'getDownloadedBlobContentHandle',
305
- this.env.driverKit.blobDriver.getDownloadedBlob(resourceInfo),
306
- );
307
- }
308
-
309
- public getOnDemandBlobContentHandle(handle: string): string {
310
- const resource = this.getAccessor(handle).persist();
311
- return this.registerComputable(
312
- 'getOnDemandBlobContentHandle',
313
- this.env.driverKit.blobDriver.getOnDemandBlob(resource),
314
- );
315
- }
316
-
317
- //
318
- // Blobs to URLs
319
- //
320
-
321
- public extractArchiveAndGetURL(handle: string, format: ArchiveFormat): string {
322
- const resource = this.getAccessor(handle).persist();
323
- return this.registerComputable(
324
- 'extractArchiveAndGetURL',
325
- this.env.driverKit.blobToURLDriver.extractArchiveAndGetURL(resource, format),
326
- );
327
- }
328
-
329
- //
330
- // Import progress
331
- //
332
-
333
- getImportProgress(handle: string): string {
334
- const resource = this.getAccessor(handle).persist();
335
- return this.registerComputable(
336
- 'getImportProgress',
337
- this.env.driverKit.uploadDriver.getProgressId(resource),
338
- );
339
- }
340
-
341
- //
342
- // Logs
343
- //
344
-
345
- getLastLogs(handle: string, nLines: number): string {
346
- const resource = this.getAccessor(handle).persist();
347
- return this.registerComputable(
348
- 'getLastLogs',
349
- this.env.driverKit.logDriver.getLastLogs(resource, nLines),
350
- );
351
- }
352
-
353
- getProgressLog(handle: string, patternToSearch: string): string {
354
- const resource = this.getAccessor(handle).persist();
355
- return this.registerComputable(
356
- 'getProgressLog',
357
- this.env.driverKit.logDriver.getProgressLog(resource, patternToSearch),
358
- );
359
- }
360
-
361
- getProgressLogWithInfo(handle: string, patternToSearch: string): string {
362
- const resource = this.getAccessor(handle).persist();
363
- return this.registerComputable(
364
- 'getProgressLogWithInfo',
365
- this.env.driverKit.logDriver.getProgressLogWithInfo(resource, patternToSearch),
366
- );
367
- }
368
-
369
- getLogHandle(handle: string): string {
370
- const resource = this.getAccessor(handle).persist();
371
- return this.registerComputable(
372
- 'getLogHandle',
373
- this.env.driverKit.logDriver.getLogHandle(resource),
374
- );
375
- }
376
-
377
- //
378
- // Blocks
379
- //
380
-
381
- public getBlockLabel(blockId: string): string {
382
- const b = this.meta.get(blockId);
383
- if (b === undefined) throw new Error(`Block ${blockId} not found.`);
384
- return b.label;
385
- }
386
-
387
- //
388
- // Result Pool
389
- //
390
-
391
- private _resultPool: ResultPool | undefined = undefined;
392
- private get resultPool(): ResultPool {
393
- if (this._resultPool === undefined) {
394
- if (this.computableCtx === undefined)
395
- throw new Error(
396
- 'can\'t use result pool in this context (most porbably called from the future mapper)',
397
- );
398
- this._resultPool = notEmpty(
399
- this.blockCtx.getResultsPool,
400
- 'getResultsPool',
401
- )(this.computableCtx);
402
- }
403
- return this._resultPool;
404
- }
405
-
406
- public calculateOptions(predicate: PSpecPredicate): Option[] {
407
- return this.resultPool.calculateOptions(predicate);
408
- }
409
-
410
- public getDataFromResultPool(): ResultCollection<PObject<string>> {
411
- const collection = this.resultPool.getData();
412
- if (collection.instabilityMarker !== undefined)
413
- this.computableCtx!.markUnstable(`incomplete_result_pool:${collection.instabilityMarker}`);
414
- return {
415
- isComplete: collection.isComplete,
416
- entries: collection.entries.map((e) => ({
417
- ref: e.ref,
418
- obj: mapPObjectData(e.obj, (d) => this.wrapAccessor(d)),
419
- })),
420
- };
421
- }
422
-
423
- public getDataWithErrorsFromResultPool(): ResultCollection<
424
- Optional<PObject<ValueOrError<string, Error>>, 'id'>
425
- > {
426
- const collection = this.resultPool.getDataWithErrors();
427
- if (collection.instabilityMarker !== undefined)
428
- this.computableCtx!.markUnstable(`incomplete_result_pool:${collection.instabilityMarker}`);
429
- return {
430
- isComplete: collection.isComplete,
431
- entries: collection.entries.map((e) => ({
432
- ref: e.ref,
433
- obj: {
434
- id: e.obj.id,
435
- spec: e.obj.spec,
436
- data: mapValueInVOE(e.obj.data, (d) => this.wrapAccessor(d)),
437
- },
438
- })),
439
- };
440
- }
441
-
442
- public getSpecsFromResultPool(): ResultCollection<PObjectSpec> {
443
- const specs = this.resultPool.getSpecs();
444
- if (specs.instabilityMarker !== undefined)
445
- this.computableCtx!.markUnstable(`specs_from_pool_incomplete:${specs.instabilityMarker}`);
446
- return specs;
447
- }
448
-
449
- getSpecFromResultPoolByRef(blockId: string, exportName: string): PObjectSpec | undefined {
450
- return this.resultPool.getSpecByRef(blockId, exportName);
451
- }
452
-
453
- getDataFromResultPoolByRef(blockId: string, exportName: string): PObject<string> | undefined {
454
- return mapPObjectData(this.resultPool.getDataByRef(blockId, exportName), (acc) =>
455
- this.wrapAccessor(acc),
456
- );
457
- }
458
-
459
- //
460
- // PFrames / PTables
461
- //
462
-
463
- public createPFrame(def: PFrameDef<string | PColumnValues | DataInfo<string>>): PFrameHandle {
464
- if (this.computableCtx === undefined)
465
- throw new Error(
466
- 'can\'t instantiate PFrames from this context (most porbably called from the future mapper)',
467
- );
468
- return this.env.driverKit.pFrameDriver.createPFrame(
469
- def.map((c) => mapPObjectData(c, (d) => this.transformInputPData(d))),
470
- this.computableCtx,
471
- );
472
- }
473
-
474
- public createPTable(def: PTableDef<PColumn<string | PColumnValues | DataInfo<string>>>): PTableHandle {
475
- if (this.computableCtx === undefined)
476
- throw new Error(
477
- 'can\'t instantiate PTable from this context (most porbably called from the future mapper)',
478
- );
479
- return this.env.driverKit.pFrameDriver.createPTable(
480
- mapPTableDef(def, (c) =>
481
- mapPObjectData(c, (d) => this.transformInputPData(d)),
482
- ),
483
- this.computableCtx,
484
- );
485
- }
486
-
487
- /**
488
- * Transforms input data for PFrame/PTable creation
489
- * - Converts string handles to accessors
490
- * - Maps accessors in DataInfo objects
491
- * - Passes through other values
492
- */
493
- private transformInputPData(d: string | PColumnValues | DataInfo<string>): PlTreeNodeAccessor | PColumnValues | DataInfo<PlTreeNodeAccessor> {
494
- if (typeof d === 'string') {
495
- return this.getAccessor(d);
496
- } else if (isDataInfo(d)) {
497
- return mapDataInfo(d, (a) => this.getAccessor(a));
498
- } else {
499
- return d;
500
- }
501
- }
502
-
503
- //
504
- // Computable
505
- //
506
-
507
- public getCurrentUnstableMarker(): string | undefined {
508
- return this.computableCtx?.unstableMarker;
509
- }
510
-
511
- //
512
- // Helpers
513
- //
514
-
515
- private getAccessor(handle: string): PlTreeNodeAccessor {
516
- const accessor = this.accessors.get(handle);
517
- if (accessor === undefined) throw new Error('No such accessor');
518
- return accessor;
519
- }
520
-
521
- private wrapAccessor(accessor: PlTreeNodeAccessor): string;
522
- private wrapAccessor(accessor: PlTreeNodeAccessor | undefined): string | undefined;
523
- private wrapAccessor(accessor: PlTreeNodeAccessor | undefined): string | undefined {
524
- if (accessor === undefined) return undefined;
525
- else {
526
- const nextHandle = randomUUID();
527
- this.accessors.set(nextHandle, accessor);
528
- return nextHandle;
529
- }
530
- }
531
-
532
125
  //
533
126
  // QuickJS Helpers
534
127
  //
535
128
 
536
- private exportSingleValue(
129
+ public exportSingleValue(
537
130
  obj: boolean | number | string | null | ArrayBuffer | undefined,
538
131
  scope: Scope | undefined,
539
132
  ): QuickJSHandle {
@@ -544,7 +137,7 @@ implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
544
137
  return result;
545
138
  }
546
139
 
547
- private tryExportSingleValue(obj: unknown, scope: Scope | undefined): QuickJSHandle | undefined {
140
+ public tryExportSingleValue(obj: unknown, scope: Scope | undefined): QuickJSHandle | undefined {
548
141
  let handle: QuickJSHandle;
549
142
  let manage = false;
550
143
  switch (typeof obj) {
@@ -619,16 +212,10 @@ implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
619
212
  Scope.withScope((localScope) => {
620
213
  const configCtx = localScope.manage(this.vm.newObject());
621
214
 
622
- // Exporting props
215
+ //
216
+ // Core props
217
+ //
623
218
 
624
- const args = this.blockCtx.args(this.computableCtx!);
625
- const activeArgs = this.blockCtx.activeArgs(this.computableCtx!);
626
- const uiState = this.blockCtx.uiState(this.computableCtx!);
627
- this.vm.setProp(configCtx, 'args', localScope.manage(this.vm.newString(args)));
628
- if (uiState !== undefined)
629
- this.vm.setProp(configCtx, 'uiState', localScope.manage(this.vm.newString(uiState)));
630
- if (activeArgs !== undefined)
631
- this.vm.setProp(configCtx, 'activeArgs', localScope.manage(this.vm.newString(activeArgs)));
632
219
  this.vm.setProp(configCtx, 'callbackRegistry', this.callbackRegistry);
633
220
  this.vm.setProp(
634
221
  configCtx,
@@ -636,292 +223,17 @@ implements JsRenderInternal.GlobalCfgRenderCtxMethods<string, string> {
636
223
  this.exportObjectUniversal(JsRenderInternal.GlobalCfgRenderCtxFeatureFlags, localScope),
637
224
  );
638
225
 
639
- // Exporting methods
640
-
641
- const exportCtxFunction = (
642
- name: string,
643
- fn: VmFunctionImplementation<QuickJSHandle>,
644
- ): void => {
645
- const withCachedError: VmFunctionImplementation<QuickJSHandle> = (...args) => {
646
- // QuickJS strips all fields from errors apart from 'name' and 'message'.
647
- // That's why here we need to store them, and rethrow them when we exit
648
- // from QuickJS code.
649
- try {
650
- return (fn as any)(...args);
651
- } catch (e: unknown) {
652
- const newErr = this.errorRepo.setAndRecreateForQuickJS(e);
653
- // eslint-disable-next-line @typescript-eslint/only-throw-error
654
- throw this.vm.newError(newErr);
655
- }
656
- };
657
-
658
- this.vm.newFunction(name, withCachedError).consume((fnh) => this.vm.setProp(configCtx, name, fnh));
659
- this.vm.newFunction(name, fn).consume((fnh) => this.vm.setProp(configCtx, name + '__internal__', fnh));
660
- };
661
-
662
226
  //
663
- // Methods for injected ctx object
227
+ // Injecting computable context helper methods if we are running in computable context
664
228
  //
665
229
 
666
- exportCtxFunction('getAccessorHandleByName', (name) => {
667
- return this.exportSingleValue(
668
- this.getAccessorHandleByName(this.vm.getString(name)),
669
- undefined,
670
- );
671
- });
230
+ if (this.computableHelper !== undefined)
231
+ this.computableHelper.injectCtx(configCtx);
672
232
 
673
233
  //
674
- // Accessors
234
+ // Creating global variable inside the vm
675
235
  //
676
236
 
677
- exportCtxFunction('resolveWithCommon', (handle, commonOptions, ...steps) => {
678
- return this.exportSingleValue(
679
- this.resolveWithCommon(
680
- this.vm.getString(handle),
681
- this.importObjectViaJson(commonOptions) as CommonFieldTraverseOpsFromSDK,
682
- ...steps.map(
683
- (step) => this.importObjectViaJson(step) as FieldTraversalStepFromSDK | string,
684
- ),
685
- ),
686
- undefined,
687
- );
688
- });
689
-
690
- exportCtxFunction('getResourceType', (handle) => {
691
- return this.exportObjectViaJson(this.getResourceType(this.vm.getString(handle)), undefined);
692
- });
693
-
694
- exportCtxFunction('getInputsLocked', (handle) => {
695
- return this.exportSingleValue(this.getInputsLocked(this.vm.getString(handle)), undefined);
696
- });
697
-
698
- exportCtxFunction('getOutputsLocked', (handle) => {
699
- return this.exportSingleValue(this.getOutputsLocked(this.vm.getString(handle)), undefined);
700
- });
701
-
702
- exportCtxFunction('getIsReadyOrError', (handle) => {
703
- return this.exportSingleValue(this.getIsReadyOrError(this.vm.getString(handle)), undefined);
704
- });
705
-
706
- exportCtxFunction('getIsFinal', (handle) => {
707
- return this.exportSingleValue(this.getIsFinal(this.vm.getString(handle)), undefined);
708
- });
709
-
710
- exportCtxFunction('getError', (handle) => {
711
- return this.exportSingleValue(this.getError(this.vm.getString(handle)), undefined);
712
- });
713
-
714
- exportCtxFunction('listInputFields', (handle) => {
715
- return this.exportObjectViaJson(this.listInputFields(this.vm.getString(handle)), undefined);
716
- });
717
-
718
- exportCtxFunction('listOutputFields', (handle) => {
719
- return this.exportObjectViaJson(this.listInputFields(this.vm.getString(handle)), undefined);
720
- });
721
-
722
- exportCtxFunction('listDynamicFields', (handle) => {
723
- return this.exportObjectViaJson(this.listInputFields(this.vm.getString(handle)), undefined);
724
- });
725
-
726
- exportCtxFunction('getKeyValueBase64', (handle, key) => {
727
- return this.exportSingleValue(
728
- this.getKeyValueBase64(this.vm.getString(handle), this.vm.getString(key)),
729
- undefined,
730
- );
731
- });
732
-
733
- exportCtxFunction('getKeyValueAsString', (handle, key) => {
734
- return this.exportSingleValue(
735
- this.getKeyValueAsString(this.vm.getString(handle), this.vm.getString(key)),
736
- undefined,
737
- );
738
- });
739
-
740
- exportCtxFunction('getDataBase64', (handle) => {
741
- return this.exportSingleValue(this.getDataBase64(this.vm.getString(handle)), undefined);
742
- });
743
-
744
- exportCtxFunction('getDataAsString', (handle) => {
745
- return this.exportSingleValue(this.getDataAsString(this.vm.getString(handle)), undefined);
746
- });
747
-
748
- //
749
- // Accessor helpers
750
- //
751
-
752
- exportCtxFunction(
753
- 'parsePObjectCollection',
754
- (handle, errorOnUnknownField, prefix, ...resolveSteps) => {
755
- return this.exportObjectUniversal(
756
- this.parsePObjectCollection(
757
- this.vm.getString(handle),
758
- this.vm.dump(errorOnUnknownField) as boolean,
759
- this.vm.getString(prefix),
760
- ...resolveSteps.map((stepHandle) => this.vm.getString(stepHandle)),
761
- ),
762
- undefined,
763
- );
764
- },
765
- );
766
-
767
- //
768
- // Blobs
769
- //
770
-
771
- exportCtxFunction('getBlobContentAsBase64', (handle) => {
772
- return this.exportSingleValue(
773
- this.getBlobContentAsBase64(this.vm.getString(handle)),
774
- undefined,
775
- );
776
- });
777
-
778
- exportCtxFunction('getBlobContentAsString', (handle) => {
779
- return this.exportSingleValue(
780
- this.getBlobContentAsString(this.vm.getString(handle)),
781
- undefined,
782
- );
783
- });
784
-
785
- exportCtxFunction('getDownloadedBlobContentHandle', (handle) => {
786
- return this.exportSingleValue(
787
- this.getDownloadedBlobContentHandle(this.vm.getString(handle)),
788
- undefined,
789
- );
790
- });
791
-
792
- exportCtxFunction('getOnDemandBlobContentHandle', (handle) => {
793
- return this.exportSingleValue(
794
- this.getOnDemandBlobContentHandle(this.vm.getString(handle)),
795
- undefined,
796
- );
797
- });
798
-
799
- //
800
- // Blobs to URLs
801
- //
802
-
803
- exportCtxFunction('extractArchiveAndGetURL', (handle, format) => {
804
- return this.exportSingleValue(
805
- this.extractArchiveAndGetURL(this.vm.getString(handle), this.vm.getString(format) as ArchiveFormat),
806
- undefined);
807
- });
808
-
809
- //
810
- // ImportProgress
811
- //
812
-
813
- exportCtxFunction('getImportProgress', (handle) => {
814
- return this.exportSingleValue(this.getImportProgress(this.vm.getString(handle)), undefined);
815
- });
816
-
817
- //
818
- // Logs
819
- //
820
-
821
- exportCtxFunction('getLastLogs', (handle, nLines) => {
822
- return this.exportSingleValue(
823
- this.getLastLogs(this.vm.getString(handle), this.vm.getNumber(nLines)),
824
- undefined,
825
- );
826
- });
827
-
828
- exportCtxFunction('getProgressLog', (handle, patternToSearch) => {
829
- return this.exportSingleValue(
830
- this.getProgressLog(this.vm.getString(handle), this.vm.getString(patternToSearch)),
831
- undefined,
832
- );
833
- });
834
-
835
- exportCtxFunction('getProgressLogWithInfo', (handle, patternToSearch) => {
836
- return this.exportSingleValue(
837
- this.getProgressLogWithInfo(this.vm.getString(handle), this.vm.getString(patternToSearch)),
838
- undefined,
839
- );
840
- });
841
-
842
- exportCtxFunction('getLogHandle', (handle) => {
843
- return this.exportSingleValue(this.getLogHandle(this.vm.getString(handle)), undefined);
844
- });
845
-
846
- //
847
- // Blocks
848
- //
849
-
850
- exportCtxFunction('getBlockLabel', (blockId) => {
851
- return this.exportSingleValue(this.getBlockLabel(this.vm.getString(blockId)), undefined);
852
- });
853
-
854
- //
855
- // Result pool
856
- //
857
-
858
- exportCtxFunction('getDataFromResultPool', () => {
859
- return this.exportObjectUniversal(this.getDataFromResultPool(), undefined);
860
- });
861
-
862
- exportCtxFunction('getDataWithErrorsFromResultPool', () => {
863
- return this.exportObjectUniversal(this.getDataWithErrorsFromResultPool(), undefined);
864
- });
865
-
866
- exportCtxFunction('getSpecsFromResultPool', () => {
867
- return this.exportObjectUniversal(this.getSpecsFromResultPool(), undefined);
868
- });
869
-
870
- exportCtxFunction('calculateOptions', (predicate) => {
871
- return this.exportObjectUniversal(
872
- this.calculateOptions(this.importObjectViaJson(predicate) as PSpecPredicate),
873
- undefined,
874
- );
875
- });
876
-
877
- exportCtxFunction('getSpecFromResultPoolByRef', (blockId, exportName) => {
878
- return this.exportObjectUniversal(
879
- this.getSpecFromResultPoolByRef(
880
- this.vm.getString(blockId),
881
- this.vm.getString(exportName),
882
- ),
883
- undefined,
884
- );
885
- });
886
-
887
- exportCtxFunction('getDataFromResultPoolByRef', (blockId, exportName) => {
888
- return this.exportObjectUniversal(
889
- this.getDataFromResultPoolByRef(
890
- this.vm.getString(blockId),
891
- this.vm.getString(exportName),
892
- ),
893
- undefined,
894
- );
895
- });
896
-
897
- //
898
- // PFrames / PTables
899
- //
900
-
901
- exportCtxFunction('createPFrame', (def) => {
902
- return this.exportSingleValue(
903
- this.createPFrame(this.importObjectViaJson(def) as PFrameDef<string | PColumnValues>),
904
- undefined,
905
- );
906
- });
907
-
908
- exportCtxFunction('createPTable', (def) => {
909
- return this.exportSingleValue(
910
- this.createPTable(
911
- this.importObjectViaJson(def) as PTableDef<PColumn<string | PColumnValues>>,
912
- ),
913
- undefined,
914
- );
915
- });
916
-
917
- //
918
- // Computable
919
- //
920
-
921
- exportCtxFunction('getCurrentUnstableMarker', () => {
922
- return this.exportSingleValue(this.getCurrentUnstableMarker(), undefined);
923
- });
924
-
925
237
  this.vm.setProp(this.vm.global, 'cfgRenderCtx', configCtx);
926
238
  });
927
239
  }