pqb 0.3.2 → 0.3.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.
- package/dist/index.d.ts +1229 -1307
- package/dist/index.esm.js +456 -403
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +458 -404
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/columnType.test.ts +2 -1
- package/src/db.test.ts +1 -1
- package/src/db.ts +16 -17
- package/src/query.ts +33 -20
- package/src/queryDataUtils.ts +0 -7
- package/src/queryMethods/aggregate.ts +2 -3
- package/src/queryMethods/clear.ts +3 -4
- package/src/queryMethods/delete.ts +3 -3
- package/src/queryMethods/from.test.ts +2 -3
- package/src/queryMethods/get.ts +0 -1
- package/src/queryMethods/index.ts +1 -0
- package/src/queryMethods/insert.ts +14 -13
- package/src/queryMethods/json.ts +7 -3
- package/src/queryMethods/merge.test.ts +471 -0
- package/src/queryMethods/merge.ts +67 -0
- package/src/queryMethods/queryMethods.test.ts +0 -19
- package/src/queryMethods/queryMethods.ts +8 -16
- package/src/queryMethods/select.test.ts +4 -0
- package/src/queryMethods/select.ts +4 -2
- package/src/queryMethods/then.ts +3 -3
- package/src/queryMethods/update.ts +13 -8
- package/src/sql/fromAndAs.ts +2 -3
- package/src/sql/select.ts +1 -2
- package/src/sql/toSql.ts +4 -3
- package/src/sql/types.ts +7 -3
- package/src/sql/window.ts +1 -1
- package/src/sql/with.ts +25 -20
- package/src/utils.ts +0 -18
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
useTestDatabase,
|
|
11
11
|
} from '../test-utils';
|
|
12
12
|
import { createDb } from '../db';
|
|
13
|
+
import { columnTypes } from './columnTypes';
|
|
13
14
|
|
|
14
15
|
describe('column base', () => {
|
|
15
16
|
useTestDatabase();
|
|
@@ -107,7 +108,7 @@ describe('column base', () => {
|
|
|
107
108
|
});
|
|
108
109
|
|
|
109
110
|
it('should return column data as returned from db if not set', async () => {
|
|
110
|
-
const db = createDb({ adapter });
|
|
111
|
+
const db = createDb({ adapter, columnTypes });
|
|
111
112
|
|
|
112
113
|
const UserWithPlainTimestamp = db('user', (t) => ({
|
|
113
114
|
createdAt: t.timestamp(),
|
package/src/db.test.ts
CHANGED
|
@@ -30,7 +30,7 @@ describe('db', () => {
|
|
|
30
30
|
it('should return date as string by default', async () => {
|
|
31
31
|
await User.insert(userData);
|
|
32
32
|
|
|
33
|
-
const db = createDb({ adapter });
|
|
33
|
+
const db = createDb({ adapter, columnTypes });
|
|
34
34
|
const table = db('user', (t) => ({
|
|
35
35
|
createdAt: t.timestamp(),
|
|
36
36
|
}));
|
package/src/db.ts
CHANGED
|
@@ -17,11 +17,9 @@ import { QueryData, SelectQueryData, Sql, ToSqlOptions } from './sql';
|
|
|
17
17
|
import { AdapterOptions, Adapter } from './adapter';
|
|
18
18
|
import {
|
|
19
19
|
ColumnsShape,
|
|
20
|
-
columnTypes,
|
|
21
20
|
ColumnShapeOutput,
|
|
22
21
|
TableSchema,
|
|
23
22
|
ColumnShapeInput,
|
|
24
|
-
ColumnTypes,
|
|
25
23
|
ColumnTypesBase,
|
|
26
24
|
getColumnTypes,
|
|
27
25
|
} from './columnSchema';
|
|
@@ -46,23 +44,19 @@ export interface Db<
|
|
|
46
44
|
): this;
|
|
47
45
|
|
|
48
46
|
adapter: Adapter;
|
|
47
|
+
columns: (keyof ColumnShapeOutput<Shape>)[];
|
|
48
|
+
|
|
49
49
|
queryBuilder: Db;
|
|
50
50
|
whereQueryBuilder: Query['whereQueryBuilder'];
|
|
51
|
+
onQueryBuilder: Query['onQueryBuilder'];
|
|
51
52
|
table: Table;
|
|
52
53
|
shape: Shape;
|
|
53
54
|
schema: TableSchema<Shape>;
|
|
54
55
|
type: ColumnShapeOutput<Shape>;
|
|
55
56
|
inputType: ColumnShapeInput<Shape>;
|
|
56
|
-
returnType: 'all';
|
|
57
|
-
then: ThenResult<
|
|
58
|
-
Pick<ColumnShapeOutput<Shape>, DefaultSelectColumns<Shape>[number]>[]
|
|
59
|
-
>;
|
|
60
57
|
query: QueryData;
|
|
61
|
-
columns: (keyof ColumnShapeOutput<Shape>)[];
|
|
62
|
-
defaultSelectColumns: DefaultSelectColumns<Shape>;
|
|
63
|
-
columnsParsers?: ColumnsParsers;
|
|
64
58
|
result: Pick<Shape, DefaultSelectColumns<Shape>[number]>;
|
|
65
|
-
hasSelect:
|
|
59
|
+
hasSelect: Query['hasSelect'];
|
|
66
60
|
hasWhere: boolean;
|
|
67
61
|
selectable: { [K in keyof Shape]: { as: K; column: Shape[K] } } & {
|
|
68
62
|
[K in keyof Shape as `${Table}.${StringKey<K>}`]: {
|
|
@@ -70,11 +64,17 @@ export interface Db<
|
|
|
70
64
|
column: Shape[K];
|
|
71
65
|
};
|
|
72
66
|
};
|
|
67
|
+
returnType: Query['returnType'];
|
|
68
|
+
then: ThenResult<
|
|
69
|
+
Pick<ColumnShapeOutput<Shape>, DefaultSelectColumns<Shape>[number]>[]
|
|
70
|
+
>;
|
|
73
71
|
tableAlias: undefined;
|
|
74
|
-
windows: PropertyKey[];
|
|
75
|
-
withData: Query['withData'];
|
|
76
72
|
joinedTables: Query['joinedTables'];
|
|
73
|
+
windows: Query['windows'];
|
|
74
|
+
defaultSelectColumns: DefaultSelectColumns<Shape>;
|
|
75
|
+
columnsParsers?: ColumnsParsers;
|
|
77
76
|
relations: Relations;
|
|
77
|
+
withData: Query['withData'];
|
|
78
78
|
[defaultsKey]: Record<
|
|
79
79
|
{
|
|
80
80
|
[K in keyof Shape]: Shape[K]['hasDefault'] extends true ? K : never;
|
|
@@ -105,7 +105,6 @@ export class Db<
|
|
|
105
105
|
this.query = {
|
|
106
106
|
adapter,
|
|
107
107
|
handleResult: handleResult,
|
|
108
|
-
returnType: 'all',
|
|
109
108
|
logger,
|
|
110
109
|
log: logParamToLogObject(logger, options.log),
|
|
111
110
|
} as QueryData;
|
|
@@ -176,18 +175,18 @@ type DbResult<CT extends ColumnTypesBase> = Db & {
|
|
|
176
175
|
close: Adapter['close'];
|
|
177
176
|
};
|
|
178
177
|
|
|
179
|
-
export type DbOptions<CT extends ColumnTypesBase
|
|
178
|
+
export type DbOptions<CT extends ColumnTypesBase> = (
|
|
180
179
|
| { adapter: Adapter }
|
|
181
180
|
| Omit<AdapterOptions, 'log'>
|
|
182
181
|
) &
|
|
183
182
|
QueryLogOptions & {
|
|
184
|
-
columnTypes
|
|
183
|
+
columnTypes: CT;
|
|
185
184
|
};
|
|
186
185
|
|
|
187
|
-
export const createDb = <CT extends ColumnTypesBase
|
|
186
|
+
export const createDb = <CT extends ColumnTypesBase>({
|
|
188
187
|
log,
|
|
189
188
|
logger,
|
|
190
|
-
columnTypes: ct
|
|
189
|
+
columnTypes: ct,
|
|
191
190
|
...options
|
|
192
191
|
}: DbOptions<CT>): DbResult<CT> => {
|
|
193
192
|
const adapter = 'adapter' in options ? options.adapter : new Adapter(options);
|
package/src/query.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
QueryMethods,
|
|
3
|
+
ThenResult,
|
|
4
|
+
ColumnInfo,
|
|
5
|
+
WhereQueryBuilder,
|
|
6
|
+
OnQueryBuilder,
|
|
7
|
+
GetArg,
|
|
8
|
+
getValueKey,
|
|
9
|
+
} from './queryMethods';
|
|
2
10
|
import { QueryData } from './sql';
|
|
3
11
|
import {
|
|
4
12
|
ColumnShapeOutput,
|
|
@@ -6,15 +14,10 @@ import {
|
|
|
6
14
|
ColumnType,
|
|
7
15
|
TableSchema,
|
|
8
16
|
} from './columnSchema';
|
|
9
|
-
import { Spread } from './utils';
|
|
17
|
+
import { EmptyObject, Spread } from './utils';
|
|
10
18
|
import { AliasOrTable, RawExpression, StringKey } from './common';
|
|
11
|
-
import { ThenResult } from './queryMethods/then';
|
|
12
19
|
import { Db } from './db';
|
|
13
|
-
import { ColumnInfo } from './queryMethods/columnInfo';
|
|
14
20
|
import { RelationQueryBase, RelationsBase } from './relations';
|
|
15
|
-
import { WhereQueryBuilder } from './queryMethods/where';
|
|
16
|
-
import { OnQueryBuilder } from './queryMethods/join';
|
|
17
|
-
import { GetArg, getValueKey } from './queryMethods/get';
|
|
18
21
|
|
|
19
22
|
export type ColumnParser = (input: unknown) => unknown;
|
|
20
23
|
export type ColumnsParsers = Record<string | getValueKey, ColumnParser>;
|
|
@@ -65,7 +68,7 @@ export type Query = QueryMethods & {
|
|
|
65
68
|
then: ThenResult<unknown>;
|
|
66
69
|
tableAlias: string | undefined;
|
|
67
70
|
joinedTables: Record<string, Pick<Query, 'result' | 'tableAlias' | 'table'>>;
|
|
68
|
-
windows:
|
|
71
|
+
windows: EmptyObject;
|
|
69
72
|
defaultSelectColumns: string[];
|
|
70
73
|
columnsParsers?: ColumnsParsers;
|
|
71
74
|
relations: RelationsBase;
|
|
@@ -93,15 +96,26 @@ export type QueryReturnType =
|
|
|
93
96
|
| 'rowCount'
|
|
94
97
|
| 'void';
|
|
95
98
|
|
|
99
|
+
export const queryTypeWithLimitOne = {
|
|
100
|
+
one: true,
|
|
101
|
+
oneOrThrow: true,
|
|
102
|
+
} as Record<QueryReturnType, true | undefined>;
|
|
103
|
+
|
|
96
104
|
export type JoinedTablesBase = Record<
|
|
97
105
|
string,
|
|
98
106
|
Pick<Query, 'result' | 'tableAlias' | 'table'>
|
|
99
107
|
>;
|
|
100
108
|
|
|
101
|
-
type
|
|
109
|
+
export type QueryReturnsAll<T extends QueryReturnType> = (
|
|
110
|
+
QueryReturnType extends T ? 'all' : T
|
|
111
|
+
) extends 'all'
|
|
112
|
+
? true
|
|
113
|
+
: false;
|
|
114
|
+
|
|
115
|
+
export type QueryThen<
|
|
102
116
|
ReturnType extends QueryReturnType,
|
|
103
117
|
Result extends ColumnsShape,
|
|
104
|
-
> = ReturnType extends
|
|
118
|
+
> = QueryReturnsAll<ReturnType> extends true
|
|
105
119
|
? ThenResult<ColumnShapeOutput<Result>[]>
|
|
106
120
|
: ReturnType extends 'one'
|
|
107
121
|
? ThenResult<ColumnShapeOutput<Result> | undefined>
|
|
@@ -130,15 +144,15 @@ type QueryThen<
|
|
|
130
144
|
export type AddQuerySelect<
|
|
131
145
|
T extends Pick<Query, 'hasSelect' | 'result' | 'then' | 'returnType'>,
|
|
132
146
|
Result extends ColumnsShape,
|
|
133
|
-
> = T['hasSelect'] extends
|
|
134
|
-
? Omit<T, '
|
|
147
|
+
> = T['hasSelect'] extends true
|
|
148
|
+
? Omit<T, 'result' | 'then'> & {
|
|
149
|
+
result: Spread<[T['result'], Result]>;
|
|
150
|
+
then: QueryThen<T['returnType'], Spread<[T['result'], Result]>>;
|
|
151
|
+
}
|
|
152
|
+
: Omit<T, 'result' | 'then'> & {
|
|
135
153
|
hasSelect: true;
|
|
136
154
|
result: Result;
|
|
137
155
|
then: QueryThen<T['returnType'], Result>;
|
|
138
|
-
}
|
|
139
|
-
: Omit<T, 'result' | 'then'> & {
|
|
140
|
-
result: Spread<[T['result'], Result]>;
|
|
141
|
-
then: QueryThen<T['returnType'], Spread<[T['result'], Result]>>;
|
|
142
156
|
};
|
|
143
157
|
|
|
144
158
|
export type QuerySelectAll<T extends Query> = Omit<
|
|
@@ -288,7 +302,6 @@ export type AddQueryWith<
|
|
|
288
302
|
With extends WithDataItem,
|
|
289
303
|
> = SetQueryWith<T, Spread<[T['withData'], { [K in With['table']]: With }]>>;
|
|
290
304
|
|
|
291
|
-
export type SetQueryWindows<T extends Query, W extends
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
> & { windows: W };
|
|
305
|
+
export type SetQueryWindows<T extends Query, W extends EmptyObject> = T & {
|
|
306
|
+
windows: W;
|
|
307
|
+
};
|
package/src/queryDataUtils.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import { Query } from './query';
|
|
2
1
|
import { QueryData } from './sql';
|
|
3
2
|
import { pushOrNewArrayToObject } from './utils';
|
|
4
3
|
|
|
5
|
-
// TODO: remove
|
|
6
|
-
export const removeFromQuery = <T extends Query>(q: T, key: string): T => {
|
|
7
|
-
if (q.query) delete q.query[key as keyof typeof q.query];
|
|
8
|
-
return q;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
4
|
export const pushQueryArray = <T extends { query: QueryData }>(
|
|
12
5
|
q: T,
|
|
13
6
|
key: string,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
StringExpression,
|
|
8
8
|
} from '../common';
|
|
9
9
|
import { AddQuerySelect, Query, SetQueryReturnsValue } from '../query';
|
|
10
|
-
import { pushQueryValue
|
|
10
|
+
import { pushQueryValue } from '../queryDataUtils';
|
|
11
11
|
import {
|
|
12
12
|
ArrayColumn,
|
|
13
13
|
BooleanColumn,
|
|
@@ -42,7 +42,7 @@ export type AggregateOptions<
|
|
|
42
42
|
filter?: WhereArg<T>;
|
|
43
43
|
filterOr?: WhereArg<T>[];
|
|
44
44
|
withinGroup?: boolean;
|
|
45
|
-
over?: T['windows']
|
|
45
|
+
over?: keyof T['windows'] | WindowArgDeclaration<T>;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
// 1 in the name means only methods which takes 1 argument are listed here
|
|
@@ -130,7 +130,6 @@ const get = <T extends Query, Column extends ColumnType>(
|
|
|
130
130
|
q: Query,
|
|
131
131
|
): SetQueryReturnsValue<T, Column> => {
|
|
132
132
|
q.query.returnType = 'valueOrThrow';
|
|
133
|
-
removeFromQuery(q, 'take');
|
|
134
133
|
|
|
135
134
|
const select = q.query.select as SelectItem[];
|
|
136
135
|
if (select.length > 1) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Query } from '../query';
|
|
2
|
-
import { removeFromQuery } from '../queryDataUtils';
|
|
3
2
|
import { isRaw } from '../common';
|
|
4
3
|
|
|
5
4
|
export type ClearStatement =
|
|
@@ -24,8 +23,8 @@ export class Clear {
|
|
|
24
23
|
_clear<T extends Query>(this: T, ...clears: ClearStatement[]): T {
|
|
25
24
|
clears.forEach((clear) => {
|
|
26
25
|
if (clear === 'where') {
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
delete this.query.and;
|
|
27
|
+
delete this.query.or;
|
|
29
28
|
} else if (clear === 'counters') {
|
|
30
29
|
if ('type' in this.query && this.query.type === 'update') {
|
|
31
30
|
this.query.updateData = this.query.updateData.filter((item) => {
|
|
@@ -50,7 +49,7 @@ export class Clear {
|
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
} else {
|
|
53
|
-
|
|
52
|
+
delete (this.query as Record<string, unknown>)[clear];
|
|
54
53
|
}
|
|
55
54
|
});
|
|
56
55
|
return this;
|
|
@@ -4,9 +4,9 @@ type DeleteArgs<T extends Query> = T['hasWhere'] extends true
|
|
|
4
4
|
? [forceAll?: boolean]
|
|
5
5
|
: [true];
|
|
6
6
|
|
|
7
|
-
type DeleteResult<T extends Query> = T['hasSelect'] extends
|
|
8
|
-
?
|
|
9
|
-
: T
|
|
7
|
+
type DeleteResult<T extends Query> = T['hasSelect'] extends true
|
|
8
|
+
? T
|
|
9
|
+
: SetQueryReturnsRowCount<T>;
|
|
10
10
|
|
|
11
11
|
const del = <T extends Query>(
|
|
12
12
|
self: T,
|
|
@@ -50,16 +50,15 @@ describe('from', () => {
|
|
|
50
50
|
it('should not insert sub query and alias if provided query is simple', () => {
|
|
51
51
|
const q = User.all();
|
|
52
52
|
expectSql(
|
|
53
|
-
|
|
53
|
+
User.select('name').from(User).toSql(),
|
|
54
54
|
'SELECT "user"."name" FROM "user"',
|
|
55
55
|
);
|
|
56
56
|
expectQueryNotMutated(q);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
it('should add ONLY keyword when `only` parameter is provided', () => {
|
|
60
|
-
const q = User.all();
|
|
61
60
|
expectSql(
|
|
62
|
-
|
|
61
|
+
User.select('id').from(User, { only: true }).toSql(),
|
|
63
62
|
'SELECT "user"."id" FROM ONLY "user"',
|
|
64
63
|
);
|
|
65
64
|
});
|
package/src/queryMethods/get.ts
CHANGED
|
@@ -39,7 +39,6 @@ const _get = <
|
|
|
39
39
|
arg: Arg,
|
|
40
40
|
): R extends 'value' ? GetOptionalResult<T, Arg> : GetResult<T, Arg> => {
|
|
41
41
|
q.query.returnType = returnType;
|
|
42
|
-
q.query.take = true;
|
|
43
42
|
|
|
44
43
|
if (typeof arg === 'object' && isRaw(arg)) {
|
|
45
44
|
addParserForRawExpression(q, getValueKey, arg);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultsKey,
|
|
3
3
|
Query,
|
|
4
|
+
QueryReturnsAll,
|
|
4
5
|
QueryReturnType,
|
|
5
6
|
SetQueryReturnsAll,
|
|
6
7
|
SetQueryReturnsOne,
|
|
@@ -136,19 +137,19 @@ type InsertHasManyData<
|
|
|
136
137
|
|
|
137
138
|
type InsertRawData = { columns: string[]; values: RawExpression };
|
|
138
139
|
|
|
139
|
-
type InsertOneResult<T extends Query> = T['hasSelect'] extends
|
|
140
|
-
?
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
: T
|
|
140
|
+
type InsertOneResult<T extends Query> = T['hasSelect'] extends true
|
|
141
|
+
? QueryReturnsAll<T['returnType']> extends true
|
|
142
|
+
? SetQueryReturnsOne<T>
|
|
143
|
+
: T['returnType'] extends 'one'
|
|
144
|
+
? SetQueryReturnsOne<T>
|
|
145
|
+
: T
|
|
146
|
+
: SetQueryReturnsRowCount<T>;
|
|
146
147
|
|
|
147
|
-
type InsertManyResult<T extends Query> = T['hasSelect'] extends
|
|
148
|
-
?
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
: T
|
|
148
|
+
type InsertManyResult<T extends Query> = T['hasSelect'] extends true
|
|
149
|
+
? T['returnType'] extends 'one' | 'oneOrThrow'
|
|
150
|
+
? SetQueryReturnsAll<T>
|
|
151
|
+
: T
|
|
152
|
+
: SetQueryReturnsRowCount<T>;
|
|
152
153
|
|
|
153
154
|
type OnConflictArg<T extends Query> =
|
|
154
155
|
| keyof T['shape']
|
|
@@ -223,7 +224,7 @@ const createInsertCtx = (q: Query): InsertCtx => ({
|
|
|
223
224
|
});
|
|
224
225
|
|
|
225
226
|
const getInsertSingleReturnType = (q: Query) => {
|
|
226
|
-
const { select, returnType } = q.query;
|
|
227
|
+
const { select, returnType = 'all' } = q.query;
|
|
227
228
|
if (select) {
|
|
228
229
|
return returnType === 'all' ? 'one' : returnType;
|
|
229
230
|
} else {
|
package/src/queryMethods/json.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AddQuerySelect,
|
|
3
|
+
Query,
|
|
4
|
+
queryTypeWithLimitOne,
|
|
5
|
+
SetQueryReturnsValueOptional,
|
|
6
|
+
} from '../query';
|
|
2
7
|
import { pushQueryValue } from '../queryDataUtils';
|
|
3
8
|
import { ColumnType, StringColumn } from '../columnSchema';
|
|
4
9
|
import { JsonItem } from '../sql';
|
|
@@ -51,12 +56,11 @@ export class Json {
|
|
|
51
56
|
const q = this._wrap(this.__model.clone()) as T;
|
|
52
57
|
q._getOptional(
|
|
53
58
|
raw<StringColumn>(
|
|
54
|
-
this.query.
|
|
59
|
+
queryTypeWithLimitOne[this.query.returnType]
|
|
55
60
|
? `row_to_json("t".*)`
|
|
56
61
|
: `COALESCE(json_agg(row_to_json("t".*)), '[]')`,
|
|
57
62
|
),
|
|
58
63
|
);
|
|
59
|
-
delete q.query.take;
|
|
60
64
|
return q as unknown as SetQueryReturnsValueOptional<T, StringColumn>;
|
|
61
65
|
}
|
|
62
66
|
|