scripts/local-secrets.mjs
Rama main · réplica de lectura del repositorio original.
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { resolve } from 'node:path';
import { writeFileAtomic } from './setup-config.mjs';
import { encodeEnvValue } from './env-file.mjs';
export function renderLocalEnvironment(fields) {
const settings = fields.filter(field => field.section?.id === 'local_environment');
if (!settings.length) throw new Error('The vault item has no Local application fields.');
const seen = new Set();
const lines = settings.map(field => {
const key = field.label;
if (!/^[A-Z][A-Z0-9_]*$/.test(key) || seen.has(key))
throw new Error('The vault item contains an invalid or duplicate environment field.');
seen.add(key);
const value = field.value ?? '';
if (typeof value !== 'string') throw new Error('Environment values must be text.');
return `${key}=${encodeEnvValue(value)}`;
});
return `${lines.join('\n')}\n`;
}
function pullLocalSecrets() {
const env = { ...process.env };
if (!env.OP_SERVICE_ACCOUNT_TOKEN) {
if (process.platform !== 'darwin')
throw new Error('Set OP_SERVICE_ACCOUNT_TOKEN to access the Development vault.');
const key = spawnSync('security', [
'find-generic-password', '-a', 'service-account', '-s', 'development-1password', '-w',
], { encoding: 'utf8' });
if (key.status !== 0 || !key.stdout.trim())
throw new Error('Could not read the development service-account token from Keychain.');
env.OP_SERVICE_ACCOUNT_TOKEN = key.stdout.trim();
}
const result = spawnSync('op', [
'item', 'get', 'devpush (local)', '--vault', 'Development', '--format', 'json',
], { env, encoding: 'utf8', maxBuffer: 4 * 1024 * 1024 });
if (result.status !== 0)
throw new Error('Could not read devpush (local). Check that op is installed and the service account has vault access.');
let item;
try { item = JSON.parse(result.stdout); }
catch { throw new Error('1Password returned an invalid item.'); }
if (!Array.isArray(item.fields)) throw new Error('1Password returned no item fields.');
const content = renderLocalEnvironment(item.fields);
writeFileAtomic(fileURLToPath(new URL('../app/.env', import.meta.url)), content, 0o600);
console.log('Restored app/.env from Development / devpush (local), with owner-only permissions.');
}
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
try { pullLocalSecrets(); }
catch (error) {
console.error(error.message);
process.exitCode = 1;
}
}