@milaboratories/pl-middle-layer 1.74.19 → 1.76.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 (87) hide show
  1. package/dist/index.cjs +1 -0
  2. package/dist/index.d.ts +3 -2
  3. package/dist/index.js +2 -2
  4. package/dist/middle_layer/block.cjs.map +1 -1
  5. package/dist/middle_layer/block.js.map +1 -1
  6. package/dist/middle_layer/block_action_context.cjs +57 -0
  7. package/dist/middle_layer/block_action_context.cjs.map +1 -0
  8. package/dist/middle_layer/block_action_context.d.ts +47 -0
  9. package/dist/middle_layer/block_action_context.d.ts.map +1 -0
  10. package/dist/middle_layer/block_action_context.js +57 -0
  11. package/dist/middle_layer/block_action_context.js.map +1 -0
  12. package/dist/middle_layer/build_stamp.cjs +1 -1
  13. package/dist/middle_layer/build_stamp.js +1 -1
  14. package/dist/middle_layer/column_links.cjs +106 -0
  15. package/dist/middle_layer/column_links.cjs.map +1 -0
  16. package/dist/middle_layer/column_links.js +104 -0
  17. package/dist/middle_layer/column_links.js.map +1 -0
  18. package/dist/middle_layer/index.d.ts +2 -1
  19. package/dist/middle_layer/middle_layer.cjs +1 -0
  20. package/dist/middle_layer/middle_layer.cjs.map +1 -1
  21. package/dist/middle_layer/middle_layer.js +1 -0
  22. package/dist/middle_layer/middle_layer.js.map +1 -1
  23. package/dist/middle_layer/project.cjs +53 -19
  24. package/dist/middle_layer/project.cjs.map +1 -1
  25. package/dist/middle_layer/project.d.ts +6 -0
  26. package/dist/middle_layer/project.d.ts.map +1 -1
  27. package/dist/middle_layer/project.js +54 -20
  28. package/dist/middle_layer/project.js.map +1 -1
  29. package/dist/middle_layer/project_overview.cjs +56 -24
  30. package/dist/middle_layer/project_overview.cjs.map +1 -1
  31. package/dist/middle_layer/project_overview.js +55 -25
  32. package/dist/middle_layer/project_overview.js.map +1 -1
  33. package/dist/model/args_derivation.cjs +153 -0
  34. package/dist/model/args_derivation.cjs.map +1 -0
  35. package/dist/model/args_derivation.d.ts +21 -0
  36. package/dist/model/args_derivation.d.ts.map +1 -0
  37. package/dist/model/args_derivation.js +148 -0
  38. package/dist/model/args_derivation.js.map +1 -0
  39. package/dist/model/project_helper.cjs +34 -8
  40. package/dist/model/project_helper.cjs.map +1 -1
  41. package/dist/model/project_helper.d.ts +18 -5
  42. package/dist/model/project_helper.d.ts.map +1 -1
  43. package/dist/model/project_helper.js +34 -8
  44. package/dist/model/project_helper.js.map +1 -1
  45. package/dist/model/project_model.cjs +2 -1
  46. package/dist/model/project_model.cjs.map +1 -1
  47. package/dist/model/project_model.d.ts +1 -1
  48. package/dist/model/project_model.js +2 -1
  49. package/dist/model/project_model.js.map +1 -1
  50. package/dist/mutator/project.cjs +73 -12
  51. package/dist/mutator/project.cjs.map +1 -1
  52. package/dist/mutator/project.d.ts +1 -0
  53. package/dist/mutator/project.d.ts.map +1 -1
  54. package/dist/mutator/project.js +73 -12
  55. package/dist/mutator/project.js.map +1 -1
  56. package/dist/mutator/template/render_block.cjs +35 -2
  57. package/dist/mutator/template/render_block.cjs.map +1 -1
  58. package/dist/mutator/template/render_block.js +35 -4
  59. package/dist/mutator/template/render_block.js.map +1 -1
  60. package/dist/mutator/template/render_template.cjs +16 -1
  61. package/dist/mutator/template/render_template.cjs.map +1 -1
  62. package/dist/mutator/template/render_template.d.ts +12 -1
  63. package/dist/mutator/template/render_template.d.ts.map +1 -1
  64. package/dist/mutator/template/render_template.js +16 -2
  65. package/dist/mutator/template/render_template.js.map +1 -1
  66. package/package.json +16 -16
  67. package/src/middle_layer/block.ts +4 -1
  68. package/src/middle_layer/block_action_context.test.ts +148 -0
  69. package/src/middle_layer/block_action_context.ts +162 -0
  70. package/src/middle_layer/column_links.test.ts +350 -0
  71. package/src/middle_layer/column_links.ts +152 -0
  72. package/src/middle_layer/index.ts +6 -0
  73. package/src/middle_layer/middle_layer.ts +2 -0
  74. package/src/middle_layer/project.ts +52 -5
  75. package/src/middle_layer/project_overview.test.ts +200 -0
  76. package/src/middle_layer/project_overview.ts +82 -28
  77. package/src/model/args.test.ts +39 -1
  78. package/src/model/args_derivation.test.ts +326 -0
  79. package/src/model/args_derivation.ts +194 -0
  80. package/src/model/project_helper.ts +55 -25
  81. package/src/model/project_model.ts +7 -2
  82. package/src/mutator/project-v3.test.ts +105 -1
  83. package/src/mutator/project.ts +128 -37
  84. package/src/mutator/project_action_context.test.ts +178 -0
  85. package/src/mutator/template/render_block.ts +70 -5
  86. package/src/mutator/template/render_template.ts +22 -2
  87. package/src/test/fake_project.ts +222 -0
