inibase 1.0.0-rc.9 → 1.0.0-rc.91

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/file.ts DELETED
@@ -1,501 +0,0 @@
1
- import { createWriteStream, createReadStream, WriteStream } from "node:fs";
2
- import { open, unlink, rename, stat } from "node:fs/promises";
3
- import { Interface, createInterface } from "node:readline";
4
- import { parse } from "node:path";
5
- import { ComparisonOperator, FieldType } from ".";
6
- import { detectFieldType, isArrayOfArrays, isNumber } from "./utils";
7
- import { encodeID, decodeID, comparePassword } from "./utils.server";
8
-
9
- const doesSupportReadLines = () => {
10
- const [major, minor, patch] = process.versions.node.split(".").map(Number);
11
- return major >= 18 && minor >= 11;
12
- };
13
-
14
- export const isExists = async (path: string) => {
15
- try {
16
- await stat(path);
17
- return true;
18
- } catch {
19
- return false;
20
- }
21
- };
22
-
23
- export const encode = (
24
- input:
25
- | string
26
- | number
27
- | boolean
28
- | null
29
- | (string | number | boolean | null)[],
30
- secretKey?: string | Buffer
31
- ) => {
32
- const secureString = (input: string | number | boolean | null) => {
33
- if (["true", "false"].includes(String(input))) return input ? 1 : 0;
34
- return typeof input === "string"
35
- ? decodeURIComponent(input)
36
- .replaceAll("<", "&lt;")
37
- .replaceAll(">", "&gt;")
38
- .replaceAll(",", "%2C")
39
- .replaceAll("|", "%7C")
40
- .replaceAll("\n", "\\n")
41
- .replaceAll("\r", "\\r")
42
- : input;
43
- };
44
- return Array.isArray(input)
45
- ? isArrayOfArrays(input)
46
- ? (input as any[])
47
- .map((_input) => _input.map(secureString).join(","))
48
- .join("|")
49
- : input.map(secureString).join(",")
50
- : secureString(input);
51
- };
52
-
53
- export const decode = (
54
- input: string | null | number,
55
- fieldType?: FieldType | FieldType[],
56
- fieldChildrenType?: FieldType | FieldType[],
57
- secretKey?: string | Buffer
58
- ): string | number | boolean | null | (string | number | null | boolean)[] => {
59
- if (!fieldType) return null;
60
- const unSecureString = (input: string) =>
61
- decodeURIComponent(input)
62
- .replaceAll("&lt;", "<")
63
- .replaceAll("&gt;", ">")
64
- .replaceAll("%2C", ",")
65
- .replaceAll("%7C", "|")
66
- .replaceAll("\\n", "\n")
67
- .replaceAll("\\r", "\r") || null;
68
- if (input === null || input === "") return null;
69
- if (Array.isArray(fieldType))
70
- fieldType = detectFieldType(String(input), fieldType);
71
- const decodeHelper = (value: string | number | any[]) => {
72
- if (Array.isArray(value) && fieldType !== "array")
73
- return value.map(decodeHelper);
74
- switch (fieldType as FieldType) {
75
- case "table":
76
- case "number":
77
- return isNumber(value) ? Number(value) : null;
78
- case "boolean":
79
- return typeof value === "string" ? value === "true" : Boolean(value);
80
- case "array":
81
- if (!Array.isArray(value)) return [value];
82
-
83
- if (fieldChildrenType)
84
- return value.map(
85
- (v) =>
86
- decode(
87
- v,
88
- Array.isArray(fieldChildrenType)
89
- ? detectFieldType(v, fieldChildrenType)
90
- : fieldChildrenType,
91
- undefined,
92
- secretKey
93
- ) as string | number | boolean | null
94
- );
95
- else return value;
96
- case "id":
97
- return isNumber(value) ? encodeID(value as number, secretKey) : value;
98
- default:
99
- return value;
100
- }
101
- };
102
- return decodeHelper(
103
- typeof input === "string"
104
- ? input.includes(",")
105
- ? input.includes("|")
106
- ? input
107
- .split("|")
108
- .map((_input) => _input.split(",").map(unSecureString))
109
- : input.split(",").map(unSecureString)
110
- : input.includes("|")
111
- ? input
112
- .split("|")
113
- .map((_input) => [
114
- _input
115
- ? fieldType === "array"
116
- ? [unSecureString(_input)]
117
- : unSecureString(_input)
118
- : null,
119
- ])
120
- : unSecureString(input)
121
- : input
122
- );
123
- };
124
-
125
- export const get = async (
126
- filePath: string,
127
- lineNumbers?: number | number[],
128
- fieldType?: FieldType | FieldType[],
129
- fieldChildrenType?: FieldType | FieldType[],
130
- secretKey?: string | Buffer
131
- ): Promise<
132
- [
133
- Record<
134
- number,
135
- | string
136
- | number
137
- | boolean
138
- | (string | number | boolean | (string | number | boolean)[])[]
139
- > | null,
140
- number
141
- ]
142
- > => {
143
- let rl: Interface;
144
- if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
145
- else
146
- rl = createInterface({
147
- input: createReadStream(filePath),
148
- crlfDelay: Infinity,
149
- });
150
- let lines: Record<
151
- number,
152
- | string
153
- | number
154
- | boolean
155
- | (string | number | boolean | (string | number | boolean)[] | null)[]
156
- | null
157
- > = {},
158
- lineCount = 0;
159
-
160
- if (!lineNumbers) {
161
- for await (const line of rl)
162
- lineCount++,
163
- (lines[lineCount] = decode(
164
- line,
165
- fieldType,
166
- fieldChildrenType,
167
- secretKey
168
- ));
169
- } else if (lineNumbers === -1) {
170
- let lastLine: string;
171
- for await (const line of rl) lineCount++, (lastLine = line);
172
- if (lastLine)
173
- lines = {
174
- [lineCount]: decode(lastLine, fieldType, fieldChildrenType, secretKey),
175
- };
176
- } else {
177
- let lineNumbersArray = [
178
- ...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
179
- ];
180
- for await (const line of rl) {
181
- lineCount++;
182
- if (!lineNumbersArray.includes(lineCount)) continue;
183
- const indexOfLineCount = lineNumbersArray.indexOf(lineCount);
184
- lines[lineCount] = decode(line, fieldType, fieldChildrenType, secretKey);
185
- lineNumbersArray[indexOfLineCount] = 0;
186
- if (!lineNumbersArray.filter((lineN) => lineN !== 0).length) break;
187
- }
188
- }
189
-
190
- return [lines ?? null, lineCount];
191
- };
192
-
193
- export const replace = async (
194
- filePath: string,
195
- replacements:
196
- | string
197
- | number
198
- | boolean
199
- | null
200
- | (string | number | boolean | null)[]
201
- | Record<
202
- number,
203
- string | boolean | number | null | (string | boolean | number | null)[]
204
- >,
205
- secretKey?: string | Buffer
206
- ) => {
207
- if (await isExists(filePath)) {
208
- let rl: Interface, writeStream: WriteStream;
209
- if (doesSupportReadLines()) {
210
- const file = await open(filePath, "w+");
211
- rl = file.readLines();
212
- writeStream = file.createWriteStream();
213
- } else {
214
- rl = createInterface({
215
- input: createReadStream(filePath),
216
- crlfDelay: Infinity,
217
- });
218
- writeStream = createWriteStream(filePath);
219
- }
220
- if (typeof replacements === "object" && !Array.isArray(replacements)) {
221
- let lineCount = 0;
222
- for await (const line of rl) {
223
- lineCount++;
224
- writeStream.write(
225
- (lineCount in replacements
226
- ? encode(replacements[lineCount], secretKey)
227
- : line) + "\n"
228
- );
229
- }
230
- } else
231
- for await (const _line of rl)
232
- writeStream.write(encode(replacements, secretKey) + "\n");
233
-
234
- writeStream.end();
235
- } else if (typeof replacements === "object" && !Array.isArray(replacements)) {
236
- let writeStream: WriteStream;
237
- if (doesSupportReadLines())
238
- writeStream = (await open(filePath, "w")).createWriteStream();
239
- else writeStream = createWriteStream(filePath);
240
- const largestLinesNumbers =
241
- Math.max(...Object.keys(replacements).map(Number)) + 1;
242
- for (let lineCount = 1; lineCount < largestLinesNumbers; lineCount++) {
243
- writeStream.write(
244
- (lineCount in replacements
245
- ? encode(replacements[lineCount], secretKey)
246
- : "") + "\n"
247
- );
248
- }
249
- writeStream.end();
250
- }
251
- };
252
-
253
- export const remove = async (
254
- filePath: string,
255
- linesToDelete: number | number[]
256
- ): Promise<void> => {
257
- let lineCount = 0;
258
-
259
- const tempFilePath = `${filePath}-${Date.now()}.tmp`,
260
- linesToDeleteArray = [
261
- ...(Array.isArray(linesToDelete) ? linesToDelete : [linesToDelete]),
262
- ];
263
-
264
- let rl: Interface, writeStream: WriteStream;
265
- if (doesSupportReadLines()) {
266
- rl = (await open(filePath)).readLines();
267
- writeStream = (await open(tempFilePath, "w+")).createWriteStream();
268
- } else {
269
- rl = createInterface({
270
- input: createReadStream(filePath),
271
- crlfDelay: Infinity,
272
- });
273
- writeStream = createWriteStream(tempFilePath);
274
- }
275
-
276
- for await (const line of rl) {
277
- lineCount++;
278
- if (!linesToDeleteArray.includes(lineCount)) {
279
- writeStream.write(`${line}\n`);
280
- }
281
- }
282
- writeStream.end(async () => {
283
- await unlink(filePath); // Remove the original file
284
- await rename(tempFilePath, filePath); // Rename the temp file to the original file name
285
- });
286
- };
287
-
288
- export const count = async (filePath: string): Promise<number> => {
289
- let lineCount = 0,
290
- rl: Interface;
291
- if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
292
- else
293
- rl = createInterface({
294
- input: createReadStream(filePath),
295
- crlfDelay: Infinity,
296
- });
297
-
298
- for await (const line of rl) lineCount++;
299
-
300
- return lineCount;
301
- };
302
-
303
- export const search = async (
304
- filePath: string,
305
- operator: ComparisonOperator | ComparisonOperator[],
306
- comparedAtValue:
307
- | string
308
- | number
309
- | boolean
310
- | null
311
- | (string | number | boolean | null)[],
312
- logicalOperator?: "and" | "or",
313
- fieldType?: FieldType | FieldType[],
314
- fieldChildrenType?: FieldType | FieldType[],
315
- limit?: number,
316
- offset?: number,
317
- readWholeFile?: boolean,
318
- secretKey?: string | Buffer
319
- ): Promise<
320
- [
321
- Record<
322
- number,
323
- Record<
324
- string,
325
- string | number | boolean | (string | number | boolean | null)[] | null
326
- >
327
- > | null,
328
- number
329
- ]
330
- > => {
331
- const handleComparisonOperator = (
332
- operator: ComparisonOperator,
333
- originalValue:
334
- | string
335
- | number
336
- | boolean
337
- | null
338
- | (string | number | boolean | null)[],
339
- comparedAtValue:
340
- | string
341
- | number
342
- | boolean
343
- | null
344
- | (string | number | boolean | null)[],
345
- fieldType?: FieldType | FieldType[],
346
- fieldChildrenType?: FieldType | FieldType[]
347
- ): boolean => {
348
- if (Array.isArray(fieldType))
349
- fieldType = detectFieldType(String(originalValue), fieldType);
350
- if (Array.isArray(comparedAtValue) && !["[]", "![]"].includes(operator))
351
- return comparedAtValue.some((comparedAtValueSingle) =>
352
- handleComparisonOperator(
353
- operator,
354
- originalValue,
355
- comparedAtValueSingle,
356
- fieldType
357
- )
358
- );
359
- // check if not array or object // it can't be array or object!
360
- switch (operator) {
361
- case "=":
362
- switch (fieldType) {
363
- case "password":
364
- return typeof originalValue === "string" &&
365
- typeof comparedAtValue === "string"
366
- ? comparePassword(originalValue, comparedAtValue)
367
- : false;
368
- case "boolean":
369
- return Number(originalValue) - Number(comparedAtValue) === 0;
370
- default:
371
- return originalValue === comparedAtValue;
372
- }
373
- case "!=":
374
- return !handleComparisonOperator(
375
- "=",
376
- originalValue,
377
- comparedAtValue,
378
- fieldType
379
- );
380
- case ">":
381
- return originalValue > comparedAtValue;
382
- case "<":
383
- return originalValue < comparedAtValue;
384
- case ">=":
385
- return originalValue >= comparedAtValue;
386
- case "<=":
387
- return originalValue <= comparedAtValue;
388
- case "[]":
389
- return (
390
- (Array.isArray(originalValue) &&
391
- Array.isArray(comparedAtValue) &&
392
- originalValue.some(comparedAtValue.includes)) ||
393
- (Array.isArray(originalValue) &&
394
- !Array.isArray(comparedAtValue) &&
395
- originalValue.includes(comparedAtValue)) ||
396
- (!Array.isArray(originalValue) &&
397
- Array.isArray(comparedAtValue) &&
398
- comparedAtValue.includes(originalValue))
399
- );
400
- case "![]":
401
- return !handleComparisonOperator(
402
- "[]",
403
- originalValue,
404
- comparedAtValue,
405
- fieldType
406
- );
407
- case "*":
408
- return new RegExp(
409
- `^${(String(comparedAtValue).includes("%")
410
- ? String(comparedAtValue)
411
- : "%" + String(comparedAtValue) + "%"
412
- ).replace(/%/g, ".*")}$`,
413
- "i"
414
- ).test(String(originalValue));
415
- case "!*":
416
- return !handleComparisonOperator(
417
- "*",
418
- originalValue,
419
- comparedAtValue,
420
- fieldType
421
- );
422
- default:
423
- throw new Error(operator);
424
- }
425
- };
426
-
427
- let RETURN: Record<
428
- number,
429
- Record<
430
- string,
431
- string | number | boolean | null | (string | number | boolean | null)[]
432
- >
433
- > = {},
434
- lineCount = 0,
435
- foundItems = 0;
436
- let rl: Interface;
437
- if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
438
- else
439
- rl = createInterface({
440
- input: createReadStream(filePath),
441
- crlfDelay: Infinity,
442
- });
443
-
444
- const columnName = parse(filePath).name;
445
-
446
- for await (const line of rl) {
447
- lineCount++;
448
- const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
449
- if (
450
- (Array.isArray(operator) &&
451
- Array.isArray(comparedAtValue) &&
452
- ((logicalOperator &&
453
- logicalOperator === "or" &&
454
- operator.some((single_operator, index) =>
455
- handleComparisonOperator(
456
- single_operator,
457
- decodedLine,
458
- comparedAtValue[index],
459
- fieldType
460
- )
461
- )) ||
462
- operator.every((single_operator, index) =>
463
- handleComparisonOperator(
464
- single_operator,
465
- decodedLine,
466
- comparedAtValue[index],
467
- fieldType
468
- )
469
- ))) ||
470
- (!Array.isArray(operator) &&
471
- handleComparisonOperator(
472
- operator,
473
- decodedLine,
474
- comparedAtValue,
475
- fieldType
476
- ))
477
- ) {
478
- foundItems++;
479
- if (offset && foundItems < offset) continue;
480
- if (limit && foundItems > limit)
481
- if (readWholeFile) continue;
482
- else break;
483
- if (!RETURN[lineCount]) RETURN[lineCount] = {};
484
- RETURN[lineCount][columnName] = decodedLine;
485
- }
486
- }
487
- if (foundItems) {
488
- return [RETURN, readWholeFile ? foundItems : foundItems - 1];
489
- } else return [null, 0];
490
- };
491
-
492
- export default class File {
493
- static get = get;
494
- static remove = remove;
495
- static search = search;
496
- static replace = replace;
497
- static count = count;
498
- static encode = encode;
499
- static decode = decode;
500
- static isExists = isExists;
501
- }
package/index.test.ts DELETED
@@ -1,210 +0,0 @@
1
- import Inibase, { Schema, Data } from "./index";
2
- import { join } from "node:path";
3
- // import os from "os";
4
- // Create a new instance of Inibase with the database path
5
- const db = new Inibase("inicontent", join("..", "inicontent", "databases"));
6
-
7
- const schema_1: Schema = [
8
- {
9
- key: "username",
10
- type: "string",
11
- required: true,
12
- },
13
- {
14
- key: "password",
15
- type: "password",
16
- required: true,
17
- },
18
- {
19
- key: "email",
20
- type: "email",
21
- required: true,
22
- },
23
- {
24
- key: "role",
25
- type: "string",
26
- required: true,
27
- },
28
- ];
29
-
30
- const data_1: Data = [
31
- {
32
- username: "admin",
33
- password: "admina",
34
- email: "karim.amahtil@gmail.com",
35
- role: "admin",
36
- },
37
- {
38
- username: "kamatil",
39
- password: "admina",
40
- email: "karim.amahtil21@gmail.com",
41
- role: "user",
42
- },
43
- {
44
- username: "tvonthego",
45
- password: "azqswx",
46
- email: "vip72abdo@gmail.com",
47
- role: "user",
48
- },
49
- ];
50
-
51
- const schema_2: Schema = [
52
- {
53
- key: "name",
54
- type: "string",
55
- required: true,
56
- },
57
- {
58
- key: "slug",
59
- type: "string",
60
- required: true,
61
- },
62
- {
63
- key: "icon",
64
- type: "url",
65
- required: false,
66
- },
67
- {
68
- key: "languages",
69
- type: "array",
70
- children: "string",
71
- required: false,
72
- },
73
- {
74
- key: "allowed_domains",
75
- type: "array",
76
- children: "url",
77
- required: false,
78
- },
79
- {
80
- key: "tables",
81
- type: "array",
82
- children: [
83
- {
84
- key: "name",
85
- type: "string",
86
- required: true,
87
- },
88
- {
89
- key: "slug",
90
- type: "string",
91
- required: true,
92
- },
93
- {
94
- key: "allowed_methods",
95
- type: "array",
96
- children: [
97
- {
98
- key: "role",
99
- type: "string",
100
- required: true,
101
- },
102
- {
103
- key: "methods",
104
- type: "string",
105
- required: true,
106
- },
107
- ],
108
- required: true,
109
- },
110
- {
111
- key: "schema",
112
- type: "array",
113
- children: [
114
- {
115
- key: "id",
116
- type: "id",
117
- required: true,
118
- },
119
- {
120
- key: "subtype",
121
- type: "string",
122
- },
123
- {
124
- key: "accept",
125
- type: "array",
126
- children: "string",
127
- },
128
- {
129
- key: "search",
130
- type: "array",
131
- children: "string",
132
- },
133
- {
134
- key: "label",
135
- type: "array",
136
- children: "string",
137
- },
138
- {
139
- key: "image",
140
- type: "string",
141
- },
142
- {
143
- key: "values",
144
- type: "array",
145
- children: "string",
146
- },
147
- ],
148
- },
149
- ],
150
- },
151
- {
152
- key: "user",
153
- type: ["array", "table"],
154
- children: "table",
155
- required: false,
156
- },
157
- ];
158
-
159
- const data_2 = [
160
- {
161
- name: "Inicontent",
162
- slug: "inicontent",
163
- allowed_domains: ["http://localhost:3000"],
164
- tables: [
165
- {
166
- name: "User",
167
- slug: "user",
168
- allowed_methods: [
169
- {
170
- role: "user",
171
- methods: "cru",
172
- },
173
- {
174
- role: "guest",
175
- methods: "c",
176
- },
177
- ],
178
- },
179
- {
180
- name: "Database",
181
- slug: "database",
182
- allowed_methods: [
183
- {
184
- role: "user",
185
- methods: "crud",
186
- },
187
- {
188
- role: "guest",
189
- methods: "c",
190
- },
191
- ],
192
- },
193
- ],
194
- user: 1,
195
- },
196
- ];
197
- try {
198
- // db.setTableSchema("database", schema_2);
199
- // const DATA = await db.post("database", data_2);
200
- const DATA = await db.get("database", 1);
201
- console.log(
202
- JSON.stringify(
203
- (DATA as Data).tables.find((table: any) => table.slug === "session"),
204
- null,
205
- 4
206
- )
207
- );
208
- } catch (er) {
209
- console.log(er);
210
- }