@alwatr/nitrobase-engine 7.10.1 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"alwatr-nitrobase.d.ts","sourceRoot":"","sources":["../src/alwatr-nitrobase.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAIL,KAAK,aAAa,EAIlB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAOjC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,qBAAa,eAAe;aA0CE,MAAM,EAAE,qBAAqB;IAzCzD;;;;OAIG;IACH,gBAAuB,OAAO,SAAuB;IAErD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAMlC;IAEF;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,iBAAiB,CAA8D;IAEvF;;;;;;;;;;;OAWG;gBACyB,MAAM,EAAE,qBAAqB;IASzD;;;;;;;;;;;OAWG;IACI,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAO9C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,WAAW,CAAC,IAAI,SAAS,UAAU,GAAG,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAW7G;;;;;;;;;;;;;;;OAeG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,IAAI;IAQ7D;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAiCtB;;;;;;;;;;;;;;;;OAgBG;IACU,YAAY,CAAC,IAAI,SAAS,UAAU,EAAE,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IA+B7G;;;;;;;;;;;;;;;;OAgBG;IACU,cAAc,CAAC,KAAK,SAAS,UAAU,EAAE,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAiCrH;;;;;;;;;OASG;IACI,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAY9C;;;;;;;;;;;;;OAaG;IACU,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B7D;;;;;;;;OAQG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC;;;;;OAKG;YACW,aAAa;IAS3B;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAMtB;;;;;OAKG;cACa,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAevH;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAYlB;;;;;;;;;;OAUG;IACI,YAAY,IAAI,cAAc,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE;CAI1E"}
1
+ {"version":3,"file":"alwatr-nitrobase.d.ts","sourceRoot":"","sources":["../src/alwatr-nitrobase.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAIL,KAAK,aAAa,EAIlB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAQjC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,qBAAa,eAAe;aA0CE,MAAM,EAAE,qBAAqB;IAzCzD;;;;OAIG;IACH,gBAAuB,OAAO,SAAuB;IAErD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAMlC;IAEF;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,iBAAiB,CAA8D;IAEvF;;;;;;;;;;;OAWG;gBACyB,MAAM,EAAE,qBAAqB;IASzD;;;;;;;;;;;OAWG;IACI,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAO9C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,WAAW,CAAC,IAAI,SAAS,UAAU,GAAG,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAW7G;;;;;;;;;;;;;;;OAeG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,IAAI;IAQ7D;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAiCtB;;;;;;;;;;;;;;;;OAgBG;IACU,YAAY,CAAC,IAAI,SAAS,UAAU,EAAE,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IA+B7G;;;;;;;;;;;;;;;;OAgBG;IACU,cAAc,CAAC,KAAK,SAAS,UAAU,EAAE,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAiCrH;;;;;;;;;OASG;IACI,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAY9C;;;;;;;;;;;;;OAaG;IACU,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B7D;;;;;;;;OAQG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC;;;;;OAKG;YACW,aAAa;IAS3B;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAMtB;;;;;OAKG;cACa,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAevH;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAYlB;;;;;;;;;;OAUG;IACI,YAAY,IAAI,cAAc,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE;CAI1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM,uCAAiD,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,uCAAiD,CAAC"}
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ /* 📦 @alwatr/nitrobase-engine v9.1.0 */
2
+ import{delay as H}from"@alwatr/delay";import{exitHook as k}from"@alwatr/exit-hook";import{getStoreId as U,getStorePath as X}from"@alwatr/nitrobase-helper";import{CollectionReference as V,DocumentReference as Y}from"@alwatr/nitrobase-reference";import{StoreFileType as O,StoreFileExtension as L,Region as D}from"@alwatr/nitrobase-types";import{existsSync as A,readJson as $,resolve as W,unlink as J,writeJson as j}from"@alwatr/node-fs";import{createLogger as G}from"@alwatr/logger";var B=G("@alwatr/nitrobase-engine");q:B.logFileModule?.("alwatr-nitrobase");class Z{config;static version="9.1.0";static rootDbStat__={name:".nitrobase",region:D.Secret,type:O.Collection,extension:L.Json,changeDebounce:40};rootDb__;cacheReferences__={};constructor(q){this.config=q;this.storeChanged_=this.storeChanged_.bind(this),B.logMethodArgs?.("new",q),this.config.defaultChangeDebounce??=40,this.rootDb__=this.loadRootDb__(),k(this.exitHook__.bind(this))}hasStore(q){let z=U(q),K=this.rootDb__.hasItem(z);return B.logMethodFull?.("hasStore",z,K),K}newDocument(q,z){return B.logMethodArgs?.("newDocument",q),this.newStoreFile__({...q,type:O.Document},z)}newCollection(q){return B.logMethodArgs?.("newCollection",q),this.newStoreFile__({...q,type:O.Collection})}newStoreFile__(q,z){B.logMethodArgs?.("newStoreFile__",q),q.changeDebounce??=this.config.defaultChangeDebounce;let K;if(q.type===O.Document){if(z===void 0)throw B.accident("newStoreFile__","document_data_required",q),Error("document_data_required",{cause:q});K=Y.newRefFromData(q,z,this.storeChanged_)}else if(q.type===O.Collection)K=V.newRefFromData(q,this.storeChanged_);else throw B.accident("newStoreFile__","store_file_type_not_supported",q),Error("store_file_type_not_supported",{cause:q});if(this.rootDb__.hasItem(K.id))throw B.accident("newStoreFile__","store_file_already_defined",q),Error("store_file_already_defined",{cause:q});this.rootDb__.addItem(K.id,q),this.cacheReferences__[K.id]=K,this.storeChanged_(K)}async openDocument(q){let z=U(q);if(B.logMethodArgs?.("openDocument",z),Object.hasOwn(this.cacheReferences__,z)){if(!(this.cacheReferences__[z]instanceof Y))throw B.accident("openDocument","document_wrong_type",z),Error("document_wrong_type",{cause:z});return this.cacheReferences__[z]}if(!this.rootDb__.hasItem(z))throw B.accident("openDocument","document_not_found",z),Error("document_not_found",{cause:z});let K=this.rootDb__.getItemData(z);if(K.type!=O.Document)throw B.accident("openDocument","document_wrong_type",z),Error("document_wrong_type",{cause:z});let Q=await this.readContext__(K),M=Y.newRefFromContext(Q,this.storeChanged_);return this.cacheReferences__[z]=M,M}async openCollection(q){let z=U(q);if(B.logMethodArgs?.("openCollection",z),Object.hasOwn(this.cacheReferences__,z)){if(!(this.cacheReferences__[z]instanceof V))throw B.accident("openCollection","collection_wrong_type",z),Error("collection_wrong_type",{cause:z});return this.cacheReferences__[z]}if(!this.rootDb__.hasItem(z))throw B.accident("openCollection","collection_not_found",z),Error("collection_not_found",{cause:z});let K=this.rootDb__.getItemData(z);if(K.type!=O.Collection)throw B.accident("openCollection","collection_wrong_type",z),Error("collection_not_found",{cause:z});let Q=await this.readContext__(K),M=V.newRefFromContext(Q,this.storeChanged_);return this.cacheReferences__[z]=M,M}unloadStore(q){let z=U(q);B.logMethodArgs?.("unloadStore",z);let K=this.cacheReferences__[z];if(K===void 0)return;if(K.hasUnprocessedChanges_===!0)K.updateDelayed_=!1,this.storeChanged_(K);delete this.cacheReferences__[z]}async removeStore(q){let z=U(q);if(B.logMethodArgs?.("removeStore",z),!this.rootDb__.hasItem(z))throw B.accident("removeStore","document_not_found",z),Error("document_not_found",{cause:z});let K=this.cacheReferences__[z];if(K!==void 0)K.freeze=!0,K.updateDelayed_=!1,K.hasUnprocessedChanges_=!1,delete this.cacheReferences__[z];let Q=X(this.rootDb__.getItemData(z));this.rootDb__.removeItem(z),await H.by(0);try{await J(W(this.config.rootPath,Q))}catch(M){B.error("removeStore","remove_file_failed",M,{id:q,path:Q})}}async saveAll(){B.logMethod?.("saveAll");for(let q of Object.values(this.cacheReferences__))if(q.hasUnprocessedChanges_===!0&&q.freeze!==!0)q.updateDelayed_=!1,await this.storeChanged_(q)}async readContext__(q){if(typeof q!=="string")q=X(q);B.logMethodArgs?.("readContext__",q),B.time?.(`readContext__time(${q})`);let z=await $(W(this.config.rootPath,q));return B.timeEnd?.(`readContext__time(${q})`),z}writeContext__(q,z){if(typeof q!=="string")q=X(q);return B.logMethodArgs?.("writeContext__",q),j(W(this.config.rootPath,q),z)}async storeChanged_(q){B.logMethodArgs?.("storeChanged__",q.id);let z=q.getStoreMeta().rev;try{if(await this.writeContext__(q.path,q.getFullContext_()),z===q.getStoreMeta().rev)q.hasUnprocessedChanges_=!1}catch(K){B.error("storeChanged__","write_context_failed",{id:q.id,error:K})}}loadRootDb__(){B.logMethod?.("loadRootDb__");let q=W(this.config.rootPath,X(Z.rootDbStat__));if(!A(q)){if(this.config.errorWhenNotInitialized===!0)throw Error("store_not_found",{cause:"Nitrobase not initialized"});return B.banner("Initialize new alwatr-nitrobase"),V.newRefFromData(Z.rootDbStat__,this.storeChanged_)}let z=$(q,!0);return V.newRefFromContext(z,this.storeChanged_,"root-db")}exitHook__(){B.logMethod?.("exitHook__");for(let q of Object.values(this.cacheReferences__))if(B.logProperty?.(`StoreFile.${q.id}.hasUnprocessedChanges`,q.hasUnprocessedChanges_),q.hasUnprocessedChanges_===!0&&q.freeze!==!0)B.incident?.("exitHook__","rescue_unsaved_context",{id:q.id}),j(W(this.config.rootPath,q.path),q.getFullContext_(),!0),q.hasUnprocessedChanges_=!1}getStoreList(){return B.logMethod?.("getStoreList"),this.rootDb__.values()}}export{Z as AlwatrNitrobase};
3
+
4
+ //# debugId=C1C6087927638DC864756E2164756E21
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/alwatr-nitrobase.ts", "../src/logger.ts"],
4
+ "sourcesContent": [
5
+ "import {delay} from '@alwatr/delay';\nimport {exitHook} from '@alwatr/exit-hook';\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';\nimport {existsSync, readJson, resolve, unlink, writeJson} from '@alwatr/node-fs';\n\nimport {logger} from './logger.js';\n\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 public 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(public 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 public 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 public 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 public newCollection(stat: Omit<StoreFileStat, 'type'>): void {\n logger.logMethodArgs?.('newCollection', stat);\n return this.newStoreFile__({\n ...stat,\n type: StoreFileType.Collection,\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 private newStoreFile__(stat: StoreFileStat, data?: DictionaryOpt): 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 public 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 public 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 public 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 public 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 public 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 public getStoreList(): CollectionItem<Omit<StoreFileStat, 'schemaVer'>>[] {\n logger.logMethod?.('getStoreList');\n return this.rootDb__.values();\n }\n}\n",
6
+ "import {createLogger} from '@alwatr/logger';\n\n\nexport const logger = /* #__PURE__ */ createLogger(__package_name__);\n"
7
+ ],
8
+ "mappings": ";AAAA,gBAAQ,sBACR,mBAAQ,0BACR,qBAAQ,kBAAY,iCACpB,8BAAQ,uBAAqB,oCAC7B,wBACE,wBACA,YACA,gCAQF,qBAAQ,cAAY,aAAU,YAAS,eAAQ,wBCf/C,uBAAQ,uBAGD,IAAM,EAAyB,EAAa,0BAAgB,EDiBnE,EAAc,EAAO,gBAAgB,kBAAkB,EAgChD,MAAM,CAAgB,CA0CC,aApCL,SAAU,cAKT,cAA8B,CACpD,KAAM,aACN,OAAQ,EAAO,OACf,KAAM,EAAc,WACpB,UAAW,EAAmB,KAC9B,eAAgB,EAClB,EAMQ,SAKA,kBAA4E,CAAC,EAcrF,WAAW,CAAiB,EAA+B,CAA/B,cAC1B,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EAEjD,EAAO,gBAAgB,MAAO,CAAM,EACpC,KAAK,OAAO,wBAA0B,GACtC,KAAK,SAAW,KAAK,aAAa,EAClC,EAAS,KAAK,WAAW,KAAK,IAAI,CAAC,EAe9B,QAAQ,CAAC,EAA+B,CAC7C,IAAM,EAAM,EAAW,CAAO,EACxB,EAAS,KAAK,SAAS,QAAQ,CAAG,EAExC,OADA,EAAO,gBAAgB,WAAY,EAAK,CAAM,EACvC,EAyBF,WAAiD,CAAC,EAAmC,EAAkB,CAE5G,OADA,EAAO,gBAAgB,cAAe,CAAI,EACnC,KAAK,eACV,IACK,EACH,KAAM,EAAc,QACtB,EACA,CACF,EAmBK,aAAa,CAAC,EAAyC,CAE5D,OADA,EAAO,gBAAgB,gBAAiB,CAAI,EACrC,KAAK,eAAe,IACtB,EACH,KAAM,EAAc,UACtB,CAAC,EASK,cAAc,CAAC,EAAqB,EAA4B,CACtE,EAAO,gBAAgB,iBAAkB,CAAI,EAE5C,EAAK,iBAA0C,KAAK,OAAO,sBAE5D,IAAI,EACJ,GAAI,EAAK,OAAS,EAAc,SAAU,CACxC,GAAI,IAAS,OAEX,MADA,EAAO,SAAS,iBAAkB,yBAA0B,CAAI,EACtD,MAAM,yBAA0B,CAAC,MAAO,CAAI,CAAC,EAEzD,EAAe,EAAkB,eAAe,EAAM,EAAM,KAAK,aAAa,EAE3E,QAAI,EAAK,OAAS,EAAc,WACnC,EAAe,EAAoB,eAAe,EAAM,KAAK,aAAa,EAI1E,WADA,EAAO,SAAS,iBAAkB,gCAAiC,CAAI,EAC7D,MAAM,gCAAiC,CAAC,MAAO,CAAI,CAAC,EAGhE,GAAI,KAAK,SAAS,QAAQ,EAAa,EAAE,EAEvC,MADA,EAAO,SAAS,iBAAkB,6BAA8B,CAAI,EAC1D,MAAM,6BAA8B,CAAC,MAAO,CAAI,CAAC,EAG7D,KAAK,SAAS,QAAQ,EAAa,GAAI,CAAI,EAC3C,KAAK,kBAAkB,EAAa,IAAM,EAG1C,KAAK,cAAc,CAAY,OAoBpB,aAAqC,CAAC,EAA2D,CAC5G,IAAM,EAAK,EAAW,CAAU,EAGhC,GAFA,EAAO,gBAAgB,eAAgB,CAAE,EAErC,OAAO,OAAO,KAAK,kBAAmB,CAAE,EAAG,CAE7C,GAAI,EADQ,KAAK,kBAAkB,aACd,GAEnB,MADA,EAAO,SAAS,eAAgB,sBAAuB,CAAE,EAC/C,MAAM,sBAAuB,CAAC,MAAO,CAAE,CAAC,EAEpD,OAAO,KAAK,kBAAkB,GAGhC,GAAI,CAAC,KAAK,SAAS,QAAQ,CAAE,EAE3B,MADA,EAAO,SAAS,eAAgB,qBAAsB,CAAE,EAC9C,MAAM,qBAAsB,CAAC,MAAO,CAAE,CAAC,EAGnD,IAAM,EAAY,KAAK,SAAS,YAAY,CAAE,EAE9C,GAAI,EAAU,MAAQ,EAAc,SAElC,MADA,EAAO,SAAS,eAAgB,sBAAuB,CAAE,EAC/C,MAAM,sBAAuB,CAAC,MAAO,CAAE,CAAC,EAGpD,IAAM,EAAU,MAAM,KAAK,cAAqC,CAAS,EACnE,EAAS,EAAkB,kBAAkB,EAAS,KAAK,aAAa,EAE9E,OADA,KAAK,kBAAkB,GAAM,EACtB,OAoBI,eAAwC,CAAC,EAAgE,CACpH,IAAM,EAAK,EAAW,CAAY,EAIlC,GAHA,EAAO,gBAAgB,iBAAkB,CAAE,EAGvC,OAAO,OAAO,KAAK,kBAAmB,CAAE,EAAG,CAE7C,GAAI,EADQ,KAAK,kBAAkB,aACd,GAEnB,MADA,EAAO,SAAS,iBAAkB,wBAAyB,CAAE,EACnD,MAAM,wBAAyB,CAAC,MAAO,CAAE,CAAC,EAEtD,OAAO,KAAK,kBAAkB,GAIhC,GAAI,CAAC,KAAK,SAAS,QAAQ,CAAE,EAE3B,MADA,EAAO,SAAS,iBAAkB,uBAAwB,CAAE,EAClD,MAAM,uBAAwB,CAAC,MAAO,CAAE,CAAC,EAGrD,IAAM,EAAY,KAAK,SAAS,YAAY,CAAE,EAE9C,GAAI,EAAU,MAAQ,EAAc,WAElC,MADA,EAAO,SAAS,iBAAkB,wBAAyB,CAAE,EACnD,MAAM,uBAAwB,CAAC,MAAO,CAAE,CAAC,EAGrD,IAAM,EAAU,MAAM,KAAK,cAAwC,CAAS,EACtE,EAAS,EAAoB,kBAAkB,EAAS,KAAK,aAAa,EAEhF,OADA,KAAK,kBAAkB,GAAM,EACtB,EAaF,WAAW,CAAC,EAA4B,CAC7C,IAAM,EAAM,EAAW,CAAO,EAC9B,EAAO,gBAAgB,cAAe,CAAG,EACzC,IAAM,EAAM,KAAK,kBAAkB,GACnC,GAAI,IAAQ,OAAW,OACvB,GAAI,EAAI,yBAA2B,GACjC,EAAI,eAAiB,GACrB,KAAK,cAAc,CAAG,EAExB,OAAO,KAAK,kBAAkB,QAiBnB,YAAW,CAAC,EAAqC,CAC5D,IAAM,EAAM,EAAW,CAAO,EAE9B,GADA,EAAO,gBAAgB,cAAe,CAAG,EACrC,CAAC,KAAK,SAAS,QAAQ,CAAG,EAE5B,MADA,EAAO,SAAS,cAAe,qBAAsB,CAAG,EAC9C,MAAM,qBAAsB,CAAC,MAAO,CAAG,CAAC,EAEpD,IAAM,EAAM,KAAK,kBAAkB,GACnC,GAAI,IAAQ,OAEV,EAAI,OAAS,GACb,EAAI,eAAiB,GACrB,EAAI,uBAAyB,GAC7B,OAAO,KAAK,kBAAkB,GAEhC,IAAM,EAAO,EAAa,KAAK,SAAS,YAAY,CAAG,CAAC,EACxD,KAAK,SAAS,WAAW,CAAG,EAC5B,MAAM,EAAM,GAAG,CAAC,EAChB,GAAI,CACF,MAAM,EAAO,EAAQ,KAAK,OAAO,SAAU,CAAI,CAAC,EAElD,MAAO,EAAO,CACZ,EAAO,MAAM,cAAe,qBAAsB,EAAO,CAAC,GAAI,EAAS,MAAI,CAAC,QAanE,QAAO,EAAkB,CACpC,EAAO,YAAY,SAAS,EAC5B,QAAW,KAAO,OAAO,OAAO,KAAK,iBAAiB,EACpD,GAAI,EAAI,yBAA2B,IAAQ,EAAI,SAAW,GACxD,EAAI,eAAiB,GACrB,MAAM,KAAK,cAAc,CAAG,OAWpB,cAAyC,CAAC,EAA0C,CAChG,GAAI,OAAO,IAAS,SAAU,EAAO,EAAa,CAAI,EACtD,EAAO,gBAAgB,gBAAiB,CAAI,EAC5C,EAAO,OAAO,qBAAqB,IAAO,EAC1C,IAAM,EAAW,MAAM,EAAS,EAAQ,KAAK,OAAO,SAAU,CAAI,CAAC,EAEnE,OADA,EAAO,UAAU,qBAAqB,IAAO,EACtC,EAYD,cAA0C,CAAC,EAA8B,EAA2B,CAC1G,GAAI,OAAO,IAAS,SAAU,EAAO,EAAa,CAAI,EAEtD,OADA,EAAO,gBAAgB,iBAAkB,CAAI,EACtC,EAAU,EAAQ,KAAK,OAAO,SAAU,CAAI,EAAG,CAAO,OAS/C,cAAmC,CAAC,EAAoE,CACtH,EAAO,gBAAgB,iBAAkB,EAAK,EAAE,EAChD,IAAM,EAAM,EAAK,aAAa,EAAE,IAChC,GAAI,CAEF,GADA,MAAM,KAAK,eAAe,EAAK,KAAM,EAAK,gBAAgB,CAAC,EACvD,IAAQ,EAAK,aAAa,EAAE,IAE9B,EAAK,uBAAyB,GAGlC,MAAO,EAAO,CACZ,EAAO,MAAM,iBAAkB,uBAAwB,CAAC,GAAI,EAAK,GAAI,OAAK,CAAC,GAOvE,YAAY,EAAuC,CACzD,EAAO,YAAY,cAAc,EACjC,IAAM,EAAW,EAAQ,KAAK,OAAO,SAAU,EAAa,EAAgB,YAAY,CAAC,EACzF,GAAI,CAAC,EAAW,CAAQ,EAAG,CACzB,GAAI,KAAK,OAAO,0BAA4B,GAC1C,MAAU,MAAM,kBAAmB,CAAC,MAAO,2BAA2B,CAAC,EAIzE,OADA,EAAO,OAAO,iCAAiC,EACxC,EAAoB,eAAe,EAAgB,aAAc,KAAK,aAAa,EAG5F,IAAM,EAAU,EAA2C,EAAU,EAAI,EACzE,OAAO,EAAoB,kBAAkB,EAAS,KAAK,cAAe,SAAS,EAM7E,UAAU,EAAS,CACzB,EAAO,YAAY,YAAY,EAC/B,QAAW,KAAO,OAAO,OAAO,KAAK,iBAAiB,EAEpD,GADA,EAAO,cAAc,aAAa,EAAI,2BAA4B,EAAI,sBAAsB,EACxF,EAAI,yBAA2B,IAAQ,EAAI,SAAW,GACxD,EAAO,WAAW,aAAc,yBAA0B,CAAC,GAAI,EAAI,EAAE,CAAC,EACtE,EAAU,EAAQ,KAAK,OAAO,SAAU,EAAI,IAAI,EAAG,EAAI,gBAAgB,EAAG,EAAI,EAC9E,EAAI,uBAAyB,GAgB5B,YAAY,EAAuD,CAExE,OADA,EAAO,YAAY,cAAc,EAC1B,KAAK,SAAS,OAAO,EAEhC",
9
+ "debugId": "C1C6087927638DC864756E2164756E21",
10
+ "names": []
11
+ }
package/package.json CHANGED
@@ -1,36 +1,68 @@
1
1
  {
2
2
  "name": "@alwatr/nitrobase-engine",
3
+ "version": "9.1.0",
3
4
  "description": "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-performance accelerated Nginx server.",
4
- "version": "7.10.1",
5
- "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
6
- "bugs": "https://github.com/Alwatr/nitrobase/issues",
7
- "dependencies": {
8
- "@alwatr/delay": "^6.0.18",
9
- "@alwatr/exit-hook": "^5.5.26",
10
- "@alwatr/logger": "^6.0.15",
11
- "@alwatr/nitrobase-helper": "^7.10.1",
12
- "@alwatr/nitrobase-reference": "^7.10.1",
13
- "@alwatr/nitrobase-types": "^7.10.1",
14
- "@alwatr/node-fs": "^5.5.29",
15
- "@alwatr/type-helper": "^7.0.0"
16
- },
17
- "devDependencies": {
18
- "@alwatr/nanolib": "^7.3.4",
19
- "@types/node": "^24.10.4",
20
- "typescript": "^5.9.3"
5
+ "license": "MPL-2.0",
6
+ "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com> (https://ali.mihandoost.com)",
7
+ "type": "module",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Alwatr/alwatr",
11
+ "directory": "pkg/nitrobase-old/engine"
21
12
  },
13
+ "homepage": "https://github.com/Alwatr/alwatr/tree/main/pkg/nitrobase-old/engine#readme",
14
+ "bugs": "https://github.com/Alwatr/alwatr/issues",
22
15
  "exports": {
23
16
  ".": {
24
17
  "types": "./dist/main.d.ts",
25
- "import": "./dist/main.mjs",
26
- "require": "./dist/main.cjs"
18
+ "import": "./dist/main.js",
19
+ "default": "./dist/main.js"
27
20
  }
28
21
  },
22
+ "sideEffects": false,
23
+ "dependencies": {
24
+ "@alwatr/delay": "9.1.0",
25
+ "@alwatr/exit-hook": "9.1.0",
26
+ "@alwatr/logger": "9.1.0",
27
+ "@alwatr/nitrobase-helper": "^9.1.0",
28
+ "@alwatr/nitrobase-reference": "^9.1.0",
29
+ "@alwatr/nitrobase-types": "^9.1.0",
30
+ "@alwatr/node-fs": "9.1.0",
31
+ "@alwatr/type-helper": "9.1.0"
32
+ },
33
+ "devDependencies": {
34
+ "@alwatr/nano-build": "9.1.0",
35
+ "@alwatr/tsconfig-base": "9.1.0",
36
+ "@alwatr/type-helper": "workspace:*",
37
+ "@types/node": "^25.5.0",
38
+ "typescript": "^6.0.2"
39
+ },
40
+ "scripts": {
41
+ "b": "bun run build",
42
+ "build": "bun run build:ts && bun run build:es",
43
+ "build:es": "nano-build --preset=module src/main.ts",
44
+ "build:ts": "tsc --build",
45
+ "cl": "bun run clean",
46
+ "clean": "rm -rfv dist *.tsbuildinfo",
47
+ "format": "prettier --write \"src/**/*.ts\"",
48
+ "lint": "eslint src/ --ext .ts",
49
+ "t": "bun run test",
50
+ "test": "ALWATR_DEBUG=0 bun test",
51
+ "w": "bun run watch",
52
+ "watch": "bun run watch:ts & bun run watch:es",
53
+ "watch:es": "bun run build:es --watch",
54
+ "watch:ts": "bun run build:ts --watch --preserveWatchOutput"
55
+ },
29
56
  "files": [
30
- "**/*.{js,mjs,cjs,map,d.ts,html,md}",
31
- "!demo/**/*"
57
+ "dist",
58
+ "src/**/*.ts",
59
+ "!src/**/*.test.ts",
60
+ "README.md",
61
+ "LICENSE"
32
62
  ],
33
- "homepage": "https://github.com/Alwatr/nitrobase/tree/next/packages/engine#readme",
63
+ "publishConfig": {
64
+ "access": "public"
65
+ },
34
66
  "keywords": [
35
67
  "alwatr",
36
68
  "data",
@@ -44,34 +76,6 @@
44
76
  "storage",
45
77
  "typescript"
46
78
  ],
47
- "license": "MPL-2.0",
48
- "main": "./dist/main.cjs",
49
- "module": "./dist/main.mjs",
50
79
  "prettier": "@alwatr/nanolib/prettier-config",
51
- "publishConfig": {
52
- "access": "public"
53
- },
54
- "repository": {
55
- "type": "git",
56
- "url": "https://github.com/Alwatr/nitrobase",
57
- "directory": "packages/engine"
58
- },
59
- "scripts": {
60
- "b": "yarn run build",
61
- "build": "yarn run build:ts & yarn run build:es",
62
- "build:es": "nano-build --preset=module",
63
- "build:ts": "tsc --build",
64
- "c": "yarn run clean",
65
- "cb": "yarn run clean && yarn run build",
66
- "clean": "rm -rfv dist *.tsbuildinfo",
67
- "d": "yarn node --enable-source-maps --trace-warnings",
68
- "w": "yarn run watch",
69
- "watch": "yarn run watch:ts & yarn run watch:es",
70
- "watch:es": "yarn run build:es --watch",
71
- "watch:ts": "yarn run build:ts --watch --preserveWatchOutput"
72
- },
73
- "sideEffects": false,
74
- "type": "module",
75
- "types": "./dist/main.d.ts",
76
- "gitHead": "e23943a279d6b0905b205c0c17b2b3249efab226"
80
+ "gitHead": "4a25cd3e0499cf61dd761e87d3711abf9b0cd208"
77
81
  }
