import { type Result } from '@conduit-client/utils'; import type { NamedPubSubService } from '@conduit-client/service-pubsub/v1'; import type { InstrumentationAttributes, NamedInstrumentationService } from '@conduit-client/service-instrumentation/v1'; import type { NamedCacheControllerService } from '@conduit-client/service-cache-control/v1'; import type { Key, CanonicalCacheControlMetadata, ReadonlyCache, CacheEntry, Cache } from '@conduit-client/service-cache/v1'; export interface NormalizedLink { type: 'link'; linkedKey: Key; } type UnknownError = { type: 'unknown'; error: Error; }; /** * An error that occurs when a type tries to read from the cache, and the cache metadata does * not match the current type */ type IncorrectTypeError = { type: 'incorrectType'; expectedType: string; actualType: string; }; /** * An error that occurs when a type tries to read from the cache and data is missing */ type MissingDataError = { type: 'missingData'; namespace: string; typeName: string; data: unknown; }; /** * A union of errors that can be returned during the write process */ export type WriteErrors = Array; /** * A union of errors that can be returned during the read process */ export type ReadErrors = Array; export type ReadResult = Result; export type WriteResult = Result; /** * A Type defines a collection of functions associated with a particular * data type. Types are not normalized but may contain normalized data. * * @typeParam Data TypeScript type that corresponds to the data * @typeParam NormalizedData TypeScript type that corresponds to the normalized data * @typeParam NormalizeInputData TypeScript type that corresponds to the data that the normalize method expects as input. Defaults to the same as Data */ export type TypeRepository = { readonly namespace: string; readonly typeName: string; equals(x: Data, y: Data): boolean; /** * Normalizes data for storage. */ write(cache: Cache, input: WriteInput): WriteResult; /** * De-normalizes a Type's data. A type could normalize into a Link, or return Data to the caller. * A caller must not be relying on the referenced type being normalized or not. * If denormalization fails, it will return undefined. */ read(cache: ReadonlyCache, input: ReadInput): ReadResult; }; /** * An InvalidatableType defines an invalidate function that takes a generic input, * and returns a promise that resolves when the invalidation is complete * * @typeParam T is another type to extend * @typeParam InvalidateInput is the input to run an invalidation */ export type Invalidatable, InvalidateInput> = T & { /** * * @param configs Partial KeyConfigs for this Type (partial KeyConfig treats missing parts as wildcard) */ invalidate(configs: InvalidateInput[]): Promise; }; /** * A QueryableType defines a collection of functions associated with a particular * data type that gets its own cache entry. * * @typeParam Data TypeScript type that corresponds to the data * @typeParam KeyConfig TypeScript type for the inputs needed to construct * a Key for the data * @typeParam NormalizeInputData TypeScript type that corresponds to the data that the normalize method expects as input. Defaults to the same as Data */ export type Queryable, QueryInput> = T & { /** * * @param cache The cache to run the query against * @param query The query to run */ query(cache: Cache, query: QueryInput): ReadResult>; }; export type DataOf> = T extends TypeRepository ? Data : never; export type ReadInputOf> = T extends TypeRepository ? ReadInput : never; export type WriteResponseOf> = T extends TypeRepository ? WriteResponse : never; export type WriteResultOf> = WriteResult>; export type WriteInputOf> = T extends TypeRepository ? WriteInput : never; export type InvalidateInputOf> = T extends Invalidatable, infer InvalidateInput> ? InvalidateInput : never; /** * A utility method for ensuring that a given entry in the cache matches a type based on namespace and name information * @param cacheEntry the cache entry to validate against * @param type the type to validate the cache entry against * @returns */ export declare function isCacheEntryForType(cacheEntry: CacheEntry, type: TypeRepository): boolean; export type KeyParamsOf = T extends IdentifiableTypeRepository, Record> ? KeyParams : never; export type WriteInput> = { data: Data; } & Extension; export type NormalizeDataInput = Record> = WriteInput; export type ReadInput = Record> = { normalizedData: NormalizedLink; } & Extension; export type ReadByKeyParamsInput = { keyParams: KeyParams; }; export type DenormalizeInput = Record> = Extension & { key: Key; }; export type DenormalizeDataInput = Record> = Extension & { normalizedData: NormalizedData; }; export type KeyParamQuery = { type: 'keyParams'; keyParams: KeyParams; } & ReadInputExtension; export type QueryFor = T extends Queryable, infer Query> ? Query : never; /** * An abstract base class that implements Type, defining additional abstract properties and methods * for building a key for a given set of parameters, and defining the canonical cache control metadata * for any data written */ export declare abstract class IdentifiableTypeRepository = Record, WriteInputExtension extends Record = Record, Query extends KeyParamQuery = KeyParamQuery> implements Queryable, NormalizedLink, WriteInput>, Query> { protected services: {}; constructor(services: {}); abstract readonly cacheControl: CanonicalCacheControlMetadata; abstract readonly namespace: string; abstract readonly typeName: string; protected abstract denormalizeData(cache: ReadonlyCache, input: DenormalizeDataInput>): Result; protected abstract normalizeData(cache: Cache, input: NormalizeDataInput): Result; get cacheMetadata(): { cacheControl: { type: "max-age"; maxAge: number; } | { type: "stale-while-revalidate"; maxAge: number; staleTime: number; } | { type: "no-cache"; } | { type: "no-store"; }; type: { namespace: string; name: string; }; }; buildKey(params: KeyParams): Key; abstract buildKeyParams(input: WriteInput): KeyParams; write(cache: Cache, input: WriteInput): WriteResult; protected validateEntry(entry: CacheEntry): Result; query(cache: Cache, query: Query): ReadResult; read(cache: ReadonlyCache, input: ReadInput): Result; denormalize(cache: ReadonlyCache, input: DenormalizeInput>): Result; equals(x: Data, y: Data): boolean; buildMissingDataError(): MissingDataError; } /** * An abstract base class that extends IdentifiableType, adding the additional constraint that the * only data required to write to the cache is an instance of the data itself, i.e. the identity of * the data lives inside the data */ export declare abstract class SelfIdentifiableTypeRepository = Record, WriteInputExtension extends Record = Record> extends IdentifiableTypeRepository { } /** * Adds flat positional keying (keySchema), keySchema-based buildKey, and invalidate/evict * to IdentifiableTypeRepository. Key params are supplied externally (e.g. from request * config) — this class makes NO claim that identity lives in the data. KeyParams must be a * flat object (scalars, scalar arrays, or stable-stringifiable objects). Provides * invalidation + key building 'for free'. */ export declare abstract class FlattenedKeyIdentifiableTypeRepository = Record, WriteInputExtension extends Record = Record> extends IdentifiableTypeRepository implements Invalidatable, Partial> { protected services: NamedCacheControllerService & NamedPubSubService & Partial; instrumentationAttributes: InstrumentationAttributes | undefined; constructor(services: NamedCacheControllerService & NamedPubSubService & Partial); abstract readonly keySchema: string[]; invalidate(configs: Partial[]): Promise; protected collectInstrumentation(duration: number, type: 'invalidate' | 'evict'): void; evict(configs: Partial[]): Promise; private setupCacheOperation; /** * Shared implementation for cache operations (invalidate/evict) * @param configs - Key configurations to match * @param cacheUpdateType - Type of cache update to perform * @param eventType - Type of event to publish */ private runCacheOperation; buildKey(config: KeyParams): Key; } /** * Flat-keyed identifiable type whose identity lives inside the data itself * (self-identifiable). Behaviorally identical to FlattenedKeyIdentifiableTypeRepository; * the distinction is a semantic marker for generators that derive keyParams from data. */ export declare abstract class FlattenedKeySelfIdentifiableTypeRepository = Record, WriteInputExtension extends Record = Record> extends FlattenedKeyIdentifiableTypeRepository { } type ScalarKeyValue = string | number | boolean | null | undefined; type FlattenedKeyParams = Record; export declare function buildNamespacedTypeKey(namespace: string, typeName: string, keyConfig: FlattenedKeyParams, keySchema: string[]): string; export declare function buildRegexForNamespacedKeys(namespace: string, typeName: string, partialKeyConfigs: Array, keySchema: string[]): RegExp; export declare function extractReadWriteData(result: Result, errorCollector: Error[]): Data | undefined; export declare function buildReadWriteResult(data: unknown, errors: Errors): Result; export type UnionRepresentation = { discriminator: Discriminator; data: Data; }; export type DiscriminatorMap = { [k in Discriminator]: { data: Data; normalized: Normalized; }; }; export type NormalizedRepresentationOf> = M extends DiscriminatorMap ? { [k in D]: UnionRepresentation; }[D] : never; export type DenormalizeMapOf> = M extends DiscriminatorMap ? { [k in D]: (normalized: M[k]['normalized']) => M[k]['data']; } : never; export type UnionDataOf> = M extends DiscriminatorMap ? D : never; export type DiscriminatorOf> = M extends DiscriminatorMap ? D : never; export type DiscriminatorNormalizeFunctionsMap> = M extends DiscriminatorMap ? { [k in D]: { test: (data: M[D]['data']) => boolean | Result; normalize: (data: M[k]['data']) => M[k]['normalized']; }; } : never; /** * * @param normalized The normalized data representation, including the discriminator value * @param denormalizeMap A map of discriminator -> denormalize functions to be used based on the datas discriminator * @returns */ export declare function denormalizeUnionRepresentation>(normalized: NormalizedRepresentationOf, denormalizeMap: DenormalizeMapOf): UnionDataOf; /** * * @param data The canonical/denormalized data representation * @param normalizeTestMap A map of discriminator to test method which return a boolean indicating if the data adheres to this "discriminator" * and a normalize function to call if the data matches this discriminator * @returns */ export declare function normalizeUnionRepresentation>(data: UnionDataOf, normalizeTestMap: DiscriminatorNormalizeFunctionsMap): NormalizedRepresentationOf; export {};