diff --git a/.gitignore b/.gitignore index 40b878db..a0d218e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -node_modules/ \ No newline at end of file +node_modules +dist +.env \ No newline at end of file diff --git a/.sequelizerc b/.sequelizerc new file mode 100644 index 00000000..409a4bed --- /dev/null +++ b/.sequelizerc @@ -0,0 +1,8 @@ +const path = require("path"); + +module.exports = { + config: path.resolve("config", "database.js"), + "models-path": path.resolve("db", "models"), + "seeders-path": path.resolve("db", "seeders"), + "migrations-path": path.resolve("db", "migrations"), +}; diff --git a/config/database.js b/config/database.js new file mode 100644 index 00000000..bed84df2 --- /dev/null +++ b/config/database.js @@ -0,0 +1,11 @@ +require("dotenv").config(); + +module.exports = { + development: { + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + dialect: process.env.DB_DIALECT, + }, +}; diff --git a/controllers/BaseController.js b/controllers/BaseController.js new file mode 100644 index 00000000..5c61f7b7 --- /dev/null +++ b/controllers/BaseController.js @@ -0,0 +1,18 @@ +class BaseController { + constructor(model) { + this.model = model; + } + + /* All controllers that extend this BASE controller will have access to the below function **/ + async getAll(req, res) { + try { + console.log("hello world!"); + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } +} + +module.exports = BaseController; diff --git a/controllers/BenefitController.js b/controllers/BenefitController.js new file mode 100644 index 00000000..0479532a --- /dev/null +++ b/controllers/BenefitController.js @@ -0,0 +1,12 @@ +const BaseController = require("./BaseController"); + +class BenefitController extends BaseController { + constructor(model) { + super(model); + } +} + +// allow users to read info, and select data only. +// user cannot add, edit or delete benefits. + +module.exports = BenefitController; diff --git a/controllers/EmployerController.js b/controllers/EmployerController.js new file mode 100644 index 00000000..3032e8aa --- /dev/null +++ b/controllers/EmployerController.js @@ -0,0 +1,204 @@ +const BaseController = require("./BaseController"); + +class EmployerController extends BaseController { + constructor(model, jobListingModel, benefitModel, applicationModel) { + super(model); + this.jobListingModel = jobListingModel; + this.benefitModel = benefitModel; + this.applicationModel = applicationModel; + } + + // Create employer + async addEmployer(req, res) { + const { + firstName, + lastName, + companyName, + email, + photo, + description, + mission_statement, + headquarters, + phone, + } = req.body; + try { + // Create new employer + const newEmployer = await this.model.create({ + firstName: firstName, + lastName: lastName, + companyName: companyName, + email: email, + photo: photo, + description: description, + mission_statement: mission_statement, + headquarters: headquarters, + phone: phone, + }); + // Respond with new employer + return res.json(newEmployer); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + // Edit and Update Employer + async updateEmployer(req, res) { + const { + firstName, + lastName, + companyName, + email, + photo, + description, + mission_statement, + headquarters, + phone, + } = req.body; + const { employerId } = req.params; + //if employerID /= in the list of employers, should throw error and not be able to update + + try { + let employer_data = await this.model.findOne({ + where: { id: employerId }, + }); + if (employer_data == null) { + throw new Error( + "Employer you are trying to edit does not exist in the database." + ); + } + await this.model.update( + { + firstName: firstName, + lastName: lastName, + companyName: companyName, + email: email, + photo: photo, + description: description, + mission_statement: mission_statement, + headquarters: headquarters, + phone: phone, + }, + { + where: { + id: employerId, + }, + } + ); + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + // <------------------------ JOB LISTING ------------------------ > + + async addJobListing(req, res) { + const { employerId } = req.params; + const { + jobTitle, + description, + jobResponsibility, + skillSet, + applicationStartDate, + applicationEndDate, + } = req.body; + + console.log(req.body); + try { + //tag to employerID + const newJobListing = await this.jobListingModel.create({ + jobTitle: jobTitle, + description: description, + jobResponsibility: jobResponsibility, + skillSet: skillSet, + applicationStartDate: applicationStartDate, + applicationEndDate: applicationEndDate, + employerId: employerId, + }); + // Respond with the new work experience + { + const { employerId } = req.params; + const { benefit1, benefit2, benefit3 } = req.body; + + try { + // Check if the talent exists + console.log("req.body", req.body); + const employer = await this.model.findByPk(employerId); + if (!employer) { + return res + .status(404) + .json({ error: true, msg: "Employer not found" }); + } + // Create a new benefit and associate it with the talent + const addJobListingBenefit = await this.benefitModel.findAll({ + where: { + id: [benefit1, benefit2, benefit3], + }, + }); + await newJobListing.setBenefits(addJobListingBenefit); + // Respond with the newly created benefit + return res.json(addJobListingBenefit); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getJobListing(req, res) { + console.log("getJobListing is being called"); + const { employerId } = req.params; + try { + //tag to talent ID + const jobListing = await this.jobListingModel.findAll({ + where: { + employerId: employerId, + }, + }); + // Respond with the new work experience + return res.json(jobListing); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getOneJobListingApps(req, res) { + console.log("req.params in getOneJobListing:", req.params); + const { employerId, jobListingId } = req.params; + + try { + //tag to talent ID + const jobListing = await this.jobListingModel.findByPk(jobListingId); + + const appsForJobListing = await jobListing.getApplications(); + console.log("i am apps for job listing", appsForJobListing); + + console.log("jobListing", jobListing); + console.log("applications for job listing", appsForJobListing); + const response = { + applications: appsForJobListing, + jobListing: jobListing, + }; + + return res.json(response); + } catch (err) { + console.log("err", err); + return res.status(400).json({ error: true, msg: err }); + } + } + //return res.json(jobListing); + //get all applications relating to the job listing. + //-> get the id of all applications that have a specific job listing id + //use stuff from the documentation +} + +//Employer Dashboard should get all job listings posted by the employer. +//Clicking on a job listing should bring the employer to a page where they can reject or accept applications associated with the job listing. + +// get all user info under base controller +// delete is not required - user can't delete profile + +module.exports = EmployerController; diff --git a/controllers/TalentController.js b/controllers/TalentController.js new file mode 100644 index 00000000..a123ca5e --- /dev/null +++ b/controllers/TalentController.js @@ -0,0 +1,777 @@ +const { application } = require("express"); +const talent = require("../db/models/talent"); +const BaseController = require("./BaseController"); + +class TalentController extends BaseController { + constructor( + model, + talentResumeModel, + talentWorkExperienceModel, + talentSkillSetModel, + talentEducationModel, + benefitModel, + employerModel, + jobListing, + application + ) { + super(model); + this.talentResumeModel = talentResumeModel; + this.talentWorkExperienceModel = talentWorkExperienceModel; + this.talentSkillSetModel = talentSkillSetModel; + this.talentEducationModel = talentEducationModel; + this.benefitModel = benefitModel; + this.employerModel = employerModel; + this.jobListingModel = jobListing; + this.applicationModel = application; + } + + // Create talent + async addTalent(req, res) { + const { firstName, lastName, email, photo } = req.body; + try { + // Create new talent + const newTalent = await this.model.create({ + firstName: firstName, + lastName: lastName, + email: email, + photo: photo, + }); + // Respond with new talent + return res.json(newTalent); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + // Edit and Update Talent + async updateTalent(req, res) { + const { firstName, lastName, email, photo } = req.body; + const { talentId } = req.params; + try { + await this.model.update( + { + firstName: firstName, + lastName: lastName, + email: email, + photo: photo, + }, + { + where: { + id: talentId, + }, + } + ); + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async editTalentName(req, res) { + const { talentId } = req.params; + const { userFirstName, userLastName } = req.body; + try { + console.log("EDITTT NAME"); + console.log("NAME", userFirstName); + const updatedTalent = await this.model.update( + { + firstName: userFirstName, + lastName: userLastName, + }, + { + where: { + id: talentId, + }, + } + ); + return res.json(updatedTalent); + } catch (err) { + console.error("Error updating talent:", err); + return res + .status(400) + .json({ error: true, msg: "Failed to update talent" }); + } + } + + // <------------------------ RESUME ------------------------ > + + async addResume(req, res) { + const { talentId } = req.params; + const { location, industry, title, objective } = req.body; + try { + //tag to talent ID + const newResume = await this.talentResumeModel.create({ + location: location, + title: title, + industry: industry, + objective: objective, + talentId: talentId, + }); + // Respond with the new work experience + return res.json(newResume); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getResume(req, res) { + const { talentId } = req.params; + try { + //tag to talent ID + const resume = await this.talentResumeModel.findAll({ + where: { + talentId: talentId, + }, + }); + // Respond with the new work experience + return res.json(resume); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + // Edit and Update Resume + async updateResume(req, res) { + const { talentId } = req.params; + const { location, title, industry, objective } = req.body; + try { + // Check if talent resume exists + const existingResume = await this.talentResumeModel.findOne({ + where: { + talentId: talentId, + }, + }); + + if (!existingResume) { + return res.status(404).json({ error: true, msg: "Resume not found" }); + } + + // Update the resume + await existingResume.update({ + location: location || existingResume.location, + title: title || existingResume.title, + industry: industry || existingResume.industry, + objective: objective || existingResume.objective, + }); + + // Fetch the updated resume + const updatedResume = await this.talentResumeModel.findOne({ + where: { + talentId: talentId, + }, + }); + + return res.json(updatedResume); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + // <------------------------ WORK EXPERIENCE ------------------------ > + + async addWorkExperience(req, res) { + const { talentId } = req.params; + const { + companyName, + position, + responsibility, + startMonth, + startYear, + endMonth, + endYear, + } = req.body; + try { + //tag to talent ID + const newWorkExperience = await this.talentWorkExperienceModel.create({ + companyName: companyName, + position: position, + responsibility: responsibility, + startMonth: startMonth, + startYear: startYear, + endMonth: endMonth, + endYear: endYear, + talentId: talentId, + }); + // Respond with the new work experience + return res.json(newWorkExperience); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getWorkExperiences(req, res) { + const { talentId } = req.params; + try { + //tag to talent ID + const workExperiences = await this.talentWorkExperienceModel.findAll({ + where: { + talentId: talentId, + }, + }); + // Respond with the new work experience + return res.json(workExperiences); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + //update work experience + async updateWorkExp(req, res) { + //check if it's an array, same name as Frontend + const { workExpData } = req.body; + try { + console.log("Request to update work experience"); + console.log(req.body); + + // Iterate over each provided work experience and update it + for (const workExp of workExpData) { + await this.talentWorkExperienceModel.update( + { + companyName: workExp.companyName, + position: workExp.position, + responsibility: workExp.responsibility, + startMonth: workExp.startMonth, + startYear: workExp.startYear, + endMonth: workExp.endMonth, + endYear: workExp.endYear, + }, + //pull workexp ID instead of talentId + { + where: { id: workExp.id }, + } + ); + + console.log(`Work experience updated`); + } + + console.log("All work exp updated"); + + return res.status(200).json({ + success: true, + message: "Work experiences updated successfully", + }); + } catch (err) { + console.error("Error updating work experiences:", err); + return res.status(400).json({ error: true, msg: err }); + } + } + + // async updateWorkExp(req, res) { + // const { talentId } = req.params; + // const { + // companyName, + // position, + // responsibility, + // startMonth, + // startYear, + // endMonth, + // endYear, + // } = req.body; + // try { + // console.log("request to update work experience"); + // console.log(req.body); + // // Check if talent resume exists + // const existingWorkExp = await this.talentWorkExperienceModel.findOne({ + // where: { + // talentId: talentId, + // //try passing workexpID instead + // }, + // }); + + // if (!existingWorkExp) { + // return res.status(404).json({ error: true, msg: "data not found" }); + // } + + // console.log("work exp found"); + + // // Update the resume + // await existingWorkExp.update({ + // companyName: companyName || existingWorkExp.companyName, + // position: position || existingWorkExp.position, + // responsibility: responsibility || existingWorkExp.responsibility, + // startMonth: startMonth || existingWorkExp.startMonth, + // startYear: startYear || existingWorkExp.startYear, + // endMonth: endMonth || existingWorkExp.endMonth, + // endYear: endYear || existingWorkExp.endYear, + // }); + + // console.log("new work exp updated"); + + // // Fetch the updated work exp + // const updatedWorkExp = await this.talentWorkExperienceModel.findOne({ + // where: { + // talentId: talentId, + // }, + // }); + + // console.log("all work exp updated"); + + // return res.json(updatedWorkExp); + // } catch (err) { + // return res.status(400).json({ error: true, msg: err }); + // } + // } + + async deleteWorkExp(req, res) { + const { workExpID } = req.params; + try { + // Check if the skill set exists + const workExp = await this.talentWorkExperienceModel.findOne({ + where: { + id: workExpID, + }, + }); + + if (!workExp) { + return res.status(404).json({ error: true, msg: "Work not found" }); + } + + // Delete the skill set + await workExp.destroy(); + + return res.json({ + success: true, + msg: "Work exp set deleted successfully", + }); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + // <------------------------ SKILL SET ------------------------ > + + async addSkillSet(req, res) { + const { talentId } = req.params; + const { skill, proficiencyLevel } = req.body; + try { + //tag to talent ID + const newSkill = await this.talentSkillSetModel.create({ + skill: skill, + proficiencyLevel: proficiencyLevel, + talentId: talentId, + }); + // Respond with the new work experience + return res.json(newSkill); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getSkillSet(req, res) { + const { talentId } = req.params; + try { + //tag to talent ID + const skill = await this.talentSkillSetModel.findAll({ + where: { + talentId: talentId, + }, + }); + // Respond with the new work experience + return res.json(skill); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + //update work experience + async updateSkill(req, res) { + //check if it's an array, same name as Frontend + const { skillData } = req.body; + try { + console.log("Request to update skill"); + console.log(req.body); + + // Iterate over each provided work experience and update it + for (const skill of skillData) { + await this.talentSkillSetModel.update( + { + skill: skill.skill, + proficiencyLevel: skill.proficiencyLevel, + }, + //pull workexp ID instead of talentId + { + where: { id: skill.id }, + } + ); + + console.log("skills updated"); + } + + console.log("All skills updated"); + + return res.status(200).json({ + success: true, + message: "skills updated successfully", + }); + } catch (err) { + console.error("Error updating skills:", err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async deleteSkill(req, res) { + const { skillId } = req.params; + try { + // Check if the skill set exists + const skillSet = await this.talentSkillSetModel.findOne({ + where: { + id: skillId, + }, + }); + + if (!skillSet) { + return res + .status(404) + .json({ error: true, msg: "Skill set not found" }); + } + + // Delete the skill set + await skillSet.destroy(); + + return res.json({ success: true, msg: "Skill set deleted successfully" }); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + // <------------------------ EDUCATION ------------------------ > + + async addEducation(req, res) { + const { talentId } = req.params; + const { + institution, + degree, + fieldOfStudy, + graduationMonth, + graduationYear, + } = req.body; + try { + //tag to talent ID + const newEducation = await this.talentEducationModel.create({ + institution: institution, + degree: degree, + fieldOfStudy: fieldOfStudy, + graduationMonth: graduationMonth, + graduationYear: graduationYear, + talentId: talentId, + }); + // Respond with the new work experience + return res.json(newEducation); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async getEducation(req, res) { + const { talentId } = req.params; + try { + //tag to talent ID + const education = await this.talentEducationModel.findAll({ + where: { + talentId: talentId, + }, + }); + // Respond with the new work experience + return res.json(education); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async updateEdu(req, res) { + //check if it's an array, same name as Frontend + const { eduData } = req.body; + try { + console.log("Request to update work experience"); + console.log(req.body); + + // Iterate over each provided work experience and update it + for (const edu of eduData) { + await this.talentEducationModel.update( + { + institution: edu.institution, + degree: edu.degree, + fieldOfStudy: edu.fieldOfStudy, + graduationMonth: edu.graduationMonth, + graduationYear: edu.graduationYear, + }, + //pull workexp ID instead of talentId + { + where: { id: edu.id }, + } + ); + + console.log(`Education updated`); + } + + console.log("All edu updated"); + + return res.status(200).json({ + success: true, + message: "Edu updated successfully", + }); + } catch (err) { + console.error("Error updating edu:", err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async deleteEdu(req, res) { + const { educationID } = req.params; + console.log("EDUCATION ID", educationID); + try { + // Check if the education entry exists + const eduSet = await this.talentEducationModel.findOne({ + where: { + id: educationID, + }, + }); + + if (!eduSet) { + return res + .status(404) + .json({ error: true, msg: "Education set not found" }); + } + + // Delete the education entry + await eduSet.destroy(); + + return res.json({ + success: true, + msg: "Education set deleted successfully", + }); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + // <------------------------ BENEFIT ------------------------ > + + async getBenefit(req, res) { + const { talentId } = req.params; + try { + const talent = await this.model.findByPk(talentId, { + include: this.benefitModel, + }); + + //show benefits only + const benefits = talent.benefits; + return res.json(talent); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + async addBenefit(req, res) { + const { talentId } = req.params; + const { selectedBenefitIds } = req.body; + try { + // Check if the talent exists + console.log("did data went through?", req.body); + const talent = await this.model.findByPk(talentId); + if (!talent) { + return res.status(404).json({ error: true, msg: "Talent not found" }); + } + // Create a new benefit and associate it with the talent + const addNewBenefit = await this.benefitModel.findAll({ + where: { + id: selectedBenefitIds, + }, + }); + await talent.setBenefits(addNewBenefit); + // Respond with the newly created benefit + return res.json(addNewBenefit); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + // <------------------------ JOB LISTINGS ------------------------ > + + async getEmAndJobListing(req, res) { + try { + // Include associated employer data when querying for job listings + console.log("hello, get employer and job listing."); + const jobListing = await this.jobListingModel.findAll({ + include: [ + { + model: this.employerModel, + attributes: ["companyName", "description"], + }, + { + model: this.benefitModel, + attributes: ["id", "category"], //benefits modal + through: { + attributes: ["jobListingId"], //joint modal + }, + }, + ], + }); + // Respond with the job listings including associated employer data + return res.json(jobListing); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } + + // <-------------------- APPLICATION ---------------------- > + + async addApplication(req, res) { + const { talentId } = req.params; + const { applicationStatus, jobListingId } = req.body; + console.log("ADD APPLICATION"); + console.log(applicationStatus); + console.log(talentId); + console.log(jobListingId); + try { + console.log("passing through"); + + //tag to talent ID + const newApplication = await this.applicationModel.create({ + jobListingId: jobListingId, + talentId: talentId, + applicationStatus: applicationStatus, + }); + console.log("job get posted."); + // Respond with the new work experience + return res.json(newApplication); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async getApplications(req, res) { + const { talentId } = req.params; + try { + console.log("talent id:", talentId); + const applications = await this.applicationModel.findAll({ + where: { + talentId: talentId, + }, + include: [ + { + model: this.jobListingModel, + include: [ + { + model: this.employerModel, + attributes: ["companyName"], + }, + ], + }, + ], + }); + console.log(applications); + // Respond with the applications data + return res.json(applications); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + async getAllApplications(req, res) { + const { talentId } = req.params; + try { + // find all job listings - ok + // console.log("HHHHHEEEELLLLLOOOOOO WOOORRLLLDDD!!!!!"); + // console.log("non applications"); + // console.log("talent id:", talentId); + + const allJobListings = await this.jobListingModel.findAll({ + include: [ + { + model: this.employerModel, + attributes: ["companyName", "description"], + }, + { + model: this.benefitModel, + attributes: ["id", "category"], //benefits modal + through: { + attributes: ["jobListingId"], //joint modal + }, + }, + ], + }); + + // console.log("all job listingss", allJobListings); + + // find the applications that the user applied - ok + + const applications = await this.applicationModel.findAll({ + where: { + talentId: talentId, + }, + include: [ + { + model: this.jobListingModel, + include: [ + { + model: this.employerModel, + attributes: ["companyName"], + }, + ], + }, + ], + }); + + console.log(applications); + + // console.log("APPLIED JOBSSSSS", applications); + + // filter by job listing that they applied to by the joblisting ID in application model + // extract applied job listing ids - ok + + const appliedJobListingIds = applications.map( + (application) => application.jobListing.id + ); + + // console.log("appliedJobListingIds", appliedJobListingIds); + + // filter applications with the job listing ids + // dont want ids that matches with applied job listing ids + const unappliedJobs = allJobListings.filter( + (jobListing) => !appliedJobListingIds.includes(jobListing.id) + ); + + // console.log(unappliedJobs); + // Respond with the non - applications data + return res.json(unappliedJobs); + } catch (err) { + return res.status(400).json({ error: true, msg: err.message }); + } + } + + async putApplicationStatus(req, res) { + console.log("putApplicationStatus is being called"); + const { talentId } = req.params; + const { applicationStatus, jobListingId, applicationId } = req.body; + console.log(applicationStatus); + // console.log(talentId); + // console.log(jobListingId); + try { + console.log("passing through"); + + //tag to talent ID + const newApplicationStatus = await this.applicationModel.update( + { applicationStatus: applicationStatus }, + { + where: { + id: applicationId, + }, + } + ); + + console.log("Application status changed."); + // Respond with the new work experience + return res.json(newApplicationStatus); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } +} + +// get all user info under base controller +// delete is not required - user can't delete profile + +module.exports = TalentController; diff --git a/db/migrations/20240206071629-primary_tables.js b/db/migrations/20240206071629-primary_tables.js new file mode 100644 index 00000000..29553492 --- /dev/null +++ b/db/migrations/20240206071629-primary_tables.js @@ -0,0 +1,119 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("talents", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + first_name: { + type: Sequelize.STRING, + allowNull: false, + }, + last_name: { + type: Sequelize.STRING, + allowNull: false, + }, + photo: { + type: Sequelize.STRING, + }, + email: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("employers", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + first_name: { + type: Sequelize.STRING, + allowNull: false, + }, + last_name: { + type: Sequelize.STRING, + allowNull: false, + }, + company_name: { + type: Sequelize.STRING, + }, + description: { + type: Sequelize.TEXT, + }, + mission_statement: { + type: Sequelize.TEXT, + }, + //Contact information + headquarters: { + type: Sequelize.STRING, + }, + phone: { + type: Sequelize.BIGINT, + }, + photo: { + type: Sequelize.STRING, + }, + email: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + }, + }); + + await queryInterface.createTable("benefits", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + category: { + type: Sequelize.STRING, + allowNull: false, + }, + description: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("talents"); + await queryInterface.dropTable("employers"); + await queryInterface.dropTable("benefits"); + }, +}; diff --git a/db/migrations/20240211024810-secondary_tables.js b/db/migrations/20240211024810-secondary_tables.js new file mode 100644 index 00000000..d9c15bac --- /dev/null +++ b/db/migrations/20240211024810-secondary_tables.js @@ -0,0 +1,300 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("talent_resumes", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + location: { + type: Sequelize.STRING, + }, + industry: { + type: Sequelize.STRING, + }, + title: { + type: Sequelize.STRING, + }, + objective: { + type: Sequelize.STRING, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("talent_work_experiences", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + company_name: { + type: Sequelize.STRING, + allowNull: false, + }, + position: { + type: Sequelize.STRING, + allowNull: false, + }, + responsibility: { + type: Sequelize.STRING, + allowNull: false, + }, + start_month: { + type: Sequelize.STRING, + allowNull: false, + }, + start_year: { + type: Sequelize.STRING, + allowNull: false, + }, + end_month: { + type: Sequelize.STRING, + }, + end_year: { + type: Sequelize.STRING, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("talent_skill_sets", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + skill: { + type: Sequelize.STRING, + }, + proficiency_level: { + type: Sequelize.STRING, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("talent_educations", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + institution: { + type: Sequelize.STRING, + allowNull: false, + }, + degree: { + type: Sequelize.STRING, + allowNull: false, + }, + field_of_study: { + type: Sequelize.STRING, + allowNull: false, + }, + graduation_month: { + type: Sequelize.STRING, + }, + graduation_year: { + type: Sequelize.STRING, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("job_listings", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + employer_id: { + type: Sequelize.INTEGER, + references: { + model: "employers", + key: "id", + }, + }, + job_title: { + type: Sequelize.STRING, + allowNull: false, + }, + description: { + type: Sequelize.STRING, + allowNull: false, + }, + job_responsibility: { + type: Sequelize.STRING, + allowNull: false, + }, + skill_set: { + type: Sequelize.STRING, + allowNull: false, + }, + application_start_date: { + type: Sequelize.STRING, + allowNull: false, + }, + application_end_date: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("applications", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + job_listing_id: { + type: Sequelize.INTEGER, + references: { + model: "job_listings", + key: "id", + }, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + application_date: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + application_status: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("chatrooms", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + application_id: { + type: Sequelize.INTEGER, + references: { + model: "applications", + key: "id", + }, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("talent_resumes"); + await queryInterface.dropTable("talent_work_experiences"); + await queryInterface.dropTable("talent_skill_sets"); + await queryInterface.dropTable("talent_educations"); + await queryInterface.dropTable("job_listings"); + await queryInterface.dropTable("applications"); + await queryInterface.dropTable("chatrooms"); + }, +}; diff --git a/db/migrations/20240211025151-tertiary_tables.js b/db/migrations/20240211025151-tertiary_tables.js new file mode 100644 index 00000000..98b38ba0 --- /dev/null +++ b/db/migrations/20240211025151-tertiary_tables.js @@ -0,0 +1,122 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("job_listing_benefits", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + job_listing_id: { + type: Sequelize.INTEGER, + references: { + model: "job_listings", + key: "id", + }, + }, + benefit_id: { + type: Sequelize.INTEGER, + references: { + model: "benefits", + key: "id", + }, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("talent_benefits", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + benefit_id: { + type: Sequelize.INTEGER, + references: { + model: "benefits", + key: "id", + }, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + + await queryInterface.createTable("messages", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + talent_id: { + type: Sequelize.INTEGER, + references: { + model: "talents", + key: "id", + }, + }, + employer_id: { + type: Sequelize.INTEGER, + references: { + model: "employers", + key: "id", + }, + }, + chatroom_id: { + type: Sequelize.INTEGER, + references: { + model: "chatrooms", + key: "id", + }, + }, + message: { + type: Sequelize.STRING, + allowNull: false, + }, + created_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: new Date(), + allowNull: false, + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("job_listing_benefits"); + await queryInterface.dropTable("talent_benefits"); + await queryInterface.dropTable("messages"); + }, +}; diff --git a/db/models/application.js b/db/models/application.js new file mode 100644 index 00000000..7a03b422 --- /dev/null +++ b/db/models/application.js @@ -0,0 +1,28 @@ +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Application extends Model { + static associate(models) { + this.belongsTo(models.talent, { foreignKey: "talentId" }); + this.belongsTo(models.jobListing, { foreignKey: "jobListingId" }); + } + } + Application.init( + { + applicationStatus: DataTypes.STRING, + talentId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + jobListingId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "application", //non-plurul + underscored: true, + } + ); + return Application; +}; diff --git a/db/models/benefit.js b/db/models/benefit.js new file mode 100644 index 00000000..f773df5b --- /dev/null +++ b/db/models/benefit.js @@ -0,0 +1,25 @@ +"use strict"; + +//write in JS format. + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Benefit extends Model { + static associate(models) { + this.belongsToMany(models.talent, { through: "talent_benefits" }); + this.belongsToMany(models.talent, { through: "job_listing_benefits" }); + } + } + Benefit.init( + { + category: DataTypes.STRING, + description: DataTypes.STRING, + }, + { + sequelize, + modelName: "benefit", //non-plurul + underscored: true, + } + ); + return Benefit; +}; diff --git a/db/models/employer.js b/db/models/employer.js new file mode 100644 index 00000000..e2acdfdf --- /dev/null +++ b/db/models/employer.js @@ -0,0 +1,32 @@ +"use strict"; + +//write in JS format. + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Employer extends Model { + static associate(models) { + this.hasMany(models.jobListing, { foreignKey: "employerId" }); + } + } + Employer.init( + { + firstName: DataTypes.STRING, + lastName: DataTypes.STRING, + companyName: DataTypes.STRING, + description: DataTypes.STRING, + missionStatement: DataTypes.STRING, + headquarters: DataTypes.STRING, + //not sure if should put number or int + phone: DataTypes.INTEGER, + photo: DataTypes.STRING, + email: DataTypes.STRING, + }, + { + sequelize, + modelName: "employer", //non-plurul + underscored: true, + } + ); + return Employer; +}; diff --git a/db/models/index.js b/db/models/index.js new file mode 100644 index 00000000..5edbd256 --- /dev/null +++ b/db/models/index.js @@ -0,0 +1,43 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const process = require('process'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../../config/database.js')[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return ( + file.indexOf('.') !== 0 && + file !== basename && + file.slice(-3) === '.js' && + file.indexOf('.test.js') === -1 + ); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/db/models/jobListing.js b/db/models/jobListing.js new file mode 100644 index 00000000..0a8803f3 --- /dev/null +++ b/db/models/jobListing.js @@ -0,0 +1,33 @@ +"use strict"; + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class JobListing extends Model { + static associate(models) { + this.belongsTo(models.employer, { foreignKey: "employerId" }); + this.hasMany(models.application, { foreignKey: "jobListingId" }); + this.belongsToMany(models.benefit, { through: "job_listing_benefits" }); + } + } + JobListing.init( + { + jobTitle: DataTypes.STRING, + description: DataTypes.STRING, + jobResponsibility: DataTypes.STRING, + skillSet: DataTypes.STRING, + applicationStartDate: DataTypes.STRING, + applicationEndDate: DataTypes.STRING, + employerId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "jobListing", + underscored: true, + } + ); + + return JobListing; +}; diff --git a/db/models/talent.js b/db/models/talent.js new file mode 100644 index 00000000..71c21450 --- /dev/null +++ b/db/models/talent.js @@ -0,0 +1,31 @@ +"use strict"; + +//write in JS format. + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Talent extends Model { + static associate(models) { + this.hasOne(models.talentResume, { foreignKey: "talentId" }); + this.hasMany(models.talentWorkExperience, { foreignKey: "talentId" }); + this.hasMany(models.talentSkillSet, { foreignKey: "talentId" }); + this.hasMany(models.talentEducation, { foreignKey: "talentId" }); + this.hasMany(models.application, { foreignKey: "talentId" }); + this.belongsToMany(models.benefit, { through: "talent_benefits" }); + } + } + Talent.init( + { + firstName: DataTypes.STRING, + lastName: DataTypes.STRING, + email: DataTypes.STRING, + photo: DataTypes.STRING, + }, + { + sequelize, + modelName: "talent", //non-plurul + underscored: true, + } + ); + return Talent; +}; diff --git a/db/models/talentEducation.js b/db/models/talentEducation.js new file mode 100644 index 00000000..6ad62f47 --- /dev/null +++ b/db/models/talentEducation.js @@ -0,0 +1,29 @@ +"use strict"; + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class TalentEducation extends Model { + static associate(models) { + this.belongsTo(models.talent, { foreignKey: "talentId" }); + } + } + TalentEducation.init( + { + institution: DataTypes.STRING, + degree: DataTypes.STRING, + fieldOfStudy: DataTypes.STRING, + graduationMonth: DataTypes.STRING, + graduationYear: DataTypes.STRING, + talentId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "talentEducation", + underscored: true, + } + ); + return TalentEducation; +}; diff --git a/db/models/talentResume.js b/db/models/talentResume.js new file mode 100644 index 00000000..cb028470 --- /dev/null +++ b/db/models/talentResume.js @@ -0,0 +1,28 @@ +"use strict"; + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class TalentResume extends Model { + static associate(models) { + this.belongsTo(models.talent, { foreignKey: "talentId" }); + } + } + TalentResume.init( + { + location: DataTypes.STRING, + industry: DataTypes.STRING, + title: DataTypes.STRING, + objective: DataTypes.STRING, + talentId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "talentResume", //non-plurul + underscored: true, + } + ); + return TalentResume; +}; diff --git a/db/models/talentSkillSet.js b/db/models/talentSkillSet.js new file mode 100644 index 00000000..33d20e00 --- /dev/null +++ b/db/models/talentSkillSet.js @@ -0,0 +1,26 @@ +"use strict"; + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class TalentSkillSet extends Model { + static associate(models) { + this.belongsTo(models.talent, { foreignKey: "talentId" }); + } + } + TalentSkillSet.init( + { + skill: DataTypes.STRING, + proficiencyLevel: DataTypes.STRING, + talentId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "talentSkillSet", + underscored: true, + } + ); + return TalentSkillSet; +}; diff --git a/db/models/talentWorkExperience.js b/db/models/talentWorkExperience.js new file mode 100644 index 00000000..f1fa5d92 --- /dev/null +++ b/db/models/talentWorkExperience.js @@ -0,0 +1,31 @@ +"use strict"; + +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class TalentWorkExperience extends Model { + static associate(models) { + this.belongsTo(models.talent, { foreignKey: "talentId" }); + } + } + TalentWorkExperience.init( + { + companyName: DataTypes.STRING, + position: DataTypes.STRING, + responsibility: DataTypes.STRING, + startMonth: DataTypes.STRING, + startYear: DataTypes.STRING, + endMonth: DataTypes.STRING, + endYear: DataTypes.STRING, + talentId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "talentWorkExperience", + underscored: true, + } + ); + return TalentWorkExperience; +}; diff --git a/db/seeders/20240206073417-primary_tables.js b/db/seeders/20240206073417-primary_tables.js new file mode 100644 index 00000000..f244f204 --- /dev/null +++ b/db/seeders/20240206073417-primary_tables.js @@ -0,0 +1,194 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("talents", [ + { + first_name: "Spidey", + last_name: "boy", + email: "kid2010@text.com", + }, + { + first_name: "Genz", + last_name: "Goose", + email: "goosegoose@text.com", + }, + { + first_name: "Cat", + last_name: "Dog", + email: "bestpetever@text.com", + }, + ]); + + await queryInterface.bulkInsert("employers", [ + { + first_name: "Tony", + last_name: "Stark", + company_name: "Avengers", + description: + "The Avengers is a team of extraordinary individuals assembled to protect the world from threats beyond the capabilities of conventional military and law enforcement agencies. Comprised of some of the most powerful heroes on Earth, The Avengers stand as the first line of defense against global and interstellar dangers.", + mission_statement: + "To safeguard humanity and maintain peace by uniting the world’s greatest heroes against any threat, no matter how formidable.", + headquarters: "Avengers Tower, New York City, NY", + phone: 2484345508, + email: "tonystark@test.com", + }, + { + first_name: "Widow", + last_name: "Black", + company_name: "Red Room", + description: + "The Red Room is a covert espionage and assassination program that operates in the shadows, training elite spies and assassins for high-stakes missions. Known for its rigorous training regimen and psychological manipulation, The Red Room has produced some of the world’s most dangerous operatives.", + mission_statement: + "To achieve strategic superiority through the deployment of expertly trained and highly skilled operatives capable of executing the most critical and covert missions.", + headquarters: "Everywhere", + phone: 2484345508, + email: "blackwidow@text.com", + }, + { + first_name: "Hulk", + last_name: "Green", + company_name: "Avengers", + description: + "The Avengers is a team of extraordinary individuals assembled to protect the world from threats beyond the capabilities of conventional military and law enforcement agencies. Comprised of some of the most powerful heroes on Earth, The Avengers stand as the first line of defense against global and interstellar dangers.", + mission_statement: + "To safeguard humanity and maintain peace by uniting the world’s greatest heroes against any threat, no matter how formidable.", + headquarters: "Avengers Tower, New York City, NY", + phone: 2484345508, + email: "blackwidow@text.com", + }, + { + first_name: "Elon", + last_name: "Musk", + company_name: "Tesla", + description: + "Tesla is a company that specializes in electric vehicles, energy storage solutions, and renewable energy products. Tesla aims to accelerate the world's transition to sustainable energy with innovative products and technologies.", + mission_statement: + "To accelerate the world's transition to sustainable energy.", + headquarters: "Palo Alto, CA", + phone: 6506815000, + email: "elonmusk@tesla.com", + }, + { + first_name: "Jeff", + last_name: "Bezos", + company_name: "Amazon", + description: + "Amazon is a multinational technology company focusing on e-commerce, cloud computing, digital streaming, and artificial intelligence. Known for its disruption of well-established industries, Amazon is one of the world's most valuable brands.", + mission_statement: + "To be Earth's most customer-centric company, where customers can find and discover anything they might want to buy online.", + headquarters: "Seattle, WA", + phone: 2062661000, + email: "jeffbezos@amazon.com", + }, + { + first_name: "Satya", + last_name: "Nadella", + company_name: "Microsoft", + description: + "Microsoft is a leading global technology company that develops, manufactures, licenses, supports, and sells a range of software products, services, and devices. It is known for its software products like Windows, Office, and Azure.", + mission_statement: + "To empower every person and every organization on the planet to achieve more.", + headquarters: "Redmond, WA", + phone: 4258828080, + email: "satyanadella@microsoft.com", + }, + { + first_name: "Sundar", + last_name: "Pichai", + company_name: "Google", + description: + "Google is a global leader in technology, specializing in internet-related services and products, including online advertising technologies, a search engine, cloud computing, software, and hardware.", + mission_statement: + "To organize the world's information and make it universally accessible and useful.", + headquarters: "Mountain View, CA", + phone: 6502530000, + email: "sundarpichai@google.com", + }, + { + first_name: "Tim", + last_name: "Cook", + company_name: "Apple", + description: + "Apple Inc. is a multinational technology company that designs, manufactures, and markets consumer electronics, computer software, and online services. Known for its innovative products like the iPhone, iPad, and Mac computers.", + mission_statement: + "To bring the best user experience to its customers through its innovative hardware, software, and services.", + headquarters: "Cupertino, CA", + phone: 4089961010, + email: "timcook@apple.com", + }, + { + first_name: "Mark", + last_name: "Zuckerberg", + company_name: "Facebook", + description: + "Facebook is a leading social media and technology company that offers online social networking services. It aims to give people the power to build community and bring the world closer together.", + mission_statement: + "To give people the power to build community and bring the world closer together.", + headquarters: "Menlo Park, CA", + phone: 6505434800, + email: "markzuckerberg@facebook.com", + }, + ]); + + await queryInterface.bulkInsert("benefits", [ + { + category: "Meaningful Impact", + description: + "Cultivate personal fulfilment by contributing to a purpose-driven organisation, creating a positive impact that extends beyond the confines of the workplace.", + }, + { + category: "Harmony in Life and Work", + description: + "Achieving a harmonious balance between personal and professional life promotes well-being and contentment for all involved.", + }, + { + category: "Professional Advancement", + description: + "Unlock continuous pathways for career growth, providing opportunities for individuals to progress and excel in their chosen fields.", + }, + { + category: "Competitive Compensation", + description: + "Receive equitable and competitive compensation packages, ensuring financial security and acknowledgement for valuable contributions in the dynamic job market.", + }, + { + category: "Stability and Assurance", + description: + "Establish a foundation of job security, creating a stable environment for organisational growth and individual flourishing in a secure professional space.", + }, + { + category: "Inclusive Workplace Culture", + description: + "Embrace diversity and nurture a company culture that values inclusivity, fostering a collaborative environment that attracts and retains a rich tapestry of talents.", + }, + { + category: "Flexible Work Arrangements", + description: + "Tailor work setups to accommodate diverse needs, promoting flexibility in the workplace to enhance productivity and job satisfaction.", + }, + { + category: "Guidance and Continuous Learning:", + description: + "Access mentorship and a spectrum of learning opportunities for continuous personal and professional development, empowering growth for individuals at all career stages.", + }, + { + category: "Holistic Well-being Support", + description: + "Prioritise health and overall well-being through comprehensive support systems, including insurance, ensuring the holistic welfare of everyone involved.", + }, + { + category: "Community Impact and Social Responsibility", + description: + "Contribute to a broader social impact by aligning with organisations that make a positive difference.", + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("talents"); + await queryInterface.dropTable("employers"); + await queryInterface.dropTable("benefits"); + }, +}; diff --git a/db/seeders/20240211125828-secondary_tables.js b/db/seeders/20240211125828-secondary_tables.js new file mode 100644 index 00000000..6a3f7635 --- /dev/null +++ b/db/seeders/20240211125828-secondary_tables.js @@ -0,0 +1,181 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("talent_resumes", [ + { + talent_id: 1, + location: "Singapore", + industry: "Technology", + title: "Software Engineer", + objective: "Seeking a challenging role in software development.", + }, + { + talent_id: 2, + location: "Malaysia", + industry: "Finance", + title: "Financial Analyst", + objective: + "Experienced financial analyst looking for new opportunities.", + }, + { + talent_id: 3, + location: "Hong Kong", + industry: "Marketing", + title: "Marketing Specialist", + objective: + "Marketing professional with expertise in digital marketing strategies.", + }, + ]); + + await queryInterface.bulkInsert("talent_work_experiences", [ + // talent_id: 1 + { + talent_id: 1, + company_name: "ABC Inc.", + position: "Software Developer", + responsibility: "Developing web applications.", + start_month: "January", + start_year: "2020", + end_month: "December", + end_year: "2022", + }, + { + talent_id: 1, + company_name: "Shopping Co.", + position: "Senior Software Engineer", + responsibility: "Leading development projects.", + start_month: "January", + start_year: "2023", + }, + // talent_id: 2 + { + talent_id: 2, + company_name: "123 Investments", + position: "Financial Analyst Intern", + responsibility: "Analyzed financial data and prepared reports.", + start_month: "June", + start_year: "2021", + end_month: "August", + end_year: "2021", + }, + // talent_id: 3 + { + talent_id: 3, + company_name: "Market Solutions Inc.", + position: "Marketing Assistant", + responsibility: "Assisted in developing marketing strategies.", + start_month: "March", + start_year: "2022", + end_month: "June", + end_year: "2022", + }, + ]); + + await queryInterface.bulkInsert("talent_skill_sets", [ + // talent_id: 1 + { + talent_id: 1, + skill: "JavaScript", + proficiency_level: "Intermediate", + }, + { + talent_id: 1, + skill: "React", + proficiency_level: "Advanced", + }, + // talent_id: 2 + { + talent_id: 2, + skill: "Financial Modeling", + proficiency_level: "Great", + }, + // talent_id: 3 + { + talent_id: 3, + skill: "Digital Marketing", + proficiency_level: "Expert", + }, + ]); + + await queryInterface.bulkInsert("talent_educations", [ + // Education for talent_id: 1 + { + talent_id: 1, + institution: "XYZ University", + degree: "Bachelor of Science in Computer Science", + field_of_study: "Computer Science", + graduation_month: "May", + graduation_year: "2020", + }, + { + talent_id: 1, + institution: "ABC University", + degree: "Master of Science in Software Engineering", + field_of_study: "Software Engineering", + graduation_month: "June", + graduation_year: "2022", + }, + // Education for talent_id: 2 + { + talent_id: 2, + institution: "University of ABC", + degree: "Bachelor of Business Administration", + field_of_study: "Finance", + graduation_month: "May", + graduation_year: "2021", + }, + // Education for talent_id: 3 + { + talent_id: 3, + institution: "XYZ University of ABC", + degree: "Bachelor of Marketing", + field_of_study: "Marketing", + graduation_month: "April", + graduation_year: "2022", + }, + ]); + + await queryInterface.bulkInsert("job_listings", [ + { + employer_id: 1, + job_title: "Senior Software Engineer", + description: "Developing and maintaining web applications.", + job_responsibility: "Lead development projects.", + skill_set: "JavaScript, React, Node.js", + application_start_date: "2024-02-01", + application_end_date: "2024-02-15", + }, + ]); + + await queryInterface.bulkInsert("applications", [ + { + job_listing_id: 1, + talent_id: 1, + application_date: new Date(), + application_status: "Pending", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + + await queryInterface.bulkInsert("chatrooms", [ + { + application_id: 1, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("talent_resumes"); + await queryInterface.dropTable("talent_work_experiences"); + await queryInterface.dropTable("talent_skill_sets"); + await queryInterface.dropTable("talent_educations"); + await queryInterface.dropTable("job_listings"); + await queryInterface.dropTable("applications"); + await queryInterface.dropTable("chatrooms"); + }, +}; diff --git a/db/seeders/20240211125839-tertiary_tables.js b/db/seeders/20240211125839-tertiary_tables.js new file mode 100644 index 00000000..65eda62a --- /dev/null +++ b/db/seeders/20240211125839-tertiary_tables.js @@ -0,0 +1,50 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("job_listing_benefits", [ + { + job_listing_id: 1, + benefit_id: 1, + }, + { + job_listing_id: 1, + benefit_id: 3, + }, + { + job_listing_id: 1, + benefit_id: 7, + }, + ]); + + await queryInterface.bulkInsert("talent_benefits", [ + { + talent_id: 1, + benefit_id: 2, + }, + { + talent_id: 1, + benefit_id: 4, + }, + { + talent_id: 1, + benefit_id: 6, + }, + ]); + + await queryInterface.bulkInsert("messages", [ + { + talent_id: 1, + chatroom_id: 1, + message: "Hello, I am interested in the job listing.", + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("job_listing_benefits"); + await queryInterface.dropTable("talent_benefits"); + await queryInterface.dropTable("messages"); + }, +}; diff --git a/db/seeders/20240215025813-job_listings.js b/db/seeders/20240215025813-job_listings.js new file mode 100644 index 00000000..5f05724d --- /dev/null +++ b/db/seeders/20240215025813-job_listings.js @@ -0,0 +1,266 @@ +"use strict"; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("job_listings", [ + { + employer_id: 1, + job_title: "Frontend Developer", + description: "Building user interfaces for web applications.", + job_responsibility: "Design and implement user-facing features.", + skill_set: "HTML, CSS, JavaScript, React", + application_start_date: "2024-02-10", + application_end_date: "2024-03-20", + }, + { + employer_id: 1, + job_title: "Backend Developer", + description: "Creating and maintaining server-side logic.", + job_responsibility: "Develop backend components and APIs.", + skill_set: "Node.js, Express, MongoDB", + application_start_date: "2024-02-03", + application_end_date: "2024-02-28", + }, + { + employer_id: 2, + job_title: "Accountant", + description: "Managing financial records and transactions.", + job_responsibility: "Prepare financial statements and reports.", + skill_set: "Accounting software, Financial analysis, Taxation", + application_start_date: "2024-02-04", + application_end_date: "2024-03-04", + }, + { + employer_id: 3, + job_title: "Graphic Designer", + description: + "Creating visual concepts and designs for various projects.", + job_responsibility: + "Develop visual elements for print and digital media.", + skill_set: "Adobe Creative Suite, Graphic design principles", + application_start_date: "2024-02-03", + application_end_date: "2024-03-28", + }, + { + employer_id: 3, + job_title: "UI/UX Designer", + description: + "Designing user interfaces and experiences for digital products.", + job_responsibility: "Create wireframes, mockups, and prototypes.", + skill_set: "UI/UX design tools, User research, Prototyping", + application_start_date: "2024-02-03", + application_end_date: "2024-03-28", + }, + { + employer_id: 3, + job_title: "Web Designer", + description: + "Designing and creating websites with a focus on aesthetics and usability.", + job_responsibility: + "Develop visually appealing and functional web layouts.", + skill_set: "HTML, CSS, JavaScript, Responsive design", + application_start_date: "2024-02-03", + application_end_date: "2024-03-28", + }, + { + employer_id: 4, + job_title: "Project Manager", + description: + "Overseeing project development and ensuring timely delivery.", + job_responsibility: + "Coordinate project activities and manage resources.", + skill_set: "Project management, Agile, Scrum", + application_start_date: "2024-02-01", + application_end_date: "2024-03-15", + }, + { + employer_id: 4, + job_title: "Data Scientist", + description: + "Analyzing and interpreting complex data to provide insights.", + job_responsibility: "Develop data models and algorithms.", + skill_set: "Python, R, Machine Learning, Data Analysis", + application_start_date: "2024-02-05", + application_end_date: "2024-03-10", + }, + { + employer_id: 5, + job_title: "Marketing Specialist", + description: "Planning and executing marketing campaigns.", + job_responsibility: "Develop marketing strategies and analyze results.", + skill_set: "SEO, Content Marketing, Social Media", + application_start_date: "2024-02-07", + application_end_date: "2024-03-25", + }, + { + employer_id: 6, + job_title: "Human Resources Manager", + description: "Managing HR operations and employee relations.", + job_responsibility: "Oversee recruitment and employee performance.", + skill_set: "HR management, Recruitment, Employee Relations", + application_start_date: "2024-02-10", + application_end_date: "2024-03-20", + }, + { + employer_id: 7, + job_title: "Software Tester", + description: "Ensuring the quality of software through testing.", + job_responsibility: "Develop and execute test plans and scripts.", + skill_set: "Manual Testing, Automated Testing, QA Tools", + application_start_date: "2024-02-12", + application_end_date: "2024-03-22", + }, + { + employer_id: 8, + job_title: "DevOps Engineer", + description: "Managing and automating software development processes.", + job_responsibility: "Implement CI/CD pipelines and monitor systems.", + skill_set: "AWS, Docker, Jenkins, Kubernetes", + application_start_date: "2024-02-14", + application_end_date: "2024-03-24", + }, + //12 job listings + ]); + + await queryInterface.bulkInsert("job_listing_benefits", [ + { + job_listing_id: 2, + benefit_id: 4, + }, + { + job_listing_id: 2, + benefit_id: 7, + }, + { + job_listing_id: 2, + benefit_id: 9, + }, + { + job_listing_id: 3, + benefit_id: 1, + }, + { + job_listing_id: 3, + benefit_id: 3, + }, + { + job_listing_id: 3, + benefit_id: 8, + }, + { + job_listing_id: 4, + benefit_id: 2, + }, + { + job_listing_id: 4, + benefit_id: 5, + }, + { + job_listing_id: 4, + benefit_id: 10, + }, + { + job_listing_id: 5, + benefit_id: 1, + }, + { + job_listing_id: 5, + benefit_id: 6, + }, + { + job_listing_id: 5, + benefit_id: 8, + }, + { + job_listing_id: 6, + benefit_id: 3, + }, + { + job_listing_id: 6, + benefit_id: 4, + }, + { + job_listing_id: 6, + benefit_id: 9, + }, + { + job_listing_id: 7, + benefit_id: 2, + }, + { + job_listing_id: 7, + benefit_id: 5, + }, + { + job_listing_id: 7, + benefit_id: 10, + }, + { + job_listing_id: 8, + benefit_id: 4, + }, + { + job_listing_id: 8, + benefit_id: 6, + }, + { + job_listing_id: 8, + benefit_id: 9, + }, + { + job_listing_id: 9, + benefit_id: 1, + }, + { + job_listing_id: 9, + benefit_id: 3, + }, + { + job_listing_id: 9, + benefit_id: 7, + }, + { + job_listing_id: 10, + benefit_id: 2, + }, + { + job_listing_id: 10, + benefit_id: 5, + }, + { + job_listing_id: 10, + benefit_id: 8, + }, + { + job_listing_id: 11, + benefit_id: 1, + }, + { + job_listing_id: 11, + benefit_id: 4, + }, + { + job_listing_id: 11, + benefit_id: 10, + }, + { + job_listing_id: 12, + benefit_id: 3, + }, + { + job_listing_id: 12, + benefit_id: 6, + }, + { + job_listing_id: 12, + benefit_id: 9, + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("job_listings"); + await queryInterface.dropTable("job_listing_benefits"); + }, +}; diff --git a/index.js b/index.js index 3fd92432..6c992373 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,84 @@ -import express from "express"; +// import env file +require("dotenv").config(); +//Enable CORS access to this server +const cors = require("cors"); +//import express to read json +const express = require("express"); -const PORT = 3000; -const app = express(); +//import auth0 middleware +const { auth } = require("express-oauth2-jwt-bearer"); -app.get("/", (req, res) => { - res.send("Hello, World!"); +// Authorization middleware. When used, the Access Token must +// exist and be verified against the Auth0 JSON Web Key Set. +const checkJwt = auth({ + audience: process.env.AUTH_AUDIENCE, + issuerBaseURL: process.env.AUTH_ISSUER_BASE_URL, }); -app.listen(PORT, () => { - console.log(`Express app listening on port ${PORT}!`); +//import DB +const db = require("./db/models/index"); +const { + talent, + benefit, + employer, + talentResume, + talentWorkExperience, + talentSkillSet, + talentEducation, + jobListing, + application, +} = db; + +//import controllers +const TalentController = require("./controllers/TalentController"); +const BenefitController = require("./controllers/BenefitController"); +const EmployerController = require("./controllers/EmployerController"); + +//import router +const TalentRouter = require("./routers/TalentRouter"); +const BenefitRouter = require("./routers/BenefitRouter"); +const EmployerRouter = require("./routers/EmployerRouter"); + +//express +const app = express(); + +// Enable CORS access to this server +app.use(cors()); +// Enable reading JSON request bodies +app.use(express.json()); + +//initialise contollers +const talentController = new TalentController( + talent, + talentResume, + talentWorkExperience, + talentSkillSet, + talentEducation, + benefit, + employer, + jobListing, + application +); +const benefitController = new BenefitController(benefit, employer); +const employerController = new EmployerController( + employer, + jobListing, + benefit, + application +); + +//initialise router +const talentRouter = new TalentRouter(talentController, checkJwt).routes(); +const benefitRouter = new BenefitRouter(benefitController).routes(); +const employerRouter = new EmployerRouter(employerController).routes(); + +// <----- USAGE-----> +// talent and employer is singular to standardise with frontend's nav bar. + +app.use("/talent", talentRouter); +app.use("/benefits", benefitRouter); +app.use("/employer", employerRouter); + +app.listen(process.env.PORT, () => { + console.log(`Express app listening on port ${process.env.PORT}!`); }); diff --git a/package-lock.json b/package-lock.json index bc0ea392..e514324f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,17 @@ "name": "project3-backend-bootcamp", "version": "1.0.0", "dependencies": { - "express": "^4.18.1" + "cors": "^2.8.5", + "dotenv": "^16.4.1", + "express": "^4.18.1", + "express-oauth2-jwt-bearer": "^1.6.0", + "i": "^0.3.7", + "pg": "^8.11.3", + "sequelize": "^6.36.0" }, "devDependencies": { - "eslint": "^8.16.0" + "eslint": "^8.16.0", + "sequelize-cli": "^6.6.2" } }, "node_modules/@eslint/eslintrc": { @@ -100,6 +107,153 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/validator": { + "version": "13.11.8", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -184,12 +338,27 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -223,6 +392,14 @@ "concat-map": "0.0.1" } }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -268,6 +445,33 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cli-color": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", + "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.61", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -286,12 +490,31 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -324,6 +547,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -338,6 +573,16 @@ "node": ">= 8" } }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -381,11 +626,81 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", + "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -394,6 +709,63 @@ "node": ">= 0.8" } }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -599,6 +971,16 @@ "node": ">= 0.6" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/express": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", @@ -640,6 +1022,32 @@ "node": ">= 0.10.0" } }, + "node_modules/express-oauth2-jwt-bearer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/express-oauth2-jwt-bearer/-/express-oauth2-jwt-bearer-1.6.0.tgz", + "integrity": "sha512-HXnez7vocYlOqlfF3ozPcf/WE3zxT7zfUNfeg5FHJnvNwhBYlNXiPOvuCtBalis8xcigvwtInzEKhBuH87+9ug==", + "dependencies": { + "jose": "^4.13.1" + }, + "engines": { + "node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0 || ^20.2.0" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -706,6 +1114,22 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -722,6 +1146,21 @@ "node": ">= 0.6" } }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -729,9 +1168,12 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -739,6 +1181,15 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -799,6 +1250,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -830,6 +1287,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -845,6 +1314,14 @@ "node": ">= 0.8" } }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -890,6 +1367,14 @@ "node": ">=0.8.19" } }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -905,6 +1390,12 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -913,6 +1404,18 @@ "node": ">= 0.10" } }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -922,6 +1425,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -934,24 +1446,122 @@ "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "@isaacs/cliui": "^8.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jose": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-beautify": { + "version": "1.14.11", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.11.tgz", + "integrity": "sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^10.3.3", + "nopt": "^7.2.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -964,6 +1574,18 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -977,12 +1599,37 @@ "node": ">= 0.8.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -991,6 +1638,22 @@ "node": ">= 0.6" } }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1046,6 +1709,34 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1065,6 +1756,35 @@ "node": ">= 0.6" } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", @@ -1110,6 +1830,11 @@ "node": ">= 0.8.0" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1148,11 +1873,160 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -1162,6 +2036,12 @@ "node": ">= 0.8.0" } }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1231,6 +2111,32 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1240,6 +2146,11 @@ "node": ">=4" } }, + "node_modules/retry-as-promised": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1279,6 +2190,20 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1307,6 +2232,118 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/sequelize": { + "version": "6.36.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", + "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "dependencies": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.9.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-cli": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", + "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", + "dev": true, + "dependencies": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sequelize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -1360,6 +2397,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1368,6 +2425,35 @@ "node": ">= 0.8" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1380,6 +2466,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1404,12 +2503,34 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1418,6 +2539,17 @@ "node": ">=0.6" } }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1454,6 +2586,32 @@ "node": ">= 0.6" } }, + "node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1479,12 +2637,28 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -1508,20 +2682,112 @@ "node": ">= 8" } }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -1593,6 +2859,116 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "requires": { + "@types/ms": "*" + } + }, + "@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "@types/node": { + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/validator": { + "version": "13.11.8", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" + }, + "abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1653,12 +3029,24 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -1688,6 +3076,11 @@ "concat-map": "0.0.1" } }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1718,6 +3111,30 @@ "supports-color": "^7.1.0" } }, + "cli-color": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", + "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.61", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1733,12 +3150,28 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1762,6 +3195,15 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1773,6 +3215,16 @@ "which": "^2.0.1" } }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1803,18 +3255,122 @@ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "^2.0.2" + } + }, + "dotenv": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", + "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==" + }, + "dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "requires": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-html": { "version": "1.0.3", @@ -1966,6 +3522,16 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "express": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", @@ -2004,6 +3570,31 @@ "vary": "~1.1.2" } }, + "express-oauth2-jwt-bearer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/express-oauth2-jwt-bearer/-/express-oauth2-jwt-bearer-1.6.0.tgz", + "integrity": "sha512-HXnez7vocYlOqlfF3ozPcf/WE3zxT7zfUNfeg5FHJnvNwhBYlNXiPOvuCtBalis8xcigvwtInzEKhBuH87+9ug==", + "requires": { + "jose": "^4.13.1" + } + }, + "ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "requires": { + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2061,6 +3652,16 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2071,6 +3672,18 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2078,9 +3691,9 @@ "dev": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2088,6 +3701,12 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -2130,6 +3749,12 @@ "type-fest": "^0.20.2" } }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2149,6 +3774,15 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2161,6 +3795,11 @@ "toidentifier": "1.0.1" } }, + "i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2191,6 +3830,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2206,17 +3850,38 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2226,12 +3891,78 @@ "is-extglob": "^2.1.1" } }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jose": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==" + }, + "js-beautify": { + "version": "1.14.11", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.11.tgz", + "integrity": "sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==", + "dev": true, + "requires": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^10.3.3", + "nopt": "^7.2.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2253,6 +3984,16 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2263,17 +4004,55 @@ "type-check": "~0.4.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2311,6 +4090,25 @@ "brace-expansion": "^1.1.7" } }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "requires": { + "moment": "^2.29.4" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2327,6 +4125,26 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "requires": { + "abbrev": "^2.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", @@ -2363,6 +4181,11 @@ "word-wrap": "^1.2.3" } }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2389,17 +4212,132 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true + } + } + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-cloudflare": "^1.1.1", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "requires": {} + }, + "pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "requires": { + "split2": "^4.1.0" + } + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2445,12 +4383,34 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "retry-as-promised": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2470,6 +4430,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -2497,6 +4465,64 @@ } } }, + "sequelize": { + "version": "6.36.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", + "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", + "requires": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.9.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "sequelize-cli": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", + "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", + "dev": true, + "requires": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + } + }, + "sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" + }, "serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -2538,11 +4564,44 @@ "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -2552,6 +4611,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2567,17 +4635,44 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2602,6 +4697,26 @@ "mime-types": "~2.1.24" } }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "requires": { + "bluebird": "^3.7.2" + } + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2621,12 +4736,22 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2641,17 +4766,84 @@ "isexe": "^2.0.0" } }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } } diff --git a/package.json b/package.json index 09b3bc32..2988e923 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,16 @@ "start": "nodemon index.js" }, "dependencies": { - "express": "^4.18.1" + "cors": "^2.8.5", + "dotenv": "^16.4.1", + "express": "^4.18.1", + "express-oauth2-jwt-bearer": "^1.6.0", + "i": "^0.3.7", + "pg": "^8.11.3", + "sequelize": "^6.36.0" }, "devDependencies": { - "eslint": "^8.16.0" + "eslint": "^8.16.0", + "sequelize-cli": "^6.6.2" } } diff --git a/routers/BenefitRouter.js b/routers/BenefitRouter.js new file mode 100644 index 00000000..469a0b1f --- /dev/null +++ b/routers/BenefitRouter.js @@ -0,0 +1,15 @@ +const express = require("express"); +const router = express.Router(); + +class BenefitRouter { + constructor(benefitController) { + this.controller = benefitController; + } + + routes() { + router.get("/", this.controller.getAll.bind(this.controller)); + return router; // Return the router instance + } +} + +module.exports = BenefitRouter; diff --git a/routers/EmployerRouter.js b/routers/EmployerRouter.js new file mode 100644 index 00000000..94172b33 --- /dev/null +++ b/routers/EmployerRouter.js @@ -0,0 +1,38 @@ +const express = require("express"); +const router = express.Router(); + +class EmployerRouter { + constructor(employerController) { + this.controller = employerController; + } + + routes() { + router.get("/", this.controller.getAll.bind(this.controller)); + router.post("/", this.controller.addEmployer.bind(this.controller)); + router.post( + "/:employerId", + this.controller.updateEmployer.bind(this.controller) + ); + + // <------------------------ JOB LISTING ------------------------ > + + router.post( + "/:employerId/job", + this.controller.addJobListing.bind(this.controller) + ); + //for getting all job listings related to the employer + router.get( + "/:employerId/job", + this.controller.getJobListing.bind(this.controller) + ); + //for getting the specific one joblisting with the id and the employer + router.get( + "/:employerId/job/:jobListingId", + this.controller.getOneJobListingApps.bind(this.controller) + ); + + return router; // Return the router instance + } +} + +module.exports = EmployerRouter; diff --git a/routers/TalentRouter.js b/routers/TalentRouter.js new file mode 100644 index 00000000..7fbdf67d --- /dev/null +++ b/routers/TalentRouter.js @@ -0,0 +1,163 @@ +const express = require("express"); +const router = express.Router(); + +class TalentRouter { + constructor(talentController, checkJwt) { + this.talentController = talentController; + this.checkJwt = checkJwt; + } + + routes() { + router.get("/", this.talentController.getAll.bind(this.talentController)); + router.post( + "/", + this.checkJwt, + this.talentController.addTalent.bind(this.talentController) + ); + + router.post( + "/:talentId", + this.talentController.updateTalent.bind(this.talentController) + ); + + router.put( + "/:talentId", + this.checkJwt, + this.talentController.editTalentName.bind(this.talentController) + ); + + // <------------------------ RESUME ------------------------ > + + router.post( + "/:talentId/resume", + this.talentController.addResume.bind(this.talentController) + ); + router.get( + "/:talentId/resume", + this.talentController.getResume.bind(this.talentController) + ); + router.put( + "/:talentId/resume", + this.talentController.updateResume.bind(this.talentController) + ); + + // <------------------------ WORK EXPERIENCE ------------------------ > + + router.post( + "/:talentId/workexperience", + this.checkJwt, + this.talentController.addWorkExperience.bind(this.talentController) + ); + router.get( + "/:talentId/workexperience", + this.talentController.getWorkExperiences.bind(this.talentController) + ); + + router.put( + "/:talentId/workexperience", + this.checkJwt, + this.talentController.updateWorkExp.bind(this.talentController) + ); + + router.delete( + "/:talentId/workexperience/:workExpID", + this.checkJwt, + this.talentController.deleteWorkExp.bind(this.talentController) + ); + + // <------------------------ SKILL SET ------------------------ > + + router.post( + "/:talentId/skill", + this.checkJwt, + this.talentController.addSkillSet.bind(this.talentController) + ); + router.get( + "/:talentId/skill", + this.talentController.getSkillSet.bind(this.talentController) + ); + + router.put( + "/:talentId/skill", + this.checkJwt, + this.talentController.updateSkill.bind(this.talentController) + ); + + router.delete( + "/:talentId/skill/:skillId", + this.checkJwt, + this.talentController.deleteSkill.bind(this.talentController) + ); + + // <------------------------ EDUCATION ------------------------ > + + router.post( + "/:talentId/education", + this.checkJwt, + this.talentController.addEducation.bind(this.talentController) + ); + router.get( + "/:talentId/education", + this.talentController.getEducation.bind(this.talentController) + ); + router.put( + "/:talentId/education", + this.checkJwt, + this.talentController.updateEdu.bind(this.talentController) + ); + + router.delete( + "/:talentId/education/:educationID", + this.checkJwt, + this.talentController.deleteEdu.bind(this.talentController) + ); + + // <------------------------ BENEFIT ------------------------ > + + router.get( + "/:talentId/benefits", + this.talentController.getBenefit.bind(this.talentController) + ); + + router.post( + "/:talentId/benefits", + this.checkJwt, + this.talentController.addBenefit.bind(this.talentController) + ); + + // <------------------- JOB LISTINGS ------------------- > + + router.get( + "/:talentId/joblistings", + this.checkJwt, + this.talentController.getEmAndJobListing.bind(this.talentController) + ); + + router.get( + "/:talentId/alljoblistings", + this.talentController.getAllApplications.bind(this.talentController) + ); + + // <------------------- APPLICATION ------------------- > + + router.post( + "/:talentId/applications", + this.checkJwt, + this.talentController.addApplication.bind(this.talentController) + ); + + router.get( + "/:talentId/applications", + this.talentController.getApplications.bind(this.talentController) + ); + + router.put( + "/:talentId/applications", + this.talentController.putApplicationStatus.bind(this.talentController) + ); + + return router; // Return the router instance + } +} + +module.exports = TalentRouter;