diff --git a/conf/base.js b/conf/base.js deleted file mode 100644 index 209e8f0..0000000 --- a/conf/base.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Base configuration - shared across all environments - */ - -module.exports = { - server: { - port: 3000, - host: '0.0.0.0' - }, - - gateway: { - url: 'http://127.0.0.1:18789', - token: 'a41984619a5f4b9bf9148ab6eb4abca53eb796d046cbbec5' - }, - - session: { - secret: 'change-me-in-production', - maxAge: 24 * 60 * 60 * 1000 // 24 hours - }, - - auth: { - disabled: false, - ldap: { - enabled: false, - url: 'ldap://localhost:389', - baseDN: 'ou=users,dc=example,dc=com', - bindDN: '', - bindPassword: '', - searchFilter: '(uid={{username}})' - } - }, - - data: { - dir: './data' - } -}; \ No newline at end of file diff --git a/conf/base.json b/conf/base.json new file mode 100644 index 0000000..d2ee6bf --- /dev/null +++ b/conf/base.json @@ -0,0 +1,27 @@ +{ + "server": { + "port": 3000, + "host": "0.0.0.0" + }, + "gateway": { + "url": "http://127.0.0.1:18789" + }, + "session": { + "secret": "change-me-in-production", + "maxAge": 86400000 + }, + "auth": { + "disabled": false, + "ldap": { + "enabled": false, + "url": "ldap://localhost:389", + "baseDN": "ou=users,dc=example,dc=com", + "bindDN": "", + "bindPassword": "", + "searchFilter": "(uid={{username}})" + } + }, + "data": { + "dir": "./data" + } +} \ No newline at end of file diff --git a/conf/development.js b/conf/development.js deleted file mode 100644 index 02892d7..0000000 --- a/conf/development.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Development environment configuration - */ - -module.exports = { - auth: { - disabled: true, // Skip auth in dev - ldap: { - enabled: false - } - }, - - server: { - // Vite runs on 5173, proxy from there - } -}; \ No newline at end of file diff --git a/conf/development.json b/conf/development.json new file mode 100644 index 0000000..7c54e5b --- /dev/null +++ b/conf/development.json @@ -0,0 +1,8 @@ +{ + "auth": { + "disabled": true, + "ldap": { + "enabled": false + } + } +} \ No newline at end of file diff --git a/conf/production.js b/conf/production.js deleted file mode 100644 index 3d7da1a..0000000 --- a/conf/production.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Production environment configuration - */ - -module.exports = { - server: { - // Use PORT env var if set, otherwise default - port: parseInt(process.env.PORT) || 3000 - }, - - session: { - // Should be set via secrets.js in production - secret: process.env.SESSION_SECRET || 'CHANGE-ME-NOW' - }, - - auth: { - disabled: false, - ldap: { - enabled: process.env.LDAP_ENABLED === 'true' - } - } -}; \ No newline at end of file diff --git a/conf/production.json b/conf/production.json new file mode 100644 index 0000000..e4075ac --- /dev/null +++ b/conf/production.json @@ -0,0 +1,11 @@ +{ + "server": { + "port": 3000 + }, + "session": { + "secret": "CHANGE-ME-NOW" + }, + "auth": { + "disabled": false + } +} \ No newline at end of file diff --git a/conf/secrets.example.js b/conf/secrets.example.js deleted file mode 100644 index 4725417..0000000 --- a/conf/secrets.example.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Example secrets file - * - * Copy this to secrets.js and fill in your actual values - * secrets.js is ignored by git - */ - -module.exports = { - gateway: { - // Your OpenClaw gateway token - token: 'your-gateway-token-here' - }, - - session: { - // Random string for session signing - secret: 'generate-a-random-string-here' - }, - - auth: { - ldap: { - // LDAP bind credentials (if needed for search) - bindDN: 'cn=admin,dc=example,dc=com', - bindPassword: 'ldap-admin-password' - } - } -}; \ No newline at end of file diff --git a/conf/secrets.example.json b/conf/secrets.example.json new file mode 100644 index 0000000..3ee7d5b --- /dev/null +++ b/conf/secrets.example.json @@ -0,0 +1,14 @@ +{ + "gateway": { + "token": "your-gateway-token-here" + }, + "session": { + "secret": "generate-a-random-string-here" + }, + "auth": { + "ldap": { + "bindDN": "cn=admin,dc=example,dc=com", + "bindPassword": "ldap-admin-password" + } + } +} \ No newline at end of file diff --git a/conf/secrets.json b/conf/secrets.json new file mode 100644 index 0000000..5cd5219 --- /dev/null +++ b/conf/secrets.json @@ -0,0 +1,14 @@ +{ + "gateway": { + "token": "a41984619a5f4b9bf9148ab6eb4abca53eb796d046cbbec5" + }, + "session": { + "secret": "dev-session-secret-change-in-production" + }, + "auth": { + "ldap": { + "bindDN": "", + "bindPassword": "" + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d87ceb1..01d4cf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "name": "openclaw-webui", "version": "1.0.0", "dependencies": { - "@simpleworkjs/conf": "^1.0.0", "eventsource": "^2.0.2", "express": "^4.18.2", "express-session": "^1.17.3", @@ -871,18 +870,6 @@ "win32" ] }, - "node_modules/@simpleworkjs/conf": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@simpleworkjs/conf/-/conf-1.0.0.tgz", - "integrity": "sha512-p1dQAELW0oUBRpDoz260TYw18IMI/Y11xYAb17P1MEPjsTAUB0LWE/6ZeA2VQmpU/LXoRnDysg0G/oASGILyUA==", - "license": "MIT", - "dependencies": { - "extend": "^3.0.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1448,12 +1435,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, "node_modules/extsprintf": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", diff --git a/package.json b/package.json index 891a4c4..cb52fd4 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "preview": "vite preview" }, "dependencies": { - "@simpleworkjs/conf": "^1.0.0", "eventsource": "^2.0.2", "express": "^4.18.2", "express-session": "^1.17.3", diff --git a/server/config.js b/server/config.js new file mode 100644 index 0000000..87eef20 --- /dev/null +++ b/server/config.js @@ -0,0 +1,75 @@ +/** + * Simple ESM-compatible configuration loader + * Loads JSON files: base.json -> environment.json -> secrets.json + */ + +import { readFileSync, existsSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +function deepMerge(target, source) { + const result = { ...target }; + for (const key of Object.keys(source)) { + if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { + result[key] = deepMerge(result[key] || {}, source[key]); + } else { + result[key] = source[key]; + } + } + return result; +} + +function loadJsonFile(filename) { + const path = join(__dirname, '..', 'conf', filename); + if (!existsSync(path)) return {}; + try { + return JSON.parse(readFileSync(path, 'utf-8')); + } catch (err) { + console.warn(`Warning: Failed to load ${filename}:`, err.message); + return {}; + } +} + +// Load configuration +const environment = process.env.NODE_ENV || 'development'; + +const base = loadJsonFile('base.json'); +const envConfig = loadJsonFile(`${environment}.json`); +const secrets = loadJsonFile('secrets.json'); + +// Merge all configs +const config = deepMerge(deepMerge(base, envConfig), secrets); + +// Add environment info +config.environment = environment; + +// Allow env var overrides for critical settings +if (process.env.PORT) { + config.server = config.server || {}; + config.server.port = parseInt(process.env.PORT); +} + +if (process.env.OPENCLAW_GATEWAY) { + config.gateway = config.gateway || {}; + config.gateway.url = process.env.OPENCLAW_GATEWAY; +} + +if (process.env.OPENCLAW_TOKEN) { + config.gateway = config.gateway || {}; + config.gateway.token = process.env.OPENCLAW_TOKEN; +} + +if (process.env.SESSION_SECRET) { + config.session = config.session || {}; + config.session.secret = process.env.SESSION_SECRET; +} + +if (process.env.LDAP_ENABLED === 'true') { + config.auth = config.auth || {}; + config.auth.ldap = config.auth.ldap || {}; + config.auth.ldap.enabled = true; +} + +export default config; \ No newline at end of file diff --git a/server/index.js b/server/index.js index b065233..7a67140 100644 --- a/server/index.js +++ b/server/index.js @@ -18,11 +18,11 @@ import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import ldap from 'ldapjs'; import { v4 as uuidv4 } from 'uuid'; -import conf from '@simpleworkjs/conf'; +import conf from './config.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); -// Configuration via @simpleworkjs/conf +// Configuration const CONFIG = { port: conf.server?.port || 3000, gatewayUrl: conf.gateway?.url || 'http://127.0.0.1:18789', @@ -38,7 +38,8 @@ const CONFIG = { bindPassword: conf.auth?.ldap?.bindPassword || '', searchFilter: conf.auth?.ldap?.searchFilter || '(uid={{username}})' }, - dataDir: conf.data?.dir || join(__dirname, '../data') + dataDir: conf.data?.dir || join(__dirname, '../data'), + environment: conf.environment }; // Ensure data directory exists