axiodb 13.1.4 → 14.2.7

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.
@@ -0,0 +1,12 @@
1
+ # Compiled TypeScript output (tsc outDir) - duplicates every source/*.ts as
2
+ # .js plus __awaiter polyfill internals (adopt/fulfilled/rejected/step) in
3
+ # each file. Already git-ignored; indexing it doubles the graph with noise.
4
+ /lib/
5
+
6
+ # graphify's own outputs - GRAPH_REPORT.md/graph.json are generated FROM the graph;
7
+ # indexing them feeds the graph its own summary back as source material.
8
+ /graphify-out/
9
+
10
+ # Built docs site (vite-react-ssg output) - duplicates Document/src + Document/public
11
+ # as pre-rendered HTML plus llms.txt/llms-full.txt concatenations of the same content.
12
+ /Document/AxioDB_Docs/
package/a.txt ADDED
@@ -0,0 +1,11 @@
1
+ Rank order for your profile:
2
+
3
+ Instahyre - curated, India product companies, recruiters reach out. Best fit.
4
+ Wellfound - startups, remote, Node-heavy. Free.
5
+ workatastartup.com (YC) - Node-native seed/Series A. Free. Barely used by Indian devs. Underpriced.
6
+ Hirist - tech-only India, less noise than Naukri.
7
+ Cutshort - startups, decent.
8
+ Weekday.works - referral-graph based.
9
+ Company careers page direct - highest signal per application. Wobot, CoverForce, do this.
10
+ r/developersIndia monthly hiring thread - free, low volume, real.
11
+ GDG Kolkata network - your actual edge. Using at ~20%.
@@ -1,12 +1,13 @@
1
1
  /**
2
- * Generates random alphabetic identifiers (document IDs, transaction IDs, session IDs).
2
+ * Generates random identifiers (document IDs, transaction IDs, session IDs).
3
3
  */
4
4
  export default class UniqueGenerator {
5
5
  private readonly length;
6
6
  constructor(length: number);
7
7
  /**
8
- * Generates a random alphabetic string of the configured length.
8
+ * Generates a random string of the configured length.
9
9
  * @param isCapital - Return the result in uppercase when true.
10
+ * @param includeNumbers - Include digits 0-9 in the character set (alphanumeric) when true.
10
11
  */
11
- RandomWord(isCapital?: boolean): string;
12
+ RandomWord(isCapital?: boolean, includeNumbers?: boolean): string;
12
13
  }
@@ -2,21 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const crypto_1 = require("crypto");
4
4
  const LETTERS = "abcdefghijklmnopqrstuvwxyz";
5
+ const DIGITS = "0123456789";
5
6
  /**
6
- * Generates random alphabetic identifiers (document IDs, transaction IDs, session IDs).
7
+ * Generates random identifiers (document IDs, transaction IDs, session IDs).
7
8
  */
