@equinor/echo-base
Advanced tools
Comparing version 0.2.96 to 0.2.97
@@ -8,4 +8,2 @@ # Change Log | ||
## 0.1.4 (2021-04-16) | ||
@@ -15,12 +13,2 @@ | ||
## 0.1.1 (2021-04-16) | ||
## 0.1.4 (2021-04-16) | ||
**Note:** Version bump only for package @equinor/echo-base |
@@ -6,2 +6,1 @@ export * from './errors'; | ||
export * from './utils'; | ||
export { default as eventHub } from './utils/eventHub'; |
@@ -6,3 +6,2 @@ export * from './errors'; | ||
export * from './utils'; | ||
export { default as eventHub } from './utils/eventHub'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,1 +0,18 @@ | ||
export declare function startLoadingApps(options: {}): void; | ||
import { EchoModulesLoading, LoadingModuleOptions } from '../types'; | ||
interface StartLoadingModules { | ||
connect(notifier: EchoModulesLoading): void; | ||
disconnect(notifier: EchoModulesLoading): void; | ||
} | ||
/** | ||
* Used to start loading modules, the modules can be provided, or a fetch call can be defined to | ||
* retrieving the moduleMetaData that in turn will load the js files, and initialize the all modules. | ||
* Module data will be stored in the globals store trough the notifier provided trough the connect function. | ||
* | ||
* This function is used in Echo Framework in the Mediator Component. | ||
* | ||
* @export | ||
* @param {LoadingModuleOptions} options | ||
* @return {*} {StartLoadingModules} | ||
*/ | ||
export declare function startLoadingModules(options: LoadingModuleOptions): StartLoadingModules; | ||
export {}; |
@@ -1,8 +0,46 @@ | ||
export function startLoadingApps(options) { | ||
import { standardStrategy } from './strategies'; | ||
import { fireAndForget, isfunc } from './utils'; | ||
/** | ||
* Used to start loading modules, the modules can be provided, or a fetch call can be defined to | ||
* retrieving the moduleMetaData that in turn will load the js files, and initialize the all modules. | ||
* Module data will be stored in the globals store trough the notifier provided trough the connect function. | ||
* | ||
* This function is used in Echo Framework in the Mediator Component. | ||
* | ||
* @export | ||
* @param {LoadingModuleOptions} options | ||
* @return {*} {StartLoadingModules} | ||
*/ | ||
export function startLoadingModules(options) { | ||
var state = { | ||
loading: false, | ||
apps: [], | ||
error: undefined, | ||
loaded: false, | ||
modules: [], | ||
error: undefined | ||
}; | ||
var notifiers = []; | ||
var call = function (notifier) { return notifier(state.error, state.modules, state.loaded); }; | ||
var notify = function () { return notifiers.forEach(call); }; | ||
var setAppModules = function (error, modules) { | ||
state.error = error; | ||
state.modules = modules; | ||
notify(); | ||
}; | ||
var setLoaded = function () { | ||
state.loaded = true; | ||
notify(); | ||
}; | ||
fireAndForget(function () { return standardStrategy(options, setAppModules).then(setLoaded, setLoaded); }); | ||
return { | ||
connect: function (notifier) { | ||
if (isfunc(notifier)) { | ||
notifiers.push(notifier); | ||
call(notifier); | ||
} | ||
}, | ||
disconnect: function (notifier) { | ||
var index = notifiers.indexOf(notifier); | ||
index !== -1 && notifiers.splice(index, 1); | ||
} | ||
}; | ||
} | ||
//# sourceMappingURL=create.js.map |
@@ -1,8 +0,47 @@ | ||
import { AppData, AvailableDependencies } from '../types/module'; | ||
import { AvailableDependencies, ModuleData, ModuleMetaData } from '../types'; | ||
declare global { | ||
interface HTMLScriptElement { | ||
app?: AppData; | ||
module?: ModuleData; | ||
} | ||
} | ||
export declare function checkAppAsync(app?: AppData | Promise<AppData>): Promise<AppData>; | ||
/** | ||
* Incudes a script tag in the DOM, | ||
* and extracts the setup function. | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {string} fileUri | ||
* @param {string} depName | ||
* @param {AvailableDependencies} dependencies | ||
* @param {string} [crossOrigin] | ||
* @param {string} [integrity] | ||
* @return {*} {(Promise<ModuleData | undefined>)} | ||
*/ | ||
export declare function includeScript(name: string, fileUri: string, depName: string, dependencies: AvailableDependencies, crossOrigin?: string, integrity?: string): Promise<ModuleData | undefined>; | ||
/** | ||
* async wrapper of check app resolving the app ModuleData | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {(ModuleData | Promise<ModuleData>)} [module] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export declare function checkAppAsync(name: string, module?: ModuleData | Promise<ModuleData>): Promise<ModuleData>; | ||
/** | ||
* Function added to window object for retrieving AvailableDependencies | ||
* | ||
* @export | ||
* @param {AvailableDependencies} [dependencies={}] | ||
* @return {*} | ||
*/ | ||
export declare function getLocalRequire(dependencies?: AvailableDependencies): (moduleName: string) => void; | ||
/** | ||
* Retiring the current module. | ||
* | ||
* @export | ||
* @param {ModuleMetaData} { name, fileUri: link, requireRef, integrity } | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {string} [crossOrigin] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export declare function includeDependency({ name, fileUri: link, requireRef, integrity }: ModuleMetaData, dependencies?: AvailableDependencies, crossOrigin?: string): Promise<ModuleData>; |
@@ -0,1 +1,9 @@ | ||
import { __awaiter, __generator } from "tslib"; | ||
/** | ||
* Returns the module dependency if present in the AvailableDependencies | ||
* | ||
* @param {string} name | ||
* @param {AvailableDependencies} dependencies | ||
* @return {*} {*} | ||
*/ | ||
function requireModule(name, dependencies) { | ||
@@ -10,11 +18,19 @@ var dependency = dependencies[name]; | ||
} | ||
function checkApp(app) { | ||
if (!app) { | ||
console.error('Invalid module found.', app); | ||
/** | ||
* Verifies if the module is a correct EchoModule with a exported setup function. | ||
* Will provide a empty module if verification fails to prevent system crash. | ||
* | ||
* @param {string} name | ||
* @param {ModuleData} [module] | ||
* @return {*} {ModuleData} | ||
*/ | ||
function checkModule(name, module) { | ||
if (!module) { | ||
console.error('Invalid module found.', name); | ||
} | ||
else if (typeof app.setup !== 'function') { | ||
console.warn('Setup function is missing.'); | ||
else if (typeof module.setup !== 'function') { | ||
console.warn('Setup function is missing.', name); | ||
} | ||
else { | ||
return app; | ||
return module; | ||
} | ||
@@ -27,5 +43,66 @@ return { | ||
} | ||
export function checkAppAsync(app) { | ||
return Promise.resolve(app).then(function (resolvedApp) { return checkApp(resolvedApp); }); | ||
/** | ||
* Incudes a script tag in the DOM, | ||
* and extracts the setup function. | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {string} fileUri | ||
* @param {string} depName | ||
* @param {AvailableDependencies} dependencies | ||
* @param {string} [crossOrigin] | ||
* @param {string} [integrity] | ||
* @return {*} {(Promise<ModuleData | undefined>)} | ||
*/ | ||
export function includeScript(name, fileUri, depName, dependencies, crossOrigin, integrity) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
var script = document.createElement('script'); | ||
script.async = true; | ||
script.src = fileUri; | ||
script.id = name; | ||
if (integrity) { | ||
script.crossOrigin = crossOrigin || 'anonymous'; | ||
script.integrity = integrity; | ||
} | ||
else if (crossOrigin) { | ||
script.crossOrigin = crossOrigin; | ||
} | ||
window[depName] = getLocalRequire(dependencies); | ||
script.onload = function () { return resolve(checkAppAsync(name, script.module)); }; | ||
script.onerror = function () { return reject('could not load'); }; | ||
document.head.appendChild(script); | ||
})]; | ||
}); | ||
}); | ||
} | ||
/** | ||
* async wrapper of check app resolving the app ModuleData | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {(ModuleData | Promise<ModuleData>)} [module] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export function checkAppAsync(name, module) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var resolvedModule; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, Promise.resolve(module)]; | ||
case 1: | ||
resolvedModule = _a.sent(); | ||
return [2 /*return*/, checkModule(name, resolvedModule)]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* Function added to window object for retrieving AvailableDependencies | ||
* | ||
* @export | ||
* @param {AvailableDependencies} [dependencies={}] | ||
* @return {*} | ||
*/ | ||
export function getLocalRequire(dependencies) { | ||
@@ -35,2 +112,22 @@ if (dependencies === void 0) { dependencies = {}; } | ||
} | ||
/** | ||
* Retiring the current module. | ||
* | ||
* @export | ||
* @param {ModuleMetaData} { name, fileUri: link, requireRef, integrity } | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {string} [crossOrigin] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export function includeDependency(_a, dependencies, crossOrigin) { | ||
var name = _a.name, link = _a.fileUri, requireRef = _a.requireRef, integrity = _a.integrity; | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, includeScript(name, link, requireRef, dependencies, crossOrigin, integrity)]; | ||
case 1: return [2 /*return*/, _b.sent()]; | ||
} | ||
}); | ||
}); | ||
} | ||
//# sourceMappingURL=dependency.js.map |
@@ -7,2 +7,2 @@ /** | ||
*/ | ||
export declare function fetchDependency(url: string, token: string): Promise<string>; | ||
export declare function defaultFetchDependency(url: string, token?: string): Promise<string>; |
@@ -8,5 +8,5 @@ import { __awaiter, __generator } from "tslib"; | ||
*/ | ||
export function fetchDependency(url, token) { | ||
export function defaultFetchDependency(url, token) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var m; | ||
var module; | ||
return __generator(this, function (_a) { | ||
@@ -20,4 +20,4 @@ switch (_a.label) { | ||
case 1: | ||
m = _a.sent(); | ||
return [4 /*yield*/, m.text()]; | ||
module = _a.sent(); | ||
return [4 /*yield*/, module.text()]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
@@ -24,0 +24,0 @@ } |
@@ -0,7 +1,12 @@ | ||
export * from './aggregate'; | ||
export * from './create'; | ||
export * from './dependency'; | ||
export * from './errors'; | ||
export * from './fetch'; | ||
export * from './fetchModules'; | ||
export * from './load'; | ||
export * from './loader'; | ||
export * from './persist'; | ||
export * from './setup'; | ||
export * from './strategies'; | ||
export * from './utils'; | ||
export * from './verify'; |
@@ -0,8 +1,13 @@ | ||
export * from './aggregate'; | ||
export * from './create'; | ||
export * from './dependency'; | ||
export * from './errors'; | ||
export * from './fetch'; | ||
export * from './fetchModules'; | ||
export * from './load'; | ||
export * from './loader'; | ||
export * from './persist'; | ||
export * from './setup'; | ||
export * from './strategies'; | ||
export * from './utils'; | ||
export * from './verify'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,3 +0,21 @@ | ||
import { App, AppData, AppMetadata, AvailableDependencies } from '../types/module'; | ||
export declare function loadModule(meta: AppMetadata, loadModuleData: (meta: AppMetadata) => AppData): App; | ||
export declare function loadApp(link: string, depName: string, dependencies: AvailableDependencies): Promise<AppData | undefined>; | ||
import { AppDependencyGetter, AvailableDependencies, DefaultLoaderConfig, ModuleLoader } from '../types'; | ||
/** | ||
* Create a module loader with the provided dependencies. | ||
* | ||
* @export | ||
* @param {DefaultLoaderConfig} [config] | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {AppDependencyGetter} [getDependencies] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export declare function createModuleLoader(config?: DefaultLoaderConfig, dependencies?: AvailableDependencies, getDependencies?: AppDependencyGetter): ModuleLoader; | ||
/** | ||
* Loader for loading modules, with dependencies. | ||
* Will return an empty module, for avoiding crashes. | ||
* | ||
* @export | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {DefaultLoaderConfig} [config={}] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export declare function getModuleLoader(getDependencies: AppDependencyGetter, config?: DefaultLoaderConfig): ModuleLoader; |
@@ -1,22 +0,61 @@ | ||
import { __assign } from "tslib"; | ||
import { checkAppAsync, getLocalRequire } from './dependency'; | ||
export function loadModule(meta, loadModuleData) { | ||
var module = loadModuleData(meta); | ||
return __assign(__assign({}, meta), module); | ||
import { __assign, __awaiter, __generator } from "tslib"; | ||
import { createEmptyModule } from '../utils/emptyApp'; | ||
import { getDependencyResolver } from '../utils/getDependencyResolver'; | ||
import { includeDependency } from './dependency'; | ||
var inBrowser = typeof document !== 'undefined'; | ||
/** | ||
* Create a module loader with the provided dependencies. | ||
* | ||
* @export | ||
* @param {DefaultLoaderConfig} [config] | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {AppDependencyGetter} [getDependencies] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export function createModuleLoader(config, dependencies, getDependencies) { | ||
var getDeps = getDependencyResolver(dependencies, getDependencies); | ||
return getModuleLoader(getDeps, config); | ||
} | ||
export function loadApp(link, depName, dependencies) { | ||
return new Promise(function (resolve, reject) { | ||
var s = document.createElement('script'); | ||
s.async = true; | ||
s.src = link; | ||
s.crossOrigin = 'cross-origin'; | ||
window[depName] = getLocalRequire(dependencies); | ||
s.onload = function () { | ||
var app = checkAppAsync(s.app); | ||
resolve(app); | ||
}; | ||
s.onerror = function () { return reject('could not load'); }; | ||
document.head.appendChild(s); | ||
/** | ||
* Loader for loading modules, with dependencies. | ||
* Will return an empty module, for avoiding crashes. | ||
* | ||
* @export | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {DefaultLoaderConfig} [config={}] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export function getModuleLoader(getDependencies, config) { | ||
if (config === void 0) { config = {}; } | ||
return function (meta) { | ||
if (inBrowser && 'requireRef' in meta && meta.requireRef) { | ||
return loadModule(meta, getDependencies, function (deps) { return includeDependency(meta, deps, config.crossOrigin); }); | ||
} | ||
console.warn('Empty Module found!', meta.name); | ||
return Promise.resolve(createEmptyModule(meta)); | ||
}; | ||
} | ||
/** | ||
* Loading the module and combining the javascript module with the modules Metadata. | ||
* | ||
* @param {ModuleMetaData} meta | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {(dependencies: AvailableDependencies) => Promise<ModuleData>} loader | ||
* @return {*} {Promise<EchoModule>} | ||
*/ | ||
function loadModule(meta, getDependencies, loader) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var dependencies, app; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
dependencies = __assign({}, (getDependencies(meta) || {})); | ||
return [4 /*yield*/, loader(dependencies)]; | ||
case 1: | ||
app = _a.sent(); | ||
return [2 /*return*/, __assign(__assign({}, app), meta)]; | ||
} | ||
}); | ||
}); | ||
} | ||
//# sourceMappingURL=loader.js.map |
@@ -1,3 +0,3 @@ | ||
import { AppMetadata } from '../types/module'; | ||
export declare function persistLocalModuleMeta(key: string, modules: AppMetadata[]): void; | ||
export declare function loadLocalModuleMeta(key: string): AppMetadata[]; | ||
import { ModuleMetaData } from '../types/module'; | ||
export declare function persistLocalModuleMeta(key: string, modules: ModuleMetaData[]): void; | ||
export declare function loadLocalModuleMeta(key: string): ModuleMetaData[]; |
@@ -1,4 +0,3 @@ | ||
import { App, AppApi, AppApiCreator, MultiApp, SingleApp } from '../types'; | ||
export declare function setupSingleApp(app: SingleApp, api: AppApi): void | Promise<void>; | ||
export declare function setupMultiApps(app: MultiApp, apiFactory: AppApiCreator): void | Promise<void>; | ||
export declare function setupApp(app: App, apiFactory: AppApiCreator): void | Promise<void>; | ||
import { EchoModule, EchoModuleApi, EchoModuleApiCreator } from '../types'; | ||
export declare function setupSingleModule(module: EchoModule, api: EchoModuleApi): void | Promise<void>; | ||
export declare function setupModule(module: EchoModule, apiFactory: EchoModuleApiCreator): void | Promise<void>; |
@@ -1,24 +0,13 @@ | ||
export function setupSingleApp(app, api) { | ||
export function setupSingleModule(module, api) { | ||
try { | ||
var result = app.setup(api); | ||
var result = module.setup(api); | ||
return result; | ||
} | ||
catch (error) { } | ||
} | ||
export function setupMultiApps(app, apiFactory) { | ||
try { | ||
return app.setup(apiFactory); | ||
catch (error) { | ||
console.warn(error); | ||
} | ||
catch (e) { | ||
console.error("Error while setting up " + (app === null || app === void 0 ? void 0 : app.name) + ".", e); | ||
} | ||
} | ||
export function setupApp(app, apiFactory) { | ||
if ('bundle' in app) { | ||
return setupMultiApps(app, apiFactory); | ||
} | ||
else { | ||
return setupSingleApp(app, apiFactory(app)); | ||
} | ||
export function setupModule(module, apiFactory) { | ||
return setupSingleModule(module, apiFactory(module)); | ||
} | ||
//# sourceMappingURL=setup.js.map |
@@ -1,4 +0,35 @@ | ||
import { AppMetadata, SingleApp } from '../types/module'; | ||
import { EchoModuleApiCreator, ModuleRequester } from '../types/creators'; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {string} id | ||
*/ | ||
export declare function removeElementById(id: string): void; | ||
export declare function isfunc(f: any): f is Function; | ||
export declare function createEmptyModule(meta: AppMetadata): SingleApp; | ||
/** | ||
* Helper function for Checking if function is present. | ||
* | ||
* @param {EchoModuleApiCreator} createModuleApi | ||
* @return {*} {boolean} | ||
*/ | ||
export declare function checkFunction(func: EchoModuleApiCreator | ModuleRequester, errorMessage: string): boolean; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {*} f | ||
* @return {*} {f is Function} | ||
*/ | ||
export declare function isfunc(f: unknown): f is Function; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {ModuleMetaData} meta | ||
* @return {*} {SingleApp} | ||
*/ | ||
export declare function createEmptyApp(meta: ModuleMetaData): EchoModule; | ||
export declare function isProduction(): boolean; | ||
export declare function filterExcludePrivateModulesInProduction(modules: EchoModule[], isProduction?: () => boolean): EchoModule[]; | ||
export declare function fireAndForget(asyncFunc: () => Promise<void>): void; |
import { __assign } from "tslib"; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {string} id | ||
*/ | ||
export function removeElementById(id) { | ||
@@ -6,6 +12,33 @@ var _a; | ||
} | ||
/** | ||
* Helper function for Checking if function is present. | ||
* | ||
* @param {EchoModuleApiCreator} createModuleApi | ||
* @return {*} {boolean} | ||
*/ | ||
export function checkFunction(func, errorMessage) { | ||
if (!isfunc(func)) { | ||
console.warn(errorMessage); | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {*} f | ||
* @return {*} {f is Function} | ||
*/ | ||
export function isfunc(f) { | ||
return typeof f === 'function'; | ||
} | ||
export function createEmptyModule(meta) { | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {ModuleMetaData} meta | ||
* @return {*} {SingleApp} | ||
*/ | ||
export function createEmptyApp(meta) { | ||
return __assign(__assign({}, meta), { setup: function () { | ||
@@ -15,2 +48,14 @@ // Empty module | ||
} | ||
export function isProduction() { | ||
return process.env.NODE_ENV === 'production'; | ||
} | ||
export function filterExcludePrivateModulesInProduction(modules, isProduction) { | ||
if (isProduction && isProduction()) { | ||
return modules.filter(function (module) { return module.private !== true; }); | ||
} | ||
return modules; | ||
} | ||
export function fireAndForget(asyncFunc) { | ||
asyncFunc(); | ||
} | ||
//# sourceMappingURL=utils.js.map |
@@ -1,2 +0,2 @@ | ||
import { AppMetadata } from '../types/module'; | ||
export declare function verifyModulesMeta(modules: AppMetadata[]): AppMetadata[]; | ||
import { ModuleMetaData } from '../types/module'; | ||
export declare function verifyModulesMeta(modules: ModuleMetaData[]): ModuleMetaData[]; |
@@ -1,10 +0,10 @@ | ||
import ArgumentError from '../errors/ArgumentError'; | ||
import { persistLocalModuleMeta } from './persist'; | ||
export function verifyModulesMeta(modules) { | ||
if (modules.length === 0) { | ||
throw new ArgumentError({ argumentName: 'No modules awaitable' }); | ||
if (modules instanceof Array) { | ||
modules.length > 0 && persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
} | ||
persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
console.info('No modules awaitable.'); | ||
return []; | ||
} | ||
//# sourceMappingURL=verify.js.map |
@@ -8,5 +8,6 @@ /** | ||
emit<T>(key: string, payload: T): void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): () => void; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): UnsubscribeFunction; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction; | ||
} | ||
export declare type UnsubscribeFunction = () => void; | ||
export declare enum EchoEvents { | ||
@@ -16,25 +17,2 @@ PlantChanged = "plantChanged", | ||
} | ||
/** | ||
* Emitter of module app shell events. | ||
*/ | ||
export interface ModuleEventEmitter { | ||
/** | ||
* Attaches a new event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
on<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Detaches an existing event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
of<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Emits a new event with the given type. | ||
* @param type The type of the event to emit. | ||
* @param arg The payload of the event. | ||
*/ | ||
emit<K extends keyof EventMap>(type: K, arg: EventMap[K]): ModuleEventEmitter; | ||
} | ||
export interface EventMap { | ||
@@ -41,0 +19,0 @@ [custom: string]: unknown; |
@@ -0,4 +1,8 @@ | ||
export * from './common'; | ||
export * from './creators'; | ||
export * from './error'; | ||
export * from './event'; | ||
export * from './loader'; | ||
export * from './module'; | ||
export * from './options'; | ||
export * from './storage'; |
@@ -0,5 +1,9 @@ | ||
export * from './common'; | ||
export * from './creators'; | ||
export * from './error'; | ||
export * from './event'; | ||
export * from './loader'; | ||
export * from './module'; | ||
export * from './options'; | ||
export * from './storage'; | ||
//# sourceMappingURL=index.js.map |
@@ -0,1 +1,5 @@ | ||
import { BaseError } from '../errors'; | ||
import { EchoModule, ModuleMetaData } from './module'; | ||
export declare class ModuleAppError extends BaseError { | ||
} | ||
/** | ||
@@ -7,1 +11,16 @@ * Configuration options for the default loader. | ||
} | ||
export interface ModulesLoader { | ||
(): Array<EchoModule>; | ||
} | ||
export interface EchoModuleLoaded { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>): void; | ||
} | ||
export interface EchoModulesLoading { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>, loaded: boolean): void; | ||
} | ||
export interface ModuleLoader { | ||
(meta: ModuleMetaData): Promise<EchoModule>; | ||
} | ||
export interface DefaultLoaderConfig { | ||
crossOrigin?: string; | ||
} |
@@ -1,2 +0,11 @@ | ||
export {}; | ||
import { __extends } from "tslib"; | ||
import { BaseError } from '../errors'; | ||
var ModuleAppError = /** @class */ (function (_super) { | ||
__extends(ModuleAppError, _super); | ||
function ModuleAppError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ModuleAppError; | ||
}(BaseError)); | ||
export { ModuleAppError }; | ||
//# sourceMappingURL=loader.js.map |
@@ -1,67 +0,34 @@ | ||
import { ModuleEventEmitter } from "./event"; | ||
export interface SingleAppMetadata { | ||
name: string; | ||
link: string; | ||
requireRef: string; | ||
integrity?: string; | ||
custom?: any; | ||
config?: Record<string, any>; | ||
import { EchoEventHub } from './event'; | ||
export interface ModuleMetaData extends MetaDataBase { | ||
requireRef?: string; | ||
} | ||
export interface MultiAppsMetadata { | ||
export interface MetaDataBase { | ||
key: string; | ||
name: string; | ||
link: string; | ||
bundle: string; | ||
shortName: string; | ||
path: string; | ||
fileUri: string; | ||
version: string; | ||
integrity?: string; | ||
custom?: any; | ||
private?: boolean; | ||
} | ||
export declare type App = SingleApp | MultiApp; | ||
/** | ||
* Describes the metadata transported by a Apps. | ||
* Echo Module setup function and meta data combined. | ||
*/ | ||
export declare type AppMetadata = SingleAppMetadata | MultiAppsMetadata; | ||
export declare type EchoModule = ModuleData & ModuleMetaData; | ||
/** | ||
* The metadata for a single app. | ||
*/ | ||
export declare type SingleApp = AppData & AppMetadata; | ||
/** | ||
* The metadata for apps containing apps. | ||
*/ | ||
export declare type MultiApp = MultiAppData & MultiAppsMetadata; | ||
/** | ||
* Defines the API accessible from Apps. | ||
*/ | ||
export interface AppApi extends ModuleEventEmitter { | ||
export interface EchoModuleApi { | ||
/** | ||
* Gets the metadata of the current App. | ||
*/ | ||
meta: AppMetadata; | ||
meta: ModuleMetaData; | ||
eventHub: EchoEventHub; | ||
} | ||
export interface RouteRegistration extends BaseRegistration { | ||
meta: AppMetaData; | ||
export interface ModuleData { | ||
setup: (api: EchoModuleApi) => void | Promise<void>; | ||
} | ||
export interface AppMetaData { | ||
name: string; | ||
icon: string; | ||
homeScreen?: boolean; | ||
} | ||
export interface BaseRegistration { | ||
key: string; | ||
} | ||
export interface AppData { | ||
setup: (api: AppApi) => void | Promise<void>; | ||
} | ||
export interface MultiAppData { | ||
setup: (apiFactory: AppApiCreator) => void | Promise<void>; | ||
} | ||
export interface EchoPortal { | ||
isAuthenticated: boolean; | ||
} | ||
export declare type AppMetaFetch = () => Promise<AppMetadata[]>; | ||
export declare type AppMetaFetch = () => Promise<ModuleMetaData[]>; | ||
/** | ||
* The creator function for the App API. | ||
*/ | ||
export interface AppApiCreator { | ||
(target: AppMetadata): AppApi; | ||
} | ||
/** | ||
* The record containing all available dependencies. | ||
@@ -68,0 +35,0 @@ */ |
@@ -1,2 +0,2 @@ | ||
import { AppData, AppMetadata } from "../types/module"; | ||
export declare function createEmptyModule(meta: AppMetadata): AppData; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
export declare function createEmptyModule(meta: ModuleMetaData): EchoModule; |
@@ -1,2 +0,2 @@ | ||
import { EchoEventHub, EchoEvents } from '../types/event'; | ||
import { EchoEventHub, EchoEvents, UnsubscribeFunction } from '../types/event'; | ||
/** | ||
@@ -26,3 +26,3 @@ * Class for creating an eventHub to be used for emitting and subscribing to either | ||
*/ | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): () => void; | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): UnsubscribeFunction; | ||
/** | ||
@@ -37,5 +37,5 @@ * Function for subscribing to an array of events. | ||
*/ | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction; | ||
} | ||
export declare const eventHub: EventHub; | ||
export default eventHub; | ||
export {}; |
@@ -60,3 +60,2 @@ /** | ||
export var eventHub = new EventHub(); | ||
export default eventHub; | ||
//# sourceMappingURL=eventHub.js.map |
@@ -0,2 +1,4 @@ | ||
export * from './emptyApp'; | ||
export * from './eventHub'; | ||
export * from './getDependencyResolver'; | ||
export * from './storage'; |
@@ -0,3 +1,5 @@ | ||
export * from './emptyApp'; | ||
export * from './eventHub'; | ||
export * from './getDependencyResolver'; | ||
export * from './storage'; | ||
//# sourceMappingURL=index.js.map |
@@ -6,2 +6,1 @@ export * from './errors'; | ||
export * from './utils'; | ||
export { default as eventHub } from './utils/eventHub'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.eventHub = exports.EchoEvents = void 0; | ||
exports.EchoEvents = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -11,4 +11,2 @@ tslib_1.__exportStar(require("./errors"), exports); | ||
tslib_1.__exportStar(require("./utils"), exports); | ||
var eventHub_1 = require("./utils/eventHub"); | ||
Object.defineProperty(exports, "eventHub", { enumerable: true, get: function () { return eventHub_1.default; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -1,1 +0,18 @@ | ||
export declare function startLoadingApps(options: {}): void; | ||
import { EchoModulesLoading, LoadingModuleOptions } from '../types'; | ||
interface StartLoadingModules { | ||
connect(notifier: EchoModulesLoading): void; | ||
disconnect(notifier: EchoModulesLoading): void; | ||
} | ||
/** | ||
* Used to start loading modules, the modules can be provided, or a fetch call can be defined to | ||
* retrieving the moduleMetaData that in turn will load the js files, and initialize the all modules. | ||
* Module data will be stored in the globals store trough the notifier provided trough the connect function. | ||
* | ||
* This function is used in Echo Framework in the Mediator Component. | ||
* | ||
* @export | ||
* @param {LoadingModuleOptions} options | ||
* @return {*} {StartLoadingModules} | ||
*/ | ||
export declare function startLoadingModules(options: LoadingModuleOptions): StartLoadingModules; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.startLoadingApps = void 0; | ||
function startLoadingApps(options) { | ||
exports.startLoadingModules = void 0; | ||
var strategies_1 = require("./strategies"); | ||
var utils_1 = require("./utils"); | ||
/** | ||
* Used to start loading modules, the modules can be provided, or a fetch call can be defined to | ||
* retrieving the moduleMetaData that in turn will load the js files, and initialize the all modules. | ||
* Module data will be stored in the globals store trough the notifier provided trough the connect function. | ||
* | ||
* This function is used in Echo Framework in the Mediator Component. | ||
* | ||
* @export | ||
* @param {LoadingModuleOptions} options | ||
* @return {*} {StartLoadingModules} | ||
*/ | ||
function startLoadingModules(options) { | ||
var state = { | ||
loading: false, | ||
apps: [], | ||
error: undefined, | ||
loaded: false, | ||
modules: [], | ||
error: undefined | ||
}; | ||
var notifiers = []; | ||
var call = function (notifier) { return notifier(state.error, state.modules, state.loaded); }; | ||
var notify = function () { return notifiers.forEach(call); }; | ||
var setAppModules = function (error, modules) { | ||
state.error = error; | ||
state.modules = modules; | ||
notify(); | ||
}; | ||
var setLoaded = function () { | ||
state.loaded = true; | ||
notify(); | ||
}; | ||
utils_1.fireAndForget(function () { return strategies_1.standardStrategy(options, setAppModules).then(setLoaded, setLoaded); }); | ||
return { | ||
connect: function (notifier) { | ||
if (utils_1.isfunc(notifier)) { | ||
notifiers.push(notifier); | ||
call(notifier); | ||
} | ||
}, | ||
disconnect: function (notifier) { | ||
var index = notifiers.indexOf(notifier); | ||
index !== -1 && notifiers.splice(index, 1); | ||
} | ||
}; | ||
} | ||
exports.startLoadingApps = startLoadingApps; | ||
exports.startLoadingModules = startLoadingModules; | ||
//# sourceMappingURL=create.js.map |
@@ -1,8 +0,47 @@ | ||
import { AppData, AvailableDependencies } from '../types/module'; | ||
import { AvailableDependencies, ModuleData, ModuleMetaData } from '../types'; | ||
declare global { | ||
interface HTMLScriptElement { | ||
app?: AppData; | ||
module?: ModuleData; | ||
} | ||
} | ||
export declare function checkAppAsync(app?: AppData | Promise<AppData>): Promise<AppData>; | ||
/** | ||
* Incudes a script tag in the DOM, | ||
* and extracts the setup function. | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {string} fileUri | ||
* @param {string} depName | ||
* @param {AvailableDependencies} dependencies | ||
* @param {string} [crossOrigin] | ||
* @param {string} [integrity] | ||
* @return {*} {(Promise<ModuleData | undefined>)} | ||
*/ | ||
export declare function includeScript(name: string, fileUri: string, depName: string, dependencies: AvailableDependencies, crossOrigin?: string, integrity?: string): Promise<ModuleData | undefined>; | ||
/** | ||
* async wrapper of check app resolving the app ModuleData | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {(ModuleData | Promise<ModuleData>)} [module] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export declare function checkAppAsync(name: string, module?: ModuleData | Promise<ModuleData>): Promise<ModuleData>; | ||
/** | ||
* Function added to window object for retrieving AvailableDependencies | ||
* | ||
* @export | ||
* @param {AvailableDependencies} [dependencies={}] | ||
* @return {*} | ||
*/ | ||
export declare function getLocalRequire(dependencies?: AvailableDependencies): (moduleName: string) => void; | ||
/** | ||
* Retiring the current module. | ||
* | ||
* @export | ||
* @param {ModuleMetaData} { name, fileUri: link, requireRef, integrity } | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {string} [crossOrigin] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
export declare function includeDependency({ name, fileUri: link, requireRef, integrity }: ModuleMetaData, dependencies?: AvailableDependencies, crossOrigin?: string): Promise<ModuleData>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getLocalRequire = exports.checkAppAsync = void 0; | ||
exports.includeDependency = exports.getLocalRequire = exports.checkAppAsync = exports.includeScript = void 0; | ||
var tslib_1 = require("tslib"); | ||
/** | ||
* Returns the module dependency if present in the AvailableDependencies | ||
* | ||
* @param {string} name | ||
* @param {AvailableDependencies} dependencies | ||
* @return {*} {*} | ||
*/ | ||
function requireModule(name, dependencies) { | ||
@@ -13,11 +21,19 @@ var dependency = dependencies[name]; | ||
} | ||
function checkApp(app) { | ||
if (!app) { | ||
console.error('Invalid module found.', app); | ||
/** | ||
* Verifies if the module is a correct EchoModule with a exported setup function. | ||
* Will provide a empty module if verification fails to prevent system crash. | ||
* | ||
* @param {string} name | ||
* @param {ModuleData} [module] | ||
* @return {*} {ModuleData} | ||
*/ | ||
function checkModule(name, module) { | ||
if (!module) { | ||
console.error('Invalid module found.', name); | ||
} | ||
else if (typeof app.setup !== 'function') { | ||
console.warn('Setup function is missing.'); | ||
else if (typeof module.setup !== 'function') { | ||
console.warn('Setup function is missing.', name); | ||
} | ||
else { | ||
return app; | ||
return module; | ||
} | ||
@@ -30,6 +46,68 @@ return { | ||
} | ||
function checkAppAsync(app) { | ||
return Promise.resolve(app).then(function (resolvedApp) { return checkApp(resolvedApp); }); | ||
/** | ||
* Incudes a script tag in the DOM, | ||
* and extracts the setup function. | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {string} fileUri | ||
* @param {string} depName | ||
* @param {AvailableDependencies} dependencies | ||
* @param {string} [crossOrigin] | ||
* @param {string} [integrity] | ||
* @return {*} {(Promise<ModuleData | undefined>)} | ||
*/ | ||
function includeScript(name, fileUri, depName, dependencies, crossOrigin, integrity) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
return tslib_1.__generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
var script = document.createElement('script'); | ||
script.async = true; | ||
script.src = fileUri; | ||
script.id = name; | ||
if (integrity) { | ||
script.crossOrigin = crossOrigin || 'anonymous'; | ||
script.integrity = integrity; | ||
} | ||
else if (crossOrigin) { | ||
script.crossOrigin = crossOrigin; | ||
} | ||
window[depName] = getLocalRequire(dependencies); | ||
script.onload = function () { return resolve(checkAppAsync(name, script.module)); }; | ||
script.onerror = function () { return reject('could not load'); }; | ||
document.head.appendChild(script); | ||
})]; | ||
}); | ||
}); | ||
} | ||
exports.includeScript = includeScript; | ||
/** | ||
* async wrapper of check app resolving the app ModuleData | ||
* | ||
* @export | ||
* @param {string} name | ||
* @param {(ModuleData | Promise<ModuleData>)} [module] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
function checkAppAsync(name, module) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var resolvedModule; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, Promise.resolve(module)]; | ||
case 1: | ||
resolvedModule = _a.sent(); | ||
return [2 /*return*/, checkModule(name, resolvedModule)]; | ||
} | ||
}); | ||
}); | ||
} | ||
exports.checkAppAsync = checkAppAsync; | ||
/** | ||
* Function added to window object for retrieving AvailableDependencies | ||
* | ||
* @export | ||
* @param {AvailableDependencies} [dependencies={}] | ||
* @return {*} | ||
*/ | ||
function getLocalRequire(dependencies) { | ||
@@ -40,2 +118,23 @@ if (dependencies === void 0) { dependencies = {}; } | ||
exports.getLocalRequire = getLocalRequire; | ||
/** | ||
* Retiring the current module. | ||
* | ||
* @export | ||
* @param {ModuleMetaData} { name, fileUri: link, requireRef, integrity } | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {string} [crossOrigin] | ||
* @return {*} {Promise<ModuleData>} | ||
*/ | ||
function includeDependency(_a, dependencies, crossOrigin) { | ||
var name = _a.name, link = _a.fileUri, requireRef = _a.requireRef, integrity = _a.integrity; | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, includeScript(name, link, requireRef, dependencies, crossOrigin, integrity)]; | ||
case 1: return [2 /*return*/, _b.sent()]; | ||
} | ||
}); | ||
}); | ||
} | ||
exports.includeDependency = includeDependency; | ||
//# sourceMappingURL=dependency.js.map |
@@ -7,2 +7,2 @@ /** | ||
*/ | ||
export declare function fetchDependency(url: string, token: string): Promise<string>; | ||
export declare function defaultFetchDependency(url: string, token?: string): Promise<string>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.fetchDependency = void 0; | ||
exports.defaultFetchDependency = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -11,5 +11,5 @@ /** | ||
*/ | ||
function fetchDependency(url, token) { | ||
function defaultFetchDependency(url, token) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var m; | ||
var module; | ||
return tslib_1.__generator(this, function (_a) { | ||
@@ -23,4 +23,4 @@ switch (_a.label) { | ||
case 1: | ||
m = _a.sent(); | ||
return [4 /*yield*/, m.text()]; | ||
module = _a.sent(); | ||
return [4 /*yield*/, module.text()]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
@@ -31,3 +31,3 @@ } | ||
} | ||
exports.fetchDependency = fetchDependency; | ||
exports.defaultFetchDependency = defaultFetchDependency; | ||
//# sourceMappingURL=fetch.js.map |
@@ -0,7 +1,12 @@ | ||
export * from './aggregate'; | ||
export * from './create'; | ||
export * from './dependency'; | ||
export * from './errors'; | ||
export * from './fetch'; | ||
export * from './fetchModules'; | ||
export * from './load'; | ||
export * from './loader'; | ||
export * from './persist'; | ||
export * from './setup'; | ||
export * from './strategies'; | ||
export * from './utils'; | ||
export * from './verify'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
tslib_1.__exportStar(require("./aggregate"), exports); | ||
tslib_1.__exportStar(require("./create"), exports); | ||
tslib_1.__exportStar(require("./dependency"), exports); | ||
tslib_1.__exportStar(require("./errors"), exports); | ||
tslib_1.__exportStar(require("./fetch"), exports); | ||
tslib_1.__exportStar(require("./fetchModules"), exports); | ||
tslib_1.__exportStar(require("./load"), exports); | ||
tslib_1.__exportStar(require("./loader"), exports); | ||
tslib_1.__exportStar(require("./persist"), exports); | ||
tslib_1.__exportStar(require("./setup"), exports); | ||
tslib_1.__exportStar(require("./strategies"), exports); | ||
tslib_1.__exportStar(require("./utils"), exports); | ||
tslib_1.__exportStar(require("./verify"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,3 +0,21 @@ | ||
import { App, AppData, AppMetadata, AvailableDependencies } from '../types/module'; | ||
export declare function loadModule(meta: AppMetadata, loadModuleData: (meta: AppMetadata) => AppData): App; | ||
export declare function loadApp(link: string, depName: string, dependencies: AvailableDependencies): Promise<AppData | undefined>; | ||
import { AppDependencyGetter, AvailableDependencies, DefaultLoaderConfig, ModuleLoader } from '../types'; | ||
/** | ||
* Create a module loader with the provided dependencies. | ||
* | ||
* @export | ||
* @param {DefaultLoaderConfig} [config] | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {AppDependencyGetter} [getDependencies] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export declare function createModuleLoader(config?: DefaultLoaderConfig, dependencies?: AvailableDependencies, getDependencies?: AppDependencyGetter): ModuleLoader; | ||
/** | ||
* Loader for loading modules, with dependencies. | ||
* Will return an empty module, for avoiding crashes. | ||
* | ||
* @export | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {DefaultLoaderConfig} [config={}] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export declare function getModuleLoader(getDependencies: AppDependencyGetter, config?: DefaultLoaderConfig): ModuleLoader; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.loadApp = exports.loadModule = void 0; | ||
exports.getModuleLoader = exports.createModuleLoader = void 0; | ||
var tslib_1 = require("tslib"); | ||
var emptyApp_1 = require("../utils/emptyApp"); | ||
var getDependencyResolver_1 = require("../utils/getDependencyResolver"); | ||
var dependency_1 = require("./dependency"); | ||
function loadModule(meta, loadModuleData) { | ||
var module = loadModuleData(meta); | ||
return tslib_1.__assign(tslib_1.__assign({}, meta), module); | ||
var inBrowser = typeof document !== 'undefined'; | ||
/** | ||
* Create a module loader with the provided dependencies. | ||
* | ||
* @export | ||
* @param {DefaultLoaderConfig} [config] | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {AppDependencyGetter} [getDependencies] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
function createModuleLoader(config, dependencies, getDependencies) { | ||
var getDeps = getDependencyResolver_1.getDependencyResolver(dependencies, getDependencies); | ||
return getModuleLoader(getDeps, config); | ||
} | ||
exports.loadModule = loadModule; | ||
function loadApp(link, depName, dependencies) { | ||
return new Promise(function (resolve, reject) { | ||
var s = document.createElement('script'); | ||
s.async = true; | ||
s.src = link; | ||
s.crossOrigin = 'cross-origin'; | ||
window[depName] = dependency_1.getLocalRequire(dependencies); | ||
s.onload = function () { | ||
var app = dependency_1.checkAppAsync(s.app); | ||
resolve(app); | ||
}; | ||
s.onerror = function () { return reject('could not load'); }; | ||
document.head.appendChild(s); | ||
exports.createModuleLoader = createModuleLoader; | ||
/** | ||
* Loader for loading modules, with dependencies. | ||
* Will return an empty module, for avoiding crashes. | ||
* | ||
* @export | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {DefaultLoaderConfig} [config={}] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
function getModuleLoader(getDependencies, config) { | ||
if (config === void 0) { config = {}; } | ||
return function (meta) { | ||
if (inBrowser && 'requireRef' in meta && meta.requireRef) { | ||
return loadModule(meta, getDependencies, function (deps) { return dependency_1.includeDependency(meta, deps, config.crossOrigin); }); | ||
} | ||
console.warn('Empty Module found!', meta.name); | ||
return Promise.resolve(emptyApp_1.createEmptyModule(meta)); | ||
}; | ||
} | ||
exports.getModuleLoader = getModuleLoader; | ||
/** | ||
* Loading the module and combining the javascript module with the modules Metadata. | ||
* | ||
* @param {ModuleMetaData} meta | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {(dependencies: AvailableDependencies) => Promise<ModuleData>} loader | ||
* @return {*} {Promise<EchoModule>} | ||
*/ | ||
function loadModule(meta, getDependencies, loader) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var dependencies, app; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
dependencies = tslib_1.__assign({}, (getDependencies(meta) || {})); | ||
return [4 /*yield*/, loader(dependencies)]; | ||
case 1: | ||
app = _a.sent(); | ||
return [2 /*return*/, tslib_1.__assign(tslib_1.__assign({}, app), meta)]; | ||
} | ||
}); | ||
}); | ||
} | ||
exports.loadApp = loadApp; | ||
//# sourceMappingURL=loader.js.map |
@@ -1,3 +0,3 @@ | ||
import { AppMetadata } from '../types/module'; | ||
export declare function persistLocalModuleMeta(key: string, modules: AppMetadata[]): void; | ||
export declare function loadLocalModuleMeta(key: string): AppMetadata[]; | ||
import { ModuleMetaData } from '../types/module'; | ||
export declare function persistLocalModuleMeta(key: string, modules: ModuleMetaData[]): void; | ||
export declare function loadLocalModuleMeta(key: string): ModuleMetaData[]; |
@@ -1,4 +0,3 @@ | ||
import { App, AppApi, AppApiCreator, MultiApp, SingleApp } from '../types'; | ||
export declare function setupSingleApp(app: SingleApp, api: AppApi): void | Promise<void>; | ||
export declare function setupMultiApps(app: MultiApp, apiFactory: AppApiCreator): void | Promise<void>; | ||
export declare function setupApp(app: App, apiFactory: AppApiCreator): void | Promise<void>; | ||
import { EchoModule, EchoModuleApi, EchoModuleApiCreator } from '../types'; | ||
export declare function setupSingleModule(module: EchoModule, api: EchoModuleApi): void | Promise<void>; | ||
export declare function setupModule(module: EchoModule, apiFactory: EchoModuleApiCreator): void | Promise<void>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setupApp = exports.setupMultiApps = exports.setupSingleApp = void 0; | ||
function setupSingleApp(app, api) { | ||
exports.setupModule = exports.setupSingleModule = void 0; | ||
function setupSingleModule(module, api) { | ||
try { | ||
var result = app.setup(api); | ||
var result = module.setup(api); | ||
return result; | ||
} | ||
catch (error) { } | ||
} | ||
exports.setupSingleApp = setupSingleApp; | ||
function setupMultiApps(app, apiFactory) { | ||
try { | ||
return app.setup(apiFactory); | ||
catch (error) { | ||
console.warn(error); | ||
} | ||
catch (e) { | ||
console.error("Error while setting up " + (app === null || app === void 0 ? void 0 : app.name) + ".", e); | ||
} | ||
} | ||
exports.setupMultiApps = setupMultiApps; | ||
function setupApp(app, apiFactory) { | ||
if ('bundle' in app) { | ||
return setupMultiApps(app, apiFactory); | ||
} | ||
else { | ||
return setupSingleApp(app, apiFactory(app)); | ||
} | ||
exports.setupSingleModule = setupSingleModule; | ||
function setupModule(module, apiFactory) { | ||
return setupSingleModule(module, apiFactory(module)); | ||
} | ||
exports.setupApp = setupApp; | ||
exports.setupModule = setupModule; | ||
//# sourceMappingURL=setup.js.map |
@@ -1,4 +0,35 @@ | ||
import { AppMetadata, SingleApp } from '../types/module'; | ||
import { EchoModuleApiCreator, ModuleRequester } from '../types/creators'; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {string} id | ||
*/ | ||
export declare function removeElementById(id: string): void; | ||
export declare function isfunc(f: any): f is Function; | ||
export declare function createEmptyModule(meta: AppMetadata): SingleApp; | ||
/** | ||
* Helper function for Checking if function is present. | ||
* | ||
* @param {EchoModuleApiCreator} createModuleApi | ||
* @return {*} {boolean} | ||
*/ | ||
export declare function checkFunction(func: EchoModuleApiCreator | ModuleRequester, errorMessage: string): boolean; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {*} f | ||
* @return {*} {f is Function} | ||
*/ | ||
export declare function isfunc(f: unknown): f is Function; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {ModuleMetaData} meta | ||
* @return {*} {SingleApp} | ||
*/ | ||
export declare function createEmptyApp(meta: ModuleMetaData): EchoModule; | ||
export declare function isProduction(): boolean; | ||
export declare function filterExcludePrivateModulesInProduction(modules: EchoModule[], isProduction?: () => boolean): EchoModule[]; | ||
export declare function fireAndForget(asyncFunc: () => Promise<void>): void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createEmptyModule = exports.isfunc = exports.removeElementById = void 0; | ||
exports.fireAndForget = exports.filterExcludePrivateModulesInProduction = exports.isProduction = exports.createEmptyApp = exports.isfunc = exports.checkFunction = exports.removeElementById = void 0; | ||
var tslib_1 = require("tslib"); | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {string} id | ||
*/ | ||
function removeElementById(id) { | ||
@@ -10,2 +16,23 @@ var _a; | ||
exports.removeElementById = removeElementById; | ||
/** | ||
* Helper function for Checking if function is present. | ||
* | ||
* @param {EchoModuleApiCreator} createModuleApi | ||
* @return {*} {boolean} | ||
*/ | ||
function checkFunction(func, errorMessage) { | ||
if (!isfunc(func)) { | ||
console.warn(errorMessage); | ||
return false; | ||
} | ||
return true; | ||
} | ||
exports.checkFunction = checkFunction; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {*} f | ||
* @return {*} {f is Function} | ||
*/ | ||
function isfunc(f) { | ||
@@ -15,3 +42,10 @@ return typeof f === 'function'; | ||
exports.isfunc = isfunc; | ||
function createEmptyModule(meta) { | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {ModuleMetaData} meta | ||
* @return {*} {SingleApp} | ||
*/ | ||
function createEmptyApp(meta) { | ||
return tslib_1.__assign(tslib_1.__assign({}, meta), { setup: function () { | ||
@@ -21,3 +55,18 @@ // Empty module | ||
} | ||
exports.createEmptyModule = createEmptyModule; | ||
exports.createEmptyApp = createEmptyApp; | ||
function isProduction() { | ||
return process.env.NODE_ENV === 'production'; | ||
} | ||
exports.isProduction = isProduction; | ||
function filterExcludePrivateModulesInProduction(modules, isProduction) { | ||
if (isProduction && isProduction()) { | ||
return modules.filter(function (module) { return module.private !== true; }); | ||
} | ||
return modules; | ||
} | ||
exports.filterExcludePrivateModulesInProduction = filterExcludePrivateModulesInProduction; | ||
function fireAndForget(asyncFunc) { | ||
asyncFunc(); | ||
} | ||
exports.fireAndForget = fireAndForget; | ||
//# sourceMappingURL=utils.js.map |
@@ -1,2 +0,2 @@ | ||
import { AppMetadata } from '../types/module'; | ||
export declare function verifyModulesMeta(modules: AppMetadata[]): AppMetadata[]; | ||
import { ModuleMetaData } from '../types/module'; | ||
export declare function verifyModulesMeta(modules: ModuleMetaData[]): ModuleMetaData[]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verifyModulesMeta = void 0; | ||
var ArgumentError_1 = require("../errors/ArgumentError"); | ||
var persist_1 = require("./persist"); | ||
function verifyModulesMeta(modules) { | ||
if (modules.length === 0) { | ||
throw new ArgumentError_1.default({ argumentName: 'No modules awaitable' }); | ||
if (modules instanceof Array) { | ||
modules.length > 0 && persist_1.persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
} | ||
persist_1.persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
console.info('No modules awaitable.'); | ||
return []; | ||
} | ||
exports.verifyModulesMeta = verifyModulesMeta; | ||
//# sourceMappingURL=verify.js.map |
@@ -8,5 +8,6 @@ /** | ||
emit<T>(key: string, payload: T): void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): () => void; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): UnsubscribeFunction; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction; | ||
} | ||
export declare type UnsubscribeFunction = () => void; | ||
export declare enum EchoEvents { | ||
@@ -16,25 +17,2 @@ PlantChanged = "plantChanged", | ||
} | ||
/** | ||
* Emitter of module app shell events. | ||
*/ | ||
export interface ModuleEventEmitter { | ||
/** | ||
* Attaches a new event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
on<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Detaches an existing event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
of<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Emits a new event with the given type. | ||
* @param type The type of the event to emit. | ||
* @param arg The payload of the event. | ||
*/ | ||
emit<K extends keyof EventMap>(type: K, arg: EventMap[K]): ModuleEventEmitter; | ||
} | ||
export interface EventMap { | ||
@@ -41,0 +19,0 @@ [custom: string]: unknown; |
@@ -0,4 +1,8 @@ | ||
export * from './common'; | ||
export * from './creators'; | ||
export * from './error'; | ||
export * from './event'; | ||
export * from './loader'; | ||
export * from './module'; | ||
export * from './options'; | ||
export * from './storage'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
tslib_1.__exportStar(require("./common"), exports); | ||
tslib_1.__exportStar(require("./creators"), exports); | ||
tslib_1.__exportStar(require("./error"), exports); | ||
tslib_1.__exportStar(require("./event"), exports); | ||
tslib_1.__exportStar(require("./loader"), exports); | ||
tslib_1.__exportStar(require("./module"), exports); | ||
tslib_1.__exportStar(require("./options"), exports); | ||
tslib_1.__exportStar(require("./storage"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -0,1 +1,5 @@ | ||
import { BaseError } from '../errors'; | ||
import { EchoModule, ModuleMetaData } from './module'; | ||
export declare class ModuleAppError extends BaseError { | ||
} | ||
/** | ||
@@ -7,1 +11,16 @@ * Configuration options for the default loader. | ||
} | ||
export interface ModulesLoader { | ||
(): Array<EchoModule>; | ||
} | ||
export interface EchoModuleLoaded { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>): void; | ||
} | ||
export interface EchoModulesLoading { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>, loaded: boolean): void; | ||
} | ||
export interface ModuleLoader { | ||
(meta: ModuleMetaData): Promise<EchoModule>; | ||
} | ||
export interface DefaultLoaderConfig { | ||
crossOrigin?: string; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ModuleAppError = void 0; | ||
var tslib_1 = require("tslib"); | ||
var errors_1 = require("../errors"); | ||
var ModuleAppError = /** @class */ (function (_super) { | ||
tslib_1.__extends(ModuleAppError, _super); | ||
function ModuleAppError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ModuleAppError; | ||
}(errors_1.BaseError)); | ||
exports.ModuleAppError = ModuleAppError; | ||
//# sourceMappingURL=loader.js.map |
@@ -1,67 +0,34 @@ | ||
import { ModuleEventEmitter } from "./event"; | ||
export interface SingleAppMetadata { | ||
name: string; | ||
link: string; | ||
requireRef: string; | ||
integrity?: string; | ||
custom?: any; | ||
config?: Record<string, any>; | ||
import { EchoEventHub } from './event'; | ||
export interface ModuleMetaData extends MetaDataBase { | ||
requireRef?: string; | ||
} | ||
export interface MultiAppsMetadata { | ||
export interface MetaDataBase { | ||
key: string; | ||
name: string; | ||
link: string; | ||
bundle: string; | ||
shortName: string; | ||
path: string; | ||
fileUri: string; | ||
version: string; | ||
integrity?: string; | ||
custom?: any; | ||
private?: boolean; | ||
} | ||
export declare type App = SingleApp | MultiApp; | ||
/** | ||
* Describes the metadata transported by a Apps. | ||
* Echo Module setup function and meta data combined. | ||
*/ | ||
export declare type AppMetadata = SingleAppMetadata | MultiAppsMetadata; | ||
export declare type EchoModule = ModuleData & ModuleMetaData; | ||
/** | ||
* The metadata for a single app. | ||
*/ | ||
export declare type SingleApp = AppData & AppMetadata; | ||
/** | ||
* The metadata for apps containing apps. | ||
*/ | ||
export declare type MultiApp = MultiAppData & MultiAppsMetadata; | ||
/** | ||
* Defines the API accessible from Apps. | ||
*/ | ||
export interface AppApi extends ModuleEventEmitter { | ||
export interface EchoModuleApi { | ||
/** | ||
* Gets the metadata of the current App. | ||
*/ | ||
meta: AppMetadata; | ||
meta: ModuleMetaData; | ||
eventHub: EchoEventHub; | ||
} | ||
export interface RouteRegistration extends BaseRegistration { | ||
meta: AppMetaData; | ||
export interface ModuleData { | ||
setup: (api: EchoModuleApi) => void | Promise<void>; | ||
} | ||
export interface AppMetaData { | ||
name: string; | ||
icon: string; | ||
homeScreen?: boolean; | ||
} | ||
export interface BaseRegistration { | ||
key: string; | ||
} | ||
export interface AppData { | ||
setup: (api: AppApi) => void | Promise<void>; | ||
} | ||
export interface MultiAppData { | ||
setup: (apiFactory: AppApiCreator) => void | Promise<void>; | ||
} | ||
export interface EchoPortal { | ||
isAuthenticated: boolean; | ||
} | ||
export declare type AppMetaFetch = () => Promise<AppMetadata[]>; | ||
export declare type AppMetaFetch = () => Promise<ModuleMetaData[]>; | ||
/** | ||
* The creator function for the App API. | ||
*/ | ||
export interface AppApiCreator { | ||
(target: AppMetadata): AppApi; | ||
} | ||
/** | ||
* The record containing all available dependencies. | ||
@@ -68,0 +35,0 @@ */ |
@@ -1,2 +0,2 @@ | ||
import { AppData, AppMetadata } from "../types/module"; | ||
export declare function createEmptyModule(meta: AppMetadata): AppData; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
export declare function createEmptyModule(meta: ModuleMetaData): EchoModule; |
@@ -1,2 +0,2 @@ | ||
import { EchoEventHub, EchoEvents } from '../types/event'; | ||
import { EchoEventHub, EchoEvents, UnsubscribeFunction } from '../types/event'; | ||
/** | ||
@@ -26,3 +26,3 @@ * Class for creating an eventHub to be used for emitting and subscribing to either | ||
*/ | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): () => void; | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): UnsubscribeFunction; | ||
/** | ||
@@ -37,5 +37,5 @@ * Function for subscribing to an array of events. | ||
*/ | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction; | ||
} | ||
export declare const eventHub: EventHub; | ||
export default eventHub; | ||
export {}; |
@@ -63,3 +63,2 @@ "use strict"; | ||
exports.eventHub = new EventHub(); | ||
exports.default = exports.eventHub; | ||
//# sourceMappingURL=eventHub.js.map |
@@ -0,2 +1,4 @@ | ||
export * from './emptyApp'; | ||
export * from './eventHub'; | ||
export * from './getDependencyResolver'; | ||
export * from './storage'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
tslib_1.__exportStar(require("./emptyApp"), exports); | ||
tslib_1.__exportStar(require("./eventHub"), exports); | ||
tslib_1.__exportStar(require("./getDependencyResolver"), exports); | ||
tslib_1.__exportStar(require("./storage"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@equinor/echo-base", | ||
"version": "0.2.96", | ||
"version": "0.2.97", | ||
"module": "esm/index.js", | ||
@@ -15,3 +15,4 @@ "main": "lib/index.js", | ||
"echo-publish-next": "npm publish --access public --tag next", | ||
"test": "echo \"Run test from root folder\" && exit 1" | ||
"test": "echo \"Run test from root folder\" && exit 1", | ||
"build-docs": "npx typedoc --out docs src/index.ts" | ||
}, | ||
@@ -34,2 +35,3 @@ "keywords": [ | ||
"@types/node": "^14.14.37", | ||
"typedoc": "^0.20.35", | ||
"typescript": "^4.2.4" | ||
@@ -36,0 +38,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
import { BaseError } from '../../errors/BaseError'; | ||
import { BaseError } from '../../errors'; | ||
@@ -3,0 +3,0 @@ describe('BaseError', () => { |
@@ -6,2 +6,1 @@ export * from './errors'; | ||
export * from './utils'; | ||
export { default as eventHub } from './utils/eventHub'; |
@@ -0,16 +1,56 @@ | ||
import { EchoModulesLoading, LoadingModuleOptions } from '../types'; | ||
import { EchoModule } from '../types/module'; | ||
import { standardStrategy } from './strategies'; | ||
import { fireAndForget, isfunc } from './utils'; | ||
interface StartLoadingModules { | ||
connect(notifier: EchoModulesLoading): void; | ||
disconnect(notifier: EchoModulesLoading): void; | ||
} | ||
/** | ||
* Used to start loading modules, the modules can be provided, or a fetch call can be defined to | ||
* retrieving the moduleMetaData that in turn will load the js files, and initialize the all modules. | ||
* Module data will be stored in the globals store trough the notifier provided trough the connect function. | ||
* | ||
* This function is used in Echo Framework in the Mediator Component. | ||
* | ||
* @export | ||
* @param {LoadingModuleOptions} options | ||
* @return {*} {StartLoadingModules} | ||
*/ | ||
export function startLoadingModules(options: LoadingModuleOptions): StartLoadingModules { | ||
const state = { | ||
loaded: false, | ||
modules: [], | ||
error: undefined | ||
}; | ||
const notifiers: EchoModulesLoading[] = []; | ||
const call = (notifier: EchoModulesLoading): void => notifier(state.error, state.modules, state.loaded); | ||
const notify = (): void => notifiers.forEach(call); | ||
const setAppModules = (error: Error, modules: Array<EchoModule>): void => { | ||
state.error = error; | ||
state.modules = modules; | ||
notify(); | ||
}; | ||
const setLoaded = (): void => { | ||
state.loaded = true; | ||
notify(); | ||
}; | ||
fireAndForget(() => standardStrategy(options, setAppModules).then(setLoaded, setLoaded)); | ||
export function startLoadingApps(options: {} ) { | ||
const state = { | ||
loading: false, | ||
apps: [], | ||
error: undefined, | ||
} | ||
} | ||
return { | ||
connect(notifier: EchoModulesLoading): void { | ||
if (isfunc(notifier)) { | ||
notifiers.push(notifier); | ||
call(notifier); | ||
} | ||
}, | ||
disconnect(notifier: EchoModulesLoading): void { | ||
const index = notifiers.indexOf(notifier); | ||
index !== -1 && notifiers.splice(index, 1); | ||
} | ||
}; | ||
} |
@@ -7,4 +7,4 @@ /** | ||
*/ | ||
export async function fetchDependency(url: string, token: string): Promise<string> { | ||
const m = await fetch(url, { | ||
export async function defaultFetchDependency(url: string, token?: string): Promise<string> { | ||
const module = await fetch(url, { | ||
headers: { token }, | ||
@@ -14,3 +14,3 @@ method: 'GET', | ||
}); | ||
return await m.text(); | ||
return await module.text(); | ||
} |
@@ -0,8 +1,12 @@ | ||
export * from './aggregate'; | ||
export * from './create'; | ||
export * from './dependency'; | ||
export * from './errors'; | ||
export * from './fetch'; | ||
export * from './fetchModules'; | ||
export * from './load'; | ||
export * from './loader'; | ||
export * from './persist'; | ||
export * from './setup'; | ||
export * from './strategies'; | ||
export * from './utils'; | ||
export * from './verify'; | ||
@@ -1,27 +0,75 @@ | ||
import { App, AppData, AppMetadata, AvailableDependencies } from '../types/module'; | ||
import { checkAppAsync, getLocalRequire } from './dependency'; | ||
import { | ||
AppDependencyGetter, | ||
AvailableDependencies, | ||
DefaultLoaderConfig, | ||
EchoModule, | ||
ModuleData, | ||
ModuleLoader, | ||
ModuleMetaData | ||
} from '../types'; | ||
import { createEmptyModule } from '../utils/emptyApp'; | ||
import { getDependencyResolver } from '../utils/getDependencyResolver'; | ||
import { includeDependency } from './dependency'; | ||
export function loadModule(meta: AppMetadata, loadModuleData: (meta: AppMetadata) => AppData): App { | ||
const module = loadModuleData(meta); | ||
return { ...meta, ...module }; | ||
const inBrowser = typeof document !== 'undefined'; | ||
/** | ||
* Create a module loader with the provided dependencies. | ||
* | ||
* @export | ||
* @param {DefaultLoaderConfig} [config] | ||
* @param {AvailableDependencies} [dependencies] | ||
* @param {AppDependencyGetter} [getDependencies] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export function createModuleLoader( | ||
config?: DefaultLoaderConfig, | ||
dependencies?: AvailableDependencies, | ||
getDependencies?: AppDependencyGetter | ||
): ModuleLoader { | ||
const getDeps = getDependencyResolver(dependencies, getDependencies); | ||
return getModuleLoader(getDeps, config); | ||
} | ||
export function loadApp( | ||
link: string, | ||
depName: string, | ||
dependencies: AvailableDependencies | ||
): Promise<AppData | undefined> { | ||
return new Promise<AppData | undefined>((resolve, reject) => { | ||
const s = document.createElement('script'); | ||
s.async = true; | ||
s.src = link; | ||
s.crossOrigin = 'cross-origin'; | ||
window[depName] = getLocalRequire(dependencies); | ||
s.onload = (): void => { | ||
const app = checkAppAsync(s.app); | ||
resolve(app); | ||
}; | ||
s.onerror = (): void => reject('could not load'); | ||
document.head.appendChild(s); | ||
}); | ||
/** | ||
* Loader for loading modules, with dependencies. | ||
* Will return an empty module, for avoiding crashes. | ||
* | ||
* @export | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {DefaultLoaderConfig} [config={}] | ||
* @return {*} {ModuleLoader} | ||
*/ | ||
export function getModuleLoader(getDependencies: AppDependencyGetter, config: DefaultLoaderConfig = {}): ModuleLoader { | ||
return (meta: ModuleMetaData): Promise<EchoModule> => { | ||
if (inBrowser && 'requireRef' in meta && meta.requireRef) { | ||
return loadModule(meta, getDependencies, (deps) => includeDependency(meta, deps, config.crossOrigin)); | ||
} | ||
console.warn('Empty Module found!', meta.name); | ||
return Promise.resolve(createEmptyModule(meta)); | ||
}; | ||
} | ||
/** | ||
* Loading the module and combining the javascript module with the modules Metadata. | ||
* | ||
* @param {ModuleMetaData} meta | ||
* @param {AppDependencyGetter} getDependencies | ||
* @param {(dependencies: AvailableDependencies) => Promise<ModuleData>} loader | ||
* @return {*} {Promise<EchoModule>} | ||
*/ | ||
async function loadModule( | ||
meta: ModuleMetaData, | ||
getDependencies: AppDependencyGetter, | ||
loader: (dependencies: AvailableDependencies) => Promise<ModuleData> | ||
): Promise<EchoModule> { | ||
const dependencies = { | ||
...(getDependencies(meta) || {}) | ||
}; | ||
const app = await loader(dependencies); | ||
return { | ||
...app, | ||
...meta | ||
}; | ||
} |
@@ -1,10 +0,10 @@ | ||
import { AppMetadata } from '../types/module'; | ||
import { ModuleMetaData } from '../types/module'; | ||
import { storage } from '../utils/storage'; | ||
export function persistLocalModuleMeta(key: string, modules: AppMetadata[]): void { | ||
export function persistLocalModuleMeta(key: string, modules: ModuleMetaData[]): void { | ||
storage.setItem(key, modules); | ||
} | ||
export function loadLocalModuleMeta(key: string): AppMetadata[] { | ||
const localModules: AppMetadata[] | undefined | string = storage.getItem(key); | ||
export function loadLocalModuleMeta(key: string): ModuleMetaData[] { | ||
const localModules: ModuleMetaData[] | undefined | string = storage.getItem(key); | ||
if (!localModules || !(localModules instanceof Array)) { | ||
@@ -11,0 +11,0 @@ return []; |
@@ -1,24 +0,14 @@ | ||
import { App, AppApi, AppApiCreator, MultiApp, SingleApp } from '../types'; | ||
import { EchoModule, EchoModuleApi, EchoModuleApiCreator } from '../types'; | ||
export function setupSingleApp(app: SingleApp, api: AppApi): void | Promise<void> { | ||
export function setupSingleModule(module: EchoModule, api: EchoModuleApi): void | Promise<void> { | ||
try { | ||
const result = app.setup(api); | ||
const result = module.setup(api); | ||
return result; | ||
} catch (error) {} | ||
} | ||
export function setupMultiApps(app: MultiApp, apiFactory: AppApiCreator): void | Promise<void> { | ||
try { | ||
return app.setup(apiFactory); | ||
} catch (e) { | ||
console.error(`Error while setting up ${app?.name}.`, e); | ||
} catch (error) { | ||
console.warn(error); | ||
} | ||
} | ||
export function setupApp(app: App, apiFactory: AppApiCreator): void | Promise<void> { | ||
if ('bundle' in app) { | ||
return setupMultiApps(app as MultiApp, apiFactory); | ||
} else { | ||
return setupSingleApp(app, apiFactory(app)); | ||
} | ||
export function setupModule(module: EchoModule, apiFactory: EchoModuleApiCreator): void | Promise<void> { | ||
return setupSingleModule(module, apiFactory(module)); | ||
} |
@@ -1,4 +0,10 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { AppMetadata, SingleApp } from '../types/module'; | ||
import { EchoModuleApiCreator, ModuleRequester } from '../types/creators'; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {string} id | ||
*/ | ||
export function removeElementById(id: string): void { | ||
@@ -8,7 +14,36 @@ document.getElementById(id)?.remove(); | ||
export function isfunc(f: any): f is Function { | ||
/** | ||
* Helper function for Checking if function is present. | ||
* | ||
* @param {EchoModuleApiCreator} createModuleApi | ||
* @return {*} {boolean} | ||
*/ | ||
export function checkFunction(func: EchoModuleApiCreator | ModuleRequester, errorMessage: string): boolean { | ||
if (!isfunc(func)) { | ||
console.warn(errorMessage); | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {*} f | ||
* @return {*} {f is Function} | ||
*/ | ||
export function isfunc(f: unknown): f is Function { | ||
return typeof f === 'function'; | ||
} | ||
export function createEmptyModule(meta: AppMetadata): SingleApp { | ||
/** | ||
* | ||
* | ||
* @export | ||
* @param {ModuleMetaData} meta | ||
* @return {*} {SingleApp} | ||
*/ | ||
export function createEmptyApp(meta: ModuleMetaData): EchoModule { | ||
return { | ||
@@ -21,1 +56,19 @@ ...meta, | ||
} | ||
export function isProduction(): boolean { | ||
return process.env.NODE_ENV === 'production'; | ||
} | ||
export function filterExcludePrivateModulesInProduction( | ||
modules: EchoModule[], | ||
isProduction?: () => boolean | ||
): EchoModule[] { | ||
if (isProduction && isProduction()) { | ||
return modules.filter((module) => module.private !== true); | ||
} | ||
return modules; | ||
} | ||
export function fireAndForget(asyncFunc: () => Promise<void>): void { | ||
asyncFunc(); | ||
} |
@@ -1,11 +0,11 @@ | ||
import ArgumentError from '../errors/ArgumentError'; | ||
import { AppMetadata } from '../types/module'; | ||
import { ModuleMetaData } from '../types/module'; | ||
import { persistLocalModuleMeta } from './persist'; | ||
export function verifyModulesMeta(modules: AppMetadata[]): AppMetadata[] { | ||
if (modules.length === 0) { | ||
throw new ArgumentError({ argumentName: 'No modules awaitable' }); | ||
export function verifyModulesMeta(modules: ModuleMetaData[]): ModuleMetaData[] { | ||
if (modules instanceof Array) { | ||
modules.length > 0 && persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
} | ||
persistLocalModuleMeta('EchoModules', modules); | ||
return modules; | ||
console.info('No modules awaitable.'); | ||
return []; | ||
} |
@@ -8,6 +8,8 @@ /** | ||
emit<T>(key: string, payload: T): void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): () => void; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void; | ||
subscribe<T>(key: string, handler: (payload: T) => void): UnsubscribeFunction; | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction; | ||
} | ||
export type UnsubscribeFunction = () => void; | ||
export enum EchoEvents { | ||
@@ -18,26 +20,2 @@ PlantChanged = 'plantChanged', | ||
/** | ||
* Emitter of module app shell events. | ||
*/ | ||
export interface ModuleEventEmitter { | ||
/** | ||
* Attaches a new event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
on<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Detaches an existing event listener. | ||
* @param type The type of the event to listen for. | ||
* @param callback The callback to trigger. | ||
*/ | ||
of<K extends keyof EventMap>(type: K, callback: Listener<EventMap[K]>): ModuleEventEmitter; | ||
/** | ||
* Emits a new event with the given type. | ||
* @param type The type of the event to emit. | ||
* @param arg The payload of the event. | ||
*/ | ||
emit<K extends keyof EventMap>(type: K, arg: EventMap[K]): ModuleEventEmitter; | ||
} | ||
export interface EventMap { | ||
@@ -44,0 +22,0 @@ [custom: string]: unknown; |
@@ -0,5 +1,8 @@ | ||
export * from './common'; | ||
export * from './creators'; | ||
export * from './error'; | ||
export * from './event'; | ||
export * from './loader'; | ||
export * from './module'; | ||
export * from './options'; | ||
export * from './storage'; | ||
@@ -0,7 +1,29 @@ | ||
import { BaseError } from '../errors'; | ||
import { EchoModule, ModuleMetaData } from './module'; | ||
export class ModuleAppError extends BaseError {} | ||
/** | ||
* Configuration options for the default loader. | ||
*/ | ||
export interface LoaderConfig { | ||
export interface LoaderConfig { | ||
crossOrigin?: string; | ||
} | ||
} | ||
export interface ModulesLoader { | ||
(): Array<EchoModule>; | ||
} | ||
export interface EchoModuleLoaded { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>): void; | ||
} | ||
export interface EchoModulesLoading { | ||
(error: ModuleAppError | undefined, modules: Array<EchoModule>, loaded: boolean): void; | ||
} | ||
export interface ModuleLoader { | ||
(meta: ModuleMetaData): Promise<EchoModule>; | ||
} | ||
export interface DefaultLoaderConfig { | ||
crossOrigin?: string; | ||
} |
@@ -1,88 +0,45 @@ | ||
import { ModuleEventEmitter } from "./event"; | ||
import { EchoEventHub } from './event'; | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export interface SingleAppMetadata { | ||
name: string; | ||
link: string; | ||
requireRef: string; | ||
integrity?: string; | ||
custom?: any; | ||
config?: Record<string, any>; | ||
export interface ModuleMetaData extends MetaDataBase { | ||
requireRef?: string; | ||
} | ||
export interface MultiAppsMetadata { | ||
export interface MetaDataBase { | ||
key: string; | ||
name: string; | ||
link: string; | ||
bundle: string; | ||
shortName: string; | ||
path: string; | ||
fileUri: string; | ||
version: string; | ||
integrity?: string; | ||
custom?: any; | ||
private?: boolean; | ||
} | ||
export type App = SingleApp | MultiApp; | ||
/** | ||
* Describes the metadata transported by a Apps. | ||
* Echo Module setup function and meta data combined. | ||
*/ | ||
export type AppMetadata = SingleAppMetadata | MultiAppsMetadata; | ||
export type EchoModule = ModuleData & ModuleMetaData; | ||
/** | ||
* The metadata for a single app. | ||
*/ | ||
export type SingleApp = AppData & AppMetadata; | ||
/** | ||
* The metadata for apps containing apps. | ||
*/ | ||
export type MultiApp = MultiAppData & MultiAppsMetadata; | ||
/** | ||
* Defines the API accessible from Apps. | ||
*/ | ||
export interface AppApi extends ModuleEventEmitter { | ||
export interface EchoModuleApi { | ||
/** | ||
* Gets the metadata of the current App. | ||
*/ | ||
meta: AppMetadata; | ||
meta: ModuleMetaData; | ||
eventHub: EchoEventHub; | ||
} | ||
export interface RouteRegistration extends BaseRegistration { | ||
meta: AppMetaData; | ||
export interface ModuleData { | ||
setup: (api: EchoModuleApi) => void | Promise<void>; | ||
} | ||
export interface AppMetaData { | ||
name: string; | ||
icon: string; | ||
homeScreen?: boolean; | ||
} | ||
export type AppMetaFetch = () => Promise<ModuleMetaData[]>; | ||
export interface BaseRegistration { | ||
key: string; | ||
} | ||
export interface AppData { | ||
setup: (api: AppApi) => void | Promise<void>; | ||
} | ||
export interface MultiAppData { | ||
setup: (apiFactory: AppApiCreator) => void | Promise<void>; | ||
} | ||
export interface EchoPortal { | ||
isAuthenticated: boolean; | ||
} | ||
export type AppMetaFetch = () => Promise<AppMetadata[]>; | ||
/** | ||
* The creator function for the App API. | ||
*/ | ||
export interface AppApiCreator { | ||
(target: AppMetadata): AppApi; | ||
} | ||
/** | ||
* The record containing all available dependencies. | ||
*/ | ||
export interface AvailableDependencies { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
[name: string]: any; | ||
} |
@@ -1,10 +0,10 @@ | ||
import { AppData, AppMetadata } from "../types/module"; | ||
import { EchoModule, ModuleMetaData } from '../types/module'; | ||
export function createEmptyModule(meta: AppMetadata): AppData { | ||
export function createEmptyModule(meta: ModuleMetaData): EchoModule { | ||
return { | ||
...meta, | ||
setup(): void { | ||
// Empty Setup | ||
}, | ||
...meta, | ||
setup(): void { | ||
// Empty Setup | ||
} | ||
}; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { EchoEventHub, EchoEvents } from '../types/event'; | ||
import { EchoEventHub, EchoEvents, UnsubscribeFunction } from '../types/event'; | ||
@@ -31,3 +31,3 @@ /** | ||
*/ | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): () => void { | ||
subscribe<T>(key: string | EchoEvents, handler: (payload: T) => void): UnsubscribeFunction { | ||
const eventHandler = (e: Event): void => { | ||
@@ -51,3 +51,3 @@ const customEvent = e as CustomEvent; | ||
*/ | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): () => void { | ||
subscribeMany<T>(keys: Array<string | EchoEvents>, handler: (payload: T) => void): UnsubscribeFunction { | ||
const unsubscribeFunctions: Array<() => void> = keys.map((key) => this.subscribe(key, handler)); | ||
@@ -62,3 +62,1 @@ return (): void => { | ||
export const eventHub = new EventHub(); | ||
export default eventHub; |
@@ -0,2 +1,4 @@ | ||
export * from './emptyApp'; | ||
export * from './eventHub'; | ||
export * from './getDependencyResolver'; | ||
export * from './storage'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
218040
294
4615
3
2