@@ -5,6 +5,7 @@ import { ProjectHelper } from "../model/project_helper.js";
5
5
  import { BlockConfig } from "@platforma-sdk/model";
6
6
  import { AuthorMarker, BlockPackSpec, BlockSettings, ProjectMeta } from "@milaboratories/pl-model-middle-layer";
7
7
  import { MiLogger } from "@milaboratories/ts-helpers";
8
+ import { ArgsIssue } from "@milaboratories/pl-model-common";
8
9
  import { AnyRef, AnyResourceRef, PlClient, PlTransaction, ResourceRef, SignedResourceId } from "@milaboratories/pl-client";
9
10
  /**
10
11
  * Duplicates an existing project resource within a transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","names":[],"sources":["../../src/mutator/project.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;wBAklEsB,iBACpB,IAAI,eACJ,WAAW,kBACX;EAAY;;;;;;;;AAOZ,gBAAgB,gBACf,QAAQ"}
1
+ {"version":3,"file":"project.d.ts","names":[],"sources":["../../src/mutator/project.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;wBA6qEsB,iBACpB,IAAI,eACJ,WAAW,kBACX;EAAY;;;;;;;;AAOZ,gBAAgB,gBACf,QAAQ"}
@@ -5,6 +5,7 @@ import { allBlocks, graphDiff, productionGraph, stagingGraph } from "../model/pr
5
5
  import { exportProjectAsTemplateV1 } from "../model/template_serializer.js";
6
6
  import { BlockPackTemplateField, createBlockPack } from "./block-pack/block_pack.js";
7
7
  import { exportContext, getPreparedExportTemplateEnvelope } from "./context_export.js";
8
+ import { argsErrorsFieldChange, argsErrorsOfBlock, derivedArgsValue } from "../model/args_derivation.js";
8
9
  import { getDebugFlags } from "../debug/index.js";
9
10
  import { BLOCK_STORAGE_FACADE_VERSION, UiError, extractConfig } from "@platforma-sdk/model";
10
11
  import { InitialBlockSettings, normalizeProjectMeta } from "@milaboratories/pl-model-middle-layer";
@@ -115,6 +116,18 @@ var BlockInfo = class {
115
116
  get currentPrerunArgs() {
116
117
  return this.currentPrerunArgsC();
117
118
  }
119
+ argsErrorsC = cached(() => `${this.fields.inputsValid?.modCount}:${this.fields.currentArgs?.modCount}`, () => argsErrorsOfBlock({
120
+ modelAPIVersion: this.config.modelAPIVersion,
121
+ inputsValid: this.fields.inputsValid,
122
+ currentArgs: this.currentArgs
123
+ }));
124
+ /**
125
+ * The errors the block's `argsIssues()` found in its current args. A block whose model API
126
+ * version has no args issues, or that has no current args, has none.
127
+ */
128
+ get argsErrors() {
129
+ return this.argsErrorsC();
130
+ }
118
131
  get stagingRendered() {
119
132
  return this.fields.stagingCtx !== void 0;
120
133
  }
@@ -363,6 +376,14 @@ var ProjectMutator = class ProjectMutator {
363
376
  status: "Ready"
364
377
  };
365
378
  }
