/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/schema/src/event.ts
125 строк
4 KB
Kit Langton
feat(api): add finite durable session history pages (#34097)
26 июн 2026, 21:49
Не верифицирован
26 июн 2026, 21:49
65210f2
Код
Авторство
О чём код?
export * as Event from "./event" import { Schema } from "effect" import { optional } from "./schema" import { ascending } from "./identifier" import { Location } from "./location" import { statics } from "./schema" export const ID = Schema.String.check(Schema.isStartsWith("evt_")).pipe( Schema.brand("Event.ID"), statics((schema) => ({ create: () => schema.make("evt_" + ascending()) })), ) export type ID = typeof ID.Type export type Definition< Type extends string = string, DataSchema extends Schema.Codec<unknown, unknown> = Schema.Codec<unknown, unknown>, > = Schema.Top & { readonly type: Type readonly durable?: { readonly version: number readonly aggregate: string } readonly data: DataSchema } export type Data<D extends Definition> = Schema.Schema.Type<D["data"]> export type Payload<D extends Definition = Definition> = { readonly id: ID readonly type: D["type"] readonly data: Data<D> readonly durable?: { readonly aggregateID: string readonly seq: number readonly version: number } readonly location?: Location.Ref readonly metadata?: Record<string, unknown> } export function define< const Type extends string, const Fields extends Readonly<Record<PropertyKey, Schema.Codec<unknown, unknown>>>, >(input: { readonly type: Type readonly durable?: { readonly version: number readonly aggregate: string } readonly schema: Fields }) { const data = Schema.Struct(input.schema) return Schema.Struct({ id: ID, metadata: optional(Schema.Record(Schema.String, Schema.Unknown)), type: Schema.Literal(input.type), durable: optional(Schema.Struct({ aggregateID: Schema.String, seq: Schema.Int, version: Schema.Int })), location: optional(Location.Ref), data, }) .annotate({ identifier: input.type }) .pipe( statics(() => ({ type: input.type, ...(input.durable === undefined ? {} : { durable: input.durable }), data, })), ) satisfies Definition<Type, typeof data> } export function inventory<const Definitions extends ReadonlyArray<Definition>>(...definitions: Definitions) { return Object.freeze(definitions) } export function latest(definitions: ReadonlyArray<Definition>) { return readonlyMap( definitions.reduce((result, definition) => { const existing = result.get(definition.type) if (!existing) { result.set(definition.type, definition) return result } if (definition.durable && existing.durable && definition.durable.version !== existing.durable.version) { if (definition.durable.version > existing.durable.version) result.set(definition.type, definition) return result } if (definition !== existing) throw new Error(`Duplicate latest event definition for ${definition.type}`) return result }, new Map<string, Definition>()), ) } export function versionedType(type: string, version: number) { return `${type}.${version}` } export function durable<const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) { return readonlyMap( definitions.reduce((result, definition) => { if (!definition.durable) return result const key = versionedType(definition.type, definition.durable.version) if (result.has(key)) throw new Error(`Duplicate durable event definition for ${key}`) result.set(key, definition) return result }, new Map<string, Definitions[number]>()), ) } function readonlyMap<Key, Value>(map: Map<Key, Value>): ReadonlyMap<Key, Value> { const result: ReadonlyMap<Key, Value> = Object.freeze({ get size() { return map.size }, entries: () => map.entries(), forEach: (callback: (value: Value, key: Key, map: ReadonlyMap<Key, Value>) => void, thisArg?: unknown) => map.forEach((value, key) => callback.call(thisArg, value, key, result)), get: (key: Key) => map.get(key), has: (key: Key) => map.has(key), keys: () => map.keys(), values: () => map.values(), [Symbol.iterator]: () => map[Symbol.iterator](), }) return result }