inibase 1.0.0-rc.37 → 1.0.0-rc.38

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/file.js CHANGED
@@ -5,7 +5,7 @@ import { pipeline } from "node:stream/promises";
5
5
  import { createGzip, createGunzip, gzip as gzipAsync, gunzip as gunzipAsync, } from "node:zlib";
6
6
  import { promisify } from "node:util";
7
7
  import { join } from "node:path";
8
- import { detectFieldType, isArrayOfArrays, isNumber, isObject, } from "./utils.js";
8
+ import { detectFieldType, isArrayOfArrays, isNumber, isObject, isPassword, } from "./utils.js";
9
9
  import { encodeID, comparePassword } from "./utils.server.js";
10
10
  import Config from "./config.js";
11
11
  const gzip = promisify(gzipAsync);
@@ -510,8 +510,7 @@ const isEqual = (originalValue, comparedAtValue, fieldType) => {
510
510
  switch (fieldType) {
511
511
  // Password comparison.
512
512
  case "password":
513
- return typeof originalValue === "string" &&
514
- typeof comparedAtValue === "string"
513
+ return isPassword(originalValue) && typeof comparedAtValue === "string"
515
514
  ? comparePassword(originalValue, comparedAtValue)
516
515
  : false;
517
516
  // Boolean comparison.
package/dist/index.d.ts CHANGED
@@ -66,6 +66,8 @@ export default class Inibase {
66
66
  salt: Buffer;
67
67
  constructor(database: string, mainFolder?: string);
68
68
  private throwError;
69
+ private _decodeIdFromSchema;
70
+ private _schemaToIdsPath;
69
71
  setTableSchema(tableName: string, schema: Schema): Promise<void>;
70
72
  getTableSchema(tableName: string): Promise<Schema | undefined>;
71
73
  getField(keyPath: string, schema: Schema): (FieldDefault & FieldStringType) | (FieldDefault & FieldObjectType) | (FieldDefault & FieldArrayType) | null;
@@ -73,7 +75,12 @@ export default class Inibase {
73
75
  private formatField;
74
76
  private formatData;
75
77
  private getDefaultValue;
76
- private joinPathesContents;
78
+ private _combineObjectsToArray;
79
+ private _CombineData;
80
+ private _addPathToKeys;
81
+ joinPathesContents(mainPath: string, data: Data | Data[]): {
82
+ [key: string]: string[];
83
+ };
77
84
  private getItemsFromSchema;
78
85
  private applyCriteria;
79
86
  private _filterSchemaByColumns;
package/dist/index.js CHANGED
@@ -53,46 +53,47 @@ export default class Inibase {
53
53
  }
54
54
  return new Error(errorMessage);
55
55
  }
56
- async setTableSchema(tableName, schema) {
57
- const decodeIdFromSchema = (schema) => schema.map((field) => {
56
+ _decodeIdFromSchema = (schema) => schema.map((field) => {
57
+ if ((field.type === "array" || field.type === "object") &&
58
+ field.children &&
59
+ Utils.isArrayOfObjects(field.children))
60
+ field.children = this._decodeIdFromSchema(field.children);
61
+ if (field.id && !Utils.isNumber(field.id))
62
+ field.id = UtilsServer.decodeID(field.id, this.salt);
63
+ return field;
64
+ });
65
+ _schemaToIdsPath = (schema, prefix = "") => {
66
+ let RETURN = {};
67
+ for (const field of schema)
58
68
  if ((field.type === "array" || field.type === "object") &&
59
69
  field.children &&
60
- Utils.isArrayOfObjects(field.children))
61
- field.children = decodeIdFromSchema(field.children);
62
- if (field.id && !Utils.isNumber(field.id))
63
- field.id = UtilsServer.decodeID(field.id, this.salt);
64
- return field;
65
- });
70
+ Utils.isArrayOfObjects(field.children)) {
71
+ Utils.deepMerge(RETURN, this._schemaToIdsPath(field.children, (prefix ?? "") + field.key + "."));
72
+ }
73
+ else if (Utils.isValidID(field.id))
74
+ RETURN[UtilsServer.decodeID(field.id, this.salt)] =
75
+ (prefix ?? "") + field.key + ".inib";
76
+ return RETURN;
77
+ };
78
+ async setTableSchema(tableName, schema) {
79
+ const tablePath = join(this.folder, this.database, tableName), tableSchemaPath = join(tablePath, "schema.json"), isTablePathExists = await File.isExists(tablePath);
66
80
  // remove id from schema
67
81
  schema = schema.filter(({ key }) => !["id", "createdAt", "updatedAt"].includes(key));
68
- schema = UtilsServer.addIdToSchema(schema, UtilsServer.findLastIdNumber(schema, this.salt), this.salt);
69
- const tablePath = join(this.folder, this.database, tableName), tableSchemaPath = join(tablePath, "schema.json");
70
- if (!(await File.isExists(tablePath)))
82
+ schema = UtilsServer.addIdToSchema(schema, UtilsServer.findLastIdNumber(schema, this.salt), this.salt, isTablePathExists);
83
+ if (!isTablePathExists)
71
84
  await mkdir(tablePath, { recursive: true });
72
85
  if (!(await File.isExists(join(tablePath, ".tmp"))))
73
86
  await mkdir(join(tablePath, ".tmp"));
74
87
  if (await File.isExists(tableSchemaPath)) {
75
88
  // update columns files names based on field id
76
- const schemaToIdsPath = (schema, prefix = "") => {
77
- let RETURN = {};
78
- for (const field of schema)
79
- if ((field.type === "array" || field.type === "object") &&
80
- field.children &&
81
- Utils.isArrayOfObjects(field.children)) {
82
- Utils.deepMerge(RETURN, schemaToIdsPath(field.children, (prefix ?? "") + field.key + "."));
83
- }
84
- else if (Utils.isValidID(field.id))
85
- RETURN[UtilsServer.decodeID(field.id, this.salt)] =
86
- (prefix ?? "") + field.key + ".inib";
87
- return RETURN;
88
- }, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath((await this.getTableSchema(tableName)) ?? []), schemaToIdsPath(schema));
89
+ const replaceOldPathes = Utils.findChangedProperties(this._schemaToIdsPath((await this.getTableSchema(tableName)) ?? []), this._schemaToIdsPath(schema));
89
90
  if (replaceOldPathes)
90
91
  await Promise.all(Object.entries(replaceOldPathes).map(async ([oldPath, newPath]) => {
91
92
  if (await File.isExists(join(tablePath, oldPath)))
92
93
  await rename(join(tablePath, oldPath), join(tablePath, newPath));
93
94
  }));
94
95
  }
95
- await File.write(join(tablePath, "schema.json"), JSON.stringify(decodeIdFromSchema(schema), null, 2), true);
96
+ await File.write(join(tablePath, "schema.json"), JSON.stringify(isTablePathExists ? this._decodeIdFromSchema(schema) : schema, null, 2), true);
96
97
  }
97
98
  async getTableSchema(tableName) {
98
99
  const tableSchemaPath = join(this.folder, this.database, tableName, "schema.json");
@@ -225,7 +226,7 @@ export default class Inibase {
225
226
  case "password":
226
227
  if (Array.isArray(value))
227
228
  value = value[0];
228
- return typeof value === "string" && value.length === 161
229
+ return Utils.isPassword(value)
229
230
  ? value
230
231
  : UtilsServer.hashPassword(String(value));
231
232
  case "number":
@@ -292,13 +293,41 @@ export default class Inibase {
292
293
  return null;
293
294
  }
294
295
  }
296
+ _combineObjectsToArray = (input) => input.reduce((result, current) => {
297
+ for (const [key, value] of Object.entries(current))
298
+ if (!result[key])
299
+ result[key] = [value];
300
+ else
301
+ result[key].push(value);
302
+ return result;
303
+ }, {});
304
+ _CombineData = (_data, prefix) => {
305
+ let RETURN = {};
306
+ if (Utils.isArrayOfObjects(_data))
307
+ RETURN = this._combineObjectsToArray(_data.map((single_data) => this._CombineData(single_data)));
308
+ else
309
+ for (const [key, value] of Object.entries(_data)) {
310
+ if (Utils.isObject(value))
311
+ Object.assign(RETURN, this._CombineData(value, `${key}.`));
312
+ else if (Utils.isArrayOfObjects(value)) {
313
+ Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value), (prefix ?? "") + key + "."));
314
+ }
315
+ else if (Utils.isArrayOfArrays(value) &&
316
+ value.every(Utils.isArrayOfObjects))
317
+ Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value.map(this._combineObjectsToArray)), (prefix ?? "") + key + "."));
318
+ else
319
+ RETURN[(prefix ?? "") + key] = File.encode(value);
320
+ }
321
+ return RETURN;
322
+ };
323
+ _addPathToKeys = (obj, path) => {
324
+ const newObject = {};
325
+ for (const key in obj)
326
+ newObject[join(path, key + ".inib")] = obj[key];
327
+ return newObject;
328
+ };
295
329
  joinPathesContents(mainPath, data) {
296
- return Utils.isArrayOfObjects(data)
297
- ? Utils.combineObjects(data.map((single_data) => this.joinPathesContents(mainPath, single_data)))
298
- : Object.fromEntries(Object.entries(Utils.objectToDotNotation(data)).map(([key, value]) => [
299
- join(mainPath, key + ".inib"),
300
- File.encode(value, this.salt),
301
- ]));
330
+ return this._addPathToKeys(this._CombineData(data), mainPath);
302
331
  }