379
+ /** Baggage of the root action context of a block render. */
380
+ blockActionContextBaggage(blockId, info) {
381
+ return {
382
+ name: this.getBlock(blockId).label,
383
+ blockPack: JSON.stringify(info.source),
384
+ blockId
385
+ };
386
+ }
366
387
  getBlock(blockId) {
367
388
  for (const block of allBlocks(this.struct)) if (block.id === blockId) return block;
368
389
  throw new Error("block not found");
@@ -398,6 +419,26 @@ var ProjectMutator = class ProjectMutator {
398
419
  }
399
420
  return deleted;
400
421
  }
422
+ /**
423
+ * Brings the block's `inputsValid` field in line with what its args derivation found: the run
424
+ * errors of its args, none when it may run with them, and no field when it has no args.
425
+ */
426
+ setArgsErrors(blockId, derivedArgs) {
427
+ this.applyArgsErrorsChange(blockId, argsErrorsFieldChange(this.getBlockInfo(blockId).fields.inputsValid, derivedArgs));
428
+ }
429
+ applyArgsErrorsChange(blockId, change) {
430
+ switch (change.type) {
431
+ case "keep": return;
432
+ case "delete":
433
+ this.deleteBlockFields(blockId, "inputsValid");
434
+ return;
435
+ case "write": {
436
+ const ref = this.tx.createValue(Pl.JsonObject, change.data);
437
+ this.setBlockField(blockId, "inputsValid", ref, "Ready", change.data);
438
+ return;
439
+ }
440
+ }
441
+ }
401
442
  updateLastModified() {
402
443
  this.lastModified = Date.now();
403
444
  this.lastModifiedChanged = true;
@@ -416,6 +457,7 @@ var ProjectMutator = class ProjectMutator {
416
457
  this.setBlockFieldObj(blockId, "stagingCtxPrevious", fields.stagingCtx);
417
458
  this.setBlockFieldObj(blockId, "stagingUiCtxPrevious", fields.stagingUiCtx);
418
459
  }
460
+ this.deleteBlockFields(blockId, "stagingActionContext");
419
461
  if (this.deleteBlockFields(blockId, "stagingOutput", "stagingCtx", "stagingUiCtx")) this.resetStagingRefreshTimestamp();
420
462
  }
421
463
  resetProduction(blockId) {
@@ -428,7 +470,7 @@ var ProjectMutator = class ProjectMutator {
428
470
  this.setBlockFieldObj(blockId, "prodCtxPrevious", fields.prodCtx);
429
471
  this.setBlockFieldObj(blockId, "prodUiCtxPrevious", fields.prodUiCtx);
430
472
  }
431
- this.deleteBlockFields(blockId, "prodOutput", "prodCtx", "prodUiCtx", "prodArgs");
473
+ this.deleteBlockFields(blockId, "prodOutput", "prodCtx", "prodUiCtx", "prodArgs", "prodActionContext");
432
474
  }
433
475
  /** Running blocks are reset, settled ones (Ready or finished Error) moved to limbo. Returns if
434
476
  * either of the actions were actually performed.
@@ -441,7 +483,10 @@ var ProjectMutator = class ProjectMutator {
441
483
  this.renderingStateChanged = true;
442
484
  this.deleteBlockFields(blockId, "prodOutputPrevious", "prodCtxPrevious", "prodUiCtxPrevious");
443
485
  return true;
444
- } else return this.deleteBlockFields(blockId, "prodOutput", "prodCtx", "prodUiCtx", "prodArgs", "prodOutputPrevious", "prodCtxPrevious", "prodUiCtxPrevious");
486
+ } else {
487
+ this.deleteBlockFields(blockId, "prodActionContext");
488
+ return this.deleteBlockFields(blockId, "prodOutput", "prodCtx", "prodUiCtx", "prodArgs", "prodOutputPrevious", "prodCtxPrevious", "prodUiCtxPrevious");
489
+ }
445
490
  }
446
491
  /**
447
492
  * Gets current block state and merges with partial updates.
@@ -487,9 +532,11 @@ var ProjectMutator = class ProjectMutator {
487
532
  const prerunArgs = this.projectHelper.derivePrerunArgsFromStorage(blockConfig, initialStorageJson);
488
533
  if (prerunArgs !== void 0) this.setBlockFieldObj(blockId, "currentPrerunArgs", this.createJsonFieldValue(prerunArgs));
489
534
  else this.deleteBlockFields(blockId, "currentPrerunArgs");
490
- const deriveArgsResult = this.projectHelper.deriveArgsFromStorage(blockConfig, initialStorageJson);
491
- if (!deriveArgsResult.error && deriveArgsResult.value !== void 0) this.setBlockFieldObj(blockId, "currentArgs", this.createJsonFieldValue(deriveArgsResult.value));
535
+ const derivedArgs = this.projectHelper.deriveArgsFromStorage(blockConfig, initialStorageJson);
536
+ const args = derivedArgsValue(derivedArgs);
537
+ if (args !== void 0) this.setBlockFieldObj(blockId, "currentArgs", this.createJsonFieldValue(args));
492
538
  else this.deleteBlockFields(blockId, "currentArgs");
539
+ this.setArgsErrors(blockId, derivedArgs);
493
540
  }
494
541
  /** Optimally sets inputs for multiple blocks in one go */
