@platforma-sdk/model 1.61.0 → 1.62.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.
- package/dist/block_model.cjs +19 -10
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +22 -5
- package/dist/block_model.js +18 -10
- package/dist/block_model.js.map +1 -1
- package/dist/columns/column_collection_builder.cjs +26 -14
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts +9 -8
- package/dist/columns/column_collection_builder.js +26 -14
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/ctx_column_sources.cjs.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +1 -1
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/index.cjs +7 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +4 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/platforma.d.ts +9 -3
- package/dist/plugin_handle.cjs.map +1 -1
- package/dist/plugin_handle.d.ts +13 -7
- package/dist/plugin_handle.js.map +1 -1
- package/dist/plugin_model.cjs +84 -12
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +121 -41
- package/dist/plugin_model.js +84 -12
- package/dist/plugin_model.js.map +1 -1
- package/dist/render/api.cjs +17 -31
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +12 -18
- package/dist/render/api.js +17 -31
- package/dist/render/api.js.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +3 -14
- package/dist/render/internal.js.map +1 -1
- package/dist/services/block_services.cjs +18 -0
- package/dist/services/block_services.cjs.map +1 -0
- package/dist/services/block_services.d.ts +18 -0
- package/dist/services/block_services.js +16 -0
- package/dist/services/block_services.js.map +1 -0
- package/dist/services/index.cjs +2 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +2 -0
- package/dist/services/service_bridge.cjs +35 -0
- package/dist/services/service_bridge.cjs.map +1 -0
- package/dist/services/service_bridge.d.ts +18 -0
- package/dist/services/service_bridge.js +33 -0
- package/dist/services/service_bridge.js.map +1 -0
- package/dist/services/service_resolve.d.ts +13 -0
- package/package.json +6 -6
- package/src/block_model.ts +49 -14
- package/src/columns/column_collection_builder.test.ts +23 -2
- package/src/columns/column_collection_builder.ts +38 -30
- package/src/columns/ctx_column_sources.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +159 -153
- package/src/components/PlDataTable/createPlDataTable/index.ts +5 -4
- package/src/index.ts +2 -0
- package/src/platforma.ts +14 -2
- package/src/plugin_handle.ts +24 -6
- package/src/plugin_model.ts +321 -82
- package/src/render/api.ts +55 -57
- package/src/render/internal.ts +3 -38
- package/src/services/block_services.ts +17 -0
- package/src/services/index.ts +3 -0
- package/src/services/service_bridge.ts +71 -0
- package/src/services/service_resolve.ts +71 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin_model.cjs","names":["DATA_MODEL_LEGACY_VERSION","DataModelBuilder"],"sources":["../src/plugin_model.ts"],"sourcesContent":["/**\n * PluginModel - Builder for creating plugin types with data model and outputs.\n *\n * Plugins are UI components with their own model logic and persistent state.\n * Block developers register plugin instances via BlockModelV3.plugin() method.\n *\n * @module plugin_model\n */\n\nimport type { BlockCodeKnownFeatureFlags } from \"@milaboratories/pl-model-common\";\nimport {\n type DataModel,\n DataModelBuilder,\n type DataRecoverFn,\n type DataVersioned,\n type TransferTarget,\n} from \"./block_migrations\";\nimport { type PluginName, DATA_MODEL_LEGACY_VERSION } from \"./block_storage\";\nimport type { PluginFactoryLike } from \"./plugin_handle\";\nimport type { PluginRenderCtx } from \"./render\";\n\n/** Symbol for internal builder creation method */\nconst FROM_BUILDER = Symbol(\"fromBuilder\");\n\n/** Symbol for internal plugin model creation — not accessible to external consumers */\nexport const CREATE_PLUGIN_MODEL = Symbol(\"createPluginModel\");\n\n/** Sentinel for PluginInstance without transferAt — no transfer possible. */\nconst NO_TRANSFER_VERSION = \"\";\n\nexport type PluginData = Record<string, unknown>;\nexport type PluginParams = undefined | Record<string, unknown>;\nexport type PluginOutputs = Record<string, unknown>;\nexport type PluginConfig = undefined | Record<string, unknown>;\n\n/**\n * Plugin data model with typed migration chain and config-aware initialization.\n *\n * @typeParam Data - Current (latest) plugin data type\n * @typeParam Versions - Map of version keys to their data types (accumulated by the chain)\n * @typeParam Config - Config type passed to init function (undefined if none)\n */\nexport class PluginDataModel<\n Data extends PluginData,\n Versions extends Record<string, unknown> = {},\n Config = undefined,\n> {\n readonly dataModel: DataModel<Data>;\n private readonly configInitFn: (config?: Config) => Data;\n\n /** @internal Phantom field to anchor the Versions type parameter. */\n declare readonly __versions?: Versions;\n\n private constructor(dataModel: DataModel<Data>, configInitFn: (config?: Config) => Data) {\n this.dataModel = dataModel;\n this.configInitFn = configInitFn;\n }\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>, Config>(\n dataModel: DataModel<Data>,\n configInitFn: (config?: Config) => Data,\n ): PluginDataModel<Data, Versions, Config> {\n return new PluginDataModel<Data, Versions, Config>(dataModel, configInitFn);\n }\n\n /** Create fresh data with optional config. */\n getDefaultData(config?: Config): DataVersioned<Data> {\n const data = this.configInitFn(config);\n return { version: this.dataModel.version, data };\n }\n}\n\n/** Internal state for plugin data model chain. */\ntype PluginChainState = {\n initialVersion: string;\n migrations: Array<{ toVersion: string; fn: (data: unknown) => unknown }>;\n recoverFn?: (version: string, data: unknown) => unknown;\n recoverAtIndex?: number;\n};\n\n/**\n * Builder for creating PluginDataModel with type-safe migrations.\n * Mirrors DataModelBuilder — same .from(), .migrate(), .recover(), .init() chain.\n *\n * @example\n * const pluginData = new PluginDataModelBuilder()\n * .from<TableData>(\"v1\")\n * .migrate<FilteredTableData>(\"v2\", (v1) => ({ ...v1, filters: [] }))\n * .init<TableConfig>((config?) => ({\n * state: createDefaultState(config?.ops),\n * filters: [],\n * }));\n */\nexport class PluginDataModelBuilder {\n from<Data extends PluginData, const V extends string>(\n version: V,\n ): PluginDataModelInitialChain<Data, Record<V, Data>> {\n return PluginDataModelInitialChain[FROM_BUILDER]<Data, Record<V, Data>>({\n initialVersion: version,\n migrations: [],\n });\n }\n}\n\n/**\n * Chain returned by .migrate(). Supports .migrate(), .recover(), .init().\n * No .upgradeLegacy() — that is only available on the initial chain.\n */\nexport class PluginDataModelChain<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> {\n protected constructor(protected readonly state: PluginChainState) {}\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelChain<Data, Versions> {\n return new PluginDataModelChain(state);\n }\n\n /**\n * Add a migration step transforming data from the current version to the next.\n */\n migrate<Next extends PluginData, const NextV extends string>(\n version: NextV,\n fn: (current: Data) => Next,\n ): PluginDataModelChain<Next, Versions & Record<NextV, Next>> {\n return PluginDataModelChain[FROM_BUILDER]<Next, Versions & Record<NextV, Next>>({\n ...this.state,\n migrations: [\n ...this.state.migrations,\n { toVersion: version, fn: fn as (data: unknown) => unknown },\n ],\n });\n }\n\n /**\n * Set a recovery handler for unknown or legacy versions.\n * Can only be called once — the returned chain has no recover() method.\n */\n recover(fn: DataRecoverFn<Data>): PluginDataModelWithRecover<Data, Versions> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Data, Versions>({\n ...this.state,\n recoverFn: fn as (version: string, data: unknown) => unknown,\n recoverAtIndex: this.state.migrations.length,\n });\n }\n\n /** Finalize the PluginDataModel. */\n init<Config = undefined>(fn: (config?: Config) => Data): PluginDataModel<Data, Versions, Config> {\n return buildPluginDataModel(this.state, fn);\n }\n}\n\n/**\n * Initial chain returned by new PluginDataModelBuilder().from().\n * Extends PluginDataModelChain with .upgradeLegacy() — available only before\n * any .migrate() calls, matching the block's DataModelInitialChain pattern.\n */\nexport class PluginDataModelInitialChain<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> extends PluginDataModelChain<Data, Versions> {\n /** @internal */\n static override [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelInitialChain<Data, Versions> {\n return new PluginDataModelInitialChain(state);\n }\n\n /**\n * Handle data from a previous plugin type occupying this slot.\n * Prepends a migration from DATA_MODEL_LEGACY_VERSION to the initial version.\n * When a plugin type changes, the old data arrives with DATA_MODEL_LEGACY_VERSION —\n * this function transforms it into the initial version, then the normal chain runs.\n *\n * Must be called right after .from() — not available after .migrate().\n * Mutually exclusive with recover().\n *\n * @param fn - Transform from old plugin's raw data to this plugin's initial data type\n */\n upgradeLegacy(fn: (data: unknown) => Data): PluginDataModelWithRecover<Data, Versions> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Data, Versions>({\n ...this.state,\n migrations: [\n { toVersion: this.state.initialVersion, fn: fn as (data: unknown) => unknown },\n ...this.state.migrations,\n ],\n initialVersion: DATA_MODEL_LEGACY_VERSION,\n });\n }\n}\n\n/**\n * Chain after .recover() — supports .migrate(), .init(). No second recover().\n */\nexport class PluginDataModelWithRecover<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> {\n private constructor(private readonly state: PluginChainState) {}\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelWithRecover<Data, Versions> {\n return new PluginDataModelWithRecover(state);\n }\n\n migrate<Next extends PluginData, const NextV extends string>(\n version: NextV,\n fn: (current: Data) => Next,\n ): PluginDataModelWithRecover<Next, Versions & Record<NextV, Next>> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Next, Versions & Record<NextV, Next>>({\n ...this.state,\n migrations: [\n ...this.state.migrations,\n { toVersion: version, fn: fn as (data: unknown) => unknown },\n ],\n });\n }\n\n init<Config = undefined>(fn: (config?: Config) => Data): PluginDataModel<Data, Versions, Config> {\n return buildPluginDataModel(this.state, fn);\n }\n}\n\n/**\n * Builds a PluginDataModel by replaying the stored chain state through DataModelBuilder.\n * @internal\n */\nfunction buildPluginDataModel<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n Config,\n>(\n state: PluginChainState,\n configInitFn: (config?: Config) => Data,\n): PluginDataModel<Data, Versions, Config> {\n // Build inner DataModel by replaying migrations through DataModelBuilder chain.\n // Uses `any` internally — type safety is maintained by the public chain types.\n let chain: any = new DataModelBuilder().from(state.initialVersion);\n\n for (let i = 0; i < state.migrations.length; i++) {\n if (state.recoverFn !== undefined && state.recoverAtIndex === i) {\n chain = chain.recover(state.recoverFn);\n }\n chain = chain.migrate(state.migrations[i].toVersion, state.migrations[i].fn);\n }\n\n // If recover was placed at or after the last migration\n if (state.recoverFn !== undefined && state.recoverAtIndex === state.migrations.length) {\n chain = chain.recover(state.recoverFn);\n }\n\n const dataModel: DataModel<Data> = chain.init(() => configInitFn());\n\n return PluginDataModel[FROM_BUILDER]<Data, Versions, Config>(dataModel, configInitFn);\n}\n\n/**\n * A named plugin instance created by `factory.create({ pluginId, ... })`.\n * Passed to both `.transfer()` (on migration chain) and `.plugin()` (on BlockModelV3).\n * Implements TransferTarget so the migration chain can accept it.\n *\n * @typeParam Id - Plugin instance ID literal type\n * @typeParam Data - Plugin data type\n * @typeParam Params - Plugin params type\n * @typeParam Outputs - Plugin outputs type\n * @typeParam TransferData - Type of data entering the plugin via transfer (never if no transfer)\n */\nexport class PluginInstance<\n Id extends string = string,\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n TransferData = never,\n> implements TransferTarget<Id, TransferData> {\n readonly id: Id;\n readonly transferVersion: string;\n /** @internal */\n readonly __transferBrand?: TransferData;\n private readonly factory: PluginModelFactory<Data, Params, Outputs, any, any>;\n private readonly config: any;\n\n private constructor(\n id: Id,\n factory: PluginModelFactory<Data, Params, Outputs, any, any>,\n transferVersion: string,\n config?: any,\n ) {\n this.id = id;\n this.factory = factory;\n this.transferVersion = transferVersion;\n this.config = config;\n }\n\n /** @internal */\n static [FROM_BUILDER]<\n Id extends string,\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n TransferData,\n >(\n id: Id,\n factory: PluginModelFactory<Data, Params, Outputs, any, any>,\n transferVersion: string,\n config?: any,\n ): PluginInstance<Id, Data, Params, Outputs, TransferData> {\n return new PluginInstance(id, factory, transferVersion, config);\n }\n\n /** @internal Create a PluginModel from this instance. Used by BlockModelV3.plugin(). */\n [CREATE_PLUGIN_MODEL](): PluginModel<Data, Params, Outputs> {\n return this.factory[CREATE_PLUGIN_MODEL](this.config);\n }\n}\n\n/**\n * Configured plugin instance returned by PluginModelFactory[CREATE_PLUGIN_MODEL]().\n * Contains the plugin's name, data model, and output definitions.\n */\nexport class PluginModel<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n> {\n /** Globally unique plugin name */\n readonly name: PluginName;\n /** Data model instance for this plugin */\n readonly dataModel: DataModel<Data>;\n /** Output definitions - functions that compute outputs from plugin context */\n readonly outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n /** Feature flags declared by this plugin */\n readonly featureFlags?: BlockCodeKnownFeatureFlags;\n /** Create fresh default data. Config (if any) is captured at creation time. */\n readonly getDefaultData: () => DataVersioned<Data>;\n\n private constructor(options: {\n name: PluginName;\n dataModel: DataModel<Data>;\n outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n getDefaultData: () => DataVersioned<Data>;\n }) {\n this.name = options.name;\n this.dataModel = options.dataModel;\n this.outputs = options.outputs;\n this.featureFlags = options.featureFlags;\n this.getDefaultData = options.getDefaultData;\n }\n\n /**\n * Internal method for creating PluginModel from factory.\n * Uses Symbol key to prevent external access.\n * @internal\n */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n >(options: {\n name: PluginName;\n dataModel: DataModel<Data>;\n outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n getDefaultData: () => DataVersioned<Data>;\n }): PluginModel<Data, Params, Outputs> {\n return new PluginModel<Data, Params, Outputs>(options);\n }\n\n /**\n * Creates a new PluginModelBuilder with a PluginDataModel (supports transfer / config).\n *\n * @example\n * const pluginData = new PluginDataModelBuilder().from<TableData>(\"v1\")\n * .migrate<FilteredTableData>(\"v2\", (v1) => ({ ...v1, filters: [] }))\n * .init<TableConfig>((config?) => ({\n * state: createDefaultState(config?.ops),\n * filters: [],\n * }));\n *\n * const myPlugin = PluginModel.define({\n * name: 'myPlugin' as PluginName,\n * data: pluginData,\n * }).build();\n */\n static define<\n Data extends PluginData,\n Params extends PluginParams = undefined,\n Versions extends Record<string, unknown> = {},\n Config extends PluginConfig = undefined,\n >(options: {\n name: PluginName;\n data: PluginDataModel<Data, Versions, Config>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelBuilder<Data, Params, {}, Config, Versions>;\n /**\n * Creates a new PluginModelBuilder with a data model factory function (backward compatible).\n *\n * @example\n * const myPlugin = PluginModel.define({\n * name: 'myPlugin' as PluginName,\n * data: (cfg) => dataModelChain.init(() => ({ value: cfg.defaultValue })),\n * }).build();\n */\n static define<\n Data extends PluginData,\n Params extends PluginParams = undefined,\n Config extends PluginConfig = undefined,\n >(options: {\n name: PluginName;\n data: (config?: Config) => DataModel<Data>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelBuilder<Data, Params, {}, Config, {}>;\n static define(options: {\n name: PluginName;\n data: PluginDataModel<any, any, any> | ((config?: any) => DataModel<any>);\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelBuilder {\n if (options.data instanceof PluginDataModel) {\n const pdm = options.data;\n return PluginModelBuilder[FROM_BUILDER]({\n name: options.name,\n dataFn: () => pdm.dataModel,\n getDefaultDataFn: (config: any) => pdm.getDefaultData(config),\n featureFlags: options.featureFlags,\n });\n }\n return PluginModelBuilder[FROM_BUILDER]({\n name: options.name,\n dataFn: options.data,\n featureFlags: options.featureFlags,\n });\n }\n}\n\n/** Plugin factory returned by PluginModelBuilder.build(). */\nexport interface PluginFactory<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n> extends PluginFactoryLike<Data, Params, Outputs> {\n /** Create a named plugin instance, optionally with transfer at a specific version. */\n create<const Id extends string, const V extends string & keyof Versions = never>(options: {\n pluginId: Id;\n transferAt?: V;\n config?: Config;\n }): PluginInstance<Id, Data, Params, Outputs, Versions[V]>;\n\n /**\n * @internal Phantom field for structural type extraction.\n * Enables InferFactoryData/InferFactoryOutputs to work via PluginFactoryLike.\n */\n readonly __types?: {\n data: Data;\n params: Params;\n outputs: Outputs;\n config: Config;\n versions: Versions;\n };\n}\n\nclass PluginModelFactory<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n> implements PluginFactory<Data, Params, Outputs, Config, Versions> {\n private readonly name: PluginName;\n private readonly dataFn: (config?: Config) => DataModel<Data>;\n private readonly getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n readonly outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n private readonly featureFlags?: BlockCodeKnownFeatureFlags;\n\n private constructor(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n }) {\n this.name = options.name;\n this.dataFn = options.dataFn;\n this.getDefaultDataFn = options.getDefaultDataFn;\n this.outputs = options.outputs;\n this.featureFlags = options.featureFlags;\n }\n\n /** @internal */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n Config extends PluginConfig,\n Versions extends Record<string, unknown>,\n >(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelFactory<Data, Params, Outputs, Config, Versions> {\n return new PluginModelFactory(options);\n }\n\n create<const Id extends string, const V extends string & keyof Versions = never>(options: {\n pluginId: Id;\n transferAt?: V;\n config?: Config;\n }): PluginInstance<Id, Data, Params, Outputs, Versions[V]> {\n const transferVersion = options.transferAt ?? NO_TRANSFER_VERSION;\n return PluginInstance[FROM_BUILDER]<Id, Data, Params, Outputs, Versions[V]>(\n options.pluginId as Id,\n this as any,\n transferVersion,\n options.config,\n );\n }\n\n /** @internal Create a PluginModel from config. Config is captured in getDefaultData closure. */\n [CREATE_PLUGIN_MODEL](config?: Config): PluginModel<Data, Params, Outputs> {\n const dataModel = this.dataFn(config);\n const getDefaultDataFn = this.getDefaultDataFn;\n return PluginModel[FROM_BUILDER]<Data, Params, Outputs>({\n name: this.name,\n dataModel,\n outputs: this.outputs,\n featureFlags: this.featureFlags,\n getDefaultData: getDefaultDataFn\n ? () => getDefaultDataFn(config)\n : () => dataModel.getDefaultData(),\n });\n }\n}\n\n/**\n * Builder for creating PluginType with type-safe output definitions.\n *\n * Use `PluginModel.define()` to create a builder instance.\n *\n * @typeParam Data - Plugin's persistent data type\n * @typeParam Params - Params derived from block's RenderCtx (optional)\n * @typeParam Config - Static configuration passed to plugin factory (optional)\n * @typeParam Outputs - Accumulated output types\n * @typeParam Versions - Version map from PluginDataModel (empty for function-based data)\n *\n * @example\n * const dataTable = PluginModel.define({\n * name: 'dataTable' as PluginName,\n * data: pluginDataModel,\n * })\n * .output('model', (ctx) => createTableModel(ctx))\n * .build();\n */\nclass PluginModelBuilder<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n> {\n private readonly name: PluginName;\n private readonly dataFn: (config?: Config) => DataModel<Data>;\n private readonly getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n private readonly outputs: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n private readonly featureFlags?: BlockCodeKnownFeatureFlags;\n\n private constructor(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs?: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n }) {\n this.name = options.name;\n this.dataFn = options.dataFn;\n this.getDefaultDataFn = options.getDefaultDataFn;\n this.outputs =\n options.outputs ??\n ({} as {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n });\n this.featureFlags = options.featureFlags;\n }\n\n /** @internal */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n Config extends PluginConfig,\n Versions extends Record<string, unknown> = {},\n >(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs?: {\n [K in keyof Outputs]: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => Outputs[K];\n };\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelBuilder<Data, Params, Outputs, Config, Versions> {\n return new PluginModelBuilder(options);\n }\n\n /**\n * Adds an output to the plugin.\n *\n * @param key - Output name\n * @param fn - Function that computes the output value from plugin context\n * @returns PluginModel with the new output added\n *\n * @example\n * .output('model', (ctx) => createModel(ctx.params.columns, ctx.data.state))\n * .output('isReady', (ctx) => ctx.params.columns !== undefined)\n */\n output<const Key extends string, T>(\n key: Key,\n fn: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => T,\n ): PluginModelBuilder<Data, Params, Outputs & { [K in Key]: T }, Config, Versions> {\n return new PluginModelBuilder<Data, Params, Outputs & { [K in Key]: T }, Config, Versions>({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n featureFlags: this.featureFlags,\n outputs: {\n ...this.outputs,\n [key]: fn,\n } as {\n [K in keyof (Outputs & { [P in Key]: T })]: (\n ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>,\n ) => (Outputs & { [P in Key]: T })[K];\n },\n });\n }\n\n /**\n * Finalizes the plugin definition and returns a PluginFactory.\n *\n * @returns Plugin factory that creates named plugin instances via .create()\n *\n * @example\n * const myPlugin = PluginModel.define({ ... })\n * .output('value', (ctx) => ctx.data.value)\n * .build();\n *\n * // Create a named instance:\n * const table = myPlugin.create({ pluginId: 'mainTable', config: { ... } });\n */\n build(): PluginFactory<Data, Params, Outputs, Config, Versions> {\n return PluginModelFactory[FROM_BUILDER]<Data, Params, Outputs, Config, Versions>({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n outputs: this.outputs,\n featureFlags: this.featureFlags,\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin_model.cjs","names":["DATA_MODEL_LEGACY_VERSION","DataModelBuilder"],"sources":["../src/plugin_model.ts"],"sourcesContent":["/**\n * PluginModel - Builder for creating plugin types with data model and outputs.\n *\n * Plugins are UI components with their own model logic and persistent state.\n * Block developers register plugin instances via BlockModelV3.plugin() method.\n *\n * @module plugin_model\n */\n\nimport type { BlockCodeKnownFeatureFlags, OutputWithStatus } from \"@milaboratories/pl-model-common\";\nimport type { ResolveModelServices, ResolveUiServices } from \"./services/service_resolve\";\nimport {\n type DataModel,\n DataModelBuilder,\n type DataRecoverFn,\n type DataVersioned,\n type TransferTarget,\n} from \"./block_migrations\";\nimport { type PluginName, DATA_MODEL_LEGACY_VERSION } from \"./block_storage\";\nimport type { PluginFactoryLike } from \"./plugin_handle\";\nimport type { PluginRenderCtx } from \"./render\";\n\n/** Symbol for internal builder creation method */\nconst FROM_BUILDER = Symbol(\"fromBuilder\");\n\n/** Output function signature for plugin render context. */\ntype PluginOutputFn<\n Data extends PluginData,\n Params extends PluginParams,\n ModelServices,\n UiServices,\n T,\n> = (\n ctx: PluginRenderCtx<\n PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>\n >,\n) => T;\n\n/** Mapped output functions for a plugin's outputs. */\ntype PluginOutputFns<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n ModelServices,\n UiServices,\n> = {\n [K in keyof Outputs]: PluginOutputFn<Data, Params, ModelServices, UiServices, Outputs[K]>;\n};\n\n/** Symbol for internal plugin model creation — not accessible to external consumers */\nexport const CREATE_PLUGIN_MODEL = Symbol(\"createPluginModel\");\n\n/** Sentinel for PluginInstance without transferAt — no transfer possible. */\nconst NO_TRANSFER_VERSION = \"\";\n\nexport type PluginData = Record<string, unknown>;\nexport type PluginParams = undefined | Record<string, unknown>;\nexport type PluginOutputs = Record<string, unknown>;\nexport type PluginConfig = undefined | Record<string, unknown>;\n\n/**\n * Plugin data model with typed migration chain and config-aware initialization.\n *\n * @typeParam Data - Current (latest) plugin data type\n * @typeParam Versions - Map of version keys to their data types (accumulated by the chain)\n * @typeParam Config - Config type passed to init function (undefined if none)\n */\nexport class PluginDataModel<\n Data extends PluginData,\n Versions extends Record<string, unknown> = {},\n Config = undefined,\n> {\n readonly dataModel: DataModel<Data>;\n private readonly configInitFn: (config?: Config) => Data;\n\n /** @internal Phantom field to anchor the Versions type parameter. */\n declare readonly __versions?: Versions;\n\n private constructor(dataModel: DataModel<Data>, configInitFn: (config?: Config) => Data) {\n this.dataModel = dataModel;\n this.configInitFn = configInitFn;\n }\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>, Config>(\n dataModel: DataModel<Data>,\n configInitFn: (config?: Config) => Data,\n ): PluginDataModel<Data, Versions, Config> {\n return new PluginDataModel<Data, Versions, Config>(dataModel, configInitFn);\n }\n\n /** Create fresh data with optional config. */\n getDefaultData(config?: Config): DataVersioned<Data> {\n const data = this.configInitFn(config);\n return { version: this.dataModel.version, data };\n }\n}\n\n/** Internal state for plugin data model chain. */\ntype PluginChainState = {\n initialVersion: string;\n migrations: Array<{ toVersion: string; fn: (data: unknown) => unknown }>;\n recoverFn?: (version: string, data: unknown) => unknown;\n recoverAtIndex?: number;\n};\n\n/** Version → persisted data shape for each migration step (third generic of `PluginModel.define` when `data` is a `PluginDataModel`). */\nexport type PluginDataModelVersions<\n M extends PluginDataModel<PluginData, Record<string, unknown>, unknown>,\n> = M extends PluginDataModel<PluginData, infer Versions, unknown> ? Versions : never;\n\n/**\n * Builder for creating PluginDataModel with type-safe migrations.\n * Mirrors DataModelBuilder — same .from(), .migrate(), .recover(), .init() chain.\n *\n * @example\n * const pluginData = new PluginDataModelBuilder()\n * .from<TableData>(\"v1\")\n * .migrate<FilteredTableData>(\"v2\", (v1) => ({ ...v1, filters: [] }))\n * .init<TableConfig>((config?) => ({\n * state: createDefaultState(config?.ops),\n * filters: [],\n * }));\n */\nexport class PluginDataModelBuilder {\n from<Data extends PluginData, const V extends string>(\n version: V,\n ): PluginDataModelInitialChain<Data, Record<V, Data>> {\n return PluginDataModelInitialChain[FROM_BUILDER]<Data, Record<V, Data>>({\n initialVersion: version,\n migrations: [],\n });\n }\n}\n\n/**\n * Chain returned by .migrate(). Supports .migrate(), .recover(), .init().\n * No .upgradeLegacy() — that is only available on the initial chain.\n */\nexport class PluginDataModelChain<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> {\n protected constructor(protected readonly state: PluginChainState) {}\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelChain<Data, Versions> {\n return new PluginDataModelChain(state);\n }\n\n /**\n * Add a migration step transforming data from the current version to the next.\n */\n migrate<Next extends PluginData, const NextV extends string>(\n version: NextV,\n fn: (current: Data) => Next,\n ): PluginDataModelChain<Next, Versions & Record<NextV, Next>> {\n return PluginDataModelChain[FROM_BUILDER]<Next, Versions & Record<NextV, Next>>({\n ...this.state,\n migrations: [\n ...this.state.migrations,\n { toVersion: version, fn: fn as (data: unknown) => unknown },\n ],\n });\n }\n\n /**\n * Set a recovery handler for unknown or legacy versions.\n * Can only be called once — the returned chain has no recover() method.\n */\n recover(fn: DataRecoverFn<Data>): PluginDataModelWithRecover<Data, Versions> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Data, Versions>({\n ...this.state,\n recoverFn: fn as (version: string, data: unknown) => unknown,\n recoverAtIndex: this.state.migrations.length,\n });\n }\n\n /** Finalize the PluginDataModel. */\n init<Config = undefined>(fn: (config?: Config) => Data): PluginDataModel<Data, Versions, Config> {\n return buildPluginDataModel(this.state, fn);\n }\n}\n\n/**\n * Initial chain returned by new PluginDataModelBuilder().from().\n * Extends PluginDataModelChain with .upgradeLegacy() — available only before\n * any .migrate() calls, matching the block's DataModelInitialChain pattern.\n */\nexport class PluginDataModelInitialChain<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> extends PluginDataModelChain<Data, Versions> {\n /** @internal */\n static override [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelInitialChain<Data, Versions> {\n return new PluginDataModelInitialChain(state);\n }\n\n /**\n * Handle data from a previous plugin type occupying this slot.\n * Prepends a migration from DATA_MODEL_LEGACY_VERSION to the initial version.\n * When a plugin type changes, the old data arrives with DATA_MODEL_LEGACY_VERSION —\n * this function transforms it into the initial version, then the normal chain runs.\n *\n * Must be called right after .from() — not available after .migrate().\n * Mutually exclusive with recover().\n *\n * @param fn - Transform from old plugin's raw data to this plugin's initial data type\n */\n upgradeLegacy(fn: (data: unknown) => Data): PluginDataModelWithRecover<Data, Versions> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Data, Versions>({\n ...this.state,\n migrations: [\n { toVersion: this.state.initialVersion, fn: fn as (data: unknown) => unknown },\n ...this.state.migrations,\n ],\n initialVersion: DATA_MODEL_LEGACY_VERSION,\n });\n }\n}\n\n/**\n * Chain after .recover() — supports .migrate(), .init(). No second recover().\n */\nexport class PluginDataModelWithRecover<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n> {\n private constructor(private readonly state: PluginChainState) {}\n\n /** @internal */\n static [FROM_BUILDER]<Data extends PluginData, Versions extends Record<string, unknown>>(\n state: PluginChainState,\n ): PluginDataModelWithRecover<Data, Versions> {\n return new PluginDataModelWithRecover(state);\n }\n\n migrate<Next extends PluginData, const NextV extends string>(\n version: NextV,\n fn: (current: Data) => Next,\n ): PluginDataModelWithRecover<Next, Versions & Record<NextV, Next>> {\n return PluginDataModelWithRecover[FROM_BUILDER]<Next, Versions & Record<NextV, Next>>({\n ...this.state,\n migrations: [\n ...this.state.migrations,\n { toVersion: version, fn: fn as (data: unknown) => unknown },\n ],\n });\n }\n\n init<Config = undefined>(fn: (config?: Config) => Data): PluginDataModel<Data, Versions, Config> {\n return buildPluginDataModel(this.state, fn);\n }\n}\n\n/**\n * Builds a PluginDataModel by replaying the stored chain state through DataModelBuilder.\n * @internal\n */\nfunction buildPluginDataModel<\n Data extends PluginData,\n Versions extends Record<string, unknown>,\n Config,\n>(\n state: PluginChainState,\n configInitFn: (config?: Config) => Data,\n): PluginDataModel<Data, Versions, Config> {\n // Build inner DataModel by replaying migrations through DataModelBuilder chain.\n // Uses `any` internally — type safety is maintained by the public chain types.\n let chain: any = new DataModelBuilder().from(state.initialVersion);\n\n for (let i = 0; i < state.migrations.length; i++) {\n if (state.recoverFn !== undefined && state.recoverAtIndex === i) {\n chain = chain.recover(state.recoverFn);\n }\n chain = chain.migrate(state.migrations[i].toVersion, state.migrations[i].fn);\n }\n\n // If recover was placed at or after the last migration\n if (state.recoverFn !== undefined && state.recoverAtIndex === state.migrations.length) {\n chain = chain.recover(state.recoverFn);\n }\n\n const dataModel: DataModel<Data> = chain.init(() => configInitFn());\n\n return PluginDataModel[FROM_BUILDER]<Data, Versions, Config>(dataModel, configInitFn);\n}\n\n/**\n * A named plugin instance created by `factory.create({ pluginId, ... })`.\n * Passed to both `.transfer()` (on migration chain) and `.plugin()` (on BlockModelV3).\n * Implements TransferTarget so the migration chain can accept it.\n *\n * @typeParam Id - Plugin instance ID literal type\n * @typeParam Data - Plugin data type\n * @typeParam Params - Plugin params type\n * @typeParam Outputs - Plugin outputs type\n * @typeParam TransferData - Type of data entering the plugin via transfer (never if no transfer)\n */\nexport class PluginInstance<\n Id extends string = string,\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n TransferData = never,\n ModelServices = unknown,\n UiServices = unknown,\n> implements TransferTarget<Id, TransferData> {\n readonly id: Id;\n readonly transferVersion: string;\n /** @internal Phantom for type inference; never set at runtime. */\n readonly __instanceTypes?: {\n data: Data;\n params: Params;\n outputs: Outputs;\n modelServices: ModelServices;\n uiServices: UiServices;\n };\n /** Bound closure that creates the PluginModel. Config is captured at factory.create() time. */\n private readonly createPluginModel: () => PluginModel<\n Data,\n Params,\n Outputs,\n ModelServices,\n UiServices\n >;\n\n private constructor(\n id: Id,\n createPluginModel: () => PluginModel<Data, Params, Outputs, ModelServices, UiServices>,\n transferVersion: string,\n ) {\n this.id = id;\n this.createPluginModel = createPluginModel;\n this.transferVersion = transferVersion;\n }\n\n /** @internal Accepts concrete Config — binds it into a closure, avoiding Config variance issues. */\n static [FROM_BUILDER]<\n Id extends string,\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n TransferData,\n Config extends PluginConfig = PluginConfig,\n ModelServices = unknown,\n UiServices = unknown,\n >(\n id: Id,\n factory: PluginModelFactory<\n Data,\n Params,\n Outputs,\n Config,\n Record<string, unknown>,\n ModelServices,\n UiServices\n >,\n transferVersion: string,\n config?: Config,\n ): PluginInstance<Id, Data, Params, Outputs, TransferData, ModelServices, UiServices> {\n return new PluginInstance(id, () => factory[CREATE_PLUGIN_MODEL](config), transferVersion);\n }\n\n /** @internal Create a PluginModel from this instance. Used by BlockModelV3.plugin(). */\n [CREATE_PLUGIN_MODEL](): PluginModel<Data, Params, Outputs, ModelServices, UiServices> {\n return this.createPluginModel();\n }\n}\n\n/**\n * Configured plugin instance returned by PluginModelFactory[CREATE_PLUGIN_MODEL]().\n * Contains the plugin's name, data model, and output definitions.\n */\nexport class PluginModel<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n ModelServices = {},\n UiServices = {},\n> {\n /** Globally unique plugin name */\n readonly name: PluginName;\n /** Data model instance for this plugin */\n readonly dataModel: DataModel<Data>;\n /** Output definitions - functions that compute outputs from plugin context */\n readonly outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n /** Per-output flags (e.g. withStatus) */\n readonly outputFlags: Record<string, { withStatus: boolean }>;\n /** Feature flags declared by this plugin */\n readonly featureFlags?: BlockCodeKnownFeatureFlags;\n /** Create fresh default data. Config (if any) is captured at creation time. */\n readonly getDefaultData: () => DataVersioned<Data>;\n\n private constructor(options: {\n name: PluginName;\n dataModel: DataModel<Data>;\n outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n getDefaultData: () => DataVersioned<Data>;\n }) {\n this.name = options.name;\n this.dataModel = options.dataModel;\n this.outputs = options.outputs;\n this.outputFlags = options.outputFlags;\n this.featureFlags = options.featureFlags;\n this.getDefaultData = options.getDefaultData;\n }\n\n /**\n * Internal method for creating PluginModel from factory.\n * Uses Symbol key to prevent external access.\n * @internal\n */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n ModelServices = {},\n UiServices = {},\n >(options: {\n name: PluginName;\n dataModel: DataModel<Data>;\n outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n getDefaultData: () => DataVersioned<Data>;\n }): PluginModel<Data, Params, Outputs, ModelServices, UiServices> {\n return new PluginModel<Data, Params, Outputs, ModelServices, UiServices>(options);\n }\n\n /**\n * Creates a new PluginModelBuilder with a PluginDataModel (supports transfer / config).\n *\n * @example\n * const pluginData = new PluginDataModelBuilder().from<TableData>(\"v1\")\n * .migrate<FilteredTableData>(\"v2\", (v1) => ({ ...v1, filters: [] }))\n * .init<TableConfig>((config?) => ({\n * state: createDefaultState(config?.ops),\n * filters: [],\n * }));\n *\n * const myPlugin = PluginModel.define({\n * name: 'myPlugin' as PluginName,\n * data: pluginData,\n * }).build();\n */\n static define<\n Data extends PluginData,\n Params extends PluginParams = undefined,\n Versions extends Record<string, unknown> = {},\n Config extends PluginConfig = undefined,\n Flags extends BlockCodeKnownFeatureFlags = {},\n >(options: {\n name: PluginName;\n data: PluginDataModel<Data, Versions, Config>;\n featureFlags?: Flags;\n }): PluginModelInitialBuilder<\n Data,\n Params,\n Config,\n Versions,\n ResolveModelServices<Flags>,\n ResolveUiServices<Flags>\n >;\n /**\n * Creates a new PluginModelBuilder with a data model factory function (backward compatible).\n *\n * @example\n * const myPlugin = PluginModel.define({\n * name: 'myPlugin' as PluginName,\n * data: (cfg) => dataModelChain.init(() => ({ value: cfg.defaultValue })),\n * }).build();\n */\n static define<\n Data extends PluginData,\n Params extends PluginParams = undefined,\n Config extends PluginConfig = undefined,\n Flags extends BlockCodeKnownFeatureFlags = {},\n >(options: {\n name: PluginName;\n data: (config?: Config) => DataModel<Data>;\n featureFlags?: Flags;\n }): PluginModelInitialBuilder<\n Data,\n Params,\n Config,\n {},\n ResolveModelServices<Flags>,\n ResolveUiServices<Flags>\n >;\n static define(options: {\n name: PluginName;\n data: PluginDataModel<any, any, any> | ((config?: any) => DataModel<any>);\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelInitialBuilder {\n if (options.data instanceof PluginDataModel) {\n const pdm = options.data;\n return PluginModelInitialBuilder.create({\n name: options.name,\n dataFn: () => pdm.dataModel,\n getDefaultDataFn: (config: any) => pdm.getDefaultData(config),\n featureFlags: options.featureFlags,\n });\n }\n return PluginModelInitialBuilder.create({\n name: options.name,\n dataFn: options.data,\n featureFlags: options.featureFlags,\n });\n }\n}\n\n/** Plugin factory returned by PluginModelBuilder.build(). */\nexport interface PluginFactory<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n> extends PluginFactoryLike<Data, Params, Outputs, ModelServices, UiServices> {\n /** Create a named plugin instance, optionally with transfer at a specific version. */\n create<const Id extends string, const V extends string & keyof Versions = never>(options: {\n pluginId: Id;\n transferAt?: V;\n config?: Config;\n }): PluginInstance<Id, Data, Params, Outputs, Versions[V], ModelServices, UiServices>;\n\n /**\n * @internal Phantom field for structural type extraction.\n * Enables InferFactoryData/InferFactoryOutputs to work via PluginFactoryLike.\n */\n readonly __types?: {\n data: Data;\n params: Params;\n outputs: Outputs;\n modelServices: ModelServices;\n uiServices: UiServices;\n config: Config;\n versions: Versions;\n };\n}\n\nclass PluginModelFactory<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n> implements PluginFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices> {\n private readonly name: PluginName;\n private readonly dataFn: (config?: Config) => DataModel<Data>;\n private readonly getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n readonly outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n private readonly outputFlags: Record<string, { withStatus: boolean }>;\n private readonly featureFlags?: BlockCodeKnownFeatureFlags;\n\n private constructor(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }) {\n this.name = options.name;\n this.dataFn = options.dataFn;\n this.getDefaultDataFn = options.getDefaultDataFn;\n this.outputs = options.outputs;\n this.outputFlags = options.outputFlags;\n this.featureFlags = options.featureFlags;\n }\n\n /** @internal */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n Config extends PluginConfig,\n Versions extends Record<string, unknown>,\n ModelServices = {},\n UiServices = {},\n >(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices> {\n return new PluginModelFactory(options);\n }\n\n create<const Id extends string, const V extends string & keyof Versions = never>(options: {\n pluginId: Id;\n transferAt?: V;\n config?: Config;\n }): PluginInstance<Id, Data, Params, Outputs, Versions[V], ModelServices, UiServices> {\n const transferVersion = options.transferAt ?? NO_TRANSFER_VERSION;\n return PluginInstance[FROM_BUILDER]<\n Id,\n Data,\n Params,\n Outputs,\n Versions[V],\n Config,\n ModelServices,\n UiServices\n >(options.pluginId as Id, this, transferVersion, options.config);\n }\n\n /** @internal Create a PluginModel from config. Config is captured in getDefaultData closure. */\n [CREATE_PLUGIN_MODEL](\n config?: Config,\n ): PluginModel<Data, Params, Outputs, ModelServices, UiServices> {\n const dataModel = this.dataFn(config);\n const getDefaultDataFn = this.getDefaultDataFn;\n return PluginModel[FROM_BUILDER]<Data, Params, Outputs, ModelServices, UiServices>({\n name: this.name,\n dataModel,\n outputs: this.outputs,\n outputFlags: this.outputFlags,\n featureFlags: this.featureFlags,\n getDefaultData: getDefaultDataFn\n ? () => getDefaultDataFn(config)\n : () => dataModel.getDefaultData(),\n });\n }\n}\n\n/**\n * Builder for creating PluginType with type-safe output definitions.\n *\n * Use `PluginModel.define()` to create a builder instance.\n *\n * @typeParam Data - Plugin's persistent data type\n * @typeParam Params - Params derived from block's RenderCtx (optional)\n * @typeParam Config - Static configuration passed to plugin factory (optional)\n * @typeParam Outputs - Accumulated output types\n * @typeParam Versions - Version map from PluginDataModel (empty for function-based data)\n *\n * @example\n * const dataTable = PluginModel.define({\n * name: 'dataTable' as PluginName,\n * data: pluginDataModel,\n * })\n * .output('model', (ctx) => createTableModel(ctx))\n * .build();\n */\nclass PluginModelBuilder<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n> {\n protected readonly name: PluginName;\n protected readonly dataFn: (config?: Config) => DataModel<Data>;\n protected readonly getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n private readonly outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n private readonly outputFlags: Record<string, { withStatus: boolean }>;\n protected readonly featureFlags?: BlockCodeKnownFeatureFlags;\n\n protected constructor(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs?: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags?: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }) {\n this.name = options.name;\n this.dataFn = options.dataFn;\n this.getDefaultDataFn = options.getDefaultDataFn;\n this.outputs =\n options.outputs ?? ({} as PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>);\n this.outputFlags = options.outputFlags ?? {};\n this.featureFlags = options.featureFlags;\n }\n\n /** @internal */\n static [FROM_BUILDER]<\n Data extends PluginData,\n Params extends PluginParams,\n Outputs extends PluginOutputs,\n Config extends PluginConfig,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n >(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n outputs?: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;\n outputFlags?: Record<string, { withStatus: boolean }>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelBuilder<Data, Params, Outputs, Config, Versions, ModelServices, UiServices> {\n return new PluginModelBuilder(options);\n }\n\n /**\n * Adds an output to the plugin.\n *\n * @param key - Output name\n * @param fn - Function that computes the output value from plugin context\n * @returns PluginModel with the new output added\n *\n * @example\n * .output('model', (ctx) => createModel(ctx.params.columns, ctx.data.state))\n * .output('isReady', (ctx) => ctx.params.columns !== undefined)\n */\n output<const Key extends string, T>(\n key: Key,\n fn: (\n ctx: PluginRenderCtx<\n PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>\n >,\n ) => T,\n ): PluginModelBuilder<\n Data,\n Params,\n Outputs & { [K in Key]: T },\n Config,\n Versions,\n ModelServices,\n UiServices\n > {\n return new PluginModelBuilder<\n Data,\n Params,\n Outputs & { [K in Key]: T },\n Config,\n Versions,\n ModelServices,\n UiServices\n >({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n featureFlags: this.featureFlags,\n outputs: {\n ...this.outputs,\n [key]: fn,\n } as {\n [K in keyof (Outputs & { [P in Key]: T })]: (\n ctx: PluginRenderCtx<\n PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>\n >,\n ) => (Outputs & { [P in Key]: T })[K];\n },\n outputFlags: { ...this.outputFlags, [key]: { withStatus: false } },\n });\n }\n\n /**\n * Adds an output wrapped with status information to the plugin.\n *\n * The UI receives the full {@link OutputWithStatus} object instead of an unwrapped value,\n * allowing it to distinguish between pending, success, and error states.\n *\n * @param key - Output name\n * @param fn - Function that computes the output value from plugin context\n * @returns PluginModel with the new status-wrapped output added\n *\n * @example\n * .outputWithStatus('table', (ctx) => {\n * const pCols = ctx.params.pFrame?.getPColumns();\n * if (pCols === undefined) return undefined;\n * return createPlDataTableV2(ctx, pCols, ctx.data.tableState);\n * })\n */\n outputWithStatus<const Key extends string, T>(\n key: Key,\n fn: (\n ctx: PluginRenderCtx<\n PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>\n >,\n ) => T,\n ): PluginModelBuilder<\n Data,\n Params,\n Outputs & { [K in Key]: OutputWithStatus<T> },\n Config,\n Versions,\n ModelServices,\n UiServices\n > {\n return new PluginModelBuilder<\n Data,\n Params,\n Outputs & { [K in Key]: OutputWithStatus<T> },\n Config,\n Versions,\n ModelServices,\n UiServices\n >({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n featureFlags: this.featureFlags,\n outputs: {\n ...this.outputs,\n [key]: fn,\n } as {\n [K in keyof (Outputs & { [P in Key]: OutputWithStatus<T> })]: (\n ctx: PluginRenderCtx<\n PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>\n >,\n ) => (Outputs & { [P in Key]: OutputWithStatus<T> })[K];\n },\n outputFlags: { ...this.outputFlags, [key]: { withStatus: true } },\n });\n }\n\n /**\n * Finalizes the plugin definition and returns a PluginFactory.\n *\n * @returns Plugin factory that creates named plugin instances via .create()\n *\n * @example\n * const myPlugin = PluginModel.define({ ... })\n * .output('value', (ctx) => ctx.data.value)\n * .build();\n *\n * // Create a named instance:\n * const table = myPlugin.create({ pluginId: 'mainTable', config: { ... } });\n */\n build(): PluginFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices> {\n return PluginModelFactory[FROM_BUILDER]<\n Data,\n Params,\n Outputs,\n Config,\n Versions,\n ModelServices,\n UiServices\n >({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n outputs: this.outputs,\n outputFlags: this.outputFlags,\n featureFlags: this.featureFlags,\n });\n }\n}\n\n/**\n * Initial builder returned by PluginModel.define(). Extends PluginModelBuilder with .params().\n * Once .params() or .output() is called, transitions to PluginModelBuilder (no second .params()).\n */\nclass PluginModelInitialBuilder<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Config extends PluginConfig = undefined,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n> extends PluginModelBuilder<Data, Params, {}, Config, Versions, ModelServices, UiServices> {\n /** @internal */\n static create<\n Data extends PluginData,\n Config extends PluginConfig,\n Versions extends Record<string, unknown> = {},\n ModelServices = {},\n UiServices = {},\n >(options: {\n name: PluginName;\n dataFn: (config?: Config) => DataModel<Data>;\n getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;\n featureFlags?: BlockCodeKnownFeatureFlags;\n }): PluginModelInitialBuilder<Data, undefined, Config, Versions, ModelServices, UiServices> {\n return new PluginModelInitialBuilder(options);\n }\n\n /**\n * Sets the Params type for this plugin — the shape of data derived from the block's\n * render context and passed into plugin output functions via `ctx.params`.\n * Must be called before .output(). Available only on the initial builder.\n *\n * @example\n * .params<{ title: string }>()\n * .output('displayText', (ctx) => ctx.params.title)\n */\n params<P extends PluginParams>(): PluginModelBuilder<\n Data,\n P,\n {},\n Config,\n Versions,\n ModelServices,\n UiServices\n > {\n return PluginModelBuilder[FROM_BUILDER]<\n Data,\n P,\n {},\n Config,\n Versions,\n ModelServices,\n UiServices\n >({\n name: this.name,\n dataFn: this.dataFn,\n getDefaultDataFn: this.getDefaultDataFn,\n featureFlags: this.featureFlags,\n });\n }\n}\n"],"mappings":"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"}
|
package/dist/plugin_model.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { PluginFactoryLike } from "./plugin_handle.js";
|
|
2
2
|
import { DataModel, DataRecoverFn, DataVersioned, TransferTarget } from "./block_migrations.js";
|
|
3
3
|
import { PluginName } from "./block_storage.js";
|
|
4
|
+
import { ResolveModelServices, ResolveUiServices } from "./services/service_resolve.js";
|
|
4
5
|
import { PluginRenderCtx } from "./render/api.js";
|
|
5
6
|
import "./render/index.js";
|
|
6
|
-
import { BlockCodeKnownFeatureFlags } from "@milaboratories/pl-model-common";
|
|
7
|
+
import { BlockCodeKnownFeatureFlags, OutputWithStatus } from "@milaboratories/pl-model-common";
|
|
7
8
|
|
|
8
9
|
//#region src/plugin_model.d.ts
|
|
9
10
|
/** Symbol for internal builder creation method */
|
|
10
11
|
declare const FROM_BUILDER: unique symbol;
|
|
12
|
+
/** Output function signature for plugin render context. */
|
|
13
|
+
type PluginOutputFn<Data extends PluginData, Params extends PluginParams, ModelServices, UiServices, T> = (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>>) => T;
|
|
14
|
+
/** Mapped output functions for a plugin's outputs. */
|
|
15
|
+
type PluginOutputFns<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, ModelServices, UiServices> = { [K in keyof Outputs]: PluginOutputFn<Data, Params, ModelServices, UiServices, Outputs[K]> };
|
|
11
16
|
/** Symbol for internal plugin model creation — not accessible to external consumers */
|
|
12
17
|
declare const CREATE_PLUGIN_MODEL: unique symbol;
|
|
13
18
|
type PluginData = Record<string, unknown>;
|
|
@@ -42,6 +47,8 @@ type PluginChainState = {
|
|
|
42
47
|
recoverFn?: (version: string, data: unknown) => unknown;
|
|
43
48
|
recoverAtIndex?: number;
|
|
44
49
|
};
|
|
50
|
+
/** Version → persisted data shape for each migration step (third generic of `PluginModel.define` when `data` is a `PluginDataModel`). */
|
|
51
|
+
type PluginDataModelVersions<M extends PluginDataModel<PluginData, Record<string, unknown>, unknown>> = M extends PluginDataModel<PluginData, infer Versions, unknown> ? Versions : never;
|
|
45
52
|
/**
|
|
46
53
|
* Builder for creating PluginDataModel with type-safe migrations.
|
|
47
54
|
* Mirrors DataModelBuilder — same .from(), .migrate(), .recover(), .init() chain.
|
|
@@ -122,30 +129,40 @@ declare class PluginDataModelWithRecover<Data extends PluginData, Versions exten
|
|
|
122
129
|
* @typeParam Outputs - Plugin outputs type
|
|
123
130
|
* @typeParam TransferData - Type of data entering the plugin via transfer (never if no transfer)
|
|
124
131
|
*/
|
|
125
|
-
declare class PluginInstance<Id extends string = string, Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, TransferData = never> implements TransferTarget<Id, TransferData> {
|
|
132
|
+
declare class PluginInstance<Id extends string = string, Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, TransferData = never, ModelServices = unknown, UiServices = unknown> implements TransferTarget<Id, TransferData> {
|
|
126
133
|
readonly id: Id;
|
|
127
134
|
readonly transferVersion: string;
|
|
128
|
-
/** @internal */
|
|
129
|
-
readonly
|
|
130
|
-
|
|
131
|
-
|
|
135
|
+
/** @internal Phantom for type inference; never set at runtime. */
|
|
136
|
+
readonly __instanceTypes?: {
|
|
137
|
+
data: Data;
|
|
138
|
+
params: Params;
|
|
139
|
+
outputs: Outputs;
|
|
140
|
+
modelServices: ModelServices;
|
|
141
|
+
uiServices: UiServices;
|
|
142
|
+
};
|
|
143
|
+
/** Bound closure that creates the PluginModel. Config is captured at factory.create() time. */
|
|
144
|
+
private readonly createPluginModel;
|
|
132
145
|
private constructor();
|
|
133
|
-
/** @internal */
|
|
134
|
-
static [FROM_BUILDER]<Id extends string, Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, TransferData>(id: Id, factory: PluginModelFactory<Data, Params, Outputs,
|
|
146
|
+
/** @internal Accepts concrete Config — binds it into a closure, avoiding Config variance issues. */
|
|
147
|
+
static [FROM_BUILDER]<Id extends string, Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, TransferData, Config extends PluginConfig = PluginConfig, ModelServices = unknown, UiServices = unknown>(id: Id, factory: PluginModelFactory<Data, Params, Outputs, Config, Record<string, unknown>, ModelServices, UiServices>, transferVersion: string, config?: Config): PluginInstance<Id, Data, Params, Outputs, TransferData, ModelServices, UiServices>;
|
|
135
148
|
/** @internal Create a PluginModel from this instance. Used by BlockModelV3.plugin(). */
|
|
136
|
-
[CREATE_PLUGIN_MODEL](): PluginModel<Data, Params, Outputs>;
|
|
149
|
+
[CREATE_PLUGIN_MODEL](): PluginModel<Data, Params, Outputs, ModelServices, UiServices>;
|
|
137
150
|
}
|
|
138
151
|
/**
|
|
139
152
|
* Configured plugin instance returned by PluginModelFactory[CREATE_PLUGIN_MODEL]().
|
|
140
153
|
* Contains the plugin's name, data model, and output definitions.
|
|
141
154
|
*/
|
|
142
|
-
declare class PluginModel<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs> {
|
|
155
|
+
declare class PluginModel<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, ModelServices = {}, UiServices = {}> {
|
|
143
156
|
/** Globally unique plugin name */
|
|
144
157
|
readonly name: PluginName;
|
|
145
158
|
/** Data model instance for this plugin */
|
|
146
159
|
readonly dataModel: DataModel<Data>;
|
|
147
160
|
/** Output definitions - functions that compute outputs from plugin context */
|
|
148
|
-
readonly outputs:
|
|
161
|
+
readonly outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
162
|
+
/** Per-output flags (e.g. withStatus) */
|
|
163
|
+
readonly outputFlags: Record<string, {
|
|
164
|
+
withStatus: boolean;
|
|
165
|
+
}>;
|
|
149
166
|
/** Feature flags declared by this plugin */
|
|
150
167
|
readonly featureFlags?: BlockCodeKnownFeatureFlags;
|
|
151
168
|
/** Create fresh default data. Config (if any) is captured at creation time. */
|
|
@@ -156,13 +173,16 @@ declare class PluginModel<Data extends PluginData = PluginData, Params extends P
|
|
|
156
173
|
* Uses Symbol key to prevent external access.
|
|
157
174
|
* @internal
|
|
158
175
|
*/
|
|
159
|
-
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs>(options: {
|
|
176
|
+
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, ModelServices = {}, UiServices = {}>(options: {
|
|
160
177
|
name: PluginName;
|
|
161
178
|
dataModel: DataModel<Data>;
|
|
162
|
-
outputs:
|
|
179
|
+
outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
180
|
+
outputFlags: Record<string, {
|
|
181
|
+
withStatus: boolean;
|
|
182
|
+
}>;
|
|
163
183
|
featureFlags?: BlockCodeKnownFeatureFlags;
|
|
164
184
|
getDefaultData: () => DataVersioned<Data>;
|
|
165
|
-
}): PluginModel<Data, Params, Outputs>;
|
|
185
|
+
}): PluginModel<Data, Params, Outputs, ModelServices, UiServices>;
|
|
166
186
|
/**
|
|
167
187
|
* Creates a new PluginModelBuilder with a PluginDataModel (supports transfer / config).
|
|
168
188
|
*
|
|
@@ -179,11 +199,11 @@ declare class PluginModel<Data extends PluginData = PluginData, Params extends P
|
|
|
179
199
|
* data: pluginData,
|
|
180
200
|
* }).build();
|
|
181
201
|
*/
|
|
182
|
-
static define<Data extends PluginData, Params extends PluginParams = undefined, Versions extends Record<string, unknown> = {}, Config extends PluginConfig = undefined>(options: {
|
|
202
|
+
static define<Data extends PluginData, Params extends PluginParams = undefined, Versions extends Record<string, unknown> = {}, Config extends PluginConfig = undefined, Flags extends BlockCodeKnownFeatureFlags = {}>(options: {
|
|
183
203
|
name: PluginName;
|
|
184
204
|
data: PluginDataModel<Data, Versions, Config>;
|
|
185
|
-
featureFlags?:
|
|
186
|
-
}):
|
|
205
|
+
featureFlags?: Flags;
|
|
206
|
+
}): PluginModelInitialBuilder<Data, Params, Config, Versions, ResolveModelServices<Flags>, ResolveUiServices<Flags>>;
|
|
187
207
|
/**
|
|
188
208
|
* Creates a new PluginModelBuilder with a data model factory function (backward compatible).
|
|
189
209
|
*
|
|
@@ -193,20 +213,20 @@ declare class PluginModel<Data extends PluginData = PluginData, Params extends P
|
|
|
193
213
|
* data: (cfg) => dataModelChain.init(() => ({ value: cfg.defaultValue })),
|
|
194
214
|
* }).build();
|
|
195
215
|
*/
|
|
196
|
-
static define<Data extends PluginData, Params extends PluginParams = undefined, Config extends PluginConfig = undefined>(options: {
|
|
216
|
+
static define<Data extends PluginData, Params extends PluginParams = undefined, Config extends PluginConfig = undefined, Flags extends BlockCodeKnownFeatureFlags = {}>(options: {
|
|
197
217
|
name: PluginName;
|
|
198
218
|
data: (config?: Config) => DataModel<Data>;
|
|
199
|
-
featureFlags?:
|
|
200
|
-
}):
|
|
219
|
+
featureFlags?: Flags;
|
|
220
|
+
}): PluginModelInitialBuilder<Data, Params, Config, {}, ResolveModelServices<Flags>, ResolveUiServices<Flags>>;
|
|
201
221
|
}
|
|
202
222
|
/** Plugin factory returned by PluginModelBuilder.build(). */
|
|
203
|
-
interface PluginFactory<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}> extends PluginFactoryLike<Data, Params, Outputs> {
|
|
223
|
+
interface PluginFactory<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}> extends PluginFactoryLike<Data, Params, Outputs, ModelServices, UiServices> {
|
|
204
224
|
/** Create a named plugin instance, optionally with transfer at a specific version. */
|
|
205
225
|
create<const Id extends string, const V extends string & keyof Versions = never>(options: {
|
|
206
226
|
pluginId: Id;
|
|
207
227
|
transferAt?: V;
|
|
208
228
|
config?: Config;
|
|
209
|
-
}): PluginInstance<Id, Data, Params, Outputs, Versions[V]>;
|
|
229
|
+
}): PluginInstance<Id, Data, Params, Outputs, Versions[V], ModelServices, UiServices>;
|
|
210
230
|
/**
|
|
211
231
|
* @internal Phantom field for structural type extraction.
|
|
212
232
|
* Enables InferFactoryData/InferFactoryOutputs to work via PluginFactoryLike.
|
|
@@ -215,32 +235,38 @@ interface PluginFactory<Data extends PluginData = PluginData, Params extends Plu
|
|
|
215
235
|
data: Data;
|
|
216
236
|
params: Params;
|
|
217
237
|
outputs: Outputs;
|
|
238
|
+
modelServices: ModelServices;
|
|
239
|
+
uiServices: UiServices;
|
|
218
240
|
config: Config;
|
|
219
241
|
versions: Versions;
|
|
220
242
|
};
|
|
221
243
|
}
|
|
222
|
-
declare class PluginModelFactory<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}> implements PluginFactory<Data, Params, Outputs, Config, Versions> {
|
|
244
|
+
declare class PluginModelFactory<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}> implements PluginFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices> {
|
|
223
245
|
private readonly name;
|
|
224
246
|
private readonly dataFn;
|
|
225
247
|
private readonly getDefaultDataFn?;
|
|
226
|
-
readonly outputs:
|
|
248
|
+
readonly outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
249
|
+
private readonly outputFlags;
|
|
227
250
|
private readonly featureFlags?;
|
|
228
251
|
private constructor();
|
|
229
252
|
/** @internal */
|
|
230
|
-
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, Config extends PluginConfig, Versions extends Record<string, unknown
|
|
253
|
+
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, Config extends PluginConfig, Versions extends Record<string, unknown>, ModelServices = {}, UiServices = {}>(options: {
|
|
231
254
|
name: PluginName;
|
|
232
255
|
dataFn: (config?: Config) => DataModel<Data>;
|
|
233
256
|
getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;
|
|
234
|
-
outputs:
|
|
257
|
+
outputs: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
258
|
+
outputFlags: Record<string, {
|
|
259
|
+
withStatus: boolean;
|
|
260
|
+
}>;
|
|
235
261
|
featureFlags?: BlockCodeKnownFeatureFlags;
|
|
236
|
-
}): PluginModelFactory<Data, Params, Outputs, Config, Versions>;
|
|
262
|
+
}): PluginModelFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices>;
|
|
237
263
|
create<const Id extends string, const V extends string & keyof Versions = never>(options: {
|
|
238
264
|
pluginId: Id;
|
|
239
265
|
transferAt?: V;
|
|
240
266
|
config?: Config;
|
|
241
|
-
}): PluginInstance<Id, Data, Params, Outputs, Versions[V]>;
|
|
267
|
+
}): PluginInstance<Id, Data, Params, Outputs, Versions[V], ModelServices, UiServices>;
|
|
242
268
|
/** @internal Create a PluginModel from config. Config is captured in getDefaultData closure. */
|
|
243
|
-
[CREATE_PLUGIN_MODEL](config?: Config): PluginModel<Data, Params, Outputs>;
|
|
269
|
+
[CREATE_PLUGIN_MODEL](config?: Config): PluginModel<Data, Params, Outputs, ModelServices, UiServices>;
|
|
244
270
|
}
|
|
245
271
|
/**
|
|
246
272
|
* Builder for creating PluginType with type-safe output definitions.
|
|
@@ -261,21 +287,34 @@ declare class PluginModelFactory<Data extends PluginData = PluginData, Params ex
|
|
|
261
287
|
* .output('model', (ctx) => createTableModel(ctx))
|
|
262
288
|
* .build();
|
|
263
289
|
*/
|
|
264
|
-
declare class PluginModelBuilder<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}> {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
290
|
+
declare class PluginModelBuilder<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Outputs extends PluginOutputs = PluginOutputs, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}> {
|
|
291
|
+
protected readonly name: PluginName;
|
|
292
|
+
protected readonly dataFn: (config?: Config) => DataModel<Data>;
|
|
293
|
+
protected readonly getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;
|
|
268
294
|
private readonly outputs;
|
|
269
|
-
private readonly
|
|
270
|
-
|
|
295
|
+
private readonly outputFlags;
|
|
296
|
+
protected readonly featureFlags?: BlockCodeKnownFeatureFlags;
|
|
297
|
+
protected constructor(options: {
|
|
298
|
+
name: PluginName;
|
|
299
|
+
dataFn: (config?: Config) => DataModel<Data>;
|
|
300
|
+
getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;
|
|
301
|
+
outputs?: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
302
|
+
outputFlags?: Record<string, {
|
|
303
|
+
withStatus: boolean;
|
|
304
|
+
}>;
|
|
305
|
+
featureFlags?: BlockCodeKnownFeatureFlags;
|
|
306
|
+
});
|
|
271
307
|
/** @internal */
|
|
272
|
-
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, Config extends PluginConfig, Versions extends Record<string, unknown> = {}>(options: {
|
|
308
|
+
static [FROM_BUILDER]<Data extends PluginData, Params extends PluginParams, Outputs extends PluginOutputs, Config extends PluginConfig, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}>(options: {
|
|
273
309
|
name: PluginName;
|
|
274
310
|
dataFn: (config?: Config) => DataModel<Data>;
|
|
275
311
|
getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;
|
|
276
|
-
outputs?:
|
|
312
|
+
outputs?: PluginOutputFns<Data, Params, Outputs, ModelServices, UiServices>;
|
|
313
|
+
outputFlags?: Record<string, {
|
|
314
|
+
withStatus: boolean;
|
|
315
|
+
}>;
|
|
277
316
|
featureFlags?: BlockCodeKnownFeatureFlags;
|
|
278
|
-
}): PluginModelBuilder<Data, Params, Outputs, Config, Versions>;
|
|
317
|
+
}): PluginModelBuilder<Data, Params, Outputs, Config, Versions, ModelServices, UiServices>;
|
|
279
318
|
/**
|
|
280
319
|
* Adds an output to the plugin.
|
|
281
320
|
*
|
|
@@ -287,7 +326,25 @@ declare class PluginModelBuilder<Data extends PluginData = PluginData, Params ex
|
|
|
287
326
|
* .output('model', (ctx) => createModel(ctx.params.columns, ctx.data.state))
|
|
288
327
|
* .output('isReady', (ctx) => ctx.params.columns !== undefined)
|
|
289
328
|
*/
|
|
290
|
-
output<const Key extends string, T>(key: Key, fn: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params>>) => T): PluginModelBuilder<Data, Params, Outputs & { [K in Key]: T }, Config, Versions>;
|
|
329
|
+
output<const Key extends string, T>(key: Key, fn: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>>) => T): PluginModelBuilder<Data, Params, Outputs & { [K in Key]: T }, Config, Versions, ModelServices, UiServices>;
|
|
330
|
+
/**
|
|
331
|
+
* Adds an output wrapped with status information to the plugin.
|
|
332
|
+
*
|
|
333
|
+
* The UI receives the full {@link OutputWithStatus} object instead of an unwrapped value,
|
|
334
|
+
* allowing it to distinguish between pending, success, and error states.
|
|
335
|
+
*
|
|
336
|
+
* @param key - Output name
|
|
337
|
+
* @param fn - Function that computes the output value from plugin context
|
|
338
|
+
* @returns PluginModel with the new status-wrapped output added
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* .outputWithStatus('table', (ctx) => {
|
|
342
|
+
* const pCols = ctx.params.pFrame?.getPColumns();
|
|
343
|
+
* if (pCols === undefined) return undefined;
|
|
344
|
+
* return createPlDataTableV2(ctx, pCols, ctx.data.tableState);
|
|
345
|
+
* })
|
|
346
|
+
*/
|
|
347
|
+
outputWithStatus<const Key extends string, T>(key: Key, fn: (ctx: PluginRenderCtx<PluginFactoryLike<Data, Params, Record<string, unknown>, ModelServices, UiServices>>) => T): PluginModelBuilder<Data, Params, Outputs & { [K in Key]: OutputWithStatus<T> }, Config, Versions, ModelServices, UiServices>;
|
|
291
348
|
/**
|
|
292
349
|
* Finalizes the plugin definition and returns a PluginFactory.
|
|
293
350
|
*
|
|
@@ -301,8 +358,31 @@ declare class PluginModelBuilder<Data extends PluginData = PluginData, Params ex
|
|
|
301
358
|
* // Create a named instance:
|
|
302
359
|
* const table = myPlugin.create({ pluginId: 'mainTable', config: { ... } });
|
|
303
360
|
*/
|
|
304
|
-
build(): PluginFactory<Data, Params, Outputs, Config, Versions>;
|
|
361
|
+
build(): PluginFactory<Data, Params, Outputs, Config, Versions, ModelServices, UiServices>;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Initial builder returned by PluginModel.define(). Extends PluginModelBuilder with .params().
|
|
365
|
+
* Once .params() or .output() is called, transitions to PluginModelBuilder (no second .params()).
|
|
366
|
+
*/
|
|
367
|
+
declare class PluginModelInitialBuilder<Data extends PluginData = PluginData, Params extends PluginParams = undefined, Config extends PluginConfig = undefined, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}> extends PluginModelBuilder<Data, Params, {}, Config, Versions, ModelServices, UiServices> {
|
|
368
|
+
/** @internal */
|
|
369
|
+
static create<Data extends PluginData, Config extends PluginConfig, Versions extends Record<string, unknown> = {}, ModelServices = {}, UiServices = {}>(options: {
|
|
370
|
+
name: PluginName;
|
|
371
|
+
dataFn: (config?: Config) => DataModel<Data>;
|
|
372
|
+
getDefaultDataFn?: (config?: Config) => DataVersioned<Data>;
|
|
373
|
+
featureFlags?: BlockCodeKnownFeatureFlags;
|
|
374
|
+
}): PluginModelInitialBuilder<Data, undefined, Config, Versions, ModelServices, UiServices>;
|
|
375
|
+
/**
|
|
376
|
+
* Sets the Params type for this plugin — the shape of data derived from the block's
|
|
377
|
+
* render context and passed into plugin output functions via `ctx.params`.
|
|
378
|
+
* Must be called before .output(). Available only on the initial builder.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* .params<{ title: string }>()
|
|
382
|
+
* .output('displayText', (ctx) => ctx.params.title)
|
|
383
|
+
*/
|
|
384
|
+
params<P extends PluginParams>(): PluginModelBuilder<Data, P, {}, Config, Versions, ModelServices, UiServices>;
|
|
305
385
|
}
|
|
306
386
|
//#endregion
|
|
307
|
-
export { PluginConfig, PluginData, PluginDataModel, PluginDataModelBuilder, PluginFactory, PluginInstance, PluginModel, PluginOutputs, PluginParams };
|
|
387
|
+
export { PluginConfig, PluginData, PluginDataModel, PluginDataModelBuilder, PluginDataModelVersions, PluginFactory, PluginInstance, PluginModel, PluginOutputs, PluginParams };
|
|
308
388
|
//# sourceMappingURL=plugin_model.d.ts.map
|
package/dist/plugin_model.js
CHANGED
|
@@ -180,23 +180,22 @@ function buildPluginDataModel(state, configInitFn) {
|
|
|
180
180
|
var PluginInstance = class PluginInstance {
|
|
181
181
|
id;
|
|
182
182
|
transferVersion;
|
|
183
|
-
/** @internal */
|
|
184
|
-
|
|
185
|
-
factory
|
|
186
|
-
|
|
187
|
-
constructor(id,
|
|
183
|
+
/** @internal Phantom for type inference; never set at runtime. */
|
|
184
|
+
__instanceTypes;
|
|
185
|
+
/** Bound closure that creates the PluginModel. Config is captured at factory.create() time. */
|
|
186
|
+
createPluginModel;
|
|
187
|
+
constructor(id, createPluginModel, transferVersion) {
|
|
188
188
|
this.id = id;
|
|
189
|
-
this.
|
|
189
|
+
this.createPluginModel = createPluginModel;
|
|
190
190
|
this.transferVersion = transferVersion;
|
|
191
|
-
this.config = config;
|
|
192
191
|
}
|
|
193
|
-
/** @internal */
|
|
192
|
+
/** @internal Accepts concrete Config — binds it into a closure, avoiding Config variance issues. */
|
|
194
193
|
static [FROM_BUILDER](id, factory, transferVersion, config) {
|
|
195
|
-
return new PluginInstance(id, factory, transferVersion
|
|
194
|
+
return new PluginInstance(id, () => factory[CREATE_PLUGIN_MODEL](config), transferVersion);
|
|
196
195
|
}
|
|
197
196
|
/** @internal Create a PluginModel from this instance. Used by BlockModelV3.plugin(). */
|
|
198
197
|
[CREATE_PLUGIN_MODEL]() {
|
|
199
|
-
return this.
|
|
198
|
+
return this.createPluginModel();
|
|
200
199
|
}
|
|
201
200
|
};
|
|
202
201
|
/**
|
|
@@ -210,6 +209,8 @@ var PluginModel = class PluginModel {
|
|
|
210
209
|
dataModel;
|
|
211
210
|
/** Output definitions - functions that compute outputs from plugin context */
|
|
212
211
|
outputs;
|
|
212
|
+
/** Per-output flags (e.g. withStatus) */
|
|
213
|
+
outputFlags;
|
|
213
214
|
/** Feature flags declared by this plugin */
|
|
214
215
|
featureFlags;
|
|
215
216
|
/** Create fresh default data. Config (if any) is captured at creation time. */
|
|
@@ -218,6 +219,7 @@ var PluginModel = class PluginModel {
|
|
|
218
219
|
this.name = options.name;
|
|
219
220
|
this.dataModel = options.dataModel;
|
|
220
221
|
this.outputs = options.outputs;
|
|
222
|
+
this.outputFlags = options.outputFlags;
|
|
221
223
|
this.featureFlags = options.featureFlags;
|
|
222
224
|
this.getDefaultData = options.getDefaultData;
|
|
223
225
|
}
|
|
@@ -232,14 +234,14 @@ var PluginModel = class PluginModel {
|
|
|
232
234
|
static define(options) {
|
|
233
235
|
if (options.data instanceof PluginDataModel) {
|
|
234
236
|
const pdm = options.data;
|
|
235
|
-
return
|
|
237
|
+
return PluginModelInitialBuilder.create({
|
|
236
238
|
name: options.name,
|
|
237
239
|
dataFn: () => pdm.dataModel,
|
|
238
240
|
getDefaultDataFn: (config) => pdm.getDefaultData(config),
|
|
239
241
|
featureFlags: options.featureFlags
|
|
240
242
|
});
|
|
241
243
|
}
|
|
242
|
-
return
|
|
244
|
+
return PluginModelInitialBuilder.create({
|
|
243
245
|
name: options.name,
|
|
244
246
|
dataFn: options.data,
|
|
245
247
|
featureFlags: options.featureFlags
|
|
@@ -251,12 +253,14 @@ var PluginModelFactory = class PluginModelFactory {
|
|
|
251
253
|
dataFn;
|
|
252
254
|
getDefaultDataFn;
|
|
253
255
|
outputs;
|
|
256
|
+
outputFlags;
|
|
254
257
|
featureFlags;
|
|
255
258
|
constructor(options) {
|
|
256
259
|
this.name = options.name;
|
|
257
260
|
this.dataFn = options.dataFn;
|
|
258
261
|
this.getDefaultDataFn = options.getDefaultDataFn;
|
|
259
262
|
this.outputs = options.outputs;
|
|
263
|
+
this.outputFlags = options.outputFlags;
|
|
260
264
|
this.featureFlags = options.featureFlags;
|
|
261
265
|
}
|
|
262
266
|
/** @internal */
|
|
@@ -275,6 +279,7 @@ var PluginModelFactory = class PluginModelFactory {
|
|
|
275
279
|
name: this.name,
|
|
276
280
|
dataModel,
|
|
277
281
|
outputs: this.outputs,
|
|
282
|
+
outputFlags: this.outputFlags,
|
|
278
283
|
featureFlags: this.featureFlags,
|
|
279
284
|
getDefaultData: getDefaultDataFn ? () => getDefaultDataFn(config) : () => dataModel.getDefaultData()
|
|
280
285
|
});
|
|
@@ -304,12 +309,14 @@ var PluginModelBuilder = class PluginModelBuilder {
|
|
|
304
309
|
dataFn;
|
|
305
310
|
getDefaultDataFn;
|
|
306
311
|
outputs;
|
|
312
|
+
outputFlags;
|
|
307
313
|
featureFlags;
|
|
308
314
|
constructor(options) {
|
|
309
315
|
this.name = options.name;
|
|
310
316
|
this.dataFn = options.dataFn;
|
|
311
317
|
this.getDefaultDataFn = options.getDefaultDataFn;
|
|
312
318
|
this.outputs = options.outputs ?? {};
|
|
319
|
+
this.outputFlags = options.outputFlags ?? {};
|
|
313
320
|
this.featureFlags = options.featureFlags;
|
|
314
321
|
}
|
|
315
322
|
/** @internal */
|
|
@@ -336,6 +343,43 @@ var PluginModelBuilder = class PluginModelBuilder {
|
|
|
336
343
|
outputs: {
|
|
337
344
|
...this.outputs,
|
|
338
345
|
[key]: fn
|
|
346
|
+
},
|
|
347
|
+
outputFlags: {
|
|
348
|
+
...this.outputFlags,
|
|
349
|
+
[key]: { withStatus: false }
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Adds an output wrapped with status information to the plugin.
|
|
355
|
+
*
|
|
356
|
+
* The UI receives the full {@link OutputWithStatus} object instead of an unwrapped value,
|
|
357
|
+
* allowing it to distinguish between pending, success, and error states.
|
|
358
|
+
*
|
|
359
|
+
* @param key - Output name
|
|
360
|
+
* @param fn - Function that computes the output value from plugin context
|
|
361
|
+
* @returns PluginModel with the new status-wrapped output added
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* .outputWithStatus('table', (ctx) => {
|
|
365
|
+
* const pCols = ctx.params.pFrame?.getPColumns();
|
|
366
|
+
* if (pCols === undefined) return undefined;
|
|
367
|
+
* return createPlDataTableV2(ctx, pCols, ctx.data.tableState);
|
|
368
|
+
* })
|
|
369
|
+
*/
|
|
370
|
+
outputWithStatus(key, fn) {
|
|
371
|
+
return new PluginModelBuilder({
|
|
372
|
+
name: this.name,
|
|
373
|
+
dataFn: this.dataFn,
|
|
374
|
+
getDefaultDataFn: this.getDefaultDataFn,
|
|
375
|
+
featureFlags: this.featureFlags,
|
|
376
|
+
outputs: {
|
|
377
|
+
...this.outputs,
|
|
378
|
+
[key]: fn
|
|
379
|
+
},
|
|
380
|
+
outputFlags: {
|
|
381
|
+
...this.outputFlags,
|
|
382
|
+
[key]: { withStatus: true }
|
|
339
383
|
}
|
|
340
384
|
});
|
|
341
385
|
}
|
|
@@ -358,6 +402,34 @@ var PluginModelBuilder = class PluginModelBuilder {
|
|
|
358
402
|
dataFn: this.dataFn,
|
|
359
403
|
getDefaultDataFn: this.getDefaultDataFn,
|
|
360
404
|
outputs: this.outputs,
|
|
405
|
+
outputFlags: this.outputFlags,
|
|
406
|
+
featureFlags: this.featureFlags
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
/**
|
|
411
|
+
* Initial builder returned by PluginModel.define(). Extends PluginModelBuilder with .params().
|
|
412
|
+
* Once .params() or .output() is called, transitions to PluginModelBuilder (no second .params()).
|
|
413
|
+
*/
|
|
414
|
+
var PluginModelInitialBuilder = class PluginModelInitialBuilder extends PluginModelBuilder {
|
|
415
|
+
/** @internal */
|
|
416
|
+
static create(options) {
|
|
417
|
+
return new PluginModelInitialBuilder(options);
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Sets the Params type for this plugin — the shape of data derived from the block's
|
|
421
|
+
* render context and passed into plugin output functions via `ctx.params`.
|
|
422
|
+
* Must be called before .output(). Available only on the initial builder.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* .params<{ title: string }>()
|
|
426
|
+
* .output('displayText', (ctx) => ctx.params.title)
|
|
427
|
+
*/
|
|
428
|
+
params() {
|
|
429
|
+
return PluginModelBuilder[FROM_BUILDER]({
|
|
430
|
+
name: this.name,
|
|
431
|
+
dataFn: this.dataFn,
|
|
432
|
+
getDefaultDataFn: this.getDefaultDataFn,
|
|
361
433
|
featureFlags: this.featureFlags
|
|
362
434
|
});
|
|
363
435
|
}
|