@bettercorp/service-base
Advanced tools
Comparing version 8.5.52 to 8.5.53
@@ -67,3 +67,5 @@ "use strict"; | ||
this.log = new __1.PluginLogger(this.mode, this._CORE_PLUGIN_NAME, this.logging); | ||
this.log.info("Starting BSB"); | ||
this.log.info("Starting BSB [{mode}]", { | ||
mode: this.mode, | ||
}); | ||
this.services = new services(this._appId, this.mode, this.cwd, this.plugins, this.logging); | ||
@@ -93,3 +95,3 @@ process.stdin.resume(); | ||
this._startKeep(exports.BOOT_STAT_KEYS.INIT); | ||
await this.services.init(this.config); | ||
await this.services.init(); | ||
this._outputKeep(exports.BOOT_STAT_KEYS.INIT); | ||
@@ -101,3 +103,3 @@ } | ||
await this.events.run(); | ||
await this.services.run(this.config); | ||
await this.services.run(); | ||
this.log.info("Disposing config for memory cleanup and safety"); | ||
@@ -104,0 +106,0 @@ this.config.dispose(); |
@@ -1,2 +0,12 @@ | ||
import { BSBService, DEBUG_MODE, SBConfig, SBEvents, SBLogging, SBPlugins, IPluginDefinition, LoadedPlugin } from "../"; | ||
import { BSBService, DEBUG_MODE, SBConfig, SBEvents, SBLogging, SBPlugins, IPluginDefinition, BSBServiceClient, LoadedPlugin } from "../"; | ||
interface SortedPlugin { | ||
type: "service" | "client"; | ||
srcPluginName: string; | ||
pluginName: string; | ||
initBeforePlugins?: string[]; | ||
initAfterPlugins?: string[]; | ||
runBeforePlugins?: string[]; | ||
runAfterPlugins?: string[]; | ||
reference: BSBService | BSBServiceClient<any>; | ||
} | ||
export declare class SBServices { | ||
@@ -11,2 +21,3 @@ private _activeServices; | ||
dispose(): void; | ||
private remapDeps; | ||
setup(sbConfig: SBConfig, sbLogging: SBLogging, sbEvents: SBEvents): Promise<void>; | ||
@@ -17,27 +28,7 @@ private setupPluginClient; | ||
private addService; | ||
private initPluginClient; | ||
init(sbConfig: SBConfig): Promise<void>; | ||
makeBeforeRequired(orderOfPlugins: { | ||
name: string; | ||
after: string[]; | ||
before: string[]; | ||
ref: BSBService; | ||
}[]): Promise<{ | ||
name: string; | ||
after: string[]; | ||
before: string[]; | ||
ref: BSBService; | ||
}[]>; | ||
makeAfterRequired(orderOfPlugins: { | ||
name: string; | ||
after: string[]; | ||
before: string[]; | ||
ref: BSBService; | ||
}[]): Promise<{ | ||
name: string; | ||
after: string[]; | ||
before: string[]; | ||
ref: BSBService; | ||
}[]>; | ||
run(sbConfig: SBConfig): Promise<void>; | ||
init(): Promise<void>; | ||
sortAndRunOrInitPlugins(plugins: SortedPlugin[], type: "init" | "run"): Promise<void>; | ||
private getTextReportedDeps; | ||
run(): Promise<void>; | ||
} | ||
export {}; |
@@ -30,2 +30,8 @@ "use strict"; | ||
} | ||
async remapDeps(sbConfig, ref) { | ||
ref.initBeforePlugins = await this.mapServicePlugins(sbConfig, ref.pluginName, ref.initBeforePlugins ?? []); | ||
ref.initAfterPlugins = await this.mapServicePlugins(sbConfig, ref.pluginName, ref.initAfterPlugins ?? []); | ||
ref.runBeforePlugins = await this.mapServicePlugins(sbConfig, ref.pluginName, ref.runBeforePlugins ?? []); | ||
ref.runAfterPlugins = await this.mapServicePlugins(sbConfig, ref.pluginName, ref.runAfterPlugins ?? []); | ||
} | ||
async setup(sbConfig, sbLogging, sbEvents) { | ||
@@ -42,2 +48,18 @@ this.log.debug("SETUP SBServices"); | ||
} | ||
for (const activeService of this._activeServices) { | ||
await this.remapDeps(sbConfig, activeService); | ||
for (const client of activeService._clients) { | ||
this.log.debug("Construct {pluginName} client {clientName}", { | ||
pluginName: activeService.pluginName, | ||
clientName: client.pluginName, | ||
}); | ||
await this.remapDeps(sbConfig, client); | ||
await this.setupPluginClient(sbConfig, sbLogging, sbEvents, activeService, client); | ||
this.log.debug("Setup {pluginName} client {asOriginalPluginName} as {clientName}", { | ||
pluginName: activeService.pluginName, | ||
clientName: client.pluginName, | ||
asOriginalPluginName: client._pluginName, | ||
}); | ||
} | ||
} | ||
this.log.debug("SETUP SBServices: Completed"); | ||
@@ -52,6 +74,29 @@ } | ||
clientContext.events = new __1.PluginEvents(this.mode, sbEvents, clientContext); | ||
context.initBeforePlugins = (context.initBeforePlugins ?? []).concat(clientContext.initBeforePlugins ?? []); | ||
context.initAfterPlugins = (context.initAfterPlugins ?? []).concat(clientContext.initAfterPlugins ?? []); | ||
context.runBeforePlugins = (context.runBeforePlugins ?? []).concat(clientContext.runBeforePlugins ?? []); | ||
context.runAfterPlugins = (context.runAfterPlugins ?? []).concat(clientContext.runAfterPlugins ?? []); | ||
if (contextPlugin.enabled) { | ||
const referencedServiceContext = this._activeServices.find((x) => x.pluginName === contextPlugin.name); | ||
if (referencedServiceContext === undefined) { | ||
throw new __1.BSBError("The plugin {plugin} is not enabled so you cannot call methods from it", { | ||
plugin: contextPlugin.name, | ||
}); | ||
} | ||
if (referencedServiceContext.methods === null) { | ||
throw new __1.BSBError("The plugin {plugin} does not have any callable methods", { | ||
plugin: contextPlugin.name, | ||
}); | ||
} | ||
clientContext.callMethod = (method, ...args) => { | ||
if (referencedServiceContext.methods[method] === undefined) { | ||
throw new __1.BSBError("The plugin {plugin} does not have a method called {method}", { | ||
plugin: contextPlugin.name, | ||
method, | ||
}); | ||
} | ||
return (0, __1.SmartFunctionCallThroughAsync)(referencedServiceContext, referencedServiceContext.methods[method], ...args); | ||
}; | ||
} | ||
else { | ||
this.log.warn("Plugin {plugin} is not enabled", { | ||
plugin: contextPlugin.name, | ||
}); | ||
} | ||
}; | ||
@@ -90,14 +135,2 @@ async mapServicePlugins(sbConfig, referencedPluginName, ...sourcePluginsList) { | ||
}); | ||
for (const client of servicePlugin._clients) { | ||
this.log.debug("Construct {pluginName} client {clientName}", { | ||
pluginName: plugin.name, | ||
clientName: client.pluginName, | ||
}); | ||
await this.setupPluginClient(sbConfig, sbLogging, sbEvents, servicePlugin, client); | ||
this.log.debug("Setup {pluginName} client {asOriginalPluginName} as {clientName}", { | ||
pluginName: plugin.name, | ||
clientName: client.pluginName, | ||
asOriginalPluginName: client._pluginName, | ||
}); | ||
} | ||
this._activeServices.push(servicePlugin); | ||
@@ -145,128 +178,141 @@ this.log.info("Ready {pluginName} ({mappedName})", { | ||
} | ||
initPluginClient = async (sbConfig, clientContext) => { | ||
const contextPlugin = await sbConfig.getServicePluginDefinition(clientContext._pluginName); | ||
if (contextPlugin.enabled) { | ||
const referencedServiceContext = this._activeServices.find((x) => x.pluginName === contextPlugin.name); | ||
if (referencedServiceContext === undefined) { | ||
throw new __1.BSBError("The plugin {plugin} is not enabled so you cannot call methods from it", { | ||
plugin: contextPlugin.name, | ||
}); | ||
} | ||
if (referencedServiceContext.methods === null) { | ||
throw new __1.BSBError("The plugin {plugin} does not have any callable methods", { | ||
plugin: contextPlugin.name, | ||
}); | ||
} | ||
clientContext.callMethod = (method, ...args) => { | ||
if (referencedServiceContext.methods[method] === undefined) { | ||
throw new __1.BSBError("The plugin {plugin} does not have a method called {method}", { | ||
plugin: contextPlugin.name, | ||
method, | ||
}); | ||
} | ||
return (0, __1.SmartFunctionCallThroughAsync)(referencedServiceContext, referencedServiceContext.methods[method], ...args); | ||
}; | ||
} | ||
await (0, __1.SmartFunctionCallSync)(clientContext, clientContext.init); | ||
}; | ||
async init(sbConfig) { | ||
async init() { | ||
this.log.info("Init all services"); | ||
const list = []; | ||
for (const service of this._activeServices) { | ||
this.log.debug("Mapping required plugins list for {plugin}", { | ||
this.log.debug("Mapping required plugins list for {plugin} [initBeforePlugins:{initBeforePlugins}][initAfterPlugins:{initAfterPlugins}]", { | ||
plugin: service.pluginName, | ||
initBeforePlugins: this.getTextReportedDeps(service.initBeforePlugins), | ||
initAfterPlugins: this.getTextReportedDeps(service.initAfterPlugins), | ||
}); | ||
service.initBeforePlugins = await this.mapServicePlugins(sbConfig, service.pluginName, service.initBeforePlugins); | ||
service.initAfterPlugins = await this.mapServicePlugins(sbConfig, service.pluginName, service.initAfterPlugins ?? []); | ||
} | ||
this.log.info("Defining service order"); | ||
const orderOfPlugins = await this.makeAfterRequired(await this.makeBeforeRequired(this._activeServices.map((x) => { | ||
return { | ||
name: x.pluginName, | ||
after: x.initAfterPlugins || [], | ||
before: x.initBeforePlugins || [], | ||
ref: x, | ||
}; | ||
}))); | ||
this.log.debug("Services init default order: {initOrder}", { | ||
initOrder: this._activeServices | ||
.map((x) => `[(${(x.initAfterPlugins || []).join(",")})${x.pluginName}(${(x.initBeforePlugins || []).join(",")})]`) | ||
.join(","), | ||
}); | ||
this.log.debug("Services init order: {initOrder}", { | ||
initOrder: orderOfPlugins | ||
.map((x) => `[(${x.after.join(",")})${x.name}(${x.before.join(",")})]`) | ||
.join(","), | ||
}); | ||
for (const service of orderOfPlugins) { | ||
this.log.debug(`Init {plugin}`, { | ||
plugin: service.name, | ||
list.push({ | ||
type: "service", | ||
srcPluginName: service.pluginName, | ||
pluginName: service.pluginName, | ||
initBeforePlugins: service.initBeforePlugins, | ||
initAfterPlugins: service.initAfterPlugins, | ||
runBeforePlugins: service.runBeforePlugins, | ||
runAfterPlugins: service.runAfterPlugins, | ||
reference: service, | ||
}); | ||
for (const client of service.ref._clients) { | ||
await this.initPluginClient(sbConfig, client); | ||
for (const client of service._clients) { | ||
this.log.debug(" - {plugin} -> {client} [initBeforePlugins:{initBeforePlugins}][initAfterPlugins:{initAfterPlugins}]", { | ||
plugin: service.pluginName, | ||
client: client.pluginName, | ||
initBeforePlugins: this.getTextReportedDeps(client.initBeforePlugins), | ||
initAfterPlugins: this.getTextReportedDeps(client.initAfterPlugins), | ||
}); | ||
list.push({ | ||
type: "client", | ||
srcPluginName: service.pluginName, | ||
pluginName: client.pluginName, | ||
initBeforePlugins: client.initBeforePlugins, | ||
initAfterPlugins: client.initAfterPlugins, | ||
runBeforePlugins: client.runBeforePlugins, | ||
runAfterPlugins: client.runAfterPlugins, | ||
reference: client, | ||
}); | ||
} | ||
(0, __1.SmartFunctionCallAsync)(service.ref, service.ref.init); | ||
} | ||
await this.sortAndRunOrInitPlugins(list, "init"); | ||
} | ||
async makeBeforeRequired(orderOfPlugins) { | ||
for (let i = 0; i < orderOfPlugins.length; i++) { | ||
if (orderOfPlugins[i].before.length === 0) | ||
continue; | ||
for (const bPlugin of orderOfPlugins[i].before) | ||
for (let j = 0; j < orderOfPlugins.length; j++) { | ||
if (orderOfPlugins[j].name == bPlugin) { | ||
orderOfPlugins[j].after.push(orderOfPlugins[i].name); | ||
async sortAndRunOrInitPlugins(plugins, type) { | ||
const pluginMap = new Map(); | ||
for (let i = 0; i < plugins.length; i++) { | ||
pluginMap.set(plugins[i].pluginName, plugins[i]); | ||
} | ||
const visitPlugin = (plugin, resolved, unresolved) => { | ||
unresolved.push(plugin); | ||
const before = (type === "init" | ||
? plugin.initBeforePlugins | ||
: plugin.runBeforePlugins) ?? []; | ||
for (let i = 0; i < before.length; i++) { | ||
const beforePluginName = before[i]; | ||
const beforePlugin = pluginMap.get(beforePluginName); | ||
if (!beforePlugin) { | ||
throw new Error(`Plugin ${beforePluginName} required by ${plugin.pluginName} not found`); | ||
} | ||
if (!resolved.includes(beforePlugin)) { | ||
if (unresolved.includes(beforePlugin)) { | ||
throw new __1.BSBError("Circular dependency detected: {plugin1}<>{plugin2}", { | ||
plugin1: plugin.pluginName, | ||
plugin2: beforePlugin.pluginName, | ||
}); | ||
} | ||
visitPlugin(beforePlugin, resolved, unresolved); | ||
} | ||
} | ||
return orderOfPlugins; | ||
} | ||
async makeAfterRequired(orderOfPlugins) { | ||
for (let i = 0; i < orderOfPlugins.length - 1; i++) { | ||
for (let j = i + 1; j < orderOfPlugins.length; j++) { | ||
if (orderOfPlugins[i].after.indexOf(orderOfPlugins[j].name) >= 0) { | ||
const temp = orderOfPlugins[i]; | ||
orderOfPlugins[i] = orderOfPlugins[j]; | ||
orderOfPlugins[j] = temp; | ||
} | ||
} | ||
resolved.push(plugin); | ||
unresolved.splice(unresolved.indexOf(plugin), 1); | ||
}; | ||
const sortedPlugins = []; | ||
for (let i = 0; i < plugins.length; i++) { | ||
if (!sortedPlugins.includes(plugins[i])) { | ||
visitPlugin(plugins[i], sortedPlugins, []); | ||
} | ||
} | ||
return orderOfPlugins; | ||
for (let i = 0; i < sortedPlugins.length; i++) { | ||
this.log.debug("Plugin {pluginName}({ptype}) trigger {type} before {beforePlugins} and after {afterPlugins}", { | ||
ptype: sortedPlugins[i].type + | ||
(sortedPlugins[i].type === "client" | ||
? ` on ${sortedPlugins[i].srcPluginName}` | ||
: ""), | ||
pluginName: sortedPlugins[i].pluginName, | ||
type, | ||
beforePlugins: this.getTextReportedDeps(type === "init" | ||
? sortedPlugins[i].initBeforePlugins | ||
: sortedPlugins[i].runBeforePlugins), | ||
afterPlugins: this.getTextReportedDeps(type === "init" | ||
? sortedPlugins[i].initAfterPlugins | ||
: sortedPlugins[i].runAfterPlugins), | ||
}); | ||
await (0, __1.SmartFunctionCallAsync)(sortedPlugins[i].reference, sortedPlugins[i].reference[type]); | ||
} | ||
} | ||
async run(sbConfig) { | ||
getTextReportedDeps(list) { | ||
if (list === undefined) | ||
return "ANY"; | ||
if (list.length === 0) | ||
return "ANY"; | ||
return list.join(", "); | ||
} | ||
async run() { | ||
this.log.info("Run all services"); | ||
const list = []; | ||
for (const service of this._activeServices) { | ||
this.log.debug("Mapping required plugins list for {plugin}", { | ||
this.log.debug("Mapping required plugins list for {plugin} [runBeforePlugins:{runBeforePlugins}][runAfterPlugins:{runAfterPlugins}]", { | ||
plugin: service.pluginName, | ||
runBeforePlugins: this.getTextReportedDeps(service.runBeforePlugins), | ||
runAfterPlugins: this.getTextReportedDeps(service.runAfterPlugins), | ||
}); | ||
service.runBeforePlugins = await this.mapServicePlugins(sbConfig, service.pluginName, service.runBeforePlugins ?? []); | ||
service.runAfterPlugins = await this.mapServicePlugins(sbConfig, service.pluginName, service.runAfterPlugins ?? []); | ||
} | ||
this.log.info("Defining service order"); | ||
const orderOfPlugins = await this.makeAfterRequired(await this.makeBeforeRequired(this._activeServices.map((x) => { | ||
return { | ||
name: x.pluginName, | ||
after: x.runBeforePlugins || [], | ||
before: x.runAfterPlugins || [], | ||
ref: x, | ||
}; | ||
}))); | ||
this.log.debug("Services run default order: {runOrder}", { | ||
runOrder: this._activeServices | ||
.map((x) => `[(${(x.runBeforePlugins || []).join(",")})${x.pluginName}(${(x.runAfterPlugins || []).join(",")})]`) | ||
.join(","), | ||
}); | ||
this.log.debug("Services run order: {runOrder}", { | ||
runOrder: orderOfPlugins | ||
.map((x) => `[(${x.after.join(",")})${x.name}(${x.before.join(",")})]`) | ||
.join(","), | ||
}); | ||
for (const service of orderOfPlugins) { | ||
this.log.debug(`Run {plugin}`, { | ||
plugin: service.name, | ||
list.push({ | ||
type: "service", | ||
srcPluginName: service.pluginName, | ||
pluginName: service.pluginName, | ||
initBeforePlugins: service.initBeforePlugins, | ||
initAfterPlugins: service.initAfterPlugins, | ||
runBeforePlugins: service.runBeforePlugins, | ||
runAfterPlugins: service.runAfterPlugins, | ||
reference: service, | ||
}); | ||
for (const client of service.ref._clients) { | ||
(0, __1.SmartFunctionCallAsync)(client, client.run); | ||
for (const client of service._clients) { | ||
this.log.debug(" - {plugin} -> {client} [runBeforePlugins:{runBeforePlugins}][runAfterPlugins:{runAfterPlugins}]", { | ||
plugin: service.pluginName, | ||
client: client.pluginName, | ||
runBeforePlugins: this.getTextReportedDeps(client.runBeforePlugins), | ||
runAfterPlugins: this.getTextReportedDeps(client.runAfterPlugins), | ||
}); | ||
list.push({ | ||
type: "client", | ||
srcPluginName: service.pluginName, | ||
pluginName: client.pluginName, | ||
initBeforePlugins: client.initBeforePlugins, | ||
initAfterPlugins: client.initAfterPlugins, | ||
runBeforePlugins: client.runBeforePlugins, | ||
runAfterPlugins: client.runAfterPlugins, | ||
reference: client, | ||
}); | ||
} | ||
(0, __1.SmartFunctionCallAsync)(service.ref, service.ref.run); | ||
} | ||
await this.sortAndRunOrInitPlugins(list, "run"); | ||
} | ||
@@ -273,0 +319,0 @@ } |
@@ -31,3 +31,3 @@ { | ||
"main": "lib/index.js", | ||
"version": "8.5.52", | ||
"version": "8.5.53", | ||
"bsb_project": true, | ||
@@ -34,0 +34,0 @@ "bsbInit": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
394590
4910