import { Entity, EntityCollection, EntityIndex, Plain, Reference } from './entity'; import { Relationship, RelationshipCollection } from './relationship'; export interface RelationshipsBuilder { relationship>(fromKey: KeysFor>, toKey: KeysFor>): RelationshipCollection; } export declare class Database { static entitiesOnly(entities: ES): Database; private readonly schema; private idCtr; constructor(entities: ES, relationships: (x: RelationshipsBuilder) => RS); id(): string; /** * Allocate an ID and store */ allocate(key: K, entity: Plain>): EntityType; /** * Store with a preallocated ID */ store(key: K, entity: EntityType): EntityType; /** * Get an entity by key */ get(key: K, id: string | Reference>): EntityType; /** * All entities of a given type */ all(key: K): Array>; /** * Lookup an entity by index */ lookup>(key: K, index: I, lookup: IndexOf['lookups'], value: IndexOf['valueType']): RichReadonlyArray>; /** * Allocate an ID and store if the entity does not yet exist */ findOrAllocate> & IndexNamesOf>(key: K, index: I, lookup: IndexOf['lookups'], entity: Plain>): EntityType; /** * Record a relationship between two entities * * Overload to account for whether we have attributes or not. */ link>(key: K, from: RelType['from'], to: RelType['to'], attributes: RelType['attr']): void; link>(key: K, from: RelType['from'], to: RelType['to']): void; /** * Follow a link */ follow(key: K, from: RelType['from']): RichReadonlyArray['to'], RelType['attr']>>; /** * Follow incoming links backwards */ incoming(key: K, to: RelType['to']): RichReadonlyArray['from'], RelType['attr']>>; e(entity: Plain): E; /** * Turn the current database collection into something that can be stored. */ save(): DehydratedDatabase; load(db: DehydratedDatabase): void; } interface DehydratedDatabase { readonly idCtr: number; readonly schema: any; } export type Link = { readonly entity: E; } & A; type RelWAttrs = { [K in keyof RS]: {} extends RelType['attr'] ? never : K; }[keyof RS]; type RelWoAttrs = { [K in keyof RS]: {} extends RelType['attr'] ? K : never; }[keyof RS]; type IndexNamesOf = A extends EntityCollection ? KeysOfUnion : never; type IndexOf> = EC extends EntityCollection ? EC['indexes'][I] extends EntityIndex ? { valueType: IndexType; lookups: keyof EC['indexes'][I]['lookups']; } : never : never; type EntityType = A extends EntityCollection ? B : never; type RelType = A extends RelationshipCollection ? R : never; type ResolveUnion = T extends T ? T : never; type KeysOfUnion = keyof ResolveUnion; export type EntitiesOf = DB extends Database ? { [k in keyof ES]: EntityType; } : {}; export interface RichReadonlyArray extends ReadonlyArray { /** * Return the first and only element, throwing if there are != 1 elements */ only(): A; } /** * Return the keys of an object that map to a particular type */ type KeysFor = { [k in keyof O]: O[k] extends T ? k : never; }[keyof O]; export {};