@platforma-sdk/model 1.2.22

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.
package/src/builder.ts ADDED
@@ -0,0 +1,345 @@
1
+ import { BlockRenderingMode, BlockSection, ValueOrErrors } from '@milaboratories/pl-model-common';
2
+ import { Checked, ConfigResult, getImmediate, PlResourceEntry, TypedConfig } from './config';
3
+ import { getPlatformaInstance, isInUI, tryRegisterCallback } from './internal';
4
+ import { Platforma } from './platforma';
5
+ import { InferRenderFunctionReturn, RenderCtx, RenderFunction } from './render';
6
+ import { PlatformaSDKVersion } from './version';
7
+
8
+ type StdCtxArgsOnly<Args, UiState = undefined> = {
9
+ readonly $blockId: string;
10
+ readonly $args: Args;
11
+ readonly $ui: UiState;
12
+ };
13
+
14
+ export type StdCtx<Args, UiState = undefined> = StdCtxArgsOnly<Args, UiState> & {
15
+ readonly $prod: PlResourceEntry;
16
+ readonly $staging: PlResourceEntry;
17
+ };
18
+
19
+ export type ResolveCfgType<Cfg extends TypedConfig, Args, UiState = undefined> = ConfigResult<
20
+ Cfg,
21
+ StdCtx<Args, UiState>
22
+ >;
23
+
24
+ type SectionsExpectedType = readonly BlockSection[];
25
+
26
+ type SectionsCfgChecked<Cfg extends TypedConfig, Args, UiState> = Checked<
27
+ Cfg,
28
+ ConfigResult<Cfg, StdCtxArgsOnly<Args, UiState>> extends SectionsExpectedType ? true : false
29
+ >;
30
+
31
+ type SectionsRFChecked<RF extends Function> = Checked<
32
+ RF,
33
+ InferRenderFunctionReturn<RF> extends SectionsExpectedType ? true : false
34
+ >;
35
+
36
+ type InputsValidExpectedType = boolean;
37
+
38
+ type InputsValidCfgChecked<Cfg extends TypedConfig, Args, UiState> = Checked<
39
+ Cfg,
40
+ ConfigResult<Cfg, StdCtxArgsOnly<Args, UiState>> extends InputsValidExpectedType ? true : false
41
+ >;
42
+
43
+ type InputsValidRFChecked<RF extends Function> = Checked<
44
+ RF,
45
+ InferRenderFunctionReturn<RF> extends InputsValidExpectedType ? true : false
46
+ >;
47
+
48
+ export type Code = {
49
+ type: 'plain';
50
+ content: string;
51
+ };
52
+
53
+ /** Field key to attach ConfAction information to a config type. */
54
+ declare const __function_handle__: unique symbol;
55
+
56
+ /** Creates branded Cfg type */
57
+ export type FunctionHandle<Return = unknown> = string & { [__function_handle__]: Return };
58
+
59
+ export type ExtractFunctionHandleReturn<Func extends FunctionHandle> =
60
+ Func[typeof __function_handle__];
61
+
62
+ export type TypedConfigOrFunctionHandle = TypedConfig | FunctionHandle;
63
+
64
+ export function isFunctionHandle(cfgOrFh: TypedConfigOrFunctionHandle): cfgOrFh is FunctionHandle {
65
+ return typeof cfgOrFh === 'string';
66
+ }
67
+
68
+ type OnlyString<S> = S extends string ? S : '';
69
+
70
+ // prettier-ignore
71
+ export type DeriveHref<S> = S extends readonly BlockSection[]
72
+ ? OnlyString<Extract<S[number], { type: 'link' }>['href']>
73
+ : never;
74
+
75
+ /** This structure is rendered from the configuration, type can accommodate any
76
+ * version of config structure. */
77
+ export type BlockConfigUniversal<
78
+ Args = unknown,
79
+ Outputs extends Record<string, TypedConfigOrFunctionHandle> = Record<
80
+ string,
81
+ TypedConfigOrFunctionHandle
82
+ >
83
+ > = {
84
+ /** SDK version used by the block */
85
+ readonly sdkVersion: string;
86
+
87
+ /** Main rendering mode for the block */
88
+ readonly renderingMode: BlockRenderingMode;
89
+
90
+ /** Initial value for the args when block is added to the project */
91
+ readonly initialArgs: Args;
92
+
93
+ /** @deprecated */
94
+ readonly canRun?: TypedConfigOrFunctionHandle;
95
+
96
+ /**
97
+ * Config to determine whether the block can be executed with current
98
+ * arguments.
99
+ *
100
+ * Optional to support earlier SDK version configs.
101
+ * */
102
+ readonly inputsValid?: TypedConfigOrFunctionHandle;
103
+
104
+ /** Configuration to derive list of section for the left overview panel */
105
+ readonly sections: TypedConfigOrFunctionHandle;
106
+
107
+ /** Configuration for the output cells */
108
+ readonly outputs: Outputs;
109
+
110
+ /** Config code bundle */
111
+ readonly code?: Code;
112
+ };
113
+
114
+ /** This structure is rendered from the configuration */
115
+ export type BlockConfig<
116
+ Args = unknown,
117
+ Outputs extends Record<string, TypedConfigOrFunctionHandle> = Record<
118
+ string,
119
+ TypedConfigOrFunctionHandle
120
+ >
121
+ > = Required<Omit<BlockConfigUniversal<Args, Outputs>, 'canRun' | 'code'>> &
122
+ Pick<BlockConfigUniversal<Args, Outputs>, 'code'>;
123
+
124
+ /** Takes universal config, and converts it into latest structure */
125
+ export function normalizeBlockConfig<
126
+ Args,
127
+ Outputs extends Record<string, TypedConfigOrFunctionHandle>
128
+ >(cfg: BlockConfigUniversal<Args, Outputs>): BlockConfig<Args, Outputs> {
129
+ if (cfg.inputsValid !== undefined) return cfg as BlockConfig<Args, Outputs>;
130
+ else {
131
+ if (cfg.canRun === undefined)
132
+ throw new Error(`Malformed config, SDK version ${cfg.sdkVersion}`);
133
+ const latest = { ...cfg, inputsValid: cfg.canRun };
134
+ delete latest['canRun'];
135
+ return latest;
136
+ }
137
+ }
138
+
139
+ /** Main entry point that each block should use in it's "config" module. Don't forget
140
+ * to call {@link done()} at the end of configuration. Value returned by this builder must be
141
+ * exported as constant with name "platforma" from the "config" module. */
142
+ export class BlockModel<
143
+ Args,
144
+ OutputsCfg extends Record<string, TypedConfigOrFunctionHandle>,
145
+ UiState,
146
+ Href extends `/${string}` = '/'
147
+ > {
148
+ private constructor(
149
+ private readonly _renderingMode: BlockRenderingMode,
150
+ private readonly _initialArgs: Args | undefined,
151
+ private readonly _outputs: OutputsCfg,
152
+ private readonly _inputsValid: TypedConfigOrFunctionHandle,
153
+ private readonly _sections: TypedConfigOrFunctionHandle
154
+ ) { }
155
+
156
+ /** Initiates configuration builder */
157
+ public static create<Args, UiState = undefined>(
158
+ renderingMode: BlockRenderingMode
159
+ ): BlockModel<Args, {}, UiState> {
160
+ return new BlockModel<Args, {}, UiState>(
161
+ renderingMode,
162
+ undefined,
163
+ {},
164
+ getImmediate(true),
165
+ getImmediate([])
166
+ );
167
+ }
168
+
169
+ /**
170
+ * Add output cell to the configuration
171
+ *
172
+ * @param key cell name, that can be used to retrieve the rendered value
173
+ * @param cfg configuration describing how to render cell value from the blocks
174
+ * workflow outputs
175
+ * */
176
+ public output<const Key extends string, const Cfg extends TypedConfig>(
177
+ key: Key,
178
+ cfg: Cfg
179
+ ): BlockModel<Args, OutputsCfg & { [K in Key]: Cfg }, UiState, Href>;
180
+ public output<const Key extends string, const RF extends RenderFunction<Args, UiState>>(
181
+ key: Key,
182
+ rf: RF
183
+ ): BlockModel<
184
+ Args,
185
+ OutputsCfg & { [K in Key]: FunctionHandle<InferRenderFunctionReturn<RF>> },
186
+ UiState,
187
+ Href
188
+ >;
189
+ public output(
190
+ key: string,
191
+ cfgOrRf: TypedConfig | Function
192
+ ): BlockModel<Args, OutputsCfg, UiState, Href> {
193
+ if (typeof cfgOrRf === 'function') {
194
+ const functionHandle = `output#${key}` as FunctionHandle;
195
+ tryRegisterCallback(functionHandle, () => cfgOrRf(new RenderCtx()));
196
+ return new BlockModel(
197
+ this._renderingMode,
198
+ this._initialArgs,
199
+ {
200
+ ...this._outputs,
201
+ [key]: functionHandle
202
+ },
203
+ this._inputsValid,
204
+ this._sections
205
+ );
206
+ } else
207
+ return new BlockModel(
208
+ this._renderingMode,
209
+ this._initialArgs,
210
+ {
211
+ ...this._outputs,
212
+ [key]: cfgOrRf
213
+ },
214
+ this._inputsValid,
215
+ this._sections
216
+ );
217
+ }
218
+
219
+ /** @deprecated */
220
+ public canRun<Cfg extends TypedConfig>(
221
+ cfg: Cfg & InputsValidCfgChecked<Cfg, Args, UiState>
222
+ ): BlockModel<Args, OutputsCfg, UiState, Href> {
223
+ return this.inputsValid(cfg as any);
224
+ }
225
+
226
+ /** Sets custom configuration predicate on the block args at which block can be executed */
227
+ public inputsValid<Cfg extends TypedConfig>(
228
+ cfg: Cfg & InputsValidCfgChecked<Cfg, Args, UiState>
229
+ ): BlockModel<Args, OutputsCfg, UiState, Href>;
230
+ public inputsValid<RF extends RenderFunction<Args, UiState, boolean>>(
231
+ rf: RF
232
+ ): BlockModel<Args, OutputsCfg, UiState, Href>;
233
+ public inputsValid(
234
+ cfgOrRf: TypedConfig | Function
235
+ ): BlockModel<Args, OutputsCfg, UiState, `/${string}`> {
236
+ if (typeof cfgOrRf === 'function') {
237
+ tryRegisterCallback('inputsValid', () => cfgOrRf(new RenderCtx()));
238
+ return new BlockModel<Args, OutputsCfg, UiState>(
239
+ this._renderingMode,
240
+ this._initialArgs,
241
+ this._outputs,
242
+ 'inputsValid' as FunctionHandle,
243
+ this._sections
244
+ );
245
+ } else
246
+ return new BlockModel<Args, OutputsCfg, UiState>(
247
+ this._renderingMode,
248
+ this._initialArgs,
249
+ this._outputs,
250
+ cfgOrRf,
251
+ this._sections
252
+ );
253
+ }
254
+
255
+ /** Sets the config to generate list of section in the left block overviews panel */
256
+ public sections<const S extends SectionsExpectedType,>(rf: S): BlockModel<Args, OutputsCfg, UiState, DeriveHref<S>>;
257
+ public sections<
258
+ const Ret extends SectionsExpectedType,
259
+ const RF extends RenderFunction<Args, UiState, Ret>
260
+ >(rf: RF): BlockModel<Args, OutputsCfg, UiState, DeriveHref<ReturnType<RF>>>;
261
+ public sections<const Cfg extends TypedConfig>(
262
+ cfg: Cfg & SectionsCfgChecked<Cfg, Args, UiState>
263
+ ): BlockModel<
264
+ Args,
265
+ OutputsCfg,
266
+ UiState,
267
+ DeriveHref<ConfigResult<Cfg, StdCtxArgsOnly<Args, UiState>>>
268
+ >;
269
+ public sections(
270
+ arrOrCfgOrRf: SectionsExpectedType | TypedConfig | Function
271
+ ): BlockModel<Args, OutputsCfg, UiState, `/${string}`> {
272
+ if (Array.isArray(arrOrCfgOrRf)){
273
+ return this.sections(getImmediate(arrOrCfgOrRf))
274
+ } else if (typeof arrOrCfgOrRf === 'function') {
275
+ tryRegisterCallback('sections', () => arrOrCfgOrRf(new RenderCtx()));
276
+ return new BlockModel<Args, OutputsCfg, UiState>(
277
+ this._renderingMode,
278
+ this._initialArgs,
279
+ this._outputs,
280
+ this._inputsValid,
281
+ 'sections' as FunctionHandle
282
+ );
283
+ } else
284
+ return new BlockModel<Args, OutputsCfg, UiState>(
285
+ this._renderingMode,
286
+ this._initialArgs,
287
+ this._outputs,
288
+ this._inputsValid,
289
+ arrOrCfgOrRf as TypedConfig
290
+ );
291
+ }
292
+
293
+
294
+ /** Sets initial args for the block, this value must be specified. */
295
+ public initialArgs(value: Args): BlockModel<Args, OutputsCfg, UiState, Href> {
296
+ return new BlockModel<Args, OutputsCfg, UiState, Href>(
297
+ this._renderingMode,
298
+ value,
299
+ this._outputs,
300
+ this._inputsValid,
301
+ this._sections
302
+ );
303
+ }
304
+
305
+ /** Renders all provided block settings into a pre-configured platforma API
306
+ * instance, that can be used in frontend to interact with block state, and
307
+ * other features provided by the platforma to the block. */
308
+ public done(): Platforma<
309
+ Args,
310
+ InferOutputsFromConfigs<Args, OutputsCfg, UiState>,
311
+ UiState,
312
+ Href
313
+ > {
314
+ if (this._initialArgs === undefined) throw new Error('Initial arguments not set.');
315
+
316
+ const config: BlockConfig<Args, OutputsCfg> = {
317
+ sdkVersion: PlatformaSDKVersion,
318
+ renderingMode: this._renderingMode,
319
+ initialArgs: this._initialArgs,
320
+ inputsValid: this._inputsValid,
321
+ sections: this._sections,
322
+ outputs: this._outputs
323
+ };
324
+
325
+ if (!isInUI())
326
+ // we are in the configuration rendering routine, not in actual UI
327
+ return { config } as any;
328
+ // normal operation inside the UI
329
+ else return getPlatformaInstance(config) as any;
330
+ }
331
+ }
332
+
333
+ export type InferOutputType<CfgOrFH, Args, UiState> = CfgOrFH extends TypedConfig
334
+ ? ResolveCfgType<CfgOrFH, Args, UiState>
335
+ : CfgOrFH extends FunctionHandle
336
+ ? ExtractFunctionHandleReturn<CfgOrFH>
337
+ : never;
338
+
339
+ type InferOutputsFromConfigs<
340
+ Args,
341
+ OutputsCfg extends Record<string, TypedConfigOrFunctionHandle>,
342
+ UiState
343
+ > = {
344
+ [Key in keyof OutputsCfg]: ValueOrErrors<InferOutputType<OutputsCfg[Key], Args, UiState>>;
345
+ };
@@ -0,0 +1,42 @@
1
+ import { PTableRecordFilter, PTableSorting } from '@milaboratories/pl-model-common';
2
+
3
+ /** Data table state */
4
+ export type PlDataTableGridState = {
5
+ /** Includes column ordering */
6
+ columnOrder?: {
7
+ /** All colIds in order */
8
+ orderedColIds: string[];
9
+ };
10
+ /** Includes current sort columns and direction */
11
+ sort?: {
12
+ /** Sorted columns and directions in order */
13
+ sortModel: {
14
+ /** Column Id to apply the sort to. */
15
+ colId: string;
16
+ /** Sort direction */
17
+ sort: 'asc' | 'desc';
18
+ }[];
19
+ };
20
+
21
+ /** current sheet selections */
22
+ sheets?: Record<string, string>;
23
+ };
24
+
25
+ /**
26
+ * Params used to get p-table handle from the driver
27
+ */
28
+ export type PTableParams = {
29
+ sorting?: PTableSorting[];
30
+ filters?: PTableRecordFilter[];
31
+ };
32
+
33
+ /**
34
+ * PlDataTable persisted state
35
+ */
36
+ export type PlDataTableState = {
37
+ // internal ag-grid state
38
+ gridState: PlDataTableGridState;
39
+
40
+ // mapping of gridState onto the p-table data structures
41
+ pTableParams?: PTableParams;
42
+ };
@@ -0,0 +1 @@
1
+ export * from './PlDataTable';