envase
Version:
Type-safe environment variable validation with Standard Schema compliance
84 lines • 3.73 kB
JavaScript
/**
* Generates markdown documentation from extracted environment variables.
*/
export const generateMarkdown = async (extractedEnvvars) => {
const lines = ['# Environment variables', ''];
const envvarsByPath = new Map();
for (const envvar of extractedEnvvars) {
const key = envvar.path.length > 0 ? envvar.path.join('.') : '';
const envvars = envvarsByPath.get(key);
if (envvars) {
envvars.push(envvar);
}
else {
envvarsByPath.set(key, [envvar]);
}
}
for (const [path, envvars] of envvarsByPath.entries()) {
if (path !== '') {
const pathParts = path.split('.');
const sectionName = pathParts
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(' ');
lines.push(`## ${sectionName}`, '');
}
for (const envvar of envvars) {
const jsonSchemaOptions = {
target: 'openapi-3.0',
libraryOptions: {
unrepresentable: 'any',
},
};
const inputSchema = envvar.schema['~standard'].jsonSchema.input(jsonSchemaOptions);
const outputSchema = envvar.schema['~standard'].jsonSchema.output(jsonSchemaOptions);
const mappedType = Array.isArray(outputSchema.anyOf)
? outputSchema.anyOf.map(({ type }) => type)
: (outputSchema.type ?? inputSchema.type);
const type = Array.isArray(mappedType)
? mappedType.map((type) => `\`${type}\``).join(' | ')
: `\`${mappedType}\``;
// inputSchema takes precedence (describes accepted format); outputSchema fills
// gaps for fields that only exist post-coercion (e.g. default on stringbool)
const schema = { ...outputSchema, ...inputSchema };
const validationResult = await envvar.schema['~standard'].validate(undefined);
const isOptional = !validationResult.issues;
let line = `- \`${envvar.envName}\` (${isOptional ? 'optional' : 'required'})`;
line += ` \n Type: ${type}`;
if (schema.description) {
line += ` \n Description: ${schema.description}`;
}
if (Array.isArray(schema.enum)) {
const enumValues = schema.enum.map((v) => `\`${v}\``).join(' | ');
line += ` \n Supported values: ${enumValues}`;
}
if (schema.format) {
line += ` \n Format: \`${schema.format}\``;
}
if (schema.pattern) {
line += ` \n Pattern: \`${schema.pattern}\``;
}
if (schema.minimum !== undefined &&
!(schema.type === 'integer' &&
schema.minimum === Number.MIN_SAFE_INTEGER)) {
line += ` \n Min value: \`${schema.minimum}\``;
}
if (schema.maximum !== undefined &&
!(schema.type === 'integer' &&
schema.maximum === Number.MAX_SAFE_INTEGER)) {
line += ` \n Max value: \`${schema.maximum}\``;
}
if (schema.minLength !== undefined) {
line += ` \n Min length: \`${schema.minLength}\``;
}
if (schema.maxLength !== undefined) {
line += ` \n Max length: \`${schema.maxLength}\``;
}
if (schema.default !== undefined) {
line += ` \n Default: \`${schema.default}\``;
}
lines.push(line, '');
}
}
return lines.join('\n');
};
//# sourceMappingURL=generate-markdown.js.map