@ix-xs/node-comfort 1.0.56 → 1.1.0

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,283 +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 ${JSON.stringify(def.defaultValue)}`;
63
- }
64
- if (def.values?.length) {
65
- colDef += ` CHECK(${col} IN (${def.values.map(v => JSON.stringify(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
- /**
110
- * @param {object} table
111
- * @param {string} table.name
112
- * @param {Record<string, {
113
- * type: "INTEGER"|"TEXT"|"REAL"|"BLOB"|"NUMERIC",
114
- * primaryKey?: boolean,
115
- * autoincrement?: boolean,
116
- * notNull?: boolean,
117
- * unique?: boolean,
118
- * defaultValue?: *,
119
- * values?: Array<*>
120
- * }>} table.options
121
- */
122
- async createTable(table) {
123
- try {
124
- this.#defineModel(table.name, table.options);
125
- return { ok: true };
126
- } catch (error) {
127
- return { error: error.message };
128
- }
129
- }
130
-
131
- /**
132
- * @param {string} tableName
133
- */
134
- async deleteTable(tableName) {
135
- try {
136
- if (!this.#models.has(tableName)) {
137
- return { error: `Table ${tableName} doesn't exist` };
138
- }
139
-
140
- this.#exec(`DROP TABLE IF EXISTS ${tableName}`);
141
- this.#models.delete(tableName);
142
- return { ok: true };
143
- } catch (error) {
144
- return { error: error.message };
145
- }
146
- }
147
-
148
- /**
149
- * @param {string} tableName
150
- */
151
- async clearTable(tableName) {
152
- try {
153
- if (!this.#models.has(tableName)) {
154
- return { error: `Table ${tableName} doesn't exist` };
155
- }
156
-
157
- this.#exec(`DELETE FROM ${tableName}`);
158
- return { ok: true };
159
- } catch (error) {
160
- return { error: error.message };
161
- }
162
- }
163
-
164
- /**
165
- * @param {string} tableName
166
- * @param {object} where
167
- */
168
- async get(tableName, where) {
169
- try {
170
- if (!this.#models.has(tableName)) return undefined;
171
-
172
- const whereClause = this.#buildWhere(where);
173
- const sql = `SELECT * FROM ${tableName} ${whereClause.where} LIMIT 1`;
174
- const stmt = this.#$.prepare(sql);
175
- const record = stmt.get(...whereClause.params);
176
-
177
- return record || undefined;
178
- } catch (error) {
179
- return { error: error.message };
180
- }
181
- }
182
-
183
- /**
184
- * @param {string} tableName
185
- * @param {object} where
186
- * @param {number} limit
187
- * @param {number} offset
188
- */
189
- async getAll(tableName, where = {}, limit = 50, offset = 0) {
190
- try {
191
- if (!this.#models.has(tableName)) return [];
192
-
193
- const whereClause = this.#buildWhere(where);
194
- const sql = `SELECT * FROM ${tableName} ${whereClause.where} ORDER BY ${this.#getOrderBy(
195
- tableName,
196
- )} LIMIT ? OFFSET ?`;
197
- const stmt = this.#$.prepare(sql);
198
- const records = stmt.all(...whereClause.params, limit, offset);
199
- return records;
200
- } catch (error) {
201
- return { error: error.message };
202
- }
203
- }
204
-
205
- /**
206
- * @param {string} tableName
207
- * @param {object} data
208
- * @param {object|null} where
209
- */
210
- async set(tableName, data, where = null) {
211
- try {
212
- if (!this.#models.has(tableName)) {
213
- return { error: `Table ${tableName} doesn't exist` };
214
- }
215
-
216
- const lookup = where ?? (data.id ? { id: data.id } : null);
217
-
218
- let finalData = data;
219
-
220
- if (lookup) {
221
- const existing = await this.get(tableName, lookup);
222
-
223
- if (existing && !existing.error) {
224
- finalData = { ...existing, ...data };
225
- }
226
- }
227
-
228
- const columns = Object.keys(finalData);
229
- const placeholders = columns.map(() => "?").join(", ");
230
- const sql = `INSERT OR REPLACE INTO ${tableName} (${columns.join(
231
- ", ",
232
- )}) VALUES (${placeholders})`;
233
-
234
- const stmt = this.#$.prepare(sql);
235
- stmt.run(...Object.values(finalData));
236
-
237
- return { ok: true };
238
- } catch (error) {
239
- return { error: error.message };
240
- }
241
- }
242
-
243
-
244
- /**
245
- * @param {string} tableName
246
- * @param {object} where
247
- */
248
- async delete(tableName, where) {
249
- try {
250
- if (!this.#models.has(tableName)) {
251
- return { error: `Table ${tableName} doesn't exist` };
252
- }
253
-
254
- const whereClause = this.#buildWhere(where);
255
- const sql = `DELETE FROM ${tableName} ${whereClause.where}`;
256
- const stmt = this.#$.prepare(sql);
257
- const result = stmt.run(...whereClause.params);
258
- return { ok: true, changes: result.changes };
259
- } catch (error) {
260
- return { error: error.message };
261
- }
262
- }
263
-
264
- /**
265
- * @param {string} tableName
266
- * @param {object} [where]
267
- */
268
- async count(tableName, where = {}) {
269
- try {
270
- if (!this.#models.has(tableName)) {
271
- return { error: `Table ${tableName} doesn't exist` };
272
- }
273
-
274
- const whereClause = this.#buildWhere(where);
275
- const sql = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause.where}`;
276
- const stmt = this.#$.prepare(sql);
277
- const result = stmt.get(...whereClause.params);
278
- return result.total;
279
- } catch (error) {
280
- return { error: error.message };
281
- }
282
- }
283
- };
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
- };