inibase 1.0.0-rc.6 → 1.0.0-rc.61

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