@ix-xs/node-comfort 1.0.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.
- package/core/CLI.js +95 -0
- package/core/Checker.js +127 -0
- package/core/FS.js +765 -0
- package/core/Logger.js +321 -0
- package/core/Stepper.js +115 -0
- package/core/Storage.js +350 -0
- package/core/Utils.js +206 -0
- package/index.js +17 -0
- package/package.json +17 -0
package/core/Storage.js
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
const FS = require("./FS");
|
|
2
|
+
const Checker = require("./Checker");
|
|
3
|
+
const { basename } = require("node:path");
|
|
4
|
+
|
|
5
|
+
const originalEmitWarning = process.emitWarning;
|
|
6
|
+
process.emitWarning = (warning, ...args) => {
|
|
7
|
+
if ((warning.name === "ExperimentalWarning" && warning.message.includes("SQLite")) || (typeof warning === "string" && warning.startsWith("SQLite is an experimental feature"))) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return originalEmitWarning.call(process, warning, ...args);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const { DatabaseSync } = require("node:sqlite");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @module Storage
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
module.exports = class Storage {
|
|
21
|
+
#$;
|
|
22
|
+
#statements = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} [path = ":memomry"]
|
|
26
|
+
*/
|
|
27
|
+
constructor(path) {
|
|
28
|
+
if (path.includes("/")) {
|
|
29
|
+
const split = path.split("/");
|
|
30
|
+
const file = split[split.length - 1];
|
|
31
|
+
const folder = FS.createPath(path.replace(file, ""));
|
|
32
|
+
|
|
33
|
+
FS.createFolder(folder);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.#$ = new DatabaseSync(path);
|
|
37
|
+
|
|
38
|
+
this.exec("PRAGMA journal_mode = WAL");
|
|
39
|
+
this.exec("PRAGMA foreign_keys = ON");
|
|
40
|
+
this.exec("PRAGMA synchronous = NORMAL");
|
|
41
|
+
this.exec("PRAGMA cache_size = -64000");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} sql
|
|
46
|
+
* @param {array|object} [options = {}]
|
|
47
|
+
*/
|
|
48
|
+
exec(sql, options) {
|
|
49
|
+
try {
|
|
50
|
+
const stmt = this.#$.prepare(sql);
|
|
51
|
+
const result = stmt.run(...Checker.isArray(options) ? options : [options]);
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
changes: result.changes,
|
|
55
|
+
lastInsertRowid: result.lastInsertRowid,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {string} sql
|
|
65
|
+
* @param {array|object} [options = []]
|
|
66
|
+
*/
|
|
67
|
+
getOne(sql, options) {
|
|
68
|
+
try {
|
|
69
|
+
const stmt = this.#$.prepare(sql);
|
|
70
|
+
|
|
71
|
+
return stmt.get(...Checker.isArray(options) ? options : [options]) || null;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} sql
|
|
79
|
+
* @param {array|object} [options = []]
|
|
80
|
+
*/
|
|
81
|
+
getAll(sql, options) {
|
|
82
|
+
try {
|
|
83
|
+
const stmt = this.#$.prepare(sql);
|
|
84
|
+
|
|
85
|
+
return stmt.all(...Checker.isArray(options) ? options : [options]) || [];
|
|
86
|
+
} catch (error) {
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} name
|
|
93
|
+
* @param {string} sql
|
|
94
|
+
*/
|
|
95
|
+
prepare(name, sql) {
|
|
96
|
+
if (this.#statements.has(name)) {
|
|
97
|
+
return this.#statements.get(name);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const stmt = this.#$.prepare(sql);
|
|
101
|
+
|
|
102
|
+
this.#statements.set(name, stmt);
|
|
103
|
+
|
|
104
|
+
return stmt;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {string} table
|
|
109
|
+
* @param {object} schema
|
|
110
|
+
*/
|
|
111
|
+
createTable(table, schema) {
|
|
112
|
+
const columns = Object.entries(schema)
|
|
113
|
+
.map(([key, type]) => `${key} ${type}`)
|
|
114
|
+
.join(", ");
|
|
115
|
+
|
|
116
|
+
const sql = `CREATE TABLE IF NOT EXISTS ${table} (${columns})`;
|
|
117
|
+
|
|
118
|
+
this.exec(sql);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {string} table
|
|
123
|
+
* @param {object} data
|
|
124
|
+
*/
|
|
125
|
+
insert(table, data) {
|
|
126
|
+
const keys = Object.keys(data);
|
|
127
|
+
const placeholders = keys.map(() => "?").join(", ");
|
|
128
|
+
const sql = `INSERT INTO ${table} (${keys.join(", ")}) VALUES (${placeholders})`;
|
|
129
|
+
|
|
130
|
+
const result = this.exec(sql, Object.values(data));
|
|
131
|
+
|
|
132
|
+
return result.lastInsertRowid;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @param {string} table
|
|
137
|
+
* @param {number} id
|
|
138
|
+
* @returns {object|null}
|
|
139
|
+
*/
|
|
140
|
+
findById(table, id) {
|
|
141
|
+
return this.getOne(`SELECT * FROM ${table} WHERE id = ?`, [id]);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {string} table
|
|
146
|
+
* @param {object} [where = {}]
|
|
147
|
+
* @param {object} [options = {}]
|
|
148
|
+
*/
|
|
149
|
+
findAll(table, where, options) {
|
|
150
|
+
const { limit = 100, offset = 0, orderBy = "id" } = options;
|
|
151
|
+
|
|
152
|
+
let sql = `SELECT * FROM ${table}`;
|
|
153
|
+
|
|
154
|
+
if (Object.keys(where).length > 0) {
|
|
155
|
+
const conditions = Object.keys(where)
|
|
156
|
+
.map(key => `${key} = ?`)
|
|
157
|
+
.join(" AND ");
|
|
158
|
+
sql += ` WHERE ${conditions}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
sql += ` ORDER BY ${orderBy} LIMIT ? OFFSET ?`;
|
|
162
|
+
|
|
163
|
+
const params = [...Object.values(where), limit, offset];
|
|
164
|
+
|
|
165
|
+
return this.getAll(sql, params);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {string} table
|
|
170
|
+
* @param {object} [where]
|
|
171
|
+
*/
|
|
172
|
+
count(table, where = {}) {
|
|
173
|
+
let sql = `SELECT COUNT(*) as count FROM ${table}`;
|
|
174
|
+
|
|
175
|
+
if (Object.keys(where).length > 0) {
|
|
176
|
+
const conditions = Object.keys(where)
|
|
177
|
+
.map(key => `${key} = ?`)
|
|
178
|
+
.join(" AND ");
|
|
179
|
+
sql += ` WHERE ${conditions}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const result = this.getOne(sql, Object.values(where));
|
|
183
|
+
|
|
184
|
+
return result?.count || 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param {string} table
|
|
189
|
+
* @param {number} id
|
|
190
|
+
* @param {object} data
|
|
191
|
+
*/
|
|
192
|
+
update(table, id, data) {
|
|
193
|
+
const keys = Object.keys(data);
|
|
194
|
+
const setClause = keys.map(key => `${key} = ?`).join(", ");
|
|
195
|
+
const sql = `UPDATE ${table} SET ${setClause} WHERE id = ?`;
|
|
196
|
+
|
|
197
|
+
const result = this.exec(sql, [...Object.values(data), id]);
|
|
198
|
+
|
|
199
|
+
return result.changes;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @param {string} table
|
|
204
|
+
* @param {number} id
|
|
205
|
+
*/
|
|
206
|
+
delete(table, id) {
|
|
207
|
+
const sql = `DELETE FROM ${table} WHERE id = ?`;
|
|
208
|
+
const result = this.exec(sql, [id]);
|
|
209
|
+
|
|
210
|
+
return result.changes;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {string} table
|
|
215
|
+
* @param {object} data
|
|
216
|
+
* @param {string} [conflictColumn]
|
|
217
|
+
*/
|
|
218
|
+
upsert(table, data, conflictColumn = "id") {
|
|
219
|
+
const keys = Object.keys(data);
|
|
220
|
+
const placeholders = keys.map(() => "?").join(", ");
|
|
221
|
+
const updates = keys
|
|
222
|
+
.filter(k => k !== conflictColumn)
|
|
223
|
+
.map(k => `${k} = EXCLUDED.${k}`)
|
|
224
|
+
.join(", ");
|
|
225
|
+
|
|
226
|
+
const sql = `
|
|
227
|
+
INSERT INTO ${table} (${keys.join(", ")})
|
|
228
|
+
VALUES (${placeholders})
|
|
229
|
+
ON CONFLICT(${conflictColumn})
|
|
230
|
+
DO UPDATE SET ${updates}
|
|
231
|
+
`;
|
|
232
|
+
|
|
233
|
+
return this.exec(sql, Object.values(data));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param {function} callback
|
|
238
|
+
*/
|
|
239
|
+
transaction(callback) {
|
|
240
|
+
try {
|
|
241
|
+
this.exec("BEGIN TRANSACTION");
|
|
242
|
+
|
|
243
|
+
const result = callback();
|
|
244
|
+
|
|
245
|
+
this.exec("COMMIT");
|
|
246
|
+
|
|
247
|
+
return result;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
this.exec("ROLLBACK");
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {string} migrationsDir - Répertoire contenant les migrations
|
|
256
|
+
*/
|
|
257
|
+
runMigrations(migrationsDir) {
|
|
258
|
+
if (!FS.getFolder(migrationsDir)) {
|
|
259
|
+
FS.createFolder(migrationsDir);
|
|
260
|
+
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const migrationFiles = FS.getFilesIn(migrationsDir).filter(f => f.endsWith(".sql")).sort();
|
|
265
|
+
|
|
266
|
+
this.createTable("__migrations", {
|
|
267
|
+
name: "TEXT PRIMARY KEY",
|
|
268
|
+
executed_at: "DATETIME DEFAULT CURRENT_TIMESTAMP",
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
for (const file of migrationFiles) {
|
|
272
|
+
const migrationName = basename(file, ".sql");
|
|
273
|
+
const alreadyRun = this.getOne("SELECT * FROM __migrations WHERE name = ?", [migrationName]);
|
|
274
|
+
|
|
275
|
+
if (!alreadyRun) {
|
|
276
|
+
const sql = FS.readFile(`${migrationsDir}/${file}`);
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
this.exec(sql);
|
|
280
|
+
this.insert("__migrations", { name: migrationName });
|
|
281
|
+
} catch (error) {
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @param {string} table
|
|
290
|
+
*/
|
|
291
|
+
export(table) {
|
|
292
|
+
return this.getAll(`SELECT * FROM ${table}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @param {string} table
|
|
297
|
+
* @param {array} data
|
|
298
|
+
*/
|
|
299
|
+
import(table, data) {
|
|
300
|
+
let count = 0;
|
|
301
|
+
this.transaction(() => {
|
|
302
|
+
for (const row of data) {
|
|
303
|
+
this.insert(table, row);
|
|
304
|
+
count++;
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
return count;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* @param {string} table
|
|
312
|
+
*/
|
|
313
|
+
truncate(table) {
|
|
314
|
+
this.exec(`DELETE FROM ${table}`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* @param {string} indexName
|
|
319
|
+
* @param {string} table
|
|
320
|
+
* @param {string} columns
|
|
321
|
+
*/
|
|
322
|
+
createIndex(indexName, table, columns) {
|
|
323
|
+
this.exec(`CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} (${columns})`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @returns {object}
|
|
328
|
+
*/
|
|
329
|
+
stats() {
|
|
330
|
+
const tables = this.getAll("SELECT name FROM sqlite_master WHERE type='table'");
|
|
331
|
+
const stats = {};
|
|
332
|
+
|
|
333
|
+
for (const { name } of tables) {
|
|
334
|
+
if (!name.startsWith("__")) {
|
|
335
|
+
const count = this.count(name);
|
|
336
|
+
stats[name] = count;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return stats;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
close() {
|
|
344
|
+
if (this.db) {
|
|
345
|
+
this.#$.close();
|
|
346
|
+
this.#statements.clear();
|
|
347
|
+
this.#$ = null;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
};
|
package/core/Utils.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
const { config } = require("@dotenvx/dotenvx");
|
|
2
|
+
const { log } = require("./Logger");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @module Utils
|
|
6
|
+
* @description
|
|
7
|
+
*/
|
|
8
|
+
module.exports = {
|
|
9
|
+
getEnv(env) {
|
|
10
|
+
config({ quiet: true });
|
|
11
|
+
return process.env[env];
|
|
12
|
+
},
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Promise that resolves after specified milliseconds.
|
|
15
|
+
*
|
|
16
|
+
* @param {number} ms - Milliseconds to wait (positive integer).
|
|
17
|
+
* @returns {Promise<void>} Promise that resolves after delay.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Sequential delays
|
|
21
|
+
* await wait(100); // 100ms
|
|
22
|
+
* await wait(500); // 500ms
|
|
23
|
+
* await wait(2000); // 2 seconds
|
|
24
|
+
*/
|
|
25
|
+
wait(ms) {
|
|
26
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param {boolean|Promise<boolean>} predicate
|
|
31
|
+
* @param {*} handler
|
|
32
|
+
* @param {object} [options]
|
|
33
|
+
* @param {number} [options.interval]
|
|
34
|
+
* @param {number|null} [options.timeout]
|
|
35
|
+
* @param {number|null} [options.max]
|
|
36
|
+
*/
|
|
37
|
+
when(predicate, handler, options) {
|
|
38
|
+
const interval = options?.interval ?? 50;
|
|
39
|
+
const timeout = options?.timeout ?? null;
|
|
40
|
+
const max = options?.max ?? null;
|
|
41
|
+
|
|
42
|
+
const listeners = {
|
|
43
|
+
trigger: new Set(),
|
|
44
|
+
error: new Set(),
|
|
45
|
+
timeout: new Set(),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
let _timer = null;
|
|
49
|
+
let _timeoutTimer = null;
|
|
50
|
+
let _stopped = false;
|
|
51
|
+
let _count = 0;
|
|
52
|
+
|
|
53
|
+
function emit(event, payload) {
|
|
54
|
+
for (const fn of listeners[event]) {
|
|
55
|
+
try {
|
|
56
|
+
fn(payload);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(`[when] listener error on "${event}":`, error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function evalPredicate() {
|
|
64
|
+
if (typeof predicate === "function") {
|
|
65
|
+
return await predicate();
|
|
66
|
+
}
|
|
67
|
+
return Boolean(predicate);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function tick() {
|
|
71
|
+
if (_stopped) return;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const ok = await evalPredicate();
|
|
75
|
+
|
|
76
|
+
if (ok) {
|
|
77
|
+
_count++;
|
|
78
|
+
emit("trigger", handler);
|
|
79
|
+
|
|
80
|
+
if (max != null && _count >= max) {
|
|
81
|
+
_stopInternal();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!_stopped) {
|
|
87
|
+
_timer = setTimeout(tick, interval);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
emit("error", error);
|
|
91
|
+
if (!_stopped) {
|
|
92
|
+
_timer = setTimeout(tick, interval);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function _stopInternal() {
|
|
98
|
+
_stopped = true;
|
|
99
|
+
if (_timer) {
|
|
100
|
+
clearTimeout(_timer);
|
|
101
|
+
_timer = null;
|
|
102
|
+
}
|
|
103
|
+
if (_timeoutTimer) {
|
|
104
|
+
clearTimeout(_timeoutTimer);
|
|
105
|
+
_timeoutTimer = null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const api = {
|
|
110
|
+
start() {
|
|
111
|
+
if (_stopped) return api;
|
|
112
|
+
|
|
113
|
+
if (!_timer) {
|
|
114
|
+
_timer = setTimeout(tick, 0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (timeout != null && !_timeoutTimer) {
|
|
118
|
+
_timeoutTimer = setTimeout(() => {
|
|
119
|
+
if (_stopped) return;
|
|
120
|
+
emit("timeout", handler);
|
|
121
|
+
_stopInternal();
|
|
122
|
+
}, timeout);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return api;
|
|
126
|
+
},
|
|
127
|
+
stop() {
|
|
128
|
+
_stopInternal();
|
|
129
|
+
return api;
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* @param {"error"|"trigger"|"timeout"} event
|
|
133
|
+
* @param {(payload: any) => void} fn
|
|
134
|
+
*/
|
|
135
|
+
on(event, fn) {
|
|
136
|
+
listeners[event]?.add(fn);
|
|
137
|
+
return api;
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* @param {"error"|"trigger"|"timeout"} event
|
|
141
|
+
* @param {(payload: any) => void} fn
|
|
142
|
+
*/
|
|
143
|
+
off(event, fn) {
|
|
144
|
+
listeners[event]?.delete(fn);
|
|
145
|
+
return api;
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
return api;
|
|
150
|
+
},
|
|
151
|
+
dontCrash() {
|
|
152
|
+
const defaults = {
|
|
153
|
+
error: (error) => {
|
|
154
|
+
log(
|
|
155
|
+
`<% red [@ix-xs/node-comfort] Process Error %>\n<% gray ${error.stack ?? error} %>`,
|
|
156
|
+
);
|
|
157
|
+
},
|
|
158
|
+
exit: (code) => {
|
|
159
|
+
log(
|
|
160
|
+
`<% yellow [@ix-xs/node-comfort] Process Exit %>\n→ Code: <% gray ${code} %>`,
|
|
161
|
+
);
|
|
162
|
+
},
|
|
163
|
+
sig: (signal) => {
|
|
164
|
+
log(
|
|
165
|
+
`<% yellow [@ix-xs/node-comfort] Process SIG* %>\n→ Signal: <% gray ${signal} %>`,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
process.exit(0);
|
|
169
|
+
},
|
|
170
|
+
beforeExit: (code) => {},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const _ = {
|
|
174
|
+
/**
|
|
175
|
+
* @template { "error" | "exit" | "sig" | "beforeExit" } E
|
|
176
|
+
* @param { E } event
|
|
177
|
+
* @param { { error: (error: Error | unknown) => void | Promise<void>, exit: (code: number) => void | Promise<void>, sig: (signal: "SIGINT" | "SIGTERM" | "SIGQUIT") => void | Promise<void>, beforeExit: (code: number) => void|Promise<void> }[E] } handler
|
|
178
|
+
*/
|
|
179
|
+
on(event, handler) {
|
|
180
|
+
if (event === "error") {
|
|
181
|
+
process.removeAllListeners("uncaughtException");
|
|
182
|
+
process.removeAllListeners("unhandledRejection");
|
|
183
|
+
process.on("uncaughtException", handler ?? defaults.error);
|
|
184
|
+
process.on("unhandledRejection", handler ?? defaults.error);
|
|
185
|
+
} else if (event === "exit") {
|
|
186
|
+
process.removeAllListeners("exit");
|
|
187
|
+
process.on("exit", handler ?? defaults.exit);
|
|
188
|
+
} else if (event === "sig") {
|
|
189
|
+
for (const signal of ["SIGINT", "SIGTERM", "SIGQUIT"]) {
|
|
190
|
+
process.removeAllListeners(signal);
|
|
191
|
+
process.on(signal, handler ?? defaults.sig);
|
|
192
|
+
}
|
|
193
|
+
} else if (event === "beforeExit") {
|
|
194
|
+
process.removeAllListeners("beforeExit");
|
|
195
|
+
process.on("beforeExit", handler ?? defaults.beforeExit);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return _;
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
_.on("error").on("exit").on("sig");
|
|
203
|
+
|
|
204
|
+
return _;
|
|
205
|
+
},
|
|
206
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const Checker = require("./core/Checker");
|
|
2
|
+
const CLI = require("./core/CLI");
|
|
3
|
+
const Storage = require("./core/Storage");
|
|
4
|
+
const FS = require("./core/FS");
|
|
5
|
+
const Logger = require("./core/Logger");
|
|
6
|
+
const Stepper = require("./core/Stepper");
|
|
7
|
+
const Utils = require("./core/Utils");
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
...Checker,
|
|
11
|
+
...CLI,
|
|
12
|
+
Storage,
|
|
13
|
+
...FS,
|
|
14
|
+
...Logger,
|
|
15
|
+
...Stepper,
|
|
16
|
+
...Utils,
|
|
17
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ix-xs/node-comfort",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "ix-xs",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@dotenvx/dotenvx": "^1.51.2"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22.5.0"
|
|
16
|
+
}
|
|
17
|
+
}
|