@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.
- package/dist/analytics.d.ts +1 -8
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +3 -3
- package/dist/calendar.d.ts +1 -8
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +3 -3
- package/dist/database.d.ts +1 -8
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +3 -3
- package/dist/email.d.ts +1 -8
- package/dist/email.d.ts.map +1 -1
- package/dist/email.js +3 -3
- package/dist/embedding.d.ts +1 -8
- package/dist/embedding.d.ts.map +1 -1
- package/dist/embedding.js +3 -3
- package/dist/impls/elevenlabs-voice.d.ts +14 -18
- package/dist/impls/elevenlabs-voice.d.ts.map +1 -1
- package/dist/impls/elevenlabs-voice.js +98 -88
- package/dist/impls/fal-voice.d.ts +22 -26
- package/dist/impls/fal-voice.d.ts.map +1 -1
- package/dist/impls/fal-voice.js +103 -78
- package/dist/impls/fathom-meeting-recorder.d.ts +35 -39
- package/dist/impls/fathom-meeting-recorder.d.ts.map +1 -1
- package/dist/impls/fathom-meeting-recorder.js +285 -142
- package/dist/impls/fathom-meeting-recorder.mapper.d.ts +4 -8
- package/dist/impls/fathom-meeting-recorder.mapper.d.ts.map +1 -1
- package/dist/impls/fathom-meeting-recorder.mapper.js +102 -38
- package/dist/impls/fathom-meeting-recorder.types.d.ts +16 -20
- package/dist/impls/fathom-meeting-recorder.types.d.ts.map +1 -1
- package/dist/impls/fathom-meeting-recorder.types.js +1 -0
- package/dist/impls/fathom-meeting-recorder.utils.d.ts +10 -14
- package/dist/impls/fathom-meeting-recorder.utils.d.ts.map +1 -1
- package/dist/impls/fathom-meeting-recorder.utils.js +58 -41
- package/dist/impls/fathom-meeting-recorder.webhooks.d.ts +3 -7
- package/dist/impls/fathom-meeting-recorder.webhooks.d.ts.map +1 -1
- package/dist/impls/fathom-meeting-recorder.webhooks.js +25 -20
- package/dist/impls/fireflies-meeting-recorder.d.ts +21 -25
- package/dist/impls/fireflies-meeting-recorder.d.ts.map +1 -1
- package/dist/impls/fireflies-meeting-recorder.js +272 -149
- package/dist/impls/fireflies-meeting-recorder.queries.d.ts +3 -6
- package/dist/impls/fireflies-meeting-recorder.queries.d.ts.map +1 -1
- package/dist/impls/fireflies-meeting-recorder.queries.js +10 -8
- package/dist/impls/fireflies-meeting-recorder.types.d.ts +26 -29
- package/dist/impls/fireflies-meeting-recorder.types.d.ts.map +1 -1
- package/dist/impls/fireflies-meeting-recorder.types.js +1 -0
- package/dist/impls/fireflies-meeting-recorder.utils.d.ts +4 -7
- package/dist/impls/fireflies-meeting-recorder.utils.d.ts.map +1 -1
- package/dist/impls/fireflies-meeting-recorder.utils.js +34 -27
- package/dist/impls/gcs-storage.d.ts +18 -22
- package/dist/impls/gcs-storage.d.ts.map +1 -1
- package/dist/impls/gcs-storage.js +92 -84
- package/dist/impls/gmail-inbound.d.ts +20 -24
- package/dist/impls/gmail-inbound.d.ts.map +1 -1
- package/dist/impls/gmail-inbound.js +212 -185
- package/dist/impls/gmail-outbound.d.ts +12 -16
- package/dist/impls/gmail-outbound.d.ts.map +1 -1
- package/dist/impls/gmail-outbound.js +126 -92
- package/dist/impls/google-calendar.d.ts +17 -21
- package/dist/impls/google-calendar.d.ts.map +1 -1
- package/dist/impls/google-calendar.js +182 -145
- package/dist/impls/gradium-voice.d.ts +20 -22
- package/dist/impls/gradium-voice.d.ts.map +1 -1
- package/dist/impls/gradium-voice.js +85 -74
- package/dist/impls/granola-meeting-recorder.d.ts +31 -24
- package/dist/impls/granola-meeting-recorder.d.ts.map +1 -1
- package/dist/impls/granola-meeting-recorder.js +511 -143
- package/dist/impls/granola-meeting-recorder.mcp.d.ts +25 -0
- package/dist/impls/granola-meeting-recorder.mcp.d.ts.map +1 -0
- package/dist/impls/granola-meeting-recorder.mcp.js +279 -0
- package/dist/impls/granola-meeting-recorder.types.d.ts +60 -49
- package/dist/impls/granola-meeting-recorder.types.d.ts.map +1 -1
- package/dist/impls/granola-meeting-recorder.types.js +1 -0
- package/dist/impls/index.d.ts +28 -28
- package/dist/impls/index.d.ts.map +1 -0
- package/dist/impls/index.js +4659 -29
- package/dist/impls/jira.d.ts +18 -22
- package/dist/impls/jira.d.ts.map +1 -1
- package/dist/impls/jira.js +112 -101
- package/dist/impls/linear.d.ts +17 -21
- package/dist/impls/linear.d.ts.map +1 -1
- package/dist/impls/linear.js +78 -69
- package/dist/impls/mistral-embedding.d.ts +17 -21
- package/dist/impls/mistral-embedding.d.ts.map +1 -1
- package/dist/impls/mistral-embedding.js +41 -39
- package/dist/impls/mistral-llm.d.ts +25 -29
- package/dist/impls/mistral-llm.d.ts.map +1 -1
- package/dist/impls/mistral-llm.js +266 -244
- package/dist/impls/notion.d.ts +20 -24
- package/dist/impls/notion.d.ts.map +1 -1
- package/dist/impls/notion.js +145 -110
- package/dist/impls/posthog-reader.d.ts +18 -22
- package/dist/impls/posthog-reader.d.ts.map +1 -1
- package/dist/impls/posthog-reader.js +148 -129
- package/dist/impls/posthog-utils.d.ts +4 -7
- package/dist/impls/posthog-utils.d.ts.map +1 -1
- package/dist/impls/posthog-utils.js +31 -22
- package/dist/impls/posthog.d.ts +33 -37
- package/dist/impls/posthog.d.ts.map +1 -1
- package/dist/impls/posthog.js +320 -119
- package/dist/impls/postmark-email.d.ts +13 -17
- package/dist/impls/postmark-email.d.ts.map +1 -1
- package/dist/impls/postmark-email.js +55 -50
- package/dist/impls/powens-client.d.ts +111 -114
- package/dist/impls/powens-client.d.ts.map +1 -1
- package/dist/impls/powens-client.js +194 -170
- package/dist/impls/powens-openbanking.d.ts +22 -26
- package/dist/impls/powens-openbanking.d.ts.map +1 -1
- package/dist/impls/powens-openbanking.js +425 -217
- package/dist/impls/provider-factory.d.ts +29 -33
- package/dist/impls/provider-factory.d.ts.map +1 -1
- package/dist/impls/provider-factory.js +4072 -275
- package/dist/impls/qdrant-vector.d.ts +18 -22
- package/dist/impls/qdrant-vector.d.ts.map +1 -1
- package/dist/impls/qdrant-vector.js +76 -69
- package/dist/impls/stripe-payments.d.ts +22 -26
- package/dist/impls/stripe-payments.d.ts.map +1 -1
- package/dist/impls/stripe-payments.js +219 -193
- package/dist/impls/supabase-psql.d.ts +21 -25
- package/dist/impls/supabase-psql.d.ts.map +1 -1
- package/dist/impls/supabase-psql.js +138 -98
- package/dist/impls/supabase-vector.d.ts +29 -33
- package/dist/impls/supabase-vector.d.ts.map +1 -1
- package/dist/impls/supabase-vector.js +278 -103
- package/dist/impls/tldv-meeting-recorder.d.ts +18 -22
- package/dist/impls/tldv-meeting-recorder.d.ts.map +1 -1
- package/dist/impls/tldv-meeting-recorder.js +142 -127
- package/dist/impls/twilio-sms.d.ts +14 -17
- package/dist/impls/twilio-sms.d.ts.map +1 -1
- package/dist/impls/twilio-sms.js +62 -55
- package/dist/index.d.ts +15 -64
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4700 -107
- package/dist/llm.d.ts +1 -8
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +3 -3
- package/dist/meeting-recorder.d.ts +1 -8
- package/dist/meeting-recorder.d.ts.map +1 -1
- package/dist/meeting-recorder.js +3 -3
- package/dist/node/analytics.js +2 -0
- package/dist/node/calendar.js +2 -0
- package/dist/node/database.js +2 -0
- package/dist/node/email.js +2 -0
- package/dist/node/embedding.js +2 -0
- package/dist/node/impls/elevenlabs-voice.js +102 -0
- package/dist/node/impls/fal-voice.js +112 -0
- package/dist/node/impls/fathom-meeting-recorder.js +287 -0
- package/dist/node/impls/fathom-meeting-recorder.mapper.js +105 -0
- package/dist/node/impls/fathom-meeting-recorder.types.js +0 -0
- package/dist/node/impls/fathom-meeting-recorder.utils.js +72 -0
- package/dist/node/impls/fathom-meeting-recorder.webhooks.js +29 -0
- package/dist/node/impls/fireflies-meeting-recorder.js +274 -0
- package/dist/node/impls/fireflies-meeting-recorder.queries.js +85 -0
- package/dist/node/impls/fireflies-meeting-recorder.types.js +0 -0
- package/dist/node/impls/fireflies-meeting-recorder.utils.js +42 -0
- package/dist/node/impls/gcs-storage.js +97 -0
- package/dist/node/impls/gmail-inbound.js +227 -0
- package/dist/node/impls/gmail-outbound.js +139 -0
- package/dist/node/impls/google-calendar.js +191 -0
- package/dist/node/impls/gradium-voice.js +90 -0
- package/dist/node/impls/granola-meeting-recorder.js +512 -0
- package/dist/node/impls/granola-meeting-recorder.mcp.js +278 -0
- package/dist/node/impls/granola-meeting-recorder.types.js +0 -0
- package/dist/node/impls/index.js +4658 -0
- package/dist/node/impls/jira.js +124 -0
- package/dist/node/impls/linear.js +83 -0
- package/dist/node/impls/mistral-embedding.js +43 -0
- package/dist/node/impls/mistral-llm.js +269 -0
- package/dist/node/impls/notion.js +160 -0
- package/dist/node/impls/posthog-reader.js +159 -0
- package/dist/node/impls/posthog-utils.js +38 -0
- package/dist/node/impls/posthog.js +322 -0
- package/dist/node/impls/postmark-email.js +60 -0
- package/dist/node/impls/powens-client.js +195 -0
- package/dist/node/impls/powens-openbanking.js +426 -0
- package/dist/node/impls/provider-factory.js +4080 -0
- package/dist/node/impls/qdrant-vector.js +78 -0
- package/dist/node/impls/stripe-payments.js +228 -0
- package/dist/node/impls/supabase-psql.js +150 -0
- package/dist/node/impls/supabase-vector.js +323 -0
- package/dist/node/impls/tldv-meeting-recorder.js +145 -0
- package/dist/node/impls/twilio-sms.js +65 -0
- package/dist/node/index.js +4699 -0
- package/dist/node/llm.js +2 -0
- package/dist/node/meeting-recorder.js +2 -0
- package/dist/node/openbanking.js +2 -0
- package/dist/node/payments.js +2 -0
- package/dist/node/project-management.js +2 -0
- package/dist/node/runtime.js +0 -0
- package/dist/node/secrets/provider.js +11 -0
- package/dist/node/sms.js +2 -0
- package/dist/node/storage.js +2 -0
- package/dist/node/vector-store.js +2 -0
- package/dist/node/voice.js +2 -0
- package/dist/openbanking.d.ts +1 -8
- package/dist/openbanking.d.ts.map +1 -1
- package/dist/openbanking.js +3 -3
- package/dist/payments.d.ts +1 -8
- package/dist/payments.d.ts.map +1 -1
- package/dist/payments.js +3 -3
- package/dist/project-management.d.ts +1 -8
- package/dist/project-management.d.ts.map +1 -1
- package/dist/project-management.js +3 -3
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/secrets/provider.d.ts +3 -2
- package/dist/secrets/provider.d.ts.map +1 -0
- package/dist/secrets/provider.js +12 -3
- package/dist/sms.d.ts +1 -8
- package/dist/sms.d.ts.map +1 -1
- package/dist/sms.js +3 -3
- package/dist/storage.d.ts +1 -8
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +3 -3
- package/dist/vector-store.d.ts +1 -8
- package/dist/vector-store.d.ts.map +1 -1
- package/dist/vector-store.js +3 -3
- package/dist/voice.d.ts +1 -8
- package/dist/voice.d.ts.map +1 -1
- package/dist/voice.js +3 -3
- package/package.json +405 -114
- package/dist/_virtual/_rolldown/runtime.js +0 -36
- package/dist/impls/elevenlabs-voice.js.map +0 -1
- package/dist/impls/fal-voice.js.map +0 -1
- package/dist/impls/fathom-meeting-recorder.js.map +0 -1
- package/dist/impls/fathom-meeting-recorder.mapper.js.map +0 -1
- package/dist/impls/fathom-meeting-recorder.utils.js.map +0 -1
- package/dist/impls/fathom-meeting-recorder.webhooks.js.map +0 -1
- package/dist/impls/fireflies-meeting-recorder.js.map +0 -1
- package/dist/impls/fireflies-meeting-recorder.queries.js.map +0 -1
- package/dist/impls/fireflies-meeting-recorder.utils.js.map +0 -1
- package/dist/impls/gcs-storage.js.map +0 -1
- package/dist/impls/gmail-inbound.js.map +0 -1
- package/dist/impls/gmail-outbound.js.map +0 -1
- package/dist/impls/google-calendar.js.map +0 -1
- package/dist/impls/gradium-voice.js.map +0 -1
- package/dist/impls/granola-meeting-recorder.js.map +0 -1
- package/dist/impls/jira.js.map +0 -1
- package/dist/impls/linear.js.map +0 -1
- package/dist/impls/mistral-embedding.js.map +0 -1
- package/dist/impls/mistral-llm.js.map +0 -1
- package/dist/impls/notion.js.map +0 -1
- package/dist/impls/posthog-reader.js.map +0 -1
- package/dist/impls/posthog-utils.js.map +0 -1
- package/dist/impls/posthog.js.map +0 -1
- package/dist/impls/postmark-email.js.map +0 -1
- package/dist/impls/powens-client.js.map +0 -1
- package/dist/impls/powens-openbanking.js.map +0 -1
- package/dist/impls/provider-factory.js.map +0 -1
- package/dist/impls/qdrant-vector.js.map +0 -1
- package/dist/impls/stripe-payments.js.map +0 -1
- package/dist/impls/supabase-psql.js.map +0 -1
- package/dist/impls/supabase-vector.js.map +0 -1
- package/dist/impls/tldv-meeting-recorder.js.map +0 -1
- package/dist/impls/twilio-sms.js.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -1,219 +1,427 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
+
};
|