forked from onecx/onecx-portal-ui-libs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: slot service implementation in angular-remote-components (onecx…
…#251) * feat: slot service with permission service to be proxied * feat: lint * feat: new topic and structure * feat: extended SlotService with component presence check * fix: topic not synchronizable * refactor: someComponentDefinedForSlot refactor * fix: fixed comparsion between strings
- Loading branch information
Showing
13 changed files
with
136 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
libs/angular-remote-components/src/lib/services/permission.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Injectable } from '@angular/core' | ||
import { PermissionsRpcTopic } from '@onecx/integration-interface' | ||
import { filter, firstValueFrom, map } from 'rxjs' | ||
|
||
@Injectable({ providedIn: 'root' }) | ||
export class PermissionService { | ||
private permissionsTopic$ = new PermissionsRpcTopic() | ||
|
||
async getPermissions(appId: string, productName: string): Promise<string[]> { | ||
const permissions = firstValueFrom( | ||
this.permissionsTopic$.pipe( | ||
filter( | ||
(message) => | ||
message.appId === appId && message.productName === productName && Array.isArray(message.permissions) | ||
), | ||
map((message) => message.permissions ?? []) | ||
) | ||
) | ||
this.permissionsTopic$.publish({ appId: appId, productName: productName }) | ||
return permissions | ||
} | ||
} |
74 changes: 66 additions & 8 deletions
74
libs/angular-remote-components/src/lib/services/slot.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,77 @@ | ||
import { InjectionToken, Type } from '@angular/core' | ||
import { Observable } from 'rxjs' | ||
import { loadRemoteModule } from '@angular-architects/module-federation' | ||
import { Injectable, InjectionToken, Type } from '@angular/core' | ||
import { RemoteComponent, RemoteComponentsTopic } from '@onecx/integration-interface' | ||
import { Observable, map, shareReplay } from 'rxjs' | ||
import { PermissionService } from './permission.service' | ||
|
||
export const SLOT_SERVICE: InjectionToken<SlotService> = new InjectionToken('SLOT_SERVICE') | ||
|
||
export type RemoteComponentInfo = { appId: string; productName: string; baseUrl: string } | ||
|
||
export type SlotComponentConfiguration = { | ||
componentType: Promise<Type<unknown> | undefined> | Type<unknown> | undefined; | ||
remoteComponent: RemoteComponentInfo; | ||
permissions: Promise<string[]> | string[]; | ||
componentType: Promise<Type<unknown> | undefined> | Type<unknown> | undefined | ||
remoteComponent: RemoteComponentInfo | ||
permissions: Promise<string[]> | string[] | ||
} | ||
|
||
export interface SlotService { | ||
init(): Promise<void> | ||
getComponentsForSlot( | ||
slotName: string | ||
): Observable<SlotComponentConfiguration[]> | ||
getComponentsForSlot(slotName: string): Observable<SlotComponentConfiguration[]> | ||
isSomeComponentDefinedForSlot(slotName: string): Observable<boolean> | ||
} | ||
|
||
@Injectable({ providedIn: 'root' }) | ||
export class SlotService implements SlotService { | ||
remoteComponents$ = new RemoteComponentsTopic() | ||
|
||
constructor(private permissionsService: PermissionService) {} | ||
|
||
async init(): Promise<void> { | ||
return Promise.resolve() | ||
} | ||
|
||
getComponentsForSlot(slotName: string): Observable<SlotComponentConfiguration[]> { | ||
return this.remoteComponents$.pipe( | ||
map((remoteComponentsInfo) => | ||
(remoteComponentsInfo.slots?.find((slotMapping) => slotMapping.name === slotName)?.components ?? []) | ||
.map((remoteComponentName) => remoteComponentsInfo.components.find((rc) => rc.name === remoteComponentName)) | ||
.filter((remoteComponent): remoteComponent is RemoteComponent => !!remoteComponent) | ||
.map((remoteComponent) => remoteComponent) | ||
), | ||
map((infos) => | ||
infos.map((remoteComponent) => ({ | ||
componentType: this.loadComponent(remoteComponent), | ||
remoteComponent, | ||
permissions: this.permissionsService.getPermissions(remoteComponent.appId, remoteComponent.productName), | ||
})) | ||
), | ||
shareReplay() | ||
) | ||
} | ||
|
||
isSomeComponentDefinedForSlot(slotName: string): Observable<boolean> { | ||
return this.remoteComponents$.pipe( | ||
map((remoteComponentsInfo) => remoteComponentsInfo.slots.some((slotMapping) => slotMapping.name === slotName)) | ||
) | ||
} | ||
|
||
private async loadComponent(component: { | ||
remoteEntryUrl: string | ||
exposedModule: string | ||
}): Promise<Type<unknown> | undefined> { | ||
try { | ||
const exposedModule = component.exposedModule.startsWith('./') | ||
? component.exposedModule.slice(2) | ||
: component.exposedModule | ||
const m = await loadRemoteModule({ | ||
type: 'module', | ||
remoteEntry: component.remoteEntryUrl, | ||
exposedModule: './' + exposedModule, | ||
}) | ||
return m[exposedModule] | ||
} catch (e) { | ||
console.log('Failed to load remote module ', component.exposedModule, component.remoteEntryUrl, e) | ||
return undefined | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
libs/integration-interface/src/lib/topics/permissions-rpc/v1/permissions-rpc.model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface PermissionsRpc { | ||
appId: string | ||
productName: string | ||
permissions?: Array<string> | ||
} |
8 changes: 8 additions & 0 deletions
8
libs/integration-interface/src/lib/topics/permissions-rpc/v1/permissions-rpc.topic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Topic } from '@onecx/accelerator' | ||
import { PermissionsRpc } from './permissions-rpc.model' | ||
|
||
export class PermissionsRpcTopic extends Topic<PermissionsRpc> { | ||
constructor() { | ||
super('permissionsRpc', 1) | ||
} | ||
} |
10 changes: 5 additions & 5 deletions
10
libs/integration-interface/src/lib/topics/permissions/v1/permissions.topic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import { SyncableTopic } from "@onecx/accelerator"; | ||
import { SyncableTopic } from '@onecx/accelerator' | ||
|
||
export class PermissionsTopic extends SyncableTopic<string[]> { | ||
constructor() { | ||
super('permissions', 1) | ||
} | ||
} | ||
constructor() { | ||
super('permissions', 1) | ||
} | ||
} |
16 changes: 8 additions & 8 deletions
16
libs/integration-interface/src/lib/topics/remote-components/v1/remote-component.model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
export interface RemoteComponent { | ||
name: string; | ||
baseUrl: string; | ||
remoteEntryUrl: string; | ||
appId: string; | ||
productName: string; | ||
exposedModule: string; | ||
} | ||
export type RemoteComponent = { | ||
name: string | ||
baseUrl: string | ||
remoteEntryUrl: string | ||
appId: string | ||
productName: string | ||
exposedModule: string | ||
} |
4 changes: 4 additions & 0 deletions
4
...integration-interface/src/lib/topics/remote-components/v1/remote-components-info.model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { RemoteComponent } from './remote-component.model' | ||
import { Slot } from './slot.model' | ||
|
||
export type RemoteComponentsInfo = { components: RemoteComponent[]; slots: Slot[] } |
6 changes: 3 additions & 3 deletions
6
libs/integration-interface/src/lib/topics/remote-components/v1/remote-components.topic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import { Topic } from '@onecx/accelerator' | ||
import { RemoteComponent } from './remote-component.model' | ||
import { RemoteComponentsInfo } from './remote-components-info.model' | ||
|
||
export class RemoteComponentsTopic extends Topic<RemoteComponent[]> { | ||
export class RemoteComponentsTopic extends Topic<RemoteComponentsInfo> { | ||
constructor() { | ||
super('remoteComponents', 1) | ||
super('remoteComponentsInfo', 1) | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
libs/integration-interface/src/lib/topics/remote-components/v1/slot.model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export type Slot = { | ||
name: string | ||
components: Array<string> | ||
} |