@develit-services/bank 0.2.2 → 0.2.4

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.
Files changed (35) hide show
  1. package/dist/database/schema.cjs +2 -3
  2. package/dist/database/schema.d.cts +6 -3
  3. package/dist/database/schema.d.mts +6 -3
  4. package/dist/database/schema.d.ts +6 -3
  5. package/dist/database/schema.mjs +2 -3
  6. package/dist/export/worker.cjs +39 -46
  7. package/dist/export/worker.d.cts +25 -15
  8. package/dist/export/worker.d.mts +25 -15
  9. package/dist/export/worker.d.ts +25 -15
  10. package/dist/export/worker.mjs +35 -42
  11. package/dist/export/workflows.cjs +92 -94
  12. package/dist/export/workflows.mjs +92 -94
  13. package/dist/export/wrangler.cjs +1 -0
  14. package/dist/export/wrangler.d.cts +1 -0
  15. package/dist/export/wrangler.d.mts +1 -0
  16. package/dist/export/wrangler.d.ts +1 -0
  17. package/dist/export/wrangler.mjs +1 -0
  18. package/dist/shared/{bank.CXUMEJH4.mjs → bank.BvUtf1S3.mjs} +41 -20
  19. package/dist/shared/{bank.CEraaQIT.cjs → bank.CHS79KTx.cjs} +42 -21
  20. package/dist/shared/{bank.2BgwPCw_.d.ts → bank.Cfz44GPA.d.cts} +1598 -12
  21. package/dist/shared/{bank.BOe_Qmuw.d.mts → bank.Cfz44GPA.d.mts} +1598 -12
  22. package/dist/shared/{bank.RD4xwHFf.d.cts → bank.Cfz44GPA.d.ts} +1598 -12
  23. package/dist/shared/{bank.B8QzFnJl.cjs → bank.CyinOg3r.cjs} +1 -1
  24. package/dist/shared/{bank.CjZRgRoJ.mjs → bank.DKtu6cfY.mjs} +1 -1
  25. package/dist/shared/{bank.B0uSWeRe.mjs → bank.DXn9jD0Q.mjs} +43 -60
  26. package/dist/shared/{bank.CWAToo_g.cjs → bank.NdqOkgpd.cjs} +41 -59
  27. package/dist/types.cjs +2 -4
  28. package/dist/types.d.cts +3 -5
  29. package/dist/types.d.mts +3 -5
  30. package/dist/types.d.ts +3 -5
  31. package/dist/types.mjs +2 -3
  32. package/package.json +2 -1
  33. package/dist/shared/bank.BGZYksmV.d.cts +0 -1598
  34. package/dist/shared/bank.BGZYksmV.d.mts +0 -1598
  35. package/dist/shared/bank.BGZYksmV.d.ts +0 -1598
@@ -3,25 +3,34 @@
3
3
  const cloudflare_workers = require('cloudflare:workers');
4
4
  const cloudflare_workflows = require('cloudflare:workflows');
5
5
  const d1 = require('drizzle-orm/d1');
6
- const database_schema = require('../shared/bank.CWAToo_g.cjs');
6
+ const database_schema = require('../shared/bank.NdqOkgpd.cjs');
7
7
  const backendSdk = require('@develit-io/backend-sdk');
8
- const bank = require('../shared/bank.CEraaQIT.cjs');
8
+ const encryption = require('../shared/bank.CHS79KTx.cjs');
9
9
  const drizzleOrm = require('drizzle-orm');
10
10
  require('drizzle-orm/sqlite-core');
11
11
  require('date-fns');
12
- require('@develit-io/general-codes');
13
- require('zod');
14
12
  require('jose');
13
+ require('@develit-io/general-codes');
15
14
  require('drizzle-zod');
16
15
  require('drizzle-orm/relations');
17
- require('../shared/bank.B8QzFnJl.cjs');
16
+ require('../shared/bank.CyinOg3r.cjs');
18
17
 
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();
18
+ const updateAccountLastSyncCommand = (db, {
19
+ lastSyncAt,
20
+ accountId,
21
+ lastSyncMetadata
22
+ }) => {
23
+ const command = db.update(database_schema.tables.account).set({
24
+ lastSyncAt,
25
+ lastSyncMetadata
26
+ }).where(drizzleOrm.eq(database_schema.tables.account.id, accountId)).returning();
27
+ return {
28
+ command
29
+ };
21
30
  };