@@ -0,0 +1,498 @@
1
+ import {delay} from '@alwatr/delay';
2
+ import {exitHook} from '@alwatr/exit-hook';
3
+ import {getStoreId, getStorePath} from '@alwatr/nitrobase-helper';
4
+ import {CollectionReference, DocumentReference} from '@alwatr/nitrobase-reference';
5
+ import {
6
+ StoreFileType,
7
+ StoreFileExtension,
8
+ Region,
9
+ type StoreFileStat,
10
+ type StoreFileContext,
11
+ type CollectionContext,
12
+ type DocumentContext,
13
+ type StoreFileId,
14
+ type CollectionItem,
15
+ } from '@alwatr/nitrobase-types';
16
+ import {existsSync, readJson, resolve, unlink, writeJson} from '@alwatr/node-fs';
17
+
18
+ import {logger} from './logger.js';
19
+
20
+
21
+ __dev_mode__: logger.logFileModule?.('alwatr-nitrobase');
22
+
23
+ /**
24
+ * AlwatrNitrobase configuration.
25
+ */
26
+ export interface AlwatrNitrobaseConfig {
27
+ /**
28
+ * The root path of the storage.
29
+ * This is where the AlwatrNitrobase will nitrobase its data.
30
+ */
31
+ rootPath: string;
32
+
33
+ /**
34
+ * The save debounce timeout in milliseconds for minimal disk I/O usage.
35
+ * This is used to limit the frequency of disk writes for performance reasons.
36
+ * The recommended value is `40`.
37
+ */
38
+ defaultChangeDebounce?: number;
39
+
40
+ /**
41
+ * If true, an error will be thrown when trying to read or write to a nitrobase file that is not initialized (new storage).
42
+ * The default value is `false` but highly recommended to set it to `true` in production to prevent data loss.
43
+ */
44
+ errorWhenNotInitialized?: boolean;
45
+ }
46
+
47
+ /**
48
+ * AlwatrNitrobase engine.
49
+ *
50
+ * It provides methods to read, write, validate, and manage nitrobase files.
51
+ * It also provides methods to interact with `documents` and `collections` in the nitrobase.
52
+ */
53
+ export class AlwatrNitrobase {
54
+ /**
55
+ * The Alwatr Nitrobase version string.
56
+ *
57
+ * Use for nitrobase file format version for check compatibility.
58
+ */
59
+ public static readonly version = __package_version__;
60
+
61
+ /**
62
+ * The root nitrobase file stat.
63
+ */
64
+ private static readonly rootDbStat__: StoreFileStat = {
65
+ name: '.nitrobase',
66
+ region: Region.Secret,
67
+ type: StoreFileType.Collection,
68
+ extension: StoreFileExtension.Json,
69
+ changeDebounce: 40,
70
+ };
71
+
72
+ /**
73
+ * `collectionReference` of all `storeFileStat`s.
74
+ * This is the root nitrobase collection.
75
+ */
76
+ private rootDb__;
77
+
78
+ /**
79
+ * Keep all loaded nitrobase file context loaded in memory.
80
+ */
81
+ private cacheReferences__: DictionaryReq<DocumentReference | CollectionReference> = {};
82
+
83
+ /**
84
+ * Constructs an AlwatrNitrobase instance with the provided configuration.
85
+ *
86
+ * @param config The configuration of the AlwatrNitrobase engine.
87
+ * @example
88
+ * ```typescript
89
+ * const alwatrStore = new AlwatrNitrobase({
90
+ * rootPath: './db',
91
+ * saveDebounce: 40,
92
+ * });
93
+ * ```
94
+ */
95
+ constructor(public readonly config: AlwatrNitrobaseConfig) {
96
+ this.storeChanged_ = this.storeChanged_.bind(this);
97
+
98
+ logger.logMethodArgs?.('new', config);
99
+ this.config.defaultChangeDebounce ??= 40;
100
+ this.rootDb__ = this.loadRootDb__();
101
+ exitHook(this.exitHook__.bind(this));
102
+ }
103
+
104
+ /**
105
+ * Checks if a nitrobase file with the given ID exists.
106
+ *
107
+ * @param storeId - The ID of the nitrobase file to check.
108
+ * @returns `true` if the nitrobase file exists, `false` otherwise.
109
+ * @example
110
+ * ```typescript
111
+ * if (!alwatrStore.hasStore('user1/profile')) {
112
+ * alwatrStore.defineDocument(...)
113
+ * }
114
+ * ```
115
+ */
116
+ public hasStore(storeId: StoreFileId): boolean {
117
+ const id_ = getStoreId(storeId);
118
+ const exists = this.rootDb__.hasItem(id_);
119
+ logger.logMethodFull?.('hasStore', id_, exists);
120
+ return exists;
121
+ }
122
+
123
+ /**
124
+ * Defines a new document with the given configuration and initial data.
125
+ * If a document with the same ID already exists, an error is thrown.
126
+ *
127
+ * @param stat nitrobase file stat
128
+ * @param data initial data for the document
129
+ * @template TDoc document data type
130
+ * @example
131
+ * ```typescript
132
+ * await alwatrStore.newDocument<Order>(
133
+ * {
134
+ * name: 'profile',
135
+ * region: Region.PerUser,
136
+ * ownerId: 'user1',
137
+ * },
138
+ * {
139
+ * name: 'Ali',
140
+ * email: 'ali@alwatr.io',
141
+ * }
142
+ * );
143
+ * ```
144
+ */
145
+ public newDocument<TDoc extends JsonObject = JsonObject>(stat: Omit<StoreFileStat, 'type'>, data: TDoc): void {
146
+ logger.logMethodArgs?.('newDocument', stat);
147
+ return this.newStoreFile__(
148
+ {
149
+ ...stat,
150
+ type: StoreFileType.Document,
151
+ },
152
+ data,
153
+ );
154
+ }
155
+
156
+ /**
157
+ * Defines a new collection with the given configuration and initial data.
158
+ * If a collection with the same ID already exists, an error is thrown.
159
+ *
160
+ * @param stat nitrobase file stat
161
+ * @example
162
+ * ```typescript
163
+ * await alwatrStore.newCollection<Order>(
164
+ * {
165
+ * name: 'orders',
166
+ * region: Region.PerUser,
167
+ * ownerId: 'user1',
168
+ * }
169
+ * );
170
+ * ```
171
+ */
172
+ public newCollection(stat: Omit<StoreFileStat, 'type'>): void {
173
+ logger.logMethodArgs?.('newCollection', stat);
174
+ return this.newStoreFile__({
175
+ ...stat,
176
+ type: StoreFileType.Collection,
177
+ });
178
+ }
179
+
180
+ /**
181
+ * Defines a AlwatrNitrobaseFile with the given configuration and initial data.
182
+ *
183
+ * @param stat nitrobase file stat
184
+ * @param data initial data for the document
185
+ */
186
+ private newStoreFile__(stat: StoreFileStat, data?: DictionaryOpt): void {
187
+ logger.logMethodArgs?.('newStoreFile__', stat);
188
+
189
+ (stat.changeDebounce as number | undefined) ??= this.config.defaultChangeDebounce;
190
+
191
+ let fileStoreRef: DocumentReference | CollectionReference;
192
+ if (stat.type === StoreFileType.Document) {
193
+ if (data === undefined) {
194
+ logger.accident('newStoreFile__', 'document_data_required', stat);
195
+ throw new Error('document_data_required', {cause: stat});
196
+ }
197
+ fileStoreRef = DocumentReference.newRefFromData(stat, data, this.storeChanged_);
198
+ }
199
+ else if (stat.type === StoreFileType.Collection) {
200
+ fileStoreRef = CollectionReference.newRefFromData(stat, this.storeChanged_);
201
+ }
202
+ else {
203
+ logger.accident('newStoreFile__', 'store_file_type_not_supported', stat);
204
+ throw new Error('store_file_type_not_supported', {cause: stat});
205
+ }
206
+
207
+ if (this.rootDb__.hasItem(fileStoreRef.id)) {
208
+ logger.accident('newStoreFile__', 'store_file_already_defined', stat);
209
+ throw new Error('store_file_already_defined', {cause: stat});
210
+ }
211
+
212
+ this.rootDb__.addItem(fileStoreRef.id, stat);
213
+ this.cacheReferences__[fileStoreRef.id] = fileStoreRef;
214
+
215
+ // fileStoreRef.save();
216
+ this.storeChanged_(fileStoreRef);
217
+ }
218
+
219
+ /**
220
+ * Open a document with the given id and create and return a DocumentReference.
221
+ * If the document not exists or its not a document, an error is thrown.
222
+ *
223
+ * @template TDoc document data type
224
+ * @param documentId document id {@link StoreFileId}
225
+ * @returns document reference {@link DocumentReference}
226
+ * @example
227
+ * ```typescript
228
+ * const userProfile = await alwatrStore.openDocument<User>({
229
+ * name: 'user1/profile',
230
+ * region: Region.PerUser,
231
+ * ownerId: 'user1',
232
+ * });
233
+ * userProfile.update({name: 'ali'});
234
+ * ```
235
+ */
236
+ public async openDocument<TDoc extends JsonObject>(documentId: StoreFileId): Promise<DocumentReference<TDoc>> {
237
+ const id = getStoreId(documentId);
238
+ logger.logMethodArgs?.('openDocument', id);
239
+
240
+ if (Object.hasOwn(this.cacheReferences__, id)) {
241
+ const ref = this.cacheReferences__[id];
242
+ if (!(ref instanceof DocumentReference)) {
243
+ logger.accident('openDocument', 'document_wrong_type', id);
244
+ throw new Error('document_wrong_type', {cause: id});
245
+ }
246
+ return this.cacheReferences__[id] as unknown as DocumentReference<TDoc>;
247
+ }
248
+
249
+ if (!this.rootDb__.hasItem(id)) {
250
+ logger.accident('openDocument', 'document_not_found', id);
251
+ throw new Error('document_not_found', {cause: id});
252
+ }
253
+
254
+ const storeStat = this.rootDb__.getItemData(id);
255
+
256
+ if (storeStat.type != StoreFileType.Document) {
257
+ logger.accident('openDocument', 'document_wrong_type', id);
258
+ throw new Error('document_wrong_type', {cause: id});
259
+ }
260
+
261
+ const context = await this.readContext__<DocumentContext<TDoc>>(storeStat);
262
+ const docRef = DocumentReference.newRefFromContext(context, this.storeChanged_);
263
+ this.cacheReferences__[id] = docRef as unknown as DocumentReference;
264
+ return docRef;
265
+ }
266
+
267
+ /**
268
+ * Open a collection with the given id and create and return a CollectionReference.
269
+ * If the collection not exists or its not a collection, an error is thrown.
270
+ *
271
+ * @template TItem collection item data type
272
+ * @param collectionId collection id {@link StoreFileId}
273
+ * @returns collection reference {@link CollectionReference}
274
+ * @example
275
+ * ```typescript
276
+ * const orders = await alwatrStore.openCollection<Order>({
277
+ * name: 'orders',
278
+ * region: Region.PerUser,
279
+ * ownerId: 'user1',
280
+ * });
281
+ * orders.append({name: 'order 1'});
282
+ * ```
283
+ */
284
+ public async openCollection<TItem extends JsonObject>(collectionId: StoreFileId): Promise<CollectionReference<TItem>> {
285
+ const id = getStoreId(collectionId);
286
+ logger.logMethodArgs?.('openCollection', id);
287
+
288
+ // try to get from cache
289
+ if (Object.hasOwn(this.cacheReferences__, id)) {
290
+ const ref = this.cacheReferences__[id];
291
+ if (!(ref instanceof CollectionReference)) {
292
+ logger.accident('openCollection', 'collection_wrong_type', id);
293
+ throw new Error('collection_wrong_type', {cause: id});
294
+ }
295
+ return this.cacheReferences__[id] as unknown as CollectionReference<TItem>;
296
+ }
297
+
298
+ // load and create new collection reference
299
+ if (!this.rootDb__.hasItem(id)) {
300
+ logger.accident('openCollection', 'collection_not_found', id);
301
+ throw new Error('collection_not_found', {cause: id});
302
+ }
303
+
304
+ const storeStat = this.rootDb__.getItemData(id);
305
+
306
+ if (storeStat.type != StoreFileType.Collection) {
307
+ logger.accident('openCollection', 'collection_wrong_type', id);
308
+ throw new Error('collection_not_found', {cause: id});
309
+ }
310
+
311
+ const context = await this.readContext__<CollectionContext<TItem>>(storeStat);
312
+ const colRef = CollectionReference.newRefFromContext(context, this.storeChanged_);
313
+ this.cacheReferences__[id] = colRef as unknown as CollectionReference;
314
+ return colRef;
315
+ }
316
+
317
+ /**
318
+ * Unloads the nitrobase file with the given id from memory.
319
+ *
320
+ * @param storeId The unique identifier of the nitrobase file. {@link StoreFileId}
321
+ * @example
322
+ * ```typescript
323
+ * alwatrStore.unloadStore({name: 'user-list', region: Region.Secret});
324
+ * alwatrStore.hasStore({name: 'user-list', region: Region.Secret}); // true
325
+ * ```
326
+ */
327
+ public unloadStore(storeId: StoreFileId): void {
328
+ const id_ = getStoreId(storeId);
329
+ logger.logMethodArgs?.('unloadStore', id_);
330
+ const ref = this.cacheReferences__[id_];
331
+ if (ref === undefined) return;
332
+ if (ref.hasUnprocessedChanges_ === true) {
333
+ ref.updateDelayed_ = false;
334
+ this.storeChanged_(ref);
335
+ }
336
+ delete this.cacheReferences__[id_];
337
+ }
338
+
339
+ /**
340
+ * Remove document or collection from nitrobase and delete the file from disk.
341
+ * If the file is not found, an error is thrown.
342
+ * If the file is not unloaded, it will be unloaded first.
343
+ * You don't need to await this method to complete unless you want to make sure the file is deleted on disk.
344
+ *
345
+ * @param storeId The ID of the file to delete. {@link StoreFileId}
346
+ * @returns A Promise that resolves when the file is deleted.
347
+ * @example
348
+ * ```typescript
349
+ * alwatrStore.removeStore({name: 'user-list', region: Region.Secret});
350
+ * alwatrStore.hasStore({name: 'user-list', region: Region.Secret}); // false
351
+ * ```
352
+ */
353
+ public async removeStore(storeId: StoreFileId): Promise<void> {
354
+ const id_ = getStoreId(storeId);
355
+ logger.logMethodArgs?.('removeStore', id_);
356
+ if (!this.rootDb__.hasItem(id_)) {
357
+ logger.accident('removeStore', 'document_not_found', id_);
358
+ throw new Error('document_not_found', {cause: id_});
359
+ }
360
+ const ref = this.cacheReferences__[id_];
361
+ if (ref !== undefined) {
362
+ // direct unload to prevent save
363
+ ref.freeze = true;
364
+ ref.updateDelayed_ = false;
365
+ ref.hasUnprocessedChanges_ = false;
366
+ delete this.cacheReferences__[id_]; // unload
367
+ }
368
+ const path = getStorePath(this.rootDb__.getItemData(id_));
369
+ this.rootDb__.removeItem(id_);
370
+ await delay.by(0);
371
+ try {
372
+ await unlink(resolve(this.config.rootPath, path));
373
+ }
374
+ catch (error) {
375
+ logger.error('removeStore', 'remove_file_failed', error, {id: storeId, path});
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Saves all changes in the nitrobase.
381
+ *
382
+ * @returns A Promise that resolves when all changes are saved.
383
+ * @example
384
+ * ```typescript
385
+ * await alwatrStore.saveAll();
386
+ * ```
387
+ */
388
+ public async saveAll(): Promise<void> {
389
+ logger.logMethod?.('saveAll');
390
+ for (const ref of Object.values(this.cacheReferences__)) {
391
+ if (ref.hasUnprocessedChanges_ === true && ref.freeze !== true) {
392
+ ref.updateDelayed_ = false;
393
+ await this.storeChanged_(ref);
394
+ }
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Reads the context from a given path or StoreFileStat object.
400
+ *
401
+ * @param path The path or StoreFileStat object from which to read the context.
402
+ * @returns A promise that resolves to the context object.
403
+ */
404
+ private async readContext__<T extends StoreFileContext>(path: string | StoreFileStat): Promise<T> {
405
+ if (typeof path !== 'string') path = getStorePath(path);
406
+ logger.logMethodArgs?.('readContext__', path);
407
+ logger.time?.(`readContext__time(${path})`);
408
+ const context = (await readJson(resolve(this.config.rootPath, path))) as T;
409
+ logger.timeEnd?.(`readContext__time(${path})`);
410
+ return context;
411
+ }
412
+
413
+ /**
414
+ * Writes the context to the specified path.
415
+ *
416
+ * @template T The type of the context.
417
+ * @param path The path where the context will be written.
418
+ * @param context The context to be written.
419
+ * @param sync Indicates whether the write operation should be synchronous.
420
+ * @returns A promise that resolves when the write operation is complete.
421
+ */
422
+ private writeContext__<T extends StoreFileContext>(path: string | StoreFileStat, context: T): Promise<void> {
423
+ if (typeof path !== 'string') path = getStorePath(path);
424
+ logger.logMethodArgs?.('writeContext__', path);
425
+ return writeJson(resolve(this.config.rootPath, path), context);
426
+ }
427
+
428
+ /**
429
+ * Write nitrobase file context.
430
+ *
431
+ * @param from nitrobase file reference
432
+ * @returns A promise that resolves when the write operation is complete.
433
+ */
434
+ protected async storeChanged_<T extends JsonObject>(from: DocumentReference<T> | CollectionReference<T>): Promise<void> {
435
+ logger.logMethodArgs?.('storeChanged__', from.id);
436
+ const rev = from.getStoreMeta().rev;
437
+ try {
438
+ await this.writeContext__(from.path, from.getFullContext_());
439
+ if (rev === from.getStoreMeta().rev) {
440
+ // Context not changed during saving
441
+ from.hasUnprocessedChanges_ = false;
442
+ }
443
+ }
444
+ catch (error) {
445
+ logger.error('storeChanged__', 'write_context_failed', {id: from.id, error});
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Load storeFilesCollection or create new one.
451
+ */
452
+ private loadRootDb__(): CollectionReference<StoreFileStat> {
453
+ logger.logMethod?.('loadRootDb__');
454
+ const fullPath = resolve(this.config.rootPath, getStorePath(AlwatrNitrobase.rootDbStat__));
455
+ if (!existsSync(fullPath)) {
456
+ if (this.config.errorWhenNotInitialized === true) {
457
+ throw new Error('store_not_found', {cause: 'Nitrobase not initialized'});
458
+ }
459
+
460
+ logger.banner('Initialize new alwatr-nitrobase');
461
+ return CollectionReference.newRefFromData(AlwatrNitrobase.rootDbStat__, this.storeChanged_);
462
+ }
463
+ // else
464
+ const context = readJson<CollectionContext<StoreFileStat>>(fullPath, true);
465
+ return CollectionReference.newRefFromContext(context, this.storeChanged_, 'root-db');
466
+ }
467
+
468
+ /**
469
+ * Save all nitrobase files.
470
+ */
471
+ private exitHook__(): void {
472
+ logger.logMethod?.('exitHook__');
473
+ for (const ref of Object.values(this.cacheReferences__)) {
474
+ logger.logProperty?.(`StoreFile.${ref.id}.hasUnprocessedChanges`, ref.hasUnprocessedChanges_);
475
+ if (ref.hasUnprocessedChanges_ === true && ref.freeze !== true) {
476
+ logger.incident?.('exitHook__', 'rescue_unsaved_context', {id: ref.id});
477
+ writeJson(resolve(this.config.rootPath, ref.path), ref.getFullContext_(), true);
478
+ ref.hasUnprocessedChanges_ = false;
479
+ }
480
+ }
481
+ }
482
+
483
+ /**
484
+ * Get all nitrobase files.
485
+ *
486
+ * @returns all nitrobase files.
487
+ * @example
488
+ * ```typescript
489
+ * const storeList = alwatrStore.getStoreList();
490
+ * for (const nitrobase of storeList) {
491
+ * console.log(nitrobase.meta.id, nitrobase.data);
492
+ * }
493
+ */
494
+ public getStoreList(): CollectionItem<Omit<StoreFileStat, 'schemaVer'>>[] {
495
+ logger.logMethod?.('getStoreList');
496
+ return this.rootDb__.values();
497
+ }
498
+ }
package/src/logger.ts ADDED
@@ -0,0 +1,4 @@
1
+ import {createLogger} from '@alwatr/logger';
2
+
3
+
4
+ export const logger = /* #__PURE__ */ createLogger(__package_name__);
package/src/main.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './alwatr-nitrobase.js';
package/CHANGELOG.md DELETED
@@ -1,351 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ## [7.10.1](https://github.com/Alwatr/nitrobase/compare/v7.10.0...v7.10.1) (2025-12-14)
7
-
8
- ### 🧹 Miscellaneous Chores
9
-
10
- * update tsconfig extends to use @alwatr/nanolib ([ffbc8ce](https://github.com/Alwatr/nitrobase/commit/ffbc8ce74d47d7f4e1ff0061722df10f68af11cc))
11
-
12
- ### 🔗 Dependencies update
13
-
14
- * replace '@alwatr/nano-build' with '@alwatr/nanolib' in logger imports ([9a355b9](https://github.com/Alwatr/nitrobase/commit/9a355b92b27434a3cd132e7e52df5c2e112ca97e))
15
- * update `@alwatr/nanolib` and `@types/node` dependencies across all packages. ([bc6d96f](https://github.com/Alwatr/nitrobase/commit/bc6d96f4fd423bcfb817d74b526596669d8a8aed))
16
- * update dependencies and switch prettier config to @alwatr/nanolib ([e2c9ffb](https://github.com/Alwatr/nitrobase/commit/e2c9ffb5f62d88a1ddaef77886d41c0cb7df604d))
17
-
18
- ## [7.10.0](https://github.com/Alwatr/nitrobase/compare/v7.9.0...v7.10.0) (2025-09-21)
19
-
20
- ### 🐛 Bug Fixes
21
-
22
- * add "sideEffects": false to package.json files for better tree-shaking ([cb6f75b](https://github.com/Alwatr/nitrobase/commit/cb6f75b86eb7dba6812aaad5136fcd867e885562))
23
- * add type imports for nano-build and type-helper in logger files ([6ca3627](https://github.com/Alwatr/nitrobase/commit/6ca362761c0d30a2813369bda49c927960c787f8))
24
-
25
- ### 🔨 Code Refactoring
26
-
27
- * rename newStoreFile_ to newStoreFile__ for consistency in AlwatrNitrobase class ([2010994](https://github.com/Alwatr/nitrobase/commit/201099488a9bd379a67355df0c26fbef205626bd))
28
- * update access modifiers to public for class properties and methods in nitrobase and user management ([a988d63](https://github.com/Alwatr/nitrobase/commit/a988d63b61828f6ce360e7179cbaccfa19dc1ae2))
29
-
30
- ### 🧹 Miscellaneous Chores
31
-
32
- * remove Exir Studio sponsorship logo from multiple README files ([506459f](https://github.com/Alwatr/nitrobase/commit/506459fea7d29b97e478da562590dd202ce7e833))
33
- * remove unused types from tsconfig.json files and update references ([b504ced](https://github.com/Alwatr/nitrobase/commit/b504ced4a8f98de4fe79a2c974937278bd4e46cb))
34
- * Update license from AGPL-3.0 to MPL-2.0 ([af1746e](https://github.com/Alwatr/nitrobase/commit/af1746ee9a3786c1cb2e0014f138e9f3b7086b8d))
35
- * update package.json files across all packages for consistency and improved metadata ([647900d](https://github.com/Alwatr/nitrobase/commit/647900d9966f8df275c4e2ef0550c501be38ece0))
36
-
37
- ### 🔗 Dependencies update
38
-
39
- * add missing dependencies in package.json ([8fe3ae3](https://github.com/Alwatr/nitrobase/commit/8fe3ae36736564a0c56b8915cfcb52b4b00befc2))
40
- * remove unused packageTracer import and related code from logger.ts ([46ee9d8](https://github.com/Alwatr/nitrobase/commit/46ee9d80bb65299933c8f41631bad527ff206f38))
41
- * update dependencies in package.json files across all packages to latest versions ([72c20ef](https://github.com/Alwatr/nitrobase/commit/72c20efbc1cac9825fb4880772e3fad797d74a23))
42
- * update imports to use new package paths for improved modularity ([e59abcc](https://github.com/Alwatr/nitrobase/commit/e59abcce6d32fe3eee1c1f1b578a4b09794e95e6))
43
-
44
- ## [7.8.0](https://github.com/Alwatr/nitrobase/compare/v7.7.0...v7.8.0) (2025-03-06)
45
-
46
- ### Dependencies update
47
-
48
- * **deps-dev:** bump the dependencies group across 1 directory with 5 updates ([fe6ab37](https://github.com/Alwatr/nitrobase/commit/fe6ab37263f609f8bce8398462b7105b8e5a55fe)) by @dependabot[bot]
49
- * update @alwatr/nanolib, @alwatr/nano-build, and @alwatr/type-helper to latest versions ([5f3f89b](https://github.com/Alwatr/nitrobase/commit/5f3f89b1236f66e9167957d60d43c8d0abff108d)) by @
50
-
51
- ## [7.7.0](https://github.com/Alwatr/nitrobase/compare/v7.6.1...v7.7.0) (2025-02-26)
52
-
53
- **Note:** Version bump only for package @alwatr/nitrobase-engine
54
-
55
- ## [7.6.0](https://github.com/Alwatr/nitrobase/compare/v7.5.9...v7.6.0) (2025-02-26)
56
-
57
- ### Miscellaneous Chores
58
-
59
- * rollback all versions ([9ff6c11](https://github.com/Alwatr/nitrobase/commit/9ff6c11ef3e44ea669a814da73ed39ddc2c8e971)) by @alimd
60
-
61
- ## [7.5.8](https://github.com/Alwatr/nitrobase/compare/v7.5.7...v7.5.8) (2025-02-18)
62
-
63
- ### Dependencies update
64
-
65
- * bump @alwatr/nanolib, @alwatr/nano-build, and @types/node to latest versions across multiple packages ([3e89c62](https://github.com/Alwatr/nitrobase/commit/3e89c62ad20f3afe0c38c6ae36d91bcb6199b231)) by @
66
- * **deps-dev:** bump the dependencies group across 1 directory with 2 updates ([03715d0](https://github.com/Alwatr/nitrobase/commit/03715d0b5534b127dfb57ffe0ea713fb168eefe6)) by @dependabot[bot]
67
-
68
- ## [7.5.7](https://github.com/Alwatr/nitrobase/compare/v7.5.6...v7.5.7) (2025-02-03)
69
-
70
- ### Dependencies update
71
-
72
- * update [@alwatr](https://github.com/alwatr) dependencies to latest versions ([f8bb10f](https://github.com/Alwatr/nitrobase/commit/f8bb10fa3343f25e2a442e80fbddb88c55fac813)) by @
73
-
74
- ## [7.5.6](https://github.com/Alwatr/nitrobase/compare/v7.5.5...v7.5.6) (2025-02-03)
75
-
76
- ### Bug Fixes
77
-
78
- * bind storeChanged_ method in constructor for proper context ([#350](https://github.com/Alwatr/nitrobase/issues/350)) ([33cf076](https://github.com/Alwatr/nitrobase/commit/33cf0767fa6f78512b687580dc1260cf882c9197)) by @
79
-
80
- ## [7.5.5](https://github.com/Alwatr/nitrobase/compare/v7.5.4...v7.5.5) (2025-02-02)
81
-
82
- ### Dependencies update
83
-
84
- * **deps-dev:** bump @types/node ([d60ee96](https://github.com/Alwatr/nitrobase/commit/d60ee96716b8df7837b3d7f9fe4b8705c94e5af0)) by @dependabot[bot]
85
- * update ([0b9eccd](https://github.com/Alwatr/nitrobase/commit/0b9eccd3b54dade17e3eeb94bd08612c57356801)) by @alimd
86
-
87
- ## [7.5.4](https://github.com/Alwatr/nitrobase/compare/v7.5.3...v7.5.4) (2025-01-12)
88
-
89
- ### Bug Fixes
90
-
91
- * **nitrobase:** optional data in newStoreFile_ and throw Error when data not exist for document type ([6d2a173](https://github.com/Alwatr/nitrobase/commit/6d2a173ca4414d6928ef1b703dd0836648eb0787)) by @alimd
92
- * **nitrobase:** remove initialData parameter from newCollection method ([56cacf0](https://github.com/Alwatr/nitrobase/commit/56cacf0e65e8be2d68f4621eaf4e6d847bf39293)) by @alimd
93
- * **nitrobase:** required initial data for newDocument ([61f1788](https://github.com/Alwatr/nitrobase/commit/61f178850594ccfc0c1a4ab9429cc2e0438eb11c)) by @alimd
94
-
95
- ### Code Refactoring
96
-
97
- * **nitrobase:** bind storeChanged_ method directly instead of using bind in multiple locations ([dba1da6](https://github.com/Alwatr/nitrobase/commit/dba1da6bf095e6984af98d8e6c65c64fcc3fb5af)) by @alimd
98
-
99
- ### Dependencies update
100
-
101
- * **deps-dev:** bump the dependencies group across 1 directory with 11 updates ([fdd30a6](https://github.com/Alwatr/nitrobase/commit/fdd30a6639ae7ead4e8dbfaca0295cb2bf0e6649)) by @dependabot[bot]
102
-
103
- ## [7.5.0](https://github.com/Alwatr/nitrobase/compare/v7.4.1...v7.5.0) (2024-11-09)
104
-
105
- ### Code Refactoring
106
-
107
- * **engine:** make `config` as a public property ([6453540](https://github.com/Alwatr/nitrobase/commit/6453540aac42340cfe3b7ac9e4c26f904aaccdcc)) by @mohammadhonarvar
108
-
109
- ## [7.4.0](https://github.com/Alwatr/nitrobase/compare/v7.3.1...v7.4.0) (2024-11-08)
110
-
111
- ### Dependencies update
112
-
113
- * bump @alwatr/nanolib from 5.2.0 to 5.2.1 across multiple packages ([e1f87b0](https://github.com/Alwatr/nitrobase/commit/e1f87b07d33e8227440256a70f012aa63410f153)) by @
114
- * **deps-dev:** bump @types/node in the dependencies group ([67ffbad](https://github.com/Alwatr/nitrobase/commit/67ffbad06c95c304d47acbe46fd137fb4cf69f95)) by @dependabot[bot]
115
- * **deps:** bump @alwatr/nanolib from 5.0.0 to 5.2.0 in the alwatr group ([dfa1eef](https://github.com/Alwatr/nitrobase/commit/dfa1eefb191bbaac2ff2fff410bb1d3ec615d959)) by @dependabot[bot]
116
-
117
- ## [7.3.1](https://github.com/Alwatr/nitrobase/compare/v7.3.0...v7.3.1) (2024-11-02)
118
-
119
- ### Miscellaneous Chores
120
-
121
- * **deps-dev:** bump the development-dependencies group with 8 updates ([63f7adc](https://github.com/Alwatr/nitrobase/commit/63f7adc5ff83d4876f34d4f089a4be9b95b711a6)) by @dependabot[bot]
122
- * **deps:** bump the alwatr-dependencies group with 2 updates ([20fb436](https://github.com/Alwatr/nitrobase/commit/20fb436b9f146d5ec7452a693c7af8faa32bedff)) by @dependabot[bot]
123
-
124
- ### Dependencies update
125
-
126
- * **deps-dev:** bump @types/node in the dependencies group ([dd3e94a](https://github.com/Alwatr/nitrobase/commit/dd3e94a4c007da8fddda4cfeffe5f0763d74952e)) by @dependabot[bot]
127
- * **deps:** bump the alwatr group with 6 updates ([eb9eeb1](https://github.com/Alwatr/nitrobase/commit/eb9eeb1901f7947cde783bf6f06340c984d6f59d)) by @dependabot[bot]
128
-
129
- ## [7.3.0](https://github.com/Alwatr/nitrobase/compare/v7.2.1...v7.3.0) (2024-10-11)
130
-
131
- ### Features
132
-
133
- * update `import`s & packages based on the latest changes of `nanolib` & prevent side-effects ([0d66f89](https://github.com/Alwatr/nitrobase/commit/0d66f894dc4ff615ab73ebd27c275f98dc384fbe)) by @mohammadhonarvar
134
-
135
- ### Code Refactoring
136
-
137
- * update `import`s & packages based on the latest changes of `nanolib` ([ce990a2](https://github.com/Alwatr/nitrobase/commit/ce990a2fedc5545e971c3bb6e58b55bfba8c0bd9)) by @mohammadhonarvar
138
-
139
- ### Miscellaneous Chores
140
-
141
- * **deps-dev:** bump the development-dependencies group with 10 updates ([7bdcf3f](https://github.com/Alwatr/nitrobase/commit/7bdcf3f47ddb8e1376a1c7ae6e221811182bae58)) by @dependabot[bot]
142
- * **deps:** bump the alwatr-dependencies group with 10 updates ([60afdde](https://github.com/Alwatr/nitrobase/commit/60afdde98562f3023e6624ee0579d6bdee80bc32)) by @dependabot[bot]
143
- * **deps:** bump the alwatr-dependencies group with 6 updates ([1cf29b2](https://github.com/Alwatr/nitrobase/commit/1cf29b20055554945cd669ea9d022ab7c503d9fc)) by @dependabot[bot]
144
-
145
- ## [7.2.1](https://github.com/Alwatr/nitrobase/compare/v7.2.0...v7.2.1) (2024-09-29)
146
-
147
- ### Miscellaneous Chores
148
-
149
- * **deps-dev:** bump @types/node in the development-dependencies group ([9b146d2](https://github.com/Alwatr/nitrobase/commit/9b146d2f6cf7d1d79a2a6f46a5e8f50e7fb2ac75)) by @dependabot[bot]
150
- * **engine:** change the license to AGPL-3.0 ([f9d89d5](https://github.com/Alwatr/nitrobase/commit/f9d89d5de592b4df397c9b15156166aed90fa8d1)) by @ArmanAsadian
151
-
152
- ### Dependencies update
153
-
154
- * update ([90a0fe1](https://github.com/Alwatr/nitrobase/commit/90a0fe146eb703c183c116776d7c5748918282da)) by @
155
-
156
- ## [7.2.0](https://github.com/Alwatr/nitrobase/compare/v7.1.1...v7.2.0) (2024-09-24)
157
-
158
- ### Code Refactoring
159
-
160
- * rename all store to nitrobase ([0928420](https://github.com/Alwatr/nitrobase/commit/0928420d8751e16ff1e8d91e1d3048a5895885a6)) by @AliMD
161
- * rename all store to nitrobase ([9e31765](https://github.com/Alwatr/nitrobase/commit/9e31765b63ecd94bcf600cb44cfd9e341dd11a4e)) by @AliMD
162
-
163
- ## [7.1.1](https://github.com/Alwatr/nitrobase/compare/v7.1.0...v7.1.1) (2024-09-24)
164
-
165
- ### Miscellaneous Chores
166
-
167
- * **deps-dev:** bump the development-dependencies group across 1 directory with 3 updates ([122251c](https://github.com/Alwatr/nitrobase/commit/122251c315c422b7e9c2d5aba827f27b321194bb)) by @dependabot[bot]
168
- * **deps:** bump the alwatr-dependencies group with 9 updates ([2a94694](https://github.com/Alwatr/nitrobase/commit/2a94694b2ec12c2915aa77934023328751d13837)) by @dependabot[bot]
169
-
170
- ### Dependencies update
171
-
172
- * update ([82c475e](https://github.com/Alwatr/nitrobase/commit/82c475e29bd7f42ad03660556f40f180b3b6c9c6)) by @AliMD
173
-
174
- ## [7.1.0](https://github.com/Alwatr/nitrobase/compare/v7.0.0...v7.1.0) (2024-09-08)
175
-
176
- ### Features
177
-
178
- * **engine:** add @alwatr/nitrobase-helper package ([66bca93](https://github.com/Alwatr/nitrobase/commit/66bca93e46f344b54b6f9eb57f4a680247e36157)) by @AliMD
179
-
180
- ### Miscellaneous Chores
181
-
182
- * **deps-dev:** bump the development-dependencies group with 2 updates ([f6d8374](https://github.com/Alwatr/nitrobase/commit/f6d837417886ccf3719100570194434455fda365)) by @dependabot[bot]
183
-
184
- ## [7.0.0](https://github.com/Alwatr/nitrobase/compare/v7.0.0-beta.1...v7.0.0) (2024-09-02)
185
-
186
- ### Features
187
-
188
- * Add getStoreList method to AlwatrNitrobase ([25ace2a](https://github.com/Alwatr/nitrobase/commit/25ace2aa4e32d9ad99d6ac2e63ac783462b9f4e5)) by @AliMD
189
-
190
- ### Bug Fixes
191
-
192
- * **engine:** set the correct names ([076fa3e](https://github.com/Alwatr/nitrobase/commit/076fa3e0d7cfe673cc58418153b7dc2aacfb340a)) by @mohammadhonarvar
193
- * **packages/engine:** apply some new name of methods ([e3d5712](https://github.com/Alwatr/nitrobase/commit/e3d5712e19406f58fb87b822e036df5847aab6c0)) by @mohammadhonarvar
194
-
195
- ### Code Refactoring
196
-
197
- * **engine:** use `hasItem` ([e17afa7](https://github.com/Alwatr/nitrobase/commit/e17afa7ef050cbf9f349dd6919739a01764aa24f)) by @mohammadhonarvar
198
- * move all demo from engine to srore package ([e34fc49](https://github.com/Alwatr/nitrobase/commit/e34fc49c71703cd287559ca4fb23f9f13842b2d0)) by @AliMD
199
- * Remove unused "ALWATR_DEBUG" environment variable from build script ([26e7642](https://github.com/Alwatr/nitrobase/commit/26e764280e0a2827904762ed3de21a9966ddfc63)) by @AliMD
200
- * Replace id_ with documentId and collectionId in AlwatrNitrobase ([e58d0fd](https://github.com/Alwatr/nitrobase/commit/e58d0fd905722352238e11ed4e308907485f8ff5)) by @AliMD
201
- * Update type imports in alwatr-nitrobase.ts ([d6f02ad](https://github.com/Alwatr/nitrobase/commit/d6f02ad5b779d04aa1b484bff96369483393af15)) by @AliMD
202
- * Update type imports in alwatr-nitrobase.ts ([274d234](https://github.com/Alwatr/nitrobase/commit/274d234e6653cade2288288a4894feb7314987a2)) by @AliMD
203
-
204
- ### Dependencies update
205
-
206
- * update ([6411ff7](https://github.com/Alwatr/nitrobase/commit/6411ff7d49323b8bbf0dbb03fbc3c640b433a8bb)) by @
207
-
208
- ## [7.0.0-beta.1](https://github.com/Alwatr/nitrobase/compare/v7.0.0-beta.0...v7.0.0-beta.1) (2024-08-31)
209
-
210
- ### Code Refactoring
211
-
212
- * Remove unnecessary debug flag ([bdebb58](https://github.com/Alwatr/nitrobase/commit/bdebb5856310efd3628edb236f790968d94035fa)) by @
213
- * Update demo for test schemaVer ([4d5038b](https://github.com/Alwatr/nitrobase/commit/4d5038b3a5ae390355e2bd6524f7edc66fedc65c)) by @
214
-
215
- ## [7.0.0-beta.0](https://github.com/Alwatr/nitrobase/compare/v6.2.1...v7.0.0-beta.0) (2024-08-31)
216
-
217
- ### ⚠ BREAKING CHANGES
218
-
219
- * The `deleteFile` method has been renamed to `remove`. Update your code accordingly.
220
- * The `doc` and `collection` methods have been deprecated and should no longer be used. Instead, use the `openDocument` and `openCollection` methods.
221
-
222
- ### Features
223
-
224
- * Add newDocument and newCollection methods to AlwatrNitrobase ([363f820](https://github.com/Alwatr/nitrobase/commit/363f820a104e49a49746c95e7f303982d3ecb481)) by @AliMD
225
- * Open document and collection with given id in AlwatrNitrobase ([5041a20](https://github.com/Alwatr/nitrobase/commit/5041a20bbf6dc3a26499aac4649e8c0d17c23537)) by @AliMD
226
-
227
- ### Bug Fixes
228
-
229
- * **alwatr-nitrobase:** logger methods name issue ([4798d15](https://github.com/Alwatr/nitrobase/commit/4798d1527d05f1c7c79ddf03520e3478c0dae529)) by @AliMD
230
-
231
- ### Code Refactoring
232
-
233
- * **AlwatrNitrobase:** compatible with new api ([42c30f2](https://github.com/Alwatr/nitrobase/commit/42c30f2c7a066305eaba5e6fae50bfa5dc4502c8)) by @AliMD
234
- * **demo:** compatible with new api ([a76cc74](https://github.com/Alwatr/nitrobase/commit/a76cc7403610661c42099aae254ca5989bda1bff)) by @AliMD
235
- * Remove unnecessary debug flag from yarn script ([7f21798](https://github.com/Alwatr/nitrobase/commit/7f217981fb9c53c01f469a1a0b2761d856dc7337)) by @AliMD
236
- * rename `deleteFile` method to `remove` ([7356079](https://github.com/Alwatr/nitrobase/commit/735607933f78424ff7bdb6728f0e7b6eb18ca8a1)) by @AliMD
237
- * update StoreFileStat type to make extension property optional ([e75a186](https://github.com/Alwatr/nitrobase/commit/e75a186fbafd30a3d745467a973bec06e1d8109e)) by @AliMD
238
- * updates the `storeChanged__` method name to `storeChanged_`. ([8fd35fa](https://github.com/Alwatr/nitrobase/commit/8fd35fa69c0ff5c5fdc1f3be11a70ca4bac7dd81)) by @AliMD
239
-
240
- ### Miscellaneous Chores
241
-
242
- * fix logs messages ([73d4496](https://github.com/Alwatr/nitrobase/commit/73d4496928c6e8fa5800f31619b9be717cba3592)) by @AliMD
243
-
244
- ### Dependencies update
245
-
246
- * update ([2657638](https://github.com/Alwatr/nitrobase/commit/26576384c4a8ffcf35776f19008432e194fb39de)) by @AliMD
247
-
248
- ## [6.2.1](https://github.com/Alwatr/nitrobase/compare/v6.2.0...v6.2.1) (2024-08-31)
249
-
250
- ### Miscellaneous Chores
251
-
252
- * **deps-dev:** bump the development-dependencies group across 1 directory with 13 updates ([7e6aa11](https://github.com/Alwatr/nitrobase/commit/7e6aa11e1b4507111993a6070b481ebc95e534c7)) by @dependabot[bot]
253
- * **deps:** bump the alwatr-dependencies group with 10 updates ([faf1fc1](https://github.com/Alwatr/nitrobase/commit/faf1fc15f8b4c9c4c451dd5fa1d564eb3bf3d9a3)) by @dependabot[bot]
254
- * **deps:** bump the alwatr-dependencies group with 9 updates ([64ac4f2](https://github.com/Alwatr/nitrobase/commit/64ac4f239c0f0a8ccdadbd736c16973bd684f811)) by @dependabot[bot]
255
-
256
- ## [6.2.0](https://github.com/Alwatr/nitrobase/compare/v6.1.0...v6.2.0) (2024-07-03)
257
-
258
- ### Features
259
-
260
- * Add freeze property to CollectionReference and DocumentReference ([af1d7e4](https://github.com/Alwatr/nitrobase/commit/af1d7e47b3217d4e361a63d9eb9c410e04ea9385)) by @AliMD
261
-
262
- ## [6.1.0](https://github.com/Alwatr/nitrobase/compare/v6.0.5...v6.1.0) (2024-07-03)
263
-
264
- ### Dependencies update
265
-
266
- * bump the development-dependencies ([546ca1b](https://github.com/Alwatr/nitrobase/commit/546ca1be049090eb3c8304fcb75e98ac0b984510)) by @AliMD
267
-
268
- ## [6.0.5](https://github.com/Alwatr/nitrobase/compare/v6.0.4...v6.0.5) (2024-05-12)
269
-
270
- ### Miscellaneous Chores
271
-
272
- * **deps-dev:** bump the development-dependencies group across 1 directory with 3 updates ([f97552d](https://github.com/Alwatr/nitrobase/commit/f97552d0e8e85bc2e2f0863da17502b8e55799e8)) by @dependabot[bot]
273
- * **deps:** bump the alwatr-dependencies group with 8 updates ([1aa95ca](https://github.com/Alwatr/nitrobase/commit/1aa95ca232a7b706eda4b0eb537316d38b27aa28)) by @dependabot[bot]
274
-
275
- ## [6.0.4](https://github.com/Alwatr/nitrobase/compare/v6.0.3...v6.0.4) (2024-04-25)
276
-
277
- **Note:** Version bump only for package @alwatr/nitrobase-engine
278
-
279
- ## [6.0.3](https://github.com/Alwatr/nitrobase/compare/v6.0.2...v6.0.3) (2024-03-28)
280
-
281
- ### Miscellaneous Chores
282
-
283
- * **deps-dev:** bump the development-dependencies group with 13 updates ([23fb121](https://github.com/Alwatr/nitrobase/commit/23fb1217470593d386b658f2a1d85fe4ef6e55df)) by @dependabot[bot]
284
- * **deps:** bump the alwatr-dependencies group with 10 updates ([ce6ee74](https://github.com/Alwatr/nitrobase/commit/ce6ee7495aaa67a8d3bb0a3f2b2ea8389e161552)) by @dependabot[bot]
285
- * **deps:** bump the alwatr-dependencies group with 9 updates ([686e155](https://github.com/Alwatr/nitrobase/commit/686e155d4c0ccab6daf81d280cf91299152b8583)) by @dependabot[bot]
286
-
287
- ## [6.0.0](https://github.com/Alwatr/nitrobase/compare/v6.0.0-alpha.0...v6.0.0) (2024-01-24)
288
-
289
- ### Features
290
-
291
- * Enhance types, add Jsonifiable type and update method signatures ([57502d2](https://github.com/Alwatr/nitrobase/commit/57502d230f0c9cb88aa9a9e71a3460f1219955b0)) by @AliMD
292
-
293
- ### Miscellaneous Chores
294
-
295
- * **deps-dev:** bump the development-dependencies group with 4 updates ([7d71044](https://github.com/Alwatr/nitrobase/commit/7d71044165583f9d56fb61a05bdf51ccb104f422)) by @dependabot[bot]
296
- * **deps:** bump the alwatr-dependencies group with 10 updates ([cc42e89](https://github.com/Alwatr/nitrobase/commit/cc42e895179c53ee2dd60802d994ba84f5a37fde)) by @dependabot[bot]
297
- * **deps:** update ([0e85743](https://github.com/Alwatr/nitrobase/commit/0e85743f76f0efdd0f6cd4001eebc4550b43f43f)) by @AliMD
298
- * **deps:** update ([a894bfc](https://github.com/Alwatr/nitrobase/commit/a894bfc62124a3eb027cad4e8d1c974761e22dad)) by @AliMD
299
-
300
- ## [6.0.0-alpha.0](https://github.com/Alwatr/nitrobase/compare/v5.1.0...v6.0.0-alpha.0) (2024-01-15)
301
-
302
- ### Miscellaneous Chores
303
-
304
- * **deps:** update ([8f3edcf](https://github.com/Alwatr/nitrobase/commit/8f3edcf8a489927a6c43dfcaa5db88a579ecac80)) by @
305
-
306
- ## [5.1.0](https://github.com/Alwatr/nitrobase/compare/v5.0.0...v5.1.0) (2024-01-13)
307
-
308
- **Note:** Version bump only for package @alwatr/nitrobase-engine
309
-
310
- # [5.0.0](https://github.com/Alwatr/nitrobase/compare/v5.0.0-beta...v5.0.0) (2024-01-12)
311
-
312
- ### Code Refactoring
313
-
314
- * **engine:** remove all string id from public api ([c44fd1c](https://github.com/Alwatr/nitrobase/commit/c44fd1c0a7daffe20ba9e836f23d63a4dd4250b8)) by @AliMD
315
-
316
- ### Features
317
-
318
- * **engine:** use alwatr exit hook ([5be4f01](https://github.com/Alwatr/nitrobase/commit/5be4f01bc746b5b4cfb1df10def3abc5632c44ee)) by @njfamirm
319
- * **nitrobase:** Add option to error when nitrobase not initialized ([4b27468](https://github.com/Alwatr/nitrobase/commit/4b27468a063027b357e27fdff2484932e23d46e0)) by @AliMD
320
-
321
- ### BREAKING CHANGES
322
-
323
- * **engine:** The string ID has been removed from public APIs to prevent confusion caused by a simple sting ID.
324
-
325
- # [5.0.0-beta](https://github.com/Alwatr/nitrobase/compare/v4.1.0...v5.0.0-beta) (2023-12-31)
326
-
327
- ### Bug Fixes
328
-
329
- * **deps:** dev deps ([b129567](https://github.com/Alwatr/nitrobase/commit/b12956768b9d60a75c0fdc43774512b86b655f78)) by @AliMD
330
- * **engine/demo:** benchmark ([48b4456](https://github.com/Alwatr/nitrobase/commit/48b4456cd09bf610bfe718c843e55ff0db2a9e5a)) by @njfamirm
331
- * **engine/demo:** import path ([6effc2c](https://github.com/Alwatr/nitrobase/commit/6effc2c105aaf4057581bc161723d59a7ea0b7e6)) by @njfamirm
332
- * **engine:** add types to deps ([170043d](https://github.com/Alwatr/nitrobase/commit/170043d9095c73e3c678c051bc3f34d2ccd43730)) by @njfamirm
333
- * **engine:** data loss issue and improve performance ([07f6877](https://github.com/Alwatr/nitrobase/commit/07f68777faec66fee4efae7afd340bebe7078f17)) by @AliMD
334
- * **engine:** file path ([bbc4abd](https://github.com/Alwatr/nitrobase/commit/bbc4abdbb601108dc91ee95eeaac5cbbc272cdd4)) by @njfamirm
335
- * **engine:** get collection issue ([742aa23](https://github.com/Alwatr/nitrobase/commit/742aa236ae98c934ea6e0904a8a91d152471a31a)) by @AliMD
336
- * **engine:** import type ([9f67871](https://github.com/Alwatr/nitrobase/commit/9f67871dba8528a5393ea372f136865c952a102c)) by @njfamirm
337
- * **engine:** Remove StoreFileStatModel class ([d47b680](https://github.com/Alwatr/nitrobase/commit/d47b680d54b8bd9a0b8926653a69cb59c8f36398)) by @AliMD
338
- * **engine:** unsaved data lost issues ([fec0bef](https://github.com/Alwatr/nitrobase/commit/fec0bef78ac67ddd669012d8804588883f39affa)) by @AliMD
339
- * **engine:** Update defaultChangeDebounce value in AlwatrNitrobase ([63edd08](https://github.com/Alwatr/nitrobase/commit/63edd08c87c675edb91b8f7aa61b901a6d1db111)) by @AliMD
340
- * **engine:** Update imports and refactor util.ts ([2b1f962](https://github.com/Alwatr/nitrobase/commit/2b1f9628f4578f707996fe5e6d5d92c7d093b615)) by @AliMD
341
-
342
- ### Features
343
-
344
- * **engine/demo:** collection with new api ([f603e86](https://github.com/Alwatr/nitrobase/commit/f603e86d2827c66219321f9df400049e76b78c21)) by @AliMD
345
- * **engine:** Add data-lost-test.js demo file ([673f324](https://github.com/Alwatr/nitrobase/commit/673f3247c4b6c1bca2f9e9d9169843ca6a5e9804)) by @AliMD
346
- * **engine:** debounce for save file ([c92749e](https://github.com/Alwatr/nitrobase/commit/c92749e83352129c02130ac2466dd5acda289795)) by @AliMD
347
- * **engine:** doc demo ([f49f78b](https://github.com/Alwatr/nitrobase/commit/f49f78bd3b5942406fe74e273e87bcbf12f67c4f)) by @njfamirm
348
- * **engine:** enhance benchmark demo ([200da18](https://github.com/Alwatr/nitrobase/commit/200da18cd9542fa4182f910c0ad813703326fe38)) by @AliMD
349
- * **engine:** impediment exit hook ([68695a9](https://github.com/Alwatr/nitrobase/commit/68695a975e0ec6c473bbd2d9a62c81720f090352)) by @AliMD
350
- * **engine:** Refactor code to improve performance and readability ([b4c0848](https://github.com/Alwatr/nitrobase/commit/b4c0848e7518ae5c96e8ab7643716a2e923f7635)) by @AliMD
351
- * **node-fs:** Update logger method arguments to include truncated path ([8c6f49a](https://github.com/Alwatr/nitrobase/commit/8c6f49ad56d5667ba1280a5d28b7a39b21c3a11a)) by @AliMD
package/dist/main.cjs DELETED
@@ -1,4 +0,0 @@
1
- /** 📦 @alwatr/nitrobase-engine v7.10.1 */
2
- __dev_mode__: console.debug("📦 @alwatr/nitrobase-engine v7.10.1");
3
- "use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var main_exports={};__export(main_exports,{AlwatrNitrobase:()=>AlwatrNitrobase});module.exports=__toCommonJS(main_exports);var import_delay=require("@alwatr/delay");var import_exit_hook=require("@alwatr/exit-hook");var import_nitrobase_helper=require("@alwatr/nitrobase-helper");var import_nitrobase_reference=require("@alwatr/nitrobase-reference");var import_nitrobase_types=require("@alwatr/nitrobase-types");var import_node_fs=require("@alwatr/node-fs");var import_logger=require("@alwatr/logger");var logger=(0,import_logger.createLogger)("@alwatr/nitrobase-engine");__dev_mode__:logger.logFileModule?.("alwatr-nitrobase");var AlwatrNitrobase=class _AlwatrNitrobase{constructor(config){this.config=config;this.cacheReferences__={};this.storeChanged_=this.storeChanged_.bind(this);logger.logMethodArgs?.("new",config);this.config.defaultChangeDebounce??=40;this.rootDb__=this.loadRootDb__();(0,import_exit_hook.exitHook)(this.exitHook__.bind(this))}static{this.version="7.10.1"}static{this.rootDbStat__={name:".nitrobase",region:import_nitrobase_types.Region.Secret,type:import_nitrobase_types.StoreFileType.Collection,extension:import_nitrobase_types.StoreFileExtension.Json,changeDebounce:40}}hasStore(storeId){const id_=(0,import_nitrobase_helper.getStoreId)(storeId);const exists=this.rootDb__.hasItem(id_);logger.logMethodFull?.("hasStore",id_,exists);return exists}newDocument(stat,data){logger.logMethodArgs?.("newDocument",stat);return this.newStoreFile__({...stat,type:import_nitrobase_types.StoreFileType.Document},data)}newCollection(stat){logger.logMethodArgs?.("newCollection",stat);return this.newStoreFile__({...stat,type:import_nitrobase_types.StoreFileType.Collection})}newStoreFile__(stat,data){logger.logMethodArgs?.("newStoreFile__",stat);stat.changeDebounce??=this.config.defaultChangeDebounce;let fileStoreRef;if(stat.type===import_nitrobase_types.StoreFileType.Document){if(data===void 0){logger.accident("newStoreFile__","document_data_required",stat);throw new Error("document_data_required",{cause:stat})}fileStoreRef=import_nitrobase_reference.DocumentReference.newRefFromData(stat,data,this.storeChanged_)}else if(stat.type===import_nitrobase_types.StoreFileType.Collection){fileStoreRef=import_nitrobase_reference.CollectionReference.newRefFromData(stat,this.storeChanged_)}else{logger.accident("newStoreFile__","store_file_type_not_supported",stat);throw new Error("store_file_type_not_supported",{cause:stat})}if(this.rootDb__.hasItem(fileStoreRef.id)){logger.accident("newStoreFile__","store_file_already_defined",stat);throw new Error("store_file_already_defined",{cause:stat})}this.rootDb__.addItem(fileStoreRef.id,stat);this.cacheReferences__[fileStoreRef.id]=fileStoreRef;this.storeChanged_(fileStoreRef)}async openDocument(documentId){const id=(0,import_nitrobase_helper.getStoreId)(documentId);logger.logMethodArgs?.("openDocument",id);if(Object.hasOwn(this.cacheReferences__,id)){const ref=this.cacheReferences__[id];if(!(ref instanceof import_nitrobase_reference.DocumentReference)){logger.accident("openDocument","document_wrong_type",id);throw new Error("document_wrong_type",{cause:id})}return this.cacheReferences__[id]}if(!this.rootDb__.hasItem(id)){logger.accident("openDocument","document_not_found",id);throw new Error("document_not_found",{cause:id})}const storeStat=this.rootDb__.getItemData(id);if(storeStat.type!=import_nitrobase_types.StoreFileType.Document){logger.accident("openDocument","document_wrong_type",id);throw new Error("document_wrong_type",{cause:id})}const context=await this.readContext__(storeStat);const docRef=import_nitrobase_reference.DocumentReference.newRefFromContext(context,this.storeChanged_);this.cacheReferences__[id]=docRef;return docRef}async openCollection(collectionId){const id=(0,import_nitrobase_helper.getStoreId)(collectionId);logger.logMethodArgs?.("openCollection",id);if(Object.hasOwn(this.cacheReferences__,id)){const ref=this.cacheReferences__[id];if(!(ref instanceof import_nitrobase_reference.CollectionReference)){logger.accident("openCollection","collection_wrong_type",id);throw new Error("collection_wrong_type",{cause:id})}return this.cacheReferences__[id]}if(!this.rootDb__.hasItem(id)){logger.accident("openCollection","collection_not_found",id);throw new Error("collection_not_found",{cause:id})}const storeStat=this.rootDb__.getItemData(id);if(storeStat.type!=import_nitrobase_types.StoreFileType.Collection){logger.accident("openCollection","collection_wrong_type",id);throw new Error("collection_not_found",{cause:id})}const context=await this.readContext__(storeStat);const colRef=import_nitrobase_reference.CollectionReference.newRefFromContext(context,this.storeChanged_);this.cacheReferences__[id]=colRef;return colRef}unloadStore(storeId){const id_=(0,import_nitrobase_helper.getStoreId)(storeId);logger.logMethodArgs?.("unloadStore",id_);const ref=this.cacheReferences__[id_];if(ref===void 0)return;if(ref.hasUnprocessedChanges_===true){ref.updateDelayed_=false;this.storeChanged_(ref)}delete this.cacheReferences__[id_]}async removeStore(storeId){const id_=(0,import_nitrobase_helper.getStoreId)(storeId);logger.logMethodArgs?.("removeStore",id_);if(!this.rootDb__.hasItem(id_)){logger.accident("removeStore","document_not_found",id_);throw new Error("document_not_found",{cause:id_})}const ref=this.cacheReferences__[id_];if(ref!==void 0){ref.freeze=true;ref.updateDelayed_=false;ref.hasUnprocessedChanges_=false;delete this.cacheReferences__[id_]}const path=(0,import_nitrobase_helper.getStorePath)(this.rootDb__.getItemData(id_));this.rootDb__.removeItem(id_);await import_delay.delay.by(0);try{await(0,import_node_fs.unlink)((0,import_node_fs.resolve)(this.config.rootPath,path))}catch(error){logger.error("removeStore","remove_file_failed",error,{id:storeId,path})}}async saveAll(){logger.logMethod?.("saveAll");for(const ref of Object.values(this.cacheReferences__)){if(ref.hasUnprocessedChanges_===true&&ref.freeze!==true){ref.updateDelayed_=false;await this.storeChanged_(ref)}}}async readContext__(path){if(typeof path!=="string")path=(0,import_nitrobase_helper.getStorePath)(path);logger.logMethodArgs?.("readContext__",path);logger.time?.(`readContext__time(${path})`);const context=await(0,import_node_fs.readJson)((0,import_node_fs.resolve)(this.config.rootPath,path));logger.timeEnd?.(`readContext__time(${path})`);return context}writeContext__(path,context){if(typeof path!=="string")path=(0,import_nitrobase_helper.getStorePath)(path);logger.logMethodArgs?.("writeContext__",path);return(0,import_node_fs.writeJson)((0,import_node_fs.resolve)(this.config.rootPath,path),context)}async storeChanged_(from){logger.logMethodArgs?.("storeChanged__",from.id);const rev=from.getStoreMeta().rev;try{await this.writeContext__(from.path,from.getFullContext_());if(rev===from.getStoreMeta().rev){from.hasUnprocessedChanges_=false}}catch(error){logger.error("storeChanged__","write_context_failed",{id:from.id,error})}}loadRootDb__(){logger.logMethod?.("loadRootDb__");const fullPath=(0,import_node_fs.resolve)(this.config.rootPath,(0,import_nitrobase_helper.getStorePath)(_AlwatrNitrobase.rootDbStat__));if(!(0,import_node_fs.existsSync)(fullPath)){if(this.config.errorWhenNotInitialized===true){throw new Error("store_not_found",{cause:"Nitrobase not initialized"})}logger.banner("Initialize new alwatr-nitrobase");return import_nitrobase_reference.CollectionReference.newRefFromData(_AlwatrNitrobase.rootDbStat__,this.storeChanged_)}const context=(0,import_node_fs.readJson)(fullPath,true);return import_nitrobase_reference.CollectionReference.newRefFromContext(context,this.storeChanged_,"root-db")}exitHook__(){logger.logMethod?.("exitHook__");for(const ref of Object.values(this.cacheReferences__)){logger.logProperty?.(`StoreFile.${ref.id}.hasUnprocessedChanges`,ref.hasUnprocessedChanges_);if(ref.hasUnprocessedChanges_===true&&ref.freeze!==true){logger.incident?.("exitHook__","rescue_unsaved_context",{id:ref.id});(0,import_node_fs.writeJson)((0,import_node_fs.resolve)(this.config.rootPath,ref.path),ref.getFullContext_(),true);ref.hasUnprocessedChanges_=false}}}getStoreList(){logger.logMethod?.("getStoreList");return this.rootDb__.values()}};0&&(module.exports={AlwatrNitrobase});
4
- //# sourceMappingURL=main.cjs.map
package/dist/main.cjs.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/main.ts", "../src/alwatr-nitrobase.ts", "../src/logger.ts"],
4
- "sourcesContent": ["export * from './alwatr-nitrobase.js';\n", "import {delay} from '@alwatr/delay';\nimport {exitHook} from '@alwatr/exit-hook';\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';\nimport {existsSync, readJson, resolve, unlink, writeJson} from '@alwatr/node-fs';\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 public 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(public 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 public 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 public 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 public newCollection(stat: Omit<StoreFileStat, 'type'>): void {\n logger.logMethodArgs?.('newCollection', stat);\n return this.newStoreFile__({\n ...stat,\n type: StoreFileType.Collection,\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 private newStoreFile__(stat: StoreFileStat, data?: DictionaryOpt): 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 public 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 public 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 public 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 public 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 public 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 public getStoreList(): CollectionItem<Omit<StoreFileStat, 'schemaVer'>>[] {\n logger.logMethod?.('getStoreList');\n return this.rootDb__.values();\n }\n}\n", "import {createLogger} from '@alwatr/logger';\n\nimport type {} from '@alwatr/nanolib';\nimport type {} from '@alwatr/type-helper';\n\nexport const logger = /* #__PURE__ */ createLogger(__package_name__);\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
package/dist/main.mjs DELETED
@@ -1,4 +0,0 @@
1
- /** 📦 @alwatr/nitrobase-engine v7.10.1 */
2
- __dev_mode__: console.debug("📦 @alwatr/nitrobase-engine v7.10.1");
3
- import{delay}from"@alwatr/delay";import{exitHook}from"@alwatr/exit-hook";import{getStoreId,getStorePath}from"@alwatr/nitrobase-helper";import{CollectionReference,DocumentReference}from"@alwatr/nitrobase-reference";import{StoreFileType,StoreFileExtension,Region}from"@alwatr/nitrobase-types";import{existsSync,readJson,resolve,unlink,writeJson}from"@alwatr/node-fs";import{createLogger}from"@alwatr/logger";var logger=createLogger("@alwatr/nitrobase-engine");__dev_mode__:logger.logFileModule?.("alwatr-nitrobase");var AlwatrNitrobase=class _AlwatrNitrobase{constructor(config){this.config=config;this.cacheReferences__={};this.storeChanged_=this.storeChanged_.bind(this);logger.logMethodArgs?.("new",config);this.config.defaultChangeDebounce??=40;this.rootDb__=this.loadRootDb__();exitHook(this.exitHook__.bind(this))}static{this.version="7.10.1"}static{this.rootDbStat__={name:".nitrobase",region:Region.Secret,type:StoreFileType.Collection,extension:StoreFileExtension.Json,changeDebounce:40}}hasStore(storeId){const id_=getStoreId(storeId);const exists=this.rootDb__.hasItem(id_);logger.logMethodFull?.("hasStore",id_,exists);return exists}newDocument(stat,data){logger.logMethodArgs?.("newDocument",stat);return this.newStoreFile__({...stat,type:StoreFileType.Document},data)}newCollection(stat){logger.logMethodArgs?.("newCollection",stat);return this.newStoreFile__({...stat,type:StoreFileType.Collection})}newStoreFile__(stat,data){logger.logMethodArgs?.("newStoreFile__",stat);stat.changeDebounce??=this.config.defaultChangeDebounce;let fileStoreRef;if(stat.type===StoreFileType.Document){if(data===void 0){logger.accident("newStoreFile__","document_data_required",stat);throw new Error("document_data_required",{cause:stat})}fileStoreRef=DocumentReference.newRefFromData(stat,data,this.storeChanged_)}else if(stat.type===StoreFileType.Collection){fileStoreRef=CollectionReference.newRefFromData(stat,this.storeChanged_)}else{logger.accident("newStoreFile__","store_file_type_not_supported",stat);throw new Error("store_file_type_not_supported",{cause:stat})}if(this.rootDb__.hasItem(fileStoreRef.id)){logger.accident("newStoreFile__","store_file_already_defined",stat);throw new Error("store_file_already_defined",{cause:stat})}this.rootDb__.addItem(fileStoreRef.id,stat);this.cacheReferences__[fileStoreRef.id]=fileStoreRef;this.storeChanged_(fileStoreRef)}async openDocument(documentId){const id=getStoreId(documentId);logger.logMethodArgs?.("openDocument",id);if(Object.hasOwn(this.cacheReferences__,id)){const ref=this.cacheReferences__[id];if(!(ref instanceof DocumentReference)){logger.accident("openDocument","document_wrong_type",id);throw new Error("document_wrong_type",{cause:id})}return this.cacheReferences__[id]}if(!this.rootDb__.hasItem(id)){logger.accident("openDocument","document_not_found",id);throw new Error("document_not_found",{cause:id})}const storeStat=this.rootDb__.getItemData(id);if(storeStat.type!=StoreFileType.Document){logger.accident("openDocument","document_wrong_type",id);throw new Error("document_wrong_type",{cause:id})}const context=await this.readContext__(storeStat);const docRef=DocumentReference.newRefFromContext(context,this.storeChanged_);this.cacheReferences__[id]=docRef;return docRef}async openCollection(collectionId){const id=getStoreId(collectionId);logger.logMethodArgs?.("openCollection",id);if(Object.hasOwn(this.cacheReferences__,id)){const ref=this.cacheReferences__[id];if(!(ref instanceof CollectionReference)){logger.accident("openCollection","collection_wrong_type",id);throw new Error("collection_wrong_type",{cause:id})}return this.cacheReferences__[id]}if(!this.rootDb__.hasItem(id)){logger.accident("openCollection","collection_not_found",id);throw new Error("collection_not_found",{cause:id})}const storeStat=this.rootDb__.getItemData(id);if(storeStat.type!=StoreFileType.Collection){logger.accident("openCollection","collection_wrong_type",id);throw new Error("collection_not_found",{cause:id})}const context=await this.readContext__(storeStat);const colRef=CollectionReference.newRefFromContext(context,this.storeChanged_);this.cacheReferences__[id]=colRef;return colRef}unloadStore(storeId){const id_=getStoreId(storeId);logger.logMethodArgs?.("unloadStore",id_);const ref=this.cacheReferences__[id_];if(ref===void 0)return;if(ref.hasUnprocessedChanges_===true){ref.updateDelayed_=false;this.storeChanged_(ref)}delete this.cacheReferences__[id_]}async removeStore(storeId){const id_=getStoreId(storeId);logger.logMethodArgs?.("removeStore",id_);if(!this.rootDb__.hasItem(id_)){logger.accident("removeStore","document_not_found",id_);throw new Error("document_not_found",{cause:id_})}const ref=this.cacheReferences__[id_];if(ref!==void 0){ref.freeze=true;ref.updateDelayed_=false;ref.hasUnprocessedChanges_=false;delete this.cacheReferences__[id_]}const path=getStorePath(this.rootDb__.getItemData(id_));this.rootDb__.removeItem(id_);await delay.by(0);try{await unlink(resolve(this.config.rootPath,path))}catch(error){logger.error("removeStore","remove_file_failed",error,{id:storeId,path})}}async saveAll(){logger.logMethod?.("saveAll");for(const ref of Object.values(this.cacheReferences__)){if(ref.hasUnprocessedChanges_===true&&ref.freeze!==true){ref.updateDelayed_=false;await this.storeChanged_(ref)}}}async readContext__(path){if(typeof path!=="string")path=getStorePath(path);logger.logMethodArgs?.("readContext__",path);logger.time?.(`readContext__time(${path})`);const context=await readJson(resolve(this.config.rootPath,path));logger.timeEnd?.(`readContext__time(${path})`);return context}writeContext__(path,context){if(typeof path!=="string")path=getStorePath(path);logger.logMethodArgs?.("writeContext__",path);return writeJson(resolve(this.config.rootPath,path),context)}async storeChanged_(from){logger.logMethodArgs?.("storeChanged__",from.id);const rev=from.getStoreMeta().rev;try{await this.writeContext__(from.path,from.getFullContext_());if(rev===from.getStoreMeta().rev){from.hasUnprocessedChanges_=false}}catch(error){logger.error("storeChanged__","write_context_failed",{id:from.id,error})}}loadRootDb__(){logger.logMethod?.("loadRootDb__");const fullPath=resolve(this.config.rootPath,getStorePath(_AlwatrNitrobase.rootDbStat__));if(!existsSync(fullPath)){if(this.config.errorWhenNotInitialized===true){throw new Error("store_not_found",{cause:"Nitrobase not initialized"})}logger.banner("Initialize new alwatr-nitrobase");return CollectionReference.newRefFromData(_AlwatrNitrobase.rootDbStat__,this.storeChanged_)}const context=readJson(fullPath,true);return CollectionReference.newRefFromContext(context,this.storeChanged_,"root-db")}exitHook__(){logger.logMethod?.("exitHook__");for(const ref of Object.values(this.cacheReferences__)){logger.logProperty?.(`StoreFile.${ref.id}.hasUnprocessedChanges`,ref.hasUnprocessedChanges_);if(ref.hasUnprocessedChanges_===true&&ref.freeze!==true){logger.incident?.("exitHook__","rescue_unsaved_context",{id:ref.id});writeJson(resolve(this.config.rootPath,ref.path),ref.getFullContext_(),true);ref.hasUnprocessedChanges_=false}}}getStoreList(){logger.logMethod?.("getStoreList");return this.rootDb__.values()}};export{AlwatrNitrobase};
4
- //# sourceMappingURL=main.mjs.map
package/dist/main.mjs.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/alwatr-nitrobase.ts", "../src/logger.ts"],
4
- "sourcesContent": ["import {delay} from '@alwatr/delay';\nimport {exitHook} from '@alwatr/exit-hook';\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';\nimport {existsSync, readJson, resolve, unlink, writeJson} from '@alwatr/node-fs';\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 public 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(public 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 public 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 public 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 public newCollection(stat: Omit<StoreFileStat, 'type'>): void {\n logger.logMethodArgs?.('newCollection', stat);\n return this.newStoreFile__({\n ...stat,\n type: StoreFileType.Collection,\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 private newStoreFile__(stat: StoreFileStat, data?: DictionaryOpt): 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 public 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 public 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 public 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 public 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 public 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 public getStoreList(): CollectionItem<Omit<StoreFileStat, 'schemaVer'>>[] {\n logger.logMethod?.('getStoreList');\n return this.rootDb__.values();\n }\n}\n", "import {createLogger} from '@alwatr/logger';\n\nimport type {} from '@alwatr/nanolib';\nimport type {} from '@alwatr/type-helper';\n\nexport const logger = /* #__PURE__ */ createLogger(__package_name__);\n"],
5
- "mappings": "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",
6
- "names": []
7
- }