@rwillians/qx 0.1.2 → 0.1.3

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.
@@ -0,0 +1,666 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.t = exports.is = exports.into = exports.from = exports.expr = exports.table = exports.create = void 0;
4
+ const std = require("./standard-schema");
5
+ const u = require("./utils");
6
+ // // // // // // // // // // // // // // // // // // // // // // // //
7
+ // SYMBOLS //
8
+ // // // // // // // // // // // // // // // // // // // // // // // //
9
+ /**
10
+ * @private Symbol used to store the table name on aliased tables.
11
+ * @since 0.1.0
12
+ * @version 1
13
+ */
14
+ const TABLE_NAME = Symbol.for('~exto.table-name');
15
+ /**
16
+ * @private Symbol used to store the table alias on aliased tables.
17
+ * @since 0.1.0
18
+ * @version 1
19
+ */
20
+ const TABLE_ALIAS = Symbol.for('~exto.table-alias');
21
+ /**
22
+ * @private A builder for column properties.
23
+ * @since 0.1.0
24
+ * @version 1
25
+ */
26
+ class ColumnPropsBuilder {
27
+ props;
28
+ constructor(props) {
29
+ this.props = props;
30
+ }
31
+ /**
32
+ * @public Marks the column as autoincrementing.
33
+ * @since 0.1.0
34
+ * @version 1
35
+ */
36
+ autoincrement() {
37
+ if (this.props.type !== 'INTEGER')
38
+ throw new Error('Autoincrement can only be set on integer columns');
39
+ return new ColumnPropsBuilder({ ...this.props, autoincrement: true });
40
+ }
41
+ /**
42
+ * @public Sets a default value for the column.
43
+ * @since 0.1.0
44
+ * @version 1
45
+ */
46
+ default(value) {
47
+ return new ColumnPropsBuilder({ ...this.props, default: value });
48
+ }
49
+ /**
50
+ * @public Marks the column as nullable.
51
+ * @since 0.1.0
52
+ * @version 1
53
+ * @throws {Error} if the column is a primary key.
54
+ */
55
+ nullable() {
56
+ if (this.props.primaryKey)
57
+ throw new Error('Cannot set nullable on a primary key column');
58
+ const { schema, ...props } = this.props;
59
+ return new ColumnPropsBuilder({ ...props, nullable: true, schema: std.nullable(schema) });
60
+ }
61
+ /**
62
+ * @public Marks the column as a primary key.
63
+ * @since 0.1.0
64
+ * @version 1
65
+ * @throws {Error} if the column is nullable.
66
+ */
67
+ primaryKey() {
68
+ if (this.props.nullable)
69
+ throw new Error('Cannot make a nullable column a primary key');
70
+ return new ColumnPropsBuilder({ ...this.props, primaryKey: true });
71
+ }
72
+ }
73
+ /**
74
+ * @public A way to define a column with a custom standard schema.
75
+ * @since 0.1.0
76
+ * @version 1
77
+ */
78
+ const defineColumn = (baseProps) => new ColumnPropsBuilder(baseProps);
79
+ /**
80
+ * @public Built-in column types.
81
+ * @since 0.1.0
82
+ * @version 1
83
+ */
84
+ const types = {
85
+ /**
86
+ * @public Defines a column type that accepts binary data.
87
+ * @since 0.1.0
88
+ * @version 1
89
+ */
90
+ binary: () => defineColumn({
91
+ type: 'BINARY',
92
+ schema: std.instanceOf(Uint8Array),
93
+ }),
94
+ /**
95
+ * @public Defines a column type that accepts boolean values.
96
+ * @since 0.1.0
97
+ * @version 1
98
+ */
99
+ boolean: () => defineColumn({
100
+ type: 'BOOLEAN',
101
+ schema: std.boolean(),
102
+ }),
103
+ /**
104
+ * @public Defines a column type that accepts a Date object, an
105
+ * ISO 8601 date string, or a Unix timestamp in milliseconds.
106
+ * @since 0.1.0
107
+ * @version 1
108
+ */
109
+ datetime: () => defineColumn({
110
+ type: 'DATETIME',
111
+ schema: std.date(),
112
+ }),
113
+ /**
114
+ * @public Defines a column type that accepts floating-point numbers.
115
+ * @since 0.1.0
116
+ * @version 1
117
+ */
118
+ float: () => defineColumn({
119
+ type: 'FLOAT',
120
+ schema: std.number({ min: Number.MIN_VALUE, max: Number.MAX_VALUE }),
121
+ }),
122
+ /**
123
+ * @public Defines a column type that accepts integer numbers.
124
+ * @since 0.1.0
125
+ * @version 1
126
+ */
127
+ integer: () => defineColumn({
128
+ type: 'INTEGER',
129
+ schema: std.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }),
130
+ }),
131
+ /**
132
+ * @public Defines a column type that accepts small strings (VARCHAR,
133
+ * up to 255 characters).
134
+ * @since 0.1.0
135
+ * @version 1
136
+ * @throws {Error} if the specified size is greater than 255.
137
+ */
138
+ string: ({ size = 255 } = {}) => defineColumn({
139
+ type: 'VARCHAR',
140
+ schema: std.string({ max: u.lte(size, 255) }),
141
+ size,
142
+ }),
143
+ /**
144
+ * @public Defines a column type that accepts large strings (TEXT).
145
+ * @since 0.1.0
146
+ * @version 1
147
+ */
148
+ text: () => defineColumn({
149
+ type: 'TEXT',
150
+ schema: std.string(),
151
+ }),
152
+ };
153
+ exports.t = types;
154
+ /**
155
+ * @private Creates the `as` function for aliasing a table.
156
+ * @since 0.1.0
157
+ * @version 1
158
+ */
159
+ const aliasedTableFn = (table) => (alias) => {
160
+ const columns = Object.fromEntries(Object
161
+ .entries(table.columns)
162
+ .map(([cname, col]) => [cname, { ...col, table: alias }]));
163
+ return { [TABLE_NAME]: table.name, [TABLE_ALIAS]: alias, ...columns };
164
+ };
165
+ /**
166
+ * @public Defines a new table.
167
+ * @since 0.1.0
168
+ * @version 1
169
+ */
170
+ const defineTable = (tname, shapeFn) => {
171
+ const columns = Object.fromEntries(Object
172
+ .entries(shapeFn(types))
173
+ .map(([cname, { props }]) => [cname, { ...props, name: cname, table: tname }]));
174
+ const table = { name: tname, columns };
175
+ return { ...table, as: aliasedTableFn(table) };
176
+ };
177
+ exports.table = defineTable;
178
+ /**
179
+ * @public Expression builders.
180
+ * @since 0.1.0
181
+ * @version 1
182
+ */
183
+ const expr = {
184
+ // // // // // // // // // // // // // // // // // // // // // // //
185
+ // BINARY OP EXPRESSIONS //
186
+ // // // // // // // // // // // // // // // // // // // // // // //
187
+ /**
188
+ * @public Builds an equality expression.
189
+ * @since 0.1.0
190
+ * @version 1
191
+ */
192
+ eq: (lhs, rhs) => ({ lhs, op: '=', rhs }),
193
+ /**
194
+ * @public Builds a not-equal expression.
195
+ * @since 0.1.0
196
+ * @version 1
197
+ */
198
+ ne: (lhs, rhs) => ({ lhs, op: '!=', rhs }),
199
+ /**
200
+ * @public Builds a less-than expression.
201
+ * @since 0.1.0
202
+ * @version 1
203
+ */
204
+ lt: (lhs, rhs) => ({ lhs, op: '<', rhs }),
205
+ /**
206
+ * @public Builds a less-than-or-equal expression.
207
+ * @since 0.1.0
208
+ * @version 1
209
+ */
210
+ lte: (lhs, rhs) => ({ lhs, op: '<=', rhs }),
211
+ /**
212
+ * @public Builds a greater-than expression.
213
+ * @since 0.1.0
214
+ * @version 1
215
+ */
216
+ gt: (lhs, rhs) => ({ lhs, op: '>', rhs }),
217
+ /**
218
+ * @public Builds a greater-than-or-equal expression.
219
+ * @since 0.1.0
220
+ * @version 1
221
+ */
222
+ gte: (lhs, rhs) => ({ lhs, op: '>=', rhs }),
223
+ /**
224
+ * @public Builds a LIKE expression.
225
+ * @since 0.1.0
226
+ * @version 1
227
+ */
228
+ like: (lhs, rhs) => ({ lhs, op: 'LIKE', rhs }),
229
+ /**
230
+ * @public Builds a NOT LIKE expression.
231
+ * @since 0.1.0
232
+ * @version 1
233
+ */
234
+ notLike: (lhs, rhs) => ({ lhs, op: 'NOT LIKE', rhs }),
235
+ /**
236
+ * @public Builds an IN expression.
237
+ * @since 0.1.0
238
+ * @version 1
239
+ */
240
+ in: (lhs, rhs) => ({ lhs, op: 'IN', rhs }),
241
+ /**
242
+ * @public Builds a NOT IN expression.
243
+ * @since 0.1.0
244
+ * @version 1
245
+ */
246
+ notIn: (lhs, rhs) => ({ lhs, op: 'NOT IN', rhs }),
247
+ /**
248
+ * @public Builds an IS expression.
249
+ * @since 0.1.0
250
+ * @version 1
251
+ */
252
+ is: (lhs, rhs) => ({ lhs, op: 'IS', rhs }),
253
+ /**
254
+ * @public Builds an IS NOT expression.
255
+ * @since 0.1.0
256
+ * @version 1
257
+ */
258
+ isNot: (lhs, rhs) => ({ lhs, op: 'IS NOT', rhs }),
259
+ // // // // // // // // // // // // // // // // // // // // // // //
260
+ // BOOLEAN OP EXPRESSIONS //
261
+ // // // // // // // // // // // // // // // // // // // // // // //
262
+ /**
263
+ * @public Builds an AND expression.
264
+ * @since 0.1.0
265
+ * @version 1
266
+ */
267
+ and: (exprs) => ({ and: exprs }),
268
+ /**
269
+ * @public Builds an OR expression.
270
+ * @since 0.1.0
271
+ * @version 1
272
+ */
273
+ or: (exprs) => ({ or: exprs }),
274
+ /**
275
+ * @public Builds a NOT expression.
276
+ * @since 0.1.0
277
+ * @version 1
278
+ */
279
+ not: (expr) => ({ not: expr }),
280
+ };
281
+ exports.expr = expr;
282
+ /**
283
+ * @public Expression type guards.
284
+ * @since 0.1.0
285
+ * @version 1
286
+ */
287
+ const is = {
288
+ // // // // // // // // // // // // // // // // // // // // // // //
289
+ // BINARY OP EXPRESSIONS //
290
+ // // // // // // // // // // // // // // // // // // // // // // //
291
+ /**
292
+ * @public Checks whether the given value is a binary op expression.
293
+ * @since 0.1.0
294
+ * @version 1
295
+ */
296
+ binaryOp: (expr) => u.isPlainObject(expr) && 'op' in expr && 'lhs' in expr && 'rhs' in expr,
297
+ /**
298
+ * @public Checks whether the given value is an equality expression.
299
+ * @since 0.1.0
300
+ * @version 1
301
+ */
302
+ eq: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '=',
303
+ /**
304
+ * @public Checks whether the given value is a not-equal expression.
305
+ * @since 0.1.0
306
+ * @version 1
307
+ */
308
+ ne: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '!=',
309
+ /**
310
+ * @public Checks whether the given value is a less-than expression.
311
+ * @since 0.1.0
312
+ * @version 1
313
+ */
314
+ lt: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '<',
315
+ /**
316
+ * @public Checks whether the given value is a less-than-or-equal expression.
317
+ * @since 0.1.0
318
+ * @version 1
319
+ */
320
+ lte: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '<=',
321
+ /**
322
+ * @public Checks whether the given value is a greater-than expression.
323
+ * @since 0.1.0
324
+ * @version 1
325
+ */
326
+ gt: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '>',
327
+ /**
328
+ * @public Checks whether the given value is a greater-than-or-equal expression.
329
+ * @since 0.1.0
330
+ * @version 1
331
+ */
332
+ gte: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === '>=',
333
+ /**
334
+ * @public Checks whether the given value is a LIKE expression.
335
+ * @since 0.1.0
336
+ * @version 1
337
+ */
338
+ like: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === 'LIKE',
339
+ /**
340
+ * @public Checks whether the given value is a NOT LIKE expression.
341
+ * @since 0.1.0
342
+ * @version 1
343
+ */
344
+ notLike: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === 'NOT LIKE',
345
+ /**
346
+ * @public Checks whether the given value is an IN expression.
347
+ * @since 0.1.0
348
+ * @version 1
349
+ */
350
+ in: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === 'IN',
351
+ /**
352
+ * @public Checks whether the given value is a NOT IN expression.
353
+ * @since 0.1.0
354
+ * @version 1
355
+ */
356
+ notIn: (expr) => u.isPlainObject(expr) && 'op' in expr && expr.op === 'NOT IN',
357
+ /**
358
+ * @public Checks whether the given value is an IS expression.
359
+ * @since 0.1.0
360
+ * @version 1
361
+ */
362
+ is: (expr) => u.isPlainObject(expr) && 'is' in expr,
363
+ // // // // // // // // // // // // // // // // // // // // // // //
364
+ // BOOLEAN OP EXPRESSIONS //
365
+ // // // // // // // // // // // // // // // // // // // // // // //
366
+ /**
367
+ * @public Checks whether the given value is an AND expression.
368
+ * @since 0.1.0
369
+ * @version 1
370
+ */
371
+ and: (expr) => u.isPlainObject(expr) && 'and' in expr,
372
+ /**
373
+ * @public Checks whether the given value is an OR expression.
374
+ * @since 0.1.0
375
+ * @version 1
376
+ */
377
+ or: (expr) => u.isPlainObject(expr) && 'or' in expr,
378
+ /**
379
+ * @public Checks whether the given value is a NOT expression.
380
+ * @since 0.1.0
381
+ * @version 1
382
+ */
383
+ not: (expr) => u.isPlainObject(expr) && 'not' in expr,
384
+ // // // // // // // // // // // // // // // // // // // // // // //
385
+ // LITERALS //
386
+ // // // // // // // // // // // // // // // // // // // // // // //
387
+ /**
388
+ * @public Checks whether the given value is a boolean literal.
389
+ * @since 0.1.0
390
+ * @version 1
391
+ */
392
+ boolean: (value) => typeof value === 'boolean',
393
+ /**
394
+ * @public Checks whether the given value is a date literal.
395
+ * @since 0.1.0
396
+ * @version 1
397
+ */
398
+ date: (value) => value instanceof Date,
399
+ /**
400
+ * @public Checks whether the given value is a null literal.
401
+ * @since 0.1.0
402
+ * @version 1
403
+ */
404
+ null: (expr) => expr === null,
405
+ /**
406
+ * @public Checks whether the given value is a number literal.
407
+ * @since 0.1.0
408
+ * @version 1
409
+ */
410
+ number: (expr) => typeof expr === 'number',
411
+ /**
412
+ * @public Checks whether the given value is a string literal.
413
+ * @since 0.1.0
414
+ * @version 1
415
+ */
416
+ string: (expr) => typeof expr === 'string',
417
+ // // // // // // // // // // // // // // // // // // // // // // //
418
+ // OTHERS //
419
+ // // // // // // // // // // // // // // // // // // // // // // //
420
+ /**
421
+ * @public Checks whether the given value is a literal expression.
422
+ * @since 0.1.0
423
+ * @version 1
424
+ */
425
+ literal: (expr) => expr === null || expr instanceof Date || ['boolean', 'number', 'string'].includes(typeof expr),
426
+ /**
427
+ * @public Checks whether the given value is a column expression.
428
+ * @since 0.1.0
429
+ * @version 1
430
+ */
431
+ column: (expr) => u.isPlainObject(expr) && 'type' in expr && 'schema' in expr,
432
+ };
433
+ exports.is = is;
434
+ ;
435
+ ;
436
+ // // // // // // // // // // // // // // // // // // // // // // // //
437
+ // CREATE STATEMENTS //
438
+ // // // // // // // // // // // // // // // // // // // // // // // //
439
+ /**
440
+ * @public Create statement builder.
441
+ * @since 0.1.0
442
+ * @version 1
443
+ */
444
+ const create = {
445
+ /**
446
+ * @public Prepares a create table statement.
447
+ * @since 0.1.0
448
+ * @version 1
449
+ */
450
+ table: (table, options = {}) => ({
451
+ /**
452
+ * @public Executes the create table statement onto the given
453
+ * database.
454
+ * @since 0.1.0
455
+ * @version 1
456
+ */
457
+ onto: async (db) => db.createTable({
458
+ ...options,
459
+ table: table.name,
460
+ columns: Object.values(table.columns),
461
+ }),
462
+ }),
463
+ };
464
+ exports.create = create;
465
+ // // // // // // // // // // // // // // // // // // // // // // // //
466
+ // INSERT STATEMENT //
467
+ // // // // // // // // // // // // // // // // // // // // // // // //
468
+ /**
469
+ * @private Resolves the value of a column before insertion. This is
470
+ * where default values are applied if the column is either
471
+ * missing or nullish.
472
+ * @since 0.1.0
473
+ * @version 1
474
+ */
475
+ const resolveInsertValue = (column, row) => {
476
+ if (column.default)
477
+ return row[column.name] ?? u.resolve(column.default);
478
+ // ↓ it's ok to omit nullable columns, let's make it null if undefined
479
+ if (column.nullable)
480
+ return row[column.name] ?? null;
481
+ return row[column.name];
482
+ };
483
+ /**
484
+ * @private Prepares a row for insertion. Only known fields are kept,
485
+ * additional fields get disposed of.
486
+ * @since 0.1.0
487
+ * @version 1
488
+ */
489
+ const prepareForInsert = (shape) => (row) => Object.fromEntries(Object
490
+ .entries(shape)
491
+ .map(([key, column]) => [key, resolveInsertValue(column, row)]));
492
+ /**
493
+ * @private Takes from the given table only the columns that can be
494
+ * present on insertion. It excludes, for example,
495
+ * autoincrement columns.
496
+ * @since 0.1.0
497
+ * @version 1
498
+ */
499
+ const getInsertShape = (table) => Object.fromEntries(Object
500
+ .entries(table.columns)
501
+ .filter(([_, col]) => !col.autoincrement));
502
+ /**
503
+ * @private Builds the standard schema to be used to parse / validate
504
+ * rows before insertion.
505
+ * @since 0.1.0
506
+ * @version 1
507
+ */
508
+ const buildInsertSchema = (shape) => std.strictObject(u.mapValues(shape, (column) => column.schema));
509
+ /**
510
+ * @public Insert statement builder.
511
+ * @since 0.1.0
512
+ * @version 1
513
+ */
514
+ class InsertBuilder {
515
+ table;
516
+ rows;
517
+ constructor(table, rows = []) {
518
+ this.table = table;
519
+ this.rows = rows;
520
+ }
521
+ /**
522
+ * @public Adds one or more rows to be inserted.
523
+ * @since 0.1.0
524
+ * @version 1
525
+ */
526
+ insert(rows) {
527
+ this.rows.push(...(u.wrap(rows)));
528
+ return this;
529
+ }
530
+ /**
531
+ * @public Executes the insert statement onto the given database.
532
+ * @since 0.1.0
533
+ * @version 1
534
+ */
535
+ async run(db) {
536
+ if (this.rows.length === 0)
537
+ return [];
538
+ const insertShape = getInsertShape(this.table);
539
+ const schema = std.array(buildInsertSchema(insertShape));
540
+ const result = std.parse(schema, this.rows.map(prepareForInsert(insertShape)));
541
+ if (result.issues)
542
+ throw new Error('Failed validation: ' + JSON.stringify(result.issues, null, 2));
543
+ const rows = await db.insert({
544
+ table: this.table.name,
545
+ records: result.value,
546
+ insertShape,
547
+ returnShape: this.table.columns,
548
+ });
549
+ return rows;
550
+ }
551
+ ;
552
+ }
553
+ /**
554
+ * @public Starts an insert statement for the given table.
555
+ * @since 0.1.0
556
+ * @version 1
557
+ */
558
+ const into = (table) => new InsertBuilder(table);
559
+ exports.into = into;
560
+ /**
561
+ * @private Transforms a {@link Query} into a {@link SelectStatement}.
562
+ * @since 0.1.0
563
+ * @version 1
564
+ */
565
+ const toSelectStatement = (query) => ({
566
+ ...query,
567
+ registry: u.mapValues(query.registry, table => table[TABLE_NAME]),
568
+ });
569
+ /**
570
+ * @public Select statement builder with a fluent API.
571
+ *
572
+ * We only need to keep track of two types in here:
573
+ * - the registry of aliased tables, so they can be
574
+ * referenced in expressions and selection; and
575
+ * - the selected columns, so we can infer the returning
576
+ * type of the query.
577
+ * @since 0.1.0
578
+ * @version 1
579
+ */
580
+ class QueryBuilder {
581
+ query;
582
+ constructor(query) {
583
+ this.query = query;
584
+ }
585
+ /**
586
+ * @public Executes the select statement against the given database,
587
+ * returning all matching rows.
588
+ * @since 0.1.0
589
+ * @version 1
590
+ */
591
+ async all(db) {
592
+ // @TODO calls query engine with the query object
593
+ return db.query(toSelectStatement(this.query));
594
+ }
595
+ /**
596
+ * @public Sets a limit on the number of rows to be returned.
597
+ * @since 0.1.0
598
+ * @version 1
599
+ */
600
+ limit(n) {
601
+ return new QueryBuilder({ ...this.query, limit: n });
602
+ }
603
+ /**
604
+ * @public Sets an offset for the rows to be returned.
605
+ * @since 0.1.0
606
+ * @version 1
607
+ */
608
+ offset(n) {
609
+ return new QueryBuilder({ ...this.query, offset: n });
610
+ }
611
+ /**
612
+ * @public Executes the select statement against the given database,
613
+ * returning the first matching row.
614
+ * @since 0.1.0
615
+ * @version 1
616
+ */
617
+ async one(db) {
618
+ // @TODO calls query engine with the query object
619
+ const op = toSelectStatement({ ...this.query, limit: 1, offset: 0 });
620
+ const rows = await db.query(op);
621
+ if (rows.length === 0)
622
+ return null;
623
+ return rows[0];
624
+ }
625
+ /**
626
+ * @public Defines the order by clause of the query.
627
+ * @since 0.1.0
628
+ * @version 1
629
+ */
630
+ orderBy(fn) {
631
+ return new QueryBuilder({ ...this.query, orderBy: fn(this.query.registry) });
632
+ }
633
+ /**
634
+ * @public Defines the selection of the query.
635
+ * @since 0.1.0
636
+ * @version 1
637
+ */
638
+ select(fn) {
639
+ return new QueryBuilder({ ...this.query, select: fn(this.query.registry) });
640
+ }
641
+ /**
642
+ * @public Defines the where clause of the query. If there's already
643
+ * a WHERE clause in the query, the new clause will be
644
+ * ANDed to the existing one.
645
+ * @since 0.1.0
646
+ * @version 1
647
+ */
648
+ where(fn) {
649
+ const value = fn(this.query.registry);
650
+ const where = this.query.where === undefined ? value
651
+ : is.and(this.query.where) ? expr.and([...this.query.where.and, value])
652
+ : expr.and([this.query.where, value]);
653
+ return new QueryBuilder({ ...this.query, where });
654
+ }
655
+ }
656
+ /**
657
+ * @public Starts a select statement from the given table.
658
+ * @since 0.1.0
659
+ * @version 1
660
+ */
661
+ const from = (table) => new QueryBuilder({
662
+ registry: { [table[TABLE_ALIAS]]: table },
663
+ from: table[TABLE_ALIAS],
664
+ select: { ...table },
665
+ });
666
+ exports.from = from;
@@ -0,0 +1,7 @@
1
+ import { type ILogger } from './index';
2
+ /**
3
+ * @public Creates a basic console logger that logs all queries.
4
+ * @since 0.1.0
5
+ * @version 1
6
+ */
7
+ export declare const createPrettyLogger: () => ILogger;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPrettyLogger = void 0;
4
+ const node_util_1 = require("node:util");
5
+ const sql_highlight_1 = require("sql-highlight");
6
+ /**
7
+ * @public Creates a basic console logger that logs all queries.
8
+ * @since 0.1.0
9
+ * @version 1
10
+ */
11
+ const createPrettyLogger = () => ({
12
+ debug: (sql, params) => { process.stdout.write((0, sql_highlight_1.highlight)(sql) + ' ' + (0, node_util_1.inspect)(params, false, null, true) + '\n'); },
13
+ });
14
+ exports.createPrettyLogger = createPrettyLogger;