@platforma-sdk/model 1.61.0 → 1.61.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.
@@ -7,7 +7,7 @@
7
7
  * @module plugin_model
8
8
  */
9
9
 
10
- import type { BlockCodeKnownFeatureFlags } from "@milaboratories/pl-model-common";
10
+ import type { BlockCodeKnownFeatureFlags, OutputWithStatus } from "@milaboratories/pl-model-common";
11
11
  import {
12
12
  type DataModel,
13
13
  DataModelBuilder,
@@ -79,6 +79,11 @@ type PluginChainState = {
79
79
  recoverAtIndex?: number;
80
80
  };
81
81
 
82
+ /** Version → persisted data shape for each migration step (third generic of `PluginModel.define` when `data` is a `PluginDataModel`). */
83
+ export type PluginDataModelVersions<
84
+ M extends PluginDataModel<PluginData, Record<string, unknown>, unknown>,
85
+ > = M extends PluginDataModel<PluginData, infer Versions, unknown> ? Versions : never;
86
+
82
87
  /**
83
88
  * Builder for creating PluginDataModel with type-safe migrations.
84
89
  * Mirrors DataModelBuilder — same .from(), .migrate(), .recover(), .init() chain.
@@ -280,8 +285,8 @@ export class PluginInstance<
280
285
  > implements TransferTarget<Id, TransferData> {
281
286
  readonly id: Id;
282
287
  readonly transferVersion: string;
283
- /** @internal */
284
- readonly __transferBrand?: TransferData;
288
+ /** @internal Phantom for type inference of Data/Params/Outputs; never set at runtime. */
289
+ readonly __instanceTypes?: { data: Data; params: Params; outputs: Outputs };
285
290
  private readonly factory: PluginModelFactory<Data, Params, Outputs, any, any>;
286
291
  private readonly config: any;
287
292
 
@@ -336,6 +341,8 @@ export class PluginModel<
336
341
  readonly outputs: {
337
342
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
338
343
  };
344
+ /** Per-output flags (e.g. withStatus) */
345
+ readonly outputFlags: Record<string, { withStatus: boolean }>;
339
346
  /** Feature flags declared by this plugin */
340
347
  readonly featureFlags?: BlockCodeKnownFeatureFlags;
341
348
  /** Create fresh default data. Config (if any) is captured at creation time. */
@@ -347,12 +354,14 @@ export class PluginModel<
347
354
  outputs: {
348
355
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
349
356
  };
357
+ outputFlags: Record<string, { withStatus: boolean }>;
350
358
  featureFlags?: BlockCodeKnownFeatureFlags;
351
359
  getDefaultData: () => DataVersioned<Data>;
352
360
  }) {
353
361
  this.name = options.name;
354
362
  this.dataModel = options.dataModel;
355
363
  this.outputs = options.outputs;
364
+ this.outputFlags = options.outputFlags;
356
365
  this.featureFlags = options.featureFlags;
357
366
  this.getDefaultData = options.getDefaultData;
358
367
  }
@@ -372,6 +381,7 @@ export class PluginModel<
372
381
  outputs: {
373
382
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
374
383
  };
384
+ outputFlags: Record<string, { withStatus: boolean }>;
375
385
  featureFlags?: BlockCodeKnownFeatureFlags;
376
386
  getDefaultData: () => DataVersioned<Data>;
