@contractspec/integration.providers-impls 1.57.0 → 1.59.0

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 (256) hide show
  1. package/dist/analytics.d.ts +1 -8
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/analytics.js +3 -3
  4. package/dist/calendar.d.ts +1 -8
  5. package/dist/calendar.d.ts.map +1 -1
  6. package/dist/calendar.js +3 -3
  7. package/dist/database.d.ts +1 -8
  8. package/dist/database.d.ts.map +1 -1
  9. package/dist/database.js +3 -3
  10. package/dist/email.d.ts +1 -8
  11. package/dist/email.d.ts.map +1 -1
  12. package/dist/email.js +3 -3
  13. package/dist/embedding.d.ts +1 -8
  14. package/dist/embedding.d.ts.map +1 -1
  15. package/dist/embedding.js +3 -3
  16. package/dist/impls/elevenlabs-voice.d.ts +14 -18
  17. package/dist/impls/elevenlabs-voice.d.ts.map +1 -1
  18. package/dist/impls/elevenlabs-voice.js +98 -88
  19. package/dist/impls/fal-voice.d.ts +22 -26
  20. package/dist/impls/fal-voice.d.ts.map +1 -1
  21. package/dist/impls/fal-voice.js +103 -78
  22. package/dist/impls/fathom-meeting-recorder.d.ts +35 -39
  23. package/dist/impls/fathom-meeting-recorder.d.ts.map +1 -1
  24. package/dist/impls/fathom-meeting-recorder.js +285 -142
  25. package/dist/impls/fathom-meeting-recorder.mapper.d.ts +4 -8
  26. package/dist/impls/fathom-meeting-recorder.mapper.d.ts.map +1 -1
  27. package/dist/impls/fathom-meeting-recorder.mapper.js +102 -38
  28. package/dist/impls/fathom-meeting-recorder.types.d.ts +16 -20
  29. package/dist/impls/fathom-meeting-recorder.types.d.ts.map +1 -1
  30. package/dist/impls/fathom-meeting-recorder.types.js +1 -0
  31. package/dist/impls/fathom-meeting-recorder.utils.d.ts +10 -14
  32. package/dist/impls/fathom-meeting-recorder.utils.d.ts.map +1 -1
  33. package/dist/impls/fathom-meeting-recorder.utils.js +58 -41
  34. package/dist/impls/fathom-meeting-recorder.webhooks.d.ts +3 -7
  35. package/dist/impls/fathom-meeting-recorder.webhooks.d.ts.map +1 -1
  36. package/dist/impls/fathom-meeting-recorder.webhooks.js +25 -20
  37. package/dist/impls/fireflies-meeting-recorder.d.ts +21 -25
  38. package/dist/impls/fireflies-meeting-recorder.d.ts.map +1 -1
  39. package/dist/impls/fireflies-meeting-recorder.js +272 -149
  40. package/dist/impls/fireflies-meeting-recorder.queries.d.ts +3 -6
  41. package/dist/impls/fireflies-meeting-recorder.queries.d.ts.map +1 -1
  42. package/dist/impls/fireflies-meeting-recorder.queries.js +10 -8
  43. package/dist/impls/fireflies-meeting-recorder.types.d.ts +26 -29
  44. package/dist/impls/fireflies-meeting-recorder.types.d.ts.map +1 -1
  45. package/dist/impls/fireflies-meeting-recorder.types.js +1 -0
  46. package/dist/impls/fireflies-meeting-recorder.utils.d.ts +4 -7
  47. package/dist/impls/fireflies-meeting-recorder.utils.d.ts.map +1 -1
  48. package/dist/impls/fireflies-meeting-recorder.utils.js +34 -27
  49. package/dist/impls/gcs-storage.d.ts +18 -22
  50. package/dist/impls/gcs-storage.d.ts.map +1 -1
  51. package/dist/impls/gcs-storage.js +92 -84
  52. package/dist/impls/gmail-inbound.d.ts +20 -24
  53. package/dist/impls/gmail-inbound.d.ts.map +1 -1
  54. package/dist/impls/gmail-inbound.js +212 -185
  55. package/dist/impls/gmail-outbound.d.ts +12 -16
  56. package/dist/impls/gmail-outbound.d.ts.map +1 -1
  57. package/dist/impls/gmail-outbound.js +126 -92
  58. package/dist/impls/google-calendar.d.ts +17 -21
  59. package/dist/impls/google-calendar.d.ts.map +1 -1
  60. package/dist/impls/google-calendar.js +182 -145
  61. package/dist/impls/gradium-voice.d.ts +20 -22
  62. package/dist/impls/gradium-voice.d.ts.map +1 -1
  63. package/dist/impls/gradium-voice.js +85 -74
  64. package/dist/impls/granola-meeting-recorder.d.ts +31 -24
  65. package/dist/impls/granola-meeting-recorder.d.ts.map +1 -1
  66. package/dist/impls/granola-meeting-recorder.js +511 -143
  67. package/dist/impls/granola-meeting-recorder.mcp.d.ts +25 -0
  68. package/dist/impls/granola-meeting-recorder.mcp.d.ts.map +1 -0
  69. package/dist/impls/granola-meeting-recorder.mcp.js +279 -0
  70. package/dist/impls/granola-meeting-recorder.types.d.ts +60 -49
  71. package/dist/impls/granola-meeting-recorder.types.d.ts.map +1 -1
  72. package/dist/impls/granola-meeting-recorder.types.js +1 -0
  73. package/dist/impls/index.d.ts +28 -28
  74. package/dist/impls/index.d.ts.map +1 -0
  75. package/dist/impls/index.js +4659 -29
  76. package/dist/impls/jira.d.ts +18 -22
  77. package/dist/impls/jira.d.ts.map +1 -1
  78. package/dist/impls/jira.js +112 -101
  79. package/dist/impls/linear.d.ts +17 -21
  80. package/dist/impls/linear.d.ts.map +1 -1
  81. package/dist/impls/linear.js +78 -69
  82. package/dist/impls/mistral-embedding.d.ts +17 -21
  83. package/dist/impls/mistral-embedding.d.ts.map +1 -1
  84. package/dist/impls/mistral-embedding.js +41 -39
  85. package/dist/impls/mistral-llm.d.ts +25 -29
  86. package/dist/impls/mistral-llm.d.ts.map +1 -1
  87. package/dist/impls/mistral-llm.js +266 -244
  88. package/dist/impls/notion.d.ts +20 -24
  89. package/dist/impls/notion.d.ts.map +1 -1
  90. package/dist/impls/notion.js +145 -110
  91. package/dist/impls/posthog-reader.d.ts +18 -22
  92. package/dist/impls/posthog-reader.d.ts.map +1 -1
  93. package/dist/impls/posthog-reader.js +148 -129
  94. package/dist/impls/posthog-utils.d.ts +4 -7
  95. package/dist/impls/posthog-utils.d.ts.map +1 -1
  96. package/dist/impls/posthog-utils.js +31 -22
  97. package/dist/impls/posthog.d.ts +33 -37
  98. package/dist/impls/posthog.d.ts.map +1 -1
  99. package/dist/impls/posthog.js +320 -119
  100. package/dist/impls/postmark-email.d.ts +13 -17
  101. package/dist/impls/postmark-email.d.ts.map +1 -1
  102. package/dist/impls/postmark-email.js +55 -50
  103. package/dist/impls/powens-client.d.ts +111 -114
  104. package/dist/impls/powens-client.d.ts.map +1 -1
  105. package/dist/impls/powens-client.js +194 -170
  106. package/dist/impls/powens-openbanking.d.ts +22 -26
  107. package/dist/impls/powens-openbanking.d.ts.map +1 -1
  108. package/dist/impls/powens-openbanking.js +425 -217
  109. package/dist/impls/provider-factory.d.ts +29 -33
  110. package/dist/impls/provider-factory.d.ts.map +1 -1
  111. package/dist/impls/provider-factory.js +4072 -275
  112. package/dist/impls/qdrant-vector.d.ts +18 -22
  113. package/dist/impls/qdrant-vector.d.ts.map +1 -1
  114. package/dist/impls/qdrant-vector.js +76 -69
  115. package/dist/impls/stripe-payments.d.ts +22 -26
  116. package/dist/impls/stripe-payments.d.ts.map +1 -1
  117. package/dist/impls/stripe-payments.js +219 -193
  118. package/dist/impls/supabase-psql.d.ts +21 -25
  119. package/dist/impls/supabase-psql.d.ts.map +1 -1
  120. package/dist/impls/supabase-psql.js +138 -98
  121. package/dist/impls/supabase-vector.d.ts +29 -33
  122. package/dist/impls/supabase-vector.d.ts.map +1 -1
  123. package/dist/impls/supabase-vector.js +278 -103
  124. package/dist/impls/tldv-meeting-recorder.d.ts +18 -22
  125. package/dist/impls/tldv-meeting-recorder.d.ts.map +1 -1
  126. package/dist/impls/tldv-meeting-recorder.js +142 -127
  127. package/dist/impls/twilio-sms.d.ts +14 -17
  128. package/dist/impls/twilio-sms.d.ts.map +1 -1
  129. package/dist/impls/twilio-sms.js +62 -55
  130. package/dist/index.d.ts +15 -64
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +4700 -107
  133. package/dist/llm.d.ts +1 -8
  134. package/dist/llm.d.ts.map +1 -1
  135. package/dist/llm.js +3 -3
  136. package/dist/meeting-recorder.d.ts +1 -8
  137. package/dist/meeting-recorder.d.ts.map +1 -1
  138. package/dist/meeting-recorder.js +3 -3
  139. package/dist/node/analytics.js +2 -0
  140. package/dist/node/calendar.js +2 -0
  141. package/dist/node/database.js +2 -0
  142. package/dist/node/email.js +2 -0
  143. package/dist/node/embedding.js +2 -0
  144. package/dist/node/impls/elevenlabs-voice.js +102 -0
  145. package/dist/node/impls/fal-voice.js +112 -0
  146. package/dist/node/impls/fathom-meeting-recorder.js +287 -0
  147. package/dist/node/impls/fathom-meeting-recorder.mapper.js +105 -0
  148. package/dist/node/impls/fathom-meeting-recorder.types.js +0 -0
  149. package/dist/node/impls/fathom-meeting-recorder.utils.js +72 -0
  150. package/dist/node/impls/fathom-meeting-recorder.webhooks.js +29 -0
  151. package/dist/node/impls/fireflies-meeting-recorder.js +274 -0
  152. package/dist/node/impls/fireflies-meeting-recorder.queries.js +85 -0
  153. package/dist/node/impls/fireflies-meeting-recorder.types.js +0 -0
  154. package/dist/node/impls/fireflies-meeting-recorder.utils.js +42 -0
  155. package/dist/node/impls/gcs-storage.js +97 -0
  156. package/dist/node/impls/gmail-inbound.js +227 -0
  157. package/dist/node/impls/gmail-outbound.js +139 -0
  158. package/dist/node/impls/google-calendar.js +191 -0
  159. package/dist/node/impls/gradium-voice.js +90 -0
  160. package/dist/node/impls/granola-meeting-recorder.js +512 -0
  161. package/dist/node/impls/granola-meeting-recorder.mcp.js +278 -0
  162. package/dist/node/impls/granola-meeting-recorder.types.js +0 -0
  163. package/dist/node/impls/index.js +4658 -0
  164. package/dist/node/impls/jira.js +124 -0
  165. package/dist/node/impls/linear.js +83 -0
  166. package/dist/node/impls/mistral-embedding.js +43 -0
  167. package/dist/node/impls/mistral-llm.js +269 -0
  168. package/dist/node/impls/notion.js +160 -0
  169. package/dist/node/impls/posthog-reader.js +159 -0
  170. package/dist/node/impls/posthog-utils.js +38 -0
  171. package/dist/node/impls/posthog.js +322 -0
  172. package/dist/node/impls/postmark-email.js +60 -0
  173. package/dist/node/impls/powens-client.js +195 -0
  174. package/dist/node/impls/powens-openbanking.js +426 -0
  175. package/dist/node/impls/provider-factory.js +4080 -0
  176. package/dist/node/impls/qdrant-vector.js +78 -0
  177. package/dist/node/impls/stripe-payments.js +228 -0
  178. package/dist/node/impls/supabase-psql.js +150 -0
  179. package/dist/node/impls/supabase-vector.js +323 -0
  180. package/dist/node/impls/tldv-meeting-recorder.js +145 -0
  181. package/dist/node/impls/twilio-sms.js +65 -0
  182. package/dist/node/index.js +4699 -0
  183. package/dist/node/llm.js +2 -0
  184. package/dist/node/meeting-recorder.js +2 -0
  185. package/dist/node/openbanking.js +2 -0
  186. package/dist/node/payments.js +2 -0
  187. package/dist/node/project-management.js +2 -0
  188. package/dist/node/runtime.js +0 -0
  189. package/dist/node/secrets/provider.js +11 -0
  190. package/dist/node/sms.js +2 -0
  191. package/dist/node/storage.js +2 -0
  192. package/dist/node/vector-store.js +2 -0
  193. package/dist/node/voice.js +2 -0
  194. package/dist/openbanking.d.ts +1 -8
  195. package/dist/openbanking.d.ts.map +1 -1
  196. package/dist/openbanking.js +3 -3
  197. package/dist/payments.d.ts +1 -8
  198. package/dist/payments.d.ts.map +1 -1
  199. package/dist/payments.js +3 -3
  200. package/dist/project-management.d.ts +1 -8
  201. package/dist/project-management.d.ts.map +1 -1
  202. package/dist/project-management.js +3 -3
  203. package/dist/runtime.d.ts +2 -2
  204. package/dist/runtime.d.ts.map +1 -0
  205. package/dist/runtime.js +1 -0
  206. package/dist/secrets/provider.d.ts +3 -2
  207. package/dist/secrets/provider.d.ts.map +1 -0
  208. package/dist/secrets/provider.js +12 -3
  209. package/dist/sms.d.ts +1 -8
  210. package/dist/sms.d.ts.map +1 -1
  211. package/dist/sms.js +3 -3
  212. package/dist/storage.d.ts +1 -8
  213. package/dist/storage.d.ts.map +1 -1
  214. package/dist/storage.js +3 -3
  215. package/dist/vector-store.d.ts +1 -8
  216. package/dist/vector-store.d.ts.map +1 -1
  217. package/dist/vector-store.js +3 -3
  218. package/dist/voice.d.ts +1 -8
  219. package/dist/voice.d.ts.map +1 -1
  220. package/dist/voice.js +3 -3
  221. package/package.json +405 -114
  222. package/dist/_virtual/_rolldown/runtime.js +0 -36
  223. package/dist/impls/elevenlabs-voice.js.map +0 -1
  224. package/dist/impls/fal-voice.js.map +0 -1
  225. package/dist/impls/fathom-meeting-recorder.js.map +0 -1
  226. package/dist/impls/fathom-meeting-recorder.mapper.js.map +0 -1
  227. package/dist/impls/fathom-meeting-recorder.utils.js.map +0 -1
  228. package/dist/impls/fathom-meeting-recorder.webhooks.js.map +0 -1
  229. package/dist/impls/fireflies-meeting-recorder.js.map +0 -1
  230. package/dist/impls/fireflies-meeting-recorder.queries.js.map +0 -1
  231. package/dist/impls/fireflies-meeting-recorder.utils.js.map +0 -1
  232. package/dist/impls/gcs-storage.js.map +0 -1
  233. package/dist/impls/gmail-inbound.js.map +0 -1
  234. package/dist/impls/gmail-outbound.js.map +0 -1
  235. package/dist/impls/google-calendar.js.map +0 -1
  236. package/dist/impls/gradium-voice.js.map +0 -1
  237. package/dist/impls/granola-meeting-recorder.js.map +0 -1
  238. package/dist/impls/jira.js.map +0 -1
  239. package/dist/impls/linear.js.map +0 -1
  240. package/dist/impls/mistral-embedding.js.map +0 -1
  241. package/dist/impls/mistral-llm.js.map +0 -1
  242. package/dist/impls/notion.js.map +0 -1
  243. package/dist/impls/posthog-reader.js.map +0 -1
  244. package/dist/impls/posthog-utils.js.map +0 -1
  245. package/dist/impls/posthog.js.map +0 -1
  246. package/dist/impls/postmark-email.js.map +0 -1
  247. package/dist/impls/powens-client.js.map +0 -1
  248. package/dist/impls/powens-openbanking.js.map +0 -1
  249. package/dist/impls/provider-factory.js.map +0 -1
  250. package/dist/impls/qdrant-vector.js.map +0 -1
  251. package/dist/impls/stripe-payments.js.map +0 -1
  252. package/dist/impls/supabase-psql.js.map +0 -1
  253. package/dist/impls/supabase-vector.js.map +0 -1
  254. package/dist/impls/tldv-meeting-recorder.js.map +0 -1
  255. package/dist/impls/twilio-sms.js.map +0 -1
  256. package/dist/index.js.map +0 -1
