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' ;
import AuditSource from './auditsource.js' ;
import BoxError from './boxerror.js' ;
2026-02-14 15:43:24 +01:00
import changelog from './changelog.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 constants from './constants.js' ;
2026-02-14 15:43:24 +01:00
import dashboard from './dashboard.js' ;
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 debugModule from 'debug' ;
import eventlog from './eventlog.js' ;
2026-02-14 15:43:24 +01:00
import mailer from './mailer.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' ;
2026-02-14 15:43:24 +01:00
import users from './users.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
const debug = debugModule ( 'box:notifications' ) ;
const TYPE _CLOUDRON _INSTALLED = 'cloudronInstalled' ;
const TYPE _CLOUDRON _UPDATED = 'cloudronUpdated' ;
const TYPE _CLOUDRON _UPDATE _FAILED = 'cloudronUpdateFailed' ;
const TYPE _CERTIFICATE _RENEWAL _FAILED = 'certificateRenewalFailed' ;
const TYPE _BACKUP _CONFIG = 'backupConfig' ;
const TYPE _APP _OOM = 'appOutOfMemory' ;
const TYPE _APP _UPDATED = 'appUpdated' ;
const TYPE _BACKUP _FAILED = 'backupFailed' ;
const TYPE _APP _DOWN = 'appDown' ;
const TYPE _APP _UP = 'appUp' ;
const TYPE _DISK _SPACE = 'diskSpace' ;
const TYPE _MAIL _STATUS = 'mailStatus' ;
const TYPE _REBOOT = 'reboot' ;
const TYPE _UPDATE _UBUNTU = 'ubuntuUpdate' ;
const TYPE _BOX _UPDATE = 'boxUpdate' ;
const TYPE _MANUAL _APP _UPDATE _NEEDED = 'manualAppUpdate' ;
2018-12-17 16:37:19 +01:00
2024-12-11 22:29:00 +01:00
const NOTIFICATION _FIELDS = [ 'id' , 'eventId' , 'type' , 'title' , 'message' , 'creationTime' , 'acknowledged' , 'context' ] ;
2021-05-28 14:34:18 -07:00
function postProcess ( result ) {
assert . strictEqual ( typeof result , 'object' ) ;
result . id = String ( result . id ) ;
2023-03-26 14:42:38 +02:00
result . acknowledged = ! ! result . acknowledged ; // convert to boolean
2021-05-28 14:34:18 -07:00
return result ;
}
2023-09-22 17:58:13 +02:00
async function add ( type , title , message , data ) {
assert . strictEqual ( typeof type , 'string' ) ;
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof title , 'string' ) ;
assert . strictEqual ( typeof message , 'string' ) ;
2023-03-26 14:42:38 +02:00
assert . strictEqual ( typeof data , 'object' ) ;
2021-05-28 14:34:18 -07:00
2024-12-11 23:32:11 +01:00
debug ( ` add: ${ type } ${ title } ` ) ;
2024-12-11 22:29:00 +01:00
const query = 'INSERT INTO notifications (type, title, message, acknowledged, eventId, context) VALUES (?, ?, ?, ?, ?, ?)' ;
const args = [ type , title , message , false , data ? . eventId || null , data . context || '' ] ;
2021-05-28 14:34:18 -07:00
const result = await database . query ( query , args ) ;
return String ( result . insertId ) ;
2018-12-17 16:37:19 +01:00
}
2021-05-28 14:34:18 -07:00
async function get ( id ) {
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof id , 'string' ) ;
2023-03-26 14:42:38 +02:00
const result = await database . query ( ` SELECT ${ NOTIFICATION _FIELDS } FROM notifications WHERE id = ? ` , [ id ] ) ;
2021-05-28 14:34:18 -07:00
if ( result . length === 0 ) return null ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
return postProcess ( result [ 0 ] ) ;
2018-12-17 16:37:19 +01:00
}
2024-12-11 22:29:00 +01:00
async function getByType ( type , context ) {
2024-12-11 15:47:41 +01:00
assert . strictEqual ( typeof type , 'string' ) ;
2024-12-11 22:29:00 +01:00
assert . strictEqual ( typeof context , 'string' ) ;
2018-12-17 16:37:19 +01:00
2024-12-11 22:29:00 +01:00
const results = await database . query ( ` SELECT ${ NOTIFICATION _FIELDS } from notifications WHERE type = ? AND context = ? ORDER BY creationTime LIMIT 1 ` , [ type , context || '' ] ) ;
2021-05-28 14:34:18 -07:00
if ( results . length === 0 ) return null ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
return postProcess ( results [ 0 ] ) ;
2018-12-17 16:37:19 +01:00
}
2021-05-28 14:34:18 -07:00
async function update ( notification , data ) {
assert . strictEqual ( typeof notification , 'object' ) ;
assert . strictEqual ( typeof data , 'object' ) ;
2018-12-17 16:37:19 +01:00
2023-03-26 14:42:38 +02:00
const args = [ ] ;
const fields = [ ] ;
for ( const k in data ) {
2021-05-28 14:34:18 -07:00
fields . push ( k + ' = ?' ) ;
args . push ( data [ k ] ) ;
}
args . push ( notification . id ) ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
const result = await database . query ( 'UPDATE notifications SET ' + fields . join ( ', ' ) + ' WHERE id = ?' , args ) ;
if ( result . affectedRows !== 1 ) throw new BoxError ( BoxError . NOT _FOUND , 'Notification not found' ) ;
2018-12-17 16:37:19 +01:00
}
2018-12-17 17:35:19 +01:00
2021-05-28 14:34:18 -07:00
async function del ( id ) {
assert . strictEqual ( typeof id , 'string' ) ;
2019-01-07 14:56:43 +01:00
2021-05-28 14:34:18 -07:00
const result = await database . query ( 'DELETE FROM notifications WHERE id = ?' , [ id ] ) ;
if ( result . affectedRows !== 1 ) throw new BoxError ( BoxError . NOT _FOUND , 'Notification not found' ) ;
}
2019-01-17 13:36:54 +01:00
2021-05-28 14:34:18 -07:00
async function list ( filters , page , perPage ) {
assert . strictEqual ( typeof filters , 'object' ) ;
assert . strictEqual ( typeof page , 'number' ) ;
assert . strictEqual ( typeof perPage , 'number' ) ;
2019-01-17 13:36:54 +01:00
2023-03-26 14:42:38 +02:00
const args = [ ] ;
2019-01-07 14:56:43 +01:00
2023-03-26 14:42:38 +02:00
const where = [ ] ;
2021-05-28 14:34:18 -07:00
if ( 'acknowledged' in filters ) {
where . push ( 'acknowledged=?' ) ;
args . push ( filters . acknowledged ) ;
}
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
let query = ` SELECT ${ NOTIFICATION _FIELDS } FROM notifications ` ;
if ( where . length ) query += ' WHERE ' + where . join ( ' AND ' ) ;
2026-01-23 12:30:07 +01:00
query += ' ORDER BY creationTime DESC LIMIT ?,?' ;
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
args . push ( ( page - 1 ) * perPage ) ;
args . push ( perPage ) ;
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
const results = await database . query ( query , args ) ;
results . forEach ( postProcess ) ;
return results ;
2021-04-19 20:52:10 -07:00
}
2024-12-11 23:32:11 +01:00
async function oomEvent ( eventId , containerId , app , addonName , event ) {
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-03-06 11:54:37 -08:00
assert . strictEqual ( typeof containerId , 'string' ) ;
2021-09-19 17:32:48 -07:00
assert . strictEqual ( typeof app , 'object' ) ;
assert ( addonName === null || typeof addonName === 'string' ) ;
2019-01-07 12:57:57 +01:00
2021-09-19 17:32:48 -07:00
assert ( app || addonName ) ;
2021-01-02 11:07:44 -08:00
2023-08-11 19:41:05 +05:30
const { fqdn : dashboardFqdn } = await dashboard . getLocation ( ) ;
2021-01-02 11:07:44 -08:00
let title , message ;
2021-09-19 17:32:48 -07:00
if ( addonName ) {
if ( app ) {
title = ` The ${ addonName } service of the app at ${ app . fqdn } ran out of memory ` ;
} else {
title = ` The ${ addonName } service ran out of memory ` ;
}
2023-08-11 19:41:05 +05:30
message = ` The service has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https:// ${ dashboardFqdn } /#/services) ` ;
2021-09-19 17:32:48 -07:00
} else if ( app ) {
title = ` The app at ${ app . fqdn } ran out of memory. ` ;
2023-08-11 19:41:05 +05:30
message = ` The app has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https:// ${ dashboardFqdn } /#/app/ ${ app . id } /resources) ` ;
2019-03-06 11:54:37 -08: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
await add ( TYPE _APP _OOM , title , message , { eventId } ) ;
2024-12-11 20:44:46 +01:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _APP _OOM ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . oomEvent ( admin . email , containerId , app , addonName , event ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
}
async function appUp ( eventId , app ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _APP _UP ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . appUp ( admin . email , app ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
}
async function appDown ( eventId , app ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _APP _DOWN ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . appDown ( admin . email , app ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
2019-01-07 12:57:57 +01:00
}
2019-01-07 13:01:27 +01:00
2021-07-30 14:30:08 +02:00
async function appUpdated ( eventId , app , fromManifest , toManifest ) {
2019-05-07 12:04:43 +02:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
2021-07-30 14:30:08 +02:00
assert . strictEqual ( typeof fromManifest , 'object' ) ;
assert . strictEqual ( typeof toManifest , 'object' ) ;
2019-05-07 12:04:43 +02:00
2026-02-05 21:51:55 +01:00
if ( ! app . appStoreId && ! app . versionsUrl ) return ; // skip notification of dev apps
2020-09-03 13:26:51 -07:00
2021-07-30 14:30:08 +02:00
const tmp = toManifest . description . match ( /<upstream>(.*)<\/upstream>/i ) ;
2019-08-02 20:56:25 -07:00
const upstreamVersion = ( tmp && tmp [ 1 ] ) ? tmp [ 1 ] : '' ;
2021-07-30 14:30:08 +02:00
const title = upstreamVersion ? ` ${ toManifest . title } at ${ app . fqdn } updated to ${ upstreamVersion } (package version ${ toManifest . version } ) `
: ` ${ toManifest . title } at ${ app . fqdn } updated to package version ${ toManifest . version } ` ;
2019-08-02 20:56:25 -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
await add ( TYPE _APP _UPDATED , title , ` The application installed at https:// ${ app . fqdn } was updated. \n \n Changelog: \n ${ toManifest . changelog } \n ` , { eventId } ) ;
2019-05-07 12:04:43 +02:00
}
2024-12-11 20:44:46 +01:00
async function boxUpdated ( eventId , oldVersion , newVersion ) {
2022-04-01 13:44:46 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2024-12-11 20:44:46 +01:00
assert . strictEqual ( typeof oldVersion , 'string' ) ;
assert . strictEqual ( typeof newVersion , 'string' ) ;
2022-04-01 13:44:46 -07:00
2024-12-11 20:44:46 +01:00
const changes = changelog . getChanges ( newVersion ) ;
2022-04-01 13:44:46 -07:00
const changelogMarkdown = changes . map ( ( m ) => ` * ${ m } \n ` ) . join ( '' ) ;
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
await add ( TYPE _CLOUDRON _UPDATED , ` Cloudron updated to v ${ newVersion } ` , ` Cloudron was updated from v ${ oldVersion } to v ${ newVersion } . \n \n Changelog: \n ${ changelogMarkdown } \n ` , { eventId } ) ;
2022-04-01 13:44:46 -07:00
}
2024-12-11 20:44:46 +01:00
async function boxInstalled ( eventId , version ) {
2019-10-14 09:30:20 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2024-12-11 20:44:46 +01:00
assert . strictEqual ( typeof version , 'string' ) ;
2019-08-03 13:59:11 -07:00
2024-12-11 20:44:46 +01:00
const changes = changelog . getChanges ( version . replace ( /\.([^.]*)$/ , '.0' ) ) ; // last .0 release
2019-08-03 13:59:11 -07:00
const changelogMarkdown = changes . map ( ( m ) => ` * ${ m } \n ` ) . join ( '' ) ;
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
await add ( TYPE _CLOUDRON _INSTALLED , ` Cloudron v ${ version } installed ` , ` Cloudron v ${ version } was installed. \n \n Changelog: \n ${ changelogMarkdown } \n ` , { eventId } ) ;
2019-10-14 09:30:20 -07:00
}
2021-05-28 14:34:18 -07:00
async function boxUpdateError ( eventId , errorMessage ) {
2019-10-14 09:30:20 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof errorMessage , 'string' ) ;
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
await add ( TYPE _CLOUDRON _UPDATE _FAILED , 'Cloudron update failed' , ` Failed to update Cloudron: ${ errorMessage } . ` , { eventId } ) ;
2025-01-24 18:44:12 +01:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _CLOUDRON _UPDATE _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . boxUpdateError ( admin . email , errorMessage ) , { debug } ) ;
2025-01-24 18:44:12 +01:00
}
}
2019-08-03 13:59:11 -07:00
}
2022-07-13 09:26:27 +05:30
async function certificateRenewalError ( eventId , fqdn , errorMessage ) {
2019-03-04 14:50:56 -08:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2022-07-13 09:26:27 +05:30
assert . strictEqual ( typeof fqdn , 'string' ) ;
2019-03-04 14:50:56 -08:00
assert . strictEqual ( typeof errorMessage , 'string' ) ;
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
await add ( TYPE _CERTIFICATE _RENEWAL _FAILED , ` Certificate renewal of ${ fqdn } failed ` , ` Failed to renew certs of ${ fqdn } : ${ errorMessage } . Renewal will be retried in 12 hours. ` , { eventId } ) ;
2021-05-28 14:34:18 -07:00
2021-07-15 09:50:11 -07:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _CERTIFICATE _RENEWAL _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . certificateRenewalError ( admin . email , fqdn , errorMessage ) , { debug } ) ;
2024-12-11 18:24:20 +01:00
}
2021-07-15 09:50:11 -07:00
}
2019-03-04 14:50:56 -08:00
}
2021-05-28 14:34:18 -07:00
async function backupFailed ( eventId , taskId , errorMessage ) {
2019-03-04 15:00:23 -08:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-03-04 17:52:31 -08:00
assert . strictEqual ( typeof taskId , 'string' ) ;
2019-03-04 15:00:23 -08:00
assert . strictEqual ( typeof errorMessage , 'string' ) ;
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
await add ( TYPE _BACKUP _FAILED , 'Backup failed' , ` Backup failed: ${ errorMessage } . Logs are available [here](/logs.html?taskId= ${ taskId } ). ` , { eventId } ) ;
2021-06-23 16:50:19 -07:00
2023-08-11 19:41:05 +05:30
const { fqdn : dashboardFqdn } = await dashboard . getLocation ( ) ;
2021-07-15 09:50:11 -07:00
const superadmins = await users . getSuperadmins ( ) ;
for ( const superadmin of superadmins ) {
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
if ( superadmin . notificationConfig . includes ( TYPE _BACKUP _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . backupFailed ( superadmin . email , errorMessage , ` https:// ${ dashboardFqdn } /logs.html?taskId= ${ taskId } ` ) , { debug } ) ;
2024-12-11 18:24:20 +01:00
}
2021-07-15 09:50:11 -07:00
}
2019-03-04 15:00:23 -08:00
}
2025-01-19 10:34:12 +01:00
async function rebootRequired ( ) {
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _REBOOT ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . rebootRequired ( admin . email ) , { debug } ) ;
2025-01-19 10:34:12 +01:00
}
}
}
2025-05-07 13:15:08 +02:00
async function lowDiskSpace ( message ) {
assert . strictEqual ( typeof message , 'string' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
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
if ( admin . notificationConfig . includes ( TYPE _DISK _SPACE ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . lowDiskSpace ( admin . email , message ) , { debug } ) ;
2025-05-07 13:15:08 +02:00
}
}
}
async function onPin ( type , message ) {
2025-01-19 10:34:12 +01:00
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
2025-05-07 13:15:08 +02:00
assert . strictEqual ( typeof message , 'string' ) ;
2025-01-19 10:34:12 +01:00
switch ( type ) {
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
case TYPE _REBOOT :
2025-01-19 10:34:12 +01:00
return await rebootRequired ( ) ;
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
case TYPE _DISK _SPACE :
2025-05-07 13:15:08 +02:00
return await lowDiskSpace ( message ) ;
2025-01-19 10:34:12 +01:00
default :
break ;
}
}
2024-12-11 15:47:41 +01:00
async function pin ( type , title , message , options ) {
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
2019-02-28 14:52:14 -08:00
assert . strictEqual ( typeof title , 'string' ) ;
2019-02-06 15:47:31 +01:00
assert . strictEqual ( typeof message , 'string' ) ;
2023-03-26 15:12:00 +02:00
assert . strictEqual ( typeof options , 'object' ) ;
2019-02-06 15:47:31 +01:00
2024-12-11 22:29:00 +01:00
const result = await getByType ( type , options . context || '' ) ;
2025-01-19 10:34:12 +01:00
if ( ! result ) {
2025-05-07 13:15:08 +02:00
await onPin ( type , message ) ;
2025-01-19 10:34:12 +01:00
return await add ( type , title , message , { eventId : null , context : options . context || '' } ) ;
}
2024-12-11 15:47:41 +01:00
// do not reset the ack state if user has already seen the update notification
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 isUpdateType = type === TYPE _BOX _UPDATE || type === TYPE _MANUAL _APP _UPDATE _NEEDED ;
2024-12-11 15:47:41 +01:00
const acknowledged = ( isUpdateType && result . message === message ) ? result . acknowledged : false ;
2025-05-07 13:15:08 +02:00
if ( result . acknowledged && ! acknowledged ) await onPin ( type , message ) ;
2025-01-19 10:34:12 +01:00
2024-12-11 22:29:00 +01:00
await update ( result , { title , message , acknowledged , creationTime : new Date ( ) } ) ;
2023-03-26 15:12:00 +02:00
return result . id ;
2019-02-06 15:47:31 +01:00
}
2019-02-27 16:10:54 -08:00
2024-12-11 15:47:41 +01:00
async function unpin ( type , options ) {
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
assert . strictEqual ( typeof options , 'object' ) ;
2023-03-26 14:18:37 +02:00
2024-12-11 22:29:00 +01:00
await database . query ( 'UPDATE notifications SET acknowledged=1 WHERE type = ? AND context = ?' , [ type , options . context || '' ] ) ;
2023-03-26 14:18:37 +02:00
}
2025-01-19 10:34:12 +01:00
async function onEvent ( eventId , action , source , data ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-02-27 16:10:54 -08:00
assert . strictEqual ( typeof action , 'string' ) ;
assert . strictEqual ( typeof source , 'object' ) ;
assert . strictEqual ( typeof data , 'object' ) ;
2019-03-01 15:14:35 -08:00
switch ( action ) {
2019-03-25 14:02:23 -07:00
case eventlog . ACTION _APP _OOM :
2025-01-19 10:34:12 +01:00
return await oomEvent ( eventId , data . containerId , data . app , data . addonName , data . event ) ;
2019-03-25 14:02:23 -07:00
2024-12-11 20:44:46 +01:00
case eventlog . ACTION _APP _UP :
2025-01-19 10:34:12 +01:00
return await appUp ( eventId , data . app ) ;
2024-12-11 20:44:46 +01:00
case eventlog . ACTION _APP _DOWN :
2025-01-19 10:34:12 +01:00
return await appDown ( eventId , data . app ) ;
2024-12-11 20:44:46 +01:00
2019-05-07 12:04:43 +02:00
case eventlog . ACTION _APP _UPDATE _FINISH :
2021-09-30 09:50:30 -07:00
if ( source . username !== AuditSource . CRON . username ) return ; // updated by user
2021-07-13 13:29:42 -07:00
if ( data . errorMessage ) return ; // the update indicator will still appear, so no need to notify user
2025-01-19 10:34:12 +01:00
return await appUpdated ( eventId , data . app , data . fromManifest , data . toManifest ) ;
2019-05-07 12:04:43 +02:00
2019-03-04 14:50:56 -08:00
case eventlog . ACTION _CERTIFICATE _RENEWAL :
case eventlog . ACTION _CERTIFICATE _NEW :
2021-05-28 14:34:18 -07:00
if ( ! data . errorMessage ) return ;
2021-06-24 00:48:54 -07:00
if ( ! data . notAfter || ( data . notAfter - new Date ( ) >= ( 10 * 24 * 60 * 60 * 1000 ) ) ) return ; // more than 10 days left to expire
2025-01-19 10:34:12 +01:00
return await certificateRenewalError ( eventId , data . domain , data . errorMessage ) ;
2019-03-04 14:50:56 -08:00
2019-03-25 14:02:23 -07:00
case eventlog . ACTION _BACKUP _FINISH :
2021-05-28 14:34:18 -07:00
if ( ! data . errorMessage ) return ;
2021-09-30 09:50:30 -07:00
if ( source . username !== AuditSource . CRON . username && ! data . timedOut ) return ; // manual stop by user
2019-10-11 19:35:21 -07:00
2025-01-19 10:34:12 +01:00
return await backupFailed ( eventId , data . taskId , data . errorMessage ) ; // only notify for automated backups or timedout
2019-03-04 15:00:23 -08:00
2022-04-01 13:44:46 -07:00
case eventlog . ACTION _INSTALL _FINISH :
2025-01-19 10:34:12 +01:00
return await boxInstalled ( eventId , data . version ) ;
2022-04-01 13:44:46 -07:00
2019-08-03 13:59:11 -07:00
case eventlog . ACTION _UPDATE _FINISH :
2025-01-19 10:34:12 +01:00
if ( ! data . errorMessage ) return await boxUpdated ( eventId , data . oldVersion , data . newVersion ) ;
if ( data . timedOut ) return await boxUpdateError ( eventId , data . errorMessage ) ;
2021-05-28 14:34:18 -07:00
return ;
2019-08-03 13:59:11 -07:00
2019-03-25 14:02:23 -07:00
default :
2021-05-28 14:34:18 -07:00
return ;
2019-02-27 16:10:54 -08:00
}
}
2026-02-14 15:43:24 +01:00
2026-02-14 16:34:34 +01:00
const TYPE _DOMAIN _CONFIG _CHECK _FAILED = 'domainConfigCheckFailed' ;
2026-02-14 15:43:24 +01:00
export default {
get ,
update ,
list ,
del ,
onEvent ,
TYPE _CLOUDRON _INSTALLED ,
TYPE _CLOUDRON _UPDATED ,
TYPE _CLOUDRON _UPDATE _FAILED ,
TYPE _CERTIFICATE _RENEWAL _FAILED ,
TYPE _BACKUP _CONFIG ,
TYPE _APP _OOM ,
TYPE _APP _UPDATED ,
TYPE _BACKUP _FAILED ,
TYPE _APP _DOWN ,
TYPE _APP _UP ,
TYPE _DISK _SPACE ,
TYPE _MAIL _STATUS ,
TYPE _REBOOT ,
TYPE _UPDATE _UBUNTU ,
TYPE _BOX _UPDATE ,
TYPE _MANUAL _APP _UPDATE _NEEDED ,
TYPE _DOMAIN _CONFIG _CHECK _FAILED ,
pin ,
unpin ,
2026-02-14 16:34:34 +01:00
_add : add ,
2026-02-14 15:43:24 +01:00
} ;