377
387
  }): PluginModel<Data, Params, Outputs> {
@@ -485,6 +495,7 @@ class PluginModelFactory<
485
495
  readonly outputs: {
486
496
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
487
497
  };
498
+ private readonly outputFlags: Record<string, { withStatus: boolean }>;
488
499
  private readonly featureFlags?: BlockCodeKnownFeatureFlags;
489
500
 
490
501
  private constructor(options: {
@@ -494,12 +505,14 @@ class PluginModelFactory<
494
505
  outputs: {
495
506
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
496
507
  };
508
+ outputFlags: Record<string, { withStatus: boolean }>;
497
509
  featureFlags?: BlockCodeKnownFeatureFlags;
498
510
  }) {
499
511
  this.name = options.name;
500
512
  this.dataFn = options.dataFn;
501
513
  this.getDefaultDataFn = options.getDefaultDataFn;
502
514
  this.outputs = options.outputs;
515
+ this.outputFlags = options.outputFlags;
503
516
  this.featureFlags = options.featureFlags;
504
517
  }
505
518
 
@@ -517,6 +530,7 @@ class PluginModelFactory<
517
530
  outputs: {
518
531
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
519
532
  };
533
+ outputFlags: Record<string, { withStatus: boolean }>;
520
534
  featureFlags?: BlockCodeKnownFeatureFlags;
521
535
  }): PluginModelFactory<Data, Params, Outputs, Config, Versions> {
522
536
  return new PluginModelFactory(options);
@@ -544,6 +558,7 @@ class PluginModelFactory<
544
558
  name: this.name,
545
559
  dataModel,
546
560
  outputs: this.outputs,
561
+ outputFlags: this.outputFlags,
547
562
  featureFlags: this.featureFlags,
548
563
  getDefaultData: getDefaultDataFn
549
564
  ? () => getDefaultDataFn(config)
@@ -584,6 +599,7 @@ class PluginModelBuilder<
584
599
  private readonly outputs: {
585
600
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
586
601
  };
602
+ private readonly outputFlags: Record<string, { withStatus: boolean }>;
587
603
  private readonly featureFlags?: BlockCodeKnownFeatureFlags;
588
604
 
589
605
  private constructor(options: {
@@ -593,6 +609,7 @@ class PluginModelBuilder<
593
609
  outputs?: {
594
610
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
595
611
  };
612
+ outputFlags?: Record<string, { withStatus: boolean }>;
596
613
  featureFlags?: BlockCodeKnownFeatureFlags;
597
614
  }) {
598
615
  this.name = options.name;
@@ -603,6 +620,7 @@ class PluginModelBuilder<
603
620
  ({} as {
604
621
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
605
622
  });
623
+ this.outputFlags = options.outputFlags ?? {};
606
624
  this.featureFlags = options.featureFlags;
607
625
  }
608
626
 
@@ -620,6 +638,7 @@ class PluginModelBuilder<
620
638
  outputs?: {
621
639
  [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];
622
640
  };
641
+ outputFlags?: Record<string, { withStatus: boolean }>;
623
642
  featureFlags?: BlockCodeKnownFeatureFlags;
624
643
  }): PluginModelBuilder<Data, Params, Outputs, Config, Versions> {
625
644
  return new PluginModelBuilder(options);
@@ -653,6 +672,57 @@ class PluginModelBuilder<
653
672
  ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>,
654
673
  ) => (Outputs & { [P in Key]: T })[K];
655
674
  },
