Files
p2ns/plugin-sites/global.profile/routes/fields.js
T
2025-12-17 20:05:50 -05:00

109 lines
3.5 KiB
JavaScript

/**
* Global Profile Plugin - Fields Routes
*
* Handles custom fields management API endpoints
*/
const sdk = require('../../../includes/plugins/sdk');
/**
* Handle fields-related routes
*/
async function handleFieldsRoutes(req, res, path, query, method) {
// GET /api/fields - Get all registered fields
if (path === 'api/fields' && method === 'GET') {
try {
await sdk.db.ready();
const fields = await sdk.db.find('@profile/fields', {});
return sdk.router.json(res, { fields: fields || [] });
} catch (err) {
sdk.log.error('global.profile', `Error getting fields: ${err.message}`);
if (err.message && err.message.includes('Database not initialized')) {
return sdk.router.json(res, { fields: [], error: 'Database not ready' }, 503);
}
return sdk.router.error(res, 'Failed to retrieve fields', 500);
}
}
// POST /api/fields - Register a new custom field
if (path === 'api/fields' && method === 'POST') {
// Require authentication for write operations
const peerId = await sdk.auth.requireLocalPeer(req, res);
if (!peerId) return true; // 401 already sent
let body = '';
req.on('data', chunk => { body += chunk.toString(); });
req.on('end', async () => {
try {
if (!body) {
return sdk.router.error(res, 'Request body is required', 400);
}
let fieldData;
try {
fieldData = JSON.parse(body);
} catch (parseErr) {
return sdk.router.error(res, 'Invalid JSON in request body', 400);
}
const pluginDomain = process.env.PLUGIN_DOMAIN || 'unknown';
if (!fieldData.fieldKey || !fieldData.label || !fieldData.type) {
return sdk.router.error(res, 'Missing required fields: fieldKey, label, type', 400);
}
// Validate fieldKey format
if (typeof fieldData.fieldKey !== 'string' || fieldData.fieldKey.trim() === '') {
return sdk.router.error(res, 'fieldKey must be a non-empty string', 400);
}
// Validate type
const validTypes = ['string', 'number', 'boolean', 'array', 'object'];
if (!validTypes.includes(fieldData.type)) {
return sdk.router.error(res, `type must be one of: ${validTypes.join(', ')}`, 400);
}
await sdk.db.ready();
// Check if field already exists
const existing = await sdk.db.get('@profile/fields', { fieldKey: fieldData.fieldKey });
if (existing && existing.registeredBy !== pluginDomain) {
return sdk.router.error(res, 'Field already registered by another plugin', 409);
}
const fieldDef = {
fieldKey: fieldData.fieldKey,
registeredBy: pluginDomain,
label: fieldData.label,
type: fieldData.type,
description: fieldData.description || '',
defaultValue: fieldData.defaultValue ? JSON.stringify(fieldData.defaultValue) : ''
};
await sdk.db.insert('@profile/fields', fieldDef);
await sdk.db.flush();
return sdk.router.json(res, { success: true, field: fieldDef });
} catch (err) {
sdk.log.error('global.profile', `Error registering field: ${err.message}`);
if (err.message && err.message.includes('Unexpected token')) {
return sdk.router.error(res, 'Invalid JSON in request body', 400);
}
return sdk.router.error(res, err.message, 500);
}
});
return true;
}
return false; // Not handled by this module
}
module.exports = {
handleFieldsRoutes
};