303
332
  async getItemsFromSchema(tableName, schema, linesNumber, options, prefix) {
304
333
  const tablePath = join(this.folder, this.database, tableName);
package/dist/utils.d.ts CHANGED
@@ -167,13 +167,6 @@ export declare const detectFieldType: (input: any, availableTypes: FieldType[])
167
167
  * @returns A boolean indicating whether the value matches the specified field type(s).
168
168
  */
169
169
  export declare const validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => boolean;
170
- /**
171
- * Converts a nested object to dot notation, flattening the object's structure.
172
- *
173
- * @param input - The input object to be converted.
174
- * @returns A flattened object using dot notation for keys.
175
- */
176
- export declare const objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
177
170
  export declare function FormatObjectCriteriaValue(value: string, isParentArray?: boolean): [
178
171
  ComparisonOperator,
179
172
  string | number | boolean | null | (string | number | null)[]
@@ -197,7 +190,6 @@ export default class Utils {
197
190
  static isHTML: (input: any) => boolean;
198
191
  static isIP: (input: any) => boolean;
199
192
  static validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[] | undefined) => boolean;
200
- static objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
201
193
  static isArrayOfNulls: (input: any) => input is null[] | null[][];
202
194
  static FormatObjectCriteriaValue: typeof FormatObjectCriteriaValue;
203
195
  }
package/dist/utils.js CHANGED
@@ -135,6 +135,7 @@ export const isURL = (input) => {
135
135
  else {
136
136
  var pattern = new RegExp("^(https?:\\/\\/)?" + // protocol
137
137
  "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name
138
+ "localhost|" + // OR localhost
138
139
  "((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address
139
140
  "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
140
141
  "(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
@@ -192,7 +193,7 @@ export const isBoolean = (input) => typeof input === "boolean" ||
192
193
  *
193
194
  * Note: Specifically checks for string length to determine if it matches the defined password length criterion.
194
195
  */
195
- export const isPassword = (input) => input.length === 161;
196
+ export const isPassword = (input) => typeof input === "string" && input.length === 97;
196
197
  /**
197
198
  * Checks if the input can be converted to a valid date.
198
199
  *
@@ -288,7 +289,7 @@ export const validateFieldType = (value, fieldType, fieldChildrenType) => {
288
289
  case "string":
289
290
  return isString(value);
290
291
  case "password":
291
- return isNumber(value) || isString(value) || isPassword(value);
292
+ return isNumber(value) || isPassword(value) || isString(value);
292
293
  case "number":
293
294
  return isNumber(value);
294
295
  case "html":
@@ -326,43 +327,6 @@ export const validateFieldType = (value, fieldType, fieldChildrenType) => {
326
327
  return false;
327
328
  }
328
329
  };
329
- /**
330
- * Converts a nested object to dot notation, flattening the object's structure.
331
- *
332
- * @param input - The input object to be converted.
333
- * @returns A flattened object using dot notation for keys.
334
- */
335
- export const objectToDotNotation = (input) => {
336
- const result = {};
337
- const stack = [
338
- { obj: input },
339
- ];
340
- while (stack.length > 0) {
341
- const { obj, parentKey } = stack.pop();
342
- for (const key in obj) {
343
- if (obj.hasOwnProperty(key)) {
344
- const newKey = parentKey ? `${parentKey}.${key}` : key;
345
- const value = obj[key];
346
- const isArray = Array.isArray(value);
347
- const isStringOrNumberArray = isArray &&
348
- value.every((item) => typeof item === "string" || typeof item === "number");
349
- if (isStringOrNumberArray) {
350
- // If the property is an array of strings or numbers, keep the array as is
351
- result[newKey] = value;
352
- }
353
- else if (isObject(value)) {
354
- // If the property is an object, push it onto the stack for further processing
355
- stack.push({ obj: value, parentKey: newKey });
356
- }
357
- else {
358
- // Otherwise, assign the value to the dot notation key
359
- result[newKey] = value;
360
- }
361
- }
362
- }
363
- }
364
- return result;
365
- };
366
330
  export function FormatObjectCriteriaValue(value, isParentArray = false) {
367
331
  switch (value[0]) {
368
332
  case ">":
@@ -436,7 +400,6 @@ export default class Utils {
436
400
  static isHTML = isHTML;
437
401
  static isIP = isIP;
438
402
  static validateFieldType = validateFieldType;
439
- static objectToDotNotation = objectToDotNotation;
440
403
  static isArrayOfNulls = isArrayOfNulls;
441
404
  static FormatObjectCriteriaValue = FormatObjectCriteriaValue;
442
405
  }
@@ -45,9 +45,10 @@ export declare const findLastIdNumber: (schema: Schema, secretKeyOrSalt: string
45
45
  * @param schema - The schema to update, defined as an array of schema objects.
46
46
  * @param oldIndex - The starting index for generating new IDs, defaults to 0.
47
47
  * @param secretKeyOrSalt - The secret key or salt for encoding IDs, can be a string, number, or Buffer.
48
+ * @param encodeIDs - If true, IDs will be encoded, else they will remain as numbers.
48
49
  * @returns The updated schema with encoded IDs.
49
50
  */
50
- export declare const addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer) => (({
51
+ export declare const addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer, encodeIDs?: boolean) => (({
51
52
  id?: string | number | undefined;
52
53
  key: string;
53
54
  required?: boolean | undefined;
@@ -76,7 +77,7 @@ export default class UtilsServer {
76
77
  static hashPassword: (password: string) => string;
77
78
  static comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
78
79
  static findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
79
- static addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer) => (({
80
+ static addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer, encodeIDs?: boolean | undefined) => (({
80
81
  id?: string | number | undefined;
81
82
  key: string;
82
83
  required?: boolean | undefined;
@@ -87,24 +87,25 @@ export const findLastIdNumber = (schema, secretKeyOrSalt) => {
87
87
  * @param schema - The schema to update, defined as an array of schema objects.
88
88
  * @param oldIndex - The starting index for generating new IDs, defaults to 0.
89
89
  * @param secretKeyOrSalt - The secret key or salt for encoding IDs, can be a string, number, or Buffer.
90
+ * @param encodeIDs - If true, IDs will be encoded, else they will remain as numbers.
90
91
  * @returns The updated schema with encoded IDs.
91
92
  */
92
- export const addIdToSchema = (schema, oldIndex = 0, secretKeyOrSalt) => schema.map((field) => {
93
+ export const addIdToSchema = (schema, oldIndex = 0, secretKeyOrSalt, encodeIDs) => schema.map((field) => {
93
94
  if (!field.id) {
94
95
  oldIndex++;
95
- field.id = encodeID(oldIndex, secretKeyOrSalt);
96
+ field.id = encodeIDs ? encodeID(oldIndex, secretKeyOrSalt) : oldIndex;
96
97
  }
97
98
  else {
98
99
  if (!isNumber(field.id))
99
100
  oldIndex = decodeID(field.id, secretKeyOrSalt);
100
101
  else {
101
102
  oldIndex = field.id;
102
- field.id = encodeID(field.id, secretKeyOrSalt);
103
+ field.id = encodeIDs ? encodeID(field.id, secretKeyOrSalt) : field.id;
103
104
  }
104
105
  }
105
106
  if ((field.type === "array" || field.type === "object") &&
106
107
  isArrayOfObjects(field.children)) {
107
- field.children = addIdToSchema(field.children, oldIndex, secretKeyOrSalt);
108
+ field.children = addIdToSchema(field.children, oldIndex, secretKeyOrSalt, encodeIDs);
108
109
  oldIndex += field.children.length;
109
110
  }
110
111
  return field;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.37",
3
+ "version": "1.0.0-rc.38",
4
4
  "author": {
5
5
  "name": "Karim Amahtil",
6
6
  "email": "karim.amahtil@gmail.com"