8
9
  class UniqueGenerator {
9
10
  constructor(length) {
10
11
  this.length = length;
11
12
  }
12
13
  /**
13
- * Generates a random alphabetic string of the configured length.
14
+ * Generates a random string of the configured length.
14
15
  * @param isCapital - Return the result in uppercase when true.
16
+ * @param includeNumbers - Include digits 0-9 in the character set (alphanumeric) when true.
15
17
  */
16
- RandomWord(isCapital = false) {
18
+ RandomWord(isCapital = false, includeNumbers = false) {
19
+ const charset = includeNumbers ? LETTERS + DIGITS : LETTERS;
17
20
  let result = "";
18
21
  for (let i = 0; i < this.length; i++) {
19
- result += LETTERS[(0, crypto_1.randomInt)(LETTERS.length)];
22
+ result += charset[(0, crypto_1.randomInt)(charset.length)];
20
23
  }
21
24
  return isCapital ? result.toUpperCase() : result;
22
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"UniqueGenerator.helper.js","sourceRoot":"","sources":["../../source/Helper/UniqueGenerator.helper.ts"],"names":[],"mappings":";;AAAA,mCAAmC;AAEnC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AAE7C;;GAEG;AACH;IACE,YAA6B,MAAc;sBAAd,MAAM;IAAW,CAAC;IAE/C;;;OAGG;IACH,UAAU,CAAC,SAAS,GAAG,KAAK;QAC1B,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,OAAO,CAAC,IAAA,kBAAS,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACnD,CAAC;CACF"}
1
+ {"version":3,"file":"UniqueGenerator.helper.js","sourceRoot":"","sources":["../../source/Helper/UniqueGenerator.helper.ts"],"names":[],"mappings":";;AAAA,mCAAmC;AAEnC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AAC7C,MAAM,MAAM,GAAG,YAAY,CAAC;AAE5B;;GAEG;AACH;IACE,YAA6B,MAAc;sBAAd,MAAM;IAAW,CAAC;IAE/C;;;;OAIG;IACH,UAAU,CAAC,SAAS,GAAG,KAAK,EAAE,cAAc,GAAG,KAAK;QAClD,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAC5D,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,OAAO,CAAC,IAAA,kBAAS,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACnD,CAAC;CACF"}
@@ -82,7 +82,7 @@ class Insertion {
82
82
  let isExist = true;
83
83
  let ID;
84
84
  do {
85
- ID = new UniqueGenerator_helper_1.default(15).RandomWord(true);
85
+ ID = new UniqueGenerator_helper_1.default(Keys_1.General.DocumentId_Length).RandomWord(true, true);
86
86
  // Sanitize ID to ensure safe file path
87
87
  const sanitizedID = PathSanitizer_helper_1.default.sanitizePathComponent(ID);
88
88
  const response = yield new FileManager_1.default().FileExists(PathSanitizer_helper_1.default.safePath(this.path, `${sanitizedID}${Keys_1.General.DBMS_File_EXT}`));
@@ -1 +1 @@
1
- {"version":3,"file":"Create.operation.js","sourceRoot":"","sources":["../../../source/Services/CRUD Operation/Create.operation.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,uDAAuD;AACvD,mCAAoC;AACpC,sFAA8D;AAE9D,iGAAkE;AAClE,mFAA0D;AAK1D,iDAAiD;AACjD,qFAAsD;AACtD,6FAA8D;AAE9D;;GAEG;AACH;IAKE;;;;OAIG;IACH,YAAY,cAAsB,EAAE,IAAkB;QACpD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,0BAAS,EAAE,CAAC;IACnC,CAAC;IAED;;;OAGG;IACU,IAAI,CACf,IAAkB,EAClB,kBAA2B;;YAE3B,IAAI,CAAC;gBACH,MAAM,UAAU,GACd,kBAAkB,KAAK,SAAS;oBAC9B,CAAC,CAAC,MAAM,IAAI,CAAC,wBAAwB,EAAE;oBACvC,CAAC,CAAC,kBAAkB,CAAC;gBAEzB,6DAA6D;gBAC7D,MAAM,mBAAmB,GAAG,8BAAa,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;gBAC5E,MAAM,QAAQ,GAAG,8BAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,mBAAmB,GAAG,cAAO,CAAC,aAAa,EAAE,CAAC,CAAC;gBAErG,wEAAwE;gBACxE,+EAA+E;gBAC/E,0EAA0E;gBAC1E,+EAA+E;gBAC/E,8EAA8E;gBAC9E,sDAAsD;gBACtD,MAAM,WAAW,GAAG,IAAI,qBAAW,EAAE,CAAC;gBACtC,MAAM,YAAY,GAAG,GAAG,QAAQ,QAAQ,IAAA,mBAAU,GAAE,EAAE,CAAC;gBACvD,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,SAAS,CAC/C,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC9B,CAAC;gBAEF,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;oBACzB,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;oBACxE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;wBACzB,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAC3D,CAAC;oBACD,OAAO,IAAI,yBAAc,EAAE,CAAC,OAAO,CAAC;wBAClC,OAAO,EAAE,4BAA4B;wBACrC,UAAU,EAAE,UAAU;qBACvB,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;KAAA;IAED;;;OAGG;IACU,wBAAwB;;YACnC,IAAI,OAAO,GAAG,IAAI,CAAC;YACnB,IAAI,EAAE,CAAC;YACP,GAAG,CAAC;gBACF,EAAE,GAAG,IAAI,gCAAe,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBAC9C,uCAAuC;gBACvC,MAAM,WAAW,GAAG,8BAAa,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;gBAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,qBAAW,EAAE,CAAC,UAAU,CACjD,8BAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,WAAW,GAAG,cAAO,CAAC,aAAa,EAAE,CAAC,CAC5E,CAAC;gBACF,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC5B,CAAC,QAAQ,OAAO,EAAE;YAElB,OAAO,EAAE,CAAC;QACZ,CAAC;KAAA;CACF"}
1
+ {"version":3,"file":"Create.operation.js","sourceRoot":"","sources":["../../../source/Services/CRUD Operation/Create.operation.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,uDAAuD;AACvD,mCAAoC;AACpC,sFAA8D;AAE9D,iGAAkE;AAClE,mFAA0D;AAK1D,iDAAiD;AACjD,qFAAsD;AACtD,6FAA8D;AAE9D;;GAEG;AACH;IAKE;;;;OAIG;IACH,YAAY,cAAsB,EAAE,IAAkB;QACpD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,0BAAS,EAAE,CAAC;IACnC,CAAC;IAED;;;OAGG;IACU,IAAI,CACf,IAAkB,EAClB,kBAA2B;;YAE3B,IAAI,CAAC;gBACH,MAAM,UAAU,GACd,kBAAkB,KAAK,SAAS;oBAC9B,CAAC,CAAC,MAAM,IAAI,CAAC,wBAAwB,EAAE;oBACvC,CAAC,CAAC,kBAAkB,CAAC;gBAEzB,6DAA6D;gBAC7D,MAAM,mBAAmB,GAAG,8BAAa,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;gBAC5E,MAAM,QAAQ,GAAG,8BAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,mBAAmB,GAAG,cAAO,CAAC,aAAa,EAAE,CAAC,CAAC;gBAErG,wEAAwE;gBACxE,+EAA+E;gBAC/E,0EAA0E;gBAC1E,+EAA+E;gBAC/E,8EAA8E;gBAC9E,sDAAsD;gBACtD,MAAM,WAAW,GAAG,IAAI,qBAAW,EAAE,CAAC;gBACtC,MAAM,YAAY,GAAG,GAAG,QAAQ,QAAQ,IAAA,mBAAU,GAAE,EAAE,CAAC;gBACvD,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,SAAS,CAC/C,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC9B,CAAC;gBAEF,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;oBACzB,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;oBACxE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;wBACzB,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAC3D,CAAC;oBACD,OAAO,IAAI,yBAAc,EAAE,CAAC,OAAO,CAAC;wBAClC,OAAO,EAAE,4BAA4B;wBACrC,UAAU,EAAE,UAAU;qBACvB,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,yBAAc,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;KAAA;IAED;;;OAGG;IACU,wBAAwB;;YACnC,IAAI,OAAO,GAAG,IAAI,CAAC;YACnB,IAAI,EAAE,CAAC;YACP,GAAG,CAAC;gBACF,EAAE,GAAG,IAAI,gCAAe,CAAC,cAAO,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC3E,uCAAuC;gBACvC,MAAM,WAAW,GAAG,8BAAa,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;gBAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,qBAAW,EAAE,CAAC,UAAU,CACjD,8BAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,WAAW,GAAG,cAAO,CAAC,aAAa,EAAE,CAAC,CAC5E,CAAC;gBACF,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC5B,CAAC,QAAQ,OAAO,EAAE;YAElB,OAAO,EAAE,CAAC;QACZ,CAAC;KAAA;CACF"}
@@ -17,129 +17,60 @@ export declare class IndexManager {
17
17
  readonly converter: Converter;
18
18
  readonly ResponseHelper: ResponseHelper;
19
19
  constructor(path: string);
20
+ /**
21
+ * Serialize IndexData shape for JSONL file storage.
22
+ * Line 1 = header (fieldName + sortedValues), remaining lines = one per indexEntries key.
23
+ *
24
+ * Example output:
25
+ * {"h":1,"f":"email","s":[]}
26
+ * {"k":"alice@x.com","v":["abc123.axiodb"]}
27
+ */
28
+ static serializeIndexData(indexData: {
29
+ fieldName: string;
30
+ indexEntries: Record<string, string[]>;
31
+ sortedValues?: number[];
32
+ }): string;
33
+ /**
34
+ * Deserialize JSONL lines back into an IndexData object.
35
+ * Expects first line to be the header: { h:1, f, s }.
36
+ */
37
+ static deserializeIndexData(lines: string[]): {
38
+ fieldName: string;
39
+ indexEntries: Record<string, string[]>;
40
+ sortedValues: number[];
41
+ } | null;
20
42
  /**
21
43
  * Create one or more index files and register them in the index metadata.
22
44
  *
23
45
  * For each supplied field name this method:
24
- * 1. Determines the index file path as `${indexName}.axiodb` inside the configured index folder.
46
+ * 1. Determines the index file path as `${indexName}.jsonl` inside the configured index folder.
25
47
  * 2. Checks whether the index file already exists. If it does not, creates the file with an empty
26
- * index structure ({ fieldName, indexEntries: [] }).
27
- * 3. Reads the index metadata file (index.meta.json), parses it, and if an entry for the index
28
- * field does not already exist, appends a metadata record `{ indexFieldName, fileName, path }`
29
- * and writes the metadata file back.
30
- *
31
- * Side effects:
32
- * - Writes new index files to disk via `fileManager.WriteFile`.
33
- * - Reads and updates the index metadata file via `fileManager.ReadFile` / `WriteFile`.
34
- * - Uses the configured `converter` to serialize/deserialize index and metadata content.
35
- *
36
- * Notes:
37
- * - The operation is not atomic: some indexes may be created while others fail. The method will
38
- * collect created and failed index names and include them in the returned response.
39
- * - A failure is recorded for a field when the index file already exists, when the index already
40
- * exists in the metadata, or when reading/writing the metadata file fails.
41
- * - The method relies on `indexFolderPath`, `indexMetaPath`, `fileManager`, and `converter`
42
- * being correctly configured and available on the instance.
48
+ * JSONL index structure (header + no entries).
49
+ * 3. Appends a JSONL line to `index.meta.jsonl` for each new index no read-modify-rewrite.
43
50
  *
44
- * @param fieldNames - One or more field names for which to create indexes.
45
- * @returns A promise that resolves to either:
46
- * - SuccessInterface: indicates which indexes were created and which already existed / failed,
47
- * typically containing a human-readable message listing affected and existing indexes.
48
- * - ErrorInterface: returned when underlying file/IO operations fail in a way that prevents
49
- * producing the expected success response.
50
- *
51
- * @example
52
- * // Create a single index
53
- * await service.createIndex('email');
54
- *
55
- * @example
56
- * // Create multiple indexes
57
- * await service.createIndex('email', 'username', 'createdAt');
51
+ * Creates are now O(1) appends instead of O(N) full-file rewrites for meta.
58
52
  */
59
53
  createIndex(...fieldNames: string[]): Promise<SuccessInterface | undefined>;
60
54
  /**
61
55
  * Deletes an index file and removes its entry from the index metadata.
62
- *
63
- * This asynchronous method attempts to delete the index file located at
64
- * `${this.indexFolderPath}/${indexName}.axiodb`. If the file exists it is removed,
65
- * and the index metadata file at `this.indexMetaPath` is read and updated by
66
- * filtering out the metadata entry whose `indexFieldName` matches `indexName`.
67
- * The metadata update is performed only if the metadata file can be read successfully.
68
- *
69
- * @param indexName - The name of the index to delete (without extension).
70
- * @returns A Promise that resolves to a SuccessInterface when the index was deleted
71
- * (and metadata updated when possible), or an ErrorInterface when the
72
- * specified index does not exist.
73
- *
74
- * @async
75
- * @remarks
76
- * - Side effects: removes a file from the file system and may modify the index metadata file.
77
- * - Uses injected helpers: `fileManager` for filesystem operations, `converter` for
78
- * (de)serialization of metadata, and `ResponseHelper` to construct the returned result.
79
- * - If the metadata file cannot be read, the method still succeeds after deleting the index file.
80
- *
81
- * @throws {Error} May propagate errors from underlying file operations if those utilities throw.
82
56
  */
83
57
  dropIndex(indexName: string): Promise<SuccessInterface | ErrorInterface>;
84
58
  /**
85
59
  * Lists all indexes currently registered for this collection.
86
- *
87
- * Reads the index metadata file (`index.meta.json`) and returns its parsed entries as-is —
88
- * this is a pure read of the same metadata `createIndex`/`dropIndex` already maintain, no new
89
- * storage format is introduced.
90
- *
91
- * @returns A promise that resolves to a SuccessInterface containing the list of index metadata
92
- * entries (`{ indexFieldName, fileName, path }`), or an ErrorInterface if the metadata
93
- * file could not be read.
94
- *
95
- * @example
96
- * const result = await service.listIndexes();
60
+ * Now uses streaming ReadLines for memory efficiency.
97
61
  */
98
62
  listIndexes(): Promise<SuccessInterface | ErrorInterface>;
99
63
  /**
100
64
  * Ensures the index folder and the index metadata file exist, creating them if necessary.
101
- *
102
- * This asynchronous method performs the following steps:
103
- * 1. Checks whether the index folder at `this.indexFolderPath` exists; if not, creates it.
104
- * 2. Checks whether the index metadata file at `this.indexMetaPath` exists; if not:
105
- * a. Constructs a default index metadata entry for a unique "documentId" index:
106
- * - indexFieldName: "documentId"
107
- * - fileName: "documentId.axiodb"
108
- * - path: `${this.indexFolderPath}/documentId.axiodb`
109
- * - unique: true
110
- * b. Calls `this.createIndex("documentId")` to create the underlying index file/structure.
111
- * c. Writes the metadata array to `this.indexMetaPath` using `this.converter.ToString(...)`.
112
- *
113
- * The operation is idempotent: if the folder or metadata file already exist, no changes are made.
114
- *
115
- * @remarks
116
- * - This method performs filesystem modifications via `folderManager` and `fileManager`.
117
- * - Any errors thrown by `folderManager`, `fileManager`, `converter`, or `createIndex` will propagate to the caller.
118
- * - Callers should `await` this method to ensure the initialization is complete before proceeding.
119
- *
120
- * @returns A Promise that resolves when initialization is complete.
121
- *
122
- * @throws Will reject if directory creation, file checks/writes, conversion, or index creation fails.
123
- *
124
- * @example
125
- * // Ensure index folder and metadata exist before using the index service
126
- * await indexService.generateIndexMeta();
127
65
  */
128
66
  generateIndexMeta(): Promise<void>;
67
+ /**
68
+ * Streams index.meta.jsonl lines into an array of IndexMetaEntry objects.
69
+ */
70
+ private listMetaEntries;
129
71
  /**
130
72
  * Finds index metadata entries that correspond to properties present on the provided document.
131
- *
132
- * Reads the index metadata file at `this.indexMetaPath`, converts its content into an object,
133
- * and returns the subset of metadata entries whose `indexFieldName` is an own property of `doc`.
134
- *
135
- * @param doc - The document to check for matching index fields. The function tests own properties
136
- * (via `Object.prototype.hasOwnProperty.call`) rather than inherited properties.
137
- * @returns A Promise that resolves to an array of matching index metadata entries, or `undefined`
138
- * if the index metadata file could not be successfully read. The array may be empty if
139
- * no metadata entries match.
140
- *
141
- * @throws May propagate errors from `fileManager.ReadFile` or `converter.ToObject` if those
142
- * operations throw or reject.
73
+ * Streams meta file, returns first match (doesn't parse the entire file).
143
74
  */
144
75
  protected findMatchingIndexMeta(doc: any): Promise<any[] | undefined>;
145
76
  }
@@ -18,54 +18,80 @@ const FileManager_1 = __importDefault(require("../../engine/Filesystem/FileManag
18
18
  const FolderManager_1 = __importDefault(require("../../engine/Filesystem/FolderManager"));
19
19
  const Converter_helper_1 = __importDefault(require("../../Helper/Converter.helper"));
20
20
  const response_helper_1 = __importDefault(require("../../Helper/response.helper"));
21
+ const INDEX_EXT = Keys_1.General.Index_File_EXT; // ".jsonl"
21
22
  class IndexManager {
22
23
  constructor(path) {
23
24
  this.path = path;
24
25
  this.indexFolderPath = `${this.path}/indexes`;
25
- this.indexMetaPath = `${this.indexFolderPath}/index.meta.json`;
26
+ this.indexMetaPath = `${this.indexFolderPath}/${Keys_1.General.Index_Meta_File}`;
26
27
  this.fileManager = new FileManager_1.default();
27
28
  this.folderManager = new FolderManager_1.default();
28
29
  this.converter = new Converter_helper_1.default();
29
30
  this.ResponseHelper = new response_helper_1.default();
30
31
  }
32
+ /**
33
+ * Serialize IndexData shape for JSONL file storage.
34
+ * Line 1 = header (fieldName + sortedValues), remaining lines = one per indexEntries key.
35
+ *
36
+ * Example output:
37
+ * {"h":1,"f":"email","s":[]}
38
+ * {"k":"alice@x.com","v":["abc123.axiodb"]}
39
+ */
40
+ static serializeIndexData(indexData) {
41
+ var _a;
42
+ const lines = [];
43
+ const header = { h: 1, f: indexData.fieldName, s: (_a = indexData.sortedValues) !== null && _a !== void 0 ? _a : [] };
44
+ lines.push(JSON.stringify(header));
45
+ for (const [key, files] of Object.entries(indexData.indexEntries)) {
46
+ lines.push(JSON.stringify({ k: key, v: files }));
47
+ }
48
+ return lines.join("\n") + "\n";
49
+ }
50
+ /**
51
+ * Deserialize JSONL lines back into an IndexData object.
52
+ * Expects first line to be the header: { h:1, f, s }.
53
+ */
54
+ static deserializeIndexData(lines) {
55
+ var _a;
56
+ if (lines.length === 0)
57
+ return null;
58
+ const decoder = new TextDecoder();
59
+ try {
60
+ const headerStr = typeof lines[0] === 'string' ? lines[0] : decoder.decode(lines[0]);
61
+ const header = JSON.parse(headerStr);
62
+ if (!header || header.h !== 1)
63
+ return null;
64
+ const indexEntries = {};
65
+ for (let i = 1; i < lines.length; i++) {
66
+ const lineStr = typeof lines[i] === 'string' ? lines[i] : decoder.decode(lines[i]);
67
+ try {
68
+ const entry = JSON.parse(lineStr);
69
+ if (entry && entry.k !== undefined && entry.v !== undefined) {
70
+ indexEntries[String(entry.k)] = entry.v;
71
+ }
72
+ }
73
+ catch (_b) { /* skip corrupt lines */ }
74
+ }
75
+ return {
76
+ fieldName: header.f,
77
+ indexEntries,
78
+ sortedValues: (_a = header.s) !== null && _a !== void 0 ? _a : [],
79
+ };
80
+ }
81
+ catch (_c) {
82
+ return null;
83
+ }
84
+ }
31
85
  /**
32
86
  * Create one or more index files and register them in the index metadata.
33
87
  *
34
88
  * For each supplied field name this method:
35
- * 1. Determines the index file path as `${indexName}.axiodb` inside the configured index folder.
89
+ * 1. Determines the index file path as `${indexName}.jsonl` inside the configured index folder.
36
90
  * 2. Checks whether the index file already exists. If it does not, creates the file with an empty
37
- * index structure ({ fieldName, indexEntries: [] }).
38
- * 3. Reads the index metadata file (index.meta.json), parses it, and if an entry for the index
39
- * field does not already exist, appends a metadata record `{ indexFieldName, fileName, path }`
40
- * and writes the metadata file back.
41
- *
42
- * Side effects:
43
- * - Writes new index files to disk via `fileManager.WriteFile`.
44
- * - Reads and updates the index metadata file via `fileManager.ReadFile` / `WriteFile`.
45
- * - Uses the configured `converter` to serialize/deserialize index and metadata content.
91
+ * JSONL index structure (header + no entries).
92
+ * 3. Appends a JSONL line to `index.meta.jsonl` for each new index no read-modify-rewrite.
46
93
  *
47
- * Notes:
48
- * - The operation is not atomic: some indexes may be created while others fail. The method will
49
- * collect created and failed index names and include them in the returned response.
50
- * - A failure is recorded for a field when the index file already exists, when the index already
51
- * exists in the metadata, or when reading/writing the metadata file fails.
52
- * - The method relies on `indexFolderPath`, `indexMetaPath`, `fileManager`, and `converter`
53
- * being correctly configured and available on the instance.
54
- *
55
- * @param fieldNames - One or more field names for which to create indexes.
56
- * @returns A promise that resolves to either:
57
- * - SuccessInterface: indicates which indexes were created and which already existed / failed,
58
- * typically containing a human-readable message listing affected and existing indexes.
59
- * - ErrorInterface: returned when underlying file/IO operations fail in a way that prevents
60
- * producing the expected success response.
61
- *
62
- * @example
63
- * // Create a single index
64
- * await service.createIndex('email');
65
- *
66
- * @example
67
- * // Create multiple indexes
68
- * await service.createIndex('email', 'username', 'createdAt');
94
+ * Creates are now O(1) appends instead of O(N) full-file rewrites for meta.
69
95
  */
70
96
  createIndex(...fieldNames) {
71
97
  return __awaiter(this, void 0, void 0, function* () {
@@ -73,7 +99,7 @@ class IndexManager {
73
99
  const FailedIndexes = [];
74
100
  for (const fieldName of fieldNames) {
75
101
  const indexName = fieldName;
76
- const indexFilePath = `${this.indexFolderPath}/${indexName}${Keys_1.General.DBMS_File_EXT}`;
102
+ const indexFilePath = `${this.indexFolderPath}/${indexName}${INDEX_EXT}`;
77
103
  const DemoIndexHash = {
78
104
  fieldName: indexName,
79
105
  indexEntries: {},
@@ -81,21 +107,26 @@ class IndexManager {
81
107
  };
82
108
  const exists = yield this.fileManager.FileExists(indexFilePath);
83
109
  if (!exists.status) {
84
- // create empty index file
85
- yield this.fileManager.WriteFile(indexFilePath, this.converter.ToString(DemoIndexHash));
86
- // Update index.meta.json
87
- const indexMetaContent = yield this.fileManager.ReadFile(this.indexMetaPath);
88
- if (indexMetaContent.status) {
89
- const indexMeta = this.converter.ToObject(indexMetaContent.data);
90
- // check if index already exists in meta
91
- const indexExists = indexMeta.find((index) => index.indexFieldName === indexName);
110
+ // create empty index file in JSONL format
111
+ yield this.fileManager.WriteFile(indexFilePath, IndexManager.serializeIndexData(DemoIndexHash));
112
+ // Append to index.meta.jsonl (O(1) — no read-modify-rewrite)
113
+ const metaEntry = {
114
+ indexFieldName: indexName,
115
+ fileName: `${indexName}${INDEX_EXT}`,
116
+ path: indexFilePath,
117
+ };
118
+ const existsMeta = yield this.fileManager.FileExists(this.indexMetaPath);
119
+ if (!existsMeta.status) {
120
+ // First index — write the initial meta file
121
+ yield this.fileManager.WriteFile(this.indexMetaPath, this.converter.ToString(metaEntry) + "\n");
122
+ EffectedIndexes.push(indexName);
123
+ }
124
+ else {
125
+ // Check for duplicate by streaming meta lines (stop on first match)
126
+ const existingMeta = yield this.listMetaEntries();
127
+ const indexExists = existingMeta.some((entry) => entry.indexFieldName === indexName);
92
128
  if (!indexExists) {
93
- indexMeta.push({
94
- indexFieldName: indexName,
95
- fileName: `${indexName}${Keys_1.General.DBMS_File_EXT}`,
96
- path: indexFilePath,
97
- });
98
- yield this.fileManager.WriteFile(this.indexMetaPath, this.converter.ToString(indexMeta));
129
+ yield this.fileManager.AppendFile(this.indexMetaPath, this.converter.ToString(metaEntry) + "\n");
99
130
  EffectedIndexes.push(indexName);
100
131
  }
101
132
  else {
@@ -116,41 +147,24 @@ class IndexManager {
116
147
  }
117
148
  /**
118
149
  * Deletes an index file and removes its entry from the index metadata.
119
- *
120
- * This asynchronous method attempts to delete the index file located at
121
- * `${this.indexFolderPath}/${indexName}.axiodb`. If the file exists it is removed,
122
- * and the index metadata file at `this.indexMetaPath` is read and updated by
123
- * filtering out the metadata entry whose `indexFieldName` matches `indexName`.
124
- * The metadata update is performed only if the metadata file can be read successfully.
125
- *
126
- * @param indexName - The name of the index to delete (without extension).
127
- * @returns A Promise that resolves to a SuccessInterface when the index was deleted
128
- * (and metadata updated when possible), or an ErrorInterface when the
129
- * specified index does not exist.
130
- *
131
- * @async
132
- * @remarks
133
- * - Side effects: removes a file from the file system and may modify the index metadata file.
134
- * - Uses injected helpers: `fileManager` for filesystem operations, `converter` for
135
- * (de)serialization of metadata, and `ResponseHelper` to construct the returned result.
136
- * - If the metadata file cannot be read, the method still succeeds after deleting the index file.
137
- *
138
- * @throws {Error} May propagate errors from underlying file operations if those utilities throw.
139
150
  */
140
151
  dropIndex(indexName) {
141
152
  return __awaiter(this, void 0, void 0, function* () {
142
- const indexFilePath = `${this.indexFolderPath}/${indexName}${Keys_1.General.DBMS_File_EXT}`;
153
+ const indexFilePath = `${this.indexFolderPath}/${indexName}${INDEX_EXT}`;
143
154
  // check if index file exists
144
155
  const exists = yield this.fileManager.FileExists(indexFilePath);
145
156
  if (exists.status === true) {
146
157
  // delete index file
147
158
  yield this.fileManager.DeleteFile(indexFilePath);
148
- // update index.meta.json
149
- const indexMetaContent = yield this.fileManager.ReadFile(this.indexMetaPath);
150
- if (indexMetaContent.status) {
151
- let indexMeta = this.converter.ToObject(indexMetaContent.data);
152
- indexMeta = indexMeta.filter((index) => index.indexFieldName !== indexName);
153
- yield this.fileManager.WriteFile(this.indexMetaPath, this.converter.ToString(indexMeta));
159
+ // update index.meta.jsonl — stream-filter instead of full parse+rewrite
160
+ const existingMeta = yield this.listMetaEntries();
161
+ const filtered = existingMeta.filter((entry) => entry.indexFieldName !== indexName);
162
+ if (filtered.length === 0) {
163
+ yield this.fileManager.DeleteFile(this.indexMetaPath);
164
+ }
165
+ else {
166
+ const lines = filtered.map((e) => this.converter.ToString(e)).join("\n") + "\n";
167
+ yield this.fileManager.WriteFile(this.indexMetaPath, lines);
154
168
  }
155
169
  return this.ResponseHelper.Success(`Index: ${indexName} deleted successfully`);
156
170
  }
@@ -161,100 +175,66 @@ class IndexManager {
161
175
  }
162
176
  /**
163
177
  * Lists all indexes currently registered for this collection.
164
- *
165
- * Reads the index metadata file (`index.meta.json`) and returns its parsed entries as-is —
166
- * this is a pure read of the same metadata `createIndex`/`dropIndex` already maintain, no new
167
- * storage format is introduced.
168
- *
169
- * @returns A promise that resolves to a SuccessInterface containing the list of index metadata
170
- * entries (`{ indexFieldName, fileName, path }`), or an ErrorInterface if the metadata
171
- * file could not be read.
172
- *
173
- * @example
174
- * const result = await service.listIndexes();
178
+ * Now uses streaming ReadLines for memory efficiency.
175
179
  */
176
180
  listIndexes() {
177
181
  return __awaiter(this, void 0, void 0, function* () {
178
- const indexMetaContent = yield this.fileManager.ReadFile(this.indexMetaPath);
179
- if (indexMetaContent.status) {
180
- const indexMeta = this.converter.ToObject(indexMetaContent.data);
182
+ try {
183
+ const indexMeta = yield this.listMetaEntries();
181
184
  return this.ResponseHelper.Success(indexMeta);
182
185
  }
183
- return this.ResponseHelper.Error("Failed to read index metadata");
186
+ catch (_a) {
187
+ return this.ResponseHelper.Error("Failed to read index metadata");
188
+ }
184
189
  });
185
190
  }
186
191
  /**
187
192
  * Ensures the index folder and the index metadata file exist, creating them if necessary.
188
- *
189
- * This asynchronous method performs the following steps:
190
- * 1. Checks whether the index folder at `this.indexFolderPath` exists; if not, creates it.
191
- * 2. Checks whether the index metadata file at `this.indexMetaPath` exists; if not:
192
- * a. Constructs a default index metadata entry for a unique "documentId" index:
193
- * - indexFieldName: "documentId"
194
- * - fileName: "documentId.axiodb"
195
- * - path: `${this.indexFolderPath}/documentId.axiodb`
196
- * - unique: true
197
- * b. Calls `this.createIndex("documentId")` to create the underlying index file/structure.
198
- * c. Writes the metadata array to `this.indexMetaPath` using `this.converter.ToString(...)`.
199
- *
200
- * The operation is idempotent: if the folder or metadata file already exist, no changes are made.
201
- *
202
- * @remarks
203
- * - This method performs filesystem modifications via `folderManager` and `fileManager`.
204
- * - Any errors thrown by `folderManager`, `fileManager`, `converter`, or `createIndex` will propagate to the caller.
205
- * - Callers should `await` this method to ensure the initialization is complete before proceeding.
206
- *
207
- * @returns A Promise that resolves when initialization is complete.
208
- *
209
- * @throws Will reject if directory creation, file checks/writes, conversion, or index creation fails.
210
- *
211
- * @example
212
- * // Ensure index folder and metadata exist before using the index service
213
- * await indexService.generateIndexMeta();
214
193
  */
215
194
  generateIndexMeta() {
216
195
  return __awaiter(this, void 0, void 0, function* () {
217
- // check is index.meta.json exists or not
196
+ // check if index.meta.jsonl exists or not
218
197
  const folderExists = yield this.folderManager.DirectoryExists(this.indexFolderPath);
219
198
  if (!folderExists.status) {
220
199
  yield this.folderManager.CreateDirectory(this.indexFolderPath);
221
200
  }
222
201
  const exists = yield this.fileManager.FileExists(this.indexMetaPath);
223
202
  if (!exists.status) {
224
- // create index.meta.json
225
- const indexMeta = [
226
- {
227
- indexFieldName: "documentId",
228
- path: `${this.indexFolderPath}/documentId${Keys_1.General.DBMS_File_EXT}`,
229
- fileName: `documentId${Keys_1.General.DBMS_File_EXT}`
230
- }
231
- ];
203
+ // create index.meta.jsonl + documentId index file
204
+ const metaEntry = {
205
+ indexFieldName: "documentId",
206
+ path: `${this.indexFolderPath}/documentId${INDEX_EXT}`,
207
+ fileName: `documentId${INDEX_EXT}`,
208
+ };
209
+ yield this.fileManager.WriteFile(this.indexMetaPath, this.converter.ToString(metaEntry) + "\n");
232
210
  yield this.createIndex("documentId");
233
- yield this.fileManager.WriteFile(this.indexMetaPath, this.converter.ToString(indexMeta));
234
211
  }
235
212
  });
236
213
  }
214
+ /**
215
+ * Streams index.meta.jsonl lines into an array of IndexMetaEntry objects.
216
+ */
217
+ listMetaEntries() {
218
+ return __awaiter(this, void 0, void 0, function* () {
219
+ const lines = yield this.fileManager.ReadLines(this.indexMetaPath);
220
+ return lines.map(line => this.converter.ToObject(line));
221
+ });
222
+ }
237
223
  /**
238
224
  * Finds index metadata entries that correspond to properties present on the provided document.
239
- *
240
- * Reads the index metadata file at `this.indexMetaPath`, converts its content into an object,
241
- * and returns the subset of metadata entries whose `indexFieldName` is an own property of `doc`.
242
- *
243
- * @param doc - The document to check for matching index fields. The function tests own properties
244
- * (via `Object.prototype.hasOwnProperty.call`) rather than inherited properties.
245
- * @returns A Promise that resolves to an array of matching index metadata entries, or `undefined`
246
- * if the index metadata file could not be successfully read. The array may be empty if
247
- * no metadata entries match.
248
- *
249
- * @throws May propagate errors from `fileManager.ReadFile` or `converter.ToObject` if those
250
- * operations throw or reject.
225
+ * Streams meta file, returns first match (doesn't parse the entire file).
251
226
  */
252
227
  findMatchingIndexMeta(doc) {
253
228
  return __awaiter(this, void 0, void 0, function* () {
254
- const indexMetaContent = yield this.fileManager.ReadFile(this.indexMetaPath);
255
- if (indexMetaContent.status) {
256
- const indexMeta = this.converter.ToObject(indexMetaContent.data);
257
- return indexMeta.filter((meta) => Object.prototype.hasOwnProperty.call(doc, meta.indexFieldName));
229
+ try {
230
+ const lines = yield this.fileManager.ReadLines(this.indexMetaPath);
231
+ if (lines.length === 0)
232
+ return undefined;
233
+ const entries = lines.map(line => this.converter.ToObject(line));
234
+ return entries.filter((meta) => Object.prototype.hasOwnProperty.call(doc, meta.indexFieldName));
235
+ }
236
+ catch (_a) {
237
+ return undefined;
258
238
  }
259
239
  });
260
240
  }