675
+ outputFlags: { ...this.outputFlags, [key]: { withStatus: false } },
676
+ });
677
+ }
678
+
679
+ /**
680
+ * Adds an output wrapped with status information to the plugin.
681
+ *
682
+ * The UI receives the full {@link OutputWithStatus} object instead of an unwrapped value,
683
+ * allowing it to distinguish between pending, success, and error states.
684
+ *
685
+ * @param key - Output name
686
+ * @param fn - Function that computes the output value from plugin context
687
+ * @returns PluginModel with the new status-wrapped output added
688
+ *
689
+ * @example
690
+ * .outputWithStatus('table', (ctx) => {
691
+ * const pCols = ctx.params.pFrame?.getPColumns();
692
+ * if (pCols === undefined) return undefined;
693
+ * return createPlDataTableV2(ctx, pCols, ctx.data.tableState);
694
+ * })
695
+ */
696
+ outputWithStatus<const Key extends string, T>(
697
+ key: Key,
698
+ fn: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => T,
699
+ ): PluginModelBuilder<
700
+ Data,
701
+ Params,
702
+ Outputs & { [K in Key]: OutputWithStatus<T> },
703
+ Config,
704
+ Versions
705
+ > {
706
+ return new PluginModelBuilder<
707
+ Data,
708
+ Params,
709
+ Outputs & { [K in Key]: OutputWithStatus<T> },
710
+ Config,
711
+ Versions
712
+ >({
713
+ name: this.name,
714
+ dataFn: this.dataFn,
715
+ getDefaultDataFn: this.getDefaultDataFn,
716
+ featureFlags: this.featureFlags,
717
+ outputs: {
718
+ ...this.outputs,
719
+ [key]: fn,
720
+ } as {
721
+ [K in keyof (Outputs & { [P in Key]: OutputWithStatus<T> })]: (
722
+ ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>,
723
+ ) => (Outputs & { [P in Key]: OutputWithStatus<T> })[K];
724
+ },
725
+ outputFlags: { ...this.outputFlags, [key]: { withStatus: true } },
656
726
  });
657
727
  }
658
728
 
@@ -675,6 +745,7 @@ class PluginModelBuilder<
675
745
  dataFn: this.dataFn,
676
746
  getDefaultDataFn: this.getDefaultDataFn,
677
747
  outputs: this.outputs,
748
+ outputFlags: this.outputFlags,
678
749
  featureFlags: this.featureFlags,
679
750
  });
680
751
  }
package/src/render/api.ts CHANGED
@@ -819,26 +819,28 @@ export class RenderCtxLegacy<Args = unknown, UiState = unknown> extends RenderCt
819
819
  *
820
820
  * @typeParam F - PluginFactoryLike phantom carrying data/params/outputs types
821
821
  */
822
- export class PluginRenderCtx<F extends PluginFactoryLike = PluginFactoryLike> {
823
- private readonly ctx: GlobalCfgRenderCtx;
822
+ export class PluginRenderCtx<F extends PluginFactoryLike = PluginFactoryLike> extends RenderCtxBase<
823
+ unknown,
824
+ InferFactoryData<F>
825
+ > {
824
826
  private readonly handle: PluginHandle<F>;
825
827
  private readonly wrappedInputs: Record<string, () => unknown>;
826
828
 
827
829
  constructor(handle: PluginHandle<F>, wrappedInputs: Record<string, () => unknown>) {
828
- this.ctx = getCfgRenderCtx();
830
+ super();
829
831
  this.handle = handle;
830
832
  this.wrappedInputs = wrappedInputs;
831
833
  }
832
834
 
833
- private dataCache?: { v: InferFactoryData<F> };
835
+ private pluginDataCache?: { v: InferFactoryData<F> };
834
836
 
835
837
  /** Plugin's persistent data from blockStorage.__plugins.{pluginId}.__data */
836
- public get data(): InferFactoryData<F> {
837
- if (this.dataCache === undefined) {
838
+ public override get data(): InferFactoryData<F> {
839
+ if (this.pluginDataCache === undefined) {
838
840
  const raw = this.ctx.blockStorage();
839
- this.dataCache = { v: getPluginData(parseJson(raw), this.handle) };
841
+ this.pluginDataCache = { v: getPluginData(parseJson(raw), this.handle) };
840
842
  }
841
- return this.dataCache.v;
843
+ return this.pluginDataCache.v;
842
844
  }
843
845
 
844
846
  private paramsCache?: { v: InferFactoryParams<F> };
@@ -854,9 +856,6 @@ export class PluginRenderCtx<F extends PluginFactoryLike = PluginFactoryLike> {
854
856
  }
855
857
  return this.paramsCache.v;
856
858
  }
857
-
858
- /** Result pool — same as block, from cfgRenderCtx methods */
859
- public readonly resultPool = new ResultPool();
860
859
  }
861
860
 
862
861
  /** @deprecated Use BlockRenderCtx instead */