96 lines
4.0 KiB
TypeScript
96 lines
4.0 KiB
TypeScript
import { Entity, EntityCollection, EntityIndex, Plain, Reference } from './entity';
|
|
import { Relationship, RelationshipCollection } from './relationship';
|
|
export interface RelationshipsBuilder<ES extends object> {
|
|
relationship<R extends Relationship<any, any, any>>(fromKey: KeysFor<ES, EntityCollection<R['from'], any>>, toKey: KeysFor<ES, EntityCollection<R['to'], any>>): RelationshipCollection<R>;
|
|
}
|
|
export declare class Database<ES extends object, RS extends object> {
|
|
static entitiesOnly<ES extends object>(entities: ES): Database<ES, {}>;
|
|
private readonly schema;
|
|
private idCtr;
|
|
constructor(entities: ES, relationships: (x: RelationshipsBuilder<ES>) => RS);
|
|
id(): string;
|
|
/**
|
|
* Allocate an ID and store
|
|
*/
|
|
allocate<K extends keyof ES>(key: K, entity: Plain<EntityType<ES[K]>>): EntityType<ES[K]>;
|
|
/**
|
|
* Store with a preallocated ID
|
|
*/
|
|
store<K extends keyof ES>(key: K, entity: EntityType<ES[K]>): EntityType<ES[K]>;
|
|
/**
|
|
* Get an entity by key
|
|
*/
|
|
get<K extends keyof ES>(key: K, id: string | Reference<EntityType<ES[K]>>): EntityType<ES[K]>;
|
|
/**
|
|
* All entities of a given type
|
|
*/
|
|
all<K extends keyof ES>(key: K): Array<EntityType<ES[K]>>;
|
|
/**
|
|
* Lookup an entity by index
|
|
*/
|
|
lookup<K extends keyof ES, I extends IndexNamesOf<ES[K]>>(key: K, index: I, lookup: IndexOf<ES[K], I>['lookups'], value: IndexOf<ES[K], I>['valueType']): RichReadonlyArray<EntityType<ES[K]>>;
|
|
/**
|
|
* Allocate an ID and store if the entity does not yet exist
|
|
*/
|
|
findOrAllocate<K extends keyof ES, I extends keyof Plain<EntityType<ES[K]>> & IndexNamesOf<ES[K]>>(key: K, index: I, lookup: IndexOf<ES[K], I>['lookups'], entity: Plain<EntityType<ES[K]>>): EntityType<ES[K]>;
|
|
/**
|
|
* Record a relationship between two entities
|
|
*
|
|
* Overload to account for whether we have attributes or not.
|
|
*/
|
|
link<K extends RelWAttrs<RS>>(key: K, from: RelType<RS[K]>['from'], to: RelType<RS[K]>['to'], attributes: RelType<RS[K]>['attr']): void;
|
|
link<K extends RelWoAttrs<RS>>(key: K, from: RelType<RS[K]>['from'], to: RelType<RS[K]>['to']): void;
|
|
/**
|
|
* Follow a link
|
|
*/
|
|
follow<K extends keyof RS>(key: K, from: RelType<RS[K]>['from']): RichReadonlyArray<Link<RelType<RS[K]>['to'], RelType<RS[K]>['attr']>>;
|
|
/**
|
|
* Follow incoming links backwards
|
|
*/
|
|
incoming<K extends keyof RS>(key: K, to: RelType<RS[K]>['to']): RichReadonlyArray<Link<RelType<RS[K]>['from'], RelType<RS[K]>['attr']>>;
|
|
e<E extends Entity>(entity: Plain<E>): 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<E, A> = {
|
|
readonly entity: E;
|
|
} & A;
|
|
type RelWAttrs<RS> = {
|
|
[K in keyof RS]: {} extends RelType<RS[K]>['attr'] ? never : K;
|
|
}[keyof RS];
|
|
type RelWoAttrs<RS> = {
|
|
[K in keyof RS]: {} extends RelType<RS[K]>['attr'] ? K : never;
|
|
}[keyof RS];
|
|
type IndexNamesOf<A> = A extends EntityCollection<any> ? KeysOfUnion<A['indexes']> : never;
|
|
type IndexOf<EC, I extends IndexNamesOf<EC>> = EC extends EntityCollection<any> ? EC['indexes'][I] extends EntityIndex<any, infer IndexType> ? {
|
|
valueType: IndexType;
|
|
lookups: keyof EC['indexes'][I]['lookups'];
|
|
} : never : never;
|
|
type EntityType<A> = A extends EntityCollection<infer B> ? B : never;
|
|
type RelType<A> = A extends RelationshipCollection<infer R> ? R : never;
|
|
type ResolveUnion<T> = T extends T ? T : never;
|
|
type KeysOfUnion<T> = keyof ResolveUnion<T>;
|
|
export type EntitiesOf<DB> = DB extends Database<infer ES, any> ? {
|
|
[k in keyof ES]: EntityType<ES[k]>;
|
|
} : {};
|
|
export interface RichReadonlyArray<A> extends ReadonlyArray<A> {
|
|
/**
|
|
* 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<O extends object, T> = {
|
|
[k in keyof O]: O[k] extends T ? k : never;
|
|
}[keyof O];
|
|
export {};
|