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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pqb",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Postgres query builder",
5
5
  "homepage": "https://porm.netlify.app/guide/query-builder.html",
6
6
  "repository": {
@@ -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: false;
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 = ColumnTypes> = (
178
+ export type DbOptions<CT extends ColumnTypesBase> = (
180
179
  | { adapter: Adapter }
181
180
  | Omit<AdapterOptions, 'log'>
182
181
  ) &
183
182
  QueryLogOptions & {
184
- columnTypes?: CT;
183
+ columnTypes: CT;
185
184
  };
186
185
 
187
- export const createDb = <CT extends ColumnTypesBase = ColumnTypes>({
186
+ export const createDb = <CT extends ColumnTypesBase>({
188
187
  log,
189
188
  logger,
190
- columnTypes: ct = columnTypes as unknown as 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 { QueryMethods } from './queryMethods/queryMethods';
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: PropertyKey[];
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 QueryThen<
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 'all'
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 false
134
- ? Omit<T, 'hasSelect' | 'result' | 'then'> & {
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 PropertyKey[]> = Omit<
292
- T,
293
- 'windows'
294
- > & { windows: W };
305
+ export type SetQueryWindows<T extends Query, W extends EmptyObject> = T & {
306
+ windows: W;
307
+ };
@@ -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, removeFromQuery } from '../queryDataUtils';
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'][number] | WindowArgDeclaration<T>;
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
- removeFromQuery(this, 'and');
28
- removeFromQuery(this, 'or');
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
- removeFromQuery(this, clear);
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 false
8
- ? SetQueryReturnsRowCount<T>
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
- q.select('name').from(User).toSql(),
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
- q.select('id').from(User, { only: true }).toSql(),
61
+ User.select('id').from(User, { only: true }).toSql(),
63
62
  'SELECT "user"."id" FROM ONLY "user"',
64
63
  );
65
64
  });
@@ -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);
@@ -11,6 +11,7 @@ export * from './insert';
11
11
  export * from './join';
12
12
  export * from './json';
13
13
  export * from './log';
14
+ export * from './merge';
14
15
  export * from './queryMethods';
15
16
  export * from './select';
16
17
  export * from './then';
@@ -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 false
140
- ? SetQueryReturnsRowCount<T>
141
- : T['returnType'] extends 'all'
142
- ? SetQueryReturnsOne<T>
143
- : T['returnType'] extends 'one'
144
- ? SetQueryReturnsOne<T>
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 false
148
- ? SetQueryReturnsRowCount<T>
149
- : T['returnType'] extends 'one' | 'oneOrThrow'
150
- ? SetQueryReturnsAll<T>
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 {
@@ -1,4 +1,9 @@
1
- import { AddQuerySelect, Query, SetQueryReturnsValueOptional } from '../query';
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.take
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