kysely-mapper
Version:
Flexible Kysely-based utility for mapping between tables and objects
335 lines • 16.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const kysely_1 = require("kysely");
const test_setup_1 = require("./utils/test-setup");
const test_mappers_1 = require("./utils/test-mappers");
const test_objects_1 = require("./utils/test-objects");
const test_utils_1 = require("./utils/test-utils");
let db;
let userMapperReturningDefault;
let userMapperReturningNothing;
let userMapperReturningID;
let userMapperReturningIDAndHandleAsH;
let userMapperReturningAll;
beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
db = yield (0, test_setup_1.createDB)();
userMapperReturningDefault = (0, test_mappers_1.createUserMapperReturningDefault)(db);
userMapperReturningNothing = (0, test_mappers_1.createUserMapperReturningNothing)(db);
userMapperReturningID = (0, test_mappers_1.createUserMapperReturningID)(db);
userMapperReturningIDAndHandleAsH =
(0, test_mappers_1.createUserMapperReturningIDAndHandleAsH)(db);
userMapperReturningAll = (0, test_mappers_1.createUserMapperReturningAll)(db);
}));
beforeEach(() => (0, test_setup_1.resetDB)(db));
afterAll(() => (0, test_setup_1.destroyDB)(db));
describe('general update', () => {
it('updates nothing returning zero update count', () => __awaiter(void 0, void 0, void 0, function* () {
const updateValues = { email: 'new.email@xyz.pdq' };
const success = yield userMapperReturningAll
.update({ id: 1 })
.run(updateValues);
expect(success).toBe(false);
const updateCount = yield userMapperReturningAll
.update({ id: 1 })
.returnCount(updateValues);
expect(updateCount).toEqual(0);
const updates = yield userMapperReturningID
.update({ id: 1 })
.returnAll(updateValues);
expect(updates.length).toEqual(0);
const update = yield userMapperReturningID
.update({ id: 1 })
.returnOne(updateValues);
expect(update).toBeNull();
}));
it('updates something returning non-zero update count', () => __awaiter(void 0, void 0, void 0, function* () {
const updateValues = { email: 'new.email@xyz.pdq' };
const insertReturn0 = yield userMapperReturningID
.insert()
.returnOne(test_objects_1.USERS[0]);
yield userMapperReturningID.insert().run(test_objects_1.USERS[1]);
yield userMapperReturningID.insert().run(test_objects_1.USERS[2]);
const updateCount1 = yield userMapperReturningAll
.update({ id: insertReturn0.id })
.returnCount(updateValues);
expect(updateCount1).toEqual(1);
const readUser1 = yield userMapperReturningID
.select('id', '=', insertReturn0.id)
.returnOne();
expect(readUser1 === null || readUser1 === void 0 ? void 0 : readUser1.email).toEqual(updateValues.email);
const updateCount2 = yield userMapperReturningAll
.update({ name: 'Sue' })
.returnCount(updateValues);
expect(updateCount2).toEqual(2);
const readUsers = yield userMapperReturningID
.select('name', '=', 'Sue')
.returnAll();
expect(readUsers.length).toEqual(2);
expect(readUsers[0].email).toEqual(updateValues.email);
expect(readUsers[1].email).toEqual(updateValues.email);
const updates = yield userMapperReturningID.update().returnAll({
name: 'Every User 1',
});
expect(updates).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]);
const update = yield userMapperReturningID
.update({ id: readUsers[0].id })
.returnOne({
name: 'Every User 2',
});
expect(update).toEqual({ id: 1 });
const readUser2 = yield userMapperReturningID
.select('id', '=', 1)
.returnOne();
expect(readUser2 === null || readUser2 === void 0 ? void 0 : readUser2.name).toEqual('Every User 2');
const updateCount = yield userMapperReturningID.update().returnCount({
name: 'Every User 3',
});
expect(updateCount).toEqual(3);
const success = yield userMapperReturningID.update().run({
name: 'Every User 4',
});
expect(success).toBe(true);
}));
it('updates returning configured return columns', () => __awaiter(void 0, void 0, void 0, function* () {
yield userMapperReturningID.insert().run(test_objects_1.USERS[0]);
const insertReturn = yield userMapperReturningID
.insert()
.returnOne(test_objects_1.USERS[1]);
yield userMapperReturningID.insert().run(test_objects_1.USERS[2]);
// Verify that update performs the correct change on the correct row.
const updateValues1 = { email: 'new.email@xyz.pdq' };
const updateReturns1 = yield userMapperReturningID
.update({ id: insertReturn.id })
.returnAll(updateValues1);
expect(updateReturns1).toEqual([{ id: insertReturn.id }]);
let readUser = yield userMapperReturningID
.select('id', '=', insertReturn.id)
.returnOne();
expect(readUser === null || readUser === void 0 ? void 0 : readUser.email).toEqual(updateValues1.email);
// Verify a different change on the same row, returning multiple columns.
const updateValues2 = { name: 'Sue' };
const updateReturns2 = yield userMapperReturningIDAndHandleAsH
.update({ email: updateValues1.email })
.returnAll(updateValues2);
updateReturns2[0].id; // ensure key is accessible
updateReturns2[0].h; // ensure key is accessible
expect(updateReturns2).toEqual([
{
id: insertReturn.id,
h: test_objects_1.USERS[1].handle,
},
]);
readUser = yield userMapperReturningID
.select('id', '=', insertReturn.id)
.returnOne();
expect(readUser === null || readUser === void 0 ? void 0 : readUser.name).toEqual(updateValues2.name);
// Verify that update changes all required rows.
const updateValues3 = { name: 'Replacement Sue' };
const updateReturns3 = yield userMapperReturningIDAndHandleAsH
.update({ name: 'Sue' })
.returnAll(updateValues3);
expect(updateReturns3.length).toEqual(3);
expect(updateReturns3[0].h).toEqual(test_objects_1.USERS[0].handle);
expect(updateReturns3[1].h).toEqual(test_objects_1.USERS[1].handle);
expect(updateReturns3[2].h).toEqual(test_objects_1.USERS[2].handle);
const readUsers = yield userMapperReturningID
.select('name', '=', updateValues3.name)
.returnAll();
expect(readUsers.length).toEqual(3);
(0, test_utils_1.ignore)('check return types', () => {
// @ts-expect-error - check return types
updateReturns2[0].title;
// @ts-expect-error - check return types
updateReturns2[0].userId;
});
}));
it('update returns void when defaulting to no return columns', () => __awaiter(void 0, void 0, void 0, function* () {
yield userMapperReturningID.insert().run(test_objects_1.USERS);
const updates = yield userMapperReturningDefault
.update({ name: 'Sue' })
.returnAll({ email: 'new.email@xyz.pdq' });
expect(updates).toBeUndefined();
const readUsers = yield userMapperReturningID
.select({
email: 'new.email@xyz.pdq',
})
.returnAll();
expect(readUsers.length).toEqual(2);
}));
it('update returns void when explicitly no return columns', () => __awaiter(void 0, void 0, void 0, function* () {
yield userMapperReturningID.insert().run(test_objects_1.USERS);
const updates = yield userMapperReturningNothing
.update({ name: 'Sue' })
.returnAll({ email: 'new.email@xyz.pdq' });
expect(updates).toBeUndefined();
const readUsers = yield userMapperReturningID
.select({
email: 'new.email@xyz.pdq',
})
.returnAll();
expect(readUsers.length).toEqual(2);
const update = yield userMapperReturningNothing
.update({ name: 'Sue' })
.returnOne({ email: 'new2.email@xyz.pdq' });
expect(update).toBeUndefined();
const readUser = yield userMapperReturningID
.select({
email: 'new2.email@xyz.pdq',
})
.returnOne();
expect(readUser.id).toEqual(1);
(0, test_utils_1.ignore)('type errors', () => {
// @ts-expect-error - check return types
updates[0].id;
// @ts-expect-error - check return types
update.id;
});
}));
it('updates configured to return all columns', () => __awaiter(void 0, void 0, void 0, function* () {
const insertReturns = yield userMapperReturningID.insert().returnAll(test_objects_1.USERS);
const updateValues1 = { email: 'new.email@xyz.pdq' };
const updateReturns = yield userMapperReturningAll
.update({ name: 'Sue' })
.returnAll(updateValues1);
const expectedUsers = [
Object.assign({}, test_objects_1.USERS[0], updateValues1, { id: insertReturns[0].id }),
Object.assign({}, test_objects_1.USERS[2], updateValues1, { id: insertReturns[2].id }),
];
expect(updateReturns).toEqual(expectedUsers);
// Ensure that the returned value can be accessed as a row.
((_) => { })(updateReturns[0].name);
((_) => { })(updateReturns[0].email);
const updateValues2 = { email: 'another.email@xyz.pdq' };
const updateReturn = yield userMapperReturningAll
.update({ name: 'Sue' })
.returnOne(updateValues2);
const expectedUser = Object.assign({}, test_objects_1.USERS[0], updateValues2, {
id: insertReturns[0].id,
});
expect(updateReturn).toEqual(expectedUser);
// Ensure that the returned value can be accessed as a row.
((_) => { })(updateReturn.name);
((_) => { })(updateReturn.email);
}));
it('updates all rows when no filter is given', () => __awaiter(void 0, void 0, void 0, function* () {
const insertReturns = yield userMapperReturningID.insert().returnAll(test_objects_1.USERS);
const updateValues = { email: 'new.email@xyz.pdq' };
const updateReturns = yield userMapperReturningIDAndHandleAsH
.update()
.returnAll(updateValues);
const expectedUsers = test_objects_1.USERS.map((user, i) => ({
id: insertReturns[i].id,
h: user.handle,
}));
expect(updateReturns).toEqual(expectedUsers);
const readUsers = yield userMapperReturningID.select().returnAll();
expect(readUsers.length).toEqual(3);
for (const user of readUsers) {
expect(user.email).toEqual(updateValues.email);
}
}));
it('updates rows indicated by a binary operator', () => __awaiter(void 0, void 0, void 0, function* () {
const insertReturns = yield userMapperReturningID.insert().returnAll(test_objects_1.USERS);
const updateValues = { email: 'new.email@xyz.pdq' };
const updateCount = yield userMapperReturningAll
.update('id', '>', insertReturns[0].id)
.returnCount(updateValues);
expect(updateCount).toEqual(2);
const readUsers = yield userMapperReturningID
.select('id', '>', insertReturns[0].id)
.returnAll();
expect(readUsers.length).toEqual(2);
for (const user of readUsers) {
expect(user.email).toEqual(updateValues.email);
}
}));
it('updates rows indicated by a kysely expression', () => __awaiter(void 0, void 0, void 0, function* () {
const insertReturns = yield userMapperReturningID.insert().returnAll(test_objects_1.USERS);
const updateValues = { email: 'new.email@xyz.pdq' };
const updateCount = yield userMapperReturningDefault
.update((0, kysely_1.sql) `id > ${insertReturns[0].id}`)
.returnCount(updateValues);
expect(updateCount).toEqual(BigInt(2));
const readUsers = yield userMapperReturningID
.select('id', '>', insertReturns[0].id)
.returnAll();
expect(readUsers.length).toEqual(2);
for (const user of readUsers) {
expect(user.email).toEqual(updateValues.email);
}
}));
it('updates rows indicated by a where expression filter', () => __awaiter(void 0, void 0, void 0, function* () {
const insertReturns = yield userMapperReturningID.insert().returnAll(test_objects_1.USERS);
const updateValues1 = { email: 'foo@xyz.pdq' };
const updateCount = yield userMapperReturningAll
.update(({ or, cmpr }) => or([
cmpr('id', '=', insertReturns[0].id),
cmpr('id', '=', insertReturns[2].id),
]))
.returnCount(updateValues1);
expect(updateCount).toEqual(2);
const updateValues2 = { email: 'bar@xyz.pdq' };
const updateReturns = yield userMapperReturningID
.update(({ or, cmpr }) => or([
cmpr('id', '=', insertReturns[0].id),
cmpr('id', '=', insertReturns[2].id),
]))
.returnAll(updateValues2);
expect(updateReturns).toEqual([
{ id: insertReturns[0].id },
{ id: insertReturns[2].id },
]);
}));
(0, test_utils_1.ignore)('detects update type errors', () => __awaiter(void 0, void 0, void 0, function* () {
userMapperReturningID.update(
// @ts-expect-error - table must have all filter fields
{ notThere: 'xyz' });
// @ts-expect-error - table must have all filter fields
userMapperReturningID.update('notThere', '=', 'foo');
userMapperReturningID.update(({ or, cmpr }) =>
// @ts-expect-error - only table columns are accessible via anyOf()
or([cmpr('notThere', '=', 'xyz'), cmpr('alsoNotThere', '=', 'Sue')]));
// @ts-expect-error - ID filter must have correct type
userMapperReturningID.update('str');
// @ts-expect-error - ID filter must have correct type
userMapperReturningID.update(['str']);
// @ts-expect-error - ID filter not allowed when when no ID column
userMapperReturningNothing.update(1);
// @ts-expect-error - ID filter not allowed when when no ID column
userMapperReturningNothing.update([1]);
userMapperReturningID.update({ id: 32 }).returnAll(
// @ts-expect-error - update must only have table columns
{ notThere: 'xyz@pdq.xyz' });
// @ts-expect-error - only requested columns are accessible
// prettier-ignore
(yield userMapperReturningID.update({ id: 32 }).returnAll(test_objects_1.USERS[0]))[0].name;
userMapperReturningID.update({ id: 32 }).returnOne(
// @ts-expect-error - update must only have table columns
{ notThere: 'xyz@pdq.xyz' });
// @ts-expect-error - only requested columns are accessible
// prettier-ignore
(yield userMapperReturningID.update({ id: 32 }).returnOne(test_objects_1.USERS[0]))[0].name;
userMapperReturningID.update({ id: 32 }).returnCount(
// @ts-expect-error - update must only have table columns
{ notThere: 'xyz@pdq.xyz' });
// @ts-expect-error - only requested columns are accessible
// prettier-ignore
(yield userMapperReturningID.update({ id: 32 }).returnCount(test_objects_1.USERS[0]))[0].name;
userMapperReturningID.update({ id: 32 }).run(
// @ts-expect-error - update must only have table columns
{ notThere: 'xyz@pdq.xyz' });
// @ts-expect-error - only requested columns are accessible
// prettier-ignore
(yield userMapperReturningID.update({ id: 32 }).run(test_objects_1.USERS[0]))[0].name;
}));
});
//# sourceMappingURL=update-general.test.js.map