@develit-services/bank 6.1.5 → 6.2.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/dist/base.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
- const paymentDirection = require('./shared/bank.CUpE2dDT.cjs');
4
+ const paymentDirection = require('./shared/bank.CeQZODQ2.cjs');
5
5
  const drizzleOrm = require('drizzle-orm');
6
6
  const cloudflare_workers = require('cloudflare:workers');
7
7
  const d1 = require('drizzle-orm/d1');
8
8
  require('jose');
9
- const bank = require('./shared/bank.CgtmsGme.cjs');
9
+ const bank = require('./shared/bank.CQHw4fZp.cjs');
10
10
  const zod = require('zod');
11
11
  const database_schema = require('./shared/bank.Ca3jzmIb.cjs');
12
12
  const generalCodes = require('@develit-io/general-codes');
package/dist/base.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
2
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
3
- import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.r1xIlFBl.cjs';
4
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.CRQln83_.cjs';
3
+ import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.B5yr_YIB.cjs';
4
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.BE4BJCuX.cjs';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
6
6
  import { DrizzleD1Database } from 'drizzle-orm/d1';
7
7
  import { z } from 'zod';
@@ -2957,19 +2957,19 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2957
2957
  filterPaymentDateTo: z.ZodOptional<z.ZodDate>;
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  PROCESSING: "PROCESSING";
2960
- BOOKED: "BOOKED";
2961
- REJECTED: "REJECTED";
2962
2960
  PENDING: "PENDING";
2961
+ BOOKED: "BOOKED";
2963
2962
  CANCELLED: "CANCELLED";
2963
+ REJECTED: "REJECTED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
2966
2966
  INFO: "INFO";
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  PROCESSING: "PROCESSING";
2969
- BOOKED: "BOOKED";
2970
- REJECTED: "REJECTED";
2971
2969
  PENDING: "PENDING";
2970
+ BOOKED: "BOOKED";
2972
2971
  CANCELLED: "CANCELLED";
2972
+ REJECTED: "REJECTED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
2975
2975
  INFO: "INFO";
@@ -3905,18 +3905,18 @@ declare const getPaymentRequestsInputSchema: z.ZodObject<{
3905
3905
  filterStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
3906
3906
  AUTHORIZED: "AUTHORIZED";
3907
3907
  COMPLETED: "COMPLETED";
3908
- OPENED: "OPENED";
3909
3908
  BOOKED: "BOOKED";
3910
- SETTLED: "SETTLED";
3911
3909
  REJECTED: "REJECTED";
3910
+ OPENED: "OPENED";
3911
+ SETTLED: "SETTLED";
3912
3912
  CLOSED: "CLOSED";
3913
3913
  }>, z.ZodArray<z.ZodEnum<{
3914
3914
  AUTHORIZED: "AUTHORIZED";
3915
3915
  COMPLETED: "COMPLETED";
3916
- OPENED: "OPENED";
3917
3916
  BOOKED: "BOOKED";
3918
- SETTLED: "SETTLED";
3919
3917
  REJECTED: "REJECTED";
3918
+ OPENED: "OPENED";
3919
+ SETTLED: "SETTLED";
3920
3920
  CLOSED: "CLOSED";
3921
3921
  }>>]>>;
3922
3922
  filterPaymentType: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
package/dist/base.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
2
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
3
- import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.r1xIlFBl.mjs';
4
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.BW_2lyPj.mjs';
3
+ import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.B5yr_YIB.mjs';
4
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.DtfSqAaY.mjs';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
6
6
  import { DrizzleD1Database } from 'drizzle-orm/d1';
7
7
  import { z } from 'zod';
@@ -2957,19 +2957,19 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2957
2957
  filterPaymentDateTo: z.ZodOptional<z.ZodDate>;
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  PROCESSING: "PROCESSING";
2960
- BOOKED: "BOOKED";
2961
- REJECTED: "REJECTED";
2962
2960
  PENDING: "PENDING";
2961
+ BOOKED: "BOOKED";
2963
2962
  CANCELLED: "CANCELLED";
2963
+ REJECTED: "REJECTED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
2966
2966
  INFO: "INFO";
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  PROCESSING: "PROCESSING";
2969
- BOOKED: "BOOKED";
2970
- REJECTED: "REJECTED";
2971
2969
  PENDING: "PENDING";
