UNPKG

@foxpage/foxpage-manager

Version:

foxpage resource manager

405 lines (404 loc) 13.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LibraryManagerImpl = void 0; const foxpage_shared_1 = require("@foxpage/foxpage-shared"); const common_1 = require("../common"); const data_service_1 = require("../data-service"); const library_1 = require("./library"); /** * library manager * library * * @export * @class PackageManager */ class LibraryManagerImpl extends common_1.ManagerBaseImpl { constructor(app) { super(app, { type: 'library', diskCache: { enable: true }, lruCache: { cloned: false } }); /** * cache library name & versions * key: library name, value: version list * @private */ this.libraryVersionsMap = new Map(); /** * library id map * key: library id, value: library name * * @private */ this.libraryIdMap = new Map(); this.generateKey = (name, version) => { return foxpage_shared_1.packager.generateKey(name, version); }; this.splitKey = (key) => { return foxpage_shared_1.packager.splitKey(key); }; this.resourceConfig = app.resourceMap; this.config = app.configs.package || {}; } /** * add library to manager * * @param {PrePackage} pkg */ addLibrary(pkg) { const { id, name, version } = pkg; this.logger.info(`add library ${name}@${version}`); if (!version) { this.logger.warn('library version is invalid'); return null; } const newPkg = this.newLibrary(pkg); this.addOne(newPkg.key, pkg, newPkg); this.updateLibraryVersionsMap(pkg); this.updateLibraryLiveVersion(pkg); this.libraryIdMap.set(id, name); return newPkg; } /** * remove library from manager via library names * * @param {string[]} names library names */ removeLibraries(names) { const versionInfo = this.getLibraryVersionsByNames(names); Object.keys(versionInfo).forEach(name => { var _a; const versions = versionInfo[name]; if (versions) { this.remove(versions.map(item => this.generateKey(name, item))); } const libraryId = (_a = this.libraryVersionsMap.get(name)) === null || _a === void 0 ? void 0 : _a.id; if (libraryId) { this.libraryIdMap.delete(libraryId); } this.libraryVersionsMap.delete(name); }); } /** * get library by library name * will return the live versions * @param {string} type * @return {*} {PrePackage | undefined} */ async getLibrary(name) { return (await this.getLibraries([name]))[0]; } /** * get all libraries by library names * will return the live versions * @param {string[]} names * @return {*} {Promise<PrePackage[]>} */ async getLibraries(names) { const keys = names.map(name => { const liveVersion = this.getLibraryLiveVersion(name); return this.generateKey(name, liveVersion || ''); }); return await this.find(keys); } /** * get libraries by id * @param ids library ids * @returns */ async getLibrariesById(ids) { const keys = ids .map(id => { const name = this.libraryIdMap.get(id); if (name) { const liveVersion = this.getLibraryLiveVersion(name); return this.generateKey(name, liveVersion || ''); } }) .filter(foxpage_shared_1.isNotNill); return await this.find(keys); } /** * select one version * * @param {string} name library name * @return {*} */ getLibraryLiveVersion(name) { var _a; return (_a = this.libraryVersionsMap.get(name)) === null || _a === void 0 ? void 0 : _a.liveVersion; } /** * update library live version * * @param {string} pkg library content */ updateLibraryLiveVersion(pkg) { if (pkg.isLive) { const pkgInfo = this.libraryVersionsMap.get(pkg.name); if (pkgInfo) { pkgInfo.liveVersion = pkg.version; } } } /** * get library sync from hot * @param name library name * @param version library version * @returns pkg */ getLibrarySync(name, version) { const versions = this.getLibraryVersionsByNames([name])[name]; if (!versions) { return null; } if (version && versions.indexOf(version) === -1) { this.logger.warn(`get local library: ${name}@${version} is empty.`); return null; } // !version use live version, or use appoint version let curVersion = this.getLibraryLiveVersion(name); if (version && version !== curVersion) { this.logger.info(`library ${name} local live version is: ${curVersion}, appoint version is: ${version}`); curVersion = version; } if (!curVersion) { this.logger.warn(`library ${name} version is invalid`); return null; } const key = this.generateKey(name, curVersion); const pkg = this.findOne(key); if (!pkg || pkg.version !== curVersion) { this.logger.warn(`get local library: ${key} is empty.`); return null; } // this.logger.info(`get local library: ${key} succeed.`); return pkg; } /** * get local library * * @param {string} name library name * @param {string} version library version * @return {*} {(PrePackage | null)} */ async getLocalLibrary(name, version) { const versions = this.getLibraryVersionsByNames([name])[name]; if (!versions) { return null; } if (version && versions.indexOf(version) === -1) { this.logger.warn(`get local library: ${name}@${version} is empty.`); return null; } // !version use live version, or use appoint version let curVersion = this.getLibraryLiveVersion(name); if (version && version !== curVersion) { this.logger.info(`library ${name} local live version is: ${curVersion}, appoint version is: ${version}`); curVersion = version; } if (!curVersion) { this.logger.warn(`library ${name} version is invalid`); return null; } const key = this.generateKey(name, curVersion); const pkg = await this.findOneFromLocal(key); if (!pkg || pkg.version !== curVersion) { this.logger.warn(`get local library: ${key} is empty.`); return null; } // this.logger.info(`get local library: ${key} succeed.`); return pkg; } /** * fetch libraries, instance libraries and install libraries then add to local * note: return contains library dependencies contents * @param {PackageFreshOption} [params] * @return {*} */ async freshLibraries(params) { const libraries = (params === null || params === void 0 ? void 0 : params.namedVersions) ? this.resolveLibrary(await this.fetchLibrariesByNamedVersions(params.namedVersions)) : await this.fetchLibraries(params === null || params === void 0 ? void 0 : params.packageIds, { strategy: params === null || params === void 0 ? void 0 : params.strategy }); return await this.install(libraries, { cache: true }); } /** * install libraries * * @param {FPPackage[]} libraries * @param {{ cache: boolean; ignoreLocal:boolean }} [opt] {cache: will add libraries instance to manager} * @return {*} */ async install(libraries, opt) { const installs = await this.initInstalls(libraries, opt); return installs; } /** * fetch libraries from server * * @param {string[]} [libraryIds] * @return {*} */ async fetchLibraries(packageIds, opt = {}) { var _a; return await data_service_1.foxpageDataService.fetchLibraries(this.appId, Object.assign(Object.assign({ packageIds }, opt), { semver: (_a = this.config) === null || _a === void 0 ? void 0 : _a.version })); } /** * fetch libraries with name and version from server * * @param {PackageNamedVersion[]} nameVersions * @param {PackageFreshOption} opt {isCanary,...} * @return {Promise<FPPackageResponse[]>} */ async fetchLibrariesByNamedVersions(nameVersions, opt) { var _a; return await data_service_1.foxpageDataService.fetchLibrariesByNamedVersions(this.appId, { nameVersions, isCanary: opt === null || opt === void 0 ? void 0 : opt.isCanary, semver: (_a = this.config) === null || _a === void 0 ? void 0 : _a.version, }); } /** * listen the "ON_PULL" event * updates & removes is the library content id list * @protected * @param {ResourceUpdateInfo} data * @return {*} {Promise<void>} */ async onPull(data) { const { updates, removes } = data.library || {}; if (updates && updates.length > 0) { // this.markNeedUpdates(updates); await this.freshLibraries({ packageIds: updates }); } if (removes && removes.length > 0) { this.removeLibraries(removes.map(item => this.libraryIdMap.get(item)).filter(foxpage_shared_1.isNotNill)); } } /** * on stash * @param data */ onStash(data) { var _a; (_a = data.libraries) === null || _a === void 0 ? void 0 : _a.map(item => { this.addLibrary(item); }); } /** * on fetch * list: the manager keys * @protected * @param {string[]} list * @return {*} {Promise<PackageImpl[]>} */ async onFetch(list) { return await this.freshLibraries({ namedVersions: list.map(item => { const [name, version] = this.splitKey(item); return { name, version }; }), }); } async createInstance(data) { const instance = this.newLibrary(data); // await instance.install(); return instance; } newLibrary(data) { return new library_1.LibraryInstance(data, { appId: this.appId, appSlug: this.appSlug, resource: this.resourceConfig, logger: this.logger, }); } resolveLibrary(libraryInfos) { return libraryInfos.map(item => item.package); } /** * init need install libraries instances * * @private * @param {FPPackage[]} libraries * @param {{ cache: boolean, ignoreLocal:boolean }} [opt] * @return {*} */ async initInstalls(libraries, opt) { var _a; const installMap = new Map(); const { cache = false, ignoreLocal = false } = opt || {}; const create = async (list, { initDependencies } = { initDependencies: false }) => { for (const pkg of list) { const { name, version, components } = pkg; const key = this.generateKey(name, version); const localPkg = !ignoreLocal ? await this.getLocalLibrary(name, version) : null; // will install it if (!localPkg && !installMap.has(key)) { let newPkg; if (cache) { newPkg = await this.addLibrary(pkg); } else { newPkg = this.newLibrary(pkg); } if (newPkg) { installMap.set(key, newPkg); } } else { if (cache) { this.updateLibraryLiveVersion(pkg); } } // init components // components: the dependencies contents if (initDependencies && (components === null || components === void 0 ? void 0 : components.length)) { await create(components); } } }; try { await create(libraries, { initDependencies: true }); } catch (e) { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(`install libraries failed: `, e); } return Array.from(installMap.values()); } /** * get library versions * * @private * @param {string[]} names library names * @return {*} {[key]: library name, [value]: versions} */ getLibraryVersionsByNames(names) { const versionInfo = {}; names.forEach(name => { const { versions } = this.libraryVersionsMap.get(name) || {}; if (!versions) { // this.logger.warn(`not exist the library@${name} in libraryMap`); versionInfo[name] = null; } else { versionInfo[name] = versions; } }); return versionInfo; } updateLibraryVersionsMap(pkg) { const { id, name, version } = pkg; const { versions } = this.libraryVersionsMap.get(name) || {}; if (versions) { versions.push(version); } else { this.libraryVersionsMap.set(name, { id, liveVersion: '', versions: [version] }); this.updateLibraryLiveVersion(pkg); } } destroy() { super.destroy(); this.libraryIdMap.clear(); this.libraryVersionsMap.clear(); } } exports.LibraryManagerImpl = LibraryManagerImpl;