// 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 { ChildrenBuilder } from './ChildrenBuilder.js'; import { notSetPropertyPath } from '../notSetPropertyPath.js'; /** * Concrete implementation of {@link INestedBuilder}, building the `ChildrenDefinition` for a * nested single-object sub-projection reached through `.nested()`. * @template TParentReadModel - The parent read model type. * @template TNestedReadModel - The nested object read model type. */ export class NestedBuilder extends ProjectionBuilderCore> implements INestedBuilder { /** @inheritdoc */ clearWith(eventType: Function): INestedBuilder { const contractType = this.toContractEventType(eventType); this._removedWith.push({ Key: contractType, Value: { Key: '$eventSourceId', ParentKey: '' } }); return this; } /** @inheritdoc */ children( targetPropertyAccessor: PropertyAccessor, builderCallback: (builder: IChildrenBuilder) => void ): INestedBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); targetPropertyAccessor(proxy as TNestedReadModel); const builder = new ChildrenBuilder(); builderCallback(builder); this._children[handler.property] = builder.buildDefinition(); return this; } /** @inheritdoc */ nested( targetPropertyAccessor: PropertyAccessor, builderCallback: (builder: INestedBuilder) => void ): INestedBuilder { const handler = new PropertyPathResolverProxyHandler(); const proxy = new Proxy({}, handler); targetPropertyAccessor(proxy as TNestedReadModel); const builder = new NestedBuilder(); builderCallback(builder); this._nested[handler.property] = builder.buildDefinition(); return this; } /** * Builds the {@link ChildrenDefinitionLike} representing this nested object. * @returns The accumulated nested definition. */ buildDefinition(): ChildrenDefinitionLike { this.resolveJoins(); return { IdentifiedBy: notSetPropertyPath, From: this._from, Join: this._join, Children: this._children, All: this._all, RemovedWith: this._removedWith, RemovedWithJoin: this._removedWithJoin, AutoMap: this._autoMap, Nested: this._nested }; } }