israeli-banks-actual-budget-importer 1.2.5 → 1.3.1

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 CHANGED
@@ -1,3 +1,23 @@
1
+ ## [1.3.1](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/compare/v1.3.0...v1.3.1) (2025-05-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * ensure graceful shutdown with timeout in scheduled run ([49bc74f](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/49bc74f0e631da2f4407bdd0aae9b105f165b134))
7
+ * ensure graceful shutdown with timeout in scheduled run ([ccd946c](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/ccd946c52181a939abd044ce443acafc18319b82))
8
+
9
+ # [1.3.0](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/compare/v1.2.5...v1.3.0) (2025-05-23)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * update schedule environment variable for periodic imports in docker compose ([82344ef](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/82344ef9d4a4629af884bd8adb87c7cbac87628d))
15
+
16
+
17
+ ### Features
18
+
19
+ * add cron scheduling support for periodic imports and update dependencies ([03fc0c3](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/commit/03fc0c3cee132ab7c513e0547337e5dcce590914))
20
+
1
21
  ## [1.2.5](https://github.com/tomerh2001/israeli-banks-actual-budget-importer/compare/v1.2.4...v1.2.5) (2025-05-12)
2
22
 
3
23
 
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 (Can be used to solve 2FA issues like with hapoalim)
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
- # build:
9
- # context: .
10
- # dockerfile: Dockerfile
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.5",
2
+ "version": "1.3.1",
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
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable unicorn/no-process-exit */
2
+
2
3
  /* eslint-disable no-await-in-loop */
3
4
  /* eslint-disable n/file-extension-in-import */
4
5
 
@@ -8,27 +9,63 @@ import _ from 'lodash';
8
9
  import actual from '@actual-app/api';
9
10
  import Queue from 'p-queue';
10
11
  import moment from 'moment';
12
+ import cron, {type ScheduledTask, validate} from 'node-cron';
13
+ import cronstrue from 'cronstrue';
11
14
  import config from '../config.json' assert {type: 'json'};
12
15
  import type {ConfigBank} from './config.d.ts';
13
16
  import {scrapeAndImportTransactions} from './utils.ts';
14
17
 
15
- const queue = new Queue({
16
- concurrency: 10,
17
- autoStart: true,
18
- interval: 1000,
19
- intervalCap: 10,
20
- });
18
+ let scheduledTask: ScheduledTask;
19
+
20
+ async function run() {
21
+ const queue = new Queue({
22
+ concurrency: 10,
23
+ autoStart: true,
24
+ interval: 1000,
25
+ intervalCap: 10,
26
+ });
27
+
28
+ await actual.init(config.actual.init);
29
+ await actual.downloadBudget(config.actual.budget.syncId, config.actual.budget);
21
30
 
22
- await actual.init(config.actual.init);
23
- await actual.downloadBudget(config.actual.budget.syncId, config.actual.budget);
31
+ for (const [companyId, bank] of _.entries(config.banks) as Array<[CompanyTypes, ConfigBank]>) {
32
+ await queue.add(async () => scrapeAndImportTransactions({companyId, bank}));
33
+ }
24
34
 
25
- for (const [companyId, bank] of _.entries(config.banks) as Array<[CompanyTypes, ConfigBank]>) {
26
- await queue.add(async () => scrapeAndImportTransactions({companyId, bank}));
35
+ await queue.onIdle();
36
+ await actual.shutdown();
37
+
38
+ console.log('Done');
27
39
  }
28
40
 
29
- await queue.onIdle();
30
- await actual.shutdown();
41
+ async function safeRun() {
42
+ try {
43
+ await run();
44
+ } catch (error) {
45
+ console.error('Error running scraper:', error);
46
+ } finally {
47
+ if (scheduledTask) {
48
+ printNextRunTime();
49
+ }
50
+ }
51
+ }
31
52
 
32
- console.log('Done');
53
+ function printNextRunTime() {
54
+ const nextRun = scheduledTask.getNextRun();
55
+ console.log('Next run:', moment(nextRun).fromNow(), 'at', moment(nextRun).format('YYYY-MM-DD HH:mm:ss'));
56
+ }
57
+
58
+ if (process.env?.SCHEDULE) {
59
+ if (!validate(process.env.SCHEDULE)) {
60
+ throw new Error(`Invalid cron schedule: ${process.env?.SCHEDULE}`);
61
+ }
33
62
 
34
- setTimeout(() => process.exit(0), moment.duration(5, 'seconds').asMilliseconds());
63
+ console.log('Started scheduled run:', process.env?.SCHEDULE, `(${cronstrue.toString(process.env?.SCHEDULE)})`);
64
+ scheduledTask = cron.schedule(process.env.SCHEDULE, safeRun);
65
+
66
+ printNextRunTime();
67
+ } else {
68
+ await safeRun().finally(() => {
69
+ setTimeout(() => process.exit(0), moment.duration(5, 'seconds').asMilliseconds());
70
+ });
71
+ }