chore(orchestration): remote joiner - relationships as map (#7752)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
|
InternalJoinerServiceConfig,
|
||||||
JoinerRelationship,
|
JoinerRelationship,
|
||||||
JoinerServiceConfig,
|
|
||||||
JoinerServiceConfigAlias,
|
JoinerServiceConfigAlias,
|
||||||
ModuleJoinerConfig,
|
ModuleJoinerConfig,
|
||||||
RemoteExpandProperty,
|
RemoteExpandProperty,
|
||||||
@@ -32,7 +32,8 @@ type InternalImplodeMapping = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RemoteJoiner {
|
export class RemoteJoiner {
|
||||||
private serviceConfigCache: Map<string, JoinerServiceConfig> = new Map()
|
private serviceConfigCache: Map<string, InternalJoinerServiceConfig> =
|
||||||
|
new Map()
|
||||||
|
|
||||||
private static filterFields(
|
private static filterFields(
|
||||||
data: any,
|
data: any,
|
||||||
@@ -146,73 +147,85 @@ export class RemoteJoiner {
|
|||||||
private buildReferences(serviceConfigs: ModuleJoinerConfig[]) {
|
private buildReferences(serviceConfigs: ModuleJoinerConfig[]) {
|
||||||
const expandedRelationships: Map<
|
const expandedRelationships: Map<
|
||||||
string,
|
string,
|
||||||
{ fieldAlias; relationships: JoinerRelationship[] }
|
{ fieldAlias; relationships: Map<string, JoinerRelationship> }
|
||||||
> = new Map()
|
> = new Map()
|
||||||
|
|
||||||
for (const service of serviceConfigs) {
|
for (const service of serviceConfigs) {
|
||||||
if (this.serviceConfigCache.has(service.serviceName!)) {
|
const service_ = service as Omit<ModuleJoinerConfig, "relationships"> & {
|
||||||
throw new Error(`Service "${service.serviceName}" is already defined.`)
|
relationships?: Map<string, JoinerRelationship>
|
||||||
}
|
}
|
||||||
|
|
||||||
service.fieldAlias ??= {}
|
if (this.serviceConfigCache.has(service_.serviceName!)) {
|
||||||
service.relationships ??= []
|
throw new Error(`Service "${service_.serviceName}" is already defined.`)
|
||||||
service.extends ??= []
|
}
|
||||||
|
|
||||||
|
service_.fieldAlias ??= {}
|
||||||
|
service_.extends ??= []
|
||||||
|
service_.relationships ??= new Map()
|
||||||
|
|
||||||
|
if (Array.isArray(service_.relationships)) {
|
||||||
|
const relationships = new Map()
|
||||||
|
for (const relationship of service_.relationships) {
|
||||||
|
relationships.set(relationship.alias, relationship)
|
||||||
|
}
|
||||||
|
service_.relationships = relationships
|
||||||
|
}
|
||||||
|
|
||||||
// add aliases
|
// add aliases
|
||||||
const isReadOnlyDefinition =
|
const isReadOnlyDefinition =
|
||||||
!isDefined(service.serviceName) || service.isReadOnlyLink
|
!isDefined(service_.serviceName) || service_.isReadOnlyLink
|
||||||
if (!isReadOnlyDefinition) {
|
if (!isReadOnlyDefinition) {
|
||||||
service.alias ??= []
|
service_.alias ??= []
|
||||||
|
|
||||||
if (!Array.isArray(service.alias)) {
|
if (!Array.isArray(service_.alias)) {
|
||||||
service.alias = [service.alias]
|
service_.alias = [service_.alias]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.autoCreateServiceNameAlias) {
|
if (this.options.autoCreateServiceNameAlias) {
|
||||||
service.alias.push({ name: service.serviceName! })
|
service_.alias.push({ name: service_.serviceName! })
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle alias.name as array
|
// handle alias.name as array
|
||||||
for (let idx = 0; idx < service.alias.length; idx++) {
|
for (let idx = 0; idx < service_.alias.length; idx++) {
|
||||||
const alias = service.alias[idx]
|
const alias = service_.alias[idx]
|
||||||
if (!Array.isArray(alias.name)) {
|
if (!Array.isArray(alias.name)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of alias.name) {
|
for (const name of alias.name) {
|
||||||
service.alias.push({
|
service_.alias.push({
|
||||||
name,
|
name,
|
||||||
args: alias.args,
|
args: alias.args,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
service.alias.splice(idx, 1)
|
service_.alias.splice(idx, 1)
|
||||||
idx--
|
idx--
|
||||||
}
|
}
|
||||||
|
|
||||||
// self-reference
|
// self-reference
|
||||||
for (const alias of service.alias) {
|
for (const alias of service_.alias) {
|
||||||
if (this.serviceConfigCache.has(`alias_${alias.name}}`)) {
|
if (this.serviceConfigCache.has(`alias_${alias.name}}`)) {
|
||||||
const defined = this.serviceConfigCache.get(`alias_${alias.name}}`)
|
const defined = this.serviceConfigCache.get(`alias_${alias.name}}`)
|
||||||
|
|
||||||
if (service.serviceName === defined?.serviceName) {
|
if (service_.serviceName === defined?.serviceName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot add alias "${alias.name}" for "${service.serviceName}". It is already defined for Service "${defined?.serviceName}".`
|
`Cannot add alias "${alias.name}" for "${service_.serviceName}". It is already defined for Service "${defined?.serviceName}".`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const args =
|
const args =
|
||||||
service.args || alias.args
|
service_.args || alias.args
|
||||||
? { ...service.args, ...alias.args }
|
? { ...service_.args, ...alias.args }
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
service.relationships?.push({
|
service_.relationships?.set(alias.name as string, {
|
||||||
alias: alias.name as string,
|
alias: alias.name as string,
|
||||||
foreignKey: alias.name + "_id",
|
foreignKey: alias.name + "_id",
|
||||||
primaryKey: "id",
|
primaryKey: "id",
|
||||||
serviceName: service.serviceName!,
|
serviceName: service_.serviceName!,
|
||||||
args,
|
args,
|
||||||
})
|
})
|
||||||
this.cacheServiceConfig(
|
this.cacheServiceConfig(
|
||||||
@@ -222,19 +235,22 @@ export class RemoteJoiner {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cacheServiceConfig(serviceConfigs, service.serviceName)
|
this.cacheServiceConfig(serviceConfigs, service_.serviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const extend of service.extends) {
|
for (const extend of service_.extends) {
|
||||||
if (!expandedRelationships.has(extend.serviceName)) {
|
if (!expandedRelationships.has(extend.serviceName)) {
|
||||||
expandedRelationships.set(extend.serviceName, {
|
expandedRelationships.set(extend.serviceName, {
|
||||||
fieldAlias: {},
|
fieldAlias: {},
|
||||||
relationships: [],
|
relationships: new Map(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const service_ = expandedRelationships.get(extend.serviceName)!
|
const service_ = expandedRelationships.get(extend.serviceName)!
|
||||||
service_.relationships.push(extend.relationship)
|
service_.relationships.set(
|
||||||
|
extend.relationship.alias,
|
||||||
|
extend.relationship
|
||||||
|
)
|
||||||
Object.assign(service_.fieldAlias ?? {}, extend.fieldAlias)
|
Object.assign(service_.fieldAlias ?? {}, extend.fieldAlias)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,21 +264,21 @@ export class RemoteJoiner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const service_ = this.serviceConfigCache.get(serviceName)!
|
const service_ = this.serviceConfigCache.get(serviceName)!
|
||||||
service_.relationships?.push(...relationships)
|
relationships.forEach((relationship, alias) => {
|
||||||
|
service_.relationships!.set(alias, relationship)
|
||||||
|
})
|
||||||
Object.assign(service_.fieldAlias!, fieldAlias ?? {})
|
Object.assign(service_.fieldAlias!, fieldAlias ?? {})
|
||||||
|
|
||||||
if (Object.keys(service_.fieldAlias!).length) {
|
if (Object.keys(service_.fieldAlias!).length) {
|
||||||
const conflictAliases = service_.relationships!.filter(
|
const conflictAliases = Array.from(
|
||||||
(relationship) => {
|
service_.relationships!.keys()
|
||||||
return fieldAlias[relationship.alias]
|
).filter((alias) => fieldAlias[alias])
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (conflictAliases.length) {
|
if (conflictAliases.length) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Conflict configuration for service "${serviceName}". The following aliases are already defined as relationships: ${conflictAliases
|
`Conflict configuration for service "${serviceName}". The following aliases are already defined as relationships: ${conflictAliases.join(
|
||||||
.map((relationship) => relationship.alias)
|
", "
|
||||||
.join(", ")}`
|
)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,7 +290,7 @@ export class RemoteJoiner {
|
|||||||
private getServiceConfig(
|
private getServiceConfig(
|
||||||
serviceName?: string,
|
serviceName?: string,
|
||||||
serviceAlias?: string
|
serviceAlias?: string
|
||||||
): JoinerServiceConfig | undefined {
|
): InternalJoinerServiceConfig | undefined {
|
||||||
if (serviceAlias) {
|
if (serviceAlias) {
|
||||||
const name = `alias_${serviceAlias}`
|
const name = `alias_${serviceAlias}`
|
||||||
return this.serviceConfigCache.get(name)
|
return this.serviceConfigCache.get(name)
|
||||||
@@ -546,7 +562,7 @@ export class RemoteJoiner {
|
|||||||
|
|
||||||
private async expandProperty(
|
private async expandProperty(
|
||||||
items: any[],
|
items: any[],
|
||||||
parentServiceConfig: JoinerServiceConfig,
|
parentServiceConfig: InternalJoinerServiceConfig,
|
||||||
expand?: RemoteExpandProperty,
|
expand?: RemoteExpandProperty,
|
||||||
options?: RemoteJoinerOptions
|
options?: RemoteJoinerOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@@ -554,8 +570,8 @@ export class RemoteJoiner {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const relationship = parentServiceConfig?.relationships?.find(
|
const relationship = parentServiceConfig?.relationships?.get(
|
||||||
(relation) => relation.alias === expand.property
|
expand.property
|
||||||
)
|
)
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship) {
|
||||||
@@ -657,7 +673,7 @@ export class RemoteJoiner {
|
|||||||
private parseExpands(
|
private parseExpands(
|
||||||
initialService: RemoteExpandProperty,
|
initialService: RemoteExpandProperty,
|
||||||
query: RemoteJoinerQuery,
|
query: RemoteJoinerQuery,
|
||||||
serviceConfig: JoinerServiceConfig,
|
serviceConfig: InternalJoinerServiceConfig,
|
||||||
expands: RemoteJoinerQuery["expands"],
|
expands: RemoteJoinerQuery["expands"],
|
||||||
implodeMapping: InternalImplodeMapping[],
|
implodeMapping: InternalImplodeMapping[],
|
||||||
options?: RemoteJoinerOptions
|
options?: RemoteJoinerOptions
|
||||||
@@ -679,7 +695,7 @@ export class RemoteJoiner {
|
|||||||
private parseProperties(
|
private parseProperties(
|
||||||
initialService: RemoteExpandProperty,
|
initialService: RemoteExpandProperty,
|
||||||
query: RemoteJoinerQuery,
|
query: RemoteJoinerQuery,
|
||||||
serviceConfig: JoinerServiceConfig,
|
serviceConfig: InternalJoinerServiceConfig,
|
||||||
expands: RemoteJoinerQuery["expands"],
|
expands: RemoteJoinerQuery["expands"],
|
||||||
implodeMapping: InternalImplodeMapping[],
|
implodeMapping: InternalImplodeMapping[],
|
||||||
options?: RemoteJoinerOptions
|
options?: RemoteJoinerOptions
|
||||||
@@ -725,9 +741,7 @@ export class RemoteJoiner {
|
|||||||
const fullPath = [BASE_PATH, ...currentPath, prop].join(".")
|
const fullPath = [BASE_PATH, ...currentPath, prop].join(".")
|
||||||
const fullAliasPath = [BASE_PATH, ...currentAliasPath, prop].join(".")
|
const fullAliasPath = [BASE_PATH, ...currentAliasPath, prop].join(".")
|
||||||
|
|
||||||
const relationship = currentServiceConfig.relationships?.find(
|
const relationship = currentServiceConfig.relationships?.get(prop)
|
||||||
(relation) => relation.alias === prop
|
|
||||||
)
|
|
||||||
|
|
||||||
const isCurrentProp =
|
const isCurrentProp =
|
||||||
fullPath === BASE_PATH + "." + expand.property ||
|
fullPath === BASE_PATH + "." + expand.property ||
|
||||||
@@ -862,9 +876,7 @@ export class RemoteJoiner {
|
|||||||
path: fullPath,
|
path: fullPath,
|
||||||
isList:
|
isList:
|
||||||
fieldAliasIsList ||
|
fieldAliasIsList ||
|
||||||
!!serviceConfig.relationships?.find(
|
!!serviceConfig.relationships?.get(parentFieldAlias)?.isList,
|
||||||
(relationship) => relationship.alias === parentFieldAlias
|
|
||||||
)?.isList,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const extMapping = expands as unknown[]
|
const extMapping = expands as unknown[]
|
||||||
@@ -895,9 +907,7 @@ export class RemoteJoiner {
|
|||||||
|
|
||||||
const partialPath: string[] = []
|
const partialPath: string[] = []
|
||||||
for (const partial of path.split(".")) {
|
for (const partial of path.split(".")) {
|
||||||
const relationship = currentServiceConfig.relationships?.find(
|
const relationship = currentServiceConfig.relationships?.get(partial)
|
||||||
(relation) => relation.alias === partial
|
|
||||||
)
|
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship) {
|
||||||
currentServiceConfig = this.getServiceConfig(relationship.serviceName)!
|
currentServiceConfig = this.getServiceConfig(relationship.serviceName)!
|
||||||
|
|||||||
@@ -91,11 +91,18 @@ export interface RemoteNestedExpands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type InternalJoinerServiceConfig = Omit<
|
||||||
|
JoinerServiceConfig,
|
||||||
|
"relationships"
|
||||||
|
> & {
|
||||||
|
relationships?: Map<string, JoinerRelationship>
|
||||||
|
}
|
||||||
|
|
||||||
export interface RemoteExpandProperty {
|
export interface RemoteExpandProperty {
|
||||||
property: string
|
property: string
|
||||||
parent: string
|
parent: string
|
||||||
parentConfig?: JoinerServiceConfig
|
parentConfig?: InternalJoinerServiceConfig
|
||||||
serviceConfig: JoinerServiceConfig
|
serviceConfig: InternalJoinerServiceConfig
|
||||||
fields?: string[]
|
fields?: string[]
|
||||||
args?: JoinerArgument[]
|
args?: JoinerArgument[]
|
||||||
expands?: RemoteNestedExpands
|
expands?: RemoteNestedExpands
|
||||||
|
|||||||
Reference in New Issue
Block a user