22
31
 
23
- const getPaymentsByBankRefIdsQuery = async (db, { ids }) => {
24
- return await db.select().from(database_schema.tables.payment).where(drizzleOrm.inArray(database_schema.tables.payment.bankRefId, ids));
32
+ const getAccountByIdQuery = async (db, { accountId }) => {
33
+ return await db.select().from(database_schema.tables.account).where(drizzleOrm.eq(database_schema.tables.account.id, accountId)).get();
25
34
  };
26
35
 
27
36
  function pushToQueue(queue, message) {
@@ -38,6 +47,7 @@ class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint
38
47
  const { accountId } = event.payload;
39
48
  const db = d1.drizzle(this.env.BANK_D1, { schema: database_schema.tables });
40
49
  while (true) {
50
+ const now = /* @__PURE__ */ new Date();
41
51
  const account = await step.do("load account", async () => {
42
52
  const account2 = await getAccountByIdQuery(db, { accountId });
43
53
  if (!account2) {
@@ -45,21 +55,10 @@ class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint
45
55
  }
46
56
  return account2;
47
57
  });
48
- if (!account.lastSyncedAt) {
58
+ if (!account.lastSyncAt) {
49
59
  throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
50
60
  }
51
- const credentials = await step.do(
52
- "load account credentials",
53
- async () => {
54
- const credentials2 = await bank.getCredentialsByAccountId(db, { accountId });
55
- if (!credentials2) {
56
- throw new cloudflare_workflows.NonRetryableError(
57
- `No credentials found for account: ${accountId}`
58
- );
59
- }
60
- return credentials2;
61
- }
62
- );
61
+ //! ### This step is currently inside the fetch payments step with retries due to cf workflows output logs (until they allow hiding sensitive data) <-----
63
62
  const payments = await step.do(
64
63
  "fetch bank payments",
65
64
  {
@@ -67,7 +66,23 @@ class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint
67
66
  timeout: "30 seconds"
68
67
  },
69
68
  async () => {
70
- const connector = bank.initiateConnector({
69
+ const encryptionKey = await encryption.importAesKey(this.env.ENCRYPTION_KEY);
70
+ const credentials = await encryption.getCredentialsByAccountId(
71
+ db,
72
+ encryptionKey,
73
+ { accountId }
74
+ );
75
+ if (!credentials) {
76
+ throw new cloudflare_workflows.NonRetryableError(
77
+ `No credentials found for account: ${accountId}`
78
+ );
79
+ }
80
+ if (credentials.expiresAt < /* @__PURE__ */ new Date()) {
81
+ throw new cloudflare_workflows.NonRetryableError(
82
+ `Credentials have expired for account: ${accountId}`
83
+ );
84
+ }
85
+ const connector = encryption.initiateConnector({
71
86
  env: this.env,
72
87
  bank: account.connectorKey,
73
88
  connectedAccounts: [
@@ -82,84 +97,67 @@ class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint
82
97
  environment: this.env.ENVIRONMENT,
83
98
  db,
84
99
  account,
85
- filter: { dateFrom: account.lastSyncedAt }
100
+ filter: { dateFrom: account.lastSyncAt }
86
101
  });
87
102
  }
88
103
  );
89
- if (payments.length) {
90
- const bankRefIds = payments.map((payment) => payment.parsed.bankRefId).filter(Boolean);
91
- const existing = await step.do("load existing payments", async () => {
92
- return await getPaymentsByBankRefIdsQuery(db, {
93
- ids: bankRefIds
94
- });
95
- });
96
- const paymentsToUpdate = payments.filter(
97
- (p) => existing.some((e) => e.bankRefId === p.parsed.bankRefId)
98
- );
99
- const paymentsToCreate = payments.filter(
100
- (p) => !existing.some((e) => e.bankRefId === p.parsed.bankRefId)
104
+ const paymentsToProcess = payments.filter(
105
+ (p) => p.parsed.status === "COMPLETED" || p.parsed.status === "FAILED"
106
+ );
107
+ if (paymentsToProcess.length) {
108
+ const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
109
+ const paymentsToInsert = paymentsToProcess.filter(
110
+ (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
101
111
  );
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.parsed }).command
106
- );
107
- eventsToEmit.push(
108
- ...paymentsToUpdate.map((p) => ({
109
- eventType: "BANK_PAYMENT",
110
- eventSignal: "paymentUpdated",
111
- bankPayment: p.parsed,
112
- metadata: {
113
- correlationId: p.parsed.correlationId,
114
- entityId: p.parsed.id,
115
- idempotencySuffix: p.parsed.status,
116
- timestamp: (/* @__PURE__ */ new Date()).toDateString()
117
- }
118
- }))
119
- );
120
- const createCommands = paymentsToCreate.map(
121
- (p) => bank.createPaymentCommand(db, { payment: p.parsed }).command
122
- );
123
- eventsToEmit.push(
124
- ...paymentsToCreate.map((p) => ({
125
- eventType: "BANK_PAYMENT",
126
- eventSignal: "paymentCreated",
127
- bankPayment: p.parsed,
128
- metadata: {
129
- correlationId: p.parsed.correlationId,
130
- entityId: p.parsed.id,
131
- timestamp: (/* @__PURE__ */ new Date()).toDateString()
132
- }
133
- }))
134
- );
135
- const latest = payments.reduce((current, p) => {
136
- return new Date(p.parsed.processedAt).getTime() > new Date(current.parsed.processedAt).getTime() ? p : current;
137
- }, payments[0]);
138
- const updateLastSyncCommand = bank.updateAccountLastSyncCommand(db, {
139
- accountId: account.id,
140
- lastSyncedAt: latest.parsed.processedAt
141
- }).command;
142
- if (eventsToEmit.length) {
143
- await db.batch(
144
- backendSdk.asNonEmpty([
145
- updateLastSyncCommand,
146
- ...updateCommands,
147
- ...createCommands
148
- ])
112
+ await step.do(
113
+ "process new payments and update lastSyncAt",
114
+ async () => {
115
+ const eventsToEmit = [];
116
+ const createCommands = paymentsToInsert.map(
117
+ (p) => encryption.createPaymentCommand(db, { payment: p.parsed }).command
149
118
  );
150
- await pushToQueue(
151
- this.env.QUEUE_BUS_QUEUE,
152
- eventsToEmit
119
+ eventsToEmit.push(
120
+ ...paymentsToInsert.map((p) => ({
121
+ eventType: "BANK_PAYMENT",
122
+ eventSignal: "paymentCreated",
123
+ bankPayment: p.parsed,
124
+ metadata: {
125
+ correlationId: p.parsed.correlationId,
126
+ entityId: p.parsed.id,
127
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
128
+ }
129
+ }))
153
130
  );
131
+ const lastSyncMetadata = {
132
+ payments: payments.length,
133
+ paymentsToProcess: paymentsToProcess.length,
134
+ paymentsInserted: paymentsToInsert.length,
135
+ lastSyncBankRefIds: paymentsToProcess.map(
136
+ (p) => p.parsed.bankRefId
137
+ ),
138
+ lastSyncPayments: lastSyncBankRefIds.length,
139
+ eventsEmitted: eventsToEmit.length
140
+ };
141
+ const updateLastSyncCommand = updateAccountLastSyncCommand(db, {
142
+ accountId: account.id,
143
+ lastSyncAt: now,
144
+ lastSyncMetadata
145
+ }).command;
146
+ if (eventsToEmit.length) {
147
+ await db.batch(
148
+ backendSdk.asNonEmpty([updateLastSyncCommand, ...createCommands])
149
+ );
150
+ await pushToQueue(
151
+ this.env.QUEUE_BUS_QUEUE,
152
+ eventsToEmit
153
+ );
154
+ }
155
+ return {
156
+ ...lastSyncMetadata,
157
+ newLastSyncAt: now
158
+ };
154
159
  }
155
- return {
156
- payments: payments.length,
157
- updated: paymentsToUpdate.length,
158
- created: paymentsToCreate.length,
159
- eventsEmitted: eventsToEmit.length,
160
- lastSyncedAt: latest?.parsed?.createdAt
161
- };
162
- });
160
+ );
163
161
  }
164
162
  await step.sleep(
165
163
  "Sleep for next sync",
@@ -1,25 +1,34 @@
1
1
  import { WorkflowEntrypoint } from 'cloudflare:workers';
2
2
  import { NonRetryableError } from 'cloudflare:workflows';
3
3
  import { drizzle } from 'drizzle-orm/d1';
4
- import { t as tables } from '../shared/bank.B0uSWeRe.mjs';
4
+ import { t as tables } from '../shared/bank.DXn9jD0Q.mjs';
5
5
  import { asNonEmpty } from '@develit-io/backend-sdk';
6
- import { g as getCredentialsByAccountId, i as initiateConnector, u as updatePaymentCommand, c as createPaymentCommand, a as updateAccountLastSyncCommand } from '../shared/bank.CXUMEJH4.mjs';
7
- import { eq, inArray } from 'drizzle-orm';
6
+ import { i as importAesKey, g as getCredentialsByAccountId, a as initiateConnector, c as createPaymentCommand } from '../shared/bank.BvUtf1S3.mjs';
7
+ import { eq } from 'drizzle-orm';
8
8
  import 'drizzle-orm/sqlite-core';
9
9
  import 'date-fns';
10
- import '@develit-io/general-codes';
11
- import 'zod';
12
10
  import 'jose';
11
+ import '@develit-io/general-codes';
13
12
  import 'drizzle-zod';
14
13
  import 'drizzle-orm/relations';
15
- import '../shared/bank.CjZRgRoJ.mjs';
14
+ import '../shared/bank.DKtu6cfY.mjs';
16
15
 
17
- const getAccountByIdQuery = async (db, { accountId }) => {
18
- return await db.select().from(tables.account).where(eq(tables.account.id, accountId)).get();
16
+ const updateAccountLastSyncCommand = (db, {
17
+ lastSyncAt,
18
+ accountId,
19
+ lastSyncMetadata
20
+ }) => {
21
+ const command = db.update(tables.account).set({
22
+ lastSyncAt,
23
+ lastSyncMetadata
24
+ }).where(eq(tables.account.id, accountId)).returning();
25
+ return {
26
+ command
27
+ };
19
28
  };
20
29
 
21
- const getPaymentsByBankRefIdsQuery = async (db, { ids }) => {
22
- return await db.select().from(tables.payment).where(inArray(tables.payment.bankRefId, ids));
30
+ const getAccountByIdQuery = async (db, { accountId }) => {
31
+ return await db.select().from(tables.account).where(eq(tables.account.id, accountId)).get();
23
32
  };
24
33
 
25
34
  function pushToQueue(queue, message) {
@@ -36,6 +45,7 @@ class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
36
45
  const { accountId } = event.payload;
37
46
  const db = drizzle(this.env.BANK_D1, { schema: tables });
38
47
  while (true) {
48
+ const now = /* @__PURE__ */ new Date();
39
49
  const account = await step.do("load account", async () => {
40
50
  const account2 = await getAccountByIdQuery(db, { accountId });
41
51
  if (!account2) {
@@ -43,21 +53,10 @@ class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
43
53
  }
44
54
  return account2;
45
55
  });
46
- if (!account.lastSyncedAt) {
56
+ if (!account.lastSyncAt) {
47
57
  throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
48
58
  }
49
- const credentials = await step.do(
50
- "load account credentials",
51
- async () => {
52
- const credentials2 = await getCredentialsByAccountId(db, { accountId });
53
- if (!credentials2) {
54
- throw new NonRetryableError(
55
- `No credentials found for account: ${accountId}`
56
- );
57
- }
58
- return credentials2;
59
- }
60
- );
59
+ //! ### This step is currently inside the fetch payments step with retries due to cf workflows output logs (until they allow hiding sensitive data) <-----
61
60
  const payments = await step.do(
62
61
  "fetch bank payments",
63
62
  {
@@ -65,6 +64,22 @@ class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
65
64
  timeout: "30 seconds"
66
65
  },
67
66
  async () => {
67
+ const encryptionKey = await importAesKey(this.env.ENCRYPTION_KEY);
68
+ const credentials = await getCredentialsByAccountId(
69
+ db,
70
+ encryptionKey,
71
+ { accountId }
72
+ );
73
+ if (!credentials) {
74
+ throw new NonRetryableError(
75
+ `No credentials found for account: ${accountId}`
76
+ );
77
+ }
78
+ if (credentials.expiresAt < /* @__PURE__ */ new Date()) {
79
+ throw new NonRetryableError(
80
+ `Credentials have expired for account: ${accountId}`
81
+ );
82
+ }
68
83
  const connector = initiateConnector({
69
84
  env: this.env,
70
85
  bank: account.connectorKey,
@@ -80,84 +95,67 @@ class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
80
95
  environment: this.env.ENVIRONMENT,
81
96
  db,
82
97
  account,
83
- filter: { dateFrom: account.lastSyncedAt }
98
+ filter: { dateFrom: account.lastSyncAt }
84
99
  });
85
100
  }
86
101
  );
87
- if (payments.length) {
88
- const bankRefIds = payments.map((payment) => payment.parsed.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.parsed.bankRefId)
96
- );
97
- const paymentsToCreate = payments.filter(
98
- (p) => !existing.some((e) => e.bankRefId === p.parsed.bankRefId)
102
+ const paymentsToProcess = payments.filter(
103
+ (p) => p.parsed.status === "COMPLETED" || p.parsed.status === "FAILED"
104
+ );
105
+ if (paymentsToProcess.length) {
106
+ const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
107
+ const paymentsToInsert = paymentsToProcess.filter(
108
+ (p) => !lastSyncBankRefIds.includes(p.parsed.bankRefId)
99
109
  );
100
- await step.do("process payments and update lastSyncAt", async () => {
101
- const eventsToEmit = [];
102
- const updateCommands = paymentsToUpdate.map(
103
- (p) => updatePaymentCommand(db, { payment: p.parsed }).command
104
- );
105
- eventsToEmit.push(
106
- ...paymentsToUpdate.map((p) => ({
107
- eventType: "BANK_PAYMENT",
108
- eventSignal: "paymentUpdated",
109
- bankPayment: p.parsed,
110
- metadata: {
111
- correlationId: p.parsed.correlationId,
112
- entityId: p.parsed.id,
113
- idempotencySuffix: p.parsed.status,
114
- timestamp: (/* @__PURE__ */ new Date()).toDateString()
115
- }
116
- }))
117
- );
118
- const createCommands = paymentsToCreate.map(
119
- (p) => createPaymentCommand(db, { payment: p.parsed }).command
120
- );
121
- eventsToEmit.push(
122
- ...paymentsToCreate.map((p) => ({
123
- eventType: "BANK_PAYMENT",
124
- eventSignal: "paymentCreated",
125
- bankPayment: p.parsed,
126
- metadata: {
127
- correlationId: p.parsed.correlationId,
128
- entityId: p.parsed.id,
129
- timestamp: (/* @__PURE__ */ new Date()).toDateString()
130
- }
131
- }))
132
- );
133
- const latest = payments.reduce((current, p) => {
134
- return new Date(p.parsed.processedAt).getTime() > new Date(current.parsed.processedAt).getTime() ? p : current;
135
- }, payments[0]);
136
- const updateLastSyncCommand = updateAccountLastSyncCommand(db, {
137
- accountId: account.id,
138
- lastSyncedAt: latest.parsed.processedAt
139
- }).command;
140
- if (eventsToEmit.length) {
141
- await db.batch(
142
- asNonEmpty([
143
- updateLastSyncCommand,
144
- ...updateCommands,
145
- ...createCommands
146
- ])
110
+ await step.do(
111
+ "process new payments and update lastSyncAt",
112
+ async () => {
113
+ const eventsToEmit = [];
114
+ const createCommands = paymentsToInsert.map(
115
+ (p) => createPaymentCommand(db, { payment: p.parsed }).command
147
116
  );
148
- await pushToQueue(
149
- this.env.QUEUE_BUS_QUEUE,
150
- eventsToEmit
117
+ eventsToEmit.push(
118
+ ...paymentsToInsert.map((p) => ({
119
+ eventType: "BANK_PAYMENT",
120
+ eventSignal: "paymentCreated",
121
+ bankPayment: p.parsed,
122
+ metadata: {
123
+ correlationId: p.parsed.correlationId,
124
+ entityId: p.parsed.id,
125
+ timestamp: (/* @__PURE__ */ new Date()).toDateString()
126
+ }
127
+ }))
151
128
  );
129
+ const lastSyncMetadata = {
130
+ payments: payments.length,
131
+ paymentsToProcess: paymentsToProcess.length,
132
+ paymentsInserted: paymentsToInsert.length,
133
+ lastSyncBankRefIds: paymentsToProcess.map(
134
+ (p) => p.parsed.bankRefId
135
+ ),
136
+ lastSyncPayments: lastSyncBankRefIds.length,
137
+ eventsEmitted: eventsToEmit.length
138
+ };
139
+ const updateLastSyncCommand = updateAccountLastSyncCommand(db, {
140
+ accountId: account.id,
141
+ lastSyncAt: now,
142
+ lastSyncMetadata
143
+ }).command;
144
+ if (eventsToEmit.length) {
145
+ await db.batch(
146
+ asNonEmpty([updateLastSyncCommand, ...createCommands])
147
+ );
148
+ await pushToQueue(
149
+ this.env.QUEUE_BUS_QUEUE,
150
+ eventsToEmit
151
+ );
152
+ }
153
+ return {
154
+ ...lastSyncMetadata,
155
+ newLastSyncAt: now
156
+ };
152
157
  }
153
- return {
154
- payments: payments.length,
155
- updated: paymentsToUpdate.length,
156
- created: paymentsToCreate.length,
157
- eventsEmitted: eventsToEmit.length,
158
- lastSyncedAt: latest?.parsed?.createdAt
159
- };
160
- });
158
+ );
161
159
  }
162
160
  await step.sleep(
163
161
  "Sleep for next sync",
@@ -11,6 +11,7 @@ function defineBankServiceWrangler(config) {
11
11
  }),
12
12
  vars: {
13
13
  // Secrets
14
+ ENCRYPTION_KEY: "[SECRET]",
14
15
  FINBRICKS_PRIVATE_KEY_PEM: "[SECRET]",
15
16
  ERSTE_API_KEY: "[SECRET]",
16
17
  ERSTE_CLIENT_SECRET: "[SECRET]",
@@ -13,6 +13,7 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
13
13
  CRON_PAYMENTS_PROCESSING: string;
14
14
  BANK_AUTH_RECIPIENT: string;
15
15
  REDIRECT_URI: string;
16
+ ENCRYPTION_KEY: string;
16
17
  FINBRICKS_PRIVATE_KEY_PEM: string;
17
18
  ERSTE_API_KEY: string;
18
19
  ERSTE_CLIENT_SECRET: string;
@@ -13,6 +13,7 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
13
13
  CRON_PAYMENTS_PROCESSING: string;
14
14
  BANK_AUTH_RECIPIENT: string;
15
15
  REDIRECT_URI: string;
16
+ ENCRYPTION_KEY: string;
16
17
  FINBRICKS_PRIVATE_KEY_PEM: string;
17
18
  ERSTE_API_KEY: string;
18
19
  ERSTE_CLIENT_SECRET: string;
@@ -13,6 +13,7 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
13
13
  CRON_PAYMENTS_PROCESSING: string;
14
14
  BANK_AUTH_RECIPIENT: string;
15
15
  REDIRECT_URI: string;
16
+ ENCRYPTION_KEY: string;
16
17
  FINBRICKS_PRIVATE_KEY_PEM: string;
17
18
  ERSTE_API_KEY: string;
18
19
  ERSTE_CLIENT_SECRET: string;
@@ -9,6 +9,7 @@ function defineBankServiceWrangler(config) {
9
9
  }),
10
10
  vars: {
11
11
  // Secrets
12
+ ENCRYPTION_KEY: "[SECRET]",
12
13
  FINBRICKS_PRIVATE_KEY_PEM: "[SECRET]",
13
14
  ERSTE_API_KEY: "[SECRET]",
14
15
  ERSTE_CLIENT_SECRET: "[SECRET]",
@@ -1,8 +1,9 @@
1
- import { t as tables, F as FinbricksConnector, M as MockConnector, E as ErsteConnector } from './bank.B0uSWeRe.mjs';
1
+ import { t as tables, F as FinbricksConnector, M as MockConnector, E as ErsteConnector } from './bank.DXn9jD0Q.mjs';
2
+ import '@develit-io/backend-sdk';
2
3
  import { eq } from 'drizzle-orm';
3
- import { M as MockCobsConnector } from './bank.CjZRgRoJ.mjs';
4
4
  import 'jose';
5
5
  import '@develit-io/general-codes';
6
+ import { M as MockCobsConnector } from './bank.DKtu6cfY.mjs';
6
7
 
7
8
  const createPaymentCommand = (db, { payment }) => {
8
9
  return {
@@ -14,24 +15,12 @@ const createPaymentCommand = (db, { payment }) => {
14
15
  };
15
16
  };
16
17
 
17
- const updatePaymentCommand = (db, { payment }) => {
18
- return {
19
- command: db.update(tables.payment).set(payment).where(eq(tables.payment.id, payment.id)).returning()
20
- };
21
- };
22
-
23
- const updateAccountLastSyncCommand = (db, { lastSyncedAt, accountId }) => {
24
- const command = db.update(tables.account).set({
25
- lastSyncedAt
26
- }).where(eq(tables.account.id, accountId)).returning();
27
- return {
28
- command
29
- };
30
- };
31
-
32
- const getCredentialsByAccountId = async (db, { accountId }) => {
18
+ const getCredentialsByAccountId = async (db, encryptionKey, { accountId }) => {
33
19
  const cred = await db.select().from(tables.accountCredentials).where(eq(tables.accountCredentials.accountId, accountId)).get();
34
- return cred;
20
+ return cred ? {
21
+ ...cred,
22
+ value: await decrypt(cred.value, encryptionKey)
23
+ } : void 0;
35
24
  };
36
25
 
37
26
  class CreditasConnector extends FinbricksConnector {
@@ -106,4 +95,36 @@ const initiateConnector = ({
106
95
  }
107
96
  };
108
97
 
109
- export { updateAccountLastSyncCommand as a, createPaymentCommand as c, getCredentialsByAccountId as g, initiateConnector as i, updatePaymentCommand as u };
98
+ async function importAesKey(base64Key) {
99
+ const raw = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
100
+ return await crypto.subtle.importKey("raw", raw, { name: "AES-GCM" }, false, [
101
+ "encrypt",
102
+ "decrypt"
103
+ ]);
104
+ }
105
+ async function encrypt(value, key) {
106
+ const encoder = new TextEncoder();
107
+ const iv = crypto.getRandomValues(new Uint8Array(12));
108
+ const ciphertext = await crypto.subtle.encrypt(
109
+ { name: "AES-GCM", iv },
110
+ key,
111
+ encoder.encode(value)
112
+ );
113
+ const combined = new Uint8Array(iv.length + ciphertext.byteLength);
114
+ combined.set(iv, 0);
115
+ combined.set(new Uint8Array(ciphertext), iv.length);
116
+ return btoa(String.fromCharCode(...combined));
117
+ }
118
+ async function decrypt(base64, key) {
119
+ const raw = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
120
+ const iv = raw.slice(0, 12);
121
+ const ciphertext = raw.slice(12);
122
+ const decrypted = await crypto.subtle.decrypt(
123
+ { name: "AES-GCM", iv },
124
+ key,
125
+ ciphertext
126
+ );
127
+ return new TextDecoder().decode(decrypted);
128
+ }
129
+
130
+ export { initiateConnector as a, createPaymentCommand as c, encrypt as e, getCredentialsByAccountId as g, importAesKey as i };