@ix-xs/node-comfort 1.0.57 → 1.1.1

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.
@@ -1,293 +0,0 @@
1
- const fs = require("./fs");
2
- const checker = require("./checker");
3
-
4
- const originalEmitWarning = process.emitWarning;
5
- process.emitWarning = (warning, ...args) => {
6
- if (
7
- (warning.name === "ExperimentalWarning" && warning.message.includes("SQLite")) ||
8
- (typeof warning === "string" && warning.startsWith("SQLite is an experimental feature"))
9
- ) {
10
- return;
11
- }
12
- return originalEmitWarning.call(process, warning, ...args);
13
- };
14
-
15
- const { DatabaseSync } = require("node:sqlite");
16
-
17
- module.exports = class localStorage {
18
- #$;
19
- #models = new Map();
20
-
21
- constructor(path = fs.createPath("localStorage/localStorage.sqlite").replaceAll("\\", "/")) {
22
- if (path.includes("/")) {
23
- const split = path.split("/");
24
- const file = split[split.length - 1];
25
- const folder = fs.createPath(path.replace(file, ""));
26
- fs.createFolder(folder);
27
- }
28
-
29
- this.#$ = new DatabaseSync(path);
30
- this.#exec("PRAGMA journal_mode = WAL");
31
- this.#exec("PRAGMA foreign_keys = ON");
32
- }
33
-
34
- #exec(sql, options = []) {
35
- try {
36
- const stmt = this.#$.prepare(sql);
37
- const result = checker.isArray(options)
38
- ? stmt.run(...options)
39
- : stmt.run(options);
40
-
41
- return {
42
- changes: result.changes,
43
- lastInsertRowid: result.lastInsertRowid,
44
- };
45
- } catch (error) {
46
- throw error;
47
- }
48
- }
49
-
50
- #buildCreateSQL(tableName, options) {
51
- const columns = Object.entries(options)
52
- .map(([col, def]) => {
53
- let colDef = `${col} ${def.type}`;
54
-
55
- if (def.primaryKey) {
56
- colDef += " PRIMARY KEY";
57
- if (def.autoincrement) colDef += " AUTOINCREMENT";
58
- }
59
- if (def.notNull) colDef += " NOT NULL";
60
- if (def.unique) colDef += " UNIQUE";
61
- if (def.defaultValue !== undefined) {
62
- colDef += ` DEFAULT ${this.#toSQLValue(def.defaultValue)}`;
63
- }
64
- if (def.values?.length) {
65
- colDef += ` CHECK(${col} IN (${def.values.map(v => this.#toSQLValue(v)).join(", ")}))`;
66
- }
67
-
68
- return colDef;
69
- })
70
- .join(", ");
71
-
72
- return `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
73
- }
74
-
75
- #defineModel(tableName, options) {
76
- if (this.#models.has(tableName)) return;
77
-
78
- const createSQL = this.#buildCreateSQL(tableName, options);
79
- this.#exec(createSQL);
80
- this.#models.set(tableName, { name: tableName, options });
81
- }
82
-
83
- #buildWhere(where = {}) {
84
- if (!where || Object.keys(where).length === 0) {
85
- return { where: "", params: [] };
86
- }
87
-
88
- const conditions = [];
89
- const params = [];
90
-
91
- for (const [key, value] of Object.entries(where)) {
92
- conditions.push(`${key} = ?`);
93
- params.push(value);
94
- }
95
-
96
- return {
97
- where: `WHERE ${conditions.join(" AND ")}`,
98
- params,
99
- };
100
- }
101
-
102
- #getOrderBy(tableName) {
103
- const model = this.#models.get(tableName);
104
- if (!model) return "id DESC";
105
- const firstCol = Object.keys(model.options)[0];
106
- return `${firstCol} DESC`;
107
- }
108
-
109
- #toSQLValue(value) {
110
- if (value === null) return "NULL";
111
- if (typeof value === "number") return String(value);
112
- if (typeof value === "bigint") return String(value);
113
- if (typeof value === "boolean") return value ? "1" : "0";
114
- if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
115
-
116
- return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
117
- }
118
-
119
- /**
120
- * @param {object} table
121
- * @param {string} table.name
122
- * @param {Record<string, {
123
- * type: "INTEGER"|"TEXT"|"REAL"|"BLOB"|"NUMERIC",
124
- * primaryKey?: boolean,
125
- * autoincrement?: boolean,
126
- * notNull?: boolean,
127
- * unique?: boolean,
128
- * defaultValue?: *,
129
- * values?: Array<*>
130
- * }>} table.options
131
- */
132
- async createTable(table) {
133
- try {
134
- this.#defineModel(table.name, table.options);
135
- return { ok: true };
136
- } catch (error) {
137
- return { error: error.message };
138
- }
139
- }
140
-
141
- /**
142
- * @param {string} tableName
143
- */
144
- async deleteTable(tableName) {
145
- try {
146
- if (!this.#models.has(tableName)) {
147
- return { error: `Table ${tableName} doesn't exist` };
148
- }
149
-
150
- this.#exec(`DROP TABLE IF EXISTS ${tableName}`);
151
- this.#models.delete(tableName);
152
- return { ok: true };
153
- } catch (error) {
154
- return { error: error.message };
155
- }
156
- }
157
-
158
- /**
159
- * @param {string} tableName
160
- */
161
- async clearTable(tableName) {
162
- try {
163
- if (!this.#models.has(tableName)) {
164
- return { error: `Table ${tableName} doesn't exist` };
165
- }
166
-
167
- this.#exec(`DELETE FROM ${tableName}`);
168
- return { ok: true };
169
- } catch (error) {
170
- return { error: error.message };
171
- }
172
- }
173
-
174
- /**
175
- * @param {string} tableName
176
- * @param {object} where
177
- */
178
- async get(tableName, where) {
179
- try {
180
- if (!this.#models.has(tableName)) return undefined;
181
-
182
- const whereClause = this.#buildWhere(where);
183
- const sql = `SELECT * FROM ${tableName} ${whereClause.where} LIMIT 1`;
184
- const stmt = this.#$.prepare(sql);
185
- const record = stmt.get(...whereClause.params);
186
-
187
- return record || undefined;
188
- } catch (error) {
189
- return { error: error.message };
190
- }
191
- }
192
-
193
- /**
194
- * @param {string} tableName
195
- * @param {object} where
196
- * @param {number} limit
197
- * @param {number} offset
198
- */
199
- async getAll(tableName, where = {}, limit = 50, offset = 0) {
200
- try {
201
- if (!this.#models.has(tableName)) return [];
202
-
203
- const whereClause = this.#buildWhere(where);
204
- const sql = `SELECT * FROM ${tableName} ${whereClause.where} ORDER BY ${this.#getOrderBy(
205
- tableName,
206
- )} LIMIT ? OFFSET ?`;
207
- const stmt = this.#$.prepare(sql);
208
- const records = stmt.all(...whereClause.params, limit, offset);
209
- return records;
210
- } catch (error) {
211
- return { error: error.message };
212
- }
213
- }
214
-
215
- /**
216
- * @param {string} tableName
217
- * @param {object} data
218
- * @param {object|null} where
219
- */
220
- async set(tableName, data, where = null) {
221
- try {
222
- if (!this.#models.has(tableName)) {
223
- return { error: `Table ${tableName} doesn't exist` };
224
- }
225
-
226
- const lookup = where ?? (data.id ? { id: data.id } : null);
227
-
228
- let finalData = data;
229
-
230
- if (lookup) {
231
- const existing = await this.get(tableName, lookup);
232
-
233
- if (existing && !existing.error) {
234
- finalData = { ...existing, ...data };
235
- }
236
- }
237
-
238
- const columns = Object.keys(finalData);
239
- const placeholders = columns.map(() => "?").join(", ");
240
- const sql = `INSERT OR REPLACE INTO ${tableName} (${columns.join(
241
- ", ",
242
- )}) VALUES (${placeholders})`;
243
-
244
- const stmt = this.#$.prepare(sql);
245
- stmt.run(...Object.values(finalData));
246
-
247
- return { ok: true };
248
- } catch (error) {
249
- return { error: error.message };
250
- }
251
- }
252
-
253
-
254
- /**
255
- * @param {string} tableName
256
- * @param {object} where
257
- */
258
- async delete(tableName, where) {
259
- try {
260
- if (!this.#models.has(tableName)) {
261
- return { error: `Table ${tableName} doesn't exist` };
262
- }
263
-
264
- const whereClause = this.#buildWhere(where);
265
- const sql = `DELETE FROM ${tableName} ${whereClause.where}`;
266
- const stmt = this.#$.prepare(sql);
267
- const result = stmt.run(...whereClause.params);
268
- return { ok: true, changes: result.changes };
269
- } catch (error) {
270
- return { error: error.message };
271
- }
272
- }
273
-
274
- /**
275
- * @param {string} tableName
276
- * @param {object} [where]
277
- */
278
- async count(tableName, where = {}) {
279
- try {
280
- if (!this.#models.has(tableName)) {
281
- return { error: `Table ${tableName} doesn't exist` };
282
- }
283
-
284
- const whereClause = this.#buildWhere(where);
285
- const sql = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause.where}`;
286
- const stmt = this.#$.prepare(sql);
287
- const result = stmt.get(...whereClause.params);
288
- return result.total;
289
- } catch (error) {
290
- return { error: error.message };
291
- }
292
- }
293
- };
package/src/logger.js DELETED
@@ -1,243 +0,0 @@
1
- const _x = "\x1B";
2
- const _style = {
3
- normal: 0,
4
- bold: 1,
5
- italic: 3,
6
- underline: 4,
7
- overline: 9,
8
- };
9
- const _color = {
10
- fg: {
11
- black: 30,
12
- red: 31,
13
- green: 32,
14
- yellow: 33,
15
- blue: 34,
16
- magenta: 35,
17
- cyan: 36,
18
- white: 37,
19
- gray: 90,
20
- redBright: 91,
21
- greenBright: 92,
22
- yellowBright: 93,
23
- blueBright: 94,
24
- magentaBright: 95,
25
- cyanBright: 96,
26
- whiteBright: 97,
27
- rgb: 38,
28
- },
29
- bg: {
30
- black: 40,
31
- red: 41,
32
- green: 42,
33
- yellow: 43,
34
- blue: 44,
35
- magenta: 45,
36
- cyan: 46,
37
- white: 47,
38
- gray: 100,
39
- redBright: 101,
40
- greenBright: 102,
41
- yellowBright: 103,
42
- blueBright: 104,
43
- magentaBright: 105,
44
- cyanBright: 106,
45
- whiteBright: 107,
46
- rgb: 48,
47
- },
48
- };
49
- const _options = {
50
- delimiters: {
51
- start: "<%",
52
- end: "%>",
53
- },
54
- timestamp: true,
55
- };
56
- const _groups = [];
57
-
58
- /**
59
- * @param {string} name
60
- * @returns {number|null}
61
- */
62
- const _getCode = (name) => {
63
- if (_style[name] !== undefined) return _style[name];
64
- if (_color.fg[name] !== undefined) return _color.fg[name];
65
- if (name.startsWith("bg")) {
66
- const bg = name.charAt(2).toLowerCase() + name.slice(3);
67
- if (_color.bg[bg] !== undefined) return _color.bg[bg];
68
- }
69
- return null;
70
- };
71
- /**
72
- * @param {string} input
73
- * @returns {{codes: number[], text: string}}
74
- */
75
- const _parse = (input) => {
76
- const tokens = input.trim().split(/\s+/);
77
- const styles = [];
78
- const fgs = [];
79
- const bgs = [];
80
- const txts = [];
81
-
82
- for (const token of tokens) {
83
- const code = _getCode(token);
84
- if (code === null) {
85
- txts.push(token);
86
- } else {
87
- if (_style[token] !== undefined) {
88
- styles.push(code);
89
- } else if (token.startsWith("bg")) {
90
- bgs.push(code);
91
- } else {
92
- fgs.push(code);
93
- }
94
- }
95
- }
96
-
97
- const codes = [...styles, ...bgs, ...fgs];
98
- const text = input
99
- .replace(
100
- /^\s*((redBright|greenBright|yellowBright|blueBright|magentaBright|cyanBright|whiteBright|red|green|yellow|blue|magenta|cyan|white|gray|black|bold|italic|underline|overline|bg\w+|\s+)*)/gi,
101
- "",
102
- )
103
- .trimStart();
104
- return { codes, text };
105
- };
106
- /**
107
- * @param {number[]} codes - ANSI codes.
108
- * @returns {string} Escape sequence.
109
- */
110
- const _build = (codes) => {
111
- if (codes.length === 0) return "";
112
- return `${_x}[${codes.join(";")}m`;
113
- };
114
- const _apply = (str) => {
115
- const esc_start = _options.delimiters.start.replace(
116
- /[.*+?^${}()|[\]\\]/g,
117
- "\\$&",
118
- );
119
- const esc_end = _options.delimiters.end.replace(
120
- /[.*+?^${}()|[\]\\]/g,
121
- "\\$&",
122
- );
123
-
124
- return str.replace(
125
- new RegExp(`${esc_start}([\\s\\S]*?)${esc_end}`, "g"),
126
- (match, content) => {
127
- const { codes, text } = _parse(content);
128
- if (codes.length === 0 || text === "") return text;
129
-
130
- if (text.includes("\n")) {
131
- return text
132
- .split(/\\r?\\n/)
133
- .filter((line) => line.trim())
134
- .map((line) => `${_build(codes)}${line}${_x}[0m`)
135
- .join("\\n");
136
- }
137
-
138
- return `${_build(codes)}${text}${_x}[0m`;
139
- },
140
- );
141
- };
142
- /**
143
- * @returns {string}
144
- */
145
- const _timestamp = () => {
146
- if (!_options.timestamp) return "";
147
- return _apply(
148
- `<%gray [${new Date().toLocaleTimeString(undefined, { hour12: false })}]%>`,
149
- );
150
- };
151
- /**
152
- * @returns {string}
153
- */
154
- const _indent = () => {
155
- return " ".repeat(0 + _groups.length);
156
- };
157
-
158
- module.exports = {
159
- /**
160
- * @param {*} content
161
- */
162
- log(content) {
163
- let str;
164
- if (typeof content === "string") {
165
- str = content;
166
- } else if (typeof content === "object") {
167
- str = JSON.stringify(content, null, 2);
168
- } else {
169
- str = String(content);
170
- }
171
-
172
- const prefix = `${_timestamp()}${_indent()}`;
173
- const fullStr = prefix ? `${prefix} ${str}` : str;
174
-
175
- const formatted = _apply(fullStr);
176
-
177
- if (formatted.includes("\n")) {
178
- const lines = formatted.split("\n");
179
-
180
- if (lines[0].trim()) console.log(lines[0]);
181
-
182
- const indentOnly = _indent();
183
- for (let i = 1; i < lines.length; i++) {
184
- if (lines[i].trim()) {
185
- console.log(`${indentOnly}${lines[i]}`);
186
- }
187
- }
188
- } else {
189
- console.log(formatted);
190
- }
191
-
192
- return this;
193
- },
194
- /**
195
- * @param {any} content - Content to format.
196
- * @returns {string} Formatted string.
197
- */
198
- logify(content) {
199
- let str;
200
- if (typeof content === "string") {
201
- str = content;
202
- } else if (typeof content === "object") {
203
- str = JSON.stringify(content, null, 2);
204
- } else {
205
- str = String(content);
206
- }
207
-
208
- const prefix = `${_timestamp()}${_indent()}`;
209
- return _apply(prefix ? `${prefix} ${str}` : str);
210
- },
211
- /**
212
- * @param {string} label
213
- */
214
- group(label) {
215
- _groups.push(label);
216
- const prefix = `${_timestamp()}${_indent()}`;
217
- console.log(prefix ? `${prefix}▼ ${label}` : `▼ ${label}`);
218
- return this;
219
- },
220
- groupEnd() {
221
- if (_groups.length > 0) _groups.pop();
222
- return this;
223
- },
224
- /**
225
- * @param {object} [options]
226
- * @param {object} [options.delimiters]
227
- * @param {string} [options.delimiters.start="<%="]
228
- * @param {string} [options.delimiters.end="%>"]
229
- * @param {boolean} [options.timestamp=true]
230
- */
231
- setLogger(options = _options) {
232
- options = {
233
- delimiters: {
234
- start: options?.delimiters?.start ?? _options.delimiters.start,
235
- end: options?.delimiters?.end ?? _options.delimiters.end,
236
- },
237
- timestamp: options?.timestamp ?? _options.timestamp,
238
- };
239
- _options.delimiters = options.delimiters;
240
- _options.timestamp = options.timestamp;
241
- return this;
242
- },
243
- };