2970
+ BOOKED: "BOOKED";
2972
2971
  CANCELLED: "CANCELLED";
2972
+ REJECTED: "REJECTED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
2975
2975
  INFO: "INFO";
@@ -3905,18 +3905,18 @@ declare const getPaymentRequestsInputSchema: z.ZodObject<{
3905
3905
  filterStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
3906
3906
  AUTHORIZED: "AUTHORIZED";
3907
3907
  COMPLETED: "COMPLETED";
3908
- OPENED: "OPENED";
3909
3908
  BOOKED: "BOOKED";
3910
- SETTLED: "SETTLED";
3911
3909
  REJECTED: "REJECTED";
3910
+ OPENED: "OPENED";
3911
+ SETTLED: "SETTLED";
3912
3912
  CLOSED: "CLOSED";
3913
3913
  }>, z.ZodArray<z.ZodEnum<{
3914
3914
  AUTHORIZED: "AUTHORIZED";
3915
3915
  COMPLETED: "COMPLETED";
3916
- OPENED: "OPENED";
3917
3916
  BOOKED: "BOOKED";
3918
- SETTLED: "SETTLED";
3919
3917
  REJECTED: "REJECTED";
3918
+ OPENED: "OPENED";
3919
+ SETTLED: "SETTLED";
3920
3920
  CLOSED: "CLOSED";
3921
3921
  }>>]>>;
3922
3922
  filterPaymentType: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
package/dist/base.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
2
2
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
3
- import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.r1xIlFBl.js';
4
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.Cu_7g0PZ.js';
3
+ import { B as BatchSelectType, P as PaymentRequestSelectType, A as AccountSelectType, a as PaymentSelectType, L as LastSyncMetadata, C as ConnectorConfig, t as tables, b as ConnectorKey, c as ConfigEnvironmentBank, I as IBankConnector, d as PaymentType, e as CurrencyCode, H as HandleAuthorizationCallbackInput, f as HandleAuthorizationCallbackOutput } from './shared/bank.B5yr_YIB.js';
4
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.B720-BP-.js';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
6
6
  import { DrizzleD1Database } from 'drizzle-orm/d1';
7
7
  import { z } from 'zod';
@@ -2957,19 +2957,19 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2957
2957
  filterPaymentDateTo: z.ZodOptional<z.ZodDate>;
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  PROCESSING: "PROCESSING";
2960
- BOOKED: "BOOKED";
2961
- REJECTED: "REJECTED";
2962
2960
  PENDING: "PENDING";
2961
+ BOOKED: "BOOKED";
2963
2962
  CANCELLED: "CANCELLED";
2963
+ REJECTED: "REJECTED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
2966
2966
  INFO: "INFO";
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  PROCESSING: "PROCESSING";
2969
- BOOKED: "BOOKED";
2970
- REJECTED: "REJECTED";
2971
2969
  PENDING: "PENDING";
2970
+ BOOKED: "BOOKED";
2972
2971
  CANCELLED: "CANCELLED";
2972
+ REJECTED: "REJECTED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
2975
2975
  INFO: "INFO";
@@ -3905,18 +3905,18 @@ declare const getPaymentRequestsInputSchema: z.ZodObject<{
3905
3905
  filterStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
3906
3906
  AUTHORIZED: "AUTHORIZED";
3907
3907
  COMPLETED: "COMPLETED";
3908
- OPENED: "OPENED";
3909
3908
  BOOKED: "BOOKED";
3910
- SETTLED: "SETTLED";
3911
3909
  REJECTED: "REJECTED";
3910
+ OPENED: "OPENED";
3911
+ SETTLED: "SETTLED";
3912
3912
  CLOSED: "CLOSED";
3913
3913
  }>, z.ZodArray<z.ZodEnum<{
3914
3914
  AUTHORIZED: "AUTHORIZED";
3915
3915
  COMPLETED: "COMPLETED";
3916
- OPENED: "OPENED";
3917
3916
  BOOKED: "BOOKED";
3918
- SETTLED: "SETTLED";
3919
3917
  REJECTED: "REJECTED";
3918
+ OPENED: "OPENED";
3919
+ SETTLED: "SETTLED";
3920
3920
  CLOSED: "CLOSED";
3921
3921
  }>>]>>;
3922
3922
  filterPaymentType: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
