inibase 1.0.0-rc.123 → 1.0.0-rc.125

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/README.md CHANGED
@@ -106,40 +106,124 @@ interface {
106
106
  <summary>Schema</summary>
107
107
  <blockquote>
108
108
 
109
+ <details>
110
+ <summary>Types</summary>
111
+ <blockquote>
112
+
109
113
  ```ts
110
- interface {
114
+ interface Field {
111
115
  id: number; // stored as a Number but displayed as a hashed ID
112
116
  key: string;
113
117
  required?: boolean;
114
- unique?: boolean;
115
- type: "string" | "number" | "boolean" | "date" | "email" | "url" | "password" | "html" | "ip" | "json" | "id";
118
+ unique?: boolean | string; // boolean for simple uniqueness, string for grouped uniqueness
119
+ regex?: RegExp; // Regular expression for custom validation
120
+ type:
121
+ | "string"
122
+ | "number"
123
+ | "boolean"
124
+ | "date"
125
+ | "email"
126
+ | "url"
127
+ | "password"
128
+ | "html"
129
+ | "ip"
130
+ | "json"
131
+ | "id";
116
132
  }
117
- interface Table {
133
+
134
+ interface TableField {
118
135
  id: number;
119
136
  key: string;
120
137
  required?: boolean;
138
+ unique?: boolean | string; // Supports uniqueness constraints
121
139
  type: "table";
122
140
  table: string;
123
141
  }
124
- interface Array {
142
+
143
+ interface ArrayField {
125
144
  id: number;
126
145
  key: string;
127
146
  required?: boolean;
147
+ unique?: boolean | string; // Supports uniqueness constraints
128
148
  type: "array";
129
- children: string|string[];
149
+ children: string | string[]; // Can be a single type or an array of types
130
150
  }
131
- interface ObjectOrArrayOfObjects {
151
+
152
+ interface ObjectOrArrayOfObjectsField {
132
153
  id: number;
133
154
  key: string;
134
155
  required?: boolean;
156
+ unique?: boolean | string; // Supports uniqueness constraints
157
+ regex?: RegExp; // For validation of object-level keys
135
158
  type: "object" | "array";
136
- children: Schema;
159
+ children: Schema; // Nested schema for objects or arrays
160
+ }
161
+ ```
162
+
163
+ </blockquote>
164
+ </details>
165
+
166
+ <details>
167
+ <summary>Unique</summary>
168
+ <blockquote>
169
+
170
+ The `unique` property ensures that the values of a specific column or a group of columns are unique within a table. This property can be either a boolean or a string.
171
+ - **Boolean**: Setting `unique: true` ensures that the values in the column are unique across all rows.
172
+ - **String**: By setting a string value, you can group columns to enforce a combined uniqueness constraint. This is useful when you need to ensure that a combination of values across multiple fields is unique.
173
+
174
+ <details>
175
+ <summary>Examples</summary>
176
+ <blockquote>
177
+
178
+ <details>
179
+ <summary>Unique Column</summary>
180
+ <blockquote>
181
+
182
+ ```js
183
+ {
184
+ key: "email",
185
+ type: "string",
186
+ required: true,
187
+ unique: true, // Ensures all email values are unique
137
188
  }
138
189
  ```
139
190
 
140
191
  </blockquote>
141
192
  </details>
142
193
 
194
+ <details>
195
+ <summary>Group of Unique Columns</summary>
196
+ <blockquote>
197
+
198
+ ```js
199
+ [
200
+ {
201
+ key: "firstName",
202
+ type: "string",
203
+ required: true,
204
+ unique: "nameGroup", // Part of "nameGroup" uniqueness
205
+ },
206
+ {
207
+ key: "lastName",
208
+ type: "string",
209
+ required: true,
210
+ unique: "nameGroup", // Part of "nameGroup" uniqueness
211
+ },
212
+ ]
213
+ ```
214
+
215
+ </blockquote>
216
+ </details>
217
+
218
+ </blockquote>
219
+ </details>
220
+
221
+ </blockquote>
222
+ </details>
223
+
224
+ </blockquote>
225
+ </details>
226
+
143
227
  <details>
144
228
  <summary>Create Table</summary>
145
229
  <blockquote>
@@ -357,7 +441,7 @@ const product = await db.post("product", productTableData);
357
441
  </blockquote>
358
442
  </details>
359
443
 
360
- <details>
444
+ <details open>
361
445
  <summary>Methods</summary>
362
446
  <blockquote>
363
447
 
package/dist/file.js CHANGED
@@ -399,7 +399,7 @@ export const append = async (filePath, data) => {
399
399
  }
400
400
  else {
401
401
  const escapedFileTempPath = escapeShellPath(fileTempPath);
402
- await exec(`echo $'${(Array.isArray(data) ? data.join("\n") : data)
402
+ await exec(`echo '${(Array.isArray(data) ? data.join("\n") : data)
403
403
  .toString()
404
404
  .replace(/'/g, "\\'")}' | gzip - >> ${escapedFileTempPath}`);
405
405
  }
@@ -542,7 +542,7 @@ export const search = async (filePath, operator, comparedAtValue, logicalOperato
542
542
  // Increment the line count for each line.
543
543
  linesCount++;
544
544
  // Search only in provided linesNumbers
545
- if (searchIn && (!searchIn.has(linesCount) || searchIn.has(-linesCount)))
545
+ if (searchIn?.size && (!searchIn.has(linesCount) || searchIn.has(-linesCount)))
546
546
  continue;
547
547
  // Decode the line for comparison.
548
548
  const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
package/dist/index.d.ts CHANGED
@@ -99,7 +99,6 @@ export default class Inibase {
99
99
  private cleanObject;
100
100
  private formatField;
101
101
  private checkUnique;
102
- private _formatData;
103
102
  private formatData;
104
103
  private getDefaultValue;
105
104
  private _combineObjectsToArray;
package/dist/index.js CHANGED
@@ -381,13 +381,13 @@ export default class Inibase {
381
381
  if (!Array.isArray(value))
382
382
  value = [value];
383
383
  if (Utils.isArrayOfObjects(fieldChildrenType))
384
- return this._formatData(value, fieldChildrenType);
384
+ return this.formatData(value, fieldChildrenType);
385
385
  if (!value.length)
386
386
  return null;
387
387
  return value.map((_value) => this.formatField(_value, fieldChildrenType));
388
388
  case "object":
389
389
  if (Utils.isArrayOfObjects(fieldChildrenType))
390
- return this._formatData(value, fieldChildrenType, _formatOnlyAvailiableKeys);
390
+ return this.formatData(value, fieldChildrenType, _formatOnlyAvailiableKeys);
391
391
  break;
392
392
  case "table":
393
393
  if (Utils.isObject(value)) {
@@ -438,24 +438,24 @@ export default class Inibase {
438
438
  for await (const [columnID, values] of valueObject.columnsValues) {
439
439
  index++;
440
440
  const field = flattenSchema.find(({ id }) => id === columnID);
441
- const [searchResult, totalLines] = await File.search(join(tablePath, `${field.key}${this.getFileExtension(tableName)}`), "[]", values, undefined, valueObject.exclude, field.type, field.children, 1, undefined, false, this.salt);
441
+ const [searchResult, totalLines] = await File.search(join(tablePath, `${field.key}${this.getFileExtension(tableName)}`), "[]", Array.from(values), undefined, valueObject.exclude, field.type, field.children, 1, undefined, false, this.salt);
442
442
  if (searchResult && totalLines > 0) {
443
443
  if (index === valueObject.columnsValues.size)
444
444
  throw this.createError("FIELD_UNIQUE", [
445
445
  field.key,
446
- Array.isArray(values) ? values.join(", ") : values,
446
+ Array.from(values).join(", "),
447
447
  ]);
448
448
  }
449
449
  else
450
- continue;
450
+ return;
451
451
  }
452
452
  }
453
453
  this.uniqueMap = new Map();
454
454
  }
455
- _formatData(data, schema, formatOnlyAvailiableKeys) {
455
+ formatData(data, schema, formatOnlyAvailiableKeys) {
456
456
  const clonedData = JSON.parse(JSON.stringify(data));
457
457
  if (Utils.isArrayOfObjects(clonedData))
458
- return clonedData.map((singleData) => this._formatData(singleData, schema, formatOnlyAvailiableKeys));
458
+ return clonedData.map((singleData) => this.formatData(singleData, schema, formatOnlyAvailiableKeys));
459
459
  if (Utils.isObject(clonedData)) {
460
460
  const RETURN = {};
461
461
  for (const field of schema) {
@@ -471,9 +471,6 @@ export default class Inibase {
471
471
  }
472
472
  return [];
473
473
  }
474
- formatData(tableName, data, formatOnlyAvailiableKeys) {
475
- data = this._formatData(data, this.tablesMap.get(tableName).schema, formatOnlyAvailiableKeys);
476
- }
477
474
  getDefaultValue(field) {
478
475
  if (Array.isArray(field.type))
479
476
  return this.getDefaultValue({
@@ -1192,7 +1189,7 @@ export default class Inibase {
1192
1189
  data.createdAt = Date.now();
1193
1190
  data.updatedAt = undefined;
1194
1191
  }
1195
- this.formatData(tableName, data);
1192
+ data = this.formatData(data, this.tablesMap.get(tableName).schema, true);
1196
1193
  const pathesContents = this.joinPathesContents(tableName, this.tablesMap.get(tableName).config.prepend
1197
1194
  ? Array.isArray(data)
1198
1195
  ? data.toReversed()
@@ -1245,7 +1242,7 @@ export default class Inibase {
1245
1242
  return this.put(tableName, data, data.id, options, returnUpdatedData || undefined);
1246
1243
  }
1247
1244
  await this.validateData(tableName, data, true);
1248
- this.formatData(tableName, data, true);
1245
+ data = this.formatData(data, this.tablesMap.get(tableName).schema, true);
1249
1246
  const pathesContents = this.joinPathesContents(tableName, {
1250
1247
  ...(({ id, ...restOfData }) => restOfData)(data),
1251
1248
  updatedAt: Date.now(),
@@ -1280,7 +1277,7 @@ export default class Inibase {
1280
1277
  Utils.isNumber(where)) {
1281
1278
  // "where" in this case, is the line(s) number(s) and not id(s)
1282
1279
  await this.validateData(tableName, data, true);
1283
- this.formatData(tableName, data, true);
1280
+ data = this.formatData(data, this.tablesMap.get(tableName).schema, true);
1284
1281
  const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(tableName, Utils.isArrayOfObjects(data)
1285
1282
  ? data.map((item) => ({
1286
1283
  ...item,
@@ -210,9 +210,20 @@ export const isEqual = (originalValue, comparedValue, fieldType) => {
210
210
  : false;
211
211
  case "boolean":
212
212
  return Number(originalValue) === Number(comparedValue);
213
- default:
214
- return ((!String(comparedValue).length && originalValue === undefined) ||
215
- originalValue == comparedValue);
213
+ default: {
214
+ // Fast checks for null-like values
215
+ const isOriginalNullLike = originalValue === null ||
216
+ originalValue === undefined ||
217
+ originalValue === "";
218
+ const isComparedNullLike = comparedValue === null ||
219
+ comparedValue === undefined ||
220
+ comparedValue === "";
221
+ // If both are null-like, treat as equivalent
222
+ if (isOriginalNullLike && isComparedNullLike)
223
+ return true;
224
+ // Direct equality check for other cases
225
+ return originalValue === comparedValue;
226
+ }
216
227
  }
217
228
  };
218
229
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.123",
3
+ "version": "1.0.0-rc.125",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Karim Amahtil",