From 0cc2a3f6137d56394187f09ab3f8504df3f398ed Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Sat, 24 Feb 2024 00:26:33 +0100 Subject: [PATCH] feat: allow to define service map Consumers of the diagram may bootstrap it with a service map that is being used during type inference. --- lib/Diagram.js | 119 ++++++++++++++++++++++++++++++++------------ lib/Diagram.spec.ts | 14 +++++- 2 files changed, 100 insertions(+), 33 deletions(-) diff --git a/lib/Diagram.js b/lib/Diagram.js index b7e21d3f1..97e19a5b2 100644 --- a/lib/Diagram.js +++ b/lib/Diagram.js @@ -12,6 +12,16 @@ import CoreModule from './core'; * } & Record } DiagramOptions */ +/** + * @template T + * @typedef {import('didi').FactoryFunction} FactoryFunction + */ + +/** + * @template T + * @typedef {import('didi').ArrayFunc} ArrayFunc + */ + /** * Bootstrap an injector from a list of modules, instantiating a number of default components * @@ -59,6 +69,7 @@ function createInjector(options) { * * @class * @constructor + * @template [ServiceMap=null] * * @example Creating a plug-in that logs whenever a shape is added to the canvas. * @@ -101,40 +112,10 @@ function createInjector(options) { */ export default function Diagram(options, injector) { - this._injector = injector = injector || createInjector(options); - - // API - - /** - * Resolves a diagram service. - * - * @template T - * - * @param {string} name The name of the service to get. - * @param {boolean} [strict=true] If false, resolve missing services to null. - * - * @return {T|null} - */ - this.get = injector.get; - - /** - * Executes a function with its dependencies injected. - * - * @template T - * - * @param {Function} func function to be invoked - * @param {InjectionContext} [context] context of the invocation - * @param {LocalsMap} [locals] locals provided - * - * @return {T|null} - */ - this.invoke = injector.invoke; + this._injector = injector || createInjector(options); // init - // indicate via event - - /** * An event indicating that all plug-ins are loaded. * @@ -157,6 +138,82 @@ export default function Diagram(options, injector) { this.get('eventBus').fire('diagram.init'); } +/** + * @overlord + * + * Resolves a diagram service. + * + * @template T + * + * @param {string} name The name of the service to get. + * + * @return {T} + */ +/** + * @overlord + * + * Resolves a diagram service. + * + * @template T + * + * @param {string} name The name of the service to get. + * @param {true} strict If false, resolve missing services to null. + * + * @return {T} + */ +/** + * @overlord + * + * Resolves a diagram service. + * + * @template T + * + * @param {string} name The name of the service to get. + * @param {boolean} strict If false, resolve missing services to null. + * + * @return {T|null} + */ +/** + * Resolves a diagram service. + * + * @template {keyof ServiceMap} Name + * + * @param {Name} name The name of the service to get. + * + * @return {ServiceMap[Name]} + */ +Diagram.prototype.get = function(name, strict) { + return this._injector.get(name, strict); +}; + +/** + * @overlord + * + * Invoke the given function, injecting dependencies. Return the result. + * + * @template T + * + * @param {FactoryFunction} func + * @param {InjectionContext} [context] + * @param {LocalsMap} [locals] + * + * @return {T} + */ +/** + * Invoke the given function, injecting dependencies provided in + * array notation. Return the result. + * + * @template T + * + * @param {ArrayFunc} func function to be invoked + * @param {InjectionContext} [context] context of the invocation + * @param {LocalsMap} [locals] locals provided + * + * @return {T} + */ +Diagram.prototype.invoke = function(func, context, locals) { + return this._injector.invoke(func, context, locals); +}; /** * Destroys the diagram diff --git a/lib/Diagram.spec.ts b/lib/Diagram.spec.ts index a7df77b80..fdf5657a7 100644 --- a/lib/Diagram.spec.ts +++ b/lib/Diagram.spec.ts @@ -1,4 +1,4 @@ -import Diagram from './Diagram'; +import Diagram from './Diagram.js'; import CommandModule from './command'; @@ -33,4 +33,14 @@ const foo = diagram.invoke((modeling: Modeling, eventBus: EventBus) => { }; }); -foo.bar = false; \ No newline at end of file +foo.bar = false; + +type ServiceMap = { + 'eventBus': EventBus +}; + +const typedDiagram = new Diagram(); + +const b = typedDiagram.get('eventBus'); + +b.on('a', (event: any) => console.log('a'));