@develit-services/bank 0.1.7 → 0.1.8

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const database_schema = require('../shared/bank.PDmcU0T-.cjs');
3
+ const database_schema = require('../shared/bank.DrMnskU2.cjs');
4
4
  require('@develit-io/backend-sdk');
5
5
  require('drizzle-orm/sqlite-core');
6
6
  require('date-fns');
@@ -1,4 +1,4 @@
1
- export { D as account, G as accountCredentials, w as batch, z as ott, x as payment, y as paymentRelations } from '../shared/bank.xIMAnZ4v.mjs';
1
+ export { D as account, G as accountCredentials, w as batch, z as ott, x as payment, y as paymentRelations } from '../shared/bank.DHj3MnQJ.mjs';
2
2
  import '@develit-io/backend-sdk';
3
3
  import 'drizzle-orm/sqlite-core';
4
4
  import 'date-fns';
@@ -1,20 +1,19 @@
1
1
  'use strict';
2
2
 
3
- const export_workflows = require('../shared/bank.B3isylGM.cjs');
4
3
  const backendSdk = require('@develit-io/backend-sdk');
5
4
  const cloudflare_workers = require('cloudflare:workers');
6
5
  const d1 = require('drizzle-orm/d1');
7
- const database_schema = require('../shared/bank.PDmcU0T-.cjs');
6
+ const database_schema = require('../shared/bank.DrMnskU2.cjs');
8
7
  require('jose');
9
8
  const generalCodes = require('@develit-io/general-codes');
10
9
  const zod = require('zod');
10
+ const bank = require('../shared/bank.pT49Hbb4.cjs');
11
11
  const drizzleOrm = require('drizzle-orm');
12
- require('cloudflare:workflows');
13
- require('../shared/bank.BcCfzRPi.cjs');
14
12
  require('drizzle-orm/sqlite-core');
15
13
  require('date-fns');
16
14
  require('drizzle-zod');
17
15
  require('drizzle-orm/relations');
16
+ require('../shared/bank.YNS7gdPU.cjs');
18
17
 
19
18
  const upsertAccountCommand = (db, { account }) => {
20
19
  const id = account.id || backendSdk.uuidv4();
@@ -419,7 +418,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
419
418
  }
420
419
  if (allFetchedPayments.length < 1) return;
421
420
  const bankRefIds = allFetchedPayments.map((payment) => payment.bankRefId).filter(Boolean);
422
- const alreadyExistingPayments = await export_workflows.getPaymentsByBankRefIdsQuery(
421
+ const alreadyExistingPayments = await bank.getPaymentsByBankRefIdsQuery(
423
422
  this.db,
424
423
  {
425
424
  ids: bankRefIds
@@ -442,7 +441,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
442
441
  timestamp: (/* @__PURE__ */ new Date()).toDateString()
443
442
  }
444
443
  });
445
- return export_workflows.updatePaymentCommand(this.db, { payment }).command;
444
+ return bank.updatePaymentCommand(this.db, { payment }).command;
446
445
  }
447
446
  eventsToPush.push({
448
447
  eventType: "BANK_PAYMENT",
@@ -454,7 +453,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
454
453
  timestamp: (/* @__PURE__ */ new Date()).toDateString()
455
454
  }
456
455
  });
457
- return export_workflows.createPaymentCommand(this.db, { payment }).command;
456
+ return bank.createPaymentCommand(this.db, { payment }).command;
458
457
  });
459
458
  await this.db.batch([paymentsCommands[0], ...paymentsCommands.slice(1)]);
460
459
  await this.pushToQueue(
@@ -475,7 +474,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
475
474
  )[0];
476
475
  }
477
476
  if (lastSyncPayment.createdAt) {
478
- await export_workflows.updateAccountLastSyncCommand(this.db, {
477
+ await bank.updateAccountLastSyncCommand(this.db, {
479
478
  accountId: account.id,
480
479
  lastSyncedAt: lastSyncPayment.createdAt
481
480
  }).command.execute();
@@ -497,7 +496,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
497
496
  );
498
497
  const accountsWithCredentials = await Promise.all(
499
498
  accountsForConnector.map(async (acc) => {
500
- const credentials = await export_workflows.getCredentialsByAccountId(this.db, {
499
+ const credentials = await bank.getCredentialsByAccountId(this.db, {
501
500
  accountId: acc.id
502
501
  });
503
502
  if (!credentials) {
@@ -514,7 +513,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
514
513
  };
515
514
  })
516
515
  );
517
- this.bankConnector = export_workflows.initiateConnector({
516
+ this.bankConnector = bank.initiateConnector({
518
517
  bank: connectorKey,
519
518
  connectedAccounts: accountsWithCredentials,
520
519
  env: this.env
@@ -833,7 +832,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
833
832
  ...preparedBatch.failedPayments,
834
833
  ...preparedBatch.newlyPreparedPayments
835
834
  ].map(
836
- (p) => export_workflows.createPaymentCommand(this.db, { payment: p }).command.execute()
835
+ (p) => bank.createPaymentCommand(this.db, { payment: p }).command.execute()
837
836
  )
838
837
  ]);
839
838
  await upsertBatchCommand(this.db, {
@@ -870,7 +869,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
870
869
  }
871
870
  });
872
871
  const updatePayments = payments.map(
873
- (payment) => export_workflows.updatePaymentCommand(this.db, {
872
+ (payment) => bank.updatePaymentCommand(this.db, {
874
873
  payment: { ...payment, status: "INITIALIZED" }
875
874
  }).command
876
875
  );
@@ -1047,7 +1046,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1047
1046
  debtor,
1048
1047
  debtorIban: debtor.iban
1049
1048
  };
1050
- const { command } = export_workflows.createPaymentCommand(this.db, { payment });
1049
+ const { command } = bank.createPaymentCommand(this.db, { payment });
1051
1050
  const createdPayment = await command.execute().then(backendSdk.first);
1052
1051
  this.logQueuePush({ payment, isPaymentExecuted: true });
1053
1052
  await this.pushToQueue(this.env.QUEUE_BUS_QUEUE, {
@@ -1078,7 +1077,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1078
1077
  message: "Account for this organization does not exist."
1079
1078
  });
1080
1079
  }
1081
- await export_workflows.updateAccountLastSyncCommand(this.db, {
1080
+ await bank.updateAccountLastSyncCommand(this.db, {
1082
1081
  accountId: account.id,
1083
1082
  lastSyncedAt
1084
1083
  }).command.execute();
@@ -1114,6 +1113,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1114
1113
  }
1115
1114
  return {
1116
1115
  ...a,
1116
+ bankCode: a.bankCode,
1117
1117
  workflow: status ? {
1118
1118
  instanceId: a.id,
1119
1119
  details: status
@@ -1221,5 +1221,4 @@ function defineBankService({
1221
1221
  };
1222
1222
  }
1223
1223
 
1224
- exports.BankWorkflows = export_workflows.workflows;
1225
1224
  exports.defineBankService = defineBankService;
@@ -1,4 +1,3 @@
1
- export { w as BankWorkflows } from '../shared/bank.ChAGzUFo.cjs';
2
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
3
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
4
3
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -1,4 +1,3 @@
1
- export { w as BankWorkflows } from '../shared/bank.ChAGzUFo.mjs';
2
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
3
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
4
3
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -1,4 +1,3 @@
1
- export { w as BankWorkflows } from '../shared/bank.ChAGzUFo.js';
2
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
3
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
4
3
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -1,19 +1,17 @@
1
- import { g as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, a as updateAccountLastSyncCommand, b as getCredentialsByAccountId, i as initiateConnector } from '../shared/bank.JtGSu6eH.mjs';
2
- export { w as BankWorkflows } from '../shared/bank.JtGSu6eH.mjs';
3
1
  import { uuidv4, bankAccountMetadataSchema, workflowInstanceStatusSchema, develitWorker, createInternalError, first, action, service } from '@develit-io/backend-sdk';
4
2
  import { WorkerEntrypoint } from 'cloudflare:workers';
5
3
  import { drizzle } from 'drizzle-orm/d1';
6
- import { t as tables, c as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, P as PAYMENT_TYPES, g as CONNECTOR_KEYS, B as BATCH_STATUSES, d as PAYMENT_STATUSES, e as PAYMENT_DIRECTIONS, i as accountInsertSchema, v as getPaymentDirection, M as MockConnector, F as FinbricksConnector, E as ErsteConnector } from '../shared/bank.xIMAnZ4v.mjs';
4
+ import { t as tables, c as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, P as PAYMENT_TYPES, g as CONNECTOR_KEYS, B as BATCH_STATUSES, d as PAYMENT_STATUSES, e as PAYMENT_DIRECTIONS, i as accountInsertSchema, v as getPaymentDirection, M as MockConnector, F as FinbricksConnector, E as ErsteConnector } from '../shared/bank.DHj3MnQJ.mjs';
7
5
  import 'jose';
8
6
  import { CURRENCY_CODES } from '@develit-io/general-codes';
9
7
  import { z } from 'zod';
8
+ import { a as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, b as updateAccountLastSyncCommand, g as getCredentialsByAccountId, i as initiateConnector } from '../shared/bank.B_nwGY5X.mjs';
10
9
  import { eq, inArray, and, sql, asc, desc, gte, lte } from 'drizzle-orm';
11
- import 'cloudflare:workflows';
12
- import '../shared/bank.D2ZeOkyc.mjs';
13
10
  import 'drizzle-orm/sqlite-core';
14
11
  import 'date-fns';
15
12
  import 'drizzle-zod';
16
13
  import 'drizzle-orm/relations';
14
+ import '../shared/bank.DulU-rr_.mjs';
17
15
 
18
16
  const upsertAccountCommand = (db, { account }) => {
19
17
  const id = account.id || uuidv4();
@@ -1113,6 +1111,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1113
1111
  }
1114
1112
  return {
1115
1113
  ...a,
1114
+ bankCode: a.bankCode,
1116
1115
  workflow: status ? {
1117
1116
  instanceId: a.id,
1118
1117
  details: status
@@ -1,21 +1,172 @@
1
1
  'use strict';
2
2
 
3
- const export_workflows = require('../shared/bank.B3isylGM.cjs');
4
- require('cloudflare:workers');
5
- require('cloudflare:workflows');
6
- require('drizzle-orm/d1');
7
- require('../shared/bank.PDmcU0T-.cjs');
8
- require('@develit-io/backend-sdk');
3
+ const cloudflare_workers = require('cloudflare:workers');
4
+ const cloudflare_workflows = require('cloudflare:workflows');
5
+ const d1 = require('drizzle-orm/d1');
6
+ const database_schema = require('../shared/bank.DrMnskU2.cjs');
7
+ const backendSdk = require('@develit-io/backend-sdk');
8
+ const bank = require('../shared/bank.pT49Hbb4.cjs');
9
+ const drizzleOrm = require('drizzle-orm');
9
10
  require('drizzle-orm/sqlite-core');
10
11
  require('date-fns');
11
- require('drizzle-orm');
12
12
  require('@develit-io/general-codes');
13
13
  require('zod');
14
14
  require('jose');
15
15
  require('drizzle-zod');
16
16
  require('drizzle-orm/relations');
17
- require('../shared/bank.BcCfzRPi.cjs');
17
+ require('../shared/bank.YNS7gdPU.cjs');
18
18
 
19
+ const getAccountByIdQuery = async (db, { accountId }) => {
20
+ return await db.select().from(database_schema.tables.account).where(drizzleOrm.eq(database_schema.tables.account.id, accountId)).get();
21
+ };
19
22
 
23
+ function pushToQueue(queue, message) {
24
+ if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
25
+ return queue.sendBatch(
26
+ message.map((m) => ({
27
+ body: m,
28
+ contentType: "v8"
29
+ }))
30
+ );
31
+ }
32
+ class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint {
33
+ async run(event, step) {
34
+ const { accountId } = event.payload;
35
+ const db = d1.drizzle(this.env.BANK_D1, { schema: database_schema.tables });
36
+ while (true) {
37
+ const account = await step.do("load account", async () => {
38
+ const account2 = await getAccountByIdQuery(db, { accountId });
39
+ if (!account2) {
40
+ throw new cloudflare_workflows.NonRetryableError(`Bank account not found: ${accountId}`);
41
+ }
42
+ return account2;
43
+ });
44
+ if (!account.lastSyncedAt) {
45
+ throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
46
+ }
47
+ const credentials = await step.do(
48
+ "load account credentials",
49
+ async () => {
50
+ const credentials2 = await bank.getCredentialsByAccountId(db, { accountId });
51
+ if (!credentials2) {
52
+ throw new cloudflare_workflows.NonRetryableError(
53
+ `No credentials found for account: ${accountId}`
54
+ );
55
+ }
56
+ return credentials2;
57
+ }
58
+ );
59
+ const payments = await step.do(
60
+ "fetch bank payments",
61
+ {
62
+ retries: { limit: 5, delay: 2e3, backoff: "constant" },
63
+ timeout: "30 seconds"
64
+ },
65
+ async () => {
66
+ const connector = bank.initiateConnector({
67
+ env: this.env,
68
+ bank: account.connectorKey,
69
+ connectedAccounts: [
70
+ {
71
+ ...account,
72
+ iban: account.iban,
73
+ token: credentials.value
74
+ }
75
+ ]
76
+ });
77
+ const fetched = await connector.getAllAccountPayments({
78
+ environment: this.env.ENVIRONMENT,
79
+ db,
80
+ account,
81
+ filter: { dateFrom: account.lastSyncedAt }
82
+ });
83
+ return fetched.map((p) => ({
84
+ ...p,
85
+ direction: database_schema.getPaymentDirection(p, account.iban)
86
+ }));
87
+ }
88
+ );
89
+ if (payments.length) {
90
+ const bankRefIds = payments.map((payment) => payment.bankRefId).filter(Boolean);
91
+ const existing = await step.do("load existing payments", async () => {
92
+ return await bank.getPaymentsByBankRefIdsQuery(db, {
93
+ ids: bankRefIds
94
+ });
95
+ });
96
+ const paymentsToUpdate = payments.filter(
97
+ (p) => existing.some((e) => e.bankRefId === p.bankRefId)
98
+ );
99
+ const paymentsToCreate = payments.filter(
100
+ (p) => !existing.some((e) => e.bankRefId === p.bankRefId)
101
+ );
102
+ await step.do("process payments and update lastSyncAt", async () => {
103
+ const eventsToEmit = [];
104
+ const updateCommands = paymentsToUpdate.map(
105
+ (p) => bank.updatePaymentCommand(db, { payment: p }).command
106
+ );
107
+ eventsToEmit.push(
108
+ ...paymentsToUpdate.map((p) => ({
109
+ eventType: "BANK_PAYMENT",
110
+ eventSignal: "paymentUpdated",
111
+ bankPayment: p,
112
+ metadata: {
113
+ correlationId: p.correlationId,
114
+ entityId: p.id,
115
+ idempotencySuffix: p.status,
116
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
117
+ }
118
+ }))
119
+ );
120
+ const createCommands = paymentsToCreate.map(
121
+ (p) => bank.createPaymentCommand(db, { payment: p }).command
122
+ );
123
+ eventsToEmit.push(
124
+ ...paymentsToCreate.map((p) => ({
125
+ eventType: "BANK_PAYMENT",
126
+ eventSignal: "paymentCreated",
127
+ bankPayment: p,
128
+ metadata: {
129
+ correlationId: p.correlationId,
130
+ entityId: p.id,
131
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
132
+ }
133
+ }))
134
+ );
135
+ const latest = payments.reduce((current, p) => {
136
+ return new Date(p.processedAt).getTime() > new Date(current.processedAt).getTime() ? p : current;
137
+ }, payments[0]);
138
+ const updateLastSyncCommand = bank.updateAccountLastSyncCommand(db, {
139
+ accountId: account.id,
140
+ lastSyncedAt: latest.processedAt
141
+ }).command;
142
+ if (eventsToEmit.length) {
143
+ await db.batch(
144
+ backendSdk.asNonEmpty([
145
+ updateLastSyncCommand,
146
+ ...updateCommands,
147
+ ...createCommands
148
+ ])
149
+ );
150
+ await pushToQueue(
151
+ this.env.QUEUE_BUS_QUEUE,
152
+ eventsToEmit
153
+ );
154
+ }
155
+ return {
156
+ payments: payments.length,
157
+ updated: paymentsToUpdate.length,
158
+ created: paymentsToCreate.length,
159
+ eventsEmitted: eventsToEmit.length,
160
+ lastSyncedAt: latest?.createdAt
161
+ };
162
+ });
163
+ }
164
+ await step.sleep(
165
+ "Sleep for next sync",
166
+ `${account.syncIntervalS} seconds`
167
+ );
168
+ }
169
+ }
170
+ }
20
171
 
21
- exports.SyncAccountPaymentsWorkflow = export_workflows.SyncAccountPaymentsWorkflow;
172
+ exports.SyncAccountPaymentsWorkflow = SyncAccountPaymentsWorkflow;
@@ -1,2 +1,10 @@
1
- export { S as SyncAccountPaymentsWorkflow } from '../shared/bank.ChAGzUFo.cjs';
2
- import 'cloudflare:workers';
1
+ import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
2
+
3
+ type Params = {
4
+ accountId: string;
5
+ };
6
+ declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
7
+ run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
8
+ }
9
+
10
+ export { SyncAccountPaymentsWorkflow };
@@ -1,2 +1,10 @@
1
- export { S as SyncAccountPaymentsWorkflow } from '../shared/bank.ChAGzUFo.mjs';
2
- import 'cloudflare:workers';
1
+ import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
2
+
3
+ type Params = {
4
+ accountId: string;
5
+ };
6
+ declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
7
+ run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
8
+ }
9
+
10
+ export { SyncAccountPaymentsWorkflow };
@@ -1,2 +1,10 @@
1
- export { S as SyncAccountPaymentsWorkflow } from '../shared/bank.ChAGzUFo.js';
2
- import 'cloudflare:workers';
1
+ import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
2
+
3
+ type Params = {
4
+ accountId: string;
5
+ };
6
+ declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
7
+ run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
8
+ }
9
+
10
+ export { SyncAccountPaymentsWorkflow };
@@ -1,15 +1,170 @@
1
- export { S as SyncAccountPaymentsWorkflow } from '../shared/bank.JtGSu6eH.mjs';
2
- import 'cloudflare:workers';
3
- import 'cloudflare:workflows';
4
- import 'drizzle-orm/d1';
5
- import '../shared/bank.xIMAnZ4v.mjs';
6
- import '@develit-io/backend-sdk';
1
+ import { WorkflowEntrypoint } from 'cloudflare:workers';
2
+ import { NonRetryableError } from 'cloudflare:workflows';
3
+ import { drizzle } from 'drizzle-orm/d1';
4
+ import { t as tables, v as getPaymentDirection } from '../shared/bank.DHj3MnQJ.mjs';
5
+ import { asNonEmpty } from '@develit-io/backend-sdk';
6
+ import { g as getCredentialsByAccountId, i as initiateConnector, a as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, b as updateAccountLastSyncCommand } from '../shared/bank.B_nwGY5X.mjs';
7
+ import { eq } from 'drizzle-orm';
7
8
  import 'drizzle-orm/sqlite-core';
8
9
  import 'date-fns';
9
- import 'drizzle-orm';
10
10
  import '@develit-io/general-codes';
11
11
  import 'zod';
12
12
  import 'jose';
13
13
  import 'drizzle-zod';
14
14
  import 'drizzle-orm/relations';
15
- import '../shared/bank.D2ZeOkyc.mjs';
15
+ import '../shared/bank.DulU-rr_.mjs';
16
+
17
+ const getAccountByIdQuery = async (db, { accountId }) => {
18
+ return await db.select().from(tables.account).where(eq(tables.account.id, accountId)).get();
19
+ };
20
+
21
+ function pushToQueue(queue, message) {
22
+ if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
23
+ return queue.sendBatch(
24
+ message.map((m) => ({
25
+ body: m,
26
+ contentType: "v8"
27
+ }))
28
+ );
29
+ }
30
+ class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
31
+ async run(event, step) {
32
+ const { accountId } = event.payload;
33
+ const db = drizzle(this.env.BANK_D1, { schema: tables });
34
+ while (true) {
35
+ const account = await step.do("load account", async () => {
36
+ const account2 = await getAccountByIdQuery(db, { accountId });
37
+ if (!account2) {
38
+ throw new NonRetryableError(`Bank account not found: ${accountId}`);
39
+ }
40
+ return account2;
41
+ });
42
+ if (!account.lastSyncedAt) {
43
+ throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
44
+ }
45
+ const credentials = await step.do(
46
+ "load account credentials",
47
+ async () => {
48
+ const credentials2 = await getCredentialsByAccountId(db, { accountId });
49
+ if (!credentials2) {
50
+ throw new NonRetryableError(
51
+ `No credentials found for account: ${accountId}`
52
+ );
53
+ }
54
+ return credentials2;
55
+ }
56
+ );
57
+ const payments = await step.do(
58
+ "fetch bank payments",
59
+ {
60
+ retries: { limit: 5, delay: 2e3, backoff: "constant" },
61
+ timeout: "30 seconds"
62
+ },
63
+ async () => {
64
+ const connector = initiateConnector({
65
+ env: this.env,
66
+ bank: account.connectorKey,
67
+ connectedAccounts: [
68
+ {
69
+ ...account,
70
+ iban: account.iban,
71
+ token: credentials.value
72
+ }
73
+ ]
74
+ });
75
+ const fetched = await connector.getAllAccountPayments({
76
+ environment: this.env.ENVIRONMENT,
77
+ db,
78
+ account,
79
+ filter: { dateFrom: account.lastSyncedAt }
80
+ });
81
+ return fetched.map((p) => ({
82
+ ...p,
83
+ direction: getPaymentDirection(p, account.iban)
84
+ }));
85
+ }
86
+ );
87
+ if (payments.length) {
88
+ const bankRefIds = payments.map((payment) => payment.bankRefId).filter(Boolean);
89
+ const existing = await step.do("load existing payments", async () => {
90
+ return await getPaymentsByBankRefIdsQuery(db, {
91
+ ids: bankRefIds
92
+ });
93
+ });
94
+ const paymentsToUpdate = payments.filter(
95
+ (p) => existing.some((e) => e.bankRefId === p.bankRefId)
96
+ );
97
+ const paymentsToCreate = payments.filter(
98
+ (p) => !existing.some((e) => e.bankRefId === p.bankRefId)
99
+ );
100
+ await step.do("process payments and update lastSyncAt", async () => {
101
+ const eventsToEmit = [];
102
+ const updateCommands = paymentsToUpdate.map(
103
+ (p) => updatePaymentCommand(db, { payment: p }).command
104
+ );
105
+ eventsToEmit.push(
106
+ ...paymentsToUpdate.map((p) => ({
107
+ eventType: "BANK_PAYMENT",
108
+ eventSignal: "paymentUpdated",
109
+ bankPayment: p,
110
+ metadata: {
111
+ correlationId: p.correlationId,
112
+ entityId: p.id,
113
+ idempotencySuffix: p.status,
114
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
115
+ }
116
+ }))
117
+ );
118
+ const createCommands = paymentsToCreate.map(
119
+ (p) => createPaymentCommand(db, { payment: p }).command
120
+ );
121
+ eventsToEmit.push(
122
+ ...paymentsToCreate.map((p) => ({
123
+ eventType: "BANK_PAYMENT",
124
+ eventSignal: "paymentCreated",
125
+ bankPayment: p,
126
+ metadata: {
127
+ correlationId: p.correlationId,
128
+ entityId: p.id,
129
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
130
+ }
131
+ }))
132
+ );
133
+ const latest = payments.reduce((current, p) => {
134
+ return new Date(p.processedAt).getTime() > new Date(current.processedAt).getTime() ? p : current;
135
+ }, payments[0]);
136
+ const updateLastSyncCommand = updateAccountLastSyncCommand(db, {
137
+ accountId: account.id,
138
+ lastSyncedAt: latest.processedAt
139
+ }).command;
140
+ if (eventsToEmit.length) {
141
+ await db.batch(
142
+ asNonEmpty([
143
+ updateLastSyncCommand,
144
+ ...updateCommands,
145
+ ...createCommands
146
+ ])
147
+ );
148
+ await pushToQueue(
149
+ this.env.QUEUE_BUS_QUEUE,
150
+ eventsToEmit
151
+ );
152
+ }
153
+ return {
154
+ payments: payments.length,
155
+ updated: paymentsToUpdate.length,
156
+ created: paymentsToCreate.length,
157
+ eventsEmitted: eventsToEmit.length,
158
+ lastSyncedAt: latest?.createdAt
159
+ };
160
+ });
161
+ }
162
+ await step.sleep(
163
+ "Sleep for next sync",
164
+ `${account.syncIntervalS} seconds`
165
+ );
166
+ }
167
+ }
168
+ }
169
+
170
+ export { SyncAccountPaymentsWorkflow };