Rename to Factory

This commit is contained in:
Matt Gibson 2024-05-20 17:31:33 -04:00
parent 09a32ee355
commit 9069384203
No known key found for this signature in database
GPG Key ID: 963EE038B0581878
3 changed files with 21 additions and 25 deletions

View File

@ -4,7 +4,7 @@ import { ExecutionContextBuilder } from "./execution-context.builder";
describe("ExecutionContextBuilder", () => {
describe("with", () => {
it("builds the context with the value returned by the predicate when the value is not a promise or observable", async () => {
it("builds the context with the value returned by the factory when the value is not a promise or observable", async () => {
const context = await new ExecutionContextBuilder()
.with(() => 42)
.as("value")
@ -13,7 +13,7 @@ describe("ExecutionContextBuilder", () => {
expect(context).toEqual({ value: 42 });
});
it("builds the context with the value resolved by the promise returned by the predicate", async () => {
it("builds the context with the value resolved by the promise returned by the factory", async () => {
const context = await new ExecutionContextBuilder()
.with(() => Promise.resolve(42))
.as("value")
@ -22,7 +22,7 @@ describe("ExecutionContextBuilder", () => {
expect(context).toEqual({ value: 42 });
});
it("builds the context with the value resolved by the observable returned by the predicate", async () => {
it("builds the context with the value resolved by the observable returned by the factory", async () => {
const context = await new ExecutionContextBuilder()
.with(() => of(42))
.as("value")
@ -33,7 +33,7 @@ describe("ExecutionContextBuilder", () => {
});
describe("multiple with", () => {
it("builds the context with all the values returned by the predicates", async () => {
it("builds the context with all the values returned by the factories", async () => {
const context = await new ExecutionContextBuilder()
.with(() => 42)
.as("value")
@ -44,7 +44,7 @@ describe("ExecutionContextBuilder", () => {
expect(context).toEqual({ value: 42, string: "foo" });
});
it("provides the current context to the predicate", async () => {
it("provides the current context to the factory", async () => {
const context = await new ExecutionContextBuilder()
.withValue(42)
.as("first")

View File

@ -9,25 +9,24 @@ export class ExecutionContextPropertyBuilder<
> {
constructor(
private readonly executionContextBuilder: TExecutionContextBuilder,
private readonly predicate: ExecutionContextPredicate<TExecutionContext, TValue>,
private readonly factory: ExecutionContextFactory<TExecutionContext, TValue>,
) {}
as<const TKey extends string>(
propertyName: TKey,
): ExecutionContextBuilder<TExecutionContext & Record<TKey, TValue>> {
return this.executionContextBuilder.addPropertyBuilder(propertyName, this.predicate);
return this.executionContextBuilder.addPropertyBuilder(propertyName, this.factory);
}
}
type ExecutionContextPredicate<TContext, T> = (context: TContext) => T | Promise<T> | Observable<T>;
type ExecutionContextFactory<TContext, T> = (context: TContext) => T | Promise<T> | Observable<T>;
export class ExecutionContextBuilder<T extends GenericExecutionContext> {
// The type of these predicates are the context that is built by the time they are called and the value they return,
// The type of these factories are the context that is built by the time they are called and the value they return,
// which is protected by the `with` method and `as` method on ExecutionContextPropertyBuilder.
protected contextMap: { name: string; predicate: ExecutionContextPredicate<unknown, unknown> }[] =
[];
protected contextMap: { name: string; factory: ExecutionContextFactory<unknown, unknown> }[] = [];
with<TValue>(
contextBuilder: ExecutionContextPredicate<T, TValue>,
contextBuilder: ExecutionContextFactory<T, TValue>,
): ExecutionContextPropertyBuilder<T, typeof this, TValue> {
return new ExecutionContextPropertyBuilder(this, contextBuilder);
}
@ -46,13 +45,13 @@ export class ExecutionContextBuilder<T extends GenericExecutionContext> {
async build(): Promise<T> {
const context: Record<string, unknown> = {};
for (const { name, predicate } of this.contextMap) {
let predicateResult = predicate(context);
if (isObservable(predicateResult)) {
predicateResult = firstValueFrom(predicateResult);
for (const { name, factory } of this.contextMap) {
let factoryResult = factory(context);
if (isObservable(factoryResult)) {
factoryResult = firstValueFrom(factoryResult);
}
context[name] = await predicateResult;
context[name] = await factoryResult;
}
return context as T;
}
@ -61,19 +60,16 @@ export class ExecutionContextBuilder<T extends GenericExecutionContext> {
* @internal This method is part of the builder pattern and is not intended for external use.
*
* @param propertyName The name of the new context property
* @param predicate The predicate that will be used to build the new context property
* @param factory The factory that will be used to build the new context property
* @returns A new ExecutionContextBuilder with the new context property added
*/
addPropertyBuilder<
TKey extends string,
TValue,
TValuePredicate extends ExecutionContextPredicate<T, TValue>,
>(
propertyName: TKey,
predicate: TValuePredicate,
): ExecutionContextBuilder<T & Record<TKey, TValue>> {
TValueFactory extends ExecutionContextFactory<T, TValue>,
>(propertyName: TKey, factory: TValueFactory): ExecutionContextBuilder<T & Record<TKey, TValue>> {
const result = new ExecutionContextBuilder<T & Record<TKey, TValue>>();
result.contextMap = this.contextMap.concat({ name: propertyName, predicate });
result.contextMap = this.contextMap.concat({ name: propertyName, factory });
return result;
}
}

View File

@ -13,7 +13,7 @@ export class UserExecutionContextBuilder extends ExecutionContextBuilder<{
this.contextMap.push({
name: "userId",
predicate: () => this.accountService.activeAccount$.pipe(map((a) => a?.id)),
factory: () => this.accountService.activeAccount$.pipe(map((a) => a?.id)),
});
}
}