israeli-banks-actual-budget-importer 1.2.5 → 1.3.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/CHANGELOG.md +12 -0
- package/README.md +4 -1
- package/compose.yml +6 -3
- package/package.json +3 -1
- package/src/index.ts +50 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [1.3.0](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/compare/v1.2.5...v1.3.0) (2025-05-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* update schedule environment variable for periodic imports in docker compose ([82344ef](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/82344ef9d4a4629af884bd8adb87c7cbac87628d))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add cron scheduling support for periodic imports and update dependencies ([03fc0c3](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/03fc0c3cee132ab7c513e0547337e5dcce590914))
|
|
12
|
+
|
|
1
13
|
## [1.2.5](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/compare/v1.2.4...v1.2.5) (2025-05-12)
|
|
2
14
|
|
|
3
15
|
|
package/README.md
CHANGED
|
@@ -30,10 +30,13 @@ services:
|
|
|
30
30
|
image: tomerh2001/israeli-banks-actual-budget-importer:latest
|
|
31
31
|
cap_add:
|
|
32
32
|
- SYS_ADMIN
|
|
33
|
+
environment:
|
|
34
|
+
- TZ=Asia/Jerusalem
|
|
35
|
+
- SCHEDULE=0 0 * * * # Optional (Used to run periodically - remove to run once)
|
|
33
36
|
volumes:
|
|
34
37
|
- ./config.json:/app/config.json
|
|
35
38
|
- ./cache:/app/cache # Optional
|
|
36
|
-
- ./chrome-data:/app/chrome-data # Optional (
|
|
39
|
+
- ./chrome-data:/app/chrome-data # Optional (Used to solve 2FA issues like with hapoalim)
|
|
37
40
|
```
|
|
38
41
|
|
|
39
42
|
### Prerequisites
|
package/compose.yml
CHANGED
|
@@ -5,9 +5,12 @@ services:
|
|
|
5
5
|
cap_add:
|
|
6
6
|
- SYS_ADMIN
|
|
7
7
|
platform: linux/amd64
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
build:
|
|
9
|
+
context: .
|
|
10
|
+
dockerfile: Dockerfile
|
|
11
|
+
environment:
|
|
12
|
+
- TZ=Asia/Jerusalem
|
|
13
|
+
- SCHEDULE=0 0 * * *
|
|
11
14
|
volumes:
|
|
12
15
|
- ./config.json:/app/config.json
|
|
13
16
|
- ./cache:/app/cache
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.3.0",
|
|
3
3
|
"name": "israeli-banks-actual-budget-importer",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
"packageManager": "yarn@4.9.1",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@actual-app/api": "^25.5.0",
|
|
29
|
+
"cronstrue": "^2.61.0",
|
|
29
30
|
"israeli-bank-scrapers": "^5.4.7",
|
|
30
31
|
"lodash": "^4.17.21",
|
|
31
32
|
"moment": "^2.30.1",
|
|
33
|
+
"node-cron": "^4.0.7",
|
|
32
34
|
"p-queue": "^8.1.0",
|
|
33
35
|
"tsx": "^4.19.4"
|
|
34
36
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,27 +8,63 @@ import _ from 'lodash';
|
|
|
8
8
|
import actual from '@actual-app/api';
|
|
9
9
|
import Queue from 'p-queue';
|
|
10
10
|
import moment from 'moment';
|
|
11
|
+
import cron, {type ScheduledTask, validate} from 'node-cron';
|
|
12
|
+
import cronstrue from 'cronstrue';
|
|
11
13
|
import config from '../config.json' assert {type: 'json'};
|
|
12
14
|
import type {ConfigBank} from './config.d.ts';
|
|
13
15
|
import {scrapeAndImportTransactions} from './utils.ts';
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
concurrency: 10,
|
|
17
|
-
autoStart: true,
|
|
18
|
-
interval: 1000,
|
|
19
|
-
intervalCap: 10,
|
|
20
|
-
});
|
|
17
|
+
let scheduledTask: ScheduledTask;
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
async function run() {
|
|
20
|
+
const queue = new Queue({
|
|
21
|
+
concurrency: 10,
|
|
22
|
+
autoStart: true,
|
|
23
|
+
interval: 1000,
|
|
24
|
+
intervalCap: 10,
|
|
25
|
+
});
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
+
await actual.init(config.actual.init);
|
|
28
|
+
await actual.downloadBudget(config.actual.budget.syncId, config.actual.budget);
|
|
29
|
+
|
|
30
|
+
for (const [companyId, bank] of _.entries(config.banks) as Array<[CompanyTypes, ConfigBank]>) {
|
|
31
|
+
await queue.add(async () => scrapeAndImportTransactions({companyId, bank}));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await queue.onIdle();
|
|
35
|
+
await actual.shutdown();
|
|
36
|
+
|
|
37
|
+
console.log('Done');
|
|
38
|
+
|
|
39
|
+
setTimeout(() => process.exit(0), moment.duration(5, 'seconds').asMilliseconds());
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
async function safeRun() {
|
|
43
|
+
try {
|
|
44
|
+
await run();
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Error running scraper:', error);
|
|
47
|
+
} finally {
|
|
48
|
+
if (scheduledTask) {
|
|
49
|
+
printNextRunTime();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
31
53
|
|
|
32
|
-
|
|
54
|
+
function printNextRunTime() {
|
|
55
|
+
const nextRun = scheduledTask.getNextRun();
|
|
56
|
+
console.log('Next run:', moment(nextRun).fromNow(), 'at', moment(nextRun).format('YYYY-MM-DD HH:mm:ss'));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (process.env?.SCHEDULE) {
|
|
60
|
+
if (!validate(process.env.SCHEDULE)) {
|
|
61
|
+
throw new Error(`Invalid cron schedule: ${process.env?.SCHEDULE}`);
|
|
62
|
+
}
|
|
33
63
|
|
|
34
|
-
|
|
64
|
+
console.log('Started scheduled run:', process.env?.SCHEDULE, `(${cronstrue.toString(process.env?.SCHEDULE)})`);
|
|
65
|
+
scheduledTask = cron.schedule(process.env.SCHEDULE, safeRun);
|
|
66
|
+
|
|
67
|
+
printNextRunTime();
|
|
68
|
+
} else {
|
|
69
|
+
await safeRun();
|
|
70
|
+
}
|