inibase 1.0.0-rc.83 → 1.0.0-rc.85

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.
package/dist/index.d.ts CHANGED
@@ -66,27 +66,27 @@ export default class Inibase {
66
66
  /**
67
67
  * Create a new table inside database, with predefined schema and config
68
68
  *
69
- * @param {string} tableName
69
+ * @param {(string|number)} tableName
70
70
  * @param {Schema} [schema]
71
71
  * @param {Config} [config]
72
72
  */
73
- createTable(tableName: string, schema?: Schema, config?: Config): Promise<void>;
73
+ createTable(tableName: string | number, schema?: Schema, config?: Config): Promise<void>;
74
74
  /**
75
75
  * Update table schema or config
76
76
  *
77
- * @param {string} tableName
77
+ * @param {(string|number)} tableName
78
78
  * @param {Schema} [schema]
79
79
  * @param {Config} [config]
80
80
  */
81
- updateTable(tableName: string, schema?: Schema, config?: Config): Promise<void>;
81
+ updateTable(tableName: string | number, schema?: Schema, config?: Config): Promise<void>;
82
82
  /**
83
83
  * Get table schema and config
84
84
  *
85
- * @param {string} tableName
85
+ * @param {(string|number)} tableName
86
86
  * @return {*} {Promise<TableObject>}
87
87
  */
88
- getTable(tableName: string): Promise<TableObject>;
89
- getTableSchema(tableName: string, encodeIDs?: boolean): Promise<Schema | undefined>;
88
+ getTable(tableName: string | number): Promise<TableObject>;
89
+ getTableSchema(tableName: string | number, encodeIDs?: boolean): Promise<Schema | undefined>;
90
90
  private throwErrorIfTableEmpty;
91
91
  private validateData;
92
92
  private formatField;
@@ -103,84 +103,85 @@ export default class Inibase {
103
103
  /**
104
104
  * Clear table cache
105
105
  *
106
- * @param {string} tableName
106
+ * @param {(string|number)} tableName
107
107
  */
108
- clearCache(tableName: string): Promise<void>;
108
+ clearCache(tableName: string | number): Promise<void>;
109
109
  /**
110
110
  * Retrieve item(s) from a table
111
111
  *
112
- * @param {string} tableName
113
- * @param {(string | number | (string | number)[] | Criteria | undefined)} [where]
114
- * @param {(Options | undefined)} [options]
112
+ * @param {(string|number)} tableName
113
+ * @param {(string | number | (string | number)[] | Criteria)} [where]
114
+ * @param {Options} [options]
115
115
  * @param {boolean} [onlyOne]
116
116
  * @param {boolean} [onlyLinesNumbers]
117
- * @return {*} {(Promise<Data[] | Data | number[] | null>)}
117
+ * @return {*} {(Promise<Data | number | (Data | number)[] | null>)}
118
118
  */
119
- get(tableName: string, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: true, onlyLinesNumbers?: false): Promise<Data | null>;
120
- get(tableName: string, where: string | number, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data | null>;
121
- get(tableName: string, where?: string | number | (string | number)[] | Criteria, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data[] | null>;
122
- get(tableName: string, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: boolean | undefined, onlyLinesNumbers: true): Promise<number[]>;
119
+ get(tableName: string | number, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: true, onlyLinesNumbers?: false): Promise<Data | null>;
120
+ get(tableName: string | number, where: string | number, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data | null>;
121
+ get(tableName: string | number, where?: string | number | (string | number)[] | Criteria, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data[] | null>;
122
+ get(tableName: string | number, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: false | undefined, onlyLinesNumbers: true): Promise<number[] | null>;
123
+ get(tableName: string | number, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: true, onlyLinesNumbers: true): Promise<number | null>;
123
124
  /**
124
125
  * Create new item(s) in a table
125
126
  *
126
- * @param {string} tableName
127
+ * @param {(string|number)} tableName
127
128
  * @param {(Data | Data[])} data Can be array of objects or a single object
128
129
  * @param {Options} [options] Pagination options, useful when the returnPostedData param is true
129
130
  * @param {boolean} [returnPostedData] By default function returns void, if you want to get the posted data, set this param to true
130
131
  * @return {*} {Promise<Data | Data[] | null | void>}
131
132
  */
132
- post(tableName: string, data: Data | Data[], options?: Options, returnPostedData?: boolean): Promise<void>;
133
- post(tableName: string, data: Data, options: Options | undefined, returnPostedData: true): Promise<Data | null>;
134
- post(tableName: string, data: Data[], options: Options | undefined, returnPostedData: true): Promise<Data[] | null>;
133
+ post(tableName: string | number, data: Data | Data[], options?: Options, returnPostedData?: boolean): Promise<void>;
134
+ post(tableName: string | number, data: Data, options: Options | undefined, returnPostedData: true): Promise<Data | null>;
135
+ post(tableName: string | number, data: Data[], options: Options | undefined, returnPostedData: true): Promise<Data[] | null>;
135
136
  /**
136
137
  * Update item(s) in a table
137
138
  *
138
- * @param {string} tableName
139
+ * @param {(string|number)} tableName
139
140
  * @param {(Data | Data[])} data
140
141
  * @param {(number | string | (number | string)[] | Criteria)} [where]
141
142
  * @param {Options} [options]
142
143
  * @param {false} [returnUpdatedData]
143
144
  * @return {*} {Promise<Data | Data[] | null | undefined | void>}
144
145
  */
145
- put(tableName: string, data: Data | Data[], where?: number | string | (number | string)[] | Criteria, options?: Options, returnUpdatedData?: false): Promise<void>;
146
- put(tableName: string, data: Data, where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true): Promise<Data | null>;
147
- put(tableName: string, data: Data[], where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true): Promise<Data[] | null>;
146
+ put(tableName: string | number, data: Data | Data[], where?: number | string | (number | string)[] | Criteria, options?: Options, returnUpdatedData?: false): Promise<void>;
147
+ put(tableName: string | number, data: Data, where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true): Promise<Data | null>;
148
+ put(tableName: string | number, data: Data[], where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true): Promise<Data[] | null>;
148
149
  /**
149
150
  * Delete item(s) in a table
150
151
  *
151
- * @param {string} tableName
152
+ * @param {(string|number)} tableName
152
153
  * @param {(number | string | (number | string)[] | Criteria)} [where]
153
154
  * @return {boolean | null} {(Promise<boolean | null>)}
154
155
  */
155
- delete(tableName: string, where?: number | string | (number | string)[] | Criteria, _id?: string | string[]): Promise<boolean | null>;
156
+ delete(tableName: string | number, where?: number | string | (number | string)[] | Criteria, _id?: string | string[]): Promise<boolean | null>;
156
157
  /**
157
158
  * Generate sum of column(s) in a table
158
159
  *
159
- * @param {string} tableName
160
+ * @param {(string|number)} tableName
160
161
  * @param {string} columns
161
162
  * @param {(number | string | (number | string)[] | Criteria)} [where]
162
163
  * @return {*} {Promise<number | Record<string, number>>}
163
164
  */
164
- sum(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
165
- sum(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
165
+ sum(tableName: string | number, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
166
+ sum(tableName: string | number, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
166
167
  /**
167
168
  * Generate max of column(s) in a table
168
169
  *
169
- * @param {string} tableName
170
+ * @param {(string|number)} tableName
170
171
  * @param {string} columns
171
172
  * @param {(number | string | (number | string)[] | Criteria)} [where]
172
173
  * @return {*} {Promise<number>}
173
174
  */
174
- max(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
175
- max(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
175
+ max(tableName: string | number, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
176
+ max(tableName: string | number, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
176
177
  /**
177
178
  * Generate min of column(s) in a table
178
179
  *
179
- * @param {string} tableName
180
+ * @param {(string|number)} tableName
180
181
  * @param {string} columns
181
182
  * @param {(number | string | (number | string)[] | Criteria)} [where]
182
183
  * @return {*} {Promise<number>}
183
184
  */
184
- min(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
185
- min(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
185
+ min(tableName: string | number, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
186
+ min(tableName: string | number, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
186
187
  }
package/dist/index.js CHANGED
@@ -84,14 +84,14 @@ export default class Inibase {
84
84
  /**
85
85
  * Create a new table inside database, with predefined schema and config
86
86
  *
87
- * @param {string} tableName
87
+ * @param {(string|number)} tableName
88
88
  * @param {Schema} [schema]
89
89
  * @param {Config} [config]
90
90
  */
91
91
  async createTable(tableName, schema, config) {
92
- const tablePath = join(this.databasePath, tableName);
92
+ const tablePath = join(this.databasePath, tableName.toString());
93
93
  if (await File.isExists(tablePath))
94
- throw this.throwError("TABLE_EXISTS", tableName);
94
+ throw this.throwError("TABLE_EXISTS", tableName.toString());
95
95
  await mkdir(join(tablePath, ".tmp"), { recursive: true });
96
96
  await mkdir(join(tablePath, ".cache"));
97
97
  // if config not set => load default global env config
@@ -115,17 +115,17 @@ export default class Inibase {
115
115
  /**
116
116
  * Update table schema or config
117
117
  *
118
- * @param {string} tableName
118
+ * @param {(string|number)} tableName
119
119
  * @param {Schema} [schema]
120
120
  * @param {Config} [config]
121
121
  */
122
122
  async updateTable(tableName, schema, config) {
123
- const table = await this.getTable(tableName), tablePath = join(this.databasePath, tableName);
123
+ const table = await this.getTable(tableName), tablePath = join(this.databasePath, tableName.toString());
124
124
  if (config) {
125
125
  if (config.compression !== undefined &&
126
126
  config.compression !== table.config.compression) {
127
127
  await UtilsServer.execFile("find", [
128
- tableName,
128
+ tableName.toString(),
129
129
  "-type",
130
130
  "f",
131
131
  "-name",
@@ -150,7 +150,7 @@ export default class Inibase {
150
150
  if (config.prepend !== undefined &&
151
151
  config.prepend !== table.config.prepend) {
152
152
  await UtilsServer.execFile("find", [
153
- tableName,
153
+ tableName.toString(),
154
154
  "-type",
155
155
  "f",
156
156
  "-name",
@@ -197,13 +197,13 @@ export default class Inibase {
197
197
  /**
198
198
  * Get table schema and config
199
199
  *
200
- * @param {string} tableName
200
+ * @param {(string|number)} tableName
201
201
  * @return {*} {Promise<TableObject>}
202
202
  */
203
203
  async getTable(tableName) {
204
- const tablePath = join(this.databasePath, tableName);
204
+ const tablePath = join(this.databasePath, tableName.toString());
205
205
  if (!(await File.isExists(tablePath)))
206
- throw this.throwError("TABLE_NOT_EXISTS", tableName);
206
+ throw this.throwError("TABLE_NOT_EXISTS", tableName.toString());
207
207
  if (!this.tables[tableName])
208
208
  this.tables[tableName] = {
209
209
  schema: await this.getTableSchema(tableName),
@@ -216,7 +216,7 @@ export default class Inibase {
216
216
  return this.tables[tableName];
217
217
  }
218
218
  async getTableSchema(tableName, encodeIDs = true) {
219
- const tableSchemaPath = join(this.databasePath, tableName, "schema.json");
219
+ const tableSchemaPath = join(this.databasePath, tableName.toString(), "schema.json");
220
220
  if (!(await File.isExists(tableSchemaPath)))
221
221
  return undefined;
222
222
  const schemaFile = await readFile(tableSchemaPath, "utf8");
@@ -252,9 +252,9 @@ export default class Inibase {
252
252
  async throwErrorIfTableEmpty(tableName) {
253
253
  const table = await this.getTable(tableName);
254
254
  if (!table.schema)
255
- throw this.throwError("NO_SCHEMA", tableName);
256
- if (!(await File.isExists(join(this.databasePath, tableName, `id${this.getFileExtension(tableName)}`))))
257
- throw this.throwError("NO_ITEMS", tableName);
255
+ throw this.throwError("NO_SCHEMA", tableName.toString());
256
+ if (!(await File.isExists(join(this.databasePath, tableName.toString(), `id${this.getFileExtension(tableName)}`))))
257
+ throw this.throwError("NO_ITEMS", tableName.toString());
258
258
  return table;
259
259
  }
260
260
  validateData(data, schema, skipRequiredField = false) {
@@ -364,7 +364,7 @@ export default class Inibase {
364
364
  return null;
365
365
  }
366
366
  async checkUnique(tableName, schema) {
367
- const tablePath = join(this.databasePath, tableName);
367
+ const tablePath = join(this.databasePath, tableName.toString());
368
368
  for await (const [key, values] of Object.entries(this.checkIFunique)) {
369
369
  const field = Utils.getField(key, schema);
370
370
  if (!field)
@@ -456,7 +456,7 @@ export default class Inibase {
456
456
  return RETURN;
457
457
  };
458
458
  joinPathesContents(tableName, data) {
459
- const tablePath = join(this.databasePath, tableName), combinedData = this._CombineData(data);
459
+ const tablePath = join(this.databasePath, tableName.toString()), combinedData = this._CombineData(data);
460
460
  const newCombinedData = {};
461
461
  for (const [key, value] of Object.entries(combinedData))
462
462
  newCombinedData[join(tablePath, `${key}${this.getFileExtension(tableName)}`)] = value;
@@ -504,8 +504,8 @@ export default class Inibase {
504
504
  }
505
505
  }
506
506
  async getItemsFromSchema(tableName, schema, linesNumber, options, prefix) {
507
- const tablePath = join(this.databasePath, tableName);
508
- let RETURN = {};
507
+ const tablePath = join(this.databasePath, tableName.toString());
508
+ const RETURN = {};
509
509
  for await (const field of schema) {
510
510
  if ((field.type === "array" ||
511
511
  (Array.isArray(field.type) && field.type.includes("array"))) &&
@@ -577,18 +577,18 @@ export default class Inibase {
577
577
  if (field.table &&
578
578
  (await File.isExists(join(this.databasePath, field.table))) &&
579
579
  (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`)))) {
580
- if (options.columns)
581
- options.columns = options.columns
582
- .filter((column) => column.includes(`${field.key}.`))
583
- .map((column) => column.replace(`${field.key}.`, ""));
584
580
  const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`), linesNumber, field.type, field.children, this.salt);
585
581
  if (items)
586
582
  for await (const [index, item] of Object.entries(items)) {
587
583
  if (!RETURN[index])
588
584
  RETURN[index] = {};
589
- RETURN[index][field.key] = item
590
- ? await this.get(field.table, item, options)
591
- : this.getDefaultValue(field);
585
+ if (item !== null && item !== undefined)
586
+ RETURN[index][field.key] = await this.get(field.table, item, {
587
+ ...options,
588
+ columns: options.columns
589
+ ?.filter((column) => column.includes(`${field.key}.`))
590
+ .map((column) => column.replace(`${field.key}.`, "")),
591
+ });
592
592
  }
593
593
  }
594
594
  }
@@ -598,7 +598,8 @@ export default class Inibase {
598
598
  for (const [index, item] of Object.entries(items)) {
599
599
  if (!RETURN[index])
600
600
  RETURN[index] = {};
601
- RETURN[index][field.key] = item ?? this.getDefaultValue(field);
601
+ if (item !== null && item !== undefined)
602
+ RETURN[index][field.key] = item;
602
603
  }
603
604
  }
604
605
  }
@@ -611,29 +612,25 @@ export default class Inibase {
611
612
  if (Utils.isObject(item)) {
612
613
  if (!Object.values(item).every((i) => i === null))
613
614
  RETURN[index][field.key] = item;
614
- else
615
- RETURN[index][field.key] = null;
616
615
  }
617
- else
618
- RETURN[index][field.key] = null;
619
616
  }
620
617
  }
621
618
  else if (field.type === "table") {
622
619
  if (field.table &&
623
620
  (await File.isExists(join(this.databasePath, field.table))) &&
624
621
  (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`)))) {
625
- if (options.columns)
626
- options.columns = options.columns
627
- .filter((column) => column.includes(`${field.key}.`))
628
- .map((column) => column.replace(`${field.key}.`, ""));
629
622
  const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`), linesNumber, "number", undefined, this.salt);
630
623
  if (items)
631
624
  for await (const [index, item] of Object.entries(items)) {
632
625
  if (!RETURN[index])
633
626
  RETURN[index] = {};
634
- RETURN[index][field.key] = item
635
- ? await this.get(field.table, UtilsServer.encodeID(item, this.salt), options)
636
- : this.getDefaultValue(field);
627
+ if (item !== null && item !== undefined)
628
+ RETURN[index][field.key] = await this.get(field.table, UtilsServer.encodeID(item, this.salt), {
629
+ ...options,
630
+ columns: options.columns
631
+ ?.filter((column) => column.includes(`${field.key}.`))
632
+ .map((column) => column.replace(`${field.key}.`, "")),
633
+ });
637
634
  }
638
635
  }
639
636
  }
@@ -643,19 +640,22 @@ export default class Inibase {
643
640
  for (const [index, item] of Object.entries(items)) {
644
641
  if (!RETURN[index])
645
642
  RETURN[index] = {};
646
- RETURN[index][field.key] = item ?? this.getDefaultValue(field);
643
+ if (item !== null && item !== undefined)
644
+ RETURN[index][field.key] = item;
647
645
  }
648
- else
649
- RETURN = Object.fromEntries(Object.entries(RETURN).map(([index, data]) => [
650
- index,
651
- { ...data, [field.key]: this.getDefaultValue(field) },
652
- ]));
646
+ // else
647
+ // RETURN = Object.fromEntries(
648
+ // Object.entries(RETURN).map(([index, data]) => [
649
+ // index,
650
+ // { ...data, [field.key]: this.getDefaultValue(field) },
651
+ // ]),
652
+ // );
653
653
  }
654
654
  }
655
655
  return RETURN;
656
656
  }
657
657
  async applyCriteria(tableName, schema, options, criteria, allTrue) {
658
- const tablePath = join(this.databasePath, tableName);
658
+ const tablePath = join(this.databasePath, tableName.toString());
659
659
  let RETURN = {}, RETURN_LineNumbers = null;
660
660
  if (!criteria)
661
661
  return [null, null];
@@ -785,10 +785,10 @@ export default class Inibase {
785
785
  /**
786
786
  * Clear table cache
787
787
  *
788
- * @param {string} tableName
788
+ * @param {(string|number)} tableName
789
789
  */
790
790
  async clearCache(tableName) {
791
- const cacheFolderPath = join(this.databasePath, tableName, ".cache");
791
+ const cacheFolderPath = join(this.databasePath, tableName.toString(), ".cache");
792
792
  await Promise.all((await readdir(cacheFolderPath))
793
793
  .filter((file) => file !== ".pagination")
794
794
  .map((file) => unlink(join(cacheFolderPath, file))));
@@ -797,7 +797,7 @@ export default class Inibase {
797
797
  page: 1,
798
798
  perPage: 15,
799
799
  }, onlyOne, onlyLinesNumbers) {
800
- const tablePath = join(this.databasePath, tableName);
800
+ const tablePath = join(this.databasePath, tableName.toString());
801
801
  // Ensure options.columns is an array
802
802
  if (options.columns) {
803
803
  options.columns = Array.isArray(options.columns)
@@ -812,7 +812,7 @@ export default class Inibase {
812
812
  let RETURN;
813
813
  let schema = (await this.getTable(tableName)).schema;
814
814
  if (!schema)
815
- throw this.throwError("NO_SCHEMA", tableName);
815
+ throw this.throwError("NO_SCHEMA", tableName.toString());
816
816
  if (!(await File.isExists(join(tablePath, `id${this.getFileExtension(tableName)}`))))
817
817
  return null;
818
818
  if (options.columns?.length)
@@ -840,8 +840,8 @@ export default class Inibase {
840
840
  cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
841
841
  if (where) {
842
842
  const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
843
- if (!lineNumbers.length)
844
- throw this.throwError("NO_RESULTS", tableName);
843
+ if (!lineNumbers?.length)
844
+ throw this.throwError("NO_RESULTS", tableName.toString());
845
845
  const itemsIDs = Object.values((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
846
846
  awkCommand = `awk '${itemsIDs.map((id) => `$1 == ${id}`).join(" || ")}'`;
847
847
  }
@@ -952,7 +952,7 @@ export default class Inibase {
952
952
  Ids = [Ids];
953
953
  const [lineNumbers, countItems] = await File.search(join(tablePath, `id${this.getFileExtension(tableName)}`), "[]", Ids.map((id) => Utils.isNumber(id) ? Number(id) : UtilsServer.decodeID(id, this.salt)), undefined, "number", undefined, Ids.length, 0, !this.totalItems[`${tableName}-*`], this.salt);
954
954
  if (!lineNumbers)
955
- throw this.throwError("NO_RESULTS", tableName);
955
+ throw this.throwError("NO_RESULTS", tableName.toString());
956
956
  if (!this.totalItems[`${tableName}-*`])
957
957
  this.totalItems[`${tableName}-*`] = countItems;
958
958
  if (onlyLinesNumbers)
@@ -979,18 +979,20 @@ export default class Inibase {
979
979
  if (!this.totalItems[`${tableName}-*`])
980
980
  this.totalItems[`${tableName}-*`] = cachedItems.length;
981
981
  if (onlyLinesNumbers)
982
- return cachedItems.map(Number);
982
+ return onlyOne ? Number(cachedItems[0]) : cachedItems.map(Number);
983
983
  return this.get(tableName, cachedItems
984
984
  .slice((options.page - 1) * options.perPage, options.page * options.perPage)
985
- .map(Number), options);
985
+ .map(Number), options, onlyOne);
986
986
  }
987
987
  let linesNumbers = null;
988
988
  [RETURN, linesNumbers] = await this.applyCriteria(tableName, schema, options, where);
989
- if (RETURN && linesNumbers) {
989
+ if (RETURN && linesNumbers?.size) {
990
990
  if (!this.totalItems[`${tableName}-*`])
991
991
  this.totalItems[`${tableName}-*`] = linesNumbers.size;
992
992
  if (onlyLinesNumbers)
993
- return Array.from(linesNumbers);
993
+ return onlyOne
994
+ ? linesNumbers.values().next().value
995
+ : Array.from(linesNumbers);
994
996
  const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]), alreadyExistsColumnsIDs = Utils.flattenSchema(schema)
995
997
  .filter(({ key }) => alreadyExistsColumns.includes(key))
996
998
  .map(({ id }) => id);
@@ -1022,9 +1024,9 @@ export default class Inibase {
1022
1024
  page: 1,
1023
1025
  perPage: 15,
1024
1026
  };
1025
- const tablePath = join(this.databasePath, tableName), schema = (await this.getTable(tableName)).schema;
1027
+ const tablePath = join(this.databasePath, tableName.toString()), schema = (await this.getTable(tableName)).schema;
1026
1028
  if (!schema)
1027
- throw this.throwError("NO_SCHEMA", tableName);
1029
+ throw this.throwError("NO_SCHEMA", tableName.toString());
1028
1030
  if (!returnPostedData)
1029
1031
  returnPostedData = false;
1030
1032
  let RETURN;
@@ -1096,7 +1098,7 @@ export default class Inibase {
1096
1098
  perPage: 15,
1097
1099
  }, returnUpdatedData) {
1098
1100
  let renameList = [];
1099
- const tablePath = join(this.databasePath, tableName), schema = (await this.throwErrorIfTableEmpty(tableName)).schema;
1101
+ const tablePath = join(this.databasePath, tableName.toString()), schema = (await this.throwErrorIfTableEmpty(tableName)).schema;
1100
1102
  this.validateData(data, schema, true);
1101
1103
  await this.checkUnique(tableName, schema);
1102
1104
  data = this.formatData(data, schema, true);
@@ -1195,13 +1197,13 @@ export default class Inibase {
1195
1197
  /**
1196
1198
  * Delete item(s) in a table
1197
1199
  *
1198
- * @param {string} tableName
1200
+ * @param {(string|number)} tableName
1199
1201
  * @param {(number | string | (number | string)[] | Criteria)} [where]
1200
1202
  * @return {boolean | null} {(Promise<boolean | null>)}
1201
1203
  */
1202
1204
  async delete(tableName, where, _id) {
1203
1205
  const renameList = [];
1204
- const tablePath = join(this.databasePath, tableName);
1206
+ const tablePath = join(this.databasePath, tableName.toString());
1205
1207
  await this.throwErrorIfTableEmpty(tableName);
1206
1208
  if (!where) {
1207
1209
  try {
@@ -1258,7 +1260,7 @@ export default class Inibase {
1258
1260
  }
1259
1261
  async sum(tableName, columns, where) {
1260
1262
  const RETURN = {};
1261
- const tablePath = join(this.databasePath, tableName);
1263
+ const tablePath = join(this.databasePath, tableName.toString());
1262
1264
  await this.throwErrorIfTableEmpty(tableName);
1263
1265
  if (!Array.isArray(columns))
1264
1266
  columns = [columns];
@@ -1279,7 +1281,7 @@ export default class Inibase {
1279
1281
  }
1280
1282
  async max(tableName, columns, where) {
1281
1283
  const RETURN = {};
1282
- const tablePath = join(this.databasePath, tableName);
1284
+ const tablePath = join(this.databasePath, tableName.toString());
1283
1285
  await this.throwErrorIfTableEmpty(tableName);
1284
1286
  if (!Array.isArray(columns))
1285
1287
  columns = [columns];
@@ -1300,7 +1302,7 @@ export default class Inibase {
1300
1302
  }
1301
1303
  async min(tableName, columns, where) {
1302
1304
  const RETURN = {};
1303
- const tablePath = join(this.databasePath, tableName);
1305
+ const tablePath = join(this.databasePath, tableName.toString());
1304
1306
  await this.throwErrorIfTableEmpty(tableName);
1305
1307
  if (!Array.isArray(columns))
1306
1308
  columns = [columns];
@@ -1,10 +1,10 @@
1
- import { exec as execAsync, execFile as execFileAsync } from "node:child_process";
2
- import { gunzip as gunzipAsync, gzip as gzipAsync } from "node:zlib";
1
+ import { exec as execSync, execFile as execFileSync } from "node:child_process";
2
+ import { gunzip as gunzipSync, gzip as gzipSync } from "node:zlib";
3
3
  import type { ComparisonOperator, Field, FieldType, Schema } from "./index.js";
4
- export declare const exec: typeof execAsync.__promisify__;
5
- export declare const execFile: typeof execFileAsync.__promisify__;
6
- export declare const gzip: typeof gzipAsync.__promisify__;
7
- export declare const gunzip: typeof gunzipAsync.__promisify__;
4
+ export declare const exec: typeof execSync.__promisify__;
5
+ export declare const execFile: typeof execFileSync.__promisify__;
6
+ export declare const gzip: typeof gzipSync.__promisify__;
7
+ export declare const gunzip: typeof gunzipSync.__promisify__;
8
8
  /**
9
9
  * Generates a hashed password using SHA-256.
10
10
  *
@@ -19,22 +19,8 @@ export declare const hashPassword: (password: string) => string;
19
19
  * @param inputPassword - The plain text input password to compare against the hashed password.
20
20
  * @returns A boolean indicating whether the input password matches the hashed password.
21
21
  */
22
- export declare const comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
23
- /**
24
- * Encodes an ID using AES-256-CBC encryption.
25
- *
26
- * @param id - The ID to encode, either a number or a string.
27
- * @param secretKeyOrSalt - The secret key or salt for encryption, can be a string, number, or Buffer.
28
- * @returns The encoded ID as a hexadecimal string.
29
- */
22
+ export declare const comparePassword: (hash: string, password: string) => boolean;
30
23
  export declare const encodeID: (id: number | string, secretKeyOrSalt: string | number | Buffer) => string;
31
- /**
32
- * Decodes an encrypted ID using AES-256-CBC decryption.
33
- *
34
- * @param input - The encrypted ID as a hexadecimal string.
35
- * @param secretKeyOrSalt - The secret key or salt used for decryption, can be a string, number, or Buffer.
36
- * @returns The decoded ID as a number.
37
- */
38
24
  export declare const decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
39
25
  export declare const extractIdsFromSchema: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number[];
40
26
  /**
@@ -69,7 +55,7 @@ export declare const hashString: (str: string) => string;
69
55
  *
70
56
  * Note: Handles various data types and comparison logic, including special handling for passwords and regex patterns.
71
57
  */
72
- export declare const compare: (operator: ComparisonOperator, originalValue: string | number | boolean | null | (string | number | boolean | null)[], comparedValue: string | number | boolean | null | (string | number | boolean | null)[], fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => boolean;
58
+ export declare const compare: (operator: ComparisonOperator, originalValue: string | number | boolean | null | (string | number | boolean | null)[], comparedValue: string | number | boolean | null | (string | number | boolean | null)[], fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => Promise<boolean>;
73
59
  /**
74
60
  * Helper function to check equality based on the field type.
75
61
  *
@@ -1,12 +1,12 @@
1
- import { exec as execAsync, execFile as execFileAsync, } from "node:child_process";
1
+ import { exec as execSync, execFile as execFileSync } from "node:child_process";
2
2
  import { createCipheriv, createDecipheriv, createHash, randomBytes, scryptSync, } from "node:crypto";
3
+ import { gunzip as gunzipSync, gzip as gzipSync } from "node:zlib";
3
4
  import { promisify } from "node:util";
4
- import { gunzip as gunzipAsync, gzip as gzipAsync } from "node:zlib";
5
5
  import { detectFieldType, isArrayOfObjects, isNumber, isPassword, isValidID, } from "./utils.js";
6
- export const exec = promisify(execAsync);
7
- export const execFile = promisify(execFileAsync);
8
- export const gzip = promisify(gzipAsync);
9
- export const gunzip = promisify(gunzipAsync);
6
+ export const exec = promisify(execSync);
7
+ export const execFile = promisify(execFileSync);
8
+ export const gzip = promisify(gzipSync);
9
+ export const gunzip = promisify(gunzipSync);
10
10
  /**
11
11
  * Generates a hashed password using SHA-256.
12
12
  *
@@ -27,45 +27,40 @@ export const hashPassword = (password) => {
27
27
  * @param inputPassword - The plain text input password to compare against the hashed password.
28
28
  * @returns A boolean indicating whether the input password matches the hashed password.
29
29
  */
30
- export const comparePassword = (hashedPassword, inputPassword) => {
31
- const [salt, originalHash] = hashedPassword.split(":");
30
+ export const comparePassword = (hash, password) => {
31
+ const [salt, originalHash] = hash.split(":");
32
32
  const inputHash = createHash("sha256")
33
- .update(inputPassword + salt)
33
+ .update(password + salt)
34
34
  .digest("hex");
35
35
  return inputHash === originalHash;
36
36
  };
37
- /**
38
- * Encodes an ID using AES-256-CBC encryption.
39
- *
40
- * @param id - The ID to encode, either a number or a string.
41
- * @param secretKeyOrSalt - The secret key or salt for encryption, can be a string, number, or Buffer.
42
- * @returns The encoded ID as a hexadecimal string.
43
- */
44
- export const encodeID = (id, secretKeyOrSalt) => {
45
- let cipher;
46
- if (Buffer.isBuffer(secretKeyOrSalt))
47
- cipher = createCipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
48
- else {
49
- const salt = scryptSync(secretKeyOrSalt.toString(), `${process.env.INIBASE_SECRET ?? "inibase"}_salt`, 32);
50
- cipher = createCipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
37
+ // Cache for derived keys if using scrypt
38
+ const derivedKeyCache = new Map();
39
+ // Helper function to create cipher or decipher
40
+ const getKeyAndIv = (secretKeyOrSalt) => {
41
+ if (Buffer.isBuffer(secretKeyOrSalt)) {
42
+ return { key: secretKeyOrSalt, iv: secretKeyOrSalt.subarray(0, 16) };
43
+ }
44
+ const cacheKey = secretKeyOrSalt.toString();
45
+ let key = derivedKeyCache.get(cacheKey);
46
+ if (!key) {
47
+ key = scryptSync(cacheKey, `${INIBASE_SECRET}`, 32);
48
+ derivedKeyCache.set(cacheKey, key); // Cache the derived key
51
49
  }
50
+ return { key, iv: key.subarray(0, 16) };
51
+ };
52
+ // Ensure the environment variable is read once
53
+ const INIBASE_SECRET = process.env.INIBASE_SECRET ?? "inibase";
54
+ // Optimized encodeID
55
+ export const encodeID = (id, secretKeyOrSalt) => {
56
+ const { key, iv } = getKeyAndIv(secretKeyOrSalt);
57
+ const cipher = createCipheriv("aes-256-cbc", key, iv);
52
58
  return cipher.update(id.toString(), "utf8", "hex") + cipher.final("hex");
53
59
  };
54
- /**
55
- * Decodes an encrypted ID using AES-256-CBC decryption.
56
- *
57
- * @param input - The encrypted ID as a hexadecimal string.
58
- * @param secretKeyOrSalt - The secret key or salt used for decryption, can be a string, number, or Buffer.
59
- * @returns The decoded ID as a number.
60
- */
60
+ // Optimized decodeID
61
61
  export const decodeID = (input, secretKeyOrSalt) => {
62
- let decipher;
63
- if (Buffer.isBuffer(secretKeyOrSalt))
64
- decipher = createDecipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
65
- else {
66
- const salt = scryptSync(secretKeyOrSalt.toString(), `${process.env.INIBASE_SECRET ?? "inibase"}_salt`, 32);
67
- decipher = createDecipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
68
- }
62
+ const { key, iv } = getKeyAndIv(secretKeyOrSalt);
63
+ const decipher = createDecipheriv("aes-256-cbc", key, iv);
69
64
  return Number(decipher.update(input, "hex", "utf8") + decipher.final("utf8"));
70
65
  };
71
66
  // Function to recursively flatten an array of objects and their nested children
@@ -146,7 +141,7 @@ export const hashString = (str) => createHash("sha256").update(str).digest("hex"
146
141
  *
147
142
  * Note: Handles various data types and comparison logic, including special handling for passwords and regex patterns.
148
143
  */
149
- export const compare = (operator, originalValue, comparedValue, fieldType, fieldChildrenType) => {
144
+ export const compare = async (operator, originalValue, comparedValue, fieldType, fieldChildrenType) => {
150
145
  // Determine the field type if it's an array of potential types.
151
146
  if (Array.isArray(fieldType)) {
152
147
  fieldType = detectFieldType(String(originalValue), fieldType);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.83",
3
+ "version": "1.0.0-rc.85",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Karim Amahtil",
@@ -78,6 +78,7 @@
78
78
  "inison": "1.0.0-rc.4"
79
79
  },
80
80
  "scripts": {
81
+ "prepublish": "npx tsc",
81
82
  "build": "npx tsc",
82
83
  "benchmark": "./benchmark/run.js"
83
84
  }