Merge pull request #105 from BRAVO68WEB/feat/meta-pagenation-api

Feat/meta pagenation api
This commit is contained in:
Jyotirmoy Bandyopadhayaya 2023-06-24 13:43:38 +05:30 committed by GitHub
commit d633b98bf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 220 additions and 83 deletions

View File

@ -15,13 +15,16 @@ export default class APIKeyController
next: NextFunction
): Promise<Response | void> => {
let apikeys;
let metadata;
try {
const { masterkey } = req.query as { masterkey: string };
apikeys = await this.listS(masterkey);
const { data, meta } = await this.listS(masterkey);
apikeys = data;
metadata = meta;
} catch (error) {
return next(error);
}
return res.status(200).json(makeResponse(apikeys));
return res.status(200).json(makeResponse(apikeys, metadata));
};
public generate = async (

View File

@ -126,12 +126,12 @@ export default class GistController
limit: string;
page: string;
};
const gists = await this.listGistsS(
const { data, meta } = await this.listGistsS(
search,
parseInt(page),
parseInt(limit)
);
res.status(200).json(makeResponse(gists));
res.status(200).json(makeResponse(data, meta));
} catch (error) {
next(error);
}

View File

@ -125,9 +125,21 @@ export default class UploadController
next: NextFunction
): Promise<Response | void> => {
try {
const { limit, offset, query = '' } = req.query;
const data = await this.listFilesS(query, Number(limit), Number(offset));
res.status(200).json(makeResponse(data));
const {
limit,
page,
query = '',
} = req.query as {
limit: string;
page: string;
query: string;
};
const { data, meta } = await this.listFilesS(
query,
parseInt(limit),
parseInt(page)
);
res.status(200).json(makeResponse(data, meta));
} catch (error: any) {
next(error);
}

View File

@ -96,13 +96,17 @@ export default class URLStoreController
next: NextFunction
): Promise<Response | void> => {
try {
const { query, limit, page } = req.query;
const urlstore = await this.getAllURLS(
query as string,
Number(limit),
Number(page)
const { query, limit, page } = req.query as {
query: string;
limit: string;
page: string;
};
const { data, meta } = await this.getAllURLS(
query,
parseInt(limit),
parseInt(page)
);
res.status(200).json(makeResponse(urlstore));
res.status(200).json(makeResponse(data, meta));
} catch (error) {
next(error);
}

View File

@ -1,7 +1,7 @@
import { NextFunction, Response } from 'express';
import { ModRequest } from '../types';
import { Apikeys } from '../graphql/types';
import { encapDataKey } from '../libs'
import { encapDataKey } from '../libs';
export interface IAPIKeyController {
list(
@ -27,13 +27,20 @@ export interface IAPIKeyController {
}
export interface IAPIKeyService {
listS(masterkey: string): Promise<encapDataKey[]>;
listS(masterkey: string): Promise<IListAPIKeys>;
generateS(masterkey: string): Promise<Apikeys>;
deleteS(apikey: string, masterkey: string): Promise<number>;
checkS(apikey: string): Promise<Apikeys | null>;
verifyS(apikey: string): Promise<boolean>;
}
export interface IListAPIKeys {
data: encapDataKey[];
meta: {
total: number;
};
}
export interface IAPIKeyAuth {
check(req: ModRequest, res: Response, next: NextFunction): Promise<void>;
}

View File

@ -29,7 +29,7 @@ export interface IGistService {
searchString: string,
pageNo: number,
pageSize: number
): Promise<Gists[]>;
): Promise<IListGists>;
}
export interface IPrivate {
@ -40,3 +40,13 @@ export interface IPrivate {
export interface GistRep extends Gists {
gist_url?: string;
}
export interface IListGists {
data: Gists[];
meta: {
total: number;
pageNo: number;
pageSize: number;
totalPages: number;
};
}

View File

@ -52,10 +52,20 @@ export interface IUploaderService {
searchQuery: any,
limit: number,
offset: number
): Promise<Uploads[]>;
): Promise<IListUploads>;
getFileS(fileID: string): Promise<Uploads>;
}
export interface IListUploads {
data: Uploads[];
meta: {
total: number;
pageNo: number;
pageSize: number;
totalPages: number;
};
}
export interface UploaderConfig {
mimeFilters: string[];
}

View File

@ -43,11 +43,21 @@ export interface IURLStoreService {
searchQuery: string,
limit: number,
offset: number
): Promise<Shorturls[]>;
): Promise<IListURLS>;
getaURLS(urlID: string): Promise<Shorturls>;
updateURLS(urlKey: string, updateObject: any): Promise<number>;
}
export interface IListURLS {
data: Shorturls[];
meta: {
total: number;
pageNo: number;
pageSize: number;
totalPages: number;
};
}
export interface URLStoreRep extends Shorturls {
url?: string;
}

