diff --git a/example_config.json b/example_config.json index ea0b29d..88374b8 100644 --- a/example_config.json +++ b/example_config.json @@ -179,7 +179,7 @@ ] }, "apis": { - "aggregate->users->get_aggregation": { + "aggregateAPIs->users->id->getAggregation": { "webhooks": [ { "url": "https://example.com", diff --git a/src/routes/aggregate/aggregate.ts b/src/routes/aggregate/aggregate.ts index 5457d7c..284698f 100644 --- a/src/routes/aggregate/aggregate.ts +++ b/src/routes/aggregate/aggregate.ts @@ -35,22 +35,22 @@ export function registerAggregateRoutes( f => f.supportedAggregation && f.supportedAggregation.length > 0, ); - // construct the api identifier - const apiIdentifier = `aggregate->${model.name}->get_aggregation`; - - // extract the api configs based on the api identifier - const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; - const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; - // calculating the authroization based on auth flag, it can be true - // if the api level auth is enabled, or if the app level auth is enabled - const authorization = - config.apis?.[apiIdentifier]?.authorization ?? - config.auth?.enableAuth ?? - false; - // for each aggregatable field, we create a GET route // //aggregation/ for (const field of aggregatableFields) { + // construct the api identifier + const apiIdentifier = `aggregateAPIs->${model.name}->${field.name}->getAggregation`; + + // extract the api configs based on the api identifier + const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; + const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; + // calculating the authroization based on auth flag, it can be true + // if the api level auth is enabled, or if the app level auth is enabled + const authorization = + config.apis?.[apiIdentifier]?.authorization ?? + config.auth?.enableAuth ?? + false; + const operations = field.supportedAggregation!; // generating the schema for the route @@ -66,6 +66,7 @@ export function registerAggregateRoutes( `/${model.name}/aggregation/${field.name}`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { // doing validation here because we need the user for SSP if (config.auth?.enableAuth && authorization) { diff --git a/src/routes/auth/change-password.ts b/src/routes/auth/change-password.ts index cb982a3..94809bb 100644 --- a/src/routes/auth/change-password.ts +++ b/src/routes/auth/change-password.ts @@ -34,6 +34,7 @@ export function registerChangePasswordRoute( '/auth/change-password', { schema, + config: {apiIdentifier: `authAPIs->${modelName}->all->changePassword`}, preHandler: async (request: FastifyRequest, reply: FastifyReply) => { try { await request.jwtVerify(); diff --git a/src/routes/auth/login.ts b/src/routes/auth/login.ts index 202efca..70f02af 100644 --- a/src/routes/auth/login.ts +++ b/src/routes/auth/login.ts @@ -50,7 +50,10 @@ export function registerLoginRoute( app.post( '/auth/login', - {schema}, + { + schema, + config: {apiIdentifier: `authAPIs->${modelName}->all->login`}, + }, async (request: FastifyRequest<{Body: ModelBody}>, reply: FastifyReply) => { const {[usernameColumn]: username, [passwordColumn]: password} = request.body; diff --git a/src/routes/auth/registration.ts b/src/routes/auth/registration.ts index 77bbc6a..88e71fc 100644 --- a/src/routes/auth/registration.ts +++ b/src/routes/auth/registration.ts @@ -68,7 +68,10 @@ export function registerRegistrationRoute( app.post( '/auth/register', - {schema}, + { + schema, + config: {apiIdentifier: `authAPIs->${modelName}->all->registration`}, + }, async (request: FastifyRequest<{Body: ModelBody}>, reply: FastifyReply) => { const incomingBody = request.body; diff --git a/src/routes/custom-queries/custom-queries.ts b/src/routes/custom-queries/custom-queries.ts index a3b652a..302d6b8 100644 --- a/src/routes/custom-queries/custom-queries.ts +++ b/src/routes/custom-queries/custom-queries.ts @@ -87,7 +87,7 @@ export function registerCustomQueryRoutes( const bodyProperties: Record = {}; // constructing the api identifier - const apiIdentifier = `customAPIs->customQueries->${cq.name}`; + const apiIdentifier = `customAPIs->customQueries->all->${cq.name}`; // extracting the api configs based on the api identifier const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; @@ -231,6 +231,7 @@ export function registerCustomQueryRoutes( method: cq.method, url: routePath, schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/delete.ts b/src/routes/operations/delete.ts index b14c376..597d443 100644 --- a/src/routes/operations/delete.ts +++ b/src/routes/operations/delete.ts @@ -35,22 +35,21 @@ export function registerDeleteRoutes( f.supportedOperations?.includes('deletable'), ); - // constructing the api identifier - const apiIdentifier = `modelAPIs->delete->${model.name}`; - - // extracting the api configs based on the api identifier - const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; - const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; - - // calculating the authroization based on auth flag, it can be true - // if the api level auth is enabled, or if the app level auth is enabled - const authorization = - config.apis?.[apiIdentifier]?.authorization ?? - config.auth?.enableAuth ?? - false; - // If we have deletable fields, we register a DELETE route for each. for (const field of deletableFields) { + // constructing the api identifier + const apiIdentifier = `modelAPIs->${model.name}->${field.name}->delete`; + + // extracting the api configs based on the api identifier + const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; + const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; + + // calculating the authroization based on auth flag, it can be true + // if the api level auth is enabled, or if the app level auth is enabled + const authorization = + config.apis?.[apiIdentifier]?.authorization ?? + config.auth?.enableAuth ?? + false; // we map the data type of the field to a JSON schema type for validation const schema: Record = generateSchema( field, @@ -63,6 +62,7 @@ export function registerDeleteRoutes( `/${model.name}/${field.name}/:${field.name}`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/edit.ts b/src/routes/operations/edit.ts index 06bf66c..c1e9b60 100644 --- a/src/routes/operations/edit.ts +++ b/src/routes/operations/edit.ts @@ -38,21 +38,20 @@ export function registerEditRoutes( f.supportedOperations?.includes('editable'), ); - // constructing the api identifier - const apiIdentifier = `modelAPIs->edit->${model.name}`; - - // extracting the api configs based on the api identifier - const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; - const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; - - // calculating the authroization based on auth flag, it can be true - // if the api level auth is enabled, or if the app level auth is enabled - const authorization = - config.apis?.[apiIdentifier]?.authorization ?? - config.auth?.enableAuth ?? - false; - for (const field of editableFields) { + // constructing the api identifier + const apiIdentifier = `modelAPIs->${model.name}->${field.name}->edit`; + + // extracting the api configs based on the api identifier + const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; + const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; + + // calculating the authroization based on auth flag, it can be true + // if the api level auth is enabled, or if the app level auth is enabled + const authorization = + config.apis?.[apiIdentifier]?.authorization ?? + config.auth?.enableAuth ?? + false; const isUnique = field.primaryKey || field.unique; const paramSchema = mapDataTypeToJsonSchema(field.type); @@ -230,6 +229,7 @@ export function registerEditRoutes( `/${model.name}/${field.name}/:${field.name}`, { schema: buildRouteSchema('PATCH'), + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { @@ -268,6 +268,7 @@ export function registerEditRoutes( `/${model.name}/${field.name}/:${field.name}`, { schema: buildRouteSchema('PUT'), + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/get-all.ts b/src/routes/operations/get-all.ts index ad509a3..9cfcf13 100644 --- a/src/routes/operations/get-all.ts +++ b/src/routes/operations/get-all.ts @@ -36,7 +36,7 @@ export function registerGetAllRoutes( for (const model of models) { // constructing the api identifier - const apiIdentifier = `modelAPIs->getAll->${model.name}`; + const apiIdentifier = `modelAPIs->${model.name}->all->getAll`; // extracting the api configs based on the api identifier const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; @@ -59,6 +59,7 @@ export function registerGetAllRoutes( `/${model.name}/`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/index-route.ts b/src/routes/operations/index-route.ts index 496bdc4..7981d5e 100644 --- a/src/routes/operations/index-route.ts +++ b/src/routes/operations/index-route.ts @@ -43,24 +43,23 @@ export function registerIndexRoutes( ); }); - // constructing the api identifier - const apiIdentifier = `modelAPIs->index->${model.name}`; - - // extracting the api configs based on the api identifier - const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; - const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; - - // calculating the authroization based on auth flag, it can be true - // if the api level auth is enabled, or if the app level auth is enabled - const authorization = - config.apis?.[apiIdentifier]?.authorization ?? - config.auth?.enableAuth ?? - false; - // index apis means for these APIs, we can fetch data using the indexable fields // for example, if we have a field user_id in the users table, and it is indexed, // then we can fetch data using the user_id field like /user/ for (const field of indexFields) { + // constructing the api identifier + const apiIdentifier = `modelAPIs->${model.name}->${field.name}->index`; + + // extracting the api configs based on the api identifier + const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; + const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; + + // calculating the authroization based on auth flag, it can be true + // if the api level auth is enabled, or if the app level auth is enabled + const authorization = + config.apis?.[apiIdentifier]?.authorization ?? + config.auth?.enableAuth ?? + false; const { schema, isUnique, @@ -71,6 +70,7 @@ export function registerIndexRoutes( `/${model.name}/${field.name}/:${field.name}`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/post.ts b/src/routes/operations/post.ts index 80c976e..919ac22 100644 --- a/src/routes/operations/post.ts +++ b/src/routes/operations/post.ts @@ -28,7 +28,7 @@ export function registerPostRoutes( for (const model of models) { // constructing the api identifier - const apiIdentifier = `modelAPIs->insert->${model.name}`; + const apiIdentifier = `modelAPIs->${model.name}->all->insert`; // extracting the api configs based on the api identifier const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; @@ -54,6 +54,7 @@ export function registerPostRoutes( `/${model.name}/`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/routes/operations/search.ts b/src/routes/operations/search.ts index 66bf377..a6c0e69 100644 --- a/src/routes/operations/search.ts +++ b/src/routes/operations/search.ts @@ -38,21 +38,20 @@ export function registerSearchRoutes( f.supportedOperations?.includes('searchable'), ); - // constructing the api identifier - const apiIdentifier = `modelAPIs->search->${model.name}`; - - // extracting the api configs based on the api identifier - const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; - const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; + for (const field of searchableFields) { + // constructing the api identifier + const apiIdentifier = `modelAPIs->${model.name}->${field.name}->search`; - // calculating the authroization based on auth flag, it can be true - // if the api level auth is enabled, or if the app level auth is enabled - const authorization = - config.apis?.[apiIdentifier]?.authorization ?? - config.auth?.enableAuth ?? - false; + // extracting the api configs based on the api identifier + const webhookConfig = config.apis?.[apiIdentifier]?.webhooks ?? null; + const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? []; - for (const field of searchableFields) { + // calculating the authroization based on auth flag, it can be true + // if the api level auth is enabled, or if the app level auth is enabled + const authorization = + config.apis?.[apiIdentifier]?.authorization ?? + config.auth?.enableAuth ?? + false; // defining the primary search query parameter // for example if the field is "name", this will create "name_search" query parameter const schema: Record = generateSchema( @@ -66,6 +65,7 @@ export function registerSearchRoutes( `/${model.name}/search/${field.name}`, { schema, + config: {apiIdentifier}, preValidation: async (request, reply) => { if (config.auth?.enableAuth && authorization) { try { diff --git a/src/server.ts b/src/server.ts index 670a61d..0ff0114 100644 --- a/src/server.ts +++ b/src/server.ts @@ -106,6 +106,8 @@ export async function startServer( ? routeOptions.method.join('/') : routeOptions.method, url: routeOptions.url, + apiIdentifier: (routeOptions.config as {apiIdentifier?: string}) + ?.apiIdentifier, }); }); diff --git a/src/types/fastify.d.ts b/src/types/fastify.d.ts index 7690343..ba7b8a5 100644 --- a/src/types/fastify.d.ts +++ b/src/types/fastify.d.ts @@ -15,6 +15,10 @@ declare module '@fastify/jwt' { } declare module 'fastify' { + interface FastifyContextConfig { + apiIdentifier?: string; + } + interface FastifyInstance { db: DatabaseQuery; buildResponse: ( diff --git a/src/utils/config.ts b/src/utils/config.ts index 09891c0..bd77669 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -41,10 +41,10 @@ export function getAPIFromUniqueIdentifier( const parts = identifier.split('->'); if (parts[0] === 'customAPIs') { - if (parts[1] === 'customQueries') { + if (parts[1] === 'customQueries' && parts[2] === 'all') { const customQueries = config?.customAPIs?.customQueries ?? []; - return customQueries.find(cq => cq.name === parts[2]) ?? null; + return customQueries.find(cq => cq.name === parts[3]) ?? null; } } diff --git a/src/utils/welcome.ts b/src/utils/welcome.ts index 94da914..7c2320a 100644 --- a/src/utils/welcome.ts +++ b/src/utils/welcome.ts @@ -5,6 +5,7 @@ import {AppConfig} from '@/interfaces/config'; export interface RouteInfo { method: string; url: string; + apiIdentifier?: string; } const ROCKET_ASCII = ` @@ -151,7 +152,8 @@ export function showWelcomeScreen( // Filter routes const filteredRoutes = routes.filter(route => { const isHead = route.method.toUpperCase().split('/').includes('HEAD'); - const isStatic = route.url.includes('/static'); + const isStatic = + route.url.includes('/static') || route.url.includes('/docs'); return !isHead && !isStatic; }); @@ -172,7 +174,17 @@ export function showWelcomeScreen( Math.max(0, maxMethodLength - route.method.length), ); - console.log(' ' + coloredMethod + padding + chalk.white(` ${route.url}`)); + const identifier = route.apiIdentifier + ? chalk.gray(` [${route.apiIdentifier}]`) + : ''; + + console.log( + ' ' + + coloredMethod + + padding + + chalk.white(` ${route.url}`) + + identifier, + ); }); console.log('\n ' + chalk.gray('─────────────────────────────────────────')); diff --git a/src/validators/config/validate-apis.ts b/src/validators/config/validate-apis.ts index 2558de6..9712551 100644 --- a/src/validators/config/validate-apis.ts +++ b/src/validators/config/validate-apis.ts @@ -34,13 +34,13 @@ function validateApisConstraints(config: AppConfig): string[] { for (const key of keys) { const parts = key.split('->'); - if (parts.length !== 3) { + if (parts.length !== 4) { errors.push(`apis/${key}: invalid key format`); continue; } if (parts[0] === 'customAPIs') { - if (parts[1] === 'customQueries') { + if (parts[1] === 'all' && parts[2] === 'all') { const customQueryConfig = getAPIFromUniqueIdentifier(config, key); if (!customQueryConfig) { diff --git a/tests/routes/aggregate.test.ts b/tests/routes/aggregate.test.ts index 6a93b88..e0fff59 100644 --- a/tests/routes/aggregate.test.ts +++ b/tests/routes/aggregate.test.ts @@ -269,7 +269,7 @@ describe('test aggregate api', () => { describe('authentication', () => { const apisConfig = { - 'aggregate->sales->get_aggregation': { + 'aggregateAPIs->sales->amount->getAggregation': { authorization: true, }, }; diff --git a/tests/routes/custom-queries.test.ts b/tests/routes/custom-queries.test.ts index 79e1f00..0becf28 100644 --- a/tests/routes/custom-queries.test.ts +++ b/tests/routes/custom-queries.test.ts @@ -235,7 +235,7 @@ describe('test custom-queries api', () => { describe('authentication', () => { const apisConfig = { - 'customAPIs->customQueries->searchUsers': { + 'customAPIs->all->all->searchUsers': { authorization: true, }, }; diff --git a/tests/routes/delete.test.ts b/tests/routes/delete.test.ts index 608f0fb..e32f7b9 100644 --- a/tests/routes/delete.test.ts +++ b/tests/routes/delete.test.ts @@ -191,7 +191,7 @@ describe('test delete api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->delete->users': { + 'modelAPIs->users->id->delete': { authorization: true, }, }; diff --git a/tests/routes/edit.test.ts b/tests/routes/edit.test.ts index 14ff14c..167a14c 100644 --- a/tests/routes/edit.test.ts +++ b/tests/routes/edit.test.ts @@ -396,7 +396,7 @@ describe('test edit api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->edit->users': { + 'modelAPIs->users->id->edit': { authorization: true, }, }; diff --git a/tests/routes/get-all.test.ts b/tests/routes/get-all.test.ts index a82fe79..e199987 100644 --- a/tests/routes/get-all.test.ts +++ b/tests/routes/get-all.test.ts @@ -387,7 +387,7 @@ describe('test get-all api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->getAll->users': { + 'modelAPIs->users->all->getAll': { authorization: true, }, }; diff --git a/tests/routes/index-route.test.ts b/tests/routes/index-route.test.ts index e50e70b..5f0d7b6 100644 --- a/tests/routes/index-route.test.ts +++ b/tests/routes/index-route.test.ts @@ -561,7 +561,7 @@ describe('test index-route api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->index->users': { + 'modelAPIs->users->id->index': { authorization: true, }, }; diff --git a/tests/routes/post.test.ts b/tests/routes/post.test.ts index 58fa4a6..1f8bf94 100644 --- a/tests/routes/post.test.ts +++ b/tests/routes/post.test.ts @@ -196,7 +196,7 @@ describe('test post api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->insert->users': { + 'modelAPIs->users->all->insert': { authorization: true, }, }; diff --git a/tests/routes/search.test.ts b/tests/routes/search.test.ts index 393d4a5..447c28d 100644 --- a/tests/routes/search.test.ts +++ b/tests/routes/search.test.ts @@ -472,7 +472,7 @@ describe('test search api', () => { describe('authentication', () => { const apisConfig = { - 'modelAPIs->search->users': { + 'modelAPIs->users->name->search': { authorization: true, }, }; diff --git a/tests/utils/config.test.ts b/tests/utils/config.test.ts index d760898..bb4dead 100644 --- a/tests/utils/config.test.ts +++ b/tests/utils/config.test.ts @@ -71,7 +71,7 @@ describe('Config Utilities', () => { it('should return the correct custom query config for a valid identifier', () => { const result = getAPIFromUniqueIdentifier( mockConfig as AppConfig, - 'customAPIs->customQueries->get_users', + 'customAPIs->customQueries->all->get_users', ); expect(result).toEqual(mockConfig.customAPIs?.customQueries?.[0]); }); @@ -79,7 +79,7 @@ describe('Config Utilities', () => { it('should return null if the first part is not customAPIs', () => { const result = getAPIFromUniqueIdentifier( mockConfig as AppConfig, - 'modelAPIs->get-all->users', + 'modelAPIs->users->all->getAll', ); expect(result).toBeNull(); }); @@ -87,7 +87,7 @@ describe('Config Utilities', () => { it('should return null if the second part is not customQueries', () => { const result = getAPIFromUniqueIdentifier( mockConfig as AppConfig, - 'customAPIs->somethingElse->get_users', + 'customAPIs->somethingElse->all->get_users', ); expect(result).toBeNull(); }); @@ -95,7 +95,7 @@ describe('Config Utilities', () => { it('should return null if the custom query name is not found', () => { const result = getAPIFromUniqueIdentifier( mockConfig as AppConfig, - 'customAPIs->customQueries->non_existent', + 'customAPIs->customQueries->all->non_existent', ); expect(result).toBeNull(); }); @@ -103,7 +103,7 @@ describe('Config Utilities', () => { it('should return null if customQueries is missing in config', () => { const result = getAPIFromUniqueIdentifier( {} as AppConfig, - 'customAPIs->customQueries->get_users', + 'customAPIs->customQueries->all->get_users', ); expect(result).toBeNull(); }); diff --git a/tests/validators/config.test.ts b/tests/validators/config.test.ts index 42c7c3d..e768b9d 100644 --- a/tests/validators/config.test.ts +++ b/tests/validators/config.test.ts @@ -2209,7 +2209,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'invalid', @@ -2221,7 +2221,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/url must match pattern "^https?:\\/\\/"', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/url must match pattern "^https?:\\/\\/"', }, { name: 'data field type is not array', @@ -2235,7 +2235,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2247,7 +2247,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/data must be array', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/data must be array', }, { name: 'data field is empty array', @@ -2261,7 +2261,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2273,7 +2273,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/data must NOT have fewer than 1 items', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/data must NOT have fewer than 1 items', }, { name: 'data field contains invalid value', @@ -2287,7 +2287,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2299,7 +2299,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/data/1 must be equal to one of the allowed values', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/data/1 must be equal to one of the allowed values', }, { name: 'triggerOnRequest is not a boolean', @@ -2313,7 +2313,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2325,7 +2325,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/triggerOnRequest must be boolean', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/triggerOnRequest must be boolean', }, { name: 'triggerOnResponse is not a boolean', @@ -2339,7 +2339,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2352,7 +2352,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - '/apis/customAPIs->customQueries->sample_query/webhooks/0/triggerOnResponse must be boolean', + '/apis/customAPIs->customQueries->all->sample_query/webhooks/0/triggerOnResponse must be boolean', }, { name: 'triggerOnResponse or triggerOnRequest needs to be true, both cannot be false', @@ -2366,7 +2366,7 @@ describe('validateInvalidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2379,7 +2379,7 @@ describe('validateInvalidApisConfig', () => { }, }, expected: - 'apis/customAPIs->customQueries->sample_query/webhooks/0: webhook must have at least one of triggerOnRequest or triggerOnResponse', + 'apis/customAPIs->customQueries->all->sample_query/webhooks/0: webhook must have at least one of triggerOnRequest or triggerOnResponse', }, ])('Scenario: $name -> should throw: "$expected"', ({patch, expected}) => { const patchObj = patch as Record; @@ -2492,7 +2492,7 @@ describe('validateValidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2516,7 +2516,7 @@ describe('validateValidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2540,7 +2540,7 @@ describe('validateValidApisConfig', () => { }, ], apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { webhooks: [ { url: 'https://example.com', @@ -2903,18 +2903,19 @@ describe('validateInvalidModelAPIsConfig', () => { { name: 'invalid webhook for modelAPis', patch: { - 'modelAPIs->aggregate->users': 'invalid', + 'aggregateAPIs->users->id->getAggregation': 'invalid', }, - expected: '/apis/modelAPIs->aggregate->users must be object', + expected: '/apis/aggregateAPIs->users->id->getAggregation must be object', }, { name: 'invalid webhook conf', patch: { - 'modelAPIs->aggregate->users': { + 'aggregateAPIs->users->id->getAggregation': { webhooks: 'invalid', }, }, - expected: '/apis/modelAPIs->aggregate->users/webhooks must be array', + expected: + '/apis/aggregateAPIs->users->id->getAggregation/webhooks must be array', }, { name: 'invalid api key format', @@ -2935,7 +2936,7 @@ describe('validateInvalidModelAPIsConfig', () => { { name: 'invalid data resp cannot be used when triggerOnRequest is true', patch: { - 'modelAPIs->aggregate->users': { + 'aggregateAPIs->users->id->getAggregation': { webhooks: [ { url: 'https://google.com', @@ -2947,7 +2948,7 @@ describe('validateInvalidModelAPIsConfig', () => { }, }, expected: - 'apis/modelAPIs->aggregate->users/webhooks/0: data resp cannot be used when triggerOnRequest is true', + 'apis/aggregateAPIs->users->id->getAggregation/webhooks/0: data resp cannot be used when triggerOnRequest is true', }, ])('Scenario: $name -> should throw error', ({patch, expected}) => { const config = { @@ -2966,7 +2967,7 @@ describe('validateValidModelAPIsConfig', () => { { name: 'valid modelAPIs', patch: { - 'modelAPIs->aggregate->users': { + 'aggregateAPIs->users->id->getAggregation': { webhooks: [ { url: 'https://google.com', @@ -2976,7 +2977,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->delete->users': { + 'modelAPIs->users->id->delete': { webhooks: [ { url: 'https://google.com', @@ -2986,7 +2987,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->edit->users': { + 'modelAPIs->users->id->edit': { webhooks: [ { url: 'https://google.com', @@ -2996,7 +2997,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->getAll->users': { + 'modelAPIs->users->all->getAll': { webhooks: [ { url: 'https://google.com', @@ -3006,7 +3007,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->index->users': { + 'modelAPIs->users->id->index': { webhooks: [ { url: 'https://google.com', @@ -3016,7 +3017,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->insert->users': { + 'modelAPIs->users->all->insert': { webhooks: [ { url: 'https://google.com', @@ -3026,7 +3027,7 @@ describe('validateValidModelAPIsConfig', () => { }, ], }, - 'modelAPIs->search->users': { + 'modelAPIs->users->id->search': { webhooks: [ { url: 'https://google.com', @@ -3260,31 +3261,31 @@ describe('validateInvalidSspConfig', () => { name: 'invalid ssp config param type', patch: {ssp: [{paramType: 'invalid', paramName: 'id', value: '1'}]}, expected: - '/apis/customAPIs->customQueries->sample_query/ssp/0/paramType must be equal to one of the allowed values', + '/apis/customAPIs->customQueries->all->sample_query/ssp/0/paramType must be equal to one of the allowed values', }, { name: 'invalid ssp config param type', patch: {ssp: [{paramType: 132, paramName: 'id', value: '1'}]}, expected: - '/apis/customAPIs->customQueries->sample_query/ssp/0/paramType must be equal to one of the allowed values', + '/apis/customAPIs->customQueries->all->sample_query/ssp/0/paramType must be equal to one of the allowed values', }, { name: 'invalid ssp config param name', patch: {ssp: [{paramType: 'body', paramName: 123, value: '1'}]}, expected: - '/apis/customAPIs->customQueries->sample_query/ssp/0/paramName must be string', + '/apis/customAPIs->customQueries->all->sample_query/ssp/0/paramName must be string', }, { name: 'invalid ssp config param value', patch: {ssp: [{paramType: 'body', paramName: 'id', value: null}]}, expected: - '/apis/customAPIs->customQueries->sample_query/ssp/0/value must be string', + '/apis/customAPIs->customQueries->all->sample_query/ssp/0/value must be string', }, ])('Scenario: $name -> should throw error', ({patch, expected}) => { const config = { ...validBaseConfig, apis: { - 'customAPIs->customQueries->sample_query': { + 'customAPIs->customQueries->all->sample_query': { ssp: patch.ssp, }, }, @@ -3323,7 +3324,7 @@ describe('validateValidSspConfig', () => { const config = { ...validBaseConfig, apis: { - 'modelAPIs->getAll->posts': { + 'modelAPIs->posts->all->getAll': { ssp: patch.ssp, }, }, @@ -3339,18 +3340,18 @@ describe('validateInvalidAuthorizationConfig', () => { { name: 'invalid authorization config', patch: {authorization: 'wrong'}, - expected: 'modelAPIs->getAll->posts/authorization must be boolean', + expected: 'modelAPIs->posts->all->getAll/authorization must be boolean', }, { name: 'invalid authorization config', patch: {authorization: null}, - expected: 'modelAPIs->getAll->posts/authorization must be boolean', + expected: 'modelAPIs->posts->all->getAll/authorization must be boolean', }, ])('Scenario: $name -> should throw error', ({patch, expected}) => { const config = { ...validBaseConfig, apis: { - 'modelAPIs->getAll->posts': { + 'modelAPIs->posts->all->getAll': { authorization: patch.authorization, }, }, @@ -3369,7 +3370,7 @@ describe('validateInvalidAuthorizationConfig', () => { name: 'authorization is enabled when authentication is disabled', patch: {authorization: true}, expected: - 'apis/modelAPIs->getAll->posts/authorization: authorization is only allowed when auth is enabled', + 'apis/modelAPIs->posts->all->getAll/authorization: authorization is only allowed when auth is enabled', }, ])('Scenario: $name -> should throw error', ({patch, expected}) => { const config = { @@ -3380,7 +3381,7 @@ describe('validateInvalidAuthorizationConfig', () => { apiKey: '1234', }, apis: { - 'modelAPIs->getAll->posts': { + 'modelAPIs->posts->all->getAll': { authorization: patch.authorization, }, }, @@ -3412,7 +3413,7 @@ describe('validateValidAuthorizationConfig', () => { apiKey: '1234', }, apis: { - 'modelAPIs->getAll->posts': { + 'modelAPIs->posts->all->getAll': { authorization: patch.authorization, }, },