// Copyright (c) Cratis. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. import { PropertyAccessor, PropertyPathResolverProxyHandler } from '@cratis/fundamentals'; import { ChildrenDefinitionLike, ProjectionBuilderCore } from './ProjectionBuilderCore.js'; import { IChildrenBuilder } from './IChildrenBuilder.js'; import { INestedBuilder } from './INestedBuilder.js'; import { NestedBuilder } from './NestedBuilder.js'; /** * Concrete implementation of {@link IChildrenBuilder}, building the `ChildrenDefinition` for a * children collection sub-projection reached through `.children()`. * @template TParentReadModel - The parent read model type. * @template TChildReadModel - The child read model type. */ export class ChildrenBuilder extends ProjectionBuilderCore> implements IChildrenBuilder { private _identifiedBy: string | undefined; private _fromEventPropertyPath: string | undefined; /** @inheritdoc */ identifiedBy(propertyAccessor: PropertyAccessor): IChildrenBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); propertyAccessor(proxy as TChildReadModel); this._identifiedBy = handler.property; return this; } /** @inheritdoc */ fromEventProperty(propertyAccessor: PropertyAccessor): IChildrenBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); propertyAccessor(proxy as TEvent); this._fromEventPropertyPath = handler.property; return this; } /** @inheritdoc */ children( targetPropertyAccessor: PropertyAccessor, builderCallback: (builder: IChildrenBuilder) => void ): IChildrenBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); targetPropertyAccessor(proxy as TChildReadModel); const builder = new ChildrenBuilder(); builderCallback(builder); this._children[handler.property] = builder.buildDefinition(); return this; } /** @inheritdoc */ nested( targetPropertyAccessor: PropertyAccessor, builderCallback: (builder: INestedBuilder) => void ): IChildrenBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); targetPropertyAccessor(proxy as TChildReadModel); const builder = new NestedBuilder(); builderCallback(builder); this._nested[handler.property] = builder.buildDefinition(); return this; } /** @inheritdoc */ protected defaultJoinOn(): string | undefined { return this._identifiedBy; } /** * Builds the {@link ChildrenDefinitionLike} representing this children collection. * @returns The accumulated children definition. */ buildDefinition(): ChildrenDefinitionLike { this.resolveJoins(); return { IdentifiedBy: this._identifiedBy ?? '$eventSourceId', From: this._from, Join: this._join, Children: this._children, All: this._all, FromEventProperty: this._fromEventPropertyPath === undefined ? undefined : { Event: undefined, PropertyExpression: this._fromEventPropertyPath }, RemovedWith: this._removedWith, RemovedWithJoin: this._removedWithJoin, AutoMap: this._autoMap, Nested: this._nested }; } }