495
542
  setStates(requests) {
@@ -508,8 +555,9 @@ var ProjectMutator = class ProjectMutator {
508
555
  const updatedStorageJson = this.projectHelper.applyStorageUpdateInVM(blockConfig, currentStorageJson, req.payload);
509
556
  this.setBlockFieldObj(req.blockId, "blockStorage", this.createGzJsonFieldValueFromContent(updatedStorageJson));
510
557
  prerunArgs = this.projectHelper.derivePrerunArgsFromStorage(blockConfig, updatedStorageJson);
511
- const derivedArgsResult = this.projectHelper.deriveArgsFromStorage(blockConfig, updatedStorageJson);
512
- args = derivedArgsResult.error ? void 0 : derivedArgsResult.value;
558
+ const derivedArgs = this.projectHelper.deriveArgsFromStorage(blockConfig, updatedStorageJson);
559
+ args = derivedArgsValue(derivedArgs);
560
+ this.setArgsErrors(req.blockId, derivedArgs);
513
561
  } else {
514
562
  this.setBlockFieldObj(req.blockId, "blockStorage", this.createGzJsonFieldValue(req.state));
515
563
  if (req.state !== null && typeof req.state === "object" && "args" in req.state) args = req.state.args;
@@ -615,15 +663,21 @@ var ProjectMutator = class ProjectMutator {
615
663
  blockId: this.tx.createValue(Pl.JsonString, JSON.stringify(blockId)),
616
664
  isProduction: this.tx.createValue(Pl.JsonBool, JSON.stringify(false)),
617
665
  context: ctx
618
- });
666
+ }, this.blockActionContextBaggage(blockId, info));
619
667
  this.setBlockField(blockId, "stagingCtx", Pl.wrapInEphHolder(this.tx, ctx), "NotReady");
620
668
  this.setBlockField(blockId, "stagingUiCtx", this.exportCtx(results.context), "NotReady");
621
669
  this.setBlockField(blockId, "stagingOutput", results.result, "NotReady");
670
+ if (results.actionContext !== void 0) this.setBlockField(blockId, "stagingActionContext", results.actionContext, "NotReady");
622
671
  }
623
672
  renderProductionFor(blockId) {
624
673
  this.resetProduction(blockId);
625
674
  const info = this.getBlockInfo(blockId);
626
675
  if (info.fields.currentArgs === void 0) throw new Error(`Can't render production for block ${blockId}: currentArgs not set`);
676
+ const argsErrors = info.argsErrors;
677
+ if (argsErrors.length > 0) {
678
+ const messages = argsErrors.map(({ message }) => message).join("; ");
679
+ throw new Error(`Can't render production for block ${blockId}: ${messages}`);
680
+ }
627
681
  const ctx = this.createProdCtx(this.getPendingProductionGraph().nodes.get(blockId).upstream);
628
682
  if (this.getBlock(blockId).renderingMode === "Light") throw new Error("Can't render production for light block.");
629
683
  const tpl = info.getTemplate(this.tx);
@@ -632,10 +686,11 @@ var ProjectMutator = class ProjectMutator {
632
686
  blockId: this.tx.createValue(Pl.JsonString, JSON.stringify(blockId)),
633
687
  isProduction: this.tx.createValue(Pl.JsonBool, JSON.stringify(true)),
634
688
  context: ctx
635
- });
689
+ }, this.blockActionContextBaggage(blockId, info));
636
690
  this.setBlockField(blockId, "prodCtx", Pl.wrapInEphHolder(this.tx, results.context), "NotReady");
637
691
  this.setBlockField(blockId, "prodUiCtx", this.exportCtx(results.context), "NotReady");
