UNPKG

@alwatr/nitrobase-engine

Version:

Nitrobase is a blazingly fast, lightweight database built on JSON. It stores data entirely in memory for lightning-quick access, while also providing a JSON file backup for persistence. You can easily serve your data over the web using our high-performanc

8 lines (7 loc) 24.6 kB
{ "version": 3, "sources": ["../src/main.ts", "../src/alwatr-nitrobase.ts", "../src/logger.ts"], "sourcesContent": ["export * from './alwatr-nitrobase.js';\n", "import {delay} from '@alwatr/nanolib';\nimport {exitHook} from '@alwatr/nanolib/exit-hook';\nimport {existsSync, readJson, resolve, unlink, writeJson} from '@alwatr/nanolib/node-fs';\nimport {getStoreId, getStorePath} from '@alwatr/nitrobase-helper';\nimport {CollectionReference, DocumentReference} from '@alwatr/nitrobase-reference';\nimport {\n StoreFileType,\n StoreFileExtension,\n Region,\n type StoreFileStat,\n type StoreFileContext,\n type CollectionContext,\n type DocumentContext,\n type StoreFileId,\n type CollectionItem,\n} from '@alwatr/nitrobase-types';\n\nimport {logger} from './logger.js';\n\n__dev_mode__: logger.logFileModule?.('alwatr-nitrobase');\n\n/**\n * AlwatrNitrobase configuration.\n */\nexport interface AlwatrNitrobaseConfig {\n /**\n * The root path of the storage.\n * This is where the AlwatrNitrobase will nitrobase its data.\n */\n rootPath: string;\n\n /**\n * The save debounce timeout in milliseconds for minimal disk I/O usage.\n * This is used to limit the frequency of disk writes for performance reasons.\n * The recommended value is `40`.\n */\n defaultChangeDebounce?: number;\n\n /**\n * If true, an error will be thrown when trying to read or write to a nitrobase file that is not initialized (new storage).\n * The default value is `false` but highly recommended to set it to `true` in production to prevent data loss.\n */\n errorWhenNotInitialized?: boolean;\n}\n\n/**\n * AlwatrNitrobase engine.\n *\n * It provides methods to read, write, validate, and manage nitrobase files.\n * It also provides methods to interact with `documents` and `collections` in the nitrobase.\n */\nexport class AlwatrNitrobase {\n /**\n * The Alwatr Nitrobase version string.\n *\n * Use for nitrobase file format version for check compatibility.\n */\n static readonly version = __package_version__;\n\n /**\n * The root nitrobase file stat.\n */\n private static readonly rootDbStat__: StoreFileStat = {\n name: '.nitrobase',\n region: Region.Secret,\n type: StoreFileType.Collection,\n extension: StoreFileExtension.Json,\n changeDebounce: 40,\n };\n\n /**\n * `collectionReference` of all `storeFileStat`s.\n * This is the root nitrobase collection.\n */\n private rootDb__;\n\n /**\n * Keep all loaded nitrobase file context loaded in memory.\n */\n private cacheReferences__: DictionaryReq<DocumentReference | CollectionReference> = {};\n\n /**\n * Constructs an AlwatrNitrobase instance with the provided configuration.\n *\n * @param config The configuration of the AlwatrNitrobase engine.\n * @example\n * ```typescript\n * const alwatrStore = new AlwatrNitrobase({\n * rootPath: './db',\n * saveDebounce: 40,\n * });\n * ```\n */\n constructor(readonly config: AlwatrNitrobaseConfig) {\n this.storeChanged_ = this.storeChanged_.bind(this);\n\n logger.logMethodArgs?.('new', config);\n this.config.defaultChangeDebounce ??= 40;\n this.rootDb__ = this.loadRootDb__();\n exitHook(this.exitHook__.bind(this));\n }\n\n /**\n * Checks if a nitrobase file with the given ID exists.\n *\n * @param storeId - The ID of the nitrobase file to check.\n * @returns `true` if the nitrobase file exists, `false` otherwise.\n * @example\n * ```typescript\n * if (!alwatrStore.hasStore('user1/profile')) {\n * alwatrStore.defineDocument(...)\n * }\n * ```\n */\n hasStore(storeId: StoreFileId): boolean {\n const id_ = getStoreId(storeId);\n const exists = this.rootDb__.hasItem(id_);\n logger.logMethodFull?.('hasStore', id_, exists);\n return exists;\n }\n\n /**\n * Defines a new document with the given configuration and initial data.\n * If a document with the same ID already exists, an error is thrown.\n *\n * @param stat nitrobase file stat\n * @param data initial data for the document\n * @template TDoc document data type\n * @example\n * ```typescript\n * await alwatrStore.newDocument<Order>(\n * {\n * name: 'profile',\n * region: Region.PerUser,\n * ownerId: 'user1',\n * },\n * {\n * name: 'Ali',\n * email: 'ali@alwatr.io',\n * }\n * );\n * ```\n */\n newDocument<TDoc extends JsonObject = JsonObject>(stat: Omit<StoreFileStat, 'type'>, data: TDoc): void {\n logger.logMethodArgs?.('newDocument', stat);\n return this.newStoreFile_(\n {\n ...stat,\n type: StoreFileType.Document,\n },\n data,\n );\n }\n\n /**\n * Defines a new collection with the given configuration and initial data.\n * If a collection with the same ID already exists, an error is thrown.\n *\n * @param stat nitrobase file stat\n * @example\n * ```typescript\n * await alwatrStore.newCollection<Order>(\n * {\n * name: 'orders',\n * region: Region.PerUser,\n * ownerId: 'user1',\n * }\n * );\n * ```\n */\n newCollection(stat: Omit<StoreFileStat, 'type'>): void {\n logger.logMethodArgs?.('newCollection', stat);\n return this.newStoreFile_(\n {\n ...stat,\n type: StoreFileType.Collection,\n }\n );\n }\n\n /**\n * Defines a AlwatrNitrobaseFile with the given configuration and initial data.\n *\n * @param stat nitrobase file stat\n * @param data initial data for the document\n */\n newStoreFile_(\n stat: StoreFileStat,\n data?: DictionaryOpt,\n ): void {\n logger.logMethodArgs?.('newStoreFile_', stat);\n\n (stat.changeDebounce as number | undefined) ??= this.config.defaultChangeDebounce;\n\n let fileStoreRef: DocumentReference | CollectionReference;\n if (stat.type === StoreFileType.Document) {\n if (data === undefined) {\n logger.accident('newStoreFile_', 'document_data_required', stat);\n throw new Error('document_data_required', {cause: stat});\n }\n fileStoreRef = DocumentReference.newRefFromData(stat, data, this.storeChanged_);\n }\n else if (stat.type === StoreFileType.Collection) {\n fileStoreRef = CollectionReference.newRefFromData(stat, this.storeChanged_);\n }\n else {\n logger.accident('newStoreFile_', 'store_file_type_not_supported', stat);\n throw new Error('store_file_type_not_supported', {cause: stat});\n }\n\n if (this.rootDb__.hasItem(fileStoreRef.id)) {\n logger.accident('newStoreFile_', 'store_file_already_defined', stat);\n throw new Error('store_file_already_defined', {cause: stat});\n }\n\n this.rootDb__.addItem(fileStoreRef.id, stat);\n this.cacheReferences__[fileStoreRef.id] = fileStoreRef;\n\n // fileStoreRef.save();\n this.storeChanged_(fileStoreRef);\n }\n\n /**\n * Open a document with the given id and create and return a DocumentReference.\n * If the document not exists or its not a document, an error is thrown.\n *\n * @template TDoc document data type\n * @param documentId document id {@link StoreFileId}\n * @returns document reference {@link DocumentReference}\n * @example\n * ```typescript\n * const userProfile = await alwatrStore.openDocument<User>({\n * name: 'user1/profile',\n * region: Region.PerUser,\n * ownerId: 'user1',\n * });\n * userProfile.update({name: 'ali'});\n * ```\n */\n async openDocument<TDoc extends JsonObject>(documentId: StoreFileId): Promise<DocumentReference<TDoc>> {\n const id = getStoreId(documentId);\n logger.logMethodArgs?.('openDocument', id);\n\n if (Object.hasOwn(this.cacheReferences__, id)) {\n const ref = this.cacheReferences__[id];\n if (!(ref instanceof DocumentReference)) {\n logger.accident('openDocument', 'document_wrong_type', id);\n throw new Error('document_wrong_type', {cause: id});\n }\n return this.cacheReferences__[id] as unknown as DocumentReference<TDoc>;\n }\n\n if (!this.rootDb__.hasItem(id)) {\n logger.accident('openDocument', 'document_not_found', id);\n throw new Error('document_not_found', {cause: id});\n }\n\n const storeStat = this.rootDb__.getItemData(id);\n\n if (storeStat.type != StoreFileType.Document) {\n logger.accident('openDocument', 'document_wrong_type', id);\n throw new Error('document_wrong_type', {cause: id});\n }\n\n const context = await this.readContext__<DocumentContext<TDoc>>(storeStat);\n const docRef = DocumentReference.newRefFromContext(context, this.storeChanged_);\n this.cacheReferences__[id] = docRef as unknown as DocumentReference;\n return docRef;\n }\n\n /**\n * Open a collection with the given id and create and return a CollectionReference.\n * If the collection not exists or its not a collection, an error is thrown.\n *\n * @template TItem collection item data type\n * @param collectionId collection id {@link StoreFileId}\n * @returns collection reference {@link CollectionReference}\n * @example\n * ```typescript\n * const orders = await alwatrStore.openCollection<Order>({\n * name: 'orders',\n * region: Region.PerUser,\n * ownerId: 'user1',\n * });\n * orders.append({name: 'order 1'});\n * ```\n */\n async openCollection<TItem extends JsonObject>(collectionId: StoreFileId): Promise<CollectionReference<TItem>> {\n const id = getStoreId(collectionId);\n logger.logMethodArgs?.('openCollection', id);\n\n // try to get from cache\n if (Object.hasOwn(this.cacheReferences__, id)) {\n const ref = this.cacheReferences__[id];\n if (!(ref instanceof CollectionReference)) {\n logger.accident('openCollection', 'collection_wrong_type', id);\n throw new Error('collection_wrong_type', {cause: id});\n }\n return this.cacheReferences__[id] as unknown as CollectionReference<TItem>;\n }\n\n // load and create new collection reference\n if (!this.rootDb__.hasItem(id)) {\n logger.accident('openCollection', 'collection_not_found', id);\n throw new Error('collection_not_found', {cause: id});\n }\n\n const storeStat = this.rootDb__.getItemData(id);\n\n if (storeStat.type != StoreFileType.Collection) {\n logger.accident('openCollection', 'collection_wrong_type', id);\n throw new Error('collection_not_found', {cause: id});\n }\n\n const context = await this.readContext__<CollectionContext<TItem>>(storeStat);\n const colRef = CollectionReference.newRefFromContext(context, this.storeChanged_);\n this.cacheReferences__[id] = colRef as unknown as CollectionReference;\n return colRef;\n }\n\n /**\n * Unloads the nitrobase file with the given id from memory.\n *\n * @param storeId The unique identifier of the nitrobase file. {@link StoreFileId}\n * @example\n * ```typescript\n * alwatrStore.unloadStore({name: 'user-list', region: Region.Secret});\n * alwatrStore.hasStore({name: 'user-list', region: Region.Secret}); // true\n * ```\n */\n unloadStore(storeId: StoreFileId): void {\n const id_ = getStoreId(storeId);\n logger.logMethodArgs?.('unloadStore', id_);\n const ref = this.cacheReferences__[id_];\n if (ref === undefined) return;\n if (ref.hasUnprocessedChanges_ === true) {\n ref.updateDelayed_ = false;\n this.storeChanged_(ref);\n }\n delete this.cacheReferences__[id_];\n }\n\n /**\n * Remove document or collection from nitrobase and delete the file from disk.\n * If the file is not found, an error is thrown.\n * If the file is not unloaded, it will be unloaded first.\n * You don't need to await this method to complete unless you want to make sure the file is deleted on disk.\n *\n * @param storeId The ID of the file to delete. {@link StoreFileId}\n * @returns A Promise that resolves when the file is deleted.\n * @example\n * ```typescript\n * alwatrStore.removeStore({name: 'user-list', region: Region.Secret});\n * alwatrStore.hasStore({name: 'user-list', region: Region.Secret}); // false\n * ```\n */\n async removeStore(storeId: StoreFileId): Promise<void> {\n const id_ = getStoreId(storeId);\n logger.logMethodArgs?.('removeStore', id_);\n if (!this.rootDb__.hasItem(id_)) {\n logger.accident('removeStore', 'document_not_found', id_);\n throw new Error('document_not_found', {cause: id_});\n }\n const ref = this.cacheReferences__[id_];\n if (ref !== undefined) {\n // direct unload to prevent save\n ref.freeze = true;\n ref.updateDelayed_ = false;\n ref.hasUnprocessedChanges_ = false;\n delete this.cacheReferences__[id_]; // unload\n }\n const path = getStorePath(this.rootDb__.getItemData(id_));\n this.rootDb__.removeItem(id_);\n await delay.by(0);\n try {\n await unlink(resolve(this.config.rootPath, path));\n }\n catch (error) {\n logger.error('removeStore', 'remove_file_failed', error, {id: storeId, path});\n }\n }\n\n /**\n * Saves all changes in the nitrobase.\n *\n * @returns A Promise that resolves when all changes are saved.\n * @example\n * ```typescript\n * await alwatrStore.saveAll();\n * ```\n */\n async saveAll(): Promise<void> {\n logger.logMethod?.('saveAll');\n for (const ref of Object.values(this.cacheReferences__)) {\n if (ref.hasUnprocessedChanges_ === true && ref.freeze !== true) {\n ref.updateDelayed_ = false;\n await this.storeChanged_(ref);\n }\n }\n }\n\n /**\n * Reads the context from a given path or StoreFileStat object.\n *\n * @param path The path or StoreFileStat object from which to read the context.\n * @returns A promise that resolves to the context object.\n */\n private async readContext__<T extends StoreFileContext>(path: string | StoreFileStat): Promise<T> {\n if (typeof path !== 'string') path = getStorePath(path);\n logger.logMethodArgs?.('readContext__', path);\n logger.time?.(`readContext__time(${path})`);\n const context = (await readJson(resolve(this.config.rootPath, path))) as T;\n logger.timeEnd?.(`readContext__time(${path})`);\n return context;\n }\n\n /**\n * Writes the context to the specified path.\n *\n * @template T The type of the context.\n * @param path The path where the context will be written.\n * @param context The context to be written.\n * @param sync Indicates whether the write operation should be synchronous.\n * @returns A promise that resolves when the write operation is complete.\n */\n private writeContext__<T extends StoreFileContext>(path: string | StoreFileStat, context: T): Promise<void> {\n if (typeof path !== 'string') path = getStorePath(path);\n logger.logMethodArgs?.('writeContext__', path);\n return writeJson(resolve(this.config.rootPath, path), context);\n }\n\n /**\n * Write nitrobase file context.\n *\n * @param from nitrobase file reference\n * @returns A promise that resolves when the write operation is complete.\n */\n protected async storeChanged_<T extends JsonObject>(from: DocumentReference<T> | CollectionReference<T>): Promise<void> {\n logger.logMethodArgs?.('storeChanged__', from.id);\n const rev = from.getStoreMeta().rev;\n try {\n await this.writeContext__(from.path, from.getFullContext_());\n if (rev === from.getStoreMeta().rev) {\n // Context not changed during saving\n from.hasUnprocessedChanges_ = false;\n }\n }\n catch (error) {\n logger.error('storeChanged__', 'write_context_failed', {id: from.id, error});\n }\n }\n\n /**\n * Load storeFilesCollection or create new one.\n */\n private loadRootDb__(): CollectionReference<StoreFileStat> {\n logger.logMethod?.('loadRootDb__');\n const fullPath = resolve(this.config.rootPath, getStorePath(AlwatrNitrobase.rootDbStat__));\n if (!existsSync(fullPath)) {\n if (this.config.errorWhenNotInitialized === true) {\n throw new Error('store_not_found', {cause: 'Nitrobase not initialized'});\n }\n\n logger.banner('Initialize new alwatr-nitrobase');\n return CollectionReference.newRefFromData(AlwatrNitrobase.rootDbStat__, this.storeChanged_);\n }\n // else\n const context = readJson<CollectionContext<StoreFileStat>>(fullPath, true);\n return CollectionReference.newRefFromContext(context, this.storeChanged_, 'root-db');\n }\n\n /**\n * Save all nitrobase files.\n */\n private exitHook__(): void {\n logger.logMethod?.('exitHook__');\n for (const ref of Object.values(this.cacheReferences__)) {\n logger.logProperty?.(`StoreFile.${ref.id}.hasUnprocessedChanges`, ref.hasUnprocessedChanges_);\n if (ref.hasUnprocessedChanges_ === true && ref.freeze !== true) {\n logger.incident?.('exitHook__', 'rescue_unsaved_context', {id: ref.id});\n writeJson(resolve(this.config.rootPath, ref.path), ref.getFullContext_(), true);\n ref.hasUnprocessedChanges_ = false;\n }\n }\n }\n\n /**\n * Get all nitrobase files.\n *\n * @returns all nitrobase files.\n * @example\n * ```typescript\n * const storeList = alwatrStore.getStoreList();\n * for (const nitrobase of storeList) {\n * console.log(nitrobase.meta.id, nitrobase.data);\n * }\n */\n getStoreList(): CollectionItem<Omit<StoreFileStat, 'schemaVer'>>[] {\n logger.logMethod?.('getStoreList');\n return this.rootDb__.values();\n }\n}\n", "import {createLogger, packageTracer} from '@alwatr/nanolib';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\nexport const logger = /* #__PURE__ */ createLogger(__package_name__);\n"], "mappings": "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", "names": ["import_nanolib"] }