pqb 0.4.7 → 0.4.9
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 +8 -1
- package/dist/index.esm.js +36 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +36 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/columnType.test.ts +220 -0
- package/src/columnSchema/columnType.ts +8 -0
- package/src/columnSchema/dateTime.ts +11 -0
- package/src/db.ts +4 -1
- package/src/queryMethods/create.test.ts +43 -0
- package/src/queryMethods/create.ts +27 -5
- package/src/queryMethods/update.test.ts +18 -0
- package/src/queryMethods/update.ts +11 -1
package/package.json
CHANGED
|
@@ -125,4 +125,224 @@ describe('column base', () => {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
});
|
|
128
|
+
|
|
129
|
+
describe('as', () => {
|
|
130
|
+
const numberTimestamp = columnTypes
|
|
131
|
+
.timestamp()
|
|
132
|
+
.encode((input: number) => new Date(input))
|
|
133
|
+
.parse(Date.parse)
|
|
134
|
+
.as(columnTypes.integer());
|
|
135
|
+
|
|
136
|
+
const dateTimestamp = columnTypes
|
|
137
|
+
.timestamp()
|
|
138
|
+
.parse((input) => new Date(input));
|
|
139
|
+
|
|
140
|
+
const db = createDb({
|
|
141
|
+
adapter,
|
|
142
|
+
columnTypes: {
|
|
143
|
+
...columnTypes,
|
|
144
|
+
numberTimestamp: () => numberTimestamp,
|
|
145
|
+
dateTimestamp: () => dateTimestamp,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const UserWithCustomTimestamps = db('user', (t) => ({
|
|
150
|
+
id: t.serial().primaryKey(),
|
|
151
|
+
name: t.text(),
|
|
152
|
+
password: t.text(),
|
|
153
|
+
createdAt: t.numberTimestamp(),
|
|
154
|
+
updatedAt: t.dateTimestamp(),
|
|
155
|
+
}));
|
|
156
|
+
|
|
157
|
+
it('should accept only column of same type and input type', () => {
|
|
158
|
+
columnTypes
|
|
159
|
+
.timestamp()
|
|
160
|
+
.encode((input: number) => input.toString())
|
|
161
|
+
// @ts-expect-error should have both encode and parse with matching types
|
|
162
|
+
.as(columnTypes.integer());
|
|
163
|
+
|
|
164
|
+
// @ts-expect-error should have both encode and parse with matching types
|
|
165
|
+
columnTypes.timestamp().parse(Date.parse).as(columnTypes.integer());
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should return same column with overridden type', () => {
|
|
169
|
+
const timestamp = columnTypes
|
|
170
|
+
.timestamp()
|
|
171
|
+
.encode((input: number) => new Date(input))
|
|
172
|
+
.parse(Date.parse);
|
|
173
|
+
|
|
174
|
+
const column = timestamp.as(columnTypes.integer());
|
|
175
|
+
|
|
176
|
+
expect(column).toBe(timestamp);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should parse correctly', async () => {
|
|
180
|
+
const id = await User.get('id').create(userData);
|
|
181
|
+
|
|
182
|
+
const user = await UserWithCustomTimestamps.find(id);
|
|
183
|
+
|
|
184
|
+
expect(typeof user.createdAt).toBe('number');
|
|
185
|
+
expect(user.updatedAt).toBeInstanceOf(Date);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should encode columns when creating', () => {
|
|
189
|
+
const createdAt = Date.now();
|
|
190
|
+
const updatedAt = new Date();
|
|
191
|
+
|
|
192
|
+
const query = UserWithCustomTimestamps.create({
|
|
193
|
+
...userData,
|
|
194
|
+
createdAt,
|
|
195
|
+
updatedAt,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expectSql(
|
|
199
|
+
query.toSql(),
|
|
200
|
+
`
|
|
201
|
+
INSERT INTO "user"("name", "password", "createdAt", "updatedAt")
|
|
202
|
+
VALUES ($1, $2, $3, $4)
|
|
203
|
+
RETURNING *
|
|
204
|
+
`,
|
|
205
|
+
[userData.name, userData.password, new Date(createdAt), updatedAt],
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should encode columns when update', async () => {
|
|
210
|
+
const id = await User.get('id').create(userData);
|
|
211
|
+
const createdAt = Date.now();
|
|
212
|
+
const updatedAt = new Date();
|
|
213
|
+
|
|
214
|
+
const query = UserWithCustomTimestamps.find(id).update({
|
|
215
|
+
createdAt,
|
|
216
|
+
updatedAt,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
expectSql(
|
|
220
|
+
query.toSql(),
|
|
221
|
+
`
|
|
222
|
+
UPDATE "user"
|
|
223
|
+
SET "createdAt" = $1, "updatedAt" = $2
|
|
224
|
+
WHERE "user"."id" = $3
|
|
225
|
+
`,
|
|
226
|
+
[new Date(createdAt), updatedAt, id],
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('timestamp().asNumber()', () => {
|
|
232
|
+
it('should parse and encode timestamp as a number', async () => {
|
|
233
|
+
const UserWithNumberTimestamp = db('user', (t) => ({
|
|
234
|
+
id: t.serial().primaryKey(),
|
|
235
|
+
name: t.text(),
|
|
236
|
+
password: t.text(),
|
|
237
|
+
createdAt: t.timestamp().asNumber(),
|
|
238
|
+
updatedAt: t.timestamp().asNumber(),
|
|
239
|
+
}));
|
|
240
|
+
|
|
241
|
+
const now = Date.now();
|
|
242
|
+
|
|
243
|
+
const createQuery = UserWithNumberTimestamp.create({
|
|
244
|
+
...userData,
|
|
245
|
+
createdAt: now,
|
|
246
|
+
updatedAt: now,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
expectSql(
|
|
250
|
+
createQuery.toSql(),
|
|
251
|
+
`
|
|
252
|
+
INSERT INTO "user"("name", "password", "createdAt", "updatedAt")
|
|
253
|
+
VALUES ($1, $2, $3, $4)
|
|
254
|
+
RETURNING *
|
|
255
|
+
`,
|
|
256
|
+
[userData.name, userData.password, new Date(now), new Date(now)],
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
const { id } = await createQuery;
|
|
260
|
+
const user = await UserWithNumberTimestamp.select(
|
|
261
|
+
'createdAt',
|
|
262
|
+
'updatedAt',
|
|
263
|
+
).find(id);
|
|
264
|
+
|
|
265
|
+
assertType<typeof user, { createdAt: number; updatedAt: number }>();
|
|
266
|
+
|
|
267
|
+
expect(typeof user.createdAt).toBe('number');
|
|
268
|
+
expect(typeof user.updatedAt).toBe('number');
|
|
269
|
+
|
|
270
|
+
const updateQuery = UserWithNumberTimestamp.find(id).update({
|
|
271
|
+
createdAt: now,
|
|
272
|
+
updatedAt: now,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
expectSql(
|
|
276
|
+
updateQuery.toSql(),
|
|
277
|
+
`
|
|
278
|
+
UPDATE "user"
|
|
279
|
+
SET "createdAt" = $1, "updatedAt" = $2
|
|
280
|
+
WHERE "user"."id" = $3
|
|
281
|
+
`,
|
|
282
|
+
[new Date(now), new Date(now), id],
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
describe('timestamp().asDate()', () => {
|
|
288
|
+
it('should parse and encode timestamp as a number', async () => {
|
|
289
|
+
columnTypes
|
|
290
|
+
.text()
|
|
291
|
+
.encode((input: number) => input)
|
|
292
|
+
.parse((text) => parseInt(text))
|
|
293
|
+
.as(columnTypes.integer());
|
|
294
|
+
|
|
295
|
+
const UserWithNumberTimestamp = db('user', (t) => ({
|
|
296
|
+
id: t.serial().primaryKey(),
|
|
297
|
+
name: t.text(),
|
|
298
|
+
password: t.text(),
|
|
299
|
+
createdAt: columnTypes.timestamp().asDate(),
|
|
300
|
+
updatedAt: columnTypes.timestamp().asDate(),
|
|
301
|
+
}));
|
|
302
|
+
|
|
303
|
+
const now = new Date();
|
|
304
|
+
|
|
305
|
+
const createQuery = UserWithNumberTimestamp.create({
|
|
306
|
+
...userData,
|
|
307
|
+
createdAt: now,
|
|
308
|
+
updatedAt: now,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
expectSql(
|
|
312
|
+
createQuery.toSql(),
|
|
313
|
+
`
|
|
314
|
+
INSERT INTO "user"("name", "password", "createdAt", "updatedAt")
|
|
315
|
+
VALUES ($1, $2, $3, $4)
|
|
316
|
+
RETURNING *
|
|
317
|
+
`,
|
|
318
|
+
[userData.name, userData.password, new Date(now), new Date(now)],
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const { id } = await createQuery;
|
|
322
|
+
const user = await UserWithNumberTimestamp.select(
|
|
323
|
+
'createdAt',
|
|
324
|
+
'updatedAt',
|
|
325
|
+
).find(id);
|
|
326
|
+
|
|
327
|
+
assertType<typeof user, { createdAt: Date; updatedAt: Date }>();
|
|
328
|
+
|
|
329
|
+
expect(user.createdAt).toBeInstanceOf(Date);
|
|
330
|
+
expect(user.updatedAt).toBeInstanceOf(Date);
|
|
331
|
+
|
|
332
|
+
const updateQuery = UserWithNumberTimestamp.find(id).update({
|
|
333
|
+
createdAt: now,
|
|
334
|
+
updatedAt: now,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
expectSql(
|
|
338
|
+
updateQuery.toSql(),
|
|
339
|
+
`
|
|
340
|
+
UPDATE "user"
|
|
341
|
+
SET "createdAt" = $1, "updatedAt" = $2
|
|
342
|
+
WHERE "user"."id" = $3
|
|
343
|
+
`,
|
|
344
|
+
[now, now, id],
|
|
345
|
+
);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
128
348
|
});
|
|
@@ -46,6 +46,7 @@ export type ColumnData = {
|
|
|
46
46
|
compression?: string;
|
|
47
47
|
foreignKey?: ForeignKey<string, string[]>;
|
|
48
48
|
modifyQuery?: (q: Query) => void;
|
|
49
|
+
as?: ColumnType;
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
type ForeignKeyMatch = 'FULL' | 'PARTIAL' | 'SIMPLE';
|
|
@@ -221,6 +222,13 @@ export abstract class ColumnType<
|
|
|
221
222
|
return this as unknown as Omit<T, 'type'> & { type: Output };
|
|
222
223
|
}
|
|
223
224
|
|
|
225
|
+
as<
|
|
226
|
+
T extends ColumnType,
|
|
227
|
+
C extends ColumnType<T['type'], Operators, T['inputType']>,
|
|
228
|
+
>(this: T, column: C): C {
|
|
229
|
+
return addColumnData(this, 'as', column) as unknown as C;
|
|
230
|
+
}
|
|
231
|
+
|
|
224
232
|
toSQL() {
|
|
225
233
|
return this.dataType;
|
|
226
234
|
}
|
|
@@ -3,6 +3,7 @@ import { Operators } from '../columnsOperators';
|
|
|
3
3
|
import { joinTruthy } from '../utils';
|
|
4
4
|
import { dateTypeMethods } from './commonMethods';
|
|
5
5
|
import { assignMethodsToClass } from './utils';
|
|
6
|
+
import { IntegerColumn } from './number';
|
|
6
7
|
|
|
7
8
|
export type DateColumnData = ColumnData & {
|
|
8
9
|
min?: Date;
|
|
@@ -22,6 +23,16 @@ export abstract class DateBaseColumn extends ColumnType<
|
|
|
22
23
|
> {
|
|
23
24
|
data = {} as DateColumnData;
|
|
24
25
|
operators = Operators.date;
|
|
26
|
+
|
|
27
|
+
asNumber() {
|
|
28
|
+
return this.encode((input: number) => new Date(input)).parse(
|
|
29
|
+
Date.parse,
|
|
30
|
+
) as unknown as IntegerColumn;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
asDate<T extends ColumnType>(this: T) {
|
|
34
|
+
return this.parse((input) => new Date(input as string));
|
|
35
|
+
}
|
|
25
36
|
}
|
|
26
37
|
|
|
27
38
|
assignMethodsToClass(DateBaseColumn, dateTypeMethods);
|
package/src/db.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
ColumnTypesBase,
|
|
23
23
|
getColumnTypes,
|
|
24
24
|
SinglePrimaryKey,
|
|
25
|
+
ColumnType,
|
|
25
26
|
} from './columnSchema';
|
|
26
27
|
import { applyMixins, pushOrNewArray } from './utils';
|
|
27
28
|
import { StringKey } from './common';
|
|
@@ -93,6 +94,8 @@ export interface Db<
|
|
|
93
94
|
>;
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
export const anyShape = {} as Record<string, ColumnType>;
|
|
98
|
+
|
|
96
99
|
export class Db<
|
|
97
100
|
Table extends string | undefined = undefined,
|
|
98
101
|
Shape extends ColumnsShape = Record<string, never>,
|
|
@@ -107,7 +110,7 @@ export class Db<
|
|
|
107
110
|
public adapter: Adapter,
|
|
108
111
|
public queryBuilder: Db,
|
|
109
112
|
public table: Table = undefined as Table,
|
|
110
|
-
public shape: Shape =
|
|
113
|
+
public shape: Shape = anyShape as Shape,
|
|
111
114
|
public columnTypes: CT,
|
|
112
115
|
options: DbTableOptions,
|
|
113
116
|
) {
|
|
@@ -150,6 +150,24 @@ describe('create functions', () => {
|
|
|
150
150
|
['name', 'override'],
|
|
151
151
|
);
|
|
152
152
|
});
|
|
153
|
+
|
|
154
|
+
it('should strip unknown keys', () => {
|
|
155
|
+
const query = User.create({
|
|
156
|
+
name: 'name',
|
|
157
|
+
password: 'password',
|
|
158
|
+
unknown: 'should be stripped',
|
|
159
|
+
} as unknown as UserRecord);
|
|
160
|
+
|
|
161
|
+
expectSql(
|
|
162
|
+
query.toSql(),
|
|
163
|
+
`
|
|
164
|
+
INSERT INTO "user"("name", "password")
|
|
165
|
+
VALUES ($1, $2)
|
|
166
|
+
RETURNING *
|
|
167
|
+
`,
|
|
168
|
+
['name', 'password'],
|
|
169
|
+
);
|
|
170
|
+
});
|
|
153
171
|
});
|
|
154
172
|
|
|
155
173
|
describe('createMany', () => {
|
|
@@ -265,6 +283,31 @@ describe('create functions', () => {
|
|
|
265
283
|
|
|
266
284
|
expectQueryNotMutated(q);
|
|
267
285
|
});
|
|
286
|
+
|
|
287
|
+
it('should strip unknown keys', () => {
|
|
288
|
+
const query = User.createMany([
|
|
289
|
+
{
|
|
290
|
+
name: 'name',
|
|
291
|
+
password: 'password',
|
|
292
|
+
unknown: 'should be stripped',
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: 'name',
|
|
296
|
+
password: 'password',
|
|
297
|
+
unknown: 'should be stripped',
|
|
298
|
+
},
|
|
299
|
+
] as unknown as UserRecord[]);
|
|
300
|
+
|
|
301
|
+
expectSql(
|
|
302
|
+
query.toSql(),
|
|
303
|
+
`
|
|
304
|
+
INSERT INTO "user"("name", "password")
|
|
305
|
+
VALUES ($1, $2), ($3, $4)
|
|
306
|
+
RETURNING *
|
|
307
|
+
`,
|
|
308
|
+
['name', 'password', 'name', 'password'],
|
|
309
|
+
);
|
|
310
|
+
});
|
|
268
311
|
});
|
|
269
312
|
|
|
270
313
|
describe('createFrom', () => {
|
|
@@ -26,6 +26,8 @@ import { WhereArg } from './where';
|
|
|
26
26
|
import { parseResult, queryMethodByReturnType } from './then';
|
|
27
27
|
import { NotFoundError } from '../errors';
|
|
28
28
|
import { RawExpression } from '../common';
|
|
29
|
+
import { ColumnsShape } from '../columnSchema';
|
|
30
|
+
import { anyShape } from '../db';
|
|
29
31
|
|
|
30
32
|
export type CreateData<
|
|
31
33
|
T extends Query,
|
|
@@ -172,6 +174,8 @@ type CreateCtx = {
|
|
|
172
174
|
relations: Record<string, Relation>;
|
|
173
175
|
};
|
|
174
176
|
|
|
177
|
+
type Encoder = (input: unknown) => unknown;
|
|
178
|
+
|
|
175
179
|
const handleSelect = (q: Query) => {
|
|
176
180
|
const select = q.query.select?.[0];
|
|
177
181
|
const isCount =
|
|
@@ -191,7 +195,9 @@ const processCreateItem = (
|
|
|
191
195
|
rowIndex: number,
|
|
192
196
|
ctx: CreateCtx,
|
|
193
197
|
columns: string[],
|
|
198
|
+
encoders: Record<string, Encoder>,
|
|
194
199
|
columnsMap: Record<string, number>,
|
|
200
|
+
shape: ColumnsShape,
|
|
195
201
|
) => {
|
|
196
202
|
Object.keys(item).forEach((key) => {
|
|
197
203
|
if (ctx.relations[key]) {
|
|
@@ -222,8 +228,12 @@ const processCreateItem = (
|
|
|
222
228
|
item[key] as NestedInsertItem,
|
|
223
229
|
]);
|
|
224
230
|
}
|
|
225
|
-
} else if (
|
|
231
|
+
} else if (
|
|
232
|
+
columnsMap[key] === undefined &&
|
|
233
|
+
(shape[key] || shape === anyShape)
|
|
234
|
+
) {
|
|
226
235
|
columnsMap[key] = columns.length;
|
|
236
|
+
encoders[key] = shape[key]?.encodeFn as Encoder;
|
|
227
237
|
columns.push(key);
|
|
228
238
|
}
|
|
229
239
|
});
|
|
@@ -256,8 +266,19 @@ const getManyReturnType = (q: Query) => {
|
|
|
256
266
|
}
|
|
257
267
|
};
|
|
258
268
|
|
|
269
|
+
const mapColumnValues = (
|
|
270
|
+
columns: string[],
|
|
271
|
+
encoders: Record<string, Encoder>,
|
|
272
|
+
data: Record<string, unknown>,
|
|
273
|
+
) => {
|
|
274
|
+
return columns.map((key) =>
|
|
275
|
+
encoders[key] ? encoders[key](data[key]) : data[key],
|
|
276
|
+
);
|
|
277
|
+
};
|
|
278
|
+
|
|
259
279
|
const handleOneData = (q: Query, data: CreateData<Query>, ctx: CreateCtx) => {
|
|
260
280
|
const columns: string[] = [];
|
|
281
|
+
const encoders: Record<string, Encoder> = {};
|
|
261
282
|
const columnsMap: Record<string, number> = {};
|
|
262
283
|
const defaults = q.query.defaults;
|
|
263
284
|
|
|
@@ -265,9 +286,9 @@ const handleOneData = (q: Query, data: CreateData<Query>, ctx: CreateCtx) => {
|
|
|
265
286
|
data = { ...defaults, ...data };
|
|
266
287
|
}
|
|
267
288
|
|
|
268
|
-
processCreateItem(data, 0, ctx, columns, columnsMap);
|
|
289
|
+
processCreateItem(data, 0, ctx, columns, encoders, columnsMap, q.shape);
|
|
269
290
|
|
|
270
|
-
const values = [columns
|
|
291
|
+
const values = [mapColumnValues(columns, encoders, data)];
|
|
271
292
|
|
|
272
293
|
return { columns, values };
|
|
273
294
|
};
|
|
@@ -278,6 +299,7 @@ const handleManyData = (
|
|
|
278
299
|
ctx: CreateCtx,
|
|
279
300
|
) => {
|
|
280
301
|
const columns: string[] = [];
|
|
302
|
+
const encoders: Record<string, Encoder> = {};
|
|
281
303
|
const columnsMap: Record<string, number> = {};
|
|
282
304
|
const defaults = q.query.defaults;
|
|
283
305
|
|
|
@@ -286,13 +308,13 @@ const handleManyData = (
|
|
|
286
308
|
}
|
|
287
309
|
|
|
288
310
|
data.forEach((item, i) => {
|
|
289
|
-
processCreateItem(item, i, ctx, columns, columnsMap);
|
|
311
|
+
processCreateItem(item, i, ctx, columns, encoders, columnsMap, q.shape);
|
|
290
312
|
});
|
|
291
313
|
|
|
292
314
|
const values = Array(data.length);
|
|
293
315
|
|
|
294
316
|
data.forEach((item, i) => {
|
|
295
|
-
(values as unknown[][])[i] = columns
|
|
317
|
+
(values as unknown[][])[i] = mapColumnValues(columns, encoders, item);
|
|
296
318
|
});
|
|
297
319
|
|
|
298
320
|
return { columns, values };
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
expectSql,
|
|
6
6
|
User,
|
|
7
7
|
userData,
|
|
8
|
+
UserRecord,
|
|
8
9
|
useTestDatabase,
|
|
9
10
|
} from '../test-utils';
|
|
10
11
|
|
|
@@ -321,6 +322,23 @@ describe('update', () => {
|
|
|
321
322
|
});
|
|
322
323
|
});
|
|
323
324
|
|
|
325
|
+
it('should strip unknown keys', () => {
|
|
326
|
+
const query = User.find(1).update({
|
|
327
|
+
name: 'name',
|
|
328
|
+
unknown: 'should be stripped',
|
|
329
|
+
} as unknown as UserRecord);
|
|
330
|
+
|
|
331
|
+
expectSql(
|
|
332
|
+
query.toSql(),
|
|
333
|
+
`
|
|
334
|
+
UPDATE "user"
|
|
335
|
+
SET "name" = $1, "updatedAt" = now()
|
|
336
|
+
WHERE "user"."id" = $2
|
|
337
|
+
`,
|
|
338
|
+
['name', 1],
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
324
342
|
describe('increment', () => {
|
|
325
343
|
it('should not mutate query', () => {
|
|
326
344
|
const q = User.all();
|
|
@@ -16,6 +16,8 @@ import { EmptyObject, MaybeArray } from '../utils';
|
|
|
16
16
|
import { CreateData } from './create';
|
|
17
17
|
import { parseResult, queryMethodByReturnType } from './then';
|
|
18
18
|
import { UpdateQueryData } from '../sql';
|
|
19
|
+
import { ColumnsShape } from '../columnSchema';
|
|
20
|
+
import { anyShape } from '../db';
|
|
19
21
|
|
|
20
22
|
export type UpdateData<T extends Query> = {
|
|
21
23
|
[K in keyof T['type']]?: T['type'][K] | RawExpression;
|
|
@@ -174,7 +176,10 @@ export class Update {
|
|
|
174
176
|
const set: Record<string, unknown> = { ...data };
|
|
175
177
|
pushQueryValue(this, 'updateData', set);
|
|
176
178
|
|
|
177
|
-
const relations = this
|
|
179
|
+
const { relations, shape } = this as {
|
|
180
|
+
relations: Record<string, Relation>;
|
|
181
|
+
shape: ColumnsShape;
|
|
182
|
+
};
|
|
178
183
|
|
|
179
184
|
const prependRelations: Record<string, Record<string, unknown>> = {};
|
|
180
185
|
const appendRelations: Record<string, Record<string, unknown>> = {};
|
|
@@ -195,6 +200,11 @@ export class Update {
|
|
|
195
200
|
}
|
|
196
201
|
appendRelations[key] = data[key] as Record<string, unknown>;
|
|
197
202
|
}
|
|
203
|
+
} else if (!shape[key] && shape !== anyShape) {
|
|
204
|
+
delete set[key];
|
|
205
|
+
} else {
|
|
206
|
+
const encode = shape[key].encodeFn;
|
|
207
|
+
if (encode) set[key] = encode(set[key]);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
|