@lyxa.ai/core 1.4.335 → 1.4.337
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/libraries/trpc/middlewares/auth.js +3 -0
- package/dist/libraries/trpc/middlewares/auth.js.map +1 -1
- package/dist/types/README.md +1 -1
- package/dist/types/package.json +1 -1
- package/dist/utilities/pagination.d.ts +2 -2
- package/dist/utilities/pagination.js +3 -3
- package/dist/utilities/pagination.js.map +1 -1
- package/package.json +1 -1
|
@@ -43,6 +43,9 @@ function createAuthenticatedProcedure(options) {
|
|
|
43
43
|
}
|
|
44
44
|
if (entity?.type == auth_1.AuthEntityType.SELLER) {
|
|
45
45
|
const shopAccessControlModel = await models_1.ShopAccessControlModel.findOne({ _id: entity.id });
|
|
46
|
+
if (shopAccessControlModel && shopAccessControlModel.status !== enum_1.Status.ACTIVE) {
|
|
47
|
+
return (0, error_common_1.unauthorizedError)('Seller is not active');
|
|
48
|
+
}
|
|
46
49
|
if (!shopAccessControlModel)
|
|
47
50
|
throw new server_1.TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });
|
|
48
51
|
if (['parent', 'parent_manager', 'parent_order_manager'].includes(shopAccessControlModel.role)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"/","sources":["libraries/trpc/middlewares/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import { TRPCError } from '@trpc/server';\nimport { publicProcedure } from '../index';\nimport { AuthEntityType, handleTokenRenewal, TokenType, verifyAccessToken } from '../../auth';\nimport {\n\tAdminModel,\n\tgetCoreUserModel,\n\tParentModel,\n\tRiderModel,\n\tShopAccessControlModel,\n\tShopModel,\n} from '../../mongo/models';\nimport { Status } from '../../../utilities/enum';\nimport { unauthorizedError } from '../../../utilities/error-common';\nimport { getLibraries } from '../../..';\n\ninterface AuthOptions {\n\tentityTypes: AuthEntityType[];\n\tallowRefreshToken?: boolean;\n\tautoRefresh?: boolean;\n}\n\n/**\n * A factory that creates an authenticated procedure, optionally allowing\n * refresh tokens and auto-refreshing expired access tokens.\n */\nexport function createAuthenticatedProcedure(options: AuthOptions) {\n\tconst { entityTypes, allowRefreshToken = true, autoRefresh = true } = options;\n\n\treturn publicProcedure.use(async ({ ctx, next }) => {\n\t\tconst authHeader = ctx.req.headers['authorization'];\n\t\tconst refreshTokenHeader = ctx.req.headers['x-refresh-token'];\n\n\t\tif (!authHeader) {\n\t\t\tthrow new TRPCError({ code: 'UNAUTHORIZED', message: 'No authorization header' });\n\t\t}\n\n\t\tconst accessToken = authHeader.replace(/^Bearer\\s+/, '');\n\t\tlet refreshToken = '';\n\n\t\tif (refreshTokenHeader) {\n\t\t\trefreshToken =\n\t\t\t\ttypeof refreshTokenHeader === 'string'\n\t\t\t\t\t? refreshTokenHeader.replace(/^Bearer\\s+/, '')\n\t\t\t\t\t: refreshTokenHeader[0].replace(/^Bearer\\s+/, '');\n\t\t}\n\n\t\tif (!accessToken) unauthorizedError('Missing access token');\n\n\t\tlet entity = await verifyAccessToken(entityTypes, accessToken);\n\n\t\tif (entity?.type == AuthEntityType.USER) {\n\t\t\tconst user = await getCoreUserModel().findOne({ _id: entity.parameters.coreUserId });\n\n\t\t\tif (!user) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'User not found' });\n\t\t\tif (user.status !== Status.ACTIVE) unauthorizedError('User is not active');\n\t\t}\n\n\t\tif (entity?.type == AuthEntityType.CRM) {\n\t\t\tconst admin = await AdminModel.findOne({ _id: entity.parameters.adminId });\n\n\t\t\tif (!admin) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin not found' });\n\t\t\tif (admin.status !== Status.ACTIVE) unauthorizedError('Admin is not active');\n\t\t}\n\n\t\t// Seller\n\t\tif (entity?.type == AuthEntityType.SELLER) {\n\t\t\tconst shopAccessControlModel = await ShopAccessControlModel.findOne({ _id: entity.id });\n\t\t\tif (!shopAccessControlModel) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\n\t\t\t// For Parent\n\t\t\tif (['parent', 'parent_manager', 'parent_order_manager'].includes(shopAccessControlModel.role)) {\n\t\t\t\tconst parent = await ParentModel.findOne({ _id: shopAccessControlModel.parent });\n\n\t\t\t\tif (!parent) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\t\t\t\tif (parent.status !== Status.ACTIVE) unauthorizedError('Seller is not active');\n\t\t\t}\n\n\t\t\t// For Shop\n\t\t\tconst shops = shopAccessControlModel.shops ?? [];\n\n\t\t\tif (\n\t\t\t\tshops.length > 0 &&\n\t\t\t\t['shop', 'shop_manager', 'shop_order_manager'].includes(shopAccessControlModel.role)\n\t\t\t) {\n\t\t\t\tconst shopId = shops[0];\n\t\t\t\tconst shop = await ShopModel.findOne({ _id: shopId });\n\n\t\t\t\tif (!shop) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\t\t\t\tif (shop.status !== Status.ACTIVE) unauthorizedError('Seller is not active');\n\t\t\t}\n\t\t}\n\n\t\t// For rider\n\t\tif (entity?.type == AuthEntityType.DELIVERY_BOY) {\n\t\t\tconst rider = await RiderModel.findOne({ _id: entity.id });\n\n\t\t\t// Check the rider exists or not\n\t\t\tif (!rider) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin not found' });\n\n\t\t\t// Check the rider isLogin true or false\n\t\t\tif (rider.isLogin) {\n\t\t\t\tif (rider.lastLoginDeviceId !== entity.parameters.deviceId) {\n\t\t\t\t\tunauthorizedError('You already logged in another device');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tunauthorizedError('You have been logged out, Please login in again');\n\t\t\t}\n\n\t\t\tawait getLibraries().getRedisService().setLastOnline(AuthEntityType.DELIVERY_BOY, rider._id.toString());\n\t\t}\n\n\t\tif (entity) {\n\t\t\tctx.entity = entity;\n\t\t\tctx.tokenType = TokenType.ACCESS;\n\t\t\tctx.usedRefreshToken = false;\n\t\t\tctx.tokenRenewed = false;\n\n\t\t\treturn next({ ctx });\n\t\t}\n\n\t\tif (!allowRefreshToken || !refreshToken) unauthorizedError('Invalid access token');\n\n\t\tconst renewalResult = await handleTokenRenewal(refreshToken);\n\n\t\tif (!renewalResult.success) {\n\t\t\tconst errorMessage =\n\t\t\t\trenewalResult.tokenStatus === 'revoked' ? 'Refresh token has been revoked' : 'Invalid refresh token';\n\n\t\t\tunauthorizedError(errorMessage);\n\t\t}\n\n\t\tif (!entityTypes.includes(renewalResult.entity!.type)) unauthorizedError('Unauthorized entity type');\n\n\t\tctx.entity = renewalResult.entity;\n\t\tctx.tokenType = TokenType.REFRESH;\n\t\tctx.usedRefreshToken = true;\n\n\t\tctx.tokenRenewed = renewalResult.tokenStatus === 'expired';\n\n\t\tif (autoRefresh && renewalResult.newTokens) {\n\t\t\tif (renewalResult.newTokens.accessToken) {\n\t\t\t\tctx.res.setHeader('X-New-Access-Token', renewalResult.newTokens.accessToken);\n\t\t\t}\n\n\t\t\tif (renewalResult.newTokens.refreshToken) {\n\t\t\t\tctx.res.setHeader('X-New-Refresh-Token', renewalResult.newTokens.refreshToken);\n\t\t\t}\n\t\t}\n\n\t\treturn next({ ctx });\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"/","sources":["libraries/trpc/middlewares/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import { TRPCError } from '@trpc/server';\nimport { publicProcedure } from '../index';\nimport { AuthEntityType, handleTokenRenewal, TokenType, verifyAccessToken } from '../../auth';\nimport {\n\tAdminModel,\n\tgetCoreUserModel,\n\tParentModel,\n\tRiderModel,\n\tShopAccessControlModel,\n\tShopModel,\n} from '../../mongo/models';\nimport { Status } from '../../../utilities/enum';\nimport { unauthorizedError } from '../../../utilities/error-common';\nimport { getLibraries } from '../../..';\n\ninterface AuthOptions {\n\tentityTypes: AuthEntityType[];\n\tallowRefreshToken?: boolean;\n\tautoRefresh?: boolean;\n}\n\n/**\n * A factory that creates an authenticated procedure, optionally allowing\n * refresh tokens and auto-refreshing expired access tokens.\n */\nexport function createAuthenticatedProcedure(options: AuthOptions) {\n\tconst { entityTypes, allowRefreshToken = true, autoRefresh = true } = options;\n\n\treturn publicProcedure.use(async ({ ctx, next }) => {\n\t\tconst authHeader = ctx.req.headers['authorization'];\n\t\tconst refreshTokenHeader = ctx.req.headers['x-refresh-token'];\n\n\t\tif (!authHeader) {\n\t\t\tthrow new TRPCError({ code: 'UNAUTHORIZED', message: 'No authorization header' });\n\t\t}\n\n\t\tconst accessToken = authHeader.replace(/^Bearer\\s+/, '');\n\t\tlet refreshToken = '';\n\n\t\tif (refreshTokenHeader) {\n\t\t\trefreshToken =\n\t\t\t\ttypeof refreshTokenHeader === 'string'\n\t\t\t\t\t? refreshTokenHeader.replace(/^Bearer\\s+/, '')\n\t\t\t\t\t: refreshTokenHeader[0].replace(/^Bearer\\s+/, '');\n\t\t}\n\n\t\tif (!accessToken) unauthorizedError('Missing access token');\n\n\t\tlet entity = await verifyAccessToken(entityTypes, accessToken);\n\n\t\tif (entity?.type == AuthEntityType.USER) {\n\t\t\tconst user = await getCoreUserModel().findOne({ _id: entity.parameters.coreUserId });\n\n\t\t\tif (!user) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'User not found' });\n\t\t\tif (user.status !== Status.ACTIVE) unauthorizedError('User is not active');\n\t\t}\n\n\t\tif (entity?.type == AuthEntityType.CRM) {\n\t\t\tconst admin = await AdminModel.findOne({ _id: entity.parameters.adminId });\n\n\t\t\tif (!admin) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin not found' });\n\t\t\tif (admin.status !== Status.ACTIVE) unauthorizedError('Admin is not active');\n\t\t}\n\n\t\t// Seller\n\t\tif (entity?.type == AuthEntityType.SELLER) {\n\t\t\tconst shopAccessControlModel = await ShopAccessControlModel.findOne({ _id: entity.id });\n\t\t\tif (shopAccessControlModel && shopAccessControlModel.status !== Status.ACTIVE) {\n\t\t\t\treturn unauthorizedError('Seller is not active');\n\t\t\t}\n\t\t\tif (!shopAccessControlModel) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\n\t\t\t// For Parent\n\t\t\tif (['parent', 'parent_manager', 'parent_order_manager'].includes(shopAccessControlModel.role)) {\n\t\t\t\tconst parent = await ParentModel.findOne({ _id: shopAccessControlModel.parent });\n\n\t\t\t\tif (!parent) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\t\t\t\tif (parent.status !== Status.ACTIVE) unauthorizedError('Seller is not active');\n\t\t\t}\n\n\t\t\t// For Shop\n\t\t\tconst shops = shopAccessControlModel.shops ?? [];\n\n\t\t\tif (\n\t\t\t\tshops.length > 0 &&\n\t\t\t\t['shop', 'shop_manager', 'shop_order_manager'].includes(shopAccessControlModel.role)\n\t\t\t) {\n\t\t\t\tconst shopId = shops[0];\n\t\t\t\tconst shop = await ShopModel.findOne({ _id: shopId });\n\n\t\t\t\tif (!shop) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Seller not found' });\n\t\t\t\tif (shop.status !== Status.ACTIVE) unauthorizedError('Seller is not active');\n\t\t\t}\n\t\t}\n\n\t\t// For rider\n\t\tif (entity?.type == AuthEntityType.DELIVERY_BOY) {\n\t\t\tconst rider = await RiderModel.findOne({ _id: entity.id });\n\n\t\t\t// Check the rider exists or not\n\t\t\tif (!rider) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin not found' });\n\n\t\t\t// Check the rider isLogin true or false\n\t\t\tif (rider.isLogin) {\n\t\t\t\tif (rider.lastLoginDeviceId !== entity.parameters.deviceId) {\n\t\t\t\t\tunauthorizedError('You already logged in another device');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tunauthorizedError('You have been logged out, Please login in again');\n\t\t\t}\n\n\t\t\tawait getLibraries().getRedisService().setLastOnline(AuthEntityType.DELIVERY_BOY, rider._id.toString());\n\t\t}\n\n\t\tif (entity) {\n\t\t\tctx.entity = entity;\n\t\t\tctx.tokenType = TokenType.ACCESS;\n\t\t\tctx.usedRefreshToken = false;\n\t\t\tctx.tokenRenewed = false;\n\n\t\t\treturn next({ ctx });\n\t\t}\n\n\t\tif (!allowRefreshToken || !refreshToken) unauthorizedError('Invalid access token');\n\n\t\tconst renewalResult = await handleTokenRenewal(refreshToken);\n\n\t\tif (!renewalResult.success) {\n\t\t\tconst errorMessage =\n\t\t\t\trenewalResult.tokenStatus === 'revoked' ? 'Refresh token has been revoked' : 'Invalid refresh token';\n\n\t\t\tunauthorizedError(errorMessage);\n\t\t}\n\n\t\tif (!entityTypes.includes(renewalResult.entity!.type)) unauthorizedError('Unauthorized entity type');\n\n\t\tctx.entity = renewalResult.entity;\n\t\tctx.tokenType = TokenType.REFRESH;\n\t\tctx.usedRefreshToken = true;\n\n\t\tctx.tokenRenewed = renewalResult.tokenStatus === 'expired';\n\n\t\tif (autoRefresh && renewalResult.newTokens) {\n\t\t\tif (renewalResult.newTokens.accessToken) {\n\t\t\t\tctx.res.setHeader('X-New-Access-Token', renewalResult.newTokens.accessToken);\n\t\t\t}\n\n\t\t\tif (renewalResult.newTokens.refreshToken) {\n\t\t\t\tctx.res.setHeader('X-New-Refresh-Token', renewalResult.newTokens.refreshToken);\n\t\t\t}\n\t\t}\n\n\t\treturn next({ ctx });\n\t});\n}\n"]}
|
package/dist/types/README.md
CHANGED
package/dist/types/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { FilterQuery, PopulateOptions, Model } from 'mongoose';
|
|
2
|
+
import { ClientSession, FilterQuery, PopulateOptions, Model } from 'mongoose';
|
|
3
3
|
import { AnyParamConstructor } from '@typegoose/typegoose/lib/types';
|
|
4
4
|
import { DocumentType, ReturnModelType } from '@typegoose/typegoose';
|
|
5
5
|
import { CustomPaginatedResponse, CustomPaginatorOptions } from './validation';
|
|
@@ -72,7 +72,7 @@ export declare function createPaginatorObject<T extends AnyParamConstructor<any>
|
|
|
72
72
|
};
|
|
73
73
|
items: any[];
|
|
74
74
|
}>;
|
|
75
|
-
export declare function paginateAggregation(model: any, pipeline: any[], page?: number, size?: number, sort?: any, populateOptions?: any): Promise<{
|
|
75
|
+
export declare function paginateAggregation(model: any, pipeline: any[], page?: number, size?: number, sort?: any, populateOptions?: any, session?: ClientSession | null): Promise<{
|
|
76
76
|
metadata: {
|
|
77
77
|
page: number;
|
|
78
78
|
size: number;
|
|
@@ -62,12 +62,12 @@ function createPaginatorObject(model, itemSchema, transformFn) {
|
|
|
62
62
|
return PaginatedSchema.parse(paginatedResult);
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
async function paginateAggregation(model, pipeline, page = 1, size = 10, sort, populateOptions) {
|
|
65
|
+
async function paginateAggregation(model, pipeline, page = 1, size = 10, sort, populateOptions, session) {
|
|
66
66
|
const skip = (page - 1) * size;
|
|
67
67
|
const limit = size;
|
|
68
68
|
const pipelineWithCount = [...pipeline];
|
|
69
69
|
pipelineWithCount.push({ $count: 'totalCount' });
|
|
70
|
-
const totalCountResult = await model.aggregate(pipelineWithCount).exec();
|
|
70
|
+
const totalCountResult = await model.aggregate(pipelineWithCount).session(session ?? null).exec();
|
|
71
71
|
const totalElements = totalCountResult?.[0]?.totalCount || 0;
|
|
72
72
|
const totalPages = Math.ceil(totalElements / size);
|
|
73
73
|
const paginatedPipeline = [...pipeline];
|
|
@@ -76,7 +76,7 @@ async function paginateAggregation(model, pipeline, page = 1, size = 10, sort, p
|
|
|
76
76
|
}
|
|
77
77
|
paginatedPipeline.push({ $skip: skip });
|
|
78
78
|
paginatedPipeline.push({ $limit: limit });
|
|
79
|
-
const data = await model.aggregate(paginatedPipeline).exec();
|
|
79
|
+
const data = await model.aggregate(paginatedPipeline).session(session ?? null).exec();
|
|
80
80
|
const populatedData = populateOptions ? await model.populate(data, populateOptions) : data;
|
|
81
81
|
return {
|
|
82
82
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"/","sources":["utilities/pagination.ts"],"names":[],"mappings":";;AASA,sDAYC;AAuED,4EAWC;AASD,sDAmBC;AACD,kDAiDC;AAKD,wCA4CC;AAtOD,6BAAwB;AASxB,SAAgB,qBAAqB,CAAgC,UAAoB;IACxF,OAAO,OAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,OAAC;aACT,MAAM,CAAC;YACP,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;YAChB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;YAChB,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;YACzB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE;SACtB,CAAC;aACD,QAAQ,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QACpF,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,UAAU,CAAC;KAC1B,CAAC,CAAC;AACJ,CAAC;AAiCD,KAAK,UAAU,aAAa,CAC3B,KAAyB,EACzB,OAA4B;IAE5B,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEjF,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/B,IAAI,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjE,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAQ,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACd,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEnD,OAAO;QACN,QAAQ,EAAE;YACT,IAAI;YACJ,IAAI;YACJ,aAAa;YACb,UAAU;SACV;QACD,SAAS,EAAE,SAAyC;KACpD,CAAC;AACH,CAAC;AAQD,SAAgB,gCAAgC,CAC/C,KAAyB;IAEzB,OAAO,KAAK,UAAU,QAAQ,CAAC,OAA4B;QAC1D,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAEpE,OAAO;YACN,QAAQ;YACR,SAAS;SACT,CAAC;IACH,CAAC,CAAC;AACH,CAAC;AASD,SAAgB,qBAAqB,CACpC,KAAyB,EACzB,UAAwB,EACxB,WAAkE;IAElE,MAAM,eAAe,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAE1D,OAAO,KAAK,UAAU,QAAQ,CAAC,OAA4B;QAC1D,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEnE,MAAM,eAAe,GAAG;YACvB,QAAQ;YACR,KAAK;SACL,CAAC;QAEF,OAAO,eAAe,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC/C,CAAC,CAAC;AACH,CAAC;AACM,KAAK,UAAU,mBAAmB,CACxC,KAAU,EACV,QAAe,EACf,OAAe,CAAC,EAChB,OAAe,EAAE,EACjB,IAAU,EACV,eAAqB;IAGrB,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC;IAGnB,MAAM,iBAAiB,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IAGxC,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAGjD,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAGnD,MAAM,iBAAiB,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IAExC,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAG1C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC;IAG7D,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAG3F,OAAO;QACN,QAAQ,EAAE;YACT,IAAI;YACJ,IAAI;YACJ,aAAa;YACb,UAAU;SACV;QACD,SAAS,EAAE,aAAa;KACxB,CAAC;AACH,CAAC;AAKM,KAAK,UAAU,cAAc,CACnC,OAAkC,EAClC,KAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAElE,IAAI,SAAS,GAAQ,EAAE,CAAC;IACxB,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,IAAI,KAAK,EAAE,CAAC;QAEX,IAAI,KAAK,GAAQ,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAEjD,IAAI,OAAO,CAAC,MAAM;YAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,QAAQ;YAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAe,CAAC,CAAC;QACtE,IAAI,OAAO,CAAC,IAAI;YAAE,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEnD,aAAa,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAChE,SAAS,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAEzC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;QACrC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACtE,CAAC;IAGD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEnD,OAAO;QACN,SAAS;QACT,QAAQ,EAAE;YACT,IAAI;YACJ,IAAI;YACJ,aAAa;YACb,UAAU;SACV;KACD,CAAC;AACH,CAAC","sourcesContent":["import { z } from 'zod';\nimport { FilterQuery, PopulateOptions, Model } from 'mongoose';\nimport { AnyParamConstructor } from '@typegoose/typegoose/lib/types';\nimport { DocumentType, ReturnModelType } from '@typegoose/typegoose';\nimport { CustomPaginatedResponse, CustomPaginatorOptions } from './validation';\n\n/**\n * A helper to create a paginated Zod schema for an item type.\n */\nexport function createPaginatedSchema<ItemType extends z.ZodTypeAny>(itemSchema: ItemType) {\n\treturn z.object({\n\t\tmetadata: z\n\t\t\t.object({\n\t\t\t\tpage: z.number(),\n\t\t\t\tsize: z.number(),\n\t\t\t\ttotalElements: z.number(),\n\t\t\t\ttotalPages: z.number(),\n\t\t\t})\n\t\t\t.catchall(z.string().or(z.number()).or(z.boolean()).or(z.null()).or(z.undefined())),\n\t\titems: z.array(itemSchema),\n\t});\n}\n\nexport interface RawPaginatedResult<T extends AnyParamConstructor<any>> {\n\tmetadata: {\n\t\tpage: number;\n\t\tsize: number;\n\t\ttotalElements: number;\n\t\ttotalPages: number;\n\t\t// Use a more specific index signature\n\t\t[key: string]: string | number | boolean | null | undefined;\n\t};\n\tdocuments: DocumentType<T>[];\n}\n\n/**\n * The common pagination options.\n */\nexport interface PaginatorOptions<TClass extends AnyParamConstructor<any>> {\n\tquery?: FilterQuery<DocumentType<TClass>>;\n\tpage?: number;\n\tsize?: number;\n\tsort?: Record<string, 1 | -1>;\n\tselect?: Record<string, 0 | 1>;\n\tpopulate?: PopulateOptions | (PopulateOptions | string)[];\n}\n\n/**\n * This internal function wraps the common query logic:\n * - filter, page, size, sort, populate\n * - fetch documents, count documents\n * - compute totalPages\n * Returns a standard object with `metadata` & `documents`.\n */\nasync function _basePaginate<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>,\n\toptions: PaginatorOptions<T>\n): Promise<RawPaginatedResult<T>> {\n\tconst { query = {}, page = 1, size = 10, sort = {}, select, populate } = options;\n\n\tconst skip = (page - 1) * size;\n\n\tlet result = model.find(query).sort(sort).skip(skip).limit(size);\n\n\tif (select) {\n\t\tresult = result.select(select) as any;\n\t}\n\tif (populate) {\n\t\tresult = result.populate(populate);\n\t}\n\n\tconst [documents, totalElements] = await Promise.all([result.exec(), model.countDocuments(query)]);\n\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\treturn {\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t\tdocuments: documents as unknown as DocumentType<T>[],\n\t};\n}\n\n/**\n * Creates a paginator returning raw documents.\n *\n * @param model The Typegoose model\n * @returns A function that, when passed `PaginatorOptions`, returns raw docs + metadata.\n */\nexport function createRawDocumentPaginatorObject<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>\n) {\n\treturn async function paginate(options: PaginatorOptions<T>): Promise<RawPaginatedResult<T>> {\n\t\tconst { metadata, documents } = await _basePaginate(model, options);\n\n\t\treturn {\n\t\t\tmetadata,\n\t\t\tdocuments,\n\t\t};\n\t};\n}\n\n/**\n * Creates a paginator that returns Zod-validated items.\n *\n * @param model The Typegoose model\n * @param itemSchema A Zod schema describing the shape of each item\n * @param transformFn Optional transform function to convert raw doc -> item\n */\nexport function createPaginatorObject<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>,\n\titemSchema: z.ZodTypeAny,\n\ttransformFn?: (doc: DocumentType<T>) => z.infer<typeof itemSchema>\n) {\n\tconst PaginatedSchema = createPaginatedSchema(itemSchema);\n\n\treturn async function paginate(options: PaginatorOptions<T>) {\n\t\tconst { metadata, documents } = await _basePaginate(model, options);\n\n\t\tconst items = transformFn ? documents.map(transformFn) : documents;\n\n\t\tconst paginatedResult = {\n\t\t\tmetadata,\n\t\t\titems,\n\t\t};\n\n\t\treturn PaginatedSchema.parse(paginatedResult);\n\t};\n}\nexport async function paginateAggregation(\n\tmodel: any,\n\tpipeline: any[],\n\tpage: number = 1,\n\tsize: number = 10,\n\tsort?: any,\n\tpopulateOptions?: any\n) {\n\t// Calculate skip and limit based on the page and size\n\tconst skip = (page - 1) * size;\n\tconst limit = size;\n\n\t// Copy the pipeline to avoid mutation\n\tconst pipelineWithCount = [...pipeline];\n\n\t// Step 1: Calculate total count\n\tpipelineWithCount.push({ $count: 'totalCount' });\n\n\t// Step 2: Execute to get total count\n\tconst totalCountResult = await model.aggregate(pipelineWithCount).exec();\n\tconst totalElements = totalCountResult?.[0]?.totalCount || 0;\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\t// Step 3: Apply pagination to the original pipeline\n\tconst paginatedPipeline = [...pipeline];\n\n\tif (sort && Object.keys(sort).length > 0) {\n\t\tpaginatedPipeline.push({ $sort: sort });\n\t}\n\n\tpaginatedPipeline.push({ $skip: skip });\n\tpaginatedPipeline.push({ $limit: limit });\n\n\t// Step 4: Execute the paginated pipeline\n\tconst data = await model.aggregate(paginatedPipeline).exec();\n\n\t// Step 5: Optional populate\n\tconst populatedData = populateOptions ? await model.populate(data, populateOptions) : data;\n\n\t// Return the paginated data with metadata\n\treturn {\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t\tdocuments: populatedData,\n\t};\n}\n\n/**\n * Generic pagination function for Mongoose models or arrays\n */\nexport async function customPaginate<T extends Document>(\n\toptions: CustomPaginatorOptions<T>,\n\tmodel?: Model<T>\n): Promise<CustomPaginatedResponse<any>> {\n\tconst page = options.page && options.page > 0 ? options.page : 1;\n\tconst size = options.size && options.size > 0 ? options.size : 10;\n\n\tlet documents: T[] = [];\n\tlet totalElements = 0;\n\n\tif (model) {\n\t\t// Mongoose query\n\t\tlet query: any = model.find(options.query || {});\n\n\t\tif (options.select) query = query.select(options.select);\n\t\tif (options.populate) query = query.populate(options.populate as any);\n\t\tif (options.sort) query = query.sort(options.sort);\n\n\t\ttotalElements = await model.countDocuments(options.query || {});\n\t\tdocuments = await query.skip((page - 1) * size).limit(size);\n\t} else if (Array.isArray(options.query)) {\n\t\t// In-memory array\n\t\ttotalElements = options.query.length;\n\t\tdocuments = options.query.slice((page - 1) * size, page * size);\n\t} else {\n\t\tthrow new Error('Either a Mongoose model or array must be provided');\n\t}\n\n\t// Apply optional transform\n\tif (options.transform) {\n\t\tdocuments = documents.map(options.transform);\n\t}\n\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\treturn {\n\t\tdocuments,\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"/","sources":["utilities/pagination.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { ClientSession, FilterQuery, PopulateOptions, Model } from 'mongoose';\nimport { AnyParamConstructor } from '@typegoose/typegoose/lib/types';\nimport { DocumentType, ReturnModelType } from '@typegoose/typegoose';\nimport { CustomPaginatedResponse, CustomPaginatorOptions } from './validation';\n\n/**\n * A helper to create a paginated Zod schema for an item type.\n */\nexport function createPaginatedSchema<ItemType extends z.ZodTypeAny>(itemSchema: ItemType) {\n\treturn z.object({\n\t\tmetadata: z\n\t\t\t.object({\n\t\t\t\tpage: z.number(),\n\t\t\t\tsize: z.number(),\n\t\t\t\ttotalElements: z.number(),\n\t\t\t\ttotalPages: z.number(),\n\t\t\t})\n\t\t\t.catchall(z.string().or(z.number()).or(z.boolean()).or(z.null()).or(z.undefined())),\n\t\titems: z.array(itemSchema),\n\t});\n}\n\nexport interface RawPaginatedResult<T extends AnyParamConstructor<any>> {\n\tmetadata: {\n\t\tpage: number;\n\t\tsize: number;\n\t\ttotalElements: number;\n\t\ttotalPages: number;\n\t\t// Use a more specific index signature\n\t\t[key: string]: string | number | boolean | null | undefined;\n\t};\n\tdocuments: DocumentType<T>[];\n}\n\n/**\n * The common pagination options.\n */\nexport interface PaginatorOptions<TClass extends AnyParamConstructor<any>> {\n\tquery?: FilterQuery<DocumentType<TClass>>;\n\tpage?: number;\n\tsize?: number;\n\tsort?: Record<string, 1 | -1>;\n\tselect?: Record<string, 0 | 1>;\n\tpopulate?: PopulateOptions | (PopulateOptions | string)[];\n}\n\n/**\n * This internal function wraps the common query logic:\n * - filter, page, size, sort, populate\n * - fetch documents, count documents\n * - compute totalPages\n * Returns a standard object with `metadata` & `documents`.\n */\nasync function _basePaginate<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>,\n\toptions: PaginatorOptions<T>\n): Promise<RawPaginatedResult<T>> {\n\tconst { query = {}, page = 1, size = 10, sort = {}, select, populate } = options;\n\n\tconst skip = (page - 1) * size;\n\n\tlet result = model.find(query).sort(sort).skip(skip).limit(size);\n\n\tif (select) {\n\t\tresult = result.select(select) as any;\n\t}\n\tif (populate) {\n\t\tresult = result.populate(populate);\n\t}\n\n\tconst [documents, totalElements] = await Promise.all([result.exec(), model.countDocuments(query)]);\n\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\treturn {\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t\tdocuments: documents as unknown as DocumentType<T>[],\n\t};\n}\n\n/**\n * Creates a paginator returning raw documents.\n *\n * @param model The Typegoose model\n * @returns A function that, when passed `PaginatorOptions`, returns raw docs + metadata.\n */\nexport function createRawDocumentPaginatorObject<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>\n) {\n\treturn async function paginate(options: PaginatorOptions<T>): Promise<RawPaginatedResult<T>> {\n\t\tconst { metadata, documents } = await _basePaginate(model, options);\n\n\t\treturn {\n\t\t\tmetadata,\n\t\t\tdocuments,\n\t\t};\n\t};\n}\n\n/**\n * Creates a paginator that returns Zod-validated items.\n *\n * @param model The Typegoose model\n * @param itemSchema A Zod schema describing the shape of each item\n * @param transformFn Optional transform function to convert raw doc -> item\n */\nexport function createPaginatorObject<T extends AnyParamConstructor<any>>(\n\tmodel: ReturnModelType<T>,\n\titemSchema: z.ZodTypeAny,\n\ttransformFn?: (doc: DocumentType<T>) => z.infer<typeof itemSchema>\n) {\n\tconst PaginatedSchema = createPaginatedSchema(itemSchema);\n\n\treturn async function paginate(options: PaginatorOptions<T>) {\n\t\tconst { metadata, documents } = await _basePaginate(model, options);\n\n\t\tconst items = transformFn ? documents.map(transformFn) : documents;\n\n\t\tconst paginatedResult = {\n\t\t\tmetadata,\n\t\t\titems,\n\t\t};\n\n\t\treturn PaginatedSchema.parse(paginatedResult);\n\t};\n}\nexport async function paginateAggregation(\n\tmodel: any,\n\tpipeline: any[],\n\tpage: number = 1,\n\tsize: number = 10,\n\tsort?: any,\n\tpopulateOptions?: any,\n\tsession?: ClientSession | null\n) {\n\t// Calculate skip and limit based on the page and size\n\tconst skip = (page - 1) * size;\n\tconst limit = size;\n\n\t// Copy the pipeline to avoid mutation\n\tconst pipelineWithCount = [...pipeline];\n\n\t// Step 1: Calculate total count\n\tpipelineWithCount.push({ $count: 'totalCount' });\n\n\t// Step 2: Execute to get total count\n\tconst totalCountResult = await model.aggregate(pipelineWithCount).session(session ?? null).exec();\n\tconst totalElements = totalCountResult?.[0]?.totalCount || 0;\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\t// Step 3: Apply pagination to the original pipeline\n\tconst paginatedPipeline = [...pipeline];\n\n\tif (sort && Object.keys(sort).length > 0) {\n\t\tpaginatedPipeline.push({ $sort: sort });\n\t}\n\n\tpaginatedPipeline.push({ $skip: skip });\n\tpaginatedPipeline.push({ $limit: limit });\n\n\t// Step 4: Execute the paginated pipeline\n\tconst data = await model.aggregate(paginatedPipeline).session(session ?? null).exec();\n\n\t// Step 5: Optional populate\n\tconst populatedData = populateOptions ? await model.populate(data, populateOptions) : data;\n\n\t// Return the paginated data with metadata\n\treturn {\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t\tdocuments: populatedData,\n\t};\n}\n\n/**\n * Generic pagination function for Mongoose models or arrays\n */\nexport async function customPaginate<T extends Document>(\n\toptions: CustomPaginatorOptions<T>,\n\tmodel?: Model<T>\n): Promise<CustomPaginatedResponse<any>> {\n\tconst page = options.page && options.page > 0 ? options.page : 1;\n\tconst size = options.size && options.size > 0 ? options.size : 10;\n\n\tlet documents: T[] = [];\n\tlet totalElements = 0;\n\n\tif (model) {\n\t\t// Mongoose query\n\t\tlet query: any = model.find(options.query || {});\n\n\t\tif (options.select) query = query.select(options.select);\n\t\tif (options.populate) query = query.populate(options.populate as any);\n\t\tif (options.sort) query = query.sort(options.sort);\n\n\t\ttotalElements = await model.countDocuments(options.query || {});\n\t\tdocuments = await query.skip((page - 1) * size).limit(size);\n\t} else if (Array.isArray(options.query)) {\n\t\t// In-memory array\n\t\ttotalElements = options.query.length;\n\t\tdocuments = options.query.slice((page - 1) * size, page * size);\n\t} else {\n\t\tthrow new Error('Either a Mongoose model or array must be provided');\n\t}\n\n\t// Apply optional transform\n\tif (options.transform) {\n\t\tdocuments = documents.map(options.transform);\n\t}\n\n\tconst totalPages = Math.ceil(totalElements / size);\n\n\treturn {\n\t\tdocuments,\n\t\tmetadata: {\n\t\t\tpage,\n\t\t\tsize,\n\t\t\ttotalElements,\n\t\t\ttotalPages,\n\t\t},\n\t};\n}\n"]}
|