import { Tokenizer } from '@sciactive/tokenizer'; import type Nymph from '../Nymph.js'; import type { Selector, Options, FormattedSelector } from '../Nymph.types.js'; import type { EntityInstanceType, EntityObjectType } from '../Entity.js'; import type { EntityConstructor, EntityData, EntityInterface, EntityReference, SerializedEntityData } from '../Entity.types.js'; /** * A Nymph database driver. */ export default abstract class NymphDriver { protected nymph: Nymph; protected tokenizer: Tokenizer; /** * A cache to make entity retrieval faster. */ protected entityCache: { [k: string]: { cdate: number; mdate: number; tags: string[]; data: EntityData; sdata: SerializedEntityData; }; }; /** * A counter for the entity cache to determine the most accessed entities. */ protected entityCount: { [k: string]: number; }; /** * Protect against infinite loops. */ private putDataCounter; /** * This is used internally by Nymph. Don't call it yourself. * * @returns A clone of this instance. */ abstract clone(): NymphDriver; /** * Connect to the data store. */ abstract connect(): Promise; abstract isConnected(): boolean; protected abstract internalTransaction(name: string): Promise; abstract startTransaction(name: string): Promise; abstract commit(name: string): Promise; abstract rollback(name: string): Promise; abstract inTransaction(): Promise; abstract deleteEntityByID(guid: string, classConstructor: EntityConstructor): Promise; abstract deleteEntityByID(guid: string, className?: string): Promise; abstract deleteUID(name: string): Promise; /** * Disconnect from the data store. */ abstract disconnect(): Promise; abstract needsMigration(): Promise<'json' | 'tokens' | 'tilmeldColumns' | false>; abstract liveMigration(migrationType: 'tokenTables' | 'tilmeldColumns' | 'tilmeldRemoveOldRows'): Promise; abstract getEtypes(): Promise; abstract getIndexes(etype: string): Promise<{ scope: 'data' | 'references' | 'tokens'; name: string; property: string; }[]>; abstract addIndex(etype: string, definition: { scope: 'data' | 'references' | 'tokens'; name: string; property: string; }): Promise; abstract deleteIndex(etype: string, scope: 'data' | 'references' | 'tokens', name: string): Promise; abstract exportDataIterator(): AsyncGenerator<{ type: 'comment' | 'uid' | 'entity'; content: string; }, void, undefined | false>; abstract getEntities(options: Options & { return: 'count'; }, ...selectors: Selector[]): Promise; abstract getEntities(options: Options & { return: 'guid'; }, ...selectors: Selector[]): Promise; abstract getEntities(options: Options & { return: 'object'; }, ...selectors: Selector[]): Promise[]>; abstract getEntities(options?: Options, ...selectors: Selector[]): Promise[]>; abstract getEntities(options?: Options, ...selectors: Selector[]): Promise[] | EntityObjectType[] | string[] | number>; abstract getUID(name: string): Promise; abstract importEntity(entity: { guid: string; cdate: number; mdate: number; tags: string[]; sdata: SerializedEntityData; etype: string; }): Promise; abstract importEntityTokens(entity: { guid: string; cdate: number; mdate: number; tags: string[]; sdata: SerializedEntityData; etype: string; }): Promise; abstract importEntityTilmeldAC(entity: { guid: string; cdate: number; mdate: number; tags: string[]; sdata: SerializedEntityData; etype: string; }): Promise; abstract importUID(uid: { name: string; value: number; }): Promise; abstract newUID(name: string): Promise; abstract renameUID(oldName: string, newName: string): Promise; abstract saveEntity(entity: EntityInterface): Promise; abstract setUID(name: string, value: number): Promise; /** * Initialize the Nymph driver. * * This is meant to be called internally by Nymph. Don't call this directly. * * @param nymph The Nymph instance. */ init(nymph: Nymph): void; protected posixRegexMatch(pattern: string, subject: string, caseInsensitive?: boolean): boolean; checkIndexName(name: string): void; export(filename: string): Promise; exportPrint(): Promise; importDataIterator(lines: Iterable, options?: { ignoreUnknownETypes?: boolean; }, transaction?: boolean): Promise; importData(text: string, transaction?: boolean): Promise; import(filename: string, options?: { ignoreUnknownETypes?: boolean; }, transaction?: boolean): Promise; checkData(etype: string, data: EntityData, sdata: SerializedEntityData, selectors: Selector[], guid?: string | null, tags?: string[] | null): boolean; /** * Remove all copies of an entity from the cache. * * @param guid The GUID of the entity to remove. */ protected cleanCache(guid: string): void; deleteEntity(entity: EntityInterface): Promise; /** * Search through a value for an entity reference. * * @param value Any value to search. * @param entity An entity, GUID, or array of either to search for. * @returns True if the reference is found, false otherwise. */ protected entityReferenceSearch(value: any, entity: EntityInterface | EntityReference | string | (EntityInterface | EntityReference | string)[]): boolean; protected removeAndReturnACValues(etype: string, data: EntityData, sdata: SerializedEntityData): { user: string | null; group: string | null; acUser: number | null; acGroup: number | null; acOther: number | null; acRead: string[] | null; acWrite: string[] | null; acFull: string[] | null; }; formatSelectors(selectors: Selector[], options?: Options): { selectors: FormattedSelector[]; qrefs: [Options, ...FormattedSelector[]][]; }; protected iterateSelectorsForQuery(selectors: FormattedSelector[], callback: (data: { key: string; value: any; typeIsOr: boolean; typeIsNot: boolean; }) => string): string[]; protected getEntitiesRowLike(options: Options & { return: 'count'; }, selectors: Selector[], performQueryCallback: (data: { options: Options; selectors: FormattedSelector[]; etype: string; }) => { result: any; }, rowFetchCallback: () => any, freeResultCallback: () => void, getCountCallback: (row: any) => number, getGUIDCallback: (row: any) => string, getTagsAndDatesCallback: (row: any) => { tags: string[]; cdate: number; mdate: number; }, getDataNameAndSValueCallback: (row: any) => { name: string; svalue: string; }): { result: any; process: () => number | Error; }; protected getEntitiesRowLike(options: Options & { return: 'guid'; }, selectors: Selector[], performQueryCallback: (data: { options: Options; selectors: FormattedSelector[]; etype: string; }) => { result: any; }, rowFetchCallback: () => any, freeResultCallback: () => void, getCountCallback: (row: any) => number, getGUIDCallback: (row: any) => string, getTagsAndDatesCallback: (row: any) => { tags: string[]; cdate: number; mdate: number; }, getDataNameAndSValueCallback: (row: any) => { name: string; svalue: string; }): { result: any; process: () => string[] | Error; }; protected getEntitiesRowLike(options: Options & { return: 'object'; }, selectors: Selector[], performQueryCallback: (data: { options: Options; selectors: FormattedSelector[]; etype: string; }) => { result: any; }, rowFetchCallback: () => any, freeResultCallback: () => void, getCountCallback: (row: any) => number, getGUIDCallback: (row: any) => string, getTagsAndDatesCallback: (row: any) => { tags: string[]; cdate: number; mdate: number; }, getDataNameAndSValueCallback: (row: any) => { name: string; svalue: string; }): { result: any; process: () => EntityObjectType[] | Error; }; protected getEntitiesRowLike(options: Options, selectors: Selector[], performQueryCallback: (data: { options: Options; selectors: FormattedSelector[]; etype: string; }) => { result: any; }, rowFetchCallback: () => any, freeResultCallback: () => void, getCountCallback: (row: any) => number, getGUIDCallback: (row: any) => string, getTagsAndDatesCallback: (row: any) => { tags: string[]; cdate: number; mdate: number; }, getDataNameAndSValueCallback: (row: any) => { name: string; svalue: string; }): { result: any; process: () => EntityInstanceType[] | Error; }; protected saveEntityRowLike(entity: EntityInterface, saveNewEntityCallback: (data: { entity: EntityInterface; guid: string; tags: string[]; data: EntityData; sdata: SerializedEntityData; uniques: string[]; cdate: number; etype: string; }) => Promise, saveExistingEntityCallback: (data: { entity: EntityInterface; guid: string; tags: string[]; data: EntityData; sdata: SerializedEntityData; uniques: string[]; mdate: number; etype: string; }) => Promise, startTransactionCallback?: (() => Promise) | null, commitTransactionCallback?: ((success: boolean) => Promise) | null): Promise; /** * Pull an entity from the cache. * * @param guid The entity's GUID. * @returns The entity's data or null if it's not cached. */ protected pullCache(guid: string): { guid: string; cdate: number; mdate: number; tags: string[]; data: EntityData; sdata: SerializedEntityData; } | null; /** * Push an entity onto the cache. * * @param guid The entity's GUID. * @param cdate The entity's cdate. * @param mdate The entity's mdate. * @param tags The entity's tags. * @param data The entity's data. * @param sdata The entity's sdata. */ protected pushCache(guid: string, cdate: number, mdate: number, tags: string[], data: EntityData, sdata: SerializedEntityData): void; protected findReferences(svalue: string): string[]; }