chore(orchestration): remote joiner - relationships as map (#7752)

This commit is contained in:
Carlos R. L. Rodrigues
2024-06-17 16:11:42 -03:00
committed by GitHub
parent 12a57836a7
commit d6c6f5998c
2 changed files with 71 additions and 54 deletions
@@ -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)!
+9 -2
View File
@@ -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