pqb 0.0.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.
- package/dist/index.d.ts +3630 -0
- package/dist/index.esm.js +4587 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +4691 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
- package/rollup.config.js +35 -0
- package/src/adapter.test.ts +10 -0
- package/src/adapter.ts +171 -0
- package/src/columnSchema/array.ts +21 -0
- package/src/columnSchema/boolean.ts +10 -0
- package/src/columnSchema/columnType.test.ts +129 -0
- package/src/columnSchema/columnType.ts +77 -0
- package/src/columnSchema/columnTypes.ts +145 -0
- package/src/columnSchema/columnsSchema.test.ts +32 -0
- package/src/columnSchema/columnsSchema.ts +100 -0
- package/src/columnSchema/commonMethods.ts +130 -0
- package/src/columnSchema/dateTime.ts +104 -0
- package/src/columnSchema/enum.ts +13 -0
- package/src/columnSchema/index.ts +11 -0
- package/src/columnSchema/json/array.ts +55 -0
- package/src/columnSchema/json/discriminatedUnion.ts +91 -0
- package/src/columnSchema/json/enum.ts +29 -0
- package/src/columnSchema/json/instanceOf.ts +16 -0
- package/src/columnSchema/json/intersection.ts +23 -0
- package/src/columnSchema/json/lazy.ts +22 -0
- package/src/columnSchema/json/literal.ts +12 -0
- package/src/columnSchema/json/map.ts +29 -0
- package/src/columnSchema/json/nativeEnum.ts +30 -0
- package/src/columnSchema/json/nullable.ts +33 -0
- package/src/columnSchema/json/nullish.ts +30 -0
- package/src/columnSchema/json/object.ts +206 -0
- package/src/columnSchema/json/optional.ts +28 -0
- package/src/columnSchema/json/record.ts +40 -0
- package/src/columnSchema/json/scalarTypes.ts +117 -0
- package/src/columnSchema/json/set.ts +34 -0
- package/src/columnSchema/json/tuple.ts +40 -0
- package/src/columnSchema/json/typeBase.ts +202 -0
- package/src/columnSchema/json/union.ts +16 -0
- package/src/columnSchema/json.ts +64 -0
- package/src/columnSchema/number.ts +122 -0
- package/src/columnSchema/string.ts +222 -0
- package/src/columnSchema/utils.ts +27 -0
- package/src/common.ts +86 -0
- package/src/db.test.ts +67 -0
- package/src/db.ts +212 -0
- package/src/errors.ts +7 -0
- package/src/index.ts +18 -0
- package/src/operators.test.ts +608 -0
- package/src/operators.ts +177 -0
- package/src/query.ts +292 -0
- package/src/queryDataUtils.ts +50 -0
- package/src/queryMethods/aggregate.test.ts +583 -0
- package/src/queryMethods/aggregate.ts +878 -0
- package/src/queryMethods/callbacks.test.ts +69 -0
- package/src/queryMethods/callbacks.ts +55 -0
- package/src/queryMethods/clear.test.ts +64 -0
- package/src/queryMethods/clear.ts +58 -0
- package/src/queryMethods/columnInfo.test.ts +45 -0
- package/src/queryMethods/columnInfo.ts +67 -0
- package/src/queryMethods/delete.test.ts +135 -0
- package/src/queryMethods/delete.ts +50 -0
- package/src/queryMethods/for.test.ts +57 -0
- package/src/queryMethods/for.ts +99 -0
- package/src/queryMethods/from.test.ts +66 -0
- package/src/queryMethods/from.ts +58 -0
- package/src/queryMethods/get.test.ts +66 -0
- package/src/queryMethods/get.ts +88 -0
- package/src/queryMethods/having.test.ts +247 -0
- package/src/queryMethods/having.ts +99 -0
- package/src/queryMethods/insert.test.ts +555 -0
- package/src/queryMethods/insert.ts +453 -0
- package/src/queryMethods/join.test.ts +150 -0
- package/src/queryMethods/join.ts +508 -0
- package/src/queryMethods/json.test.ts +398 -0
- package/src/queryMethods/json.ts +259 -0
- package/src/queryMethods/log.test.ts +172 -0
- package/src/queryMethods/log.ts +123 -0
- package/src/queryMethods/queryMethods.test.ts +629 -0
- package/src/queryMethods/queryMethods.ts +428 -0
- package/src/queryMethods/select.test.ts +479 -0
- package/src/queryMethods/select.ts +249 -0
- package/src/queryMethods/then.ts +236 -0
- package/src/queryMethods/transaction.test.ts +66 -0
- package/src/queryMethods/transaction.ts +66 -0
- package/src/queryMethods/union.test.ts +59 -0
- package/src/queryMethods/union.ts +89 -0
- package/src/queryMethods/update.test.ts +417 -0
- package/src/queryMethods/update.ts +350 -0
- package/src/queryMethods/upsert.test.ts +56 -0
- package/src/queryMethods/upsert.ts +43 -0
- package/src/queryMethods/where.test.ts +1594 -0
- package/src/queryMethods/where.ts +450 -0
- package/src/queryMethods/window.test.ts +66 -0
- package/src/queryMethods/window.ts +108 -0
- package/src/queryMethods/with.test.ts +191 -0
- package/src/queryMethods/with.ts +92 -0
- package/src/quote.ts +36 -0
- package/src/relations.ts +194 -0
- package/src/sql/aggregate.ts +80 -0
- package/src/sql/columnInfo.ts +22 -0
- package/src/sql/common.ts +42 -0
- package/src/sql/delete.ts +41 -0
- package/src/sql/distinct.ts +19 -0
- package/src/sql/fromAndAs.ts +51 -0
- package/src/sql/having.ts +140 -0
- package/src/sql/index.ts +2 -0
- package/src/sql/insert.ts +102 -0
- package/src/sql/join.ts +242 -0
- package/src/sql/orderBy.ts +41 -0
- package/src/sql/select.ts +153 -0
- package/src/sql/toSql.ts +153 -0
- package/src/sql/truncate.ts +13 -0
- package/src/sql/types.ts +355 -0
- package/src/sql/update.ts +62 -0
- package/src/sql/where.ts +314 -0
- package/src/sql/window.ts +38 -0
- package/src/sql/with.ts +32 -0
- package/src/test-utils.ts +172 -0
- package/src/utils.ts +140 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { createDb } from '../db';
|
|
2
|
+
import { adapter, dbOptions, userData, useTestDatabase } from '../test-utils';
|
|
3
|
+
import { logColors } from './log';
|
|
4
|
+
import { noop } from '../utils';
|
|
5
|
+
|
|
6
|
+
describe('query log', () => {
|
|
7
|
+
useTestDatabase();
|
|
8
|
+
|
|
9
|
+
it('should not have `log` query object by default', () => {
|
|
10
|
+
const db = createDb(dbOptions);
|
|
11
|
+
|
|
12
|
+
expect(db('user').query.log).toBe(undefined);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should set `log` query object when configuring db instance', () => {
|
|
16
|
+
const db = createDb({
|
|
17
|
+
...dbOptions,
|
|
18
|
+
log: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
expect(db('user').query.log).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should set `log` query object for a table', () => {
|
|
25
|
+
const db = createDb(dbOptions);
|
|
26
|
+
const table = db('user', undefined, { log: true });
|
|
27
|
+
|
|
28
|
+
expect(table.query.log).toBeTruthy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should set `log` query object with query method', () => {
|
|
32
|
+
const db = createDb(dbOptions);
|
|
33
|
+
const table = db('user');
|
|
34
|
+
|
|
35
|
+
expect(table.log().query.log).toBeTruthy();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should log elapsed time, sql and binding values', async () => {
|
|
39
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
40
|
+
hrtime.mockReturnValueOnce([0, 0]);
|
|
41
|
+
hrtime.mockReturnValueOnce([1, 1000000]);
|
|
42
|
+
|
|
43
|
+
const logger = {
|
|
44
|
+
log: jest.fn(),
|
|
45
|
+
error: jest.fn(),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const db = createDb({ adapter, log: true, logger });
|
|
49
|
+
|
|
50
|
+
await db('user').where({ name: 'name' });
|
|
51
|
+
|
|
52
|
+
expect(logger.log.mock.calls).toEqual([
|
|
53
|
+
[
|
|
54
|
+
`${logColors.boldCyanBright('(1s 1.0ms)')} ${logColors.boldBlue(
|
|
55
|
+
`SELECT * FROM "user" WHERE "user"."name" = $1`,
|
|
56
|
+
)} ${logColors.boldYellow(`['name']`)}`,
|
|
57
|
+
],
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should log elapsed time, sql and binding values without colors', async () => {
|
|
62
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
63
|
+
hrtime.mockReturnValueOnce([0, 0]);
|
|
64
|
+
hrtime.mockReturnValueOnce([1, 1000000]);
|
|
65
|
+
|
|
66
|
+
const logger = {
|
|
67
|
+
log: jest.fn(),
|
|
68
|
+
error: jest.fn(),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const db = createDb({ adapter, log: { colors: false }, logger });
|
|
72
|
+
|
|
73
|
+
await db('user').where({ name: 'name' });
|
|
74
|
+
|
|
75
|
+
expect(logger.log.mock.calls).toEqual([
|
|
76
|
+
[`(1s 1.0ms) SELECT * FROM "user" WHERE "user"."name" = $1 ['name']`],
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should log in red in case of error', async () => {
|
|
81
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
82
|
+
hrtime.mockReturnValueOnce([0, 0]);
|
|
83
|
+
hrtime.mockReturnValueOnce([1, 1000000]);
|
|
84
|
+
|
|
85
|
+
const logger = {
|
|
86
|
+
log: jest.fn(),
|
|
87
|
+
error: jest.fn(),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const db = createDb({ adapter, log: true, logger });
|
|
91
|
+
|
|
92
|
+
await db('user').where({ wrongColumn: 'value' }).then(noop, noop);
|
|
93
|
+
|
|
94
|
+
expect(logger.error.mock.calls).toEqual([
|
|
95
|
+
[
|
|
96
|
+
`${logColors.boldMagenta('(1s 1.0ms)')} ${logColors.boldRed(
|
|
97
|
+
`SELECT * FROM "user" WHERE "user"."wrongColumn" = $1`,
|
|
98
|
+
)} ${logColors.boldYellow(`['value']`)} ${logColors.boldRed(
|
|
99
|
+
'Error: column user.wrongColumn does not exist',
|
|
100
|
+
)}`,
|
|
101
|
+
],
|
|
102
|
+
]);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should log in red in case of error without colors', async () => {
|
|
106
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
107
|
+
hrtime.mockReturnValueOnce([0, 0]);
|
|
108
|
+
hrtime.mockReturnValueOnce([1, 1000000]);
|
|
109
|
+
|
|
110
|
+
const logger = {
|
|
111
|
+
log: jest.fn(),
|
|
112
|
+
error: jest.fn(),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const db = createDb({ adapter, log: { colors: false }, logger });
|
|
116
|
+
|
|
117
|
+
await db('user').where({ wrongColumn: 'value' }).then(noop, noop);
|
|
118
|
+
|
|
119
|
+
expect(logger.error.mock.calls).toEqual([
|
|
120
|
+
[
|
|
121
|
+
`(1s 1.0ms) SELECT * FROM "user" WHERE "user"."wrongColumn" = $1 ['value'] Error: column user.wrongColumn does not exist`,
|
|
122
|
+
],
|
|
123
|
+
]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should log successful transaction', async () => {
|
|
127
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
128
|
+
hrtime.mockReturnValue([0, 0]);
|
|
129
|
+
hrtime.mockReturnValue([1, 1000000]);
|
|
130
|
+
|
|
131
|
+
const logger = {
|
|
132
|
+
log: jest.fn(),
|
|
133
|
+
error: jest.fn(),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const db = createDb({ adapter, log: { colors: false }, logger });
|
|
137
|
+
|
|
138
|
+
await db.transaction(async (q) => {
|
|
139
|
+
await db('user').transacting(q).insert(userData);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(logger.log.mock.calls).toEqual([
|
|
143
|
+
['(1s 1.0ms) BEGIN'],
|
|
144
|
+
[expect.stringContaining('INSERT INTO "user"')],
|
|
145
|
+
['(1s 1.0ms) COMMIT'],
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should log failed transaction', async () => {
|
|
150
|
+
const hrtime = jest.spyOn(process, 'hrtime');
|
|
151
|
+
hrtime.mockReturnValue([0, 0]);
|
|
152
|
+
hrtime.mockReturnValue([1, 1000000]);
|
|
153
|
+
|
|
154
|
+
const logger = {
|
|
155
|
+
log: jest.fn(),
|
|
156
|
+
error: jest.fn(),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const db = createDb({ adapter, log: { colors: false }, logger });
|
|
160
|
+
|
|
161
|
+
await expect(
|
|
162
|
+
db.transaction(async (q) => {
|
|
163
|
+
await db('user').transacting(q).insert({ name: 'name' });
|
|
164
|
+
}),
|
|
165
|
+
).rejects.toThrow();
|
|
166
|
+
|
|
167
|
+
expect(logger.log.mock.calls).toEqual([
|
|
168
|
+
['(1s 1.0ms) BEGIN'],
|
|
169
|
+
['(1s 1.0ms) ROLLBACK'],
|
|
170
|
+
]);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Query } from '../query';
|
|
2
|
+
import { Sql } from '../sql';
|
|
3
|
+
import { quote } from '../quote';
|
|
4
|
+
|
|
5
|
+
export type QueryLogObject = {
|
|
6
|
+
colors: boolean;
|
|
7
|
+
beforeQuery(q: Query, sql: Sql): unknown;
|
|
8
|
+
afterQuery(q: Query, sql: Sql, logData: unknown): void;
|
|
9
|
+
onError(error: Error, q: Query, sql: Sql, logData: unknown): void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type QueryLogger = {
|
|
13
|
+
log(message: string): void;
|
|
14
|
+
error(message: string): void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type QueryLogOptions = {
|
|
18
|
+
log?: boolean | Partial<QueryLogObject>;
|
|
19
|
+
logger?: QueryLogger;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const logColors = {
|
|
23
|
+
boldCyanBright: (message: string) =>
|
|
24
|
+
`\u001b[1m\u001b[96m${message}\u001b[39m\u001b[22m`,
|
|
25
|
+
|
|
26
|
+
boldBlue: (message: string) =>
|
|
27
|
+
`\u001b[1m\u001b[34m${message}\u001b[39m\u001b[22m`,
|
|
28
|
+
|
|
29
|
+
boldYellow: (message: string) =>
|
|
30
|
+
`\u001b[1m\u001b[33m${message}\u001b[39m\u001b[22m`,
|
|
31
|
+
|
|
32
|
+
boldMagenta: (message: string) =>
|
|
33
|
+
`\u001b[1m\u001b[33m${message}\u001b[39m\u001b[22m`,
|
|
34
|
+
|
|
35
|
+
boldRed: (message: string) =>
|
|
36
|
+
`\u001b[1m\u001b[31m${message}\u001b[39m\u001b[22m`,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const makeMessage = (
|
|
40
|
+
colors: boolean,
|
|
41
|
+
timeColor: (message: string) => string,
|
|
42
|
+
time: [number, number],
|
|
43
|
+
sqlColor: (message: string) => string,
|
|
44
|
+
sql: string,
|
|
45
|
+
valuesColor: (message: string) => string,
|
|
46
|
+
values: unknown[],
|
|
47
|
+
): string => {
|
|
48
|
+
const elapsed = process.hrtime(time);
|
|
49
|
+
const formattedTime = `(${elapsed[0] ? `${elapsed[0]}s ` : ''}${(
|
|
50
|
+
elapsed[1] / 1000000
|
|
51
|
+
).toFixed(1)}ms)`;
|
|
52
|
+
|
|
53
|
+
const result = `${colors ? timeColor(formattedTime) : formattedTime} ${
|
|
54
|
+
colors ? sqlColor(sql) : sql
|
|
55
|
+
}`;
|
|
56
|
+
|
|
57
|
+
if (!values.length) {
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const formattedValues = `[${values.map(quote).join(', ')}]`;
|
|
62
|
+
|
|
63
|
+
return `${result} ${colors ? valuesColor(formattedValues) : formattedValues}`;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const logParamToLogObject = (
|
|
67
|
+
logger: QueryLogger,
|
|
68
|
+
log: QueryLogOptions['log'],
|
|
69
|
+
): QueryLogObject | undefined => {
|
|
70
|
+
if (!log) return;
|
|
71
|
+
const logObject = Object.assign(
|
|
72
|
+
{
|
|
73
|
+
colors: true,
|
|
74
|
+
beforeQuery() {
|
|
75
|
+
return process.hrtime();
|
|
76
|
+
},
|
|
77
|
+
afterQuery(_, sql, time: [number, number]) {
|
|
78
|
+
logger.log(
|
|
79
|
+
makeMessage(
|
|
80
|
+
colors,
|
|
81
|
+
logColors.boldCyanBright,
|
|
82
|
+
time,
|
|
83
|
+
logColors.boldBlue,
|
|
84
|
+
sql.text,
|
|
85
|
+
logColors.boldYellow,
|
|
86
|
+
sql.values,
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
onError(error, _, sql, time: [number, number]) {
|
|
91
|
+
const message = `Error: ${error.message}`;
|
|
92
|
+
|
|
93
|
+
logger.error(
|
|
94
|
+
`${makeMessage(
|
|
95
|
+
colors,
|
|
96
|
+
logColors.boldMagenta,
|
|
97
|
+
time,
|
|
98
|
+
logColors.boldRed,
|
|
99
|
+
sql.text,
|
|
100
|
+
logColors.boldYellow,
|
|
101
|
+
sql.values,
|
|
102
|
+
)} ${colors ? logColors.boldRed(message) : message}`,
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
} as QueryLogObject,
|
|
106
|
+
log === true ? {} : log,
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const colors = logObject.colors;
|
|
110
|
+
|
|
111
|
+
return logObject;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export class QueryLog {
|
|
115
|
+
log<T extends Query>(this: T, log = true): T {
|
|
116
|
+
return this.clone()._log(log);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_log<T extends Query>(this: T, log = true): T {
|
|
120
|
+
this.query.log = logParamToLogObject(this.query.logger, log);
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
}
|