@develit-services/bank 5.8.0 → 5.9.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,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
- const paymentDirection = require('./shared/bank.CQjuudum.cjs');
5
- const bank = require('./shared/bank.Cy7xa566.cjs');
4
+ const paymentDirection = require('./shared/bank.BsWBG0gb.cjs');
5
+ const bank = require('./shared/bank.DBTtRCcf.cjs');
6
6
  const drizzleOrm = require('drizzle-orm');
7
7
  const cloudflare_workers = require('cloudflare:workers');
8
8
  const d1 = require('drizzle-orm/d1');
9
9
  require('jose');
10
10
  const zod = require('zod');
11
- const database_schema = require('./shared/bank.9Yw4KHyl.cjs');
11
+ const database_schema = require('./shared/bank.Ca3jzmIb.cjs');
12
12
  const generalCodes = require('@develit-io/general-codes');
13
13
  require('date-fns');
14
14
  require('node:crypto');
@@ -208,6 +208,26 @@ function isAlreadyFiniteError(err) {
208
208
  return /cannot_terminate|finite state/i.test(message);
209
209
  }
210
210
 
211
+ async function disableAccountSync({
212
+ accountId,
213
+ persistDisabled,
214
+ terminateInstance,
215
+ logger
216
+ }) {
217
+ await persistDisabled();
218
+ try {
219
+ const instanceId = await terminateInstance();
220
+ logger.info("sync-workflow.disable.terminated", { accountId, instanceId });
221
+ return { terminated: true, instanceId };
222
+ } catch (err) {
223
+ logger.warn("sync-workflow.disable.terminate-skipped", {
224
+ accountId,
225
+ error: err instanceof Error ? err.message : String(err)
226
+ });
227
+ return { terminated: false, instanceId: null };
228
+ }
229
+ }
230
+
211
231
  const upsertAccountCommand = (db, { account }) => {
212
232
  const id = account.id || backendSdk.uuidv4();
213
233
  const { id: _id, ...accountWithoutId } = account;
@@ -295,6 +315,13 @@ const createPaymentRequestCommand = (db, { paymentRequest }) => {
295
315
  };
296
316
  };
297
317
 
