Skip to content

Commit

Permalink
Merge pull request #70 from UN-OCHA/HPC-8149
Browse files Browse the repository at this point in the history
🐛 HPC-8149: Don't include deleted data by default
  • Loading branch information
Pl217 authored Dec 6, 2021
2 parents 5b27e21 + d16f9d9 commit f979cec
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@unocha/hpc-api-core",
"version": "1.1.2",
"version": "1.1.3",
"description": "Core libraries supporting HPC.Tools API Backend",
"license": "Apache-2.0",
"private": false,
Expand Down
8 changes: 6 additions & 2 deletions src/db/util/id-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {
FieldDefinition,
InstanceDataOf,
} from './model-definition';
import { defineSequelizeModel, FieldsWithSequelize } from './sequelize-model';
import {
AdditionalFindArgsForSequelizeTables,
defineSequelizeModel,
FieldsWithSequelize,
} from './sequelize-model';
import { Op } from './conditions';

/**
Expand All @@ -32,7 +36,7 @@ type IdOf<
export interface ModelWithId<
F extends FieldDefinition,
IDField extends null | keyof F['generated']
> extends Model<F> {
> extends Model<F, AdditionalFindArgsForSequelizeTables> {
readonly get: (id: IdOf<F, IDField>) => Promise<null | InstanceDataOf<F>>;
readonly getAll: (
id: Iterable<IdOf<F, IDField>>
Expand Down
39 changes: 22 additions & 17 deletions src/db/util/raw-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ export type OrderByCond<F extends FieldDefinition> = {
order?: 'asc' | 'desc';
};

export type FindFn<F extends FieldDefinition> = (args?: {
where?: WhereCond<F>;
limit?: number;
offset?: number;
orderBy?: OrderByCond<F> | Array<OrderByCond<F>>;
trx?: Knex.Transaction<any, any>;
}) => Promise<Array<InstanceDataOf<F>>>;
export type FindFn<F extends FieldDefinition, AdditionalArgs = {}> = (
args?: {
where?: WhereCond<F>;
limit?: number;
offset?: number;
orderBy?: OrderByCond<F> | Array<OrderByCond<F>>;
trx?: Knex.Transaction<any, any>;
} & AdditionalArgs
) => Promise<Array<InstanceDataOf<F>>>;

export type FindOneFn<F extends FieldDefinition> = (args: {
where: WhereCond<F>;
trx?: Knex.Transaction<any, any>;
}) => Promise<InstanceDataOf<F> | null>;
export type FindOneFn<F extends FieldDefinition, AdditionalArgs = {}> = (
args: {
where: WhereCond<F>;
trx?: Knex.Transaction<any, any>;
} & AdditionalArgs
) => Promise<InstanceDataOf<F> | null>;

export type UpdateFn<F extends FieldDefinition> = (args: {
values: Partial<UserDataOf<F>>;
Expand All @@ -67,12 +71,12 @@ export type ModelInternals<F extends FieldDefinition> = {
/**
* The definition of a model
*/
export type Model<F extends FieldDefinition> = {
export type Model<F extends FieldDefinition, AdditionalFindArgs = {}> = {
readonly _internals: ModelInternals<F>;
readonly create: CreateFn<F>;
readonly createMany: CreateManyFn<F>;
readonly find: FindFn<F>;
readonly findOne: FindOneFn<F>;
readonly find: FindFn<F, AdditionalFindArgs>;
readonly findOne: FindOneFn<F, AdditionalFindArgs>;
readonly update: UpdateFn<F>;
readonly destroy: DestroyFn<F>;
};
Expand All @@ -84,9 +88,10 @@ export type InstanceDataOfModel<M extends Model<any>> = M extends Model<infer F>
/**
* A function that takes a knex connection and returns the model definition
*/
export type ModelInitializer<F extends FieldDefinition> = (
conn: Knex
) => Model<F>;
export type ModelInitializer<
F extends FieldDefinition,
AdditionalFindArgs = {}
> = (conn: Knex) => Model<F, AdditionalFindArgs>;

export const defineRawModel =
<F extends FieldDefinition>(opts: {
Expand Down
63 changes: 62 additions & 1 deletion src/db/util/sequelize-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import {
CreateFn,
CreateManyFn,
UpdateFn,
FindFn,
FindOneFn,
} from './raw-model';
import { FieldDefinition } from './model-definition';
import { Cond, Op } from './conditions';

type DeletedAtField<SoftDeletionEnabled extends boolean> =
SoftDeletionEnabled extends true
Expand Down Expand Up @@ -60,6 +63,15 @@ const genDeletedAtField = <P extends boolean>(
}
: {}) as DeletedAtField<P>;

export type AdditionalFindArgsForSequelizeTables = {
/**
* If true, also include deleted records in the result.
*
* This only affects tables with softDeletionEnabled set to true
*/
includeDeleted?: true;
};

/**
* A model that has been defined by sequelize
*
Expand All @@ -78,7 +90,10 @@ export const defineSequelizeModel =
*/
genIdentifier?: (data: unknown) => string;
softDeletionEnabled: SoftDeletionEnabled;
}): ModelInitializer<FieldsWithSequelize<F, SoftDeletionEnabled>> =>
}): ModelInitializer<
FieldsWithSequelize<F, SoftDeletionEnabled>,
AdditionalFindArgsForSequelizeTables
> =>
(conn) => {
type Fields = FieldsWithSequelize<F, SoftDeletionEnabled>;

Expand All @@ -93,6 +108,50 @@ export const defineSequelizeModel =
fields,
})(conn);

const find: FindFn<Fields, AdditionalFindArgsForSequelizeTables> = (
args
) => {
if (args?.includeDeleted || !opts.softDeletionEnabled) {
return model.find(args);
} else {
return model.find({
...args,
where: {
[Cond.AND]: [
{
deletedAt: {
[Op.IS_NULL]: true,
},
},
args?.where || {},
],
},
});
}
};

const findOne: FindOneFn<Fields, AdditionalFindArgsForSequelizeTables> = (
args
) => {
if (args?.includeDeleted || !opts.softDeletionEnabled) {
return model.findOne(args);
} else {
return model.findOne({
...args,
where: {
[Cond.AND]: [
{
deletedAt: {
[Op.IS_NULL]: true,
},
},
args?.where || {},
],
},
});
}
};

const create: CreateFn<Fields> = (data, opts) => {
return model.create(
{
Expand Down Expand Up @@ -127,6 +186,8 @@ export const defineSequelizeModel =

return {
...model,
find,
findOne,
create,
createMany,
update,
Expand Down

0 comments on commit f979cec

Please sign in to comment.