@@ -1,219 +1,427 @@
1
- import { PowensClient, PowensClientError } from "./powens-client.js";
2
-
3
- //#region src/impls/powens-openbanking.ts
4
- var PowensOpenBankingProvider = class {
5
- client;
6
- logger;
7
- constructor(options) {
8
- this.client = new PowensClient(options);
9
- this.logger = options.logger;
10
- }
11
- async listAccounts(params) {
12
- if (!params.userId) throw new PowensClientError("Powens account listing requires the upstream userId mapped to Powens user UUID.", 400);
13
- const context = this.toContext(params.tenantId, params.connectionId);
14
- try {
15
- const response = await this.client.listAccounts({
16
- userUuid: params.userId,
17
- cursor: params.cursor,
18
- limit: params.pageSize,
19
- includeBalances: params.includeBalances,
20
- institutionUuid: params.institutionId
21
- });
22
- return {
23
- accounts: response.accounts.map((account) => this.mapAccount(account, context)),
24
- nextCursor: response.pagination?.nextCursor,
25
- hasMore: response.pagination?.hasMore
26
- };
27
- } catch (error) {
28
- this.handleError("listAccounts", error);
29
- }
30
- }
31
- async getAccountDetails(params) {
32
- const context = this.toContext(params.tenantId, params.connectionId);
33
- try {
34
- const account = await this.client.getAccount(params.accountId);
35
- return this.mapAccountDetails(account, context);
36
- } catch (error) {
37
- this.handleError("getAccountDetails", error);
38
- }
39
- }
40
- async listTransactions(params) {
41
- const context = this.toContext(params.tenantId, params.connectionId);
42
- try {
43
- const response = await this.client.listTransactions({
44
- accountUuid: params.accountId,
45
- cursor: params.cursor,
46
- limit: params.pageSize,
47
- from: params.from,
48
- to: params.to,
49
- includePending: params.includePending
50
- });
51
- return {
52
- transactions: response.transactions.map((transaction) => this.mapTransaction(transaction, context)),
53
- nextCursor: response.pagination?.nextCursor,
54
- hasMore: response.pagination?.hasMore
55
- };
56
- } catch (error) {
57
- this.handleError("listTransactions", error);
58
- }
59
- }
60
- async getBalances(params) {
61
- const context = this.toContext(params.tenantId, params.connectionId);
62
- try {
63
- return (await this.client.getBalances(params.accountId)).filter((balance) => params.balanceTypes?.length ? params.balanceTypes.includes(String(balance.type)) : true).map((balance) => this.mapBalance(balance, context));
64
- } catch (error) {
65
- this.handleError("getBalances", error);
66
- }
67
- }
68
- async getConnectionStatus(params) {
69
- try {
70
- const status = await this.client.getConnectionStatus(params.connectionId);
71
- return {
72
- connectionId: params.connectionId,
73
- tenantId: params.tenantId,
74
- status: this.mapConnectionStatus(status.status),
75
- lastCheckedAt: status.lastAttemptAt,
76
- errorCode: status.errorCode,
77
- errorMessage: status.errorMessage,
78
- details: status.metadata
79
- };
80
- } catch (error) {
81
- this.handleError("getConnectionStatus", error);
82
- }
83
- }
84
- mapAccount(account, context) {
85
- return {
86
- id: account.uuid,
87
- externalId: account.reference ?? account.uuid,
88
- tenantId: context.tenantId,
89
- connectionId: context.connectionId,
90
- userId: account.userUuid,
91
- displayName: account.name,
92
- institutionId: account.institution.id,
93
- institutionName: account.institution.name,
94
- institutionLogoUrl: account.institution.logoUrl,
95
- accountType: account.type ?? "unknown",
96
- iban: account.iban,
97
- bic: account.bic,
98
- currency: account.currency ?? "EUR",
99
- accountNumberMasked: account.metadata?.account_number_masked,
100
- ownership: this.mapOwnership(account.metadata?.ownership),
101
- status: this.mapAccountStatus(account.status),
102
- lastSyncedAt: account.metadata?.last_sync_at,
103
- metadata: account.metadata
104
- };
105
- }
106
- mapAccountDetails(account, context) {
107
- return {
108
- ...this.mapAccount(account, context),
109
- productCode: account.metadata?.product_code,
110
- openedAt: account.metadata?.opened_at,
111
- closedAt: account.metadata?.closed_at,
112
- availableBalance: account.availableBalance ?? void 0,
113
- currentBalance: account.balance ?? void 0,
114
- creditLimit: account.metadata?.credit_limit,
115
- customFields: account.metadata
116
- };
117
- }
118
- mapTransaction(transaction, context) {
119
- return {
120
- id: transaction.uuid,
121
- externalId: transaction.uuid,
122
- tenantId: context.tenantId,
123
- accountId: transaction.accountUuid,
124
- connectionId: context.connectionId,
125
- amount: transaction.amount,
126
- currency: transaction.currency,
127
- direction: transaction.direction === "credit" ? "credit" : "debit",
128
- description: transaction.description ?? transaction.rawLabel,
129
- bookingDate: transaction.bookingDate,
130
- valueDate: transaction.valueDate,
131
- postedAt: transaction.bookingDate,
132
- category: transaction.category,
133
- rawCategory: transaction.rawLabel,
134
- merchantName: transaction.merchantName,
135
- merchantCategoryCode: transaction.merchantCategoryCode,
136
- counterpartyName: transaction.counterpartyName,
137
- counterpartyAccount: transaction.counterpartyAccount,
138
- reference: transaction.metadata?.reference,
139
- status: this.mapTransactionStatus(transaction.status),
140
- metadata: transaction.metadata
141
- };
142
- }
143
- mapBalance(balance, context) {
144
- return {
145
- accountId: balance.accountUuid,
146
- connectionId: context.connectionId,
147
- tenantId: context.tenantId,
148
- type: balance.type ?? "current",
149
- currency: balance.currency ?? "EUR",
150
- amount: balance.amount,
151
- lastUpdatedAt: balance.updatedAt,
152
- metadata: balance.metadata
153
- };
154
- }
155
- toContext(tenantId, connectionId) {
156
- return {
157
- tenantId,
158
- connectionId
159
- };
160
- }
161
- mapOwnership(value) {
162
- switch (value?.toLowerCase()) {
163
- case "individual":
164
- case "personal": return "individual";
165
- case "joint": return "joint";
166
- case "business":
167
- case "corporate": return "business";
168
- default: return "unknown";
169
- }
170
- }
171
- mapAccountStatus(status) {
172
- switch (status?.toLowerCase()) {
173
- case "active":
174
- case "enabled": return "active";
175
- case "disabled":
176
- case "inactive": return "inactive";
177
- case "closed": return "closed";
178
- case "suspended": return "suspended";
179
- default: return "active";
180
- }
181
- }
182
- mapTransactionStatus(status) {
183
- switch (status?.toLowerCase()) {
184
- case "pending":
185
- case "authorised": return "pending";
186
- case "booked":
187
- case "posted": return "booked";
188
- case "cancelled":
189
- case "rejected": return "cancelled";
190
- default: return "booked";
191
- }
192
- }
193
- mapConnectionStatus(status) {
194
- switch (status) {
195
- case "healthy": return "healthy";
196
- case "pending": return "degraded";
197
- case "error": return "error";
198
- case "revoked": return "disconnected";
199
- default: return "degraded";
200
- }
201
- }
202
- handleError(operation, error) {
203
- if (error instanceof PowensClientError) {
204
- this.logger?.error?.(`[PowensOpenBankingProvider] ${operation} failed`, {
205
- status: error.status,
206
- code: error.code,
207
- requestId: error.requestId,
208
- message: error.message
209
- });
210
- throw error;
211
- }
212
- this.logger?.error?.(`[PowensOpenBankingProvider] ${operation} failed with unexpected error`, error);
213
- throw error instanceof Error ? error : /* @__PURE__ */ new Error(`Powens operation "${operation}" failed`);
214
- }
1
+ // @bun
2
+ // src/impls/powens-client.ts
3
+ import { URL } from "url";
4
+ var POWENS_BASE_URL = {
5
+ sandbox: "https://api-sandbox.powens.com/v2",
6
+ production: "https://api.powens.com/v2"
215
7
  };
216
8
 
217
- //#endregion
218
- export { PowensOpenBankingProvider };
219
- //# sourceMappingURL=powens-openbanking.js.map
9
+ class PowensClientError extends Error {
10
+ status;
11
+ code;
12
+ requestId;
13
+ response;
14
+ constructor(message, status, code, requestId, response) {
15
+ super(message);
16
+ this.name = "PowensClientError";
17
+ this.status = status;
18
+ this.code = code;
19
+ this.requestId = requestId;
20
+ this.response = response;
21
+ }
22
+ }
23
+
24
+ class PowensClient {
25
+ clientId;
26
+ clientSecret;
27
+ apiKey;
28
+ fetchImpl;
29
+ logger;
30
+ defaultTimeoutMs;
31
+ token;
32
+ baseUrl;
33
+ constructor(options) {
34
+ this.clientId = options.clientId;
35
+ this.clientSecret = options.clientSecret;
36
+ this.apiKey = options.apiKey;
37
+ this.fetchImpl = options.fetchImpl ?? fetch;
38
+ this.logger = options.logger;
39
+ this.defaultTimeoutMs = options.defaultTimeoutMs ?? 15000;
40
+ this.baseUrl = options.baseUrl ?? POWENS_BASE_URL[options.environment] ?? POWENS_BASE_URL.production;
41
+ }
42
+ async listAccounts(params) {
43
+ const searchParams = {
44
+ cursor: params.cursor,
45
+ limit: params.limit,
46
+ include_balances: params.includeBalances,
47
+ institution_uuid: params.institutionUuid
48
+ };
49
+ const response = await this.request({
50
+ method: "GET",
51
+ path: `/users/${encodeURIComponent(params.userUuid)}/accounts`,
52
+ searchParams
53
+ });
54
+ return response;
55
+ }
56
+ async getAccount(accountUuid) {
57
+ return this.request({
58
+ method: "GET",
59
+ path: `/accounts/${encodeURIComponent(accountUuid)}`
60
+ });
61
+ }
62
+ async listTransactions(params) {
63
+ const searchParams = {
64
+ cursor: params.cursor,
65
+ limit: params.limit,
66
+ from: params.from,
67
+ to: params.to,
68
+ include_pending: params.includePending
69
+ };
70
+ return this.request({
71
+ method: "GET",
72
+ path: `/accounts/${encodeURIComponent(params.accountUuid)}/transactions`,
73
+ searchParams
74
+ });
75
+ }
76
+ async getBalances(accountUuid) {
77
+ return this.request({
78
+ method: "GET",
79
+ path: `/accounts/${encodeURIComponent(accountUuid)}/balances`
80
+ });
81
+ }
82
+ async getConnectionStatus(connectionUuid) {
83
+ return this.request({
84
+ method: "GET",
85
+ path: `/connections/${encodeURIComponent(connectionUuid)}`
86
+ });
87
+ }
88
+ async request(options) {
89
+ const url = new URL(options.path, this.baseUrl);
90
+ if (options.searchParams) {
91
+ for (const [key, value] of Object.entries(options.searchParams)) {
92
+ if (value === undefined || value === null)
93
+ continue;
94
+ url.searchParams.set(key, String(value));
95
+ }
96
+ }
97
+ const headers = {
98
+ Accept: "application/json",
99
+ "Content-Type": "application/json",
100
+ ...options.headers
101
+ };
102
+ if (this.apiKey) {
103
+ headers["x-api-key"] = this.apiKey;
104
+ }
105
+ if (!options.skipAuth) {
106
+ const token = await this.ensureAccessToken();
107
+ headers.Authorization = `Bearer ${token}`;
108
+ }
109
+ const controller = new AbortController;
110
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? this.defaultTimeoutMs);
111
+ try {
112
+ const response = await this.fetchImpl(url, {
113
+ method: options.method,
114
+ headers,
115
+ body: options.body ? JSON.stringify(options.body) : undefined,
116
+ signal: controller.signal
117
+ });
118
+ const requestId = response.headers.get("x-request-id") ?? undefined;
119
+ if (!response.ok) {
120
+ let errorBody;
121
+ try {
122
+ errorBody = await response.json();
123
+ } catch {}
124
+ const errorObject = typeof errorBody === "object" && errorBody !== null ? errorBody : undefined;
125
+ const message = typeof errorObject?.message === "string" ? errorObject.message : `Powens API request failed with status ${response.status}`;
126
+ const code = typeof errorObject?.code === "string" ? errorObject.code : undefined;
127
+ throw new PowensClientError(message, response.status, code, requestId, errorBody);
128
+ }
129
+ if (response.status === 204) {
130
+ return;
131
+ }
132
+ try {
133
+ return await response.json();
134
+ } catch (error) {
135
+ this.logger?.error?.("[PowensClient] Failed to parse JSON response", error);
136
+ throw new PowensClientError("Failed to parse Powens response payload as JSON", response.status, undefined, requestId);
137
+ }
138
+ } catch (error) {
139
+ if (error instanceof PowensClientError) {
140
+ throw error;
141
+ }
142
+ if (error.name === "AbortError") {
143
+ throw new PowensClientError(`Powens API request timed out after ${options.timeoutMs ?? this.defaultTimeoutMs}ms`, 408);
144
+ }
145
+ this.logger?.error?.("[PowensClient] Request failed", error);
146
+ throw new PowensClientError(error.message ?? "Powens API request failed", 500);
147
+ } finally {
148
+ clearTimeout(timeout);
149
+ }
150
+ }
151
+ async ensureAccessToken() {
152
+ if (this.token && Date.now() < this.token.expiresAt - 5000) {
153
+ return this.token.accessToken;
154
+ }
155
+ this.token = await this.fetchAccessToken();
156
+ return this.token.accessToken;
157
+ }
158
+ async fetchAccessToken() {
159
+ const url = new URL("/oauth/token", this.baseUrl);
160
+ const basicAuth = Buffer.from(`${this.clientId}:${this.clientSecret}`, "utf-8").toString("base64");
161
+ const response = await this.fetchImpl(url, {
162
+ method: "POST",
163
+ headers: {
164
+ Authorization: `Basic ${basicAuth}`,
165
+ "Content-Type": "application/x-www-form-urlencoded",
166
+ Accept: "application/json"
167
+ },
168
+ body: new URLSearchParams({
169
+ grant_type: "client_credentials"
170
+ }).toString()
171
+ });
172
+ if (!response.ok) {
173
+ let errorBody;
174
+ try {
175
+ errorBody = await response.json();
176
+ } catch {}
177
+ const errorObject = typeof errorBody === "object" && errorBody !== null ? errorBody : undefined;
178
+ const message = typeof errorObject?.error_description === "string" ? errorObject.error_description : "Failed to obtain Powens access token";
179
+ throw new PowensClientError(message, response.status, undefined, undefined, errorBody);
180
+ }
181
+ const payload = await response.json();
182
+ const expiresAt = Date.now() + payload.expires_in * 1000;
183
+ this.logger?.debug?.("[PowensClient] Received access token", {
184
+ expiresIn: payload.expires_in
185
+ });
186
+ return {
187
+ accessToken: payload.access_token,
188
+ expiresAt,
189
+ scope: payload.scope
190
+ };
191
+ }
192
+ }
193
+
194
+ // src/impls/powens-openbanking.ts
195
+ class PowensOpenBankingProvider {
196
+ client;
197
+ logger;
198
+ constructor(options) {
199
+ this.client = new PowensClient(options);
200
+ this.logger = options.logger;
201
+ }
202
+ async listAccounts(params) {
203
+ if (!params.userId) {
204
+ throw new PowensClientError("Powens account listing requires the upstream userId mapped to Powens user UUID.", 400);
205
+ }
206
+ const context = this.toContext(params.tenantId, params.connectionId);
207
+ try {
208
+ const response = await this.client.listAccounts({
209
+ userUuid: params.userId,
210
+ cursor: params.cursor,
211
+ limit: params.pageSize,
212
+ includeBalances: params.includeBalances,
213
+ institutionUuid: params.institutionId
214
+ });
215
+ return {
216
+ accounts: response.accounts.map((account) => this.mapAccount(account, context)),
217
+ nextCursor: response.pagination?.nextCursor,
218
+ hasMore: response.pagination?.hasMore
219
+ };
220
+ } catch (error) {
221
+ this.handleError("listAccounts", error);
222
+ }
223
+ }
224
+ async getAccountDetails(params) {
225
+ const context = this.toContext(params.tenantId, params.connectionId);
226
+ try {
227
+ const account = await this.client.getAccount(params.accountId);
228
+ return this.mapAccountDetails(account, context);
229
+ } catch (error) {
230
+ this.handleError("getAccountDetails", error);
231
+ }
232
+ }
233
+ async listTransactions(params) {
234
+ const context = this.toContext(params.tenantId, params.connectionId);
235
+ try {
236
+ const response = await this.client.listTransactions({
237
+ accountUuid: params.accountId,
238
+ cursor: params.cursor,
239
+ limit: params.pageSize,
240
+ from: params.from,
241
+ to: params.to,
242
+ includePending: params.includePending
243
+ });
244
+ return {
245
+ transactions: response.transactions.map((transaction) => this.mapTransaction(transaction, context)),
246
+ nextCursor: response.pagination?.nextCursor,
247
+ hasMore: response.pagination?.hasMore
248
+ };
249
+ } catch (error) {
250
+ this.handleError("listTransactions", error);
251
+ }
252
+ }
253
+ async getBalances(params) {
254
+ const context = this.toContext(params.tenantId, params.connectionId);
255
+ try {
256
+ const balances = await this.client.getBalances(params.accountId);
257
+ return balances.filter((balance) => params.balanceTypes?.length ? params.balanceTypes.includes(String(balance.type)) : true).map((balance) => this.mapBalance(balance, context));
258
+ } catch (error) {
259
+ this.handleError("getBalances", error);
260
+ }
261
+ }
262
+ async getConnectionStatus(params) {
263
+ try {
264
+ const status = await this.client.getConnectionStatus(params.connectionId);
265
+ return {
266
+ connectionId: params.connectionId,
267
+ tenantId: params.tenantId,
268
+ status: this.mapConnectionStatus(status.status),
269
+ lastCheckedAt: status.lastAttemptAt,
270
+ errorCode: status.errorCode,
271
+ errorMessage: status.errorMessage,
272
+ details: status.metadata
273
+ };
274
+ } catch (error) {
275
+ this.handleError("getConnectionStatus", error);
276
+ }
277
+ }
278
+ mapAccount(account, context) {
279
+ return {
280
+ id: account.uuid,
281
+ externalId: account.reference ?? account.uuid,
282
+ tenantId: context.tenantId,
283
+ connectionId: context.connectionId,
284
+ userId: account.userUuid,
285
+ displayName: account.name,
286
+ institutionId: account.institution.id,
287
+ institutionName: account.institution.name,
288
+ institutionLogoUrl: account.institution.logoUrl,
289
+ accountType: account.type ?? "unknown",
290
+ iban: account.iban,
291
+ bic: account.bic,
292
+ currency: account.currency ?? "EUR",
293
+ accountNumberMasked: account.metadata?.account_number_masked,
294
+ ownership: this.mapOwnership(account.metadata?.ownership),
295
+ status: this.mapAccountStatus(account.status),
296
+ lastSyncedAt: account.metadata?.last_sync_at,
297
+ metadata: account.metadata
298
+ };
299
+ }
300
+ mapAccountDetails(account, context) {
301
+ return {
302
+ ...this.mapAccount(account, context),
303
+ productCode: account.metadata?.product_code,
304
+ openedAt: account.metadata?.opened_at,
305
+ closedAt: account.metadata?.closed_at,
306
+ availableBalance: account.availableBalance ?? undefined,
307
+ currentBalance: account.balance ?? undefined,
308
+ creditLimit: account.metadata?.credit_limit,
309
+ customFields: account.metadata
310
+ };
311
+ }
312
+ mapTransaction(transaction, context) {
313
+ return {
314
+ id: transaction.uuid,
315
+ externalId: transaction.uuid,
316
+ tenantId: context.tenantId,
317
+ accountId: transaction.accountUuid,
318
+ connectionId: context.connectionId,
319
+ amount: transaction.amount,
320
+ currency: transaction.currency,
321
+ direction: transaction.direction === "credit" ? "credit" : "debit",
322
+ description: transaction.description ?? transaction.rawLabel,
323
+ bookingDate: transaction.bookingDate,
324
+ valueDate: transaction.valueDate,
325
+ postedAt: transaction.bookingDate,
326
+ category: transaction.category,
327
+ rawCategory: transaction.rawLabel,
328
+ merchantName: transaction.merchantName,
329
+ merchantCategoryCode: transaction.merchantCategoryCode,
330
+ counterpartyName: transaction.counterpartyName,
331
+ counterpartyAccount: transaction.counterpartyAccount,
332
+ reference: transaction.metadata?.reference,
333
+ status: this.mapTransactionStatus(transaction.status),
334
+ metadata: transaction.metadata
335
+ };
336
+ }
337
+ mapBalance(balance, context) {
338
+ return {
339
+ accountId: balance.accountUuid,
340
+ connectionId: context.connectionId,
341
+ tenantId: context.tenantId,
342
+ type: balance.type ?? "current",
343
+ currency: balance.currency ?? "EUR",
344
+ amount: balance.amount,
345
+ lastUpdatedAt: balance.updatedAt,
346
+ metadata: balance.metadata
347
+ };
348
+ }
349
+ toContext(tenantId, connectionId) {
350
+ return { tenantId, connectionId };
351
+ }
352
+ mapOwnership(value) {
353
+ switch (value?.toLowerCase()) {
354
+ case "individual":
355
+ case "personal":
356
+ return "individual";
357
+ case "joint":
358
+ return "joint";
359
+ case "business":
360
+ case "corporate":
361
+ return "business";
362
+ default:
363
+ return "unknown";
364
+ }
365
+ }
366
+ mapAccountStatus(status) {
367
+ switch (status?.toLowerCase()) {
368
+ case "active":
369
+ case "enabled":
370
+ return "active";
371
+ case "disabled":
372
+ case "inactive":
373
+ return "inactive";
374
+ case "closed":
375
+ return "closed";
376
+ case "suspended":
377
+ return "suspended";
378
+ default:
379
+ return "active";
380
+ }
381
+ }
382
+ mapTransactionStatus(status) {
383
+ switch (status?.toLowerCase()) {
384
+ case "pending":
385
+ case "authorised":
386
+ return "pending";
387
+ case "booked":
388
+ case "posted":
389
+ return "booked";
390
+ case "cancelled":
391
+ case "rejected":
392
+ return "cancelled";
393
+ default:
394
+ return "booked";
395
+ }
396
+ }
397
+ mapConnectionStatus(status) {
398
+ switch (status) {
399
+ case "healthy":
400
+ return "healthy";
401
+ case "pending":
402
+ return "degraded";
403
+ case "error":
404
+ return "error";
405
+ case "revoked":
406
+ return "disconnected";
407
+ default:
408
+ return "degraded";
409
+ }
410
+ }
411
+ handleError(operation, error) {
412
+ if (error instanceof PowensClientError) {
413
+ this.logger?.error?.(`[PowensOpenBankingProvider] ${operation} failed`, {
414
+ status: error.status,
415
+ code: error.code,
416
+ requestId: error.requestId,
417
+ message: error.message
418
+ });
419
+ throw error;
420
+ }
421
+ this.logger?.error?.(`[PowensOpenBankingProvider] ${operation} failed with unexpected error`, error);
422
+ throw error instanceof Error ? error : new Error(`Powens operation "${operation}" failed`);
423
+ }
424
+ }
425
+ export {
426
+ PowensOpenBankingProvider
427
+ };