feat: add peerDependencies

This commit is contained in:
2025-07-07 13:11:16 +02:00
parent 2093dd7097
commit dd1570d52e
36 changed files with 481 additions and 274 deletions

View File

@@ -75,7 +75,9 @@ export class HLCForwardJumpError extends Error {
readonly timejump: number,
readonly tolerance: number,
) {
super(`HLC Violation: Detected a forward time jump of ${timejump}ms, which exceed the allowed tolerance of ${tolerance}ms.`);
super(
`HLC Violation: Detected a forward time jump of ${timejump}ms, which exceed the allowed tolerance of ${tolerance}ms.`,
);
}
}
@@ -96,7 +98,9 @@ export class HLCClockOffsetError extends Error {
readonly offset: number,
readonly maxOffset: number,
) {
super(`HLC Violation: Received time is ${offset}ms ahead of the wall time, exceeding the 'maxOffset' limit of ${maxOffset}ms.`);
super(
`HLC Violation: Received time is ${offset}ms ahead of the wall time, exceeding the 'maxOffset' limit of ${maxOffset}ms.`,
);
}
}

View File

@@ -47,7 +47,9 @@ export class EventFactory<const TEvents extends Event[] = Event[]> {
*
* @param type - Event type to retrieve.
*/
get<TType extends TEvents[number]["state"]["type"]>(type: TType): Extract<TEvents[number], { state: { type: TType } }> {
get<TType extends TEvents[number]["state"]["type"]>(
type: TType,
): Extract<TEvents[number], { state: { type: TType } }> {
return this.#index.get(type) as Extract<TEvents[number], { state: { type: TType } }>;
}
}

View File

@@ -118,7 +118,9 @@ export class EventStore<
*
* @param name - Aggregate name to retrieve.
*/
aggregate<TName extends TAggregateFactory["$aggregates"][number]["name"]>(name: TName): Extract<TAggregateFactory["$aggregates"][number], { name: TName }> {
aggregate<TName extends TAggregateFactory["$aggregates"][number]["name"]>(
name: TName,
): Extract<TAggregateFactory["$aggregates"][number], { name: TName }> {
return this.#aggregates.get(name) as Extract<TAggregateFactory["$aggregates"][number], { name: TName }>;
}
@@ -128,7 +130,10 @@ export class EventStore<
* @param aggregate - Aggregate to push events from.
* @param settings - Event settings which can modify insertion behavior.
*/
async pushAggregate(aggregate: InstanceType<TAggregateFactory["$aggregates"][number]>, settings?: EventsInsertSettings): Promise<void> {
async pushAggregate(
aggregate: InstanceType<TAggregateFactory["$aggregates"][number]>,
settings?: EventsInsertSettings,
): Promise<void> {
await aggregate.save(settings);
}
@@ -144,7 +149,10 @@ export class EventStore<
* @param aggregates - Aggregates to push events from.
* @param settings - Event settings which can modify insertion behavior.
*/
async pushManyAggregates(aggregates: InstanceType<TAggregateFactory["$aggregates"][number]>[], settings?: EventsInsertSettings): Promise<void> {
async pushManyAggregates(
aggregates: InstanceType<TAggregateFactory["$aggregates"][number]>[],
settings?: EventsInsertSettings,
): Promise<void> {
const events: this["$events"][number]["$record"][] = [];
for (const aggregate of aggregates) {
events.push(...aggregate.toPending());
@@ -209,7 +217,10 @@ export class EventStore<
* @param records - List of event records to insert.
* @param settings - Event settings which can modify insertion behavior.
*/
async pushManyEvents(records: this["$events"][number]["$record"][], settings: EventsInsertSettings = {}): Promise<void> {
async pushManyEvents(
records: this["$events"][number]["$record"][],
settings: EventsInsertSettings = {},
): Promise<void> {
const events: this["$events"][number]["$record"][] = [];
for (const record of records) {
const event = this.#events.get(record.type);
@@ -270,7 +281,10 @@ export class EventStore<
* @param streams - Streams to retrieve events for.
* @param options - Read options to pass to the provider. (Optional)
*/
async getEventsByStreams(streams: string[], options?: EventReadOptions): Promise<TEventFactory["$events"][number]["$record"][]> {
async getEventsByStreams(
streams: string[],
options?: EventReadOptions,
): Promise<TEventFactory["$events"][number]["$record"][]> {
return this.events.getByStreams(streams, options);
}
@@ -280,7 +294,10 @@ export class EventStore<
* @param keys - Relational keys to retrieve events for.
* @param options - Relational logic options. (Optional)
*/
async getEventsByRelations(keys: string[], options?: EventReadOptions): Promise<TEventFactory["$events"][number]["$record"][]> {
async getEventsByRelations(
keys: string[],
options?: EventReadOptions,
): Promise<TEventFactory["$events"][number]["$record"][]> {
const streamIds = await this.relations.getByKeys(keys);
if (streamIds.length === 0) {
return [];
@@ -317,7 +334,10 @@ export class EventStore<
* const state = await eventStore.reduce({ name: "foo:reducer", stream: "stream-id", reducer });
* ```
*/
makeReducer<TState extends Unknown>(foldFn: ReducerLeftFold<TState, TEventFactory>, stateFn: ReducerState<TState>): Reducer<TEventFactory, TState> {
makeReducer<TState extends Unknown>(
foldFn: ReducerLeftFold<TState, TEventFactory>,
stateFn: ReducerState<TState>,
): Reducer<TEventFactory, TState> {
return makeReducer<TEventFactory, TState>(foldFn, stateFn);
}
@@ -352,7 +372,9 @@ export class EventStore<
* });
* ```
*/
makeAggregateReducer<TAggregateRoot extends typeof AggregateRoot<TEventFactory>>(aggregate: TAggregateRoot): Reducer<TEventFactory, InstanceType<TAggregateRoot>> {
makeAggregateReducer<TAggregateRoot extends typeof AggregateRoot<TEventFactory>>(
aggregate: TAggregateRoot,
): Reducer<TEventFactory, InstanceType<TAggregateRoot>> {
return makeAggregateReducer<TEventFactory, TAggregateRoot>(aggregate);
}
@@ -392,7 +414,9 @@ export class EventStore<
}
const events = (
stream !== undefined ? await this.getEventsByStreams([id], { ...query, cursor }) : await this.getEventsByRelations([id], { ...query, cursor })
stream !== undefined
? await this.getEventsByStreams([id], { ...query, cursor })
: await this.getEventsByRelations([id], { ...query, cursor })
).concat(pending);
if (events.length === 0) {
@@ -430,9 +454,16 @@ export class EventStore<
* await eventStore.createSnapshot({ relation: `foo:${foo}:bars`, reducer });
* ```
*/
async createSnapshot<TReducer extends Reducer>({ name, stream, relation, reducer, ...query }: ReduceQuery<TReducer>): Promise<void> {
async createSnapshot<TReducer extends Reducer>({
name,
stream,
relation,
reducer,
...query
}: ReduceQuery<TReducer>): Promise<void> {
const id = stream ?? relation;
const events = stream !== undefined ? await this.getEventsByStreams([id], query) : await this.getEventsByRelations([id], query);
const events =
stream !== undefined ? await this.getEventsByStreams([id], query) : await this.getEventsByRelations([id], query);
if (events.length === 0) {
return undefined;
}
@@ -543,7 +574,10 @@ export type EventStoreHooks<TEventFactory extends EventFactory> = Partial<{
* @param records - List of event records inserted.
* @param settings - Event insert settings used.
*/
onEventsInserted(records: TEventFactory["$events"][number]["$record"][], settings: EventsInsertSettings): Promise<void>;
onEventsInserted(
records: TEventFactory["$events"][number]["$record"][],
settings: EventsInsertSettings,
): Promise<void>;
/**
* Triggered when an unhandled exception is thrown during `.pushEvent` and

View File

@@ -1,4 +1,4 @@
import z, { ZodType } from "zod";
import z, { ZodType } from "zod/v4";
import { EventValidationError } from "./errors.ts";
import { makeId } from "./nanoid.ts";

View File

@@ -12,9 +12,13 @@ export class HLC {
last: Timestamp;
constructor(
{ time = getTime, maxOffset = 0, timeUpperBound = 0, toleratedForwardClockJump = 0, last }: Options = {},
) {
constructor({
time = getTime,
maxOffset = 0,
timeUpperBound = 0,
toleratedForwardClockJump = 0,
last,
}: Options = {}) {
this.time = time;
this.maxTime = timeUpperBound > 0 ? timeUpperBound : Number.MAX_SAFE_INTEGER;
this.maxOffset = maxOffset;

View File

@@ -132,7 +132,10 @@ export class Projector<TEventFactory extends EventFactory = EventFactory> {
*/
once<
TType extends TEventFactory["$events"][number]["$record"]["type"],
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<TEventFactory["$events"][number]["$record"], { type: TType }>,
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<
TEventFactory["$events"][number]["$record"],
{ type: TType }
>,
TSuccessData extends Record<string, any> | void = void,
>(
type: TType,
@@ -175,7 +178,10 @@ export class Projector<TEventFactory extends EventFactory = EventFactory> {
*/
on<
TType extends TEventFactory["$events"][number]["$record"]["type"],
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<TEventFactory["$events"][number]["$record"], { type: TType }>,
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<
TEventFactory["$events"][number]["$record"],
{ type: TType }
>,
>(type: TType, handler: ProjectionHandler<TRecord>): Subscription {
return this.#subscribe(type, FILTER_CONTINUOUS, handler as any);
}
@@ -194,7 +200,10 @@ export class Projector<TEventFactory extends EventFactory = EventFactory> {
*/
all<
TType extends TEventFactory["$events"][number]["$record"]["type"],
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<TEventFactory["$events"][number]["$record"], { type: TType }>,
TRecord extends TEventFactory["$events"][number]["$record"] = Extract<
TEventFactory["$events"][number]["$record"],
{ type: TType }
>,
>(type: TType, handler: ProjectionHandler<TRecord>): Subscription {
return this.#subscribe(type, FILTER_ALL, handler as any);
}

View File

@@ -8,9 +8,10 @@ import { EventFactory } from "./event-factory.ts";
*
* @param aggregate - Aggregate to instantiate and create an instance of.
*/
export function makeAggregateReducer<TEventFactory extends EventFactory, TAggregateRoot extends typeof AggregateRoot<TEventFactory>>(
aggregate: TAggregateRoot,
): Reducer<TEventFactory, InstanceType<TAggregateRoot>> {
export function makeAggregateReducer<
TEventFactory extends EventFactory,
TAggregateRoot extends typeof AggregateRoot<TEventFactory>,
>(aggregate: TAggregateRoot): Reducer<TEventFactory, InstanceType<TAggregateRoot>> {
return {
from(snapshot: Unknown) {
return aggregate.from(snapshot);
@@ -45,7 +46,10 @@ export function makeReducer<TEventFactory extends EventFactory, TState extends U
};
}
export type Reducer<TEventFactory extends EventFactory = EventFactory, TState extends Record<string, unknown> | AggregateRoot<TEventFactory> = any> = {
export type Reducer<
TEventFactory extends EventFactory = EventFactory,
TState extends Record<string, unknown> | AggregateRoot<TEventFactory> = any,
> = {
/**
* Return result directly from a snapshot that does not have any subsequent
* events to fold onto a state.
@@ -80,10 +84,10 @@ export type Reducer<TEventFactory extends EventFactory = EventFactory, TState ex
* })
* ```
*/
export type ReducerLeftFold<TState extends Record<string, unknown> = any, TEventFactory extends EventFactory = EventFactory> = (
state: TState,
event: TEventFactory["$events"][number]["$record"],
) => TState;
export type ReducerLeftFold<
TState extends Record<string, unknown> = any,
TEventFactory extends EventFactory = EventFactory,
> = (state: TState, event: TEventFactory["$events"][number]["$record"]) => TState;
export type ReducerState<TState extends Unknown> = () => TState;

View File

@@ -1,4 +1,4 @@
import { ZodError } from "zod";
import { ZodError } from "zod/v4";
export function toPrettyErrorLines(error: ZodError, padding: number = 0): string[] {
const lines: string[] = [];