@stamhoofd/backend-backup 2.85.4 → 2.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.ts CHANGED
@@ -1,112 +1,11 @@
1
1
  import backendEnv from '@stamhoofd/backend-env';
2
- backendEnv.load({ service: 'backup' });
3
2
 
4
- import { CORSPreflightEndpoint, Router, RouterServer } from '@simonbackx/simple-endpoints';
5
- import { CORSMiddleware, LogMiddleware } from '@stamhoofd/backend-middleware';
6
- import { loadLogger } from '@stamhoofd/logging';
7
- import { startCrons, stopCrons, waitForCrons } from '@stamhoofd/crons';
8
- import { cleanBackups } from './src/helpers/backup';
9
-
10
- process.on('unhandledRejection', (error: Error) => {
11
- console.error('unhandledRejection');
12
- console.error(error.message, error.stack);
3
+ backendEnv.load({ service: 'backup' }).catch((error) => {
4
+ console.error('Failed to load environment:', error);
13
5
  process.exit(1);
14
- });
15
-
16
- // Set timezone!
17
- process.env.TZ = 'UTC';
18
-
19
- // Quick check
20
- if (new Date().getTimezoneOffset() !== 0) {
21
- throw new Error('Process should always run in UTC timezone');
22
- }
23
-
24
- const start = async () => {
25
- console.log('Started Backup.');
26
- loadLogger();
27
- const router = new Router();
28
- await router.loadEndpoints(__dirname + '/src/endpoints');
29
- router.endpoints.push(new CORSPreflightEndpoint());
30
-
31
- const routerServer = new RouterServer(router);
32
- routerServer.verbose = false;
33
-
34
- // Send the app version along
35
- routerServer.addRequestMiddleware(LogMiddleware);
36
- routerServer.addResponseMiddleware(LogMiddleware);
37
-
38
- // Add CORS headers
39
- routerServer.addResponseMiddleware(CORSMiddleware);
40
-
41
- routerServer.listen(STAMHOOFD.PORT ?? 9090);
42
-
43
- if (routerServer.server) {
44
- // Default timeout is a bit too short
45
- routerServer.server.timeout = 15000;
46
- }
47
-
48
- if (STAMHOOFD.environment === 'development') {
49
- return;
50
- }
51
-
52
- const shutdown = async () => {
53
- console.log('Shutting down...');
54
- // Disable keep alive
55
- routerServer.defaultHeaders = Object.assign(routerServer.defaultHeaders, { Connection: 'close' });
56
- if (routerServer.server) {
57
- routerServer.server.headersTimeout = 5000;
58
- routerServer.server.keepAliveTimeout = 1;
59
- }
60
-
61
- stopCrons();
62
-
63
- if (STAMHOOFD.environment === 'development') {
64
- setTimeout(() => {
65
- console.error('Forcing exit after 5 seconds');
66
- process.exit(1);
67
- }, 5000);
68
- }
69
-
70
- try {
71
- await routerServer.close();
72
- console.log('HTTP server stopped');
73
- }
74
- catch (err) {
75
- console.error('Failed to stop HTTP server:');
76
- console.error(err);
77
- }
78
-
79
- await waitForCrons();
80
-
81
- // Should not be needed, but added for security as sometimes a promise hangs somewhere
82
- process.exit(0);
83
- };
84
-
85
- process.on('SIGTERM', () => {
86
- console.info('SIGTERM signal received.');
87
- shutdown().catch((e) => {
88
- console.error(e);
89
- process.exit(1);
90
- });
91
- });
92
-
93
- process.on('SIGINT', () => {
94
- console.info('SIGINT signal received.');
95
- shutdown().catch((e) => {
96
- console.error(e);
97
- process.exit(1);
98
- });
99
- });
100
-
101
- // Register crons
102
- await import('./src/crons');
103
- startCrons();
104
-
105
- // Clean backups on boot (bit faster to retrieve the timestamp of the last backup for the health endpoint)
106
- await cleanBackups();
107
- };
108
-
109
- start().catch((error) => {
110
- console.error('unhandledRejection', error);
6
+ }).then(async () => {
7
+ await import('./src/boot');
8
+ }).catch((error) => {
9
+ console.error('Failed to start the API:', error);
111
10
  process.exit(1);
112
11
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamhoofd/backend-backup",
3
- "version": "2.85.4",
3
+ "version": "2.87.0",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -9,24 +9,24 @@
9
9
  },
10
10
  "license": "UNLICENCED",
11
11
  "scripts": {
12
- "dev": "echo 'Waiting for shared backend packages...' && wait-on ../../shared/middleware/dist/index.js && echo 'Start building backend backup server' && concurrently -r 'yarn build --watch --preserveWatchOutput' \"wait-on ./dist/index.js && nodemon --quiet --inspect=5858 --watch dist --watch '../../../shared/*/dist/' --watch '../../shared/*/dist/' --ext .ts,.json,.sql,.js --watch .env.json --delay 1000ms --exec 'node --enable-source-maps ./dist/index.js' --signal SIGTERM\"",
12
+ "dev": "wait-on ../../shared/middleware/dist/index.js && concurrently -r 'yarn -s build --watch --preserveWatchOutput' \"wait-on ./dist/index.js && nodemon --quiet --inspect=5858 --watch dist --watch '../../../shared/*/dist/' --watch '../../shared/*/dist/' --ext .ts,.json,.sql,.js --watch .env.json --delay 1000ms --exec 'node --enable-source-maps ./dist/index.js' --signal SIGTERM\"",
13
13
  "build": "tsc -b",
14
- "build:full": "yarn clear && yarn build",
14
+ "build:full": "yarn -s clear && yarn -s build",
15
15
  "clear": "rm -rf ./dist",
16
- "start": "yarn build && node --enable-source-maps ./dist/index.js",
16
+ "start": "yarn -s build && node --enable-source-maps ./dist/index.js",
17
17
  "lint": "eslint"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@types/formidable": "3.4.5",
21
21
  "@types/luxon": "3.4.2",
22
22
  "@types/mysql": "^2.15.20",
23
- "@types/node": "^20.12"
23
+ "@types/node": "^22"
24
24
  },
25
25
  "dependencies": {
26
26
  "@aws-sdk/client-s3": "3.823.0",
27
27
  "@simonbackx/simple-endpoints": "1.20.1",
28
28
  "@simonbackx/simple-logging": "^1.0.1",
29
- "formidable": "3.5.1",
29
+ "formidable": "3.5.4",
30
30
  "luxon": "3.4.4",
31
31
  "mockdate": "^3.0.2",
32
32
  "mysql2": "^3.14.1"
@@ -34,5 +34,5 @@
34
34
  "publishConfig": {
35
35
  "access": "public"
36
36
  },
37
- "gitHead": "ecceacc395d167a6761f1425e77cfc06a31fe8a9"
37
+ "gitHead": "372713e1e4b626d6b4ce4f3d148f14948528312e"
38
38
  }
package/src/boot.ts ADDED
@@ -0,0 +1,109 @@
1
+ import { CORSPreflightEndpoint, Router, RouterServer } from '@simonbackx/simple-endpoints';
2
+ import { CORSMiddleware, LogMiddleware } from '@stamhoofd/backend-middleware';
3
+ import { loadLogger } from '@stamhoofd/logging';
4
+ import { startCrons, stopCrons, waitForCrons } from '@stamhoofd/crons';
5
+ import { cleanBackups } from './helpers/backup';
6
+
7
+ process.on('unhandledRejection', (error: Error) => {
8
+ console.error('unhandledRejection');
9
+ console.error(error.message, error.stack);
10
+ process.exit(1);
11
+ });
12
+
13
+ // Set timezone!
14
+ process.env.TZ = 'UTC';
15
+
16
+ // Quick check
17
+ if (new Date().getTimezoneOffset() !== 0) {
18
+ throw new Error('Process should always run in UTC timezone');
19
+ }
20
+
21
+ const start = async () => {
22
+ console.log('Started Backup.');
23
+ loadLogger();
24
+ const router = new Router();
25
+ await router.loadEndpoints(__dirname + '/endpoints');
26
+ router.endpoints.push(new CORSPreflightEndpoint());
27
+
28
+ const routerServer = new RouterServer(router);
29
+ routerServer.verbose = false;
30
+
31
+ // Send the app version along
32
+ routerServer.addRequestMiddleware(LogMiddleware);
33
+ routerServer.addResponseMiddleware(LogMiddleware);
34
+
35
+ // Add CORS headers
36
+ routerServer.addResponseMiddleware(CORSMiddleware);
37
+
38
+ routerServer.listen(STAMHOOFD.PORT ?? 9090);
39
+
40
+ if (routerServer.server) {
41
+ // Default timeout is a bit too short
42
+ routerServer.server.timeout = 15000;
43
+ }
44
+
45
+ if (STAMHOOFD.environment === 'development') {
46
+ return;
47
+ }
48
+
49
+ const shutdown = async () => {
50
+ console.log('Shutting down...');
51
+ // Disable keep alive
52
+ routerServer.defaultHeaders = Object.assign(routerServer.defaultHeaders, { Connection: 'close' });
53
+ if (routerServer.server) {
54
+ routerServer.server.headersTimeout = 5000;
55
+ routerServer.server.keepAliveTimeout = 1;
56
+ }
57
+
58
+ stopCrons();
59
+
60
+ if (STAMHOOFD.environment === 'development') {
61
+ setTimeout(() => {
62
+ console.error('Forcing exit after 5 seconds');
63
+ process.exit(1);
64
+ }, 5000);
65
+ }
66
+
67
+ try {
68
+ await routerServer.close();
69
+ console.log('HTTP server stopped');
70
+ }
71
+ catch (err) {
72
+ console.error('Failed to stop HTTP server:');
73
+ console.error(err);
74
+ }
75
+
76
+ await waitForCrons();
77
+
78
+ // Should not be needed, but added for security as sometimes a promise hangs somewhere
79
+ process.exit(0);
80
+ };
81
+
82
+ process.on('SIGTERM', () => {
83
+ console.info('SIGTERM signal received.');
84
+ shutdown().catch((e) => {
85
+ console.error(e);
86
+ process.exit(1);
87
+ });
88
+ });
89
+
90
+ process.on('SIGINT', () => {
91
+ console.info('SIGINT signal received.');
92
+ shutdown().catch((e) => {
93
+ console.error(e);
94
+ process.exit(1);
95
+ });
96
+ });
97
+
98
+ // Register crons
99
+ await import('./crons');
100
+ startCrons();
101
+
102
+ // Clean backups on boot (bit faster to retrieve the timestamp of the last backup for the health endpoint)
103
+ await cleanBackups();
104
+ };
105
+
106
+ start().catch((error) => {
107
+ console.error('unhandledRejection', error);
108
+ process.exit(1);
109
+ });
@@ -42,7 +42,7 @@ async function hashFile(path: string, algo = 'md5') {
42
42
  const hashFunc = createHash(algo); // you can also sha256, sha512 etc
43
43
 
44
44
  const contentStream = createReadStream(path);
45
- const updateDone = new Promise((resolve, reject) => {
45
+ const updateDone = new Promise<void>((resolve, reject) => {
46
46
  contentStream.on('data', data => hashFunc.update(data));
47
47
  contentStream.on('close', resolve);
48
48
  contentStream.on('error', reject);