inibase 1.0.0-rc.8 → 1.0.0-rc.80

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