@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
@@ -12,8 +12,39 @@ const BContext = {
12
12
  };
13
13
  const BContextMultiParentPrefix = "parent/";
14
14
  const HeavyBlockOutputNames = ["context", "result"];
15
- function createRenderHeavyBlock(tx, tpl, inputs) {
16
- return require_render_template.createRenderTemplate(tx, tpl, true, inputs, HeavyBlockOutputNames);
15
+ /** Resource type of a block action context. See ActionContextV1Type in the backend. */
16
+ const ActionContextType = {
17
+ name: "ActionContext",
18
+ version: "1"
19
+ };
20
+ /** The capability under which the backend accepts the "actionContext" link on a render. */
21
+ const ActionContextLinkCapability = "optionalFieldsInSchemas:v1";
22
+ /**
23
+ * Creates the root action context of a block render: an ActionContext resource carrying the
24
+ * baggage, with a new random `run-id`, since each render is one run of the block and the contexts
25
+ * the templates create copy it. Undefined without baggage, or on a backend that cannot take the link.
26
+ */
27
+ function createBlockActionContext(tx, baggage) {
28
+ if (baggage === void 0 || !tx.hasCapability("optionalFieldsInSchemas:v1")) return void 0;
29
+ return tx.createEphemeral(ActionContextType, JSON.stringify({
30
+ name: baggage.name,
31
+ "block-pack": baggage.blockPack,
32
+ "block-id": baggage.blockId,
33
+ "run-id": (0, node_crypto.randomUUID)()
34
+ }));
35
+ }
36
+ /**
37
+ * Creates the heavy block render, and with `baggage` its root action context in the same
38
+ * transaction. Returns `actionContext`: the render is garbage collected after its outputs resolve,
39
+ * so the caller must hold the context to keep it.
40
+ */
41
+ function createRenderHeavyBlock(tx, tpl, inputs, baggage) {
42
+ const actionContext = createBlockActionContext(tx, baggage);
43
+ const { outputs } = require_render_template.createRenderTemplateWithResource(tx, tpl, true, inputs, HeavyBlockOutputNames, actionContext);
44
+ return actionContext === void 0 ? outputs : {
45
+ ...outputs,
46
+ actionContext
47
+ };
17
48
  }
18
49
  function createBContextEnd(tx) {
19
50
  const ctx = tx.createEphemeral(BContextEnd);
@@ -29,6 +60,8 @@ function createBContextFromUpstreams(tx, upstreamCtxs) {
29
60
  tx.lock(ctx);
30
61
  return ctx;
31
62
  }
63
+ exports.ActionContextLinkCapability = ActionContextLinkCapability;
64
+ exports.ActionContextType = ActionContextType;
32
65
  exports.BContext = BContext;
33
66
  exports.BContextEnd = BContextEnd;
34
67
  exports.BContextMultiParentPrefix = BContextMultiParentPrefix;
@@ -1 +1 @@
1
- {"version":3,"file":"render_block.cjs","names":["createRenderTemplate","field","Pl","randomUUID"],"sources":["../../../src/mutator/template/render_block.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceRef, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport { randomUUID } from \"node:crypto\";\nimport { createRenderTemplate } from \"./render_template\";\n\nexport const BContextEnd: ResourceType = { name: \"BContextEnd\", version: \"1\" };\nexport const BContext: ResourceType = { name: \"BContext\", version: \"1\" };\nexport const BContextId = \"id\";\nexport const BContextParent = \"parent\";\nexport const BContextMultiParentPrefix = \"parent/\";\n\n// TODO: add implementation for dual context heavy block.\n// export type BlockType =\n// | 'LightBlock'\n// | 'HeavyBlock'\n// | 'DualContextHeavyBlock';\n// moved to project model ==>>>\n\nexport type HeavyBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n isProduction: AnyRef;\n context: AnyRef;\n};\n\nexport type HeavyBlockOutputs = {\n context: AnyRef;\n result: AnyRef;\n};\n\nexport const HeavyBlockOutputNames: (keyof HeavyBlockOutputs)[] = [\"context\", \"result\"];\n\nexport function createRenderHeavyBlock(\n tx: PlTransaction,\n tpl: AnyRef,\n inputs: HeavyBlockInputs,\n): HeavyBlockOutputs {\n return createRenderTemplate(tx, tpl, true, inputs, HeavyBlockOutputNames);\n}\n\nexport type LightBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n stagingContext: AnyRef;\n productionContext: AnyRef;\n};\n\nexport type LightBlockOutput = {\n result: AnyRef;\n};\n\nexport const LightBlockOutputNames: (keyof LightBlockOutput)[] = [\"result\"];\n\nexport function createRenderLightBlock(\n tx: PlTransaction,\n tpl: ResourceRef,\n inputs: LightBlockInputs,\n): LightBlockOutput {\n return createRenderTemplate(tx, tpl, true, inputs, LightBlockOutputNames);\n}\n\nexport function createBContextEnd(tx: PlTransaction): ResourceRef {\n const ctx = tx.createEphemeral(BContextEnd);\n tx.lock(ctx);\n return ctx;\n}\n\nexport function createBContextFromUpstreams(tx: PlTransaction, upstreamCtxs: AnyRef[]): AnyRef {\n if (upstreamCtxs.length === 0) return createBContextEnd(tx);\n\n if (upstreamCtxs.length === 1) return upstreamCtxs[0];\n\n const ctx = tx.createEphemeral(BContext);\n\n // setting id\n tx.createField(field(ctx, BContextId), \"Input\", Pl.createPlString(tx, randomUUID()));\n\n // setting parents\n for (let i = 0; i < upstreamCtxs.length; i++)\n tx.createField(field(ctx, `${BContextMultiParentPrefix}${i}`), \"Input\", upstreamCtxs[i]);\n\n tx.lock(ctx);\n\n return ctx;\n}\n"],"mappings":";;;;AAKA,MAAa,cAA4B;CAAE,MAAM;CAAe,SAAS;AAAI;AAC7E,MAAa,WAAyB;CAAE,MAAM;CAAY,SAAS;AAAI;AAGvE,MAAa,4BAA4B;AAqBzC,MAAa,wBAAqD,CAAC,WAAW,QAAQ;AAEtF,SAAgB,uBACd,IACA,KACA,QACmB;CACnB,OAAOA,wBAAAA,qBAAqB,IAAI,KAAK,MAAM,QAAQ,qBAAqB;AAC1E;AAuBA,SAAgB,kBAAkB,IAAgC;CAChE,MAAM,MAAM,GAAG,gBAAgB,WAAW;CAC1C,GAAG,KAAK,GAAG;CACX,OAAO;AACT;AAEA,SAAgB,4BAA4B,IAAmB,cAAgC;CAC7F,IAAI,aAAa,WAAW,GAAG,OAAO,kBAAkB,EAAE;CAE1D,IAAI,aAAa,WAAW,GAAG,OAAO,aAAa;CAEnD,MAAM,MAAM,GAAG,gBAAgB,QAAQ;CAGvC,GAAG,aAAA,GAAYC,0BAAAA,MAAAA,CAAM,KAAA,IAAe,GAAG,SAASC,0BAAAA,GAAG,eAAe,KAAA,GAAIC,YAAAA,WAAAA,CAAW,CAAC,CAAC;CAGnF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,GAAG,aAAA,GAAYF,0BAAAA,MAAAA,CAAM,KAAK,GAAG,4BAA4B,GAAG,GAAG,SAAS,aAAa,EAAE;CAEzF,GAAG,KAAK,GAAG;CAEX,OAAO;AACT"}
1
+ {"version":3,"file":"render_block.cjs","names":["randomUUID","createRenderTemplateWithResource","field","Pl"],"sources":["../../../src/mutator/template/render_block.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceRef, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport { randomUUID } from \"node:crypto\";\nimport { createRenderTemplateWithResource } from \"./render_template\";\n\nexport const BContextEnd: ResourceType = { name: \"BContextEnd\", version: \"1\" };\nexport const BContext: ResourceType = { name: \"BContext\", version: \"1\" };\nexport const BContextId = \"id\";\nexport const BContextParent = \"parent\";\nexport const BContextMultiParentPrefix = \"parent/\";\n\n// TODO: add implementation for dual context heavy block.\n// export type BlockType =\n// | 'LightBlock'\n// | 'HeavyBlock'\n// | 'DualContextHeavyBlock';\n// moved to project model ==>>>\n\nexport type HeavyBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n isProduction: AnyRef;\n context: AnyRef;\n};\n\nexport type HeavyBlockOutputs = {\n context: AnyRef;\n result: AnyRef;\n};\n\nexport const HeavyBlockOutputNames: (keyof HeavyBlockOutputs)[] = [\"context\", \"result\"];\n\n/** Baggage of the root action context of a block render. See the block action context spec. */\nexport type BlockActionContextBaggage = {\n /** Display name of the block. */\n name: string;\n /** JSON of the block pack spec. */\n blockPack: string;\n blockId: string;\n};\n\n/** Resource type of a block action context. See ActionContextV1Type in the backend. */\nexport const ActionContextType: ResourceType = { name: \"ActionContext\", version: \"1\" };\n\n/** The capability under which the backend accepts the \"actionContext\" link on a render. */\nexport const ActionContextLinkCapability = \"optionalFieldsInSchemas:v1\";\n\n/**\n * Creates the root action context of a block render: an ActionContext resource carrying the\n * baggage, with a new random `run-id`, since each render is one run of the block and the contexts\n * the templates create copy it. Undefined without baggage, or on a backend that cannot take the link.\n */\nfunction createBlockActionContext(\n tx: PlTransaction,\n baggage: BlockActionContextBaggage | undefined,\n): ResourceRef | undefined {\n if (baggage === undefined || !tx.hasCapability(ActionContextLinkCapability)) return undefined;\n return tx.createEphemeral(\n ActionContextType,\n JSON.stringify({\n name: baggage.name,\n \"block-pack\": baggage.blockPack,\n \"block-id\": baggage.blockId,\n \"run-id\": randomUUID(),\n }),\n );\n}\n\n/**\n * Creates the heavy block render, and with `baggage` its root action context in the same\n * transaction. Returns `actionContext`: the render is garbage collected after its outputs resolve,\n * so the caller must hold the context to keep it.\n */\nexport function createRenderHeavyBlock(\n tx: PlTransaction,\n tpl: AnyRef,\n inputs: HeavyBlockInputs,\n baggage?: BlockActionContextBaggage,\n): HeavyBlockOutputs & { actionContext?: ResourceRef } {\n const actionContext = createBlockActionContext(tx, baggage);\n const { outputs } = createRenderTemplateWithResource(\n tx,\n tpl,\n true,\n inputs,\n HeavyBlockOutputNames,\n actionContext,\n );\n return actionContext === undefined ? outputs : { ...outputs, actionContext };\n}\n\nexport type LightBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n stagingContext: AnyRef;\n productionContext: AnyRef;\n};\n\nexport type LightBlockOutput = {\n result: AnyRef;\n};\n\nexport const LightBlockOutputNames: (keyof LightBlockOutput)[] = [\"result\"];\n\n/**\n * Creates the light block render, with the same action context as a heavy one, so template code\n * of either kind knows its block and run.\n */\nexport function createRenderLightBlock(\n tx: PlTransaction,\n tpl: ResourceRef,\n inputs: LightBlockInputs,\n baggage?: BlockActionContextBaggage,\n): LightBlockOutput & { actionContext?: ResourceRef } {\n const actionContext = createBlockActionContext(tx, baggage);\n const { outputs } = createRenderTemplateWithResource(\n tx,\n tpl,\n true,\n inputs,\n LightBlockOutputNames,\n actionContext,\n );\n return actionContext === undefined ? outputs : { ...outputs, actionContext };\n}\n\nexport function createBContextEnd(tx: PlTransaction): ResourceRef {\n const ctx = tx.createEphemeral(BContextEnd);\n tx.lock(ctx);\n return ctx;\n}\n\nexport function createBContextFromUpstreams(tx: PlTransaction, upstreamCtxs: AnyRef[]): AnyRef {\n if (upstreamCtxs.length === 0) return createBContextEnd(tx);\n\n if (upstreamCtxs.length === 1) return upstreamCtxs[0];\n\n const ctx = tx.createEphemeral(BContext);\n\n // setting id\n tx.createField(field(ctx, BContextId), \"Input\", Pl.createPlString(tx, randomUUID()));\n\n // setting parents\n for (let i = 0; i < upstreamCtxs.length; i++)\n tx.createField(field(ctx, `${BContextMultiParentPrefix}${i}`), \"Input\", upstreamCtxs[i]);\n\n tx.lock(ctx);\n\n return ctx;\n}\n"],"mappings":";;;;AAKA,MAAa,cAA4B;CAAE,MAAM;CAAe,SAAS;AAAI;AAC7E,MAAa,WAAyB;CAAE,MAAM;CAAY,SAAS;AAAI;AAGvE,MAAa,4BAA4B;AAqBzC,MAAa,wBAAqD,CAAC,WAAW,QAAQ;;AAYtF,MAAa,oBAAkC;CAAE,MAAM;CAAiB,SAAS;AAAI;;AAGrF,MAAa,8BAA8B;;;;;;AAO3C,SAAS,yBACP,IACA,SACyB;CACzB,IAAI,YAAY,KAAA,KAAa,CAAC,GAAG,cAAA,4BAAyC,GAAG,OAAO,KAAA;CACpF,OAAO,GAAG,gBACR,mBACA,KAAK,UAAU;EACb,MAAM,QAAQ;EACd,cAAc,QAAQ;EACtB,YAAY,QAAQ;EACpB,WAAA,GAAUA,YAAAA,WAAAA,CAAW;CACvB,CAAC,CACH;AACF;;;;;;AAOA,SAAgB,uBACd,IACA,KACA,QACA,SACqD;CACrD,MAAM,gBAAgB,yBAAyB,IAAI,OAAO;CAC1D,MAAM,EAAE,YAAYC,wBAAAA,iCAClB,IACA,KACA,MACA,QACA,uBACA,aACF;CACA,OAAO,kBAAkB,KAAA,IAAY,UAAU;EAAE,GAAG;EAAS;CAAc;AAC7E;AAqCA,SAAgB,kBAAkB,IAAgC;CAChE,MAAM,MAAM,GAAG,gBAAgB,WAAW;CAC1C,GAAG,KAAK,GAAG;CACX,OAAO;AACT;AAEA,SAAgB,4BAA4B,IAAmB,cAAgC;CAC7F,IAAI,aAAa,WAAW,GAAG,OAAO,kBAAkB,EAAE;CAE1D,IAAI,aAAa,WAAW,GAAG,OAAO,aAAa;CAEnD,MAAM,MAAM,GAAG,gBAAgB,QAAQ;CAGvC,GAAG,aAAA,GAAYC,0BAAAA,MAAAA,CAAM,KAAA,IAAe,GAAG,SAASC,0BAAAA,GAAG,eAAe,KAAA,GAAIH,YAAAA,WAAAA,CAAW,CAAC,CAAC;CAGnF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,GAAG,aAAA,GAAYE,0BAAAA,MAAAA,CAAM,KAAK,GAAG,4BAA4B,GAAG,GAAG,SAAS,aAAa,EAAE;CAEzF,GAAG,KAAK,GAAG;CAEX,OAAO;AACT"}
@@ -1,4 +1,4 @@
1
- import { createRenderTemplate } from "./render_template.js";
1
+ import { createRenderTemplateWithResource } from "./render_template.js";
2
2
  import { Pl, field } from "@milaboratories/pl-client";
3
3
  import { randomUUID } from "node:crypto";
4
4
  // src/mutator/template/render_block.ts
@@ -12,8 +12,39 @@ const BContext = {
12
12
  };
13
13
  const BContextMultiParentPrefix = "parent/";
14
14
  const HeavyBlockOutputNames = ["context", "result"];
15
- function createRenderHeavyBlock(tx, tpl, inputs) {
16
- return createRenderTemplate(tx, tpl, true, inputs, HeavyBlockOutputNames);
15
+ /** Resource type of a block action context. See ActionContextV1Type in the backend. */
16
+ const ActionContextType = {
17
+ name: "ActionContext",
18
+ version: "1"
19
+ };
20
+ /** The capability under which the backend accepts the "actionContext" link on a render. */
21
+ const ActionContextLinkCapability = "optionalFieldsInSchemas:v1";
22
+ /**
23
+ * Creates the root action context of a block render: an ActionContext resource carrying the
24
+ * baggage, with a new random `run-id`, since each render is one run of the block and the contexts
25
+ * the templates create copy it. Undefined without baggage, or on a backend that cannot take the link.
26
+ */
27
+ function createBlockActionContext(tx, baggage) {
28
+ if (baggage === void 0 || !tx.hasCapability("optionalFieldsInSchemas:v1")) return void 0;
29
+ return tx.createEphemeral(ActionContextType, JSON.stringify({
30
+ name: baggage.name,
31
+ "block-pack": baggage.blockPack,
32
+ "block-id": baggage.blockId,
33
+ "run-id": randomUUID()
34
+ }));
35
+ }
36
+ /**
37
+ * Creates the heavy block render, and with `baggage` its root action context in the same
38
+ * transaction. Returns `actionContext`: the render is garbage collected after its outputs resolve,
39
+ * so the caller must hold the context to keep it.
40
+ */
41
+ function createRenderHeavyBlock(tx, tpl, inputs, baggage) {
42
+ const actionContext = createBlockActionContext(tx, baggage);
43
+ const { outputs } = createRenderTemplateWithResource(tx, tpl, true, inputs, HeavyBlockOutputNames, actionContext);
44
+ return actionContext === void 0 ? outputs : {
45
+ ...outputs,
46
+ actionContext
47
+ };
17
48
  }
18
49
  function createBContextEnd(tx) {
19
50
  const ctx = tx.createEphemeral(BContextEnd);
@@ -29,6 +60,6 @@ function createBContextFromUpstreams(tx, upstreamCtxs) {
29
60
  tx.lock(ctx);
30
61
  return ctx;
31
62
  }
32
- export { BContext, BContextEnd, BContextMultiParentPrefix, HeavyBlockOutputNames, createBContextEnd, createBContextFromUpstreams, createRenderHeavyBlock };
63
+ export { ActionContextLinkCapability, ActionContextType, BContext, BContextEnd, BContextMultiParentPrefix, HeavyBlockOutputNames, createBContextEnd, createBContextFromUpstreams, createRenderHeavyBlock };
33
64
 
34
65
  //# sourceMappingURL=render_block.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render_block.js","names":[],"sources":["../../../src/mutator/template/render_block.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceRef, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport { randomUUID } from \"node:crypto\";\nimport { createRenderTemplate } from \"./render_template\";\n\nexport const BContextEnd: ResourceType = { name: \"BContextEnd\", version: \"1\" };\nexport const BContext: ResourceType = { name: \"BContext\", version: \"1\" };\nexport const BContextId = \"id\";\nexport const BContextParent = \"parent\";\nexport const BContextMultiParentPrefix = \"parent/\";\n\n// TODO: add implementation for dual context heavy block.\n// export type BlockType =\n// | 'LightBlock'\n// | 'HeavyBlock'\n// | 'DualContextHeavyBlock';\n// moved to project model ==>>>\n\nexport type HeavyBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n isProduction: AnyRef;\n context: AnyRef;\n};\n\nexport type HeavyBlockOutputs = {\n context: AnyRef;\n result: AnyRef;\n};\n\nexport const HeavyBlockOutputNames: (keyof HeavyBlockOutputs)[] = [\"context\", \"result\"];\n\nexport function createRenderHeavyBlock(\n tx: PlTransaction,\n tpl: AnyRef,\n inputs: HeavyBlockInputs,\n): HeavyBlockOutputs {\n return createRenderTemplate(tx, tpl, true, inputs, HeavyBlockOutputNames);\n}\n\nexport type LightBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n stagingContext: AnyRef;\n productionContext: AnyRef;\n};\n\nexport type LightBlockOutput = {\n result: AnyRef;\n};\n\nexport const LightBlockOutputNames: (keyof LightBlockOutput)[] = [\"result\"];\n\nexport function createRenderLightBlock(\n tx: PlTransaction,\n tpl: ResourceRef,\n inputs: LightBlockInputs,\n): LightBlockOutput {\n return createRenderTemplate(tx, tpl, true, inputs, LightBlockOutputNames);\n}\n\nexport function createBContextEnd(tx: PlTransaction): ResourceRef {\n const ctx = tx.createEphemeral(BContextEnd);\n tx.lock(ctx);\n return ctx;\n}\n\nexport function createBContextFromUpstreams(tx: PlTransaction, upstreamCtxs: AnyRef[]): AnyRef {\n if (upstreamCtxs.length === 0) return createBContextEnd(tx);\n\n if (upstreamCtxs.length === 1) return upstreamCtxs[0];\n\n const ctx = tx.createEphemeral(BContext);\n\n // setting id\n tx.createField(field(ctx, BContextId), \"Input\", Pl.createPlString(tx, randomUUID()));\n\n // setting parents\n for (let i = 0; i < upstreamCtxs.length; i++)\n tx.createField(field(ctx, `${BContextMultiParentPrefix}${i}`), \"Input\", upstreamCtxs[i]);\n\n tx.lock(ctx);\n\n return ctx;\n}\n"],"mappings":";;;;AAKA,MAAa,cAA4B;CAAE,MAAM;CAAe,SAAS;AAAI;AAC7E,MAAa,WAAyB;CAAE,MAAM;CAAY,SAAS;AAAI;AAGvE,MAAa,4BAA4B;AAqBzC,MAAa,wBAAqD,CAAC,WAAW,QAAQ;AAEtF,SAAgB,uBACd,IACA,KACA,QACmB;CACnB,OAAO,qBAAqB,IAAI,KAAK,MAAM,QAAQ,qBAAqB;AAC1E;AAuBA,SAAgB,kBAAkB,IAAgC;CAChE,MAAM,MAAM,GAAG,gBAAgB,WAAW;CAC1C,GAAG,KAAK,GAAG;CACX,OAAO;AACT;AAEA,SAAgB,4BAA4B,IAAmB,cAAgC;CAC7F,IAAI,aAAa,WAAW,GAAG,OAAO,kBAAkB,EAAE;CAE1D,IAAI,aAAa,WAAW,GAAG,OAAO,aAAa;CAEnD,MAAM,MAAM,GAAG,gBAAgB,QAAQ;CAGvC,GAAG,YAAY,MAAM,KAAA,IAAe,GAAG,SAAS,GAAG,eAAe,IAAI,WAAW,CAAC,CAAC;CAGnF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,GAAG,YAAY,MAAM,KAAK,GAAG,4BAA4B,GAAG,GAAG,SAAS,aAAa,EAAE;CAEzF,GAAG,KAAK,GAAG;CAEX,OAAO;AACT"}
1
+ {"version":3,"file":"render_block.js","names":[],"sources":["../../../src/mutator/template/render_block.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceRef, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport { randomUUID } from \"node:crypto\";\nimport { createRenderTemplateWithResource } from \"./render_template\";\n\nexport const BContextEnd: ResourceType = { name: \"BContextEnd\", version: \"1\" };\nexport const BContext: ResourceType = { name: \"BContext\", version: \"1\" };\nexport const BContextId = \"id\";\nexport const BContextParent = \"parent\";\nexport const BContextMultiParentPrefix = \"parent/\";\n\n// TODO: add implementation for dual context heavy block.\n// export type BlockType =\n// | 'LightBlock'\n// | 'HeavyBlock'\n// | 'DualContextHeavyBlock';\n// moved to project model ==>>>\n\nexport type HeavyBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n isProduction: AnyRef;\n context: AnyRef;\n};\n\nexport type HeavyBlockOutputs = {\n context: AnyRef;\n result: AnyRef;\n};\n\nexport const HeavyBlockOutputNames: (keyof HeavyBlockOutputs)[] = [\"context\", \"result\"];\n\n/** Baggage of the root action context of a block render. See the block action context spec. */\nexport type BlockActionContextBaggage = {\n /** Display name of the block. */\n name: string;\n /** JSON of the block pack spec. */\n blockPack: string;\n blockId: string;\n};\n\n/** Resource type of a block action context. See ActionContextV1Type in the backend. */\nexport const ActionContextType: ResourceType = { name: \"ActionContext\", version: \"1\" };\n\n/** The capability under which the backend accepts the \"actionContext\" link on a render. */\nexport const ActionContextLinkCapability = \"optionalFieldsInSchemas:v1\";\n\n/**\n * Creates the root action context of a block render: an ActionContext resource carrying the\n * baggage, with a new random `run-id`, since each render is one run of the block and the contexts\n * the templates create copy it. Undefined without baggage, or on a backend that cannot take the link.\n */\nfunction createBlockActionContext(\n tx: PlTransaction,\n baggage: BlockActionContextBaggage | undefined,\n): ResourceRef | undefined {\n if (baggage === undefined || !tx.hasCapability(ActionContextLinkCapability)) return undefined;\n return tx.createEphemeral(\n ActionContextType,\n JSON.stringify({\n name: baggage.name,\n \"block-pack\": baggage.blockPack,\n \"block-id\": baggage.blockId,\n \"run-id\": randomUUID(),\n }),\n );\n}\n\n/**\n * Creates the heavy block render, and with `baggage` its root action context in the same\n * transaction. Returns `actionContext`: the render is garbage collected after its outputs resolve,\n * so the caller must hold the context to keep it.\n */\nexport function createRenderHeavyBlock(\n tx: PlTransaction,\n tpl: AnyRef,\n inputs: HeavyBlockInputs,\n baggage?: BlockActionContextBaggage,\n): HeavyBlockOutputs & { actionContext?: ResourceRef } {\n const actionContext = createBlockActionContext(tx, baggage);\n const { outputs } = createRenderTemplateWithResource(\n tx,\n tpl,\n true,\n inputs,\n HeavyBlockOutputNames,\n actionContext,\n );\n return actionContext === undefined ? outputs : { ...outputs, actionContext };\n}\n\nexport type LightBlockInputs = {\n args: AnyRef;\n blockId: AnyRef;\n stagingContext: AnyRef;\n productionContext: AnyRef;\n};\n\nexport type LightBlockOutput = {\n result: AnyRef;\n};\n\nexport const LightBlockOutputNames: (keyof LightBlockOutput)[] = [\"result\"];\n\n/**\n * Creates the light block render, with the same action context as a heavy one, so template code\n * of either kind knows its block and run.\n */\nexport function createRenderLightBlock(\n tx: PlTransaction,\n tpl: ResourceRef,\n inputs: LightBlockInputs,\n baggage?: BlockActionContextBaggage,\n): LightBlockOutput & { actionContext?: ResourceRef } {\n const actionContext = createBlockActionContext(tx, baggage);\n const { outputs } = createRenderTemplateWithResource(\n tx,\n tpl,\n true,\n inputs,\n LightBlockOutputNames,\n actionContext,\n );\n return actionContext === undefined ? outputs : { ...outputs, actionContext };\n}\n\nexport function createBContextEnd(tx: PlTransaction): ResourceRef {\n const ctx = tx.createEphemeral(BContextEnd);\n tx.lock(ctx);\n return ctx;\n}\n\nexport function createBContextFromUpstreams(tx: PlTransaction, upstreamCtxs: AnyRef[]): AnyRef {\n if (upstreamCtxs.length === 0) return createBContextEnd(tx);\n\n if (upstreamCtxs.length === 1) return upstreamCtxs[0];\n\n const ctx = tx.createEphemeral(BContext);\n\n // setting id\n tx.createField(field(ctx, BContextId), \"Input\", Pl.createPlString(tx, randomUUID()));\n\n // setting parents\n for (let i = 0; i < upstreamCtxs.length; i++)\n tx.createField(field(ctx, `${BContextMultiParentPrefix}${i}`), \"Input\", upstreamCtxs[i]);\n\n tx.lock(ctx);\n\n return ctx;\n}\n"],"mappings":";;;;AAKA,MAAa,cAA4B;CAAE,MAAM;CAAe,SAAS;AAAI;AAC7E,MAAa,WAAyB;CAAE,MAAM;CAAY,SAAS;AAAI;AAGvE,MAAa,4BAA4B;AAqBzC,MAAa,wBAAqD,CAAC,WAAW,QAAQ;;AAYtF,MAAa,oBAAkC;CAAE,MAAM;CAAiB,SAAS;AAAI;;AAGrF,MAAa,8BAA8B;;;;;;AAO3C,SAAS,yBACP,IACA,SACyB;CACzB,IAAI,YAAY,KAAA,KAAa,CAAC,GAAG,cAAA,4BAAyC,GAAG,OAAO,KAAA;CACpF,OAAO,GAAG,gBACR,mBACA,KAAK,UAAU;EACb,MAAM,QAAQ;EACd,cAAc,QAAQ;EACtB,YAAY,QAAQ;EACpB,UAAU,WAAW;CACvB,CAAC,CACH;AACF;;;;;;AAOA,SAAgB,uBACd,IACA,KACA,QACA,SACqD;CACrD,MAAM,gBAAgB,yBAAyB,IAAI,OAAO;CAC1D,MAAM,EAAE,YAAY,iCAClB,IACA,KACA,MACA,QACA,uBACA,aACF;CACA,OAAO,kBAAkB,KAAA,IAAY,UAAU;EAAE,GAAG;EAAS;CAAc;AAC7E;AAqCA,SAAgB,kBAAkB,IAAgC;CAChE,MAAM,MAAM,GAAG,gBAAgB,WAAW;CAC1C,GAAG,KAAK,GAAG;CACX,OAAO;AACT;AAEA,SAAgB,4BAA4B,IAAmB,cAAgC;CAC7F,IAAI,aAAa,WAAW,GAAG,OAAO,kBAAkB,EAAE;CAE1D,IAAI,aAAa,WAAW,GAAG,OAAO,aAAa;CAEnD,MAAM,MAAM,GAAG,gBAAgB,QAAQ;CAGvC,GAAG,YAAY,MAAM,KAAA,IAAe,GAAG,SAAS,GAAG,eAAe,IAAI,WAAW,CAAC,CAAC;CAGnF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,GAAG,YAAY,MAAM,KAAK,GAAG,4BAA4B,GAAG,GAAG,SAAS,aAAa,EAAE;CAEzF,GAAG,KAAK,GAAG;CAEX,OAAO;AACT"}
@@ -18,15 +18,30 @@ const RenderTemplate = {
18
18
  * @param outputNames names of the outputs to collect and return from this method
19
19
  */
20
20
  function createRenderTemplate(tx, tpl, ephemeral, inputs, outputNames) {
21
+ return createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames).outputs;
22
+ }
23
+ /**
24
+ * Same as {@link createRenderTemplate}, and also returns the render resource itself.
25
+ *
26
+ * With `actionContext`, the render's "actionContext" service field points to it. The link is created
27
+ * before the inputs are locked: the backend accepts it only in the creating transaction, ahead of
28
+ * any explicit input lock.
29
+ */
30
+ function createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames, actionContext) {
21
31
  if (outputNames.length === 0) throw new Error("Zero output names provided");
22
32
  const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);
23
33
  const tplField = (0, _milaboratories_pl_client.field)(rId, "template");
24
34
  const inputsField = (0, _milaboratories_pl_client.field)(rId, "inputs");
25
35
  tx.createField(tplField, "Input", tpl);
26
36
  tx.createField(inputsField, "Input", _milaboratories_pl_client.Pl.createPlMap(tx, inputs, ephemeral));
37
+ if (actionContext !== void 0) tx.createField((0, _milaboratories_pl_client.field)(rId, "actionContext"), "Service", actionContext);
27
38
  tx.lockInputs(rId);
28
- return _milaboratories_pl_client.Pl.futureRecord(tx, rId, outputNames, "Output", "outputs/");
39
+ return {
40
+ render: rId,
41
+ outputs: _milaboratories_pl_client.Pl.futureRecord(tx, rId, outputNames, "Output", "outputs/")
42
+ };
29
43
  }
30
44
  exports.createRenderTemplate = createRenderTemplate;
45
+ exports.createRenderTemplateWithResource = createRenderTemplateWithResource;
31
46
 
32
47
  //# sourceMappingURL=render_template.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"render_template.cjs","names":["field","Pl"],"sources":["../../../src/mutator/template/render_template.ts"],"sourcesContent":["import type { AnyRef, FieldRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport type { ResourceType } from \"@platforma-sdk/model\";\n\nconst EphRenderTemplate: ResourceType = {\n name: \"EphRenderTemplate\",\n version: \"1\",\n};\nconst RenderTemplate: ResourceType = {\n name: \"RenderTemplate\",\n version: \"1\",\n};\n\n/**\n * Creates render template operation, for a given remplate and inputs.\n *\n * @param tx transaction to use during rendering creation\n * @param tpl reference to the template resource (see {@link loadTemplate})\n * @param ephemeral true for ephemeral templates, false for pure templates\n * @param inputs map of inputs pointing to other resources or fields\n * @param outputNames names of the outputs to collect and return from this method\n */\nexport function createRenderTemplate<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n): Record<O, FieldRef> {\n if (outputNames.length === 0) throw new Error(\"Zero output names provided\");\n const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);\n\n const tplField = field(rId, \"template\");\n const inputsField = field(rId, \"inputs\");\n\n tx.createField(tplField, \"Input\", tpl);\n tx.createField(inputsField, \"Input\", Pl.createPlMap(tx, inputs, ephemeral));\n tx.lockInputs(rId);\n\n return Pl.futureRecord(tx, rId, outputNames, \"Output\", \"outputs/\");\n}\n"],"mappings":";;AAIA,MAAM,oBAAkC;CACtC,MAAM;CACN,SAAS;AACX;AACA,MAAM,iBAA+B;CACnC,MAAM;CACN,SAAS;AACX;;;;;;;;;;AAWA,SAAgB,qBACd,IACA,KACA,WACA,QACA,aACqB;CACrB,IAAI,YAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAA4B;CAC1E,MAAM,MAAM,YAAY,GAAG,gBAAgB,iBAAiB,IAAI,GAAG,aAAa,cAAc;CAE9F,MAAM,YAAA,GAAWA,0BAAAA,MAAAA,CAAM,KAAK,UAAU;CACtC,MAAM,eAAA,GAAcA,0BAAAA,MAAAA,CAAM,KAAK,QAAQ;CAEvC,GAAG,YAAY,UAAU,SAAS,GAAG;CACrC,GAAG,YAAY,aAAa,SAASC,0BAAAA,GAAG,YAAY,IAAI,QAAQ,SAAS,CAAC;CAC1E,GAAG,WAAW,GAAG;CAEjB,OAAOA,0BAAAA,GAAG,aAAa,IAAI,KAAK,aAAa,UAAU,UAAU;AACnE"}
1
+ {"version":3,"file":"render_template.cjs","names":["field","Pl"],"sources":["../../../src/mutator/template/render_template.ts"],"sourcesContent":["import type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport type { ResourceType } from \"@platforma-sdk/model\";\n\nconst EphRenderTemplate: ResourceType = {\n name: \"EphRenderTemplate\",\n version: \"1\",\n};\nconst RenderTemplate: ResourceType = {\n name: \"RenderTemplate\",\n version: \"1\",\n};\n\n/**\n * Creates render template operation, for a given remplate and inputs.\n *\n * @param tx transaction to use during rendering creation\n * @param tpl reference to the template resource (see {@link loadTemplate})\n * @param ephemeral true for ephemeral templates, false for pure templates\n * @param inputs map of inputs pointing to other resources or fields\n * @param outputNames names of the outputs to collect and return from this method\n */\nexport function createRenderTemplate<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n): Record<O, FieldRef> {\n return createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames).outputs;\n}\n\n/**\n * Same as {@link createRenderTemplate}, and also returns the render resource itself.\n *\n * With `actionContext`, the render's \"actionContext\" service field points to it. The link is created\n * before the inputs are locked: the backend accepts it only in the creating transaction, ahead of\n * any explicit input lock.\n */\nexport function createRenderTemplateWithResource<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n actionContext?: AnyRef,\n): { render: ResourceRef; outputs: Record<O, FieldRef> } {\n if (outputNames.length === 0) throw new Error(\"Zero output names provided\");\n const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);\n\n const tplField = field(rId, \"template\");\n const inputsField = field(rId, \"inputs\");\n\n tx.createField(tplField, \"Input\", tpl);\n tx.createField(inputsField, \"Input\", Pl.createPlMap(tx, inputs, ephemeral));\n if (actionContext !== undefined)\n tx.createField(field(rId, \"actionContext\"), \"Service\", actionContext);\n tx.lockInputs(rId);\n\n return { render: rId, outputs: Pl.futureRecord(tx, rId, outputNames, \"Output\", \"outputs/\") };\n}\n"],"mappings":";;AAIA,MAAM,oBAAkC;CACtC,MAAM;CACN,SAAS;AACX;AACA,MAAM,iBAA+B;CACnC,MAAM;CACN,SAAS;AACX;;;;;;;;;;AAWA,SAAgB,qBACd,IACA,KACA,WACA,QACA,aACqB;CACrB,OAAO,iCAAiC,IAAI,KAAK,WAAW,QAAQ,WAAW,CAAC,CAAC;AACnF;;;;;;;;AASA,SAAgB,iCACd,IACA,KACA,WACA,QACA,aACA,eACuD;CACvD,IAAI,YAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAA4B;CAC1E,MAAM,MAAM,YAAY,GAAG,gBAAgB,iBAAiB,IAAI,GAAG,aAAa,cAAc;CAE9F,MAAM,YAAA,GAAWA,0BAAAA,MAAAA,CAAM,KAAK,UAAU;CACtC,MAAM,eAAA,GAAcA,0BAAAA,MAAAA,CAAM,KAAK,QAAQ;CAEvC,GAAG,YAAY,UAAU,SAAS,GAAG;CACrC,GAAG,YAAY,aAAa,SAASC,0BAAAA,GAAG,YAAY,IAAI,QAAQ,SAAS,CAAC;CAC1E,IAAI,kBAAkB,KAAA,GACpB,GAAG,aAAA,GAAYD,0BAAAA,MAAAA,CAAM,KAAK,eAAe,GAAG,WAAW,aAAa;CACtE,GAAG,WAAW,GAAG;CAEjB,OAAO;EAAE,QAAQ;EAAK,SAASC,0BAAAA,GAAG,aAAa,IAAI,KAAK,aAAa,UAAU,UAAU;CAAE;AAC7F"}
@@ -1,4 +1,4 @@
1
- import { AnyRef, FieldRef, Pl, PlTransaction } from "@milaboratories/pl-client";
1
+ import { AnyRef, FieldRef, Pl, PlTransaction, ResourceRef } from "@milaboratories/pl-client";
2
2
  /**
3
3
  * Creates render template operation, for a given remplate and inputs.
4
4
  *
@@ -9,4 +9,15 @@ import { AnyRef, FieldRef, Pl, PlTransaction } from "@milaboratories/pl-client";
9
9
  * @param outputNames names of the outputs to collect and return from this method
10
10
  */
11
11
  export declare function createRenderTemplate<O extends string>(tx: PlTransaction, tpl: AnyRef, ephemeral: boolean, inputs: Pl.PlRecord, outputNames: O[]): Record<O, FieldRef>;
12
+ /**
13
+ * Same as {@link createRenderTemplate}, and also returns the render resource itself.
14
+ *
15
+ * With `actionContext`, the render's "actionContext" service field points to it. The link is created
16
+ * before the inputs are locked: the backend accepts it only in the creating transaction, ahead of
17
+ * any explicit input lock.
18
+ */
19
+ export declare function createRenderTemplateWithResource<O extends string>(tx: PlTransaction, tpl: AnyRef, ephemeral: boolean, inputs: Pl.PlRecord, outputNames: O[], actionContext?: AnyRef): {
20
+ render: ResourceRef;
21
+ outputs: Record<O, FieldRef>;
22
+ };
12
23
  //# sourceMappingURL=render_template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render_template.d.ts","names":[],"sources":["../../../src/mutator/template/render_template.ts"],"mappings":";;;;;;;;;;wBAsBgB,qBAAqB,kBACnC,IAAI,eACJ,KAAK,QACL,oBACA,QAAQ,GAAG,UACX,aAAa,MACZ,OAAO,GAAG"}
1
+ {"version":3,"file":"render_template.d.ts","names":[],"sources":["../../../src/mutator/template/render_template.ts"],"mappings":";;;;;;;;;;wBAsBgB,qBAAqB,kBACnC,IAAI,eACJ,KAAK,QACL,oBACA,QAAQ,GAAG,UACX,aAAa,MACZ,OAAO,GAAG;;;;;;;;wBAWG,iCAAiC,kBAC/C,IAAI,eACJ,KAAK,QACL,oBACA,QAAQ,GAAG,UACX,aAAa,KACb,gBAAgB;EACb,QAAQ;EAAa,SAAS,OAAO,GAAG"}
@@ -18,15 +18,29 @@ const RenderTemplate = {
18
18
  * @param outputNames names of the outputs to collect and return from this method
19
19
  */
20
20
  function createRenderTemplate(tx, tpl, ephemeral, inputs, outputNames) {
21
+ return createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames).outputs;
22
+ }
23
+ /**
24
+ * Same as {@link createRenderTemplate}, and also returns the render resource itself.
25
+ *
26
+ * With `actionContext`, the render's "actionContext" service field points to it. The link is created
27
+ * before the inputs are locked: the backend accepts it only in the creating transaction, ahead of
28
+ * any explicit input lock.
29
+ */
30
+ function createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames, actionContext) {
21
31
  if (outputNames.length === 0) throw new Error("Zero output names provided");
22
32
  const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);
23
33
  const tplField = field(rId, "template");
24
34
  const inputsField = field(rId, "inputs");
25
35
  tx.createField(tplField, "Input", tpl);
26
36
  tx.createField(inputsField, "Input", Pl.createPlMap(tx, inputs, ephemeral));
37
+ if (actionContext !== void 0) tx.createField(field(rId, "actionContext"), "Service", actionContext);
27
38
  tx.lockInputs(rId);
28
- return Pl.futureRecord(tx, rId, outputNames, "Output", "outputs/");
39
+ return {
40
+ render: rId,
41
+ outputs: Pl.futureRecord(tx, rId, outputNames, "Output", "outputs/")
42
+ };
29
43
  }