318
+ const updateAccountSyncEnabledCommand = (db, { accountId, syncEnabled }) => {
319
+ const command = db.update(paymentDirection.tables.account).set({ syncEnabled }).where(drizzleOrm.eq(paymentDirection.tables.account.id, accountId)).returning();
320
+ return {
321
+ command
322
+ };
323
+ };
324
+
298
325
  const getAccountBatchCountsQuery = async (db, { accountId }) => {
299
326
  const result = await db.select({
300
327
  totalCount: drizzleOrm.sql`COUNT(*)`.as("totalCount"),
@@ -564,6 +591,21 @@ const getPaymentRequestsQuery = async (db, params) => {
564
591
  return { paymentRequests, totalCount };
565
592
  };
566
593
 
594
+ const getSyncCandidateAccountsQuery = async (db) => {
595
+ return await db.select({
596
+ id: paymentDirection.tables.account.id,
597
+ syncIntervalS: paymentDirection.tables.account.syncIntervalS,
598
+ lastSyncAt: paymentDirection.tables.account.lastSyncAt,
599
+ lastSyncMetadata: paymentDirection.tables.account.lastSyncMetadata,
600
+ createdAt: paymentDirection.tables.account.createdAt
601
+ }).from(paymentDirection.tables.account).where(
602
+ drizzleOrm.and(
603
+ drizzleOrm.eq(paymentDirection.tables.account.status, "AUTHORIZED"),
604
+ drizzleOrm.eq(paymentDirection.tables.account.syncEnabled, true)
605
+ )
606
+ ).all();
607
+ };
608
+
567
609
  const SIGNAL_MAP = {
568
610
  OPENED: "paymentRequestOpened",
569
611
  AUTHORIZED: "paymentRequestAuthorized",
@@ -790,7 +832,9 @@ const syncAccountTerminateInputSchema = zod.z.object({
790
832
  accountId: zod.z.uuid()
791
833
  });
792
834
  zod.z.object({
793
- instanceId: zod.z.string()
835
+ terminated: zod.z.boolean(),
836
+ // Null when the flag was persisted but no live instance existed to kill.
837
+ instanceId: zod.z.string().nullable()
794
838
  });
795
839
 
796
840
  const updateAccountInputSchema = zod.z.object({
@@ -866,6 +910,11 @@ var __decorateClass = (decorators, target, key, kind) => {
866
910
  if (kind && result) __defProp(target, key, result);
867
911
  return result;
868
912
  };
913
+ const accountNotFoundError = () => backendSdk.createInternalError(null, {
914
+ message: "Account not found",
915
+ code: "DB-B-005",
916
+ status: 404
917
+ });
869
918
  const syncEventConsoleLogger = {
870
919
  info: (event, data) => console.log(JSON.stringify({ level: "info", event, ...data })),
871
920
  warn: (event, data) => console.warn(JSON.stringify({ level: "warn", event, ...data })),
@@ -973,6 +1022,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
973
1022
  { data: input, schema: syncAccountInputSchema },
974
1023
  { successMessage: "Account sync workflow started" },
975
1024
  async ({ accountId }) => {
1025
+ await this.setSyncEnabledOrThrow(accountId, true);
976
1026
  if (isDispatchActive(
977
1027
  accountId,
978
1028
  this.env.SYNC_DISPATCH_ACCOUNT_IDS,
@@ -1027,6 +1077,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
1027
1077
  { data: input, schema: syncAccountRestartInputSchema },
1028
1078
  { successMessage: "Account sync workflow restarted" },
1029
1079
  async ({ accountId }) => {
1080
+ await this.setSyncEnabledOrThrow(accountId, true);
1030
1081
  const instance = await this.getCurrentSyncInstance(accountId);
1031
1082
  await instance.restart();
1032
1083
  return {
@@ -1041,11 +1092,16 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
1041
1092
  { data: input, schema: syncAccountTerminateInputSchema },
1042
1093
  { successMessage: "Account sync workflow terminated" },
1043
1094
  async ({ accountId }) => {
1044
- const instance = await this.getCurrentSyncInstance(accountId);
1045
- await terminateSyncWorkflow(instance);
1046
- return {
1047
- instanceId: instance.id
1048
- };
1095
+ return disableAccountSync({
1096
+ accountId,
1097
+ persistDisabled: () => this.setSyncEnabledOrThrow(accountId, false),
1098
+ terminateInstance: async () => {
1099
+ const instance = await this.getCurrentSyncInstance(accountId);
1100
+ await terminateSyncWorkflow(instance);
1101
+ return instance.id;
1102
+ },
1103
+ logger: syncEventConsoleLogger
1104
+ });
1049
1105
  }
1050
1106
  );
1051
1107
  }
@@ -1339,6 +1395,15 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
1339
1395
  * account — under dispatch that is the windowed instance recorded with the
1340
1396
  * last sync write, not the legacy canonical id.
1341
1397
  */
1398
+ async setSyncEnabledOrThrow(accountId, syncEnabled) {
1399
+ const [updated] = await updateAccountSyncEnabledCommand(this.db, {
1400
+ accountId,
1401
+ syncEnabled
1402
+ }).command;
1403
+ if (!updated) {
1404
+ throw accountNotFoundError();
1405
+ }
1406
+ }
1342
1407
  async getCurrentSyncInstance(accountId) {
1343
1408
  const account = await bank.getAccountByIdQuery(this.db, { accountId });
1344
1409
  return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
@@ -1351,12 +1416,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
1351
1416
  async dispatchSyncWorkflows() {
1352
1417
  const selection = this.env.SYNC_DISPATCH_ACCOUNT_IDS;
1353
1418
  if (!selection?.trim()) return;
1354
- const accounts = await this.db.select({
1355
- id: paymentDirection.tables.account.id,
1356
- syncIntervalS: paymentDirection.tables.account.syncIntervalS,
1357
- lastSyncAt: paymentDirection.tables.account.lastSyncAt,
1358
- createdAt: paymentDirection.tables.account.createdAt
1359
- }).from(paymentDirection.tables.account).where(drizzleOrm.eq(paymentDirection.tables.account.status, "AUTHORIZED")).all();
1419
+ const accounts = await getSyncCandidateAccountsQuery(this.db);
1360
1420
  const maxIterations = bank.parseIterationBudgetParam(
1361
1421
  this.env.SYNC_WORKFLOW_MAX_ITERATIONS
1362
1422
  );
@@ -1375,13 +1435,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
1375
1435
  });
1376
1436
  }
1377
1437
  async heartbeatSyncWorkflows() {
1378
- const accounts = await this.db.select({
1379
- id: paymentDirection.tables.account.id,
1380
- lastSyncMetadata: paymentDirection.tables.account.lastSyncMetadata,
1381
- syncIntervalS: paymentDirection.tables.account.syncIntervalS,
1382
- lastSyncAt: paymentDirection.tables.account.lastSyncAt,
1383
- createdAt: paymentDirection.tables.account.createdAt
1384
- }).from(paymentDirection.tables.account).where(drizzleOrm.eq(paymentDirection.tables.account.status, "AUTHORIZED")).all();
1438
+ const accounts = await getSyncCandidateAccountsQuery(this.db);
1385
1439
  const resetAfterIterations = Number(
1386
1440
  this.env.SYNC_WORKFLOW_RESET_AFTER_ITERATIONS
1387
1441
  );
@@ -2273,11 +2327,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
2273
2327
  async ({ accountId }) => {
2274
2328
  const account = await bank.getAccountByIdQuery(this.db, { accountId });
2275
2329
  if (!account) {
2276
- throw backendSdk.createInternalError(null, {
2277
- message: "Account not found",
2278
- code: "DB-B-005",
2279
- status: 404
2280
- });
2330
+ throw accountNotFoundError();
2281
2331
  }
2282
2332
  try {
2283
2333
  const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
package/dist/base.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- 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.CefGTNH1.cjs';
2
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.CtIkqQG9.cjs';
1
+ 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.CgiEbvJu.cjs';
2
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.DZyrkXc_.cjs';
3
3
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
4
4
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
2699
2699
  limit: z.ZodNumber;
2700
2700
  sort: z.ZodObject<{
2701
2701
  column: z.ZodEnum<{
2702
- batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2703
2702
  createdAt: "createdAt";
2704
2703
  updatedAt: "updatedAt";
2704
+ batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2705
2705
  }>;
2706
2706
  direction: z.ZodEnum<{
2707
2707
  asc: "asc";
@@ -2958,8 +2958,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  BOOKED: "BOOKED";
2960
2960
  REJECTED: "REJECTED";
2961
- PROCESSING: "PROCESSING";
2962
2961
  PENDING: "PENDING";
2962
+ PROCESSING: "PROCESSING";
2963
2963
  CANCELLED: "CANCELLED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
@@ -2967,8 +2967,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  BOOKED: "BOOKED";
2969
2969
  REJECTED: "REJECTED";
2970
- PROCESSING: "PROCESSING";
2971
2970
  PENDING: "PENDING";
2971
+ PROCESSING: "PROCESSING";
2972
2972
  CANCELLED: "CANCELLED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
@@ -3114,7 +3114,8 @@ declare const syncAccountTerminateInputSchema: z.ZodObject<{
3114
3114
  accountId: z.ZodUUID;
3115
3115
  }, z.core.$strip>;
3116
3116
  declare const syncAccountTerminateOutputSchema: z.ZodObject<{
3117
- instanceId: z.ZodString;
3117
+ terminated: z.ZodBoolean;
3118
+ instanceId: z.ZodNullable<z.ZodString>;
3118
3119
  }, z.core.$strip>;
3119
3120
  interface SyncAccountTerminateInput extends z.infer<typeof syncAccountTerminateInputSchema> {
3120
3121
  }
@@ -3266,6 +3267,22 @@ declare const updateAccountInputSchema: z.ZodObject<{
3266
3267
  identity: undefined;
3267
3268
  generated: undefined;
3268
3269
  }, {}>;
3270
+ syncEnabled: drizzle_orm_sqlite_core.SQLiteColumn<{
3271
+ name: string;
3272
+ tableName: "account";
3273
+ dataType: "boolean";
3274
+ data: boolean;
3275
+ driverParam: number;
3276
+ notNull: true;
3277
+ hasDefault: true;
3278
+ isPrimaryKey: false;
3279
+ isAutoincrement: false;
3280
+ hasRuntimeDefault: false;
3281
+ enumValues: undefined;
3282
+ baseColumn: never;
3283
+ identity: undefined;
3284
+ generated: undefined;
3285
+ }, {}>;
3269
3286
  syncIntervalS: drizzle_orm_sqlite_core.SQLiteColumn<{
3270
3287
  name: string;
3271
3288
  tableName: "account";
@@ -4092,6 +4109,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4092
4109
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4093
4110
  bankRefId: string;
4094
4111
  batchSizeLimit: number;
4112
+ syncEnabled: boolean;
4095
4113
  syncIntervalS: number;
4096
4114
  lastSyncAt: Date | null;
4097
4115
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4127,6 +4145,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4127
4145
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4128
4146
  bankRefId: string;
4129
4147
  batchSizeLimit: number;
4148
+ syncEnabled: boolean;
4130
4149
  syncIntervalS: number;
4131
4150
  lastSyncAt: Date | null;
4132
4151
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4198,6 +4217,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4198
4217
  * account — under dispatch that is the windowed instance recorded with the
4199
4218
  * last sync write, not the legacy canonical id.
4200
4219
  */
4220
+ private setSyncEnabledOrThrow;
4201
4221
  private getCurrentSyncInstance;
4202
4222
  private dispatchSyncWorkflows;
4203
4223
  private heartbeatSyncWorkflows;
package/dist/base.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- 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.CefGTNH1.mjs';
2
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.oNDZ44du.mjs';
1
+ 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.CgiEbvJu.mjs';
2
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.D19D3a9C.mjs';
3
3
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
4
4
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
2699
2699
  limit: z.ZodNumber;
2700
2700
  sort: z.ZodObject<{
2701
2701
  column: z.ZodEnum<{
2702
- batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2703
2702
  createdAt: "createdAt";
2704
2703
  updatedAt: "updatedAt";
2704
+ batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2705
2705
  }>;
2706
2706
  direction: z.ZodEnum<{
2707
2707
  asc: "asc";
@@ -2958,8 +2958,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  BOOKED: "BOOKED";
2960
2960
  REJECTED: "REJECTED";
2961
- PROCESSING: "PROCESSING";
2962
2961
  PENDING: "PENDING";
2962
+ PROCESSING: "PROCESSING";
2963
2963
  CANCELLED: "CANCELLED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
@@ -2967,8 +2967,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  BOOKED: "BOOKED";
2969
2969
  REJECTED: "REJECTED";
2970
- PROCESSING: "PROCESSING";
2971
2970
  PENDING: "PENDING";
2971
+ PROCESSING: "PROCESSING";
2972
2972
  CANCELLED: "CANCELLED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
@@ -3114,7 +3114,8 @@ declare const syncAccountTerminateInputSchema: z.ZodObject<{
3114
3114
  accountId: z.ZodUUID;
3115
3115
  }, z.core.$strip>;
3116
3116
  declare const syncAccountTerminateOutputSchema: z.ZodObject<{
3117
- instanceId: z.ZodString;
3117
+ terminated: z.ZodBoolean;
3118
+ instanceId: z.ZodNullable<z.ZodString>;
3118
3119
  }, z.core.$strip>;
3119
3120
  interface SyncAccountTerminateInput extends z.infer<typeof syncAccountTerminateInputSchema> {
3120
3121
  }
@@ -3266,6 +3267,22 @@ declare const updateAccountInputSchema: z.ZodObject<{
3266
3267
  identity: undefined;
3267
3268
  generated: undefined;
3268
3269
  }, {}>;
3270
+ syncEnabled: drizzle_orm_sqlite_core.SQLiteColumn<{
3271
+ name: string;
3272
+ tableName: "account";
3273
+ dataType: "boolean";
3274
+ data: boolean;
3275
+ driverParam: number;
3276
+ notNull: true;
3277
+ hasDefault: true;
3278
+ isPrimaryKey: false;
3279
+ isAutoincrement: false;
3280
+ hasRuntimeDefault: false;
3281
+ enumValues: undefined;
3282
+ baseColumn: never;
3283
+ identity: undefined;
3284
+ generated: undefined;
3285
+ }, {}>;
3269
3286
  syncIntervalS: drizzle_orm_sqlite_core.SQLiteColumn<{
3270
3287
  name: string;
3271
3288
  tableName: "account";
@@ -4092,6 +4109,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4092
4109
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4093
4110
  bankRefId: string;
4094
4111
  batchSizeLimit: number;
4112
+ syncEnabled: boolean;
4095
4113
  syncIntervalS: number;
4096
4114
  lastSyncAt: Date | null;
4097
4115
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4127,6 +4145,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4127
4145
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4128
4146
  bankRefId: string;
4129
4147
  batchSizeLimit: number;
4148
+ syncEnabled: boolean;
4130
4149
  syncIntervalS: number;
4131
4150
  lastSyncAt: Date | null;
4132
4151
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4198,6 +4217,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4198
4217
  * account — under dispatch that is the windowed instance recorded with the
4199
4218
  * last sync write, not the legacy canonical id.
4200
4219
  */
4220
+ private setSyncEnabledOrThrow;
4201
4221
  private getCurrentSyncInstance;
4202
4222
  private dispatchSyncWorkflows;
4203
4223
  private heartbeatSyncWorkflows;
package/dist/base.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- 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.CefGTNH1.js';
2
- import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.BOeuHdjy.js';
1
+ 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.CgiEbvJu.js';
2
+ import { S as SendPaymentInput, a as SendPaymentOutput, b as SendPaymentSyncInput, c as SendPaymentSyncOutput, F as FinbricksSupportedBanksResponse } from './shared/bank.-8YAJoxw.js';
3
3
  import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
4
4
  import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
2699
2699
  limit: z.ZodNumber;
2700
2700
  sort: z.ZodObject<{
2701
2701
  column: z.ZodEnum<{
2702
- batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2703
2702
  createdAt: "createdAt";
2704
2703
  updatedAt: "updatedAt";
2704
+ batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
2705
2705
  }>;
2706
2706
  direction: z.ZodEnum<{
2707
2707
  asc: "asc";
@@ -2958,8 +2958,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2958
2958
  filterPaymentStatus: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
2959
2959
  BOOKED: "BOOKED";
2960
2960
  REJECTED: "REJECTED";
2961
- PROCESSING: "PROCESSING";
2962
2961
  PENDING: "PENDING";
2962
+ PROCESSING: "PROCESSING";
2963
2963
  CANCELLED: "CANCELLED";
2964
2964
  SCHEDULED: "SCHEDULED";
2965
2965
  HOLD: "HOLD";
@@ -2967,8 +2967,8 @@ declare const getPaymentsInputSchema: z.ZodObject<{
2967
2967
  }>, z.ZodArray<z.ZodEnum<{
2968
2968
  BOOKED: "BOOKED";
2969
2969
  REJECTED: "REJECTED";
2970
- PROCESSING: "PROCESSING";
2971
2970
  PENDING: "PENDING";
2971
+ PROCESSING: "PROCESSING";
2972
2972
  CANCELLED: "CANCELLED";
2973
2973
  SCHEDULED: "SCHEDULED";
2974
2974
  HOLD: "HOLD";
@@ -3114,7 +3114,8 @@ declare const syncAccountTerminateInputSchema: z.ZodObject<{
3114
3114
  accountId: z.ZodUUID;
3115
3115
  }, z.core.$strip>;
3116
3116
  declare const syncAccountTerminateOutputSchema: z.ZodObject<{
3117
- instanceId: z.ZodString;
3117
+ terminated: z.ZodBoolean;
3118
+ instanceId: z.ZodNullable<z.ZodString>;
3118
3119
  }, z.core.$strip>;
3119
3120
  interface SyncAccountTerminateInput extends z.infer<typeof syncAccountTerminateInputSchema> {
3120
3121
  }
@@ -3266,6 +3267,22 @@ declare const updateAccountInputSchema: z.ZodObject<{
3266
3267
  identity: undefined;
3267
3268
  generated: undefined;
3268
3269
  }, {}>;
3270
+ syncEnabled: drizzle_orm_sqlite_core.SQLiteColumn<{
3271
+ name: string;
3272
+ tableName: "account";
3273
+ dataType: "boolean";
3274
+ data: boolean;
3275
+ driverParam: number;
3276
+ notNull: true;
3277
+ hasDefault: true;
3278
+ isPrimaryKey: false;
3279
+ isAutoincrement: false;
3280
+ hasRuntimeDefault: false;
3281
+ enumValues: undefined;
3282
+ baseColumn: never;
3283
+ identity: undefined;
3284
+ generated: undefined;
3285
+ }, {}>;
3269
3286
  syncIntervalS: drizzle_orm_sqlite_core.SQLiteColumn<{
3270
3287
  name: string;
3271
3288
  tableName: "account";
@@ -4092,6 +4109,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4092
4109
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4093
4110
  bankRefId: string;
4094
4111
  batchSizeLimit: number;
4112
+ syncEnabled: boolean;
4095
4113
  syncIntervalS: number;
4096
4114
  lastSyncAt: Date | null;
4097
4115
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4127,6 +4145,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4127
4145
  status: "AUTHORIZED" | "DISABLED" | "EXPIRED";
4128
4146
  bankRefId: string;
4129
4147
  batchSizeLimit: number;
4148
+ syncEnabled: boolean;
4130
4149
  syncIntervalS: number;
4131
4150
  lastSyncAt: Date | null;
4132
4151
  lastSyncMetadata: LastSyncMetadata | null;
@@ -4198,6 +4217,7 @@ declare class BankServiceBase extends BankServiceBase_base {
4198
4217
  * account — under dispatch that is the windowed instance recorded with the
4199
4218
  * last sync write, not the legacy canonical id.
4200
4219
  */
4220
+ private setSyncEnabledOrThrow;
4201
4221
  private getCurrentSyncInstance;
4202
4222
  private dispatchSyncWorkflows;
4203
4223
  private heartbeatSyncWorkflows;
package/dist/base.mjs CHANGED
@@ -1,12 +1,12 @@
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.BVXtqHnq.mjs';
3
- import { j as encrypt, d as createCredentialsResolver, i as initiateConnector, p as parseIterationBudgetParam, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, b as getAccountByIdQuery, k as resolveCurrentSyncInstanceId, l as importAesKey, h as createPaymentCommand } from './shared/bank.D6gBgL07.mjs';
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.kz-PKVi5.mjs';
3
+ import { j as encrypt, d as createCredentialsResolver, i as initiateConnector, p as parseIterationBudgetParam, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, b as getAccountByIdQuery, k as resolveCurrentSyncInstanceId, l as importAesKey, h as createPaymentCommand } from './shared/bank.DAjqsBQN.mjs';
4
4
  import { eq, sql, and, like, asc, desc, inArray, gte, lte, isNull, count } from 'drizzle-orm';
5
5
  import { WorkerEntrypoint } from 'cloudflare:workers';
6
6
  import { drizzle } from 'drizzle-orm/d1';
7
7
  import 'jose';
8
8
  import { z } from 'zod';
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.BzDNLxB_.mjs';
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';
11
11
  import 'date-fns';
12
12
  import 'node:crypto';
@@ -206,6 +206,26 @@ function isAlreadyFiniteError(err) {
206
206
  return /cannot_terminate|finite state/i.test(message);
207
207
  }
208
208
 
209
+ async function disableAccountSync({
210
+ accountId,
211
+ persistDisabled,
212
+ terminateInstance,
213
+ logger
214
+ }) {
215
+ await persistDisabled();
216
+ try {
217
+ const instanceId = await terminateInstance();
218
+ logger.info("sync-workflow.disable.terminated", { accountId, instanceId });
219
+ return { terminated: true, instanceId };
220
+ } catch (err) {
221
+ logger.warn("sync-workflow.disable.terminate-skipped", {
222
+ accountId,
223
+ error: err instanceof Error ? err.message : String(err)
224
+ });
225
+ return { terminated: false, instanceId: null };
226
+ }
227
+ }
228
+
209
229
  const upsertAccountCommand = (db, { account }) => {
210
230
  const id = account.id || uuidv4();
211
231
  const { id: _id, ...accountWithoutId } = account;
@@ -293,6 +313,13 @@ const createPaymentRequestCommand = (db, { paymentRequest }) => {
293
313
  };
294
314
  };
295
315
 
316
+ const updateAccountSyncEnabledCommand = (db, { accountId, syncEnabled }) => {
317
+ const command = db.update(tables.account).set({ syncEnabled }).where(eq(tables.account.id, accountId)).returning();
318
+ return {
319
+ command
320
+ };
321
+ };
322
+
296
323
  const getAccountBatchCountsQuery = async (db, { accountId }) => {
297
324
  const result = await db.select({
298
325
  totalCount: sql`COUNT(*)`.as("totalCount"),
@@ -562,6 +589,21 @@ const getPaymentRequestsQuery = async (db, params) => {
562
589
  return { paymentRequests, totalCount };
563
590
  };
564
591
 
592
+ const getSyncCandidateAccountsQuery = async (db) => {
593
+ return await db.select({
594
+ id: tables.account.id,
595
+ syncIntervalS: tables.account.syncIntervalS,
596
+ lastSyncAt: tables.account.lastSyncAt,
597
+ lastSyncMetadata: tables.account.lastSyncMetadata,
598
+ createdAt: tables.account.createdAt
599
+ }).from(tables.account).where(
600
+ and(
601
+ eq(tables.account.status, "AUTHORIZED"),
602
+ eq(tables.account.syncEnabled, true)
603
+ )
604
+ ).all();
605
+ };
606
+
565
607
  const SIGNAL_MAP = {
566
608
  OPENED: "paymentRequestOpened",
567
609
  AUTHORIZED: "paymentRequestAuthorized",
@@ -788,7 +830,9 @@ const syncAccountTerminateInputSchema = z.object({
788
830
  accountId: z.uuid()
789
831
  });
790
832
  z.object({
791
- instanceId: z.string()
833
+ terminated: z.boolean(),
834
+ // Null when the flag was persisted but no live instance existed to kill.
835
+ instanceId: z.string().nullable()
792
836
  });
793
837
 
794
838
  const updateAccountInputSchema = z.object({
@@ -864,6 +908,11 @@ var __decorateClass = (decorators, target, key, kind) => {
864
908
  if (kind && result) __defProp(target, key, result);
865
909
  return result;
866
910
  };
911
+ const accountNotFoundError = () => createInternalError(null, {
912
+ message: "Account not found",
913
+ code: "DB-B-005",
914
+ status: 404
915
+ });
867
916
  const syncEventConsoleLogger = {
868
917
  info: (event, data) => console.log(JSON.stringify({ level: "info", event, ...data })),
869
918
  warn: (event, data) => console.warn(JSON.stringify({ level: "warn", event, ...data })),
@@ -971,6 +1020,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
971
1020
  { data: input, schema: syncAccountInputSchema },
972
1021
  { successMessage: "Account sync workflow started" },
973
1022
  async ({ accountId }) => {
1023
+ await this.setSyncEnabledOrThrow(accountId, true);
974
1024
  if (isDispatchActive(
975
1025
  accountId,
976
1026
  this.env.SYNC_DISPATCH_ACCOUNT_IDS,
@@ -1025,6 +1075,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1025
1075
  { data: input, schema: syncAccountRestartInputSchema },
1026
1076
  { successMessage: "Account sync workflow restarted" },
1027
1077
  async ({ accountId }) => {
1078
+ await this.setSyncEnabledOrThrow(accountId, true);
1028
1079
  const instance = await this.getCurrentSyncInstance(accountId);
1029
1080
  await instance.restart();
1030
1081
  return {
@@ -1039,11 +1090,16 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1039
1090
  { data: input, schema: syncAccountTerminateInputSchema },
1040
1091
  { successMessage: "Account sync workflow terminated" },
1041
1092
  async ({ accountId }) => {
1042
- const instance = await this.getCurrentSyncInstance(accountId);
1043
- await terminateSyncWorkflow(instance);
1044
- return {
1045
- instanceId: instance.id
1046
- };
1093
+ return disableAccountSync({
1094
+ accountId,
1095
+ persistDisabled: () => this.setSyncEnabledOrThrow(accountId, false),
1096
+ terminateInstance: async () => {
1097
+ const instance = await this.getCurrentSyncInstance(accountId);
1098
+ await terminateSyncWorkflow(instance);
1099
+ return instance.id;
1100
+ },
1101
+ logger: syncEventConsoleLogger
1102
+ });
1047
1103
  }
1048
1104
  );
1049
1105
  }
@@ -1337,6 +1393,15 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1337
1393
  * account — under dispatch that is the windowed instance recorded with the
1338
1394
  * last sync write, not the legacy canonical id.
1339
1395
  */
1396
+ async setSyncEnabledOrThrow(accountId, syncEnabled) {
1397
+ const [updated] = await updateAccountSyncEnabledCommand(this.db, {
1398
+ accountId,
1399
+ syncEnabled
1400
+ }).command;
1401
+ if (!updated) {
1402
+ throw accountNotFoundError();
1403
+ }
1404
+ }
1340
1405
  async getCurrentSyncInstance(accountId) {
1341
1406
  const account = await getAccountByIdQuery(this.db, { accountId });
1342
1407
  return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
@@ -1349,12 +1414,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1349
1414
  async dispatchSyncWorkflows() {
1350
1415
  const selection = this.env.SYNC_DISPATCH_ACCOUNT_IDS;
1351
1416
  if (!selection?.trim()) return;
1352
- const accounts = await this.db.select({
1353
- id: tables.account.id,
1354
- syncIntervalS: tables.account.syncIntervalS,
1355
- lastSyncAt: tables.account.lastSyncAt,
1356
- createdAt: tables.account.createdAt
1357
- }).from(tables.account).where(eq(tables.account.status, "AUTHORIZED")).all();
1417
+ const accounts = await getSyncCandidateAccountsQuery(this.db);
1358
1418
  const maxIterations = parseIterationBudgetParam(
1359
1419
  this.env.SYNC_WORKFLOW_MAX_ITERATIONS
1360
1420
  );
@@ -1373,13 +1433,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
1373
1433
  });
1374
1434
  }
1375
1435
  async heartbeatSyncWorkflows() {
1376
- const accounts = await this.db.select({
1377
- id: tables.account.id,
1378
- lastSyncMetadata: tables.account.lastSyncMetadata,
1379
- syncIntervalS: tables.account.syncIntervalS,
1380
- lastSyncAt: tables.account.lastSyncAt,
1381
- createdAt: tables.account.createdAt
1382
- }).from(tables.account).where(eq(tables.account.status, "AUTHORIZED")).all();
1436
+ const accounts = await getSyncCandidateAccountsQuery(this.db);
1383
1437
  const resetAfterIterations = Number(
1384
1438
  this.env.SYNC_WORKFLOW_RESET_AFTER_ITERATIONS
1385
1439
  );
@@ -2271,11 +2325,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
2271
2325
  async ({ accountId }) => {
2272
2326
  const account = await getAccountByIdQuery(this.db, { accountId });
2273
2327
  if (!account) {
2274
- throw createInternalError(null, {
2275
- message: "Account not found",
2276
- code: "DB-B-005",
2277
- status: 404
2278
- });
2328
+ throw accountNotFoundError();
2279
2329
  }
2280
2330
  try {
2281
2331
  const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(