Migrate codebase from CommonJS to ES Modules
- Convert all require()/module.exports to import/export across 260+ files
- Add "type": "module" to package.json to enable ESM by default
- Add migrations/package.json with "type": "commonjs" to keep db-migrate compatible
- Convert eslint.config.js to ESM with sourceType: "module"
- Replace __dirname/__filename with import.meta.dirname/import.meta.filename
- Replace require.main === module with process.argv[1] === import.meta.filename
- Remove 'use strict' directives (implicit in ESM)
- Convert dynamic require() in switch statements to static import lookup maps
(dns.js, domains.js, backupformats.js, backupsites.js, network.js)
- Extract self-referencing exports.CONSTANT patterns into standalone const
declarations (apps.js, services.js, locks.js, users.js, mail.js, etc.)
- Lazify SERVICES object in services.js to avoid circular dependency TDZ issues
- Add clearMailQueue() to mailer.js for ESM-safe queue clearing in tests
- Add _setMockApp() to ldapserver.js for ESM-safe test mocking
- Add _setMockResolve() wrapper to dig.js for ESM-safe DNS mocking in tests
- Convert backupupload.js to use dynamic imports so --check exits before
loading the module graph (which requires BOX_ENV)
- Update check-install to use ESM import for infra_version.js
- Convert scripts/ (hotfix, release, remote_hotfix.js, find-unused-translations)
- All 1315 tests passing
Migration stats (AI-assisted using Cursor with Claude):
- Wall clock time: ~3-4 hours
- Assistant completions: ~80-100
- Estimated token usage: ~1-2M tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 09:53:14 +01:00
import assert from 'node:assert' ;
2026-02-14 15:43:24 +01:00
import database from './database.js' ;
Migrate codebase from CommonJS to ES Modules
- Convert all require()/module.exports to import/export across 260+ files
- Add "type": "module" to package.json to enable ESM by default
- Add migrations/package.json with "type": "commonjs" to keep db-migrate compatible
- Convert eslint.config.js to ESM with sourceType: "module"
- Replace __dirname/__filename with import.meta.dirname/import.meta.filename
- Replace require.main === module with process.argv[1] === import.meta.filename
- Remove 'use strict' directives (implicit in ESM)
- Convert dynamic require() in switch statements to static import lookup maps
(dns.js, domains.js, backupformats.js, backupsites.js, network.js)
- Extract self-referencing exports.CONSTANT patterns into standalone const
declarations (apps.js, services.js, locks.js, users.js, mail.js, etc.)
- Lazify SERVICES object in services.js to avoid circular dependency TDZ issues
- Add clearMailQueue() to mailer.js for ESM-safe queue clearing in tests
- Add _setMockApp() to ldapserver.js for ESM-safe test mocking
- Add _setMockResolve() wrapper to dig.js for ESM-safe DNS mocking in tests
- Convert backupupload.js to use dynamic imports so --check exits before
loading the module graph (which requires BOX_ENV)
- Update check-install to use ESM import for infra_version.js
- Convert scripts/ (hotfix, release, remote_hotfix.js, find-unused-translations)
- All 1315 tests passing
Migration stats (AI-assisted using Cursor with Claude):
- Wall clock time: ~3-4 hours
- Assistant completions: ~80-100
- Estimated token usage: ~1-2M tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 09:53:14 +01:00
import safe from 'safetydance' ;
2015-07-20 00:09:47 -07:00
Migrate codebase from CommonJS to ES Modules
- Convert all require()/module.exports to import/export across 260+ files
- Add "type": "module" to package.json to enable ESM by default
- Add migrations/package.json with "type": "commonjs" to keep db-migrate compatible
- Convert eslint.config.js to ESM with sourceType: "module"
- Replace __dirname/__filename with import.meta.dirname/import.meta.filename
- Replace require.main === module with process.argv[1] === import.meta.filename
- Remove 'use strict' directives (implicit in ESM)
- Convert dynamic require() in switch statements to static import lookup maps
(dns.js, domains.js, backupformats.js, backupsites.js, network.js)
- Extract self-referencing exports.CONSTANT patterns into standalone const
declarations (apps.js, services.js, locks.js, users.js, mail.js, etc.)
- Lazify SERVICES object in services.js to avoid circular dependency TDZ issues
- Add clearMailQueue() to mailer.js for ESM-safe queue clearing in tests
- Add _setMockApp() to ldapserver.js for ESM-safe test mocking
- Add _setMockResolve() wrapper to dig.js for ESM-safe DNS mocking in tests
- Convert backupupload.js to use dynamic imports so --check exits before
loading the module graph (which requires BOX_ENV)
- Update check-install to use ESM import for infra_version.js
- Convert scripts/ (hotfix, release, remote_hotfix.js, find-unused-translations)
- All 1315 tests passing
Migration stats (AI-assisted using Cursor with Claude):
- Wall clock time: ~3-4 hours
- Assistant completions: ~80-100
- Estimated token usage: ~1-2M tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 09:53:14 +01:00
const APPSTORE _API _TOKEN _KEY = 'appstore_api_token' ;
const API _SERVER _ORIGIN _KEY = 'api_server_origin' ;
const AUTOUPDATE _PATTERN _KEY = 'autoupdate_pattern' ;
const CLOUDRON _AVATAR _KEY = 'cloudron_avatar' ;
const CLOUDRON _BACKGROUND _KEY = 'cloudron_background' ;
const CLOUDRON _ID _KEY = 'cloudron_id' ;
const CLOUDRON _NAME _KEY = 'cloudron_name' ;
const CONSOLE _SERVER _ORIGIN _KEY = 'console_server_origin' ;
const DASHBOARD _DOMAIN _KEY = 'dashboard_domain' ;
const DASHBOARD _SUBDOMAIN _KEY = 'dashboard_subdomain' ;
const DIRECTORY _SERVER _KEY = 'directory_server_config' ;
const DYNAMIC _DNS _KEY = 'dynamic_dns' ;
const EXTERNAL _LDAP _KEY = 'external_ldap_config' ;
const FOOTER _KEY = 'footer' ;
const FIREWALL _BLOCKLIST _KEY = 'firewall_blocklist' ;
const GHOSTS _CONFIG _KEY = 'ghosts_config' ;
const IPV4 _CONFIG _KEY = 'ipv4_config' ;
const IPV6 _CONFIG _KEY = 'ipv6_config' ;
const LANGUAGE _KEY = 'language' ;
const MAIL _DOMAIN _KEY = 'mail_domain' ;
const MAIL _SUBDOMAIN _KEY = 'mail_subdomain' ;
const OIDC _COOKIE _SECRET _KEY = 'cookie_secret' ;
const PROFILE _CONFIG _KEY = 'profile_config' ;
const REVERSE _PROXY _CONFIG _KEY = 'reverseproxy_config' ;
const SERVICES _CONFIG _KEY = 'services_config' ;
const TIME _ZONE _KEY = 'time_zone' ;
const TRUSTED _IPS _KEY = 'trusted_ips_key' ;
2015-07-20 00:09:47 -07:00
2021-08-18 13:25:42 -07:00
const SETTINGS _FIELDS = [ 'name' , 'value' ] . join ( ',' ) ;
2021-08-18 15:31:07 -07:00
const SETTINGS _BLOB _FIELDS = [ 'name' , 'valueBlob' ] . join ( ',' ) ;
2021-08-18 13:25:42 -07:00
2021-08-18 15:31:07 -07:00
async function get ( key ) {
assert . strictEqual ( typeof key , 'string' ) ;
const result = await database . query ( ` SELECT ${ SETTINGS _FIELDS } FROM settings WHERE name = ? ` , [ key ] ) ;
2021-08-18 15:40:28 -07:00
if ( result . length === 0 ) return null ; // can't return the default value here because we might need to massage/json parse the result
2021-08-18 15:31:07 -07:00
return result [ 0 ] . value ;
}
async function set ( key , value ) {
assert . strictEqual ( typeof key , 'string' ) ;
assert ( value === null || typeof value === 'string' ) ;
await database . query ( 'INSERT INTO settings (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=VALUES(value)' , [ key , value ] ) ; // don't rely on affectedRows here since it gives 2
}
2023-08-03 11:34:33 +05:30
async function getJson ( key ) {
assert . strictEqual ( typeof key , 'string' ) ;
return safe . JSON . parse ( await get ( key ) ) ;
}
async function setJson ( key , value ) {
assert . strictEqual ( typeof key , 'string' ) ;
assert . strictEqual ( typeof value , 'object' ) ; // can be null
await set ( key , value ? JSON . stringify ( value ) : null ) ;
}
2021-08-18 15:31:07 -07:00
async function getBlob ( key ) {
assert . strictEqual ( typeof key , 'string' ) ;
const result = await database . query ( ` SELECT ${ SETTINGS _BLOB _FIELDS } FROM settings WHERE name = ? ` , [ key ] ) ;
if ( result . length === 0 ) return null ;
return result [ 0 ] . valueBlob ;
}
async function setBlob ( key , value ) {
assert . strictEqual ( typeof key , 'string' ) ;
assert ( value === null || Buffer . isBuffer ( value ) ) ;
await database . query ( 'INSERT INTO settings (name, valueBlob) VALUES (?, ?) ON DUPLICATE KEY UPDATE valueBlob=VALUES(valueBlob)' , [ key , value ] ) ; // don't rely on affectedRows here since it gives 2
}
async function clear ( ) {
await database . query ( 'DELETE FROM settings' ) ;
}
2026-02-14 15:43:24 +01:00
2026-02-14 16:34:34 +01:00
const WEB _SERVER _ORIGIN _KEY = 'web_server_origin' ;
const _clear = clear ;
2026-02-14 15:43:24 +01:00
export default {
get ,
set ,
getJson ,
setJson ,
getBlob ,
setBlob ,
APPSTORE _API _TOKEN _KEY ,
API _SERVER _ORIGIN _KEY ,
AUTOUPDATE _PATTERN _KEY ,
CLOUDRON _AVATAR _KEY ,
CLOUDRON _BACKGROUND _KEY ,
CLOUDRON _ID _KEY ,
CLOUDRON _NAME _KEY ,
CONSOLE _SERVER _ORIGIN _KEY ,
DASHBOARD _DOMAIN _KEY ,
DASHBOARD _SUBDOMAIN _KEY ,
DIRECTORY _SERVER _KEY ,
DYNAMIC _DNS _KEY ,
EXTERNAL _LDAP _KEY ,
FOOTER _KEY ,
FIREWALL _BLOCKLIST _KEY ,
GHOSTS _CONFIG _KEY ,
IPV4 _CONFIG _KEY ,
IPV6 _CONFIG _KEY ,
LANGUAGE _KEY ,
MAIL _DOMAIN _KEY ,
MAIL _SUBDOMAIN _KEY ,
OIDC _COOKIE _SECRET _KEY ,
PROFILE _CONFIG _KEY ,
REVERSE _PROXY _CONFIG _KEY ,
SERVICES _CONFIG _KEY ,
TIME _ZONE _KEY ,
TRUSTED _IPS _KEY ,
WEB _SERVER _ORIGIN _KEY ,
_clear ,
2026-02-14 16:34:34 +01:00
_set : set ,
2026-02-14 15:43:24 +01:00
} ;