Merge branch 'feature/integrate-playwright' into feature/dashboard

This commit is contained in:
Keith Solomon
2025-05-25 17:40:08 -05:00
3 changed files with 94 additions and 12 deletions

13
helpers/utils.js Normal file
View File

@@ -0,0 +1,13 @@
/**
* Utility functions for the application.
*/
const isValidDomain = (domain) => {
// Regular expression to validate a domain name
const domainRegex = /^(?!:\/\/)([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/;
return domainRegex.test(domain);
}
module.exports = {
isValidDomain
};

View File

@@ -3,6 +3,7 @@
*/ */
const { supabase } = require('../auth'); const { supabase } = require('../auth');
const { isValidDomain } = require('../helpers/utils');
class SiteModel { class SiteModel {
@@ -16,11 +17,25 @@ class SiteModel {
* *
* @returns {Promise<Object>} - The result of the insert operation. * @returns {Promise<Object>} - The result of the insert operation.
*/ */
async insert(name, domainName) { async insert(domainName) {
const { error } = await supabase.from(siteModel.tableName).insert({ // validate inputs
name: name, if (!domainName) {
throw new Error('Name and domain name are required to insert a site.');
}
// validate domain name format
if (!isValidDomain(domainName)) {
throw new Error('Invalid domain name format.');
}
// check if the domain name already exists
if (await this.getByDomainName(domainName).then(data => data.length !== 0)) {
throw new Error('Domain name already exists.');
}
const { data, error } = await supabase.from(SiteModel.tableName).insert({
domain_name: domainName, domain_name: domainName,
}); }).select();
if (error) { if (error) {
console.error('Error inserting site:', error); console.error('Error inserting site:', error);
@@ -64,6 +79,24 @@ class SiteModel {
return data; return data;
} }
/**
* Retrieves a site by its domain name.
*
* @param {string} domainName - The domain name of the site.
*
* @returns {Promise<Object>} - The site object.
*/
async getByDomainName(domainName) {
const { data, error } = await supabase.from(SiteModel.tableName).select('*').eq('domain_name', domainName);
if (error) {
console.error('Error fetching site by domain name:', error);
throw error;
}
return data;
}
} }
module.exports = SiteModel; module.exports = SiteModel;

View File

@@ -21,8 +21,14 @@ router.get('/', async function(req, res, next) {
*/ */
router.get('/:id', async function(req, res, next) { router.get('/:id', async function(req, res, next) {
const siteId = req.params.id; const siteId = req.params.id;
let site = null;
const site = await siteModel.getById(siteId); try {
site = await siteModel.getById(siteId);
} catch (error) {
console.error('Error fetching site by ID:', error);
return res.status(400).send('Error fetching site: ' + error.message);
}
if (!site) { if (!site) {
return res.status(404).send('Site not found'); return res.status(404).send('Site not found');
@@ -31,22 +37,52 @@ router.get('/:id', async function(req, res, next) {
} }
}); });
/**
* GET site by domain name.
*
* Returns a specific site by its domain name in JSON format.
*/
router.get('/domain/:domain', async function(req, res, next) {
const domainName = req.params.domain;
let sites = null;
try {
sites = await siteModel.getByDomainName(domainName);
} catch (error) {
console.error('Error fetching site by domain name:', error);
return res.status(400).send('Error fetching site: ' + error.message);
}
console.log('Site found:', sites);
if (!sites || sites.length === 0) {
return res.status(404).send('Site not found');
} else {
res.json(sites[0]); // Return the first match
}
});
/** /**
* POST create a new site. * POST create a new site.
* *
* Creates a new site with the provided domain name. * Creates a new site with the provided domain name.
* *
* // TODO: Implement validation for domain name format
* // TODO: Implement error handling for duplicate domains
* // TODO: Ability to add additional site properties (e.g., name, description) * // TODO: Ability to add additional site properties (e.g., name, description)
*/ */
router.post('/add/:domain', function(req, res, next) { router.post('/add', async function(req, res, next) {
const domain = req.params.domain; const domain = req.body.domain;
let newSite = null;
const newSite = siteModel.insert(domain); // insert method passes a lot of validation errors to the caller
try {
newSite = await siteModel.insert(domain);
} catch (error) {
console.error('Error creating site:', error);
return res.status(400).send('Error creating site: ' + error.message);
}
if (!newSite) { if (!newSite) {
return res.status(400).send('Error creating site'); res.status(400).send('Error creating site');
} else { } else {
res.status(201).json(newSite); res.status(201).json(newSite);
} }