| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- const fs = require('fs');
- const path = require('path');
- const os = require('os');
- const { PACKAGE_ROOT, outputsRoot } = require('./output-paths');
- const RELAY_CONFIG_FILE = path.join(outputsRoot(), 'webhook', 'relay-config.json');
- const CROSS_PROJECT_CREDENTIALS_FILE = path.join(os.homedir(), '.qiwe-skill', 'relay-credentials.json');
- function ensureDir(filePath) {
- const dir = path.dirname(filePath);
- if (!fs.existsSync(dir)) {
- fs.mkdirSync(dir, { recursive: true });
- }
- }
- function readJsonMaybe(filePath) {
- try {
- if (!filePath || !fs.existsSync(filePath)) return {};
- return JSON.parse(fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, ''));
- } catch {
- return {};
- }
- }
- function readEnvLocal() {
- const candidates = [
- path.resolve(process.cwd(), '.env.local'),
- path.resolve(process.cwd(), '.env'),
- path.join(PACKAGE_ROOT, '.env.local'),
- path.join(PACKAGE_ROOT, '.env')
- ];
- const env = {};
- for (const envPath of [...new Set(candidates)]) {
- if (!fs.existsSync(envPath)) continue;
- const content = fs.readFileSync(envPath, 'utf8').replace(/^\uFEFF/, '');
- for (const rawLine of content.split(/\r?\n/)) {
- const line = rawLine.trim();
- if (!line || line.startsWith('#')) continue;
- const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
- if (!match || env[match[1]]) continue;
- let value = match[2].trim();
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
- env[match[1]] = value;
- }
- }
- return env;
- }
- function readRelayConfigFile() {
- return readJsonMaybe(RELAY_CONFIG_FILE);
- }
- function writeRelayConfigFile(config) {
- ensureDir(RELAY_CONFIG_FILE);
- const current = readRelayConfigFile();
- fs.writeFileSync(
- RELAY_CONFIG_FILE,
- JSON.stringify({ ...current, ...config, updatedAt: new Date().toISOString() }, null, 2),
- 'utf8'
- );
- }
- function isRelayEnabled() {
- const env = readEnvLocal();
- const baseUrl = process.env.RELAY_BASE_URL || env.RELAY_BASE_URL || readRelayConfigFile().relayBaseUrl || '';
- const apiKey = process.env.TENANT_API_KEY || env.TENANT_API_KEY || '';
- const apiSecret = process.env.TENANT_API_SECRET || env.TENANT_API_SECRET || '';
- return !!(baseUrl && apiKey && apiSecret);
- }
- function getRelayBaseUrl() {
- const env = readEnvLocal();
- return (process.env.RELAY_BASE_URL || env.RELAY_BASE_URL || readRelayConfigFile().relayBaseUrl || 'http://8.138.37.248:4000').replace(/\/$/, '');
- }
- function getTenantApiKey() {
- const env = readEnvLocal();
- return process.env.TENANT_API_KEY || env.TENANT_API_KEY || '';
- }
- function getTenantApiSecret() {
- const env = readEnvLocal();
- return process.env.TENANT_API_SECRET || env.TENANT_API_SECRET || '';
- }
- function getTenantId() {
- const env = readEnvLocal();
- return process.env.TENANT_ID || env.TENANT_ID || readRelayConfigFile().tenantId || '';
- }
- function getRelayPrivateKey() {
- const env = readEnvLocal();
- return (process.env.RELAY_PRIVATE_KEY || env.RELAY_PRIVATE_KEY || '').replace(/\\n/g, '\n');
- }
- function getRelayPublicKey() {
- return readRelayConfigFile().publicKey || '';
- }
- function getRelayDeviceGuid() {
- return readRelayConfigFile().deviceGuid || '';
- }
- function getRelayCredentials() {
- return {
- relayBaseUrl: getRelayBaseUrl(),
- tenantId: getTenantId(),
- tenantApiKey: getTenantApiKey(),
- tenantApiSecret: getTenantApiSecret(),
- privateKey: getRelayPrivateKey(),
- publicKey: getRelayPublicKey(),
- deviceGuid: getRelayDeviceGuid()
- };
- }
- function normalizePrivateKey(privateKey) {
- return privateKey
- .replace(/\r\n/g, '\n')
- .replace(/\n/g, '\\n');
- }
- function saveRelayCredentialsToEnv(creds, envPath) {
- const targetPath = envPath || path.join(PACKAGE_ROOT, '.env.local');
- ensureDir(targetPath);
- let content = '';
- if (fs.existsSync(targetPath)) {
- content = fs.readFileSync(targetPath, 'utf8');
- }
- const normalizedPrivateKey = creds.privateKey ? normalizePrivateKey(creds.privateKey) : '';
- const entries = {
- RELAY_BASE_URL: creds.relayBaseUrl || getRelayBaseUrl(),
- TENANT_ID: creds.tenantId || '',
- TENANT_API_KEY: creds.tenantApiKey || '',
- TENANT_API_SECRET: creds.tenantApiSecret || '',
- RELAY_PRIVATE_KEY: normalizedPrivateKey
- };
- for (const [key, value] of Object.entries(entries)) {
- if (!value) continue;
- const regex = new RegExp(`^${key}\\s*=.*$`, 'm');
- const line = `${key}=${value}`;
- if (regex.test(content)) {
- content = content.replace(regex, line);
- } else {
- content = `${content.replace(/\n*$/, '')}${content ? '\n' : ''}${line}\n`;
- }
- }
- fs.writeFileSync(targetPath, content.trim() + '\n', 'utf8');
- for (const [key, value] of Object.entries(entries)) {
- if (value) process.env[key] = value;
- }
- return targetPath;
- }
- function saveRelayCredentials(creds) {
- const saved = [];
- try {
- saved.push(saveRelayCredentialsToEnv(creds));
- } catch (err) {
- console.warn('[RelayConfig] Failed to save .env.local:', err.message);
- }
- try {
- writeRelayConfigFile({
- relayBaseUrl: creds.relayBaseUrl || getRelayBaseUrl(),
- tenantId: creds.tenantId || '',
- publicKey: creds.publicKey || '',
- deviceGuid: creds.deviceGuid || ''
- });
- saved.push(RELAY_CONFIG_FILE);
- } catch (err) {
- console.warn('[RelayConfig] Failed to save relay-config.json:', err.message);
- }
- return saved;
- }
- function saveRelayCredentialsToFile(creds) {
- try {
- ensureDir(CROSS_PROJECT_CREDENTIALS_FILE);
- fs.writeFileSync(
- CROSS_PROJECT_CREDENTIALS_FILE,
- JSON.stringify({ ...creds, updatedAt: new Date().toISOString() }, null, 2),
- 'utf8'
- );
- return CROSS_PROJECT_CREDENTIALS_FILE;
- } catch (err) {
- console.warn('[RelayConfig] Failed to save cross-project credentials:', err.message);
- return null;
- }
- }
- function loadRelayCredentialsFromFile() {
- return readJsonMaybe(CROSS_PROJECT_CREDENTIALS_FILE);
- }
- function ensureRelayConfigDir() {
- ensureDir(RELAY_CONFIG_FILE);
- }
- module.exports = {
- RELAY_CONFIG_FILE,
- isRelayEnabled,
- getRelayBaseUrl,
- getTenantApiKey,
- getTenantApiSecret,
- getTenantId,
- getRelayPrivateKey,
- getRelayPublicKey,
- getRelayDeviceGuid,
- getRelayCredentials,
- saveRelayCredentials,
- saveRelayCredentialsToEnv,
- saveRelayCredentialsToFile,
- loadRelayCredentialsFromFile,
- writeRelayConfigFile,
- readRelayConfigFile,
- ensureRelayConfigDir,
- normalizePrivateKey
- };
|