View File

@ -5,6 +5,7 @@ import APIKeyAuth from '../middlewares/apikey_check';
import {
deleteFileValidation,
urlUploadValidation,
listFileValidation,
} from '../validators/upload.validation';
const uploadController = new UploadController();
@ -45,7 +46,12 @@ router.post(
uploadController.uploadFileFromURL as any
);
router.get('/', apiKeyAuth.check as any, uploadController.getAllFiles as any);
router.get(
'/',
apiKeyAuth.check as any,
listFileValidation as any,
uploadController.getAllFiles as any
);
router.get(
'/:fileID',

View File

@ -1,9 +1,8 @@
import { gql } from 'graphql-request';
import { client } from '../helpers';
import { IAPIKeyService } from '../interfaces/apikey.interface';
import { IAPIKeyService, IListAPIKeys } from '../interfaces/apikey.interface';
import { encapDataKeys } from '../libs';
import { Apikeys, Apikeys_Mutation_Response } from '../graphql/types';
import { encapDataKey } from '../libs';
export default class APIKeyService implements IAPIKeyService {
public async checkS(apikey: string): Promise<Apikeys | null> {
const query = gql`
@ -25,7 +24,6 @@ export default class APIKeyService implements IAPIKeyService {
if (result.apikeys.length === 0) {
return null;
} else {
// return result.apikeys[0];
const updateLastUsedquery = gql`
mutation updateLastUsed($apikeyID: uuid!) {
update_apikeys_by_pk(
@ -84,7 +82,7 @@ export default class APIKeyService implements IAPIKeyService {
return result.delete_apikeys.affected_rows;
}
public async listS(masterKey: string): Promise<encapDataKey[]> {
public async listS(masterKey: string): Promise<IListAPIKeys> {
if (masterKey !== process.env.MASTER_KEY)
throw new Error('Invalid master key');
const query = gql`
@ -94,12 +92,28 @@ export default class APIKeyService implements IAPIKeyService {
keyID
last_used
}
apikeys_aggregate {
aggregate {
count
}
}
}
`;
const result: {
apikeys: Apikeys[];
apikeys_aggregate: {
aggregate: {
count: number;
};
};
} = await client.request(query);
return encapDataKeys(result.apikeys);
return {
data: encapDataKeys(result.apikeys),
meta: {
total: result.apikeys_aggregate.aggregate.count,
},
};
}
public async verifyS(apikey: string): Promise<boolean> {

View File

@ -1,6 +1,10 @@
import { gql } from 'graphql-request';
import { client } from '../helpers';
import { IGistService, IPrivate } from '../interfaces/gists.interface';
import {
IGistService,
IListGists,
IPrivate,
} from '../interfaces/gists.interface';
import { UserMeta } from '../types';
import { Gists, Gists_Mutation_Response } from '../graphql/types';
@ -127,7 +131,7 @@ export default class GistService implements IGistService {
searchString = '',
pageNo = 1,
pageSize = 10
): Promise<Gists[]> {
): Promise<IListGists> {
const query = gql`
query listGists($searchString: String!, $pageNo: Int!, $pageSize: Int!) {
gists(
@ -148,6 +152,19 @@ export default class GistService implements IGistService {
isOneTimeOnly
views
}
gists_aggregate(
where: {
_or: [
{ content: { _iregex: $searchString } }
{ gist_url_key: { _iregex: $searchString } }
]
}
) {
aggregate {
count
}
}
}
`;
const variables = {
@ -157,8 +174,29 @@ export default class GistService implements IGistService {
};
const result: {
gists: Gists[];
gists_aggregate: {
aggregate: {
count: number;
};
};
} = await client.request(query, variables);
return result.gists;
result.gists = result.gists.map(gist => {
if (gist.isPrivate) {
gist.content = 'Locked 🔒';
}
return gist;
});
return {
data: result.gists,
meta: {
pageNo,
pageSize,
total: result.gists_aggregate.aggregate.count,
totalPages: Math.ceil(
result.gists_aggregate.aggregate.count / pageSize
),
},
};
}
public async updateGistS(gistID: string, content: string): Promise<number> {

View File

@ -2,7 +2,7 @@ import UploaderService from '../data/uploader.service';
import { gql } from 'graphql-request';
import { client } from '../helpers';
import sharp from 'sharp';
import { IUploaderService } from '../interfaces/upload.interface';
import { IListUploads, IUploaderService } from '../interfaces/upload.interface';
import { UserMeta } from '../types';
import axios from 'axios';
import fs from 'fs';
@ -333,9 +333,9 @@ export default class Uploader implements IUploaderService {
public listFilesS = async (
searchQuery: any,
limit: number,
offset: number
): Promise<Uploads[]> => {
limit = 1,
offset = 10
): Promise<IListUploads> => {
const query = gql`
query listFiles($searchQuery: String!, $limit: Int!, $offset: Int!) {
uploads(
@ -373,14 +373,27 @@ export default class Uploader implements IUploaderService {
const variables = {
searchQuery,
limit: limit,
offset: offset,
offset: (offset - 1) * limit,
};
const data: {
uploads: Uploads[];
uploads_aggregate: {
aggregate: {
count: number;
};
};
} = await client.request(query, variables);
return data.uploads;
return {
data: data.uploads,
meta: {
total: data.uploads_aggregate.aggregate.count,
pageNo: offset,
pageSize: limit,
totalPages: Math.ceil(data.uploads_aggregate.aggregate.count / limit),
},
};
};
public getFileS = async (fileID: string): Promise<Uploads> => {

View File

@ -1,7 +1,7 @@
import { gql } from 'graphql-request';
import { client } from '../helpers';
import { UserMeta } from '../types';
import { IURLStoreService } from '../interfaces/urlstore.interface';
import { IListURLS, IURLStoreService } from '../interfaces/urlstore.interface';
import { Shorturls, Shorturls_Mutation_Response } from '../graphql/types';
export default class URLStore implements IURLStoreService {
@ -64,8 +64,8 @@ export default class URLStore implements IURLStoreService {
public async getAllURLS(
searchQuery = '',
limit = 10,
offset = 0
): Promise<Shorturls[]> {
offset = 1
): Promise<IListURLS> {
const query = gql`
query getAllURLS($searchQuery: String!, $limit: Int!, $offset: Int!) {
shorturls(
@ -83,17 +83,45 @@ export default class URLStore implements IURLStoreService {
short_key
urlID
}
shorturls_aggregate(
where: {
_or: [
{ short_key: { _iregex: $searchQuery } }
{ original_url: { _iregex: $searchQuery } }
]
}
) {
aggregate {
count
}
}
}
`;
const variables = {
searchQuery,
limit,
offset,
offset: (offset - 1) * limit,
};
const result: {
shorturls: Shorturls[];
shorturls_aggregate: {
aggregate: {
count: number;
};
};
} = await client.request(query, variables);
return result.shorturls;
return {
data: result.shorturls,
meta: {
pageNo: offset,
pageSize: limit,
total: result.shorturls_aggregate.aggregate.count,
totalPages: Math.ceil(
result.shorturls_aggregate.aggregate.count / limit
),
},
};
}
public async getaURLS(urlID: string): Promise<Shorturls> {

View File

@ -49,3 +49,28 @@ export const urlUploadValidation = async (
return;
}
};
export const listFileValidation = async (
req: ModRequest,
res: Response,
next: NextFunction
) => {
try {
const schema = Joi.object().keys({
query: Joi.string().optional(),
page: Joi.number().optional().default(1),
limit: Joi.number().optional().default(10),
});
req.query = await schema.validateAsync(req.query);
next();
} catch (err) {
res.status(400).send(
new CustomError({
data: err,
message: ErrorMsg.VALIDATION,
statusCode: 400,
})
);
return;
}
};

View File

@ -58,8 +58,8 @@ export const urlGelAllValidation = async (
try {
const schema = Joi.object().keys({
query: Joi.string().optional(),
page: Joi.number().optional(),
limit: Joi.number().optional(),
page: Joi.number().optional().default(1),
limit: Joi.number().optional().default(10),
});
req.query = await schema.validateAsync(req.query);
next();

View File

@ -2290,18 +2290,6 @@
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4":
<<<<<<< HEAD
version "7.22.3"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz"
integrity sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.21.9":
version "7.21.9"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz"
integrity sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==
=======
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
@ -2312,7 +2300,6 @@
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==
>>>>>>> dev
dependencies:
"@babel/code-frame" "^7.22.5"
"@babel/parser" "^7.22.5"
@ -3447,17 +3434,10 @@
pump "^3.0.0"
tar-fs "^2.1.1"
<<<<<<< HEAD
"@next/env@13.4.7":
version "13.4.7"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.7.tgz#ca12d341edb128ca70384635bd2794125ffb1c01"
integrity sha512-ZlbiFulnwiFsW9UV1ku1OvX/oyIPLtMk9p/nnvDSwI0s7vSoZdRtxXNsaO+ZXrLv/pMbXVGq4lL8TbY9iuGmVw==
=======
"@next/env@13.4.3":
version "13.4.3"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.3.tgz#cb00bdd43a0619a79a52c9336df8a0aa84f8f4bf"
integrity sha512-pa1ErjyFensznttAk3EIv77vFbfSYT6cLzVRK5jx4uiRuCQo+m2wCFAREaHKIy63dlgvOyMlzh6R8Inu8H3KrQ==
>>>>>>> dev
"@next/eslint-plugin-next@13.4.5":
version "13.4.5"
@ -3486,7 +3466,6 @@
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.7.tgz#0cac0f01d4e308b439e6c33182bed77835fe383b"
integrity sha512-T1kD2FWOEy5WPidOn1si0rYmWORNch4a/NR52Ghyp4q7KyxOCuiOfZzyhVC5tsLIBDH3+cNdB5DkD9afpNDaOw==
<<<<<<< HEAD
"@next/swc-linux-x64-gnu@13.4.7":
version "13.4.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.7.tgz#feb61e16a68c67f3ef230f30d9562a3783c7bd59"
@ -3496,17 +3475,6 @@
version "13.4.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.7.tgz#02179ecfa6d24a2956c2b54f7d27a050568bbf24"
integrity sha512-X6r12F8d8SKAtYJqLZBBMIwEqcTRvUdVm+xIq+l6pJqlgT2tNsLLf2i5Cl88xSsIytBICGsCNNHd+siD2fbWBA==
=======
"@next/swc-linux-x64-gnu@13.4.3":
version "13.4.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.3.tgz#3f85bc5591c6a0d4908404f7e88e3c04f4462039"
integrity sha512-AMdFX6EKJjC0G/CM6hJvkY8wUjCcbdj3Qg7uAQJ7PVejRWaVt0sDTMavbRfgMchx8h8KsAudUCtdFkG9hlEClw==
"@next/swc-linux-x64-musl@13.4.3":
version "13.4.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.3.tgz#f4535adc2374a86bc8e43af149b551567df065de"
integrity sha512-jySgSXE48shaLtcQbiFO9ajE9mqz7pcAVLnVLvRIlUHyQYR/WyZdK8ehLs65Mz6j9cLrJM+YdmdJPyV4WDaz2g==
>>>>>>> dev
"@next/swc-win32-arm64-msvc@13.4.7":
version "13.4.7"
@ -5243,9 +5211,6 @@
dependencies:
"@types/react" "*"
<<<<<<< HEAD
"@types/react@*", "@types/react@18.2.7", "@types/react@>=16":
=======
"@types/react@*", "@types/react@>=16":
version "18.2.13"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.13.tgz#a98c09bde8b18f80021935b11d2d29ef5f4dcb2f"
@ -5256,7 +5221,6 @@
csstype "^3.0.2"
"@types/react@18.2.7":
>>>>>>> dev
version "18.2.7"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.7.tgz#dfb4518042a3117a045b8c222316f83414a783b3"
integrity sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==
@ -11220,17 +11184,10 @@ next-auth@^4.22.1:
preact-render-to-string "^5.1.19"
uuid "^8.3.2"
<<<<<<< HEAD
next@^13.4.7:
version "13.4.7"
resolved "https://registry.yarnpkg.com/next/-/next-13.4.7.tgz#2ab20e6fada2e25cb81bd17f68956705ffd9824e"
integrity sha512-M8z3k9VmG51SRT6v5uDKdJXcAqLzP3C+vaKfLIAM0Mhx1um1G7MDnO63+m52qPdZfrTFzMZNzfsgvm3ghuVHIQ==
=======
next@13.4.3:
version "13.4.3"
resolved "https://registry.yarnpkg.com/next/-/next-13.4.3.tgz#7f417dec9fa2731d8c1d1819a1c7d0919ad6fc75"
integrity sha512-FV3pBrAAnAIfOclTvncw9dDohyeuEEXPe5KNcva91anT/rdycWbgtu3IjUj4n5yHnWK8YEPo0vrUecHmnmUNbA==
>>>>>>> dev
dependencies:
"@next/env" "13.4.7"
"@swc/helpers" "0.5.1"