638
692
  this.setBlockField(blockId, "prodOutput", results.result, "NotReady");
693
+ if (results.actionContext !== void 0) this.setBlockField(blockId, "prodActionContext", results.actionContext, "NotReady");
639
694
  this.setBlockFieldObj(blockId, "prodArgs", info.fields.currentArgs);
640
695
  if (this.blocksInLimbo.delete(blockId)) this.renderingStateChanged = true;
641
696
  }
@@ -652,8 +707,9 @@ var ProjectMutator = class ProjectMutator {
652
707
  if (spec.storageMode === "fromModel") {
653
708
  storageToWrite = spec.initialStorage ?? this.projectHelper.getInitialStorageInVM(blockConfig);
654
709
  prerunArgs = this.projectHelper.derivePrerunArgsFromStorage(blockConfig, storageToWrite);
655
- const deriveArgsResult = this.projectHelper.deriveArgsFromStorage(blockConfig, storageToWrite);
656
- args = deriveArgsResult.error ? void 0 : deriveArgsResult.value;
710
+ const derivedArgs = this.projectHelper.deriveArgsFromStorage(blockConfig, storageToWrite);
711
+ args = derivedArgsValue(derivedArgs);
712
+ this.setArgsErrors(blockId, derivedArgs);
657
713
  } else if (spec.storageMode === "legacy") {
658
714
  args = JSON.parse(spec.legacyState).args;
659
715
  if (args === void 0) throw new Error("args is undefined in legacyState");
@@ -808,9 +864,11 @@ var ProjectMutator = class ProjectMutator {
808
864
  const prerunArgs = this.projectHelper.derivePrerunArgsFromStorage(newConfig, storageJson);
809
865
  if (prerunArgs !== void 0) this.setBlockFieldObj(blockId, "currentPrerunArgs", this.createJsonFieldValue(prerunArgs));
810
866
  else this.deleteBlockFields(blockId, "currentPrerunArgs");
811
- const deriveArgsResult = this.projectHelper.deriveArgsFromStorage(newConfig, storageJson);
812
- if (!deriveArgsResult.error && deriveArgsResult.value !== void 0) this.setBlockFieldObj(blockId, "currentArgs", this.createJsonFieldValue(deriveArgsResult.value));
867
+ const derivedArgs = this.projectHelper.deriveArgsFromStorage(newConfig, storageJson);
868
+ const args = derivedArgsValue(derivedArgs);
869
+ if (args !== void 0) this.setBlockFieldObj(blockId, "currentArgs", this.createJsonFieldValue(args));
813
870
  else this.deleteBlockFields(blockId, "currentArgs");
871
+ this.setArgsErrors(blockId, derivedArgs);
814
872
  };
815
873
  if (newClearState !== void 0) {
816
874
  if (newConfig.modelAPIVersion === BLOCK_STORAGE_FACADE_VERSION) {
@@ -819,6 +877,7 @@ var ProjectMutator = class ProjectMutator {
819
877
  this.updateLastModified();
820
878
  } else {
821
879
  persistBlockPack();
880
+ this.deleteBlockFields(blockId, "inputsValid");
822
881
  this.setStates([{
823
882
  modelAPIVersion: 1,
824
883
  blockId,
@@ -834,6 +893,7 @@ var ProjectMutator = class ProjectMutator {
834
893
  applyStorageAndDeriveArgs(migrationResult.newStorageJson);
835
894
  } else {
836
895
  persistBlockPack();
896
+ this.deleteBlockFields(blockId, "inputsValid");
837
897
  if (info.fields.currentArgs !== void 0) this.setBlockFieldObj(blockId, "currentPrerunArgs", info.fields.currentArgs);
838
898
  }
839
899
  this.blocksWithChangedInputs.add(blockId);
@@ -900,6 +960,7 @@ var ProjectMutator = class ProjectMutator {
900
960
  const blockId = queue.shift();
901
961
  const fields = this.getBlockInfo(blockId).fields;
902
962
  if (fields.prodOutput?.status === "Ready" && fields.prodCtx?.status === "Ready") continue;
963
+ this.deleteBlockFields(blockId, "prodActionContext");
903
964
  if (this.deleteBlockFields(blockId, "prodOutput", "prodCtx", "prodUiCtx", "prodArgs")) {
904
965
  stopped.push(blockId);
905
966
  for (const downstream of activeProdGraph.traverseIdsExcludingRoots("downstream", blockId)) {