package/dist/base.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { uuidv4, first, buildMultiFilterConditions as buildMultiFilterConditions$1, bankAccountMetadataSchema, structuredAddressSchema, workflowInstanceStatusSchema, develitWorker, createInternalError, action, service } from '@develit-io/backend-sdk';
2
- import { G as tables, g as accountInsertSchema, H as relations, o as isProcessedStatus, p as isTerminalStatus, L as getNonTerminalPaymentRequestsQuery, x as toIncomingPayment, N as calculateCzechIban, j as assignAccount, u as toBatchedPayment, y as toPaymentRequestInsert, a as FinbricksClient, F as FINBRICKS_ENDPOINTS } from './shared/bank.DOriJdJs.mjs';
2
+ import { G as tables, g as accountInsertSchema, H as relations, o as isProcessedStatus, p as isTerminalStatus, N as getNonTerminalPaymentRequestsQuery, x as toIncomingPayment, O as calculateCzechIban, j as assignAccount, u as toBatchedPayment, y as toPaymentRequestInsert, a as FinbricksClient, F as FINBRICKS_ENDPOINTS } from './shared/bank.CGuCPc4G.mjs';
3
3
  import { eq, sql, and, like, asc, desc, inArray, gte, lte, isNull, count } from 'drizzle-orm';
4
4
  import { WorkerEntrypoint } from 'cloudflare:workers';
5
5
  import { drizzle } from 'drizzle-orm/d1';
6
6
  import 'jose';
7
- import { h as encrypt, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, j as importAesKey, f as createPaymentCommand, b as getAccountByIdQuery } from './shared/bank.DrAb7VfO.mjs';
7
+ import { h as encrypt, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, j as importAesKey, f as createPaymentCommand, b as getAccountByIdQuery } from './shared/bank.Tt5XZ2jk.mjs';
8
8
  import { z } from 'zod';
9
9
  import { I as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, g as PAYMENT_TYPES, b as CONNECTOR_KEYS, a as BATCH_STATUSES, f as PAYMENT_STATUSES, P as PAYMENT_DIRECTIONS, e as PAYMENT_REQUEST_STATUSES } from './shared/bank.BT7HayCV.mjs';
10
10
  import { CURRENCY_CODES } from '@develit-io/general-codes';
@@ -1,4 +1,4 @@
1
- export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.r1xIlFBl.cjs';
1
+ export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.B5yr_YIB.cjs';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/general-codes';
@@ -1,4 +1,4 @@
1
- export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.r1xIlFBl.mjs';
1
+ export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.B5yr_YIB.mjs';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/general-codes';
@@ -1,4 +1,4 @@
1
- export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.r1xIlFBl.js';
1
+ export { aB as account, aC as accountCredentials, aD as batch, aE as ott, aF as payment, aG as paymentRequest } from '../shared/bank.B5yr_YIB.js';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/general-codes';
@@ -1,14 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
- const paymentDirection = require('../shared/bank.CUpE2dDT.cjs');
4
+ const paymentDirection = require('../shared/bank.CeQZODQ2.cjs');
5
5
  const batchLifecycle = require('../shared/bank.NF8bZBy0.cjs');
6
6
  const drizzleOrm = require('drizzle-orm');
7
- const bank = require('../shared/bank.CgtmsGme.cjs');
7
+ const bank = require('../shared/bank.CQHw4fZp.cjs');
8
8
  const cloudflare_workers = require('cloudflare:workers');
9
9
  const cloudflare_workflows = require('cloudflare:workflows');
10
10
  const d1 = require('drizzle-orm/d1');
11
11
  require('node:crypto');
12
+ const superjson = require('superjson');
12
13
  require('date-fns');
13
14
  require('../shared/bank.Ca3jzmIb.cjs');
14
15
  require('drizzle-orm/sqlite-core');
@@ -17,6 +18,10 @@ require('jose');
17
18
  require('zod');
18
19
  require('drizzle-orm/zod');
19
20
 