30
- export { createRenderTemplate };
44
+ export { createRenderTemplate, createRenderTemplateWithResource };
31
45
 
32
46
  //# sourceMappingURL=render_template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render_template.js","names":[],"sources":["../../../src/mutator/template/render_template.ts"],"sourcesContent":["import type { AnyRef, FieldRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport type { ResourceType } from \"@platforma-sdk/model\";\n\nconst EphRenderTemplate: ResourceType = {\n name: \"EphRenderTemplate\",\n version: \"1\",\n};\nconst RenderTemplate: ResourceType = {\n name: \"RenderTemplate\",\n version: \"1\",\n};\n\n/**\n * Creates render template operation, for a given remplate and inputs.\n *\n * @param tx transaction to use during rendering creation\n * @param tpl reference to the template resource (see {@link loadTemplate})\n * @param ephemeral true for ephemeral templates, false for pure templates\n * @param inputs map of inputs pointing to other resources or fields\n * @param outputNames names of the outputs to collect and return from this method\n */\nexport function createRenderTemplate<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n): Record<O, FieldRef> {\n if (outputNames.length === 0) throw new Error(\"Zero output names provided\");\n const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);\n\n const tplField = field(rId, \"template\");\n const inputsField = field(rId, \"inputs\");\n\n tx.createField(tplField, \"Input\", tpl);\n tx.createField(inputsField, \"Input\", Pl.createPlMap(tx, inputs, ephemeral));\n tx.lockInputs(rId);\n\n return Pl.futureRecord(tx, rId, outputNames, \"Output\", \"outputs/\");\n}\n"],"mappings":";;AAIA,MAAM,oBAAkC;CACtC,MAAM;CACN,SAAS;AACX;AACA,MAAM,iBAA+B;CACnC,MAAM;CACN,SAAS;AACX;;;;;;;;;;AAWA,SAAgB,qBACd,IACA,KACA,WACA,QACA,aACqB;CACrB,IAAI,YAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAA4B;CAC1E,MAAM,MAAM,YAAY,GAAG,gBAAgB,iBAAiB,IAAI,GAAG,aAAa,cAAc;CAE9F,MAAM,WAAW,MAAM,KAAK,UAAU;CACtC,MAAM,cAAc,MAAM,KAAK,QAAQ;CAEvC,GAAG,YAAY,UAAU,SAAS,GAAG;CACrC,GAAG,YAAY,aAAa,SAAS,GAAG,YAAY,IAAI,QAAQ,SAAS,CAAC;CAC1E,GAAG,WAAW,GAAG;CAEjB,OAAO,GAAG,aAAa,IAAI,KAAK,aAAa,UAAU,UAAU;AACnE"}
