diff --git a/sunbird-self-creation-portal/constants/common.js b/sunbird-self-creation-portal/constants/common.js new file mode 100644 index 00000000..6f08648c --- /dev/null +++ b/sunbird-self-creation-portal/constants/common.js @@ -0,0 +1,20 @@ +/** + * name : constants/common.js + * author : Priyanka Pradeep + * Date : 23 - Apr - 2025 + * Description : All commonly used constants through out the package + */ + +module.exports = { + PROJECT_STATUS_PUBLISHED: 'published', + PROJECT_PROJECTION_FIELDS: ['_id', 'title', 'createdBy', 'createdAt', 'description'], + RESOURCE_TYPE_PROJECT: 'projects', + PROJECT_TRANSFORM_KEYS: { + _id: 'id', + createdAt: 'created_at', + createdBy: 'created_by', + }, + AUTH_TOKEN_KEY: 'X-auth-token', + HEADER_CONTENT_TYPE: 'content-type', + INTERNAL_ACCESS_TOKEN: 'internal-access-token', +} diff --git a/sunbird-self-creation-portal/constants/routes.js b/sunbird-self-creation-portal/constants/routes.js new file mode 100644 index 00000000..b404d53d --- /dev/null +++ b/sunbird-self-creation-portal/constants/routes.js @@ -0,0 +1,1073 @@ +module.exports = { + routes: [ + { + sourceRoute: '/scp/v1/permissions/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/config/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/config/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/form/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/create', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/form/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/read', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/form/read/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/read/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/form/update', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/update', + type: 'PUT', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/form/update/:id', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/update/:id', + type: 'PUT', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/create', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/read', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/organization-extensions/updateConfig/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/organization-extensions/updateConfig/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/organization-extensions/createConfig', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/organization-extensions/createConfig', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/delete', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/delete', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entity-types/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/delete/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/create', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/read', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/read/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/read/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/update', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/update', + type: 'PUT', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/update/:id', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/update/:id', + type: 'PUT', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/delete', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/delete', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/entities/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/delete/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/details/', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/details/', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/details/:id', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/cloud-services/file/fetchJsonFromCloud', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/fetchJsonFromCloud', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/reviewerList', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/reviewerList', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/reviewerList', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/reviewerList', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/update/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/permissions/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/create', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/permissions/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/permissions/getPermissions', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/getPermissions', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/permissions/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/delete/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/modules/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/create', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/modules/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/modules/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/modules/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/delete/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/certificates/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/certificates/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/certificates/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/certificates/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/certificates/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/certificates/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/resource/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/resource/upForReview', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/upForReview', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/create/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/create/:role_id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/list', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/list', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/submitForReview/', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/submitForReview/', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/projects/submitForReview/:resource_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/submitForReview/:resource_id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/comments/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/comments/update', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/comments/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/comments/update/:id', + type: 'DELETE', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/update/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/reviews/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/reviews/start/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/start/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/reviews/approve/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/approve/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/reviews/rejectOrReport/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/rejectOrReport/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/cloud-services/file/getSignedUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/getSignedUrl', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/cloud-services/file/getDownloadableUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/getDownloadableUrl', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/resource/getPublishedResources', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/getPublishedResources', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/getDataManagers', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/getDataManagers', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/update/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/update/:id', + type: 'DELETE', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/list', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/details/:id', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/rollouts/publish/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/rollouts/publish/:id', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/resource/publishCallback', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/publishCallback', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/update', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/update/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/update/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/addResources/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/addResources/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/removeResources/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/removeResources/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/details/:id', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/submitForReview/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/submitForReview/:id', + type: 'POST', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/getProgramManagers', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/getProgramManagers', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/scp/v1/programs/publish/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/programs/publish/:id', + type: 'GET', + }, + service: 'scp', + }, + { + sourceRoute: '/project/v1/cloud-services/files/download', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/download', + type: 'GET', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/cloud-services/files/preSignedUrls', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/preSignedUrls', + type: 'POST', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/cloud-services/files/getDownloadableUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/getDownloadableUrl', + type: 'POST', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/project/templates/details', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/details', + type: 'GET', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/project/templates/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/details/:id', + type: 'GET', + }, + service: 'project', + }, + + { + sourceRoute: '/project/v1/admin/dbFind', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/dbFind', + type: 'POST', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/admin/dbFind/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/dbFind/:id', + type: 'POST', + }, + service: 'project', + }, + { + sourceRoute: '/project/v1/scp/publishTemplateAndTasks', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/scp/publishTemplateAndTasks', + type: 'POST', + }, + service: 'project', + }, + { + sourceRoute: '/notification/v1/email/send', + type: 'POST', + targetRoute: { + path: '/notification/v1/email/send', + type: 'POST', + }, + service: 'notification', + }, + { + sourceRoute: '/scheduler/jobs/create', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/create', + type: 'POST', + }, + service: 'scheduler', + }, + { + sourceRoute: '/scheduler/jobs/updateDelay', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/updateDelay', + type: 'POST', + }, + service: 'scheduler', + }, + { + sourceRoute: '/scheduler/jobs/remove', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/remove', + type: 'POST', + }, + service: 'scheduler', + }, + { + sourceRoute: '/scheduler/jobs/list', + type: 'GET', + targetRoute: { + path: '/scheduler/jobs/list', + type: 'GET', + }, + service: 'scheduler', + }, + { + sourceRoute: '/scheduler/jobs/purge', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/purge', + type: 'POST', + }, + service: 'scheduler', + }, + { + sourceRoute: '/user/v1/user/read', + type: 'GET', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/api/user/v2/read', + type: 'GET', + functionName: 'profileRead', + }, + service: 'user', + }, + { + sourceRoute: '/user/v1/user/read/:id', + type: 'GET', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/api/user/v5/read/:id', + type: 'GET', + functionName: 'profileRead', + }, + service: 'user', + }, + { + sourceRoute: '/entity-management/v1/entities/find', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/find', + type: 'POST', + }, + service: 'entity', + }, + { + sourceRoute: '/entity-management/v1/entityTypes/find', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/find', + type: 'POST', + }, + service: 'entity', + }, + { + sourceRoute: '/user/v1/organization/read', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/api/org/v1/read', + type: 'POST', + functionName: 'readOrganization', + }, + service: 'user', + }, + { + sourceRoute: '/user/v1/account/search', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/api/user/v1/search', + type: 'POST', + functionName: 'accountList', + }, + service: 'user', + }, + { + sourceRoute: '/user/v1/organization/list', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/api/org/v1/search', + type: 'POST', + functionName: 'organizationList', + }, + service: 'user', + }, + ], +} diff --git a/sunbird-self-creation-portal/controllers/customHandler.js b/sunbird-self-creation-portal/controllers/customHandler.js new file mode 100644 index 00000000..365e6d46 --- /dev/null +++ b/sunbird-self-creation-portal/controllers/customHandler.js @@ -0,0 +1,12 @@ +const routesConfig = require('../constants/routes') +const scpController = require('./scp') + +const customHandler = async (req, res) => { + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await scpController[selectedRouteConfig.targetRoute.functionName](req, res, selectedRouteConfig) +} + +const customHandlerController = { + customHandler, +} +module.exports = customHandlerController diff --git a/sunbird-self-creation-portal/controllers/orchestrationController.js b/sunbird-self-creation-portal/controllers/orchestrationController.js new file mode 100644 index 00000000..94ddd8e4 --- /dev/null +++ b/sunbird-self-creation-portal/controllers/orchestrationController.js @@ -0,0 +1,18 @@ +const routesConfig = require('../constants/routes') +const scpController = require('../controllers/scp') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.service, req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find( + (obj) => req.service === obj.service && obj.sourceRoute === req.sourceRoute + ) + if (selectedRouteConfig && selectedRouteConfig.service) { + req['baseUrl'] = process.env[`${selectedRouteConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + return await scpController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/sunbird-self-creation-portal/controllers/scp.js b/sunbird-self-creation-portal/controllers/scp.js new file mode 100644 index 00000000..0d4604c0 --- /dev/null +++ b/sunbird-self-creation-portal/controllers/scp.js @@ -0,0 +1,489 @@ +/** + * name : controllers/scp.js + * author : Priyanka Pradeep + * Date : 24-Apr-2025 + * Description : Orchestration controller for scp + */ + +const routeConfigs = require('../constants/routes') +const requesters = require('../utils/requester') +const common = require('../constants/common') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const { pathParamSetter } = require('../utils/pathParamSetter') + +const fetchLocationDetails = async (req, res, selectedConfig) => { + try { + // validate the body, if body is not present throw error + if (!(Object.keys(req['body']).length > 0) || !(Object.keys(req['body']['query']).length > 0)) { + if (process.env.DEBUG_MODE == 'true') { + console.log('req.body cannot be empty') + } + res.status(500).json('Internal Server Error') + } + + // if passed api config has service value defined. We are getting the baseURl of that service from env of Interface service + if (selectedConfig.service) { + req['baseUrl'] = process.env[`${selectedConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + let targetedRoutePath = selectedConfig.targetRoute.path + const params = matchPathsAndExtractParams(selectedConfig.sourceRoute, req.originalUrl) + const targetRoute = pathParamSetter(targetedRoutePath, params) + + // prepare req.body to match sunbird location API req.body + let bodyData = {} + bodyData['request'] = {} + bodyData['request']['filters'] = {} + if ('_id' in req.body.query) { + if (typeof req.body.query._id == 'object') { + bodyData['request']['filters'] = { + id: req.body.query._id['$in'], + } + } else { + bodyData['request']['filters'] = { + id: req.body.query._id, + } + } + } + if ('code' in req.body.query) { + if (typeof req.body.query.code == 'object') { + bodyData['request']['filters'] = { + code: req.body.query.code['$in'], + } + } else { + bodyData['request']['filters'] = { + code: req.body.query.code, + } + } + } + + if ('metaInformation.name' in req.body.query) { + bodyData['request']['filters'] = { + name: req.body.query['metaInformation.name'], + } + } + + if ('entityType' in req.body.query) { + bodyData['request']['filters']['type'] = req.body.query.entityType['$in'] + } + + // fetch location details + let locationDetails = await requesters.post(req.baseUrl, targetRoute, bodyData, { + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, + }) + + // confirm success response + if (locationDetails.responseCode === 'OK') { + locationDetails['result'] = locationDetails.result.response + locationDetails['status'] = 200 + + // modify the response to be compatible with EP + if (locationDetails.result.length > 0) { + locationDetails.result.map((location) => { + location['_id'] = location.id + location['registryDetails'] = { + code: location.code, + } + location['metaInformation'] = { + name: location.name, + } + location['entityType'] = location.type + }) + } + } else { + if (process.env.DEBUG_MODE == 'true') { + console.log('location API error', JSON.stringify(locationDetails)) + } + res.json(locationDetails) + } + + res.json(locationDetails) + } catch (error) { + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching location details:', error) + } + res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const profileRead = async (req, res, selectedConfig) => { + try { + // if passed api config has service value defined. We are getting the baseURl of that service from env of Interface service + if (selectedConfig.service) { + req['baseUrl'] = process.env[`${selectedConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + + let targetedRoutePath = selectedConfig.targetRoute.path + console.log(targetedRoutePath, 'targetedRoutePath') + const params = matchPathsAndExtractParams(selectedConfig.sourceRoute, req.originalUrl) + const targetRoute = pathParamSetter(targetedRoutePath, params) + + // Fetch user profile details + let userProfileData = await requesters.get( + req.baseUrl, + targetRoute, + { + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, + 'x-authenticated-user-token': req.headers['x-auth-token'], + }, + req.body + ) + + if (process.env.DEBUG_MODE == 'true') { + console.log('RESPONSE:', userProfileData) + console.log('RESPONSE.RESULT:', userProfileData?.result) + } + + // confirm success response + if (userProfileData.responseCode === 'OK') { + userProfileData['result'] = userProfileData.result.response + //generate role data for SCP + if (userProfileData.result.roles && userProfileData.result.roles.length > 0) { + // Create a new user_roles array with transformed data + userProfileData.result.user_roles = userProfileData.result.roles.map((eachRole) => { + return { + label: eachRole.role + .toLowerCase() + .split('_') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '), + title: eachRole.role, + } + }) + } + + if (userProfileData.result.organisations && userProfileData.result.organisations.length > 0) { + userProfileData['result'].organization_id = userProfileData.result?.organisations[0].organisationId + } + + ;(userProfileData['result'].name = userProfileData.userName), + (userProfileData['result'].email = userProfileData.recoveryEmail) + res.json(userProfileData) + } else { + if (process.env.DEBUG_MODE == 'true') { + console.log('profileRead error', JSON.stringify(userProfileData)) + } + res.json(userProfileData) + } + } catch (error) { + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching user details:', error) + } + res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const readOrganization = async (req, res, selectedConfig) => { + // Constructing the request body to fetch organization details + const body = { + request: { + // Extracting organisation ID or code from query parameters + organisationId: req.query.organisation_id || req.query.organisation_code, + }, + } + + try { + // If the selected API config has a defined service, set the base URL dynamically + if (selectedConfig.service) { + req['baseUrl'] = process.env[`${selectedConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + + // Sending a POST request to the target service API + const response = await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, body, { + 'device-info': req.headers['device-info'], // Passing device info from request headers + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, // Authorization token from environment variables + }) + + // Logging response in debug mode for troubleshooting + if (process.env.DEBUG_MODE == 'true') { + console.log('RESPONSE:', response) + console.log('RESPONSE.RESULT:', response?.result) + } + + // Constructing the final response object with relevant data + const responseData = { + result: { + id: response.result.response.id, + name: response.result.response.orgName, + code: response.result.response.orgCode, + related_orgs: [], // Placeholder for related organizations (if needed in future) + }, + responseCode: response.responseCode, // Including response code from API response + } + + // Sending the final response to the client + return res.json(responseData) + } catch (error) { + // Logging error details in debug mode if enabled + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching organization details:', error) + } + // Returning a generic internal server error response + return res.status(500).json({ error: 'Internal Server Error' }) + } +} + +/** + * This function calls sunbird's location search api + * @param {Object} bodyData - Body data for api call + * @param {*} baseUrl - Base url + * @returns + */ +const getLocationDetails = async (bodyData, baseUrl) => { + try { + // setting API end point and making the call + const apiEndpoint = '/api/data/v1/location/search' + const locationDetails = await requesters.post(baseUrl, apiEndpoint, bodyData, { + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, + }) + + // Verifying the response + if (locationDetails.responseCode === 'OK' && locationDetails.result?.response?.length > 0) { + return locationDetails.result.response + } else { + if (process.env.DEBUG_MODE === 'true') { + console.log('Location API error', JSON.stringify(locationDetails)) + } + return [] + } + } catch (error) { + if (process.env.DEBUG_MODE === 'true') { + console.error('Error in getLocationDetails:', error) + } + return [] + } +} + +const readUserById = async (req, res, selectedConfig) => { + const userId = req.params.id + try { + console.log('read by userid') + const targetRoute1 = selectedConfig.targetRoute.paths[0].path + const targetRoute2 = selectedConfig.targetRoute.paths[1] + + const userResponse = await requesters.get(req.baseUrl, targetRoute1, req.headers, { + id: userId, + }) + + if (process.env.DEBUG_MODE == 'true') { + console.log('READ API response status:', userResponse.params.status) + console.log(' user read API resp == ', JSON.stringify(userResponse)) + console.log(' API Response', JSON.stringify(userResponse)) + } + if (userResponse.params.status == 'FAILED') { + if (process.env.DEBUG_MODE == 'true') { + console.log('userResponse.params.status ', userResponse.params.status) + console.log('userResponse.params.status ', JSON.stringify(userResponse)) + } + return res.send(userResponse) + } + const enrollmentResponse = await requesters.get(targetRoute2.baseUrl, targetRoute2.path, req.headers, { + id: userId, + }) + + if (process.env.DEBUG_MODE == 'true') { + console.log('CALLING COMPETENCY ') + } + + let competencyIds = [] + if (enrollmentResponse.result && enrollmentResponse.result.courses) { + competencyIds = getCompetencyIds(enrollmentResponse.result.courses || []) + } + + if (process.env.DEBUG_MODE == 'true') { + console.log('competencyIds ==', competencyIds) + console.log('userResponse profile response ', userResponse) + } + const responseData = processUserResponse(userResponse) + responseData.result.competency = competencyIds + + if (process.env.DEBUG_MODE == 'true') { + console.log('RESPONSE DATA: ', JSON.stringify(responseData, null, 3)) + } + responseData.responseCode = 'OK' + return res.send(responseData) + } catch (error) { + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching user details:', error) + } + return res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const processUserSearchResponse = (content) => { + if (process.env.DEBUG_MODE == 'true') { + // console.log(content,'============ user Details ====================') + } + return { + result: content.map((user) => { + return { + id: user.id, + image: user?.profileImageUrl, + name: user?.firstName, + organization: { + id: user?.organisations?.[0]?.organisationId, + name: user?.organisations?.[0]?.orgName, + }, + email: user?.primaryEmail, + } + }), + } +} + +const accountList = async (req, res, selectedConfig) => { + const body = { + request: { + filters: {}, + }, + } + try { + const userIds = req.body.user_ids + + if (selectedConfig.service) { + req['baseUrl'] = process.env[`${selectedConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + + if (userIds) { + body.request.filters.id = userIds + } + + if (req.query.organisation_id) { + body.request.filters['organisations.organisationId'] = req.query.organisation_id + } + + if (req.query.organisation_code) { + body.request.filters['organisations.organisationId'] = req.query.organisation_code + } + + if (req.query.type && req.query.type != 'all') { + body.request.filters['roles.role'] = req.query.type + } + + if (req.query.limit) { + body.request['limit'] = parseInt(req.query.limit) + } + + if (process.env.DEBUG_MODE == 'true') { + console.log('------- ================ -------', req.body) + console.log(body, 'Req body') + } + + // Format token removes "Bearer " if present at the start + const authToken = req.headers['x-auth-token'] || '' + const cleanToken = authToken.replace(/^bearer\s+/i, '') + + const userSearchResponse = await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, body, { + 'device-info': req.headers['device-info'], // Passing device info from request headers + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, // Authorization token from environment variables + 'x-authenticated-user-token': cleanToken, + }) + console.log(userSearchResponse, 'userSearchResponse') + console.log(cleanToken, body, 'Req body') + + if (userSearchResponse?.responseCode != 'OK') { + throw new Error('User Search Failed') + } + + let data = processUserSearchResponse(userSearchResponse.result.response.content) || [] + + return res.json({ + result: { + data: data?.result, + count: data?.result?.length, + }, + }) + } catch (error) { + console.log(error, 'error') + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching user details:', error) + } + return res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const organizationList = async (req, res, selectedConfig) => { + console.log('came to org list') + const body = { + request: { + filters: {}, + }, + } + try { + const orgIds = req.body.organizationIds + + if (selectedConfig.service) { + req['baseUrl'] = process.env[`${selectedConfig.service.toUpperCase()}_SERVICE_BASE_URL`] + } + + if (orgIds) { + body.request.filters.id = orgIds + } + + if (req.query.organization_id) { + body.request.filters.id = req.query.organization_id + } + + if (req.query.limit) { + body.request['limit'] = parseInt(req.query.limit) + } + + if (process.env.DEBUG_MODE == 'true') { + console.log('------- ================ -------', req.body) + console.log(body, 'Req body') + } + + // Format token removes "Bearer " if present at the start + const authToken = req.headers['x-auth-token'] || '' + const cleanToken = authToken.replace(/^bearer\s+/i, '') + + const orgSearchResponse = await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, body, { + 'device-info': req.headers['device-info'], // Passing device info from request headers + Authorization: `Bearer ${process.env.SUNBIRD_BEARER_TOKEN}`, // Authorization token from environment variables + 'x-authenticated-user-token': cleanToken, + }) + console.log(orgSearchResponse, 'orgSearchResponse') + console.log(cleanToken, body, 'Req body') + + if (orgSearchResponse?.responseCode != 'OK') { + throw new Error('User Search Failed') + } + + let data = processOrgSearchResponse(orgSearchResponse.result.response.content) || [] + // return res.json(orgSearchResponse) + return res.json({ result: data?.result }) + } catch (error) { + console.log(error, 'error') + if (process.env.DEBUG_MODE == 'true') { + console.error('Error fetching user details:', error) + } + return res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const processOrgSearchResponse = (content) => { + if (process.env.DEBUG_MODE == 'true') { + // console.log(content,'============ org Details ====================') + } + return { + result: content.map((org) => { + console.log(org, 'org') + return { + id: org.id, + name: org?.orgName, + code: org?.orgCode, + description: '', + } + }), + } +} + +scpController = { + readUserById, + profileRead, + fetchLocationDetails, + readOrganization, + accountList, + organizationList, + getLocationDetails, +} + +module.exports = scpController diff --git a/sunbird-self-creation-portal/index.js b/sunbird-self-creation-portal/index.js new file mode 100644 index 00000000..13e1fc05 --- /dev/null +++ b/sunbird-self-creation-portal/index.js @@ -0,0 +1,37 @@ +const express = require('express') +const router = express.Router() +const routes = require('./constants/routes') +const packageRouter = require('./router') + +const getDependencies = () => { + return ['kafka', 'kafka-connect', 'redis'] +} + +const getPackageMeta = () => { + return { + basePackageName: 'scp', + packageName: 'sunbird-self-creation-portal', + } +} + +const createPackage = (options) => { + return { + router: () => { + console.log('router') + }, + endpoints: [], + dependencies: [], + } +} + +router.get('/', (req, res) => { + res.send('Hello, world! From Elevate Project') +}) + +module.exports = { + dependencies: getDependencies(), + routes, + createPackage, + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/sunbird-self-creation-portal/package.json b/sunbird-self-creation-portal/package.json new file mode 100644 index 00000000..96ebc8b0 --- /dev/null +++ b/sunbird-self-creation-portal/package.json @@ -0,0 +1,18 @@ +{ + "name": "sunbird-self-creation-portal", + "version": "1.0.2", + "description": "Sunbird Self Creation Portal Package", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Priyanka Pradeep", + "license": "ISC", + "dependencies": { + "axios": "^1.4.0", + "express": "^4.18.2", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" + } +} diff --git a/sunbird-self-creation-portal/router/index.js b/sunbird-self-creation-portal/router/index.js new file mode 100644 index 00000000..29e2b5a4 --- /dev/null +++ b/sunbird-self-creation-portal/router/index.js @@ -0,0 +1,14 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const { customHandler } = require('../controllers/customHandler') + +const packageRouter = async (req, res, responses) => { + let response + if (req.orchestrated) response = await orchestrationHandler(req, res, responses) + else if (req.requiresCustomHandling) { + response = await customHandler(req, res) + } else response = await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter \ No newline at end of file diff --git a/sunbird-self-creation-portal/utils/pathParamSetter.js b/sunbird-self-creation-portal/utils/pathParamSetter.js new file mode 100644 index 00000000..130b1fe5 --- /dev/null +++ b/sunbird-self-creation-portal/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/sunbird-self-creation-portal/utils/patternMatcher.js b/sunbird-self-creation-portal/utils/patternMatcher.js new file mode 100644 index 00000000..cc70b819 --- /dev/null +++ b/sunbird-self-creation-portal/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9-]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} \ No newline at end of file diff --git a/sunbird-self-creation-portal/utils/requestParser.js b/sunbird-self-creation-portal/utils/requestParser.js new file mode 100644 index 00000000..ecd12e5a --- /dev/null +++ b/sunbird-self-creation-portal/utils/requestParser.js @@ -0,0 +1,6 @@ +const _ = require('lodash') + +// exports.transformUpdateUserBody = (requestBody) => { +// const allowedKeys = ['name', 'email', 'image', 'location', 'about', 'preferred_language'] +// return _.pick(requestBody, allowedKeys) +// } diff --git a/sunbird-self-creation-portal/utils/requester.js b/sunbird-self-creation-portal/utils/requester.js new file mode 100644 index 00000000..9a872be9 --- /dev/null +++ b/sunbird-self-creation-portal/utils/requester.js @@ -0,0 +1,144 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + if(route.service){ + req['baseUrl'] = process.env[`${route.service.toUpperCase()}_SERVICE_BASE_URL`] + } + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + console.log(params,'params') + const targetRoute = pathParamSetter(route.targetRoute.path, params) + console.log(route.targetRoute.path, params,'route.targetRoute.path, params') + console.log(targetRoute,'targetRoute') + console.log(req.baseUrl,'req.baseUrl') + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) +} +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + + const options = { + method: 'PATCH', + headers: headers, + body: JSON.stringify(requestBody), + } + + const response = await fetch(url, options) + + const data = await response.json() + return data + } catch (error) { + console.error(error) + throw error + } +} +const axiosPatch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + console.log(url, requestBody) + const config = { + headers: headers, + } + axios + .patch(url, requestBody, config) + .then((response) => { + // Handle the successful response here + console.log('PATCH request successful:', response.data) + return response.data + }) + .catch((error) => { + // Handle any errors that occurred during the PATCH request + console.error('Error making PATCH request:', error) + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error('Error making PATCH request:', error) + } +} + +const get = (baseUrl, route, headers, requestBody = {}) => { + const url = baseUrl + route + const options = { + headers, + data: requestBody + }; + + return axios + .get(url, options) // Use POST to send body data + .then((response) => response.data) + .catch((error) => { + console.error('Error fetching data:', error) + if (error.response) { + return error.response + } + return error + }) +} + +const requesters = { + passThroughRequester, + post, + patch, + axiosPatch, + get +} + +module.exports = requesters \ No newline at end of file