21
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
22
+
23
+ const superjson__default = /*#__PURE__*/_interopDefaultCompat(superjson);
24
+
20
25
  const updateAccountLastSyncCommand = (db, {
21
26
  lastSyncAt,
22
27
  accountId,
@@ -412,8 +417,7 @@ function guardStepResultSize(value, ceilingBytes = STEP_RESULT_BYTE_CEILING) {
412
417
  }
413
418
  function rethrowFetchError(err) {
414
419
  if (err instanceof cloudflare_workflows.NonRetryableError) throw err;
415
- const message = err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : JSON.stringify(err);
416
- throw new Error(message);
420
+ throw new Error(paymentDirection.extractErrorDetails(err).message);
417
421
  }
418
422
 
419
423
  const MIN_CATCH_UP_WINDOW_MS = 6 * 60 * 60 * 1e3;
@@ -435,7 +439,10 @@ async function fetchBoundedByWindow({
435
439
  const halvedSpanMs = Math.floor(
436
440
  (current.dateTo.getTime() - current.dateFrom.getTime()) / 2
437
441
  );
438
- if (halvedSpanMs < minWindowMs) throw tooLarge;
442
+ if (halvedSpanMs < minWindowMs) {
443
+ tooLarge.oversizedResult = { result, window: current };
444
+ throw tooLarge;
445
+ }
439
446
  current = {
440
447
  dateFrom: current.dateFrom,
441
448
  dateTo: new Date(current.dateFrom.getTime() + halvedSpanMs),
@@ -447,6 +454,24 @@ async function fetchBoundedByWindow({
447
454
  }
448
455
  }
449
456
 
457
+ function buildPaymentsR2Key(params) {
458
+ return `sync-account-payments/${params.accountId}/${params.instanceId}/${params.iteration}.json`;
459
+ }
460
+ async function writePaymentsToR2(bucket, key, payments) {
461
+ await bucket.put(key, superjson__default.stringify(payments), {
462
+ httpMetadata: { contentType: "application/json" }
463
+ });
464
+ }
465
+ async function readPaymentsFromR2(bucket, key) {
466
+ const object = await bucket.get(key);
467
+ if (!object) {
468
+ throw new Error(
469
+ `Expected a payments payload at R2 key "${key}" but it was missing`
470
+ );
471
+ }
472
+ return superjson__default.parse(await object.text());
473
+ }
474
+
450
475
  class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
451
476
  async run(event, step) {
452
477
  const { accountId } = event.payload;
@@ -553,9 +578,10 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
553
578
  }))
554
579
  );
555
580
  };
556
- let bounded;
581
+ let paymentsRef;
582
+ let effectiveSyncWindow;
557
583
  try {
558
- bounded = await fetchBoundedByWindow({
584
+ const bounded = await fetchBoundedByWindow({
559
585
  window: syncWindow,
560
586
  fetchWindow,
561
587
  guardResult: guardStepResultSize,
@@ -567,56 +593,76 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
567
593
  dateTo: narrowed.dateTo.toISOString()
568
594
  })
569
595
  });
596
+ paymentsRef = { kind: "inline", items: bounded.result };
597
+ effectiveSyncWindow = bounded.window;
570
598
  } catch (err) {
571
- if (err instanceof StepResultTooLargeError) {
572
- logger.error("payments.fetch.result-too-large", {
573
- accountId,
574
- connectorKey: account.connectorKey,
575
- dateFrom: syncWindow.dateFrom.toISOString(),
576
- dateTo: syncWindow.dateTo.toISOString()
577
- });
599
+ if (!(err instanceof StepResultTooLargeError) || !err.oversizedResult) {
600
+ throw err;
578
601
  }
579
- throw err;
602
+ const { result, window } = err.oversizedResult;
603
+ const r2Key = buildPaymentsR2Key({
604
+ accountId,
605
+ instanceId: event.instanceId,
606
+ iteration
607
+ });
608
+ await writePaymentsToR2(this.env.BANK_SYNC_R2, r2Key, result);
609
+ logger.error("payments.fetch.result-too-large", {
610
+ accountId,
611
+ connectorKey: account.connectorKey,
612
+ dateFrom: syncWindow.dateFrom.toISOString(),
613
+ dateTo: syncWindow.dateTo.toISOString(),
614
+ r2Key,
615
+ count: result.length
616
+ });
617
+ paymentsRef = { kind: "r2", key: r2Key, count: result.length };
618
+ effectiveSyncWindow = window;
580
619
  }
581
620
  logger.info("payments.fetch.completed", {
582
621
  accountId,
583
622
  connectorKey: account.connectorKey,
584
- paymentsCount: bounded.result.length
623
+ paymentsCount: paymentsRef.kind === "inline" ? paymentsRef.items.length : paymentsRef.count
585
624
  });
586
625
  return {
587
- payments: bounded.result,
626
+ paymentsRef,
588
627
  windowMs: {
589
- dateFromMs: bounded.window.dateFrom.getTime(),
590
- dateToMs: bounded.window.dateTo.getTime(),
591
- isCatchUp: bounded.window.isCatchUp
628
+ dateFromMs: effectiveSyncWindow.dateFrom.getTime(),
629
+ dateToMs: effectiveSyncWindow.dateTo.getTime(),
630
+ isCatchUp: effectiveSyncWindow.isCatchUp
592
631
  }
593
632
  };
594
633
  } catch (err) {
634
+ const details = paymentDirection.extractErrorDetails(err);
595
635
  logger.error("payments.fetch.failed", {
596
636
  accountId,
597
637
  connectorKey: account.connectorKey,
598
- error: err instanceof Error ? err.message : String(err)
638
+ error: details.message,
639
+ errorCode: details.code,
640
+ errorStatus: details.status,
641
+ stack: err instanceof Error ? err.stack : void 0
599
642
  });
600
643
  rethrowFetchError(err);
601
644
  }
602
645
  }