1
+ {"version":3,"file":"render_template.js","names":[],"sources":["../../../src/mutator/template/render_template.ts"],"sourcesContent":["import type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport type { ResourceType } from \"@platforma-sdk/model\";\n\nconst EphRenderTemplate: ResourceType = {\n name: \"EphRenderTemplate\",\n version: \"1\",\n};\nconst RenderTemplate: ResourceType = {\n name: \"RenderTemplate\",\n version: \"1\",\n};\n\n/**\n * Creates render template operation, for a given remplate and inputs.\n *\n * @param tx transaction to use during rendering creation\n * @param tpl reference to the template resource (see {@link loadTemplate})\n * @param ephemeral true for ephemeral templates, false for pure templates\n * @param inputs map of inputs pointing to other resources or fields\n * @param outputNames names of the outputs to collect and return from this method\n */\nexport function createRenderTemplate<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n): Record<O, FieldRef> {\n return createRenderTemplateWithResource(tx, tpl, ephemeral, inputs, outputNames).outputs;\n}\n\n/**\n * Same as {@link createRenderTemplate}, and also returns the render resource itself.\n *\n * With `actionContext`, the render's \"actionContext\" service field points to it. The link is created\n * before the inputs are locked: the backend accepts it only in the creating transaction, ahead of\n * any explicit input lock.\n */\nexport function createRenderTemplateWithResource<O extends string>(\n tx: PlTransaction,\n tpl: AnyRef,\n ephemeral: boolean,\n inputs: Pl.PlRecord,\n outputNames: O[],\n actionContext?: AnyRef,\n): { render: ResourceRef; outputs: Record<O, FieldRef> } {\n if (outputNames.length === 0) throw new Error(\"Zero output names provided\");\n const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);\n\n const tplField = field(rId, \"template\");\n const inputsField = field(rId, \"inputs\");\n\n tx.createField(tplField, \"Input\", tpl);\n tx.createField(inputsField, \"Input\", Pl.createPlMap(tx, inputs, ephemeral));\n if (actionContext !== undefined)\n tx.createField(field(rId, \"actionContext\"), \"Service\", actionContext);\n tx.lockInputs(rId);\n\n return { render: rId, outputs: Pl.futureRecord(tx, rId, outputNames, \"Output\", \"outputs/\") };\n}\n"],"mappings":";;AAIA,MAAM,oBAAkC;CACtC,MAAM;CACN,SAAS;AACX;AACA,MAAM,iBAA+B;CACnC,MAAM;CACN,SAAS;AACX;;;;;;;;;;AAWA,SAAgB,qBACd,IACA,KACA,WACA,QACA,aACqB;CACrB,OAAO,iCAAiC,IAAI,KAAK,WAAW,QAAQ,WAAW,CAAC,CAAC;AACnF;;;;;;;;AASA,SAAgB,iCACd,IACA,KACA,WACA,QACA,aACA,eACuD;CACvD,IAAI,YAAY,WAAW,GAAG,MAAM,IAAI,MAAM,4BAA4B;CAC1E,MAAM,MAAM,YAAY,GAAG,gBAAgB,iBAAiB,IAAI,GAAG,aAAa,cAAc;CAE9F,MAAM,WAAW,MAAM,KAAK,UAAU;CACtC,MAAM,cAAc,MAAM,KAAK,QAAQ;CAEvC,GAAG,YAAY,UAAU,SAAS,GAAG;CACrC,GAAG,YAAY,aAAa,SAAS,GAAG,YAAY,IAAI,QAAQ,SAAS,CAAC;CAC1E,IAAI,kBAAkB,KAAA,GACpB,GAAG,YAAY,MAAM,KAAK,eAAe,GAAG,WAAW,aAAa;CACtE,GAAG,WAAW,GAAG;CAEjB,OAAO;EAAE,QAAQ;EAAK,SAAS,GAAG,aAAa,IAAI,KAAK,aAAa,UAAU,UAAU;CAAE;AAC7F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-middle-layer",
3
- "version": "1.74.19",
3
+ "version": "1.76.0",
4
4
  "description": "Pl Middle Layer",
5
5
  "keywords": [],
6
6
  "license": "UNLICENSED",
@@ -19,27 +19,27 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@milaboratories/columns-collection-driver": "0.2.12",
22
+ "@milaboratories/columns-collection-driver": "0.2.13",
23
23
  "@milaboratories/computable": "2.9.9",
24
24
  "@milaboratories/helpers": "1.14.6",
25
- "@milaboratories/pf-driver": "1.9.12",
26
- "@milaboratories/pf-spec-driver": "1.5.12",
25
+ "@milaboratories/pf-driver": "1.9.13",
26
+ "@milaboratories/pf-spec-driver": "1.5.13",
27
27
  "@milaboratories/pframes-rs-node": "1.2.0",
28
- "@milaboratories/pl-client": "3.19.3",
29
- "@milaboratories/pl-crash-recorder": "0.3.8",
30
- "@milaboratories/pl-deployments": "3.0.24",
31
- "@milaboratories/pl-drivers": "1.16.38",
32
- "@milaboratories/pl-errors": "1.4.55",
28
+ "@milaboratories/pl-client": "3.20.0",
29
+ "@milaboratories/pl-crash-recorder": "0.3.9",
30
+ "@milaboratories/pl-deployments": "3.0.25",
31
+ "@milaboratories/pl-drivers": "1.16.40",
32
+ "@milaboratories/pl-errors": "1.4.57",
33
33
  "@milaboratories/pl-http": "1.2.5",
34
- "@milaboratories/pl-model-backend": "1.4.40",
35
- "@milaboratories/pl-model-common": "1.54.2",
36
- "@milaboratories/pl-model-middle-layer": "1.34.6",
37
- "@milaboratories/pl-tree": "1.16.7",
34
+ "@milaboratories/pl-model-backend": "1.4.42",
35
+ "@milaboratories/pl-model-common": "1.55.0",
36
+ "@milaboratories/pl-model-middle-layer": "1.35.0",
37
+ "@milaboratories/pl-tree": "1.16.9",
38
38
  "@milaboratories/resolve-helper": "1.1.3",
39
39
  "@milaboratories/ts-helpers": "1.9.0",
40
- "@platforma-sdk/block-tools": "2.17.2",
41
- "@platforma-sdk/model": "1.87.0",
42
- "@platforma-sdk/workflow-tengo": "6.19.0",
40
+ "@platforma-sdk/block-tools": "2.17.4",
41
+ "@platforma-sdk/model": "1.88.0",
42
+ "@platforma-sdk/workflow-tengo": "6.20.0",
43
43
  "canonicalize": "~2.1.0",
44
44
  "denque": "^2.1.0",
45
45
  "es-toolkit": "^1.39.10",
@@ -17,7 +17,10 @@ import { deepFreeze } from "@milaboratories/ts-helpers";
17
17
  import { extractCodeWithInfo } from "@platforma-sdk/model";
18
18
  import { getDebugFlags } from "../debug";
19
19
 
20
- export type BlockParameters = Omit<BlockStateInternalV3, "outputs" | "navigationState">;
20
+ export type BlockParameters = Omit<
21
+ BlockStateInternalV3,
22
+ "outputs" | "navigationState" | "columnLinks"
23
+ >;
21
24
 
22
25
  export function getBlockParameters(
23
26
  projectEntry: PlTreeEntry,
@@ -0,0 +1,148 @@
1
+ import type { SignedResourceId } from "@milaboratories/pl-client";
2
+ import { createSignedResourceId, parseSignedResourceId } from "@milaboratories/pl-client";
3
+ import { describe, expect, test } from "vitest";
4
+ import { projectFieldName } from "../model/project_model";
5
+ import type { ActionContextReader, ActionContextReadTx } from "./block_action_context";
6
+ import { readBlockActionContextTree } from "./block_action_context";
7
+
8
+ type FakeResource = {
9
+ data?: Record<string, string>;
10
+ fields: { name: string; value: SignedResourceId }[];
11
+ kvs: { key: string; value: string }[];
12
+ };
13
+
14
+ function signedId(globalId: number): SignedResourceId {
15
+ return createSignedResourceId(BigInt(globalId));
16
+ }
17
+
18
+ /** A client whose read transaction serves the given resources by global ID. */
19
+ function fakeClient(resources: Map<string, FakeResource>): ActionContextReader {
20
+ const lookup = (ref: SignedResourceId) => {
21
+ const resource = resources.get(String(parseSignedResourceId(ref).globalId));
22
+ if (resource === undefined) throw new Error(`no resource ${ref}`);
23
+ return resource;
24
+ };
25
+ const tx: ActionContextReadTx = {
26
+ getResourceData: async (ref: SignedResourceId) => {
27
+ const resource = lookup(ref);
28
+ return {
29
+ data: resource.data === undefined ? undefined : Buffer.from(JSON.stringify(resource.data)),
30
+ fields: resource.fields,
31
+ };
32
+ },
33
+ listKeyValuesString: async (ref: SignedResourceId) => lookup(ref).kvs,
34
+ };
35
+
36
+ return {
37
+ withReadTx: async <T>(_name: string, body: (tx: ActionContextReadTx) => Promise<T>) =>
38
+ await body(tx),
39
+ };
40
+ }
41
+
42
+ const project = signedId(1);
43
+ const prodRoot = signedId(10);
44
+ const stagingRoot = signedId(11);
45
+ const child = signedId(20);
46
+ const grandchild = signedId(30);
47
+
48
+ function resources(): Map<string, FakeResource> {
49
+ return new Map<string, FakeResource>([
50
+ [
51
+ "1",
52
+ {
53
+ fields: [
54
+ { name: projectFieldName("block1", "prodActionContext"), value: prodRoot },
55
+ { name: projectFieldName("block1", "stagingActionContext"), value: stagingRoot },
56
+ ],
57
+ kvs: [],
58
+ },
59
+ ],
60
+ [
61
+ "10",
62
+ {
63
+ data: { name: "prod render" },
64
+ fields: [
65
+ { name: "child/32", value: child },
66
+ { name: "other", value: signedId(99) },
67
+ ],
68
+ kvs: [
69
+ // timestamps of different lengths: string order differs from time order
70
+ { key: "transition/render/16/1000", value: '{"state":"Running"}' },
71
+ { key: "transition/render/16/999", value: '{"state":"WaitingForInputs"}' },
72
+ { key: "reading/exec/16/progress", value: "40" },
73
+ { key: "reading/exec/16/stage", value: "align" },
74
+ { key: "unrelated", value: "x" },
75
+ ],
76
+ },
77
+ ],
78
+ ["11", { data: { name: "staging render" }, fields: [], kvs: [] }],
79
+ [
80
+ "20",
81
+ {
82
+ data: { name: "child render" },
83
+ fields: [{ name: "child/48", value: grandchild }],
84
+ kvs: [{ key: "transition/render/32/5", value: '{"state":"Completed","detail":"ok"}' }],
85
+ },
86
+ ],
87
+ ["30", { data: { name: "grandchild render" }, fields: [], kvs: [] }],
88
+ ]);
89
+ }
90
+
91
+ describe("readBlockActionContextTree", () => {
92
+ test("reads the prod tree with children, ordered transitions and readings", async () => {
93
+ const tree = (await readBlockActionContextTree(
94
+ fakeClient(resources()),
95
+ project,
96
+ "block1",
97
+ "prod",
98
+ ))!;
99
+
100
+ expect(tree.contextId).toEqual("10");
101
+ expect(tree.resource).toEqual("16");
102
+ expect(tree.baggage).toEqual({ name: "prod render" });
103
+ expect(tree.transitions.map((t) => [t.timestampNs, t.state])).toEqual([
104
+ ["999", "WaitingForInputs"],
105
+ ["1000", "Running"],
106
+ ]);
107
+ expect(tree.readings).toEqual([
108
+ { namespace: "exec", resource: "16", key: "progress", value: "40" },
109
+ { namespace: "exec", resource: "16", key: "stage", value: "align" },
110
+ ]);
111
+
112
+ expect(tree.children.map((c) => c.baggage["name"])).toEqual(["child render"]);
113
+ const childNode = tree.children[0];
114
+ expect(childNode.transitions).toEqual([
115
+ {
116
+ namespace: "render",
117
+ resource: "32",
118
+ timestampNs: "5",
119
+ state: "Completed",
120
+ detail: "ok",
121
+ reason: "",
122
+ },
123
+ ]);
124
+ expect(childNode.resource).toEqual("32");
125
+ expect(childNode.children.map((c) => c.contextId)).toEqual(["30"]);
126
+ expect(childNode.children[0].resource).toBeUndefined();
127
+ expect(childNode.children[0].children).toEqual([]);
128
+ });
129
+
130
+ test("reads the staging tree for staging mode", async () => {
131
+ const tree = (await readBlockActionContextTree(
132
+ fakeClient(resources()),
133
+ project,
134
+ "block1",
135
+ "staging",
136
+ ))!;
137
+
138
+ expect(tree.contextId).toEqual("11");
139
+ expect(tree.baggage).toEqual({ name: "staging render" });
140
+ expect(tree.children).toEqual([]);
141
+ });
142
+
143
+ test("returns undefined for a block without an action context field", async () => {
144
+ expect(
145
+ await readBlockActionContextTree(fakeClient(resources()), project, "block2", "prod"),
146
+ ).toBeUndefined();
147
+ });
148
+ });