@aboubacar3012/infisical-env-sync
Version:
Sync Infisical secrets to your .env files easily. Compatible with Next.js, React and all Node.js frameworks.
60 lines (55 loc) • 1.93 kB
JavaScript
// src/index.js
require('dotenv').config();
const { InfisicalSDK } = require('@infisical/sdk');
const fs = require('fs');
const getClient = (() => {
let clientInstance = null;
return async (config = {}) => {
if (clientInstance) return clientInstance;
const sdk = new InfisicalSDK({ siteUrl: config.siteUrl || process.env.SITE_URL });
await sdk.auth().universalAuth.login({
clientId: config.clientId || process.env.CLIENT_ID,
clientSecret: config.clientSecret || process.env.CLIENT_SECRET,
});
clientInstance = sdk;
return clientInstance;
};
})();
const getEnvVariables = async (env, config = {}) => {
const client = await getClient(config);
const { secrets } = await client.secrets().listSecrets({
environment: env,
projectId: config.projectId || process.env.PROJECT_ID,
secretPath: '/',
});
return secrets.map(({ secretKey, secretValue }) => ({ secretKey, secretValue }));
};
const syncEnv = async ({
env = 'dev',
envPath = '.env',
config = {},
} = {}) => {
const envVars = await getEnvVariables(env, config);
let envLines = [];
let existingVars = {};
if (fs.existsSync(envPath)) {
envLines = fs.readFileSync(envPath, 'utf-8').split(/\r?\n/);
envLines.forEach(line => {
const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
if (match) {
existingVars[match[1]] = match[2];
}
});
}
let newVars = envVars.filter(v => !(v.secretKey in existingVars));
if (newVars.length > 0) {
newVars = newVars.sort((a, b) => a.secretKey.localeCompare(b.secretKey));
if (envLines.length > 0 && envLines[envLines.length - 1].trim() !== '') envLines.push('');
newVars.forEach(v => {
envLines.push(`${v.secretKey}="${String(v.secretValue).replace(/\r?\n|\r/g, ' ')}"`);
});
}
fs.writeFileSync(envPath, envLines.join('\n'));
return { added: newVars.length };
};
module.exports = { syncEnv };