|
|
@ -21,7 +21,7 @@ import { |
|
|
Injectable, |
|
|
Injectable, |
|
|
Injector, |
|
|
Injector, |
|
|
ModuleWithComponentFactories, |
|
|
ModuleWithComponentFactories, |
|
|
Type |
|
|
Type, ɵNG_MOD_DEF |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { DOCUMENT } from '@angular/common'; |
|
|
import { DOCUMENT } from '@angular/common'; |
|
|
import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs'; |
|
|
import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs'; |
|
|
@ -50,7 +50,6 @@ export class ResourcesService { |
|
|
|
|
|
|
|
|
private loadedJsonResources: { [url: string]: ReplaySubject<any> } = {}; |
|
|
private loadedJsonResources: { [url: string]: ReplaySubject<any> } = {}; |
|
|
private loadedResources: { [url: string]: ReplaySubject<void> } = {}; |
|
|
private loadedResources: { [url: string]: ReplaySubject<void> } = {}; |
|
|
private loadedModules: { [url: string]: ReplaySubject<Type<any>[]> } = {}; |
|
|
|
|
|
private loadedModulesAndFactories: { [url: string]: ReplaySubject<ModulesWithFactories> } = {}; |
|
|
private loadedModulesAndFactories: { [url: string]: ReplaySubject<ModulesWithFactories> } = {}; |
|
|
|
|
|
|
|
|
private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0]; |
|
|
private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0]; |
|
|
@ -201,71 +200,6 @@ export class ResourcesService { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public loadModules(resourceId: string | TbResourceId, modulesMap: IModulesMap): Observable<Type<any>[]> { |
|
|
|
|
|
const url = this.getDownloadUrl(resourceId); |
|
|
|
|
|
if (this.loadedModules[url]) { |
|
|
|
|
|
return this.loadedModules[url].asObservable(); |
|
|
|
|
|
} |
|
|
|
|
|
modulesMap.init(); |
|
|
|
|
|
const meta = this.getMetaInfo(resourceId); |
|
|
|
|
|
const subject = new ReplaySubject<Type<any>[]>(); |
|
|
|
|
|
this.loadedModules[url] = subject; |
|
|
|
|
|
import('@angular/compiler').then( |
|
|
|
|
|
() => { |
|
|
|
|
|
System.import(url, undefined, meta).then( |
|
|
|
|
|
(module) => { |
|
|
|
|
|
try { |
|
|
|
|
|
let modules; |
|
|
|
|
|
try { |
|
|
|
|
|
modules = this.extractNgModules(module); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error(e); |
|
|
|
|
|
} |
|
|
|
|
|
if (modules && modules.length) { |
|
|
|
|
|
const tasks: Promise<ModuleWithComponentFactories<any>>[] = []; |
|
|
|
|
|
for (const m of modules) { |
|
|
|
|
|
tasks.push(this.compiler.compileModuleAndAllComponentsAsync(m)); |
|
|
|
|
|
} |
|
|
|
|
|
forkJoin(tasks).subscribe((compiled) => { |
|
|
|
|
|
try { |
|
|
|
|
|
for (const c of compiled) { |
|
|
|
|
|
c.ngModuleFactory.create(this.injector); |
|
|
|
|
|
} |
|
|
|
|
|
this.loadedModules[url].next(modules); |
|
|
|
|
|
this.loadedModules[url].complete(); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
this.loadedModules[url].error(new Error(`Unable to init module from url: ${url}`)); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
(e) => { |
|
|
|
|
|
this.loadedModules[url].error(new Error(`Unable to compile module from url: ${url}`)); |
|
|
|
|
|
}); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.loadedModules[url].error(new Error(`Module '${url}' doesn't have default export or not NgModule!`)); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
this.loadedModules[url].error(new Error(`Unable to load module from url: ${url}`)); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
(e) => { |
|
|
|
|
|
this.loadedModules[url].error(new Error(`Unable to load module from url: ${url}`)); |
|
|
|
|
|
console.error(`Unable to load module from url: ${url}`, e); |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
return subject.asObservable().pipe( |
|
|
|
|
|
tap({ |
|
|
|
|
|
next: () => System.delete(url), |
|
|
|
|
|
error: () => { |
|
|
|
|
|
delete this.loadedModulesAndFactories[url]; |
|
|
|
|
|
System.delete(url); |
|
|
|
|
|
}, |
|
|
|
|
|
complete: () => System.delete(url) |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private extractNgModules(module: any, modules: Type<any>[] = []): Type<any>[] { |
|
|
private extractNgModules(module: any, modules: Type<any>[] = []): Type<any>[] { |
|
|
try { |
|
|
try { |
|
|
let potentialModules = [module]; |
|
|
let potentialModules = [module]; |
|
|
@ -274,7 +208,7 @@ export class ResourcesService { |
|
|
while (potentialModules.length && currentScanDepth < 10) { |
|
|
while (potentialModules.length && currentScanDepth < 10) { |
|
|
const newPotentialModules = []; |
|
|
const newPotentialModules = []; |
|
|
for (const potentialModule of potentialModules) { |
|
|
for (const potentialModule of potentialModules) { |
|
|
if (potentialModule && ('ɵmod' in potentialModule)) { |
|
|
if (potentialModule && (ɵNG_MOD_DEF in potentialModule)) { |
|
|
modules.push(potentialModule); |
|
|
modules.push(potentialModule); |
|
|
} else { |
|
|
} else { |
|
|
for (const k of Object.keys(potentialModule)) { |
|
|
for (const k of Object.keys(potentialModule)) { |
|
|
@ -349,7 +283,6 @@ export class ResourcesService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private clearModulesCache() { |
|
|
private clearModulesCache() { |
|
|
this.loadedModules = {}; |
|
|
|
|
|
this.loadedModulesAndFactories = {}; |
|
|
this.loadedModulesAndFactories = {}; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|