@xenterprises/fastify-xplaid 1.0.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/.gitlab-ci.yml ADDED
@@ -0,0 +1,45 @@
1
+ # ============================================================================
2
+ # GitLab CI/CD Pipeline - xPlaid
3
+ # ============================================================================
4
+ # Runs tests on merge requests and commits to main/master
5
+
6
+ stages:
7
+ - test
8
+
9
+ variables:
10
+ NODE_ENV: test
11
+
12
+ # ============================================================================
13
+ # Shared Configuration
14
+ # ============================================================================
15
+ .shared_rules: &shared_rules
16
+ rules:
17
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
18
+ - if: '$CI_COMMIT_BRANCH == "main"'
19
+ - if: '$CI_COMMIT_BRANCH == "master"'
20
+ - if: '$CI_COMMIT_TAG'
21
+
22
+ # ============================================================================
23
+ # STAGE: TEST
24
+ # ============================================================================
25
+ test:
26
+ stage: test
27
+ image: node:20-alpine
28
+ <<: *shared_rules
29
+
30
+ cache:
31
+ key: ${CI_COMMIT_REF_SLUG}
32
+ paths:
33
+ - node_modules/
34
+
35
+ before_script:
36
+ - npm ci
37
+
38
+ script:
39
+ - echo "Running xPlaid tests..."
40
+ - npm test
41
+ - npm audit --audit-level=high || true
42
+
43
+ retry:
44
+ max: 2
45
+ when: runner_system_failure
package/README.md ADDED
@@ -0,0 +1,393 @@
1
+ # xPlaid
2
+
3
+ Fastify plugin for Plaid financial data integration - bank account linking, transactions, identity verification, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install xplaid plaid
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```javascript
14
+ import Fastify from "fastify";
15
+ import xPlaid from "xplaid";
16
+
17
+ const fastify = Fastify();
18
+
19
+ await fastify.register(xPlaid, {
20
+ clientId: process.env.PLAID_CLIENT_ID,
21
+ secret: process.env.PLAID_SECRET,
22
+ environment: "sandbox", // 'sandbox' | 'development' | 'production'
23
+ });
24
+
25
+ // The plugin is now available at fastify.xplaid
26
+ ```
27
+
28
+ ## Configuration Options
29
+
30
+ | Option | Type | Required | Default | Description |
31
+ |--------|------|----------|---------|-------------|
32
+ | `clientId` | string | Yes | - | Your Plaid client ID |
33
+ | `secret` | string | Yes | - | Your Plaid secret |
34
+ | `environment` | string | No | `'sandbox'` | Plaid environment: `'sandbox'`, `'development'`, or `'production'` |
35
+ | `active` | boolean | No | `true` | Enable/disable the plugin |
36
+
37
+ ## Link Flow
38
+
39
+ The Plaid Link flow is the primary way users connect their bank accounts:
40
+
41
+ ### 1. Create a Link Token
42
+
43
+ ```javascript
44
+ // Create a link token for the frontend
45
+ const linkToken = await fastify.xplaid.link.createToken({
46
+ userId: "user_123",
47
+ clientName: "My App",
48
+ products: ["transactions", "auth"],
49
+ countryCodes: ["US"],
50
+ language: "en",
51
+ // Optional: webhook for real-time updates
52
+ webhook: "https://myapp.com/webhooks/plaid",
53
+ // Optional: redirect URI for OAuth flows
54
+ redirectUri: "https://myapp.com/oauth-callback",
55
+ });
56
+
57
+ // Return linkToken.link_token to your frontend
58
+ ```
59
+
60
+ ### 2. Exchange Public Token
61
+
62
+ After the user completes Plaid Link, exchange the public token for an access token:
63
+
64
+ ```javascript
65
+ // Exchange the public token from Plaid Link
66
+ const result = await fastify.xplaid.link.exchangePublicToken("public-token-from-link");
67
+
68
+ // Store these securely
69
+ const accessToken = result.access_token;
70
+ const itemId = result.item_id;
71
+ ```
72
+
73
+ ### 3. Get Link Token Info
74
+
75
+ ```javascript
76
+ const tokenInfo = await fastify.xplaid.link.getToken("link-token-id");
77
+ ```
78
+
79
+ ## Accounts
80
+
81
+ ```javascript
82
+ // Get all accounts for an item
83
+ const accounts = await fastify.xplaid.accounts.get(accessToken);
84
+
85
+ // Get real-time balance
86
+ const balance = await fastify.xplaid.accounts.getBalance(accessToken, {
87
+ accountIds: ["account_id_1", "account_id_2"], // Optional: filter by accounts
88
+ });
89
+ ```
90
+
91
+ ## Transactions
92
+
93
+ ### Sync Transactions (Recommended)
94
+
95
+ The sync endpoint is the recommended way to get transactions:
96
+
97
+ ```javascript
98
+ // Initial sync - get all available transactions
99
+ let cursor = null;
100
+ let allTransactions = [];
101
+
102
+ let response = await fastify.xplaid.transactions.sync(accessToken, { cursor });
103
+
104
+ allTransactions.push(...response.added);
105
+ cursor = response.next_cursor;
106
+
107
+ // Store the cursor for future syncs
108
+ // On subsequent syncs, pass the cursor to get only new/updated transactions
109
+ ```
110
+
111
+ ### Get Transactions (Legacy)
112
+
113
+ ```javascript
114
+ const transactions = await fastify.xplaid.transactions.get(accessToken, {
115
+ startDate: "2024-01-01",
116
+ endDate: "2024-12-31",
117
+ count: 100,
118
+ offset: 0,
119
+ accountIds: ["account_id"], // Optional
120
+ });
121
+ ```
122
+
123
+ ### Refresh Transactions
124
+
125
+ Force a refresh of transaction data:
126
+
127
+ ```javascript
128
+ await fastify.xplaid.transactions.refresh(accessToken);
129
+ ```
130
+
131
+ ## Identity
132
+
133
+ Get identity information (name, email, phone, address) from the bank:
134
+
135
+ ```javascript
136
+ const identity = await fastify.xplaid.identity.get(accessToken, {
137
+ accountIds: ["account_id"], // Optional
138
+ });
139
+ ```
140
+
141
+ ## Auth
142
+
143
+ Get ACH routing and account numbers:
144
+
145
+ ```javascript
146
+ const auth = await fastify.xplaid.auth.get(accessToken, {
147
+ accountIds: ["account_id"], // Optional
148
+ });
149
+
150
+ // Returns account numbers including:
151
+ // - ACH routing numbers
152
+ // - Account numbers
153
+ // - Wire routing numbers (if available)
154
+ ```
155
+
156
+ ## Investments
157
+
158
+ ### Get Holdings
159
+
160
+ ```javascript
161
+ const holdings = await fastify.xplaid.investments.getHoldings(accessToken, {
162
+ accountIds: ["account_id"], // Optional
163
+ });
164
+ ```
165
+
166
+ ### Get Investment Transactions
167
+
168
+ ```javascript
169
+ const investmentTx = await fastify.xplaid.investments.getTransactions(accessToken, {
170
+ startDate: "2024-01-01",
171
+ endDate: "2024-12-31",
172
+ count: 100,
173
+ offset: 0,
174
+ accountIds: ["account_id"], // Optional
175
+ });
176
+ ```
177
+
178
+ ## Liabilities
179
+
180
+ Get loan and credit card liability information:
181
+
182
+ ```javascript
183
+ const liabilities = await fastify.xplaid.liabilities.get(accessToken, {
184
+ accountIds: ["account_id"], // Optional
185
+ });
186
+
187
+ // Returns credit, mortgage, and student loan details
188
+ ```
189
+
190
+ ## Item Management
191
+
192
+ ### Get Item Info
193
+
194
+ ```javascript
195
+ const item = await fastify.xplaid.items.get(accessToken);
196
+ ```
197
+
198
+ ### Remove an Item
199
+
200
+ Permanently delete an item and revoke access:
201
+
202
+ ```javascript
203
+ await fastify.xplaid.items.remove(accessToken);
204
+ ```
205
+
206
+ ### Get Institution
207
+
208
+ ```javascript
209
+ const institution = await fastify.xplaid.items.getInstitution("ins_123", {
210
+ countryCodes: ["US"],
211
+ includeOptionalMetadata: true,
212
+ includeStatus: true,
213
+ });
214
+ ```
215
+
216
+ ### Search Institutions
217
+
218
+ ```javascript
219
+ const institutions = await fastify.xplaid.items.searchInstitutions({
220
+ query: "Chase",
221
+ products: ["transactions"],
222
+ countryCodes: ["US"],
223
+ count: 10,
224
+ offset: 0,
225
+ });
226
+ ```
227
+
228
+ ## Webhooks
229
+
230
+ ### Update Webhook URL
231
+
232
+ ```javascript
233
+ await fastify.xplaid.webhooks.update(accessToken, "https://myapp.com/new-webhook-url");
234
+ ```
235
+
236
+ ### Get Verification Key
237
+
238
+ Verify webhook signatures:
239
+
240
+ ```javascript
241
+ const key = await fastify.xplaid.webhooks.getVerificationKey("key_id_from_webhook_header");
242
+ ```
243
+
244
+ ## Constants
245
+
246
+ The plugin exposes useful constants:
247
+
248
+ ```javascript
249
+ const { ENVIRONMENTS, PRODUCTS, COUNTRY_CODES } = fastify.xplaid.constants;
250
+
251
+ // Or import directly
252
+ import { ENVIRONMENTS, PRODUCTS, COUNTRY_CODES } from "xplaid";
253
+
254
+ // ENVIRONMENTS
255
+ ENVIRONMENTS.SANDBOX // 'sandbox'
256
+ ENVIRONMENTS.DEVELOPMENT // 'development'
257
+ ENVIRONMENTS.PRODUCTION // 'production'
258
+
259
+ // PRODUCTS
260
+ PRODUCTS.AUTH // 'auth'
261
+ PRODUCTS.TRANSACTIONS // 'transactions'
262
+ PRODUCTS.IDENTITY // 'identity'
263
+ PRODUCTS.INVESTMENTS // 'investments'
264
+ PRODUCTS.LIABILITIES // 'liabilities'
265
+ PRODUCTS.ASSETS // 'assets'
266
+
267
+ // COUNTRY_CODES
268
+ COUNTRY_CODES.US // 'US'
269
+ COUNTRY_CODES.CA // 'CA'
270
+ COUNTRY_CODES.GB // 'GB'
271
+ COUNTRY_CODES.IE // 'IE'
272
+ COUNTRY_CODES.FR // 'FR'
273
+ COUNTRY_CODES.ES // 'ES'
274
+ COUNTRY_CODES.NL // 'NL'
275
+ ```
276
+
277
+ ## Raw Client Access
278
+
279
+ For advanced use cases, access the underlying Plaid client directly:
280
+
281
+ ```javascript
282
+ const plaidClient = fastify.xplaid.raw;
283
+
284
+ // Use any Plaid API method
285
+ const response = await plaidClient.sandboxItemFireWebhook({
286
+ access_token: accessToken,
287
+ webhook_code: "DEFAULT_UPDATE",
288
+ });
289
+ ```
290
+
291
+ ## Error Handling
292
+
293
+ Plaid errors include detailed error codes:
294
+
295
+ ```javascript
296
+ try {
297
+ const accounts = await fastify.xplaid.accounts.get(accessToken);
298
+ } catch (error) {
299
+ if (error.response?.data) {
300
+ const plaidError = error.response.data;
301
+ console.error("Plaid error:", {
302
+ errorType: plaidError.error_type,
303
+ errorCode: plaidError.error_code,
304
+ errorMessage: plaidError.error_message,
305
+ displayMessage: plaidError.display_message,
306
+ });
307
+ }
308
+ }
309
+ ```
310
+
311
+ Common error types:
312
+ - `INVALID_REQUEST` - Invalid parameters
313
+ - `INVALID_INPUT` - Invalid input data
314
+ - `INSTITUTION_ERROR` - Bank is unavailable
315
+ - `RATE_LIMIT_EXCEEDED` - Too many requests
316
+ - `API_ERROR` - Plaid internal error
317
+ - `ITEM_ERROR` - Item-specific error (e.g., login required)
318
+
319
+ ## Configuration Access
320
+
321
+ ```javascript
322
+ const config = fastify.xplaid.config;
323
+ // {
324
+ // clientId: '***id', // Masked for security
325
+ // environment: 'sandbox'
326
+ // }
327
+ ```
328
+
329
+ ## Complete Example
330
+
331
+ ```javascript
332
+ import Fastify from "fastify";
333
+ import xPlaid from "xplaid";
334
+
335
+ const fastify = Fastify({ logger: true });
336
+
337
+ await fastify.register(xPlaid, {
338
+ clientId: process.env.PLAID_CLIENT_ID,
339
+ secret: process.env.PLAID_SECRET,
340
+ environment: process.env.PLAID_ENV || "sandbox",
341
+ });
342
+
343
+ // Create link token endpoint
344
+ fastify.post("/api/create-link-token", async (request, reply) => {
345
+ const { userId } = request.body;
346
+
347
+ const linkToken = await fastify.xplaid.link.createToken({
348
+ userId,
349
+ clientName: "My Finance App",
350
+ products: ["transactions"],
351
+ countryCodes: ["US"],
352
+ language: "en",
353
+ });
354
+
355
+ return { linkToken: linkToken.link_token };
356
+ });
357
+
358
+ // Exchange public token endpoint
359
+ fastify.post("/api/exchange-token", async (request, reply) => {
360
+ const { publicToken, userId } = request.body;
361
+
362
+ const result = await fastify.xplaid.link.exchangePublicToken(publicToken);
363
+
364
+ // Store accessToken and itemId in your database
365
+ // associated with the userId
366
+
367
+ return { success: true };
368
+ });
369
+
370
+ // Get transactions endpoint
371
+ fastify.get("/api/transactions", async (request, reply) => {
372
+ const { userId } = request.user; // From your auth middleware
373
+
374
+ // Retrieve accessToken from your database for this user
375
+ const accessToken = await getAccessTokenForUser(userId);
376
+
377
+ const transactions = await fastify.xplaid.transactions.sync(accessToken);
378
+
379
+ return { transactions: transactions.added };
380
+ });
381
+
382
+ await fastify.listen({ port: 3000 });
383
+ ```
384
+
385
+ ## Testing
386
+
387
+ ```bash
388
+ npm test
389
+ ```
390
+
391
+ ## License
392
+
393
+ ISC
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@xenterprises/fastify-xplaid",
3
+ "version": "1.0.0",
4
+ "description": "Fastify plugin for Plaid financial data integration - bank account linking, transactions, and identity verification",
5
+ "type": "module",
6
+ "main": "src/xPlaid.js",
7
+ "exports": {
8
+ ".": "./src/xPlaid.js"
9
+ },
10
+ "scripts": {
11
+ "test": "node --test test/xPlaid.test.js"
12
+ },
13
+ "keywords": [
14
+ "fastify",
15
+ "fastify-plugin",
16
+ "plaid",
17
+ "banking",
18
+ "financial",
19
+ "transactions",
20
+ "identity",
21
+ "fintech",
22
+ "open-banking"
23
+ ],
24
+ "author": "",
25
+ "license": "ISC",
26
+ "dependencies": {
27
+ "fastify-plugin": "^5.0.1",
28
+ "plaid": "^28.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "fastify": "^5.0.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=20.0.0"
35
+ }
36
+ }