mirror of
https://github.com/jambonz/jambonz-node.git
synced 2026-10-30 15:14:29 +00:00
add support for env schema, allowing users to provide environment variables for an application
This commit is contained in:
1 parent
117f0b93e7
commit
9d91683c6b
16 files changed
+548
-18
No files matched your search
@@ -0,0 +1,156 @@
|
||||
const Ajv = require('ajv');
|
||||
const addFormats = require('ajv-formats');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const schemaPath = path.join(__dirname, 'schema/app-schema.json');
|
||||
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
|
||||
|
||||
/**
|
||||
* Gets the appropriate configuration from app.json based on the request path
|
||||
* @param {Object} params - Parameters object
|
||||
* @param {string} params.urlPath - The request path to match against
|
||||
* @param {string} params.appJsonPath - Path to app.json file
|
||||
* @returns {Object} - Result with { success: boolean, config: Object, error: string }
|
||||
*/
|
||||
function getAppConfig({ urlPath, appJsonPath }) {
|
||||
try {
|
||||
if (!appJsonPath) {
|
||||
return {
|
||||
success: false,
|
||||
config: {},
|
||||
error: 'appJsonPath is required'
|
||||
};
|
||||
}
|
||||
|
||||
if (!fs.existsSync(appJsonPath)) {
|
||||
return {
|
||||
success: false,
|
||||
config: {},
|
||||
error: `app.json file not found at ${appJsonPath}`
|
||||
};
|
||||
}
|
||||
|
||||
// Read and parse app.json
|
||||
const appJson = JSON.parse(fs.readFileSync(appJsonPath, 'utf8'));
|
||||
|
||||
// Get regular (non-slash) properties
|
||||
const regularProperties = Object.entries(appJson)
|
||||
.filter(([key]) => !key.startsWith('/'))
|
||||
.reduce((acc, [key, value]) => {
|
||||
// If the property is marked as obscure, replace its value with asterisks
|
||||
if (value.obscure && value.value) {
|
||||
acc[key] = {
|
||||
...value,
|
||||
value: '*'.repeat(value.value.length)
|
||||
};
|
||||
} else {
|
||||
acc[key] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Check for a matching path property
|
||||
const pathProperty = appJson[urlPath];
|
||||
if (pathProperty) {
|
||||
// Combine path-specific properties with regular properties
|
||||
// Path-specific properties take precedence
|
||||
const mergedConfig = {
|
||||
...regularProperties,
|
||||
...pathProperty
|
||||
};
|
||||
|
||||
// Handle obscure properties in path-specific config
|
||||
Object.entries(pathProperty).forEach(([key, value]) => {
|
||||
if (value.obscure && value.value) {
|
||||
mergedConfig[key] = {
|
||||
...value,
|
||||
value: '*'.repeat(value.value.length)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
config: mergedConfig,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
|
||||
// If no matching path property, return only the regular properties
|
||||
return {
|
||||
success: true,
|
||||
config: regularProperties,
|
||||
error: null
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
success: false,
|
||||
config: {},
|
||||
error: `Error reading app.json: ${err.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a jambonz application configuration against the schema
|
||||
* @param {Object} config - The configuration object to validate
|
||||
* @returns {Object} - Validation result with { isValid: boolean, errors: Array<string> }
|
||||
*/
|
||||
function validateAppConfig(config) {
|
||||
try {
|
||||
const ajv = new Ajv({ allErrors: true });
|
||||
addFormats(ajv);
|
||||
|
||||
const validate = ajv.compile(schema);
|
||||
const errors = [];
|
||||
|
||||
// Validate each property in the config
|
||||
Object.entries(config).forEach(([key, value]) => {
|
||||
if (key.startsWith('/')) {
|
||||
// For slash properties, validate each property within the path object
|
||||
Object.entries(value).forEach(([propKey, propValue]) => {
|
||||
const isValid = validate(propValue);
|
||||
if (!isValid) {
|
||||
errors.push(...validate.errors.map((err) => {
|
||||
const errPath = err.instancePath ?
|
||||
` at path ${key}.${propKey}${err.instancePath}` : ` at path ${key}.${propKey}`;
|
||||
const message = err.message || 'Unknown error';
|
||||
const params = err.params ?
|
||||
` (${Object.entries(err.params).map(([k, v]) => `${k}: ${v}`).join(', ')})` : '';
|
||||
return `${message}${errPath}${params}`;
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// For non-slash properties, validate the property directly
|
||||
const isValid = validate(value);
|
||||
if (!isValid) {
|
||||
errors.push(...validate.errors.map((err) => {
|
||||
const errPath = err.instancePath ? ` at path ${key}${err.instancePath}` : ` at path ${key}`;
|
||||
const message = err.message || 'Unknown error';
|
||||
const params = err.params ?
|
||||
` (${Object.entries(err.params).map(([k, v]) => `${k}: ${v}`).join(', ')})` : '';
|
||||
return `${message}${errPath}${params}`;
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
isValid: errors.length === 0,
|
||||
errors
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
isValid: false,
|
||||
errors: [`Error during validation: ${err.message}`]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateAppConfig,
|
||||
getAppConfig,
|
||||
schema
|
||||
};
|
||||
Reference in new issue
Block a user