603
646
  );
604
- const payments = fetched.payments;
605
647
  const effectiveWindow = {
606
648
  dateFrom: new Date(fetched.windowMs.dateFromMs),
607
649
  dateTo: new Date(fetched.windowMs.dateToMs),
608
650
  isCatchUp: fetched.windowMs.isCatchUp
609
651
  };
610
- const paymentsToProcess = payments.filter(
611
- (p) => paymentDirection.isPaymentCompleted(p.parsed)
612
- );
613
- const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
614
- const paymentsToInsert = paymentsToProcess.filter(
615
- (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
616
- );
617
652
  await step.do(
618
653
  "process new payments and update lastSyncAt",
619
654
  async (ctx) => {
655
+ const payments = fetched.paymentsRef.kind === "r2" ? await readPaymentsFromR2(
656
+ this.env.BANK_SYNC_R2,
657
+ fetched.paymentsRef.key
658
+ ) : fetched.paymentsRef.items;
659
+ const paymentsToProcess = payments.filter(
660
+ (p) => paymentDirection.isPaymentCompleted(p.parsed)
661
+ );
662
+ const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
663
+ const paymentsToInsert = paymentsToProcess.filter(
664
+ (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
665
+ );
620
666
  const eventsToEmit = [];
621
667
  const bankRefIds = paymentsToInsert.map((p) => p.parsed.bankRefId).filter((id) => id != null);
622
668
  const BANK_REF_ID_CHUNK_SIZE = 90;
@@ -734,6 +780,9 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
734
780
  instanceId: event.instanceId
735
781
  });
736
782
  }
783
+ if (fetched.paymentsRef.kind === "r2") {
784
+ await this.env.BANK_SYNC_R2.delete(fetched.paymentsRef.key);
785
+ }
737
786
  return {
738
787
  ...lastSyncMetadata,
739
788
  newLastSyncAt: effectiveWindow.dateTo
@@ -1,12 +1,13 @@
1
1
  import { first, uuidv4, asNonEmpty } from '@develit-io/backend-sdk';
2
- import { G as tables, H as relations, v as toBatchedPaymentFromPaymentRequest, z as toPreparedPayment, m as isPaymentCompleted } from '../shared/bank.DOriJdJs.mjs';
2
+ import { G as tables, H as relations, v as toBatchedPaymentFromPaymentRequest, z as toPreparedPayment, J as extractErrorDetails, m as isPaymentCompleted } from '../shared/bank.CGuCPc4G.mjs';
3
3
  import { i as isBatchAuthorized, b as isBatchFailed, d as isBatchProcessing } from '../shared/bank.XqSw509X.mjs';
4
4
  import { sql, and, eq, inArray } from 'drizzle-orm';
5
- import { g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, f as createPaymentCommand } from '../shared/bank.DrAb7VfO.mjs';
5
+ import { g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, f as createPaymentCommand } from '../shared/bank.Tt5XZ2jk.mjs';
6
6
  import { WorkflowEntrypoint } from 'cloudflare:workers';
7
7
  import { NonRetryableError } from 'cloudflare:workflows';
8
8
  import { drizzle } from 'drizzle-orm/d1';
9
9
  import 'node:crypto';
10
+ import superjson from 'superjson';
10
11
  import 'date-fns';
11
12
  import '../shared/bank.BT7HayCV.mjs';
12
13
  import 'drizzle-orm/sqlite-core';
@@ -410,8 +411,7 @@ function guardStepResultSize(value, ceilingBytes = STEP_RESULT_BYTE_CEILING) {
410
411
  }
411
412
  function rethrowFetchError(err) {
412
413
  if (err instanceof NonRetryableError) throw err;
413
- const message = err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : JSON.stringify(err);
414
- throw new Error(message);
414
+ throw new Error(extractErrorDetails(err).message);
415
415
  }
416
416
 
417
417
  const MIN_CATCH_UP_WINDOW_MS = 6 * 60 * 60 * 1e3;
@@ -433,7 +433,10 @@ async function fetchBoundedByWindow({
433
433
  const halvedSpanMs = Math.floor(
434
434
  (current.dateTo.getTime() - current.dateFrom.getTime()) / 2
435
435
  );
436
- if (halvedSpanMs < minWindowMs) throw tooLarge;
436
+ if (halvedSpanMs < minWindowMs) {
437
+ tooLarge.oversizedResult = { result, window: current };
438
+ throw tooLarge;
439
+ }
437
440
  current = {
438
441
  dateFrom: current.dateFrom,
439
442
  dateTo: new Date(current.dateFrom.getTime() + halvedSpanMs),
@@ -445,6 +448,24 @@ async function fetchBoundedByWindow({
445
448
  }
446
449
  }
447
450
 
451
+ function buildPaymentsR2Key(params) {
452
+ return `sync-account-payments/${params.accountId}/${params.instanceId}/${params.iteration}.json`;
453
+ }
454
+ async function writePaymentsToR2(bucket, key, payments) {
455
+ await bucket.put(key, superjson.stringify(payments), {
456
+ httpMetadata: { contentType: "application/json" }
457
+ });
458
+ }
459
+ async function readPaymentsFromR2(bucket, key) {
460
+ const object = await bucket.get(key);
461
+ if (!object) {
462
+ throw new Error(
463
+ `Expected a payments payload at R2 key "${key}" but it was missing`
464
+ );
465
+ }
466
+ return superjson.parse(await object.text());
467
+ }
468
+
448
469
  class BankSyncAccountPayments extends WorkflowEntrypoint {
449
470
  async run(event, step) {
450
471
  const { accountId } = event.payload;
@@ -551,9 +572,10 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
551
572
  }))
552
573
  );
553
574
  };
554
- let bounded;
575
+ let paymentsRef;
576
+ let effectiveSyncWindow;
555
577
  try {
556
- bounded = await fetchBoundedByWindow({
578
+ const bounded = await fetchBoundedByWindow({
557
579
  window: syncWindow,
558
580
  fetchWindow,
559
581
  guardResult: guardStepResultSize,
@@ -565,56 +587,76 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
565
587
  dateTo: narrowed.dateTo.toISOString()
566
588
  })
567
589
  });
590
+ paymentsRef = { kind: "inline", items: bounded.result };
591
+ effectiveSyncWindow = bounded.window;
568
592
  } catch (err) {
569
- if (err instanceof StepResultTooLargeError) {
570
- logger.error("payments.fetch.result-too-large", {
571
- accountId,
572
- connectorKey: account.connectorKey,
573
- dateFrom: syncWindow.dateFrom.toISOString(),
574
- dateTo: syncWindow.dateTo.toISOString()
575
- });
593
+ if (!(err instanceof StepResultTooLargeError) || !err.oversizedResult) {
594
+ throw err;
576
595
  }
577
- throw err;
596
+ const { result, window } = err.oversizedResult;
597
+ const r2Key = buildPaymentsR2Key({
598
+ accountId,
599
+ instanceId: event.instanceId,
600
+ iteration
601
+ });
602
+ await writePaymentsToR2(this.env.BANK_SYNC_R2, r2Key, result);
603
+ logger.error("payments.fetch.result-too-large", {
604
+ accountId,
605
+ connectorKey: account.connectorKey,
606
+ dateFrom: syncWindow.dateFrom.toISOString(),
607
+ dateTo: syncWindow.dateTo.toISOString(),
608
+ r2Key,
609
+ count: result.length
610
+ });
611
+ paymentsRef = { kind: "r2", key: r2Key, count: result.length };
612
+ effectiveSyncWindow = window;
578
613
  }
579
614
  logger.info("payments.fetch.completed", {
580
615
  accountId,
581
616
  connectorKey: account.connectorKey,
582
- paymentsCount: bounded.result.length
617
+ paymentsCount: paymentsRef.kind === "inline" ? paymentsRef.items.length : paymentsRef.count
583
618
  });
584
619
  return {
585
- payments: bounded.result,
620
+ paymentsRef,
586
621
  windowMs: {
587
- dateFromMs: bounded.window.dateFrom.getTime(),
588
- dateToMs: bounded.window.dateTo.getTime(),
589
- isCatchUp: bounded.window.isCatchUp
622
+ dateFromMs: effectiveSyncWindow.dateFrom.getTime(),
623
+ dateToMs: effectiveSyncWindow.dateTo.getTime(),
624
+ isCatchUp: effectiveSyncWindow.isCatchUp
590
625
  }
591
626
  };
592
627
  } catch (err) {
628
+ const details = extractErrorDetails(err);
593
629
  logger.error("payments.fetch.failed", {
594
630
  accountId,
595
631
  connectorKey: account.connectorKey,
596
- error: err instanceof Error ? err.message : String(err)
632
+ error: details.message,
633
+ errorCode: details.code,
634
+ errorStatus: details.status,
635
+ stack: err instanceof Error ? err.stack : void 0
597
636
  });
598
637
  rethrowFetchError(err);
599
638
  }
600
639
  }
601
640
  );
602
- const payments = fetched.payments;
603
641
  const effectiveWindow = {
604
642
  dateFrom: new Date(fetched.windowMs.dateFromMs),
605
643
  dateTo: new Date(fetched.windowMs.dateToMs),
606
644
  isCatchUp: fetched.windowMs.isCatchUp
607
645
  };
608
- const paymentsToProcess = payments.filter(
609
- (p) => isPaymentCompleted(p.parsed)
610
- );
611
- const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
612
- const paymentsToInsert = paymentsToProcess.filter(
613
- (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
614
- );
615
646
  await step.do(
616
647
  "process new payments and update lastSyncAt",
617
648
  async (ctx) => {
649
+ const payments = fetched.paymentsRef.kind === "r2" ? await readPaymentsFromR2(
650
+ this.env.BANK_SYNC_R2,
651
+ fetched.paymentsRef.key
652
+ ) : fetched.paymentsRef.items;
653
+ const paymentsToProcess = payments.filter(
654
+ (p) => isPaymentCompleted(p.parsed)
655
+ );
656
+ const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
657
+ const paymentsToInsert = paymentsToProcess.filter(
658
+ (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
659
+ );
618
660
  const eventsToEmit = [];
619
661
  const bankRefIds = paymentsToInsert.map((p) => p.parsed.bankRefId).filter((id) => id != null);
620
662
  const BANK_REF_ID_CHUNK_SIZE = 90;
@@ -732,6 +774,9 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
732
774
  instanceId: event.instanceId
733
775
  });
734
776
  }
777
+ if (fetched.paymentsRef.kind === "r2") {
778
+ await this.env.BANK_SYNC_R2.delete(fetched.paymentsRef.key);
779
+ }
735
780
  return {
736
781
  ...lastSyncMetadata,
737
782
  newLastSyncAt: effectiveWindow.dateTo
package/dist/service.cjs CHANGED
@@ -6,6 +6,9 @@ const BANK_SERVICE_BINDINGS = {
6
6
  SECRETS_STORE: { kind: "service", target: "secrets-store", bare: true },
7
7
  BANK_KV: { kind: "kv", suffix: "bank" },
8
8
  BANK_D1: { kind: "d1", suffix: "bank" },
9
+ // Spillover for `fetch bank payments` results too large to return from a
10
+ // Workflow step directly — see sync-payments-store.ts.
11
+ BANK_SYNC_R2: { kind: "r2", suffix: "bank-sync-payloads" },
9
12
  QUEUE_BUS_QUEUE: { kind: "queueProducer", suffix: "queue-bus" },
10
13
  NOTIFICATIONS_QUEUE: { kind: "queueProducer", suffix: "notifications" },
11
14
  SYNC_ACCOUNT_PAYMENTS_WORKFLOW: {