Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/update endpoint and service scaffold #23

Merged
merged 32 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ce7474f
Fix import error
Ehbraheem Aug 3, 2020
89f4b8c
Fix mustache interpolation issues
Ehbraheem Aug 3, 2020
961023f
Update packages
Ehbraheem Aug 3, 2020
f8b800d
Update restart policy
Ehbraheem Aug 3, 2020
398b016
Fix test files and helpers
Ehbraheem Aug 3, 2020
971071e
Add query helpers
Ehbraheem Aug 4, 2020
a5b0abb
proper route unit test
Ehbraheem Aug 4, 2020
43793e3
Remove casting
Ehbraheem Aug 4, 2020
9cd8348
Add document link
Ehbraheem Aug 4, 2020
648270f
Fix error in test helper
Ehbraheem Aug 4, 2020
f1afe3f
Hyperlink support + Removed deleted doc from query
Ehbraheem Aug 5, 2020
c661901
Change HTTP method to PUT
Ehbraheem Aug 5, 2020
5128970
Removed dead async/await
Ehbraheem Aug 7, 2020
8c73ab6
Update dependencies
Ehbraheem Aug 11, 2020
037c885
Better service license
Ehbraheem Aug 11, 2020
4218fc9
Turned off HTTPS for localhost
Ehbraheem Aug 11, 2020
13a16a0
Add missing dependencies, TS typing, and fix route test
Ehbraheem Aug 11, 2020
b7e9d4d
Fix mustache interpolations after generation
Ehbraheem Aug 12, 2020
bc7e7e8
Add project config
Ehbraheem Aug 14, 2020
2a8dc7f
Fix failing lint
Ehbraheem Aug 14, 2020
9ea5675
Merge branch 'master' into fix/update-endpoint-and-service-scaffold
jabdul Dec 19, 2021
5ac4f8b
Add new changes
Ehbraheem Feb 8, 2022
f36ba32
Add env config
Ehbraheem Feb 8, 2022
f3ecf0b
Finishing touches
Ehbraheem Feb 8, 2022
4d6fea8
Release 0.6.0: Upgrade packages and scaffold files
Ehbraheem Feb 8, 2022
cf16b55
Fix NPM error
Ehbraheem Feb 8, 2022
e9c9539
Release 0.6.1: Fix package scaffold
Ehbraheem Feb 8, 2022
5ed2348
Fix typings
Ehbraheem Feb 9, 2022
dfdb3b3
Release 0.6.2: Fix typings
Ehbraheem Feb 9, 2022
3c525c3
Upgrade service dependencies
Ehbraheem Feb 16, 2022
3dd5eb4
Release 0.6.3: Fix typescript error in generated dependencies
Ehbraheem Feb 16, 2022
6254e9f
Fix default service organisation name
Ehbraheem Feb 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ interface {{{scaffold_entity_capitalise}}}Fields extends Persistable {

export interface {{{scaffold_entity_capitalise}}}I extends {{{scaffold_entity_capitalise}}}Fields, Document {}

export const {{{scaffold_entity_capitalise}}}Schema: Schema = new Schema(
export const {{{scaffold_entity_capitalise}}}Schema = new Schema(
{
name: { type: String, lowercase: true, trim: true, required: true },
meta: { type: MetaSchema },
},
DefaultSchemaOptions,
);

{{{scaffold_entity_capitalise}}}Schema.virtual('links').get(function() {
return { self: { href: `/${this.id}` } };
});

{{{scaffold_entity_capitalise}}}Schema.index({ 'meta.created': -1 });
{{{scaffold_entity_capitalise}}}Schema.index({ 'meta.updated': -1 });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { factory } from 'factory-girl';
import '../../../../test/factories/{{{scaffold_factory}}}';
import queries from './queries';
import { configFiles } from '../../../utils/loadconfig';
import { verify{{{scaffold_entity_capitalise}}}, verifyResponse } from '../../../../test/helpers/accounts';

import { mongooseConnect, dbConfig as config } from '@ctt/crud-api';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { QueryArgs, DbClient, Query } from '@ctt/crud-api';
const create = async ({ payload }: QueryArgs): Promise<{{{scaffold_entity_capitalise}}}I> => {
const {{{scaffold_entity}}} = new {{{scaffold_entity_capitalise}}}({
...payload,
meta: { ...payload.meta, ...{ created: timezone.parse(Date.now(), intl.tz.LB) } },
meta: { ...payload.meta, ...{ created: timezone.parse(Date.now(), intl.tz.WAT) } },
});

return (await {{{scaffold_entity}}}.save()).toObject();
Expand All @@ -23,6 +23,7 @@ const findAll = async ({ payload }: QueryArgs): Promise<PaginateResult<{{{scaffo
$gte: path(['from'], payload),
$lte: path(['to'], payload),
},
'meta.active': true,
}),
},
{
Expand All @@ -36,26 +37,24 @@ const findAll = async ({ payload }: QueryArgs): Promise<PaginateResult<{{{scaffo
);

const findById = async ({ payload }: QueryArgs): Promise<{{{scaffold_entity_capitalise}}}I> =>
{{{scaffold_entity_capitalise}}}.findById(payload.id).lean({ virtuals: true });
{{{scaffold_entity_capitalise}}}.findOne({ _id: payload.id, 'meta.active': true }).lean({ virtuals: true });

const removeById = async ({ payload }: QueryArgs): Promise<object> =>
{{{scaffold_entity_capitalise}}}.updateOne(
{ _id: payload.id },
{ $set: { 'meta.active': false, 'meta.updated': Date.now() } },
{ _id: payload.id, 'meta.active': true },
{ $set: { 'meta.active': false, 'meta.updated': timezone.parse(Date.now(), intl.tz.WAT) } },
);

const updateById = async ({ payload }: QueryArgs): Promise<object> =>
{{{scaffold_entity_capitalise}}}.updateOne(
{ _id: payload.id },
{ _id: payload.id, 'meta.active': true },
{
...pickBy(val => !!val, {
...payload,
...{
$set: {
'meta.updated': Date.now(),
},
},
}),
$set: {
...pickBy(val => !!val, {
...payload,
'meta.updated': timezone.parse(Date.now(), intl.tz.WAT),
}),
},
},
);

Expand Down
24 changes: 12 additions & 12 deletions scaffold/endpoint/{{{scaffold_entities}}}/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,18 @@ describe(`Routes: ${ROUTE_NAME}`, () => {
mockContentType.mockImplementation(() => mockResponse);
mockRequest = {
log: jest.fn(),
params: jest.fn().mockReturnValue({ {{{scaffold_entity}}}Id: uid }),
params: jest.fn().mockReturnValue({ {{{scaffold_entity_route_id}}}: uid }),
};
});

it(`sets HTTP method GET on /${ROUTE_NAME} path`, () => {
expect(router.method).toBe('GET');
expect(router.path).toBe(`/${ROUTE_NAME}/{{{{scaffold_entity}}}Id}`);
expect(router.path).toBe(`/${ROUTE_NAME}/{{{scaffold_entity_route_id}}}`);
});

it('sets validation on request params', () => {
const { params } = router.options.validate;
expect(params.{{{scaffold_entity}}}Id).toBeDefined();
expect(params.{{{scaffold_entity_route_id}}}).toBeDefined();
});

it(`sets response HTTP status code to ${statusCode} on success`, async () => {
Expand Down Expand Up @@ -159,18 +159,18 @@ describe(`Routes: ${ROUTE_NAME}`, () => {
mockStatusCode.mockImplementation(() => mockResponse);
mockRequest = {
log: jest.fn(),
params: jest.fn().mockReturnValue({ {{{scaffold_entity}}}Id: uid }),
params: jest.fn().mockReturnValue({ {{{scaffold_entity_route_id}}}: uid }),
};
});

it(`sets HTTP method DELETE on /${ROUTE_NAME} path`, () => {
expect(router.method).toBe('DELETE');
expect(router.path).toBe(`/${ROUTE_NAME}/{{{{scaffold_entity}}}Id}`);
expect(router.path).toBe(`/${ROUTE_NAME}/{{{scaffold_entity_route_id}}}`);
});

it('sets validation on request params', () => {
const { params } = router.options.validate;
expect(params.{{{scaffold_entity}}}Id).toBeDefined();
expect(params.{{{scaffold_entity_route_id}}}).toBeDefined();
});

it(`sets response HTTP status code to ${statusCode} on success`, async () => {
Expand All @@ -189,7 +189,7 @@ describe(`Routes: ${ROUTE_NAME}`, () => {
});
});

describe(`PATCH /${ROUTE_NAME}`, () => {
describe(`PUT /${ROUTE_NAME}`, () => {
const router: any = update{{{scaffold_entity_capitalise}}}({ services, validate }); // eslint-disable-line @typescript-eslint/no-explicit-any
const responseData = '{{{scaffold_entity_capitalise}}} entry modified';
const statusCode = 200;
Expand All @@ -211,20 +211,20 @@ describe(`Routes: ${ROUTE_NAME}`, () => {
mockStatusCode.mockImplementation(() => mockResponse);
mockRequest = {
log: jest.fn(),
params: jest.fn().mockReturnValue({ {{{scaffold_entity}}}Id: uid }),
params: jest.fn().mockReturnValue({ {{{scaffold_entity_route_id}}}: uid }),
payload: jest.fn().mockReturnValue({}),
};
});

it(`sets HTTP method PATCH on /${ROUTE_NAME} path`, () => {
expect(router.method).toBe('PATCH');
expect(router.path).toBe(`/${ROUTE_NAME}/{{{{scaffold_entity}}}Id}`);
it(`sets HTTP method PUT on /${ROUTE_NAME} path`, () => {
expect(router.method).toBe('PUT');
expect(router.path).toBe(`/${ROUTE_NAME}/{{{scaffold_entity_route_id}}}`);
});

it('sets validation on request payload and params', () => {
const { payload } = router.options.validate;
const { params } = router.options.validate;
expect(params.{{{scaffold_entity}}}Id).toBeDefined();
expect(params.{{{scaffold_entity_route_id}}}).toBeDefined();
expect(payload).toBeDefined();
});

Expand Down
20 changes: 10 additions & 10 deletions scaffold/endpoint/{{{scaffold_entities}}}/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default ({ services, config, json, validate }: RouteArgs): ServerRoute =>

export const find{{{scaffold_entity_capitalise}}} = ({ services, validate, json, config }: RouteArgs): ServerRoute => ({
method: 'GET',
path: '/{{{scaffold_entities}}}/{{{{scaffold_entity}}}Id}',
path: '/{{{scaffold_entities}}}/{{{scaffold_entity_route_id}}}',
options: {
...service.options.secureOption,
validate: {
Expand All @@ -112,14 +112,14 @@ export const find{{{scaffold_entity_capitalise}}} = ({ services, validate, json,
.takeover();
},
params: {
{{{scaffold_entity}}}Id: validateObjectId(validate),
{{{scaffold_entity_id}}}: validateObjectId(validate),
},
},

tags: ['{{{scaffold_entities}}}'],
},
handler: async (request, h): Promise<ResponseObject> => {
const payload = { id: request.params.{{{scaffold_entity}}}Id };
const payload = { id: request.params.{{{scaffold_entity_id}}} };
request.log([`/${ROUTE_NAME}`]);
let response;

Expand Down Expand Up @@ -213,7 +213,7 @@ export const findAll{{{scaffold_entity_capitalise}}}s = ({ services, validate, c

export const remove{{{scaffold_entity_capitalise}}} = ({ services, validate, config, json }: RouteArgs): ServerRoute => ({
method: 'DELETE',
path: '/{{{scaffold_entities}}}/{{{{scaffold_entity}}}Id}',
path: '/{{{scaffold_entities}}}/{{{scaffold_entity_route_id}}}',
options: {
...service.options.secureOption,
validate: {
Expand All @@ -233,14 +233,14 @@ export const remove{{{scaffold_entity_capitalise}}} = ({ services, validate, con
.takeover();
},
params: {
{{{scaffold_entity}}}Id: validateObjectId(validate),
{{{scaffold_entity_id}}}: validateObjectId(validate),
},
},

tags: ['{{{scaffold_entities}}}'],
},
handler: async (request, h): Promise<ResponseObject> => {
const payload = { id: request.params.{{{scaffold_entity}}}Id };
const payload = { id: request.params.{{{scaffold_entity_id}}} };
request.log([`/${ROUTE_NAME}`]);
let response;

Expand All @@ -263,8 +263,8 @@ export const remove{{{scaffold_entity_capitalise}}} = ({ services, validate, con
});

export const update{{{scaffold_entity_capitalise}}} = ({ services, validate, config, json }: RouteArgs): ServerRoute => ({
method: 'PATCH',
path: '/{{{scaffold_entities}}}/{{{{scaffold_entity}}}Id}',
method: 'PUT',
path: '/{{{scaffold_entities}}}/{{{scaffold_entity_route_id}}}',
options: {
...service.options.secureOption,
validate: {
Expand All @@ -284,7 +284,7 @@ export const update{{{scaffold_entity_capitalise}}} = ({ services, validate, con
.takeover();
},
params: {
{{{scaffold_entity}}}Id: validateObjectId(validate),
{{{scaffold_entity_id}}}: validateObjectId(validate),
},
payload: makeRequestPayloadSchema(validate),
},
Expand All @@ -294,7 +294,7 @@ export const update{{{scaffold_entity_capitalise}}} = ({ services, validate, con
handler: async (request, h): Promise<ResponseObject> => {
const payload = {
...(request.payload as object),
id: request.params.{{{scaffold_entity}}}Id,
id: request.params.{{{scaffold_entity_id}}},
};
request.log([`/${ROUTE_NAME}`]);
let response;
Expand Down
1 change: 1 addition & 0 deletions scaffold/endpoint/{{{scaffold_entities}}}/services.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import tmplJson from './parsers/json';
import { Dict, Crud, ServiceArgs } from '@ctt/crud-api';
import { pickBy } from 'ramda';
import { {{{scaffold_entity_capitalise}}}I } from '../persistence/mongoose/{{{scaffold_entity_capitalise}}}/model';
import { PaginateResult } from 'mongoose';
import { responseDocumentSchema, createPaginationLink } from '../utils/schemas';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let app = null;
const url = `/${ROUTE_NAME}`;
let headers = null;

describe('Users', () => {
describe('{{{scaffold_entities_capitalized}}}', () => {
beforeAll(async () => {
app = await application();
await app.start();
Expand Down
2 changes: 1 addition & 1 deletion scaffold/service/nodemon.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"env": {
"NODE_ENV": "development"
},
"ext": "ts",
"ext": "ts,js,json",
"exec": "ts-node -- src/index.ts"
}
4 changes: 2 additions & 2 deletions scaffold/service/package.json.replace
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
},
"dependencies": {
"@ctt/crud-api": "1.6.27",
"@ctt/redis-client": "0.0.0-beta.5",
"@ctt/service-utils": "1.3.11",
"@ctt/redis-client": "0.0.1",
"@ctt/service-utils": "1.3.22",
"convict": "4.3.2",
"dotenv": "6.0.0",
"hapi-auth-jwt2": "8.1.0",
Expand Down
32 changes: 24 additions & 8 deletions scaffold/service/src/utils/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const errorResponseSchema = {
},
};

const link = {
const paginationLink = {
type: 'object',
properties: {
href: {
Expand All @@ -49,6 +49,20 @@ const link = {
},
};

const links = {
type: 'object',
properties: {
self: {
type: 'object',
properties: {
href: {
type: 'string',
},
},
},
},
};

export const paginationResponseSchema = {
pagination: {
type: 'object',
Expand All @@ -62,11 +76,11 @@ export const paginationResponseSchema = {
type: 'integer',
format: 'int32',
},
first: link,
last: link,
next: link,
current: link,
previous: link,
first: paginationLink,
last: paginationLink,
next: paginationLink,
current: paginationLink,
previous: paginationLink,
},
},
};
Expand All @@ -92,6 +106,7 @@ export const responseDocumentSchema = (template): object => ({
id: {
type: 'string',
},
links,
...metaResponseSchema,
},
},
Expand All @@ -101,12 +116,13 @@ export const responseDocumentSchema = (template): object => ({
},
});

export const validateObjectId = (validator: Root): StringSchema => validator.string().regex(/\b[0-9a-fA-F]{24}\b/);
export const validateObjectId = (validator: Root): StringSchema =>
validator.string().regex(/\b[0-9a-fA-F]{24}\b/);

export const createPaginationLink = (endpoint: string): Function => (
page: number,
limit?: number,
offset?: number
offset?: number,
): object => ({
href: `/${endpoint}?page=${page}&limit=${limit}${offset ? `&offset=${offset}` : ''}`,
});
Loading