Skip to content

Commit

Permalink
feat: 💄 add get List route
Browse files Browse the repository at this point in the history
  • Loading branch information
doralteres committed Sep 5, 2023
1 parent 66b9833 commit 8f52771
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/routes/getList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {Router} from 'express';
import {getListOptions, pureModelType} from '../types';
import {buildOptionsFromConfig} from '../middleware/config';
import {
buildOptionsFromQueryParams,
checkFilterableFields,
checkSortableFields,
} from '../middleware/query';

const getListRoute = (
model: pureModelType,
router: Router,
config: getListOptions
) =>
router.get(
'/',
checkFilterableFields(config.filterableFields),
checkSortableFields(config.sortableFields),
async (req, res) => {
const {
pagination,
middleware,
filterableFields,
sortableFields,
...sequelizeOptions
} = config;
try {
const options = await buildOptionsFromConfig(
sequelizeOptions,
req,
res
);
const queryOptions = buildOptionsFromQueryParams(req.query);
if (pagination) {
const {rows, count} = await model.findAndCountAll({
...options,
...queryOptions,
where: {...options.where, ...queryOptions.where},
});
// TODO: set PAGINATION
res.json({rows, count});
} else {
const data = await model.findAll({
...options,
...queryOptions,
where: {...options.where, ...queryOptions.where},
});
res.json(data);
}
} catch (error) {
console.error(error);
res.status(500).send(error);
}
}
);

export default getListRoute;
98 changes: 98 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {NextFunction, Request, Response} from 'express';
import {
CreateOptions,
DestroyOptions,
FindAndCountOptions,
FindOptions,
Model,
ModelCtor,
NonNullFindOptions,
UpdateOptions,
} from 'sequelize';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type modelType = ModelCtor<Model<any, any>> | string;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type pureModelType = ModelCtor<Model<any, any>>;

type expressFunc = (req: Request, res: Response, next: NextFunction) => void;

export type sequelizeFunc<T> = (req: Request, res: Response) => Promise<T>;

export type sequelizePropOrFunc<T> = T extends unknown
? T | sequelizeFunc<T>
: never;

export type expressCrudProps<T> = {
[key in keyof T]: sequelizePropOrFunc<T[key]>;
};

type customFieldCore = {include: string[]} | {exclude: string[]} | string[];

export type customFields = sequelizePropOrFunc<customFieldCore>;

interface operationFieldCore {
middleware?: expressFunc;
// customFunc?: expressFunc;
}

interface getListCore {
filterableFields?: customFields;
sortableFields?: customFields;
}

interface getListOptionsWithPagination
extends operationFieldCore,
getListCore,
expressCrudProps<Omit<FindAndCountOptions<unknown>, 'group' | 'offset'>> {
pagination: true;
}

interface getListOptionsWithOutPagination
extends operationFieldCore,
getListCore,
expressCrudProps<FindOptions<unknown>> {
pagination?: false;
}

export type getListOptions =
| getListOptionsWithPagination
| getListOptionsWithOutPagination;

export interface getOneOptions
extends operationFieldCore,
expressCrudProps<Omit<NonNullFindOptions<unknown>, 'where'>> {}

interface createOptions
extends operationFieldCore,
expressCrudProps<CreateOptions<unknown>> {
creatableFields?: customFields;
}

interface updateOptions
extends operationFieldCore,
expressCrudProps<Omit<UpdateOptions<unknown>, 'where'>> {
updatableFields?: customFields;
}

interface deleteOptions
extends operationFieldCore,
expressCrudProps<Omit<DestroyOptions<unknown>, 'where'>> {}

type operationsType = {
getList?: getListOptions;
getOne?: getOneOptions;
create?: createOptions;
update?: updateOptions;
delete?: deleteOptions;
};

export type sequelizeCrudConfigModel = {
model: modelType;
operations: operationsType;
};

export type sequelizeCrudConfig = {
[basepath: string]: sequelizeCrudConfigModel;
};
8 changes: 8 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {Sequelize} from 'sequelize';
import {modelType} from './types';

export const getModel = (sequelize: Sequelize, model: modelType) =>
typeof model === 'string' ? sequelize.model(model) : model;

export const getPath = (path: string) =>
path.startsWith('/') ? path : `/${path}`;

0 comments on commit 8f52771

Please sign in to comment.