UNPKG

investec-pb-api

Version:

A simple package for interacting with Investec's private banking API

255 lines (252 loc) 8.53 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { InvestecPbApi: () => InvestecPbApi }); module.exports = __toCommonJS(index_exports); // src/investec-pb-api.ts var import_node_fetch = __toESM(require("node-fetch"), 1); var createEndpoint = (host, path) => new URL(path, host).toString(); var InvestecPbApi = class { host; clientId; clientSecret; apiKey; token; expiresIn; /** * Create a new InvestecPbApi instance. * @param clientId OAuth client ID * @param clientSecret OAuth client secret * @param apiKey API key from Investec * @param host Optional API host (defaults to Investec production) */ constructor(clientId, clientSecret, apiKey, host = "https://openapi.investec.com") { this.host = host; this.apiKey = apiKey; this.clientId = clientId; this.clientSecret = clientSecret; this.expiresIn = /* @__PURE__ */ new Date(); } /** * Get a valid OAuth token, refreshing if necessary. * @returns Access token string */ async getToken() { const now = /* @__PURE__ */ new Date(); if (this.token) { if (now.getTime() < this.expiresIn.getTime()) { return this.token; } } const result = await this.getAccessToken(); now.setSeconds(now.getSeconds() + result.expires_in); this.expiresIn = now; return result.access_token; } /** * Request a new OAuth access token from Investec. * @returns AuthResponse object * @throws Error if authentication fails */ async getAccessToken() { const endpoint = createEndpoint(this.host, `/identity/v2/oauth2/token`); const response = await (0, import_node_fetch.default)(endpoint, { method: "POST", headers: { Authorization: "Basic " + Buffer.from(this.clientId + ":" + this.clientSecret).toString( "base64" ), "x-api-key": this.apiKey, "content-type": "application/x-www-form-urlencoded" }, body: "grant_type=client_credentials" }); if (response.status !== 200) { throw new Error(response.statusText); } const result = await response.json(); this.token = result.access_token; return result; } /** * Make multiple transfers from an account. * @param accountId The account ID to transfer from * @param transfers One or more transfer instructions * @returns TransferResponse * @throws Error if parameters are missing or API call fails */ async transferMultiple(accountId, transfers) { if (!accountId || !transfers) { throw new Error("Missing required parameters"); } const endpoint = createEndpoint( this.host, `/za//pb/v1/accounts/${encodeURIComponent(accountId)}/transfermultiple` ); const token = this.token || await this.getToken(); if (!Array.isArray(transfers)) { transfers = [transfers]; } const payload = { transferList: transfers }; return fetchPost(endpoint, token, payload); } /** * Make multiple payments from an account. * @param accountId The account ID to pay from * @param payments One or more payment instructions * @returns TransferResponse * @throws Error if parameters are missing or API call fails */ async payMultiple(accountId, payments) { if (!accountId || !payments) { throw new Error("Missing required parameters"); } const endpoint = createEndpoint( this.host, `/za//pb/v1/accounts/${encodeURIComponent(accountId)}/paymultiple` ); const token = this.token || await this.getToken(); if (!Array.isArray(payments)) { payments = [payments]; } const payload = { paymentList: payments }; return fetchPost(endpoint, token, payload); } /** * Retrieve all beneficiaries for the authenticated user. * @returns BeneficiaryResponse */ async getBeneficiaries() { const endpoint = createEndpoint( this.host, `/za/pb/v1/accounts/beneficiaries` ); const token = this.token || await this.getToken(); return fetchGet(endpoint, token); } /** * Retrieve all accounts for the authenticated user. * @returns AccountResponse */ async getAccounts() { const endpoint = createEndpoint(this.host, `/za/pb/v1/accounts`); const token = this.token || await this.getToken(); return fetchGet(endpoint, token); } /** * Get the balance for a specific account. * @param accountId The account ID * @returns AccountBalanceResponse * @throws Error if accountId is missing or API call fails */ async getAccountBalances(accountId) { if (!accountId) { throw new Error("Missing required parameters"); } const endpoint = createEndpoint( this.host, `/za/pb/v1/accounts/${encodeURIComponent(accountId)}/balance` ); const token = this.token || await this.getToken(); return fetchGet(endpoint, token); } /** * Get transactions for a specific account, optionally filtered by date and type. * @param accountId The account ID * @param fromDate Optional start date (YYYY-MM-DD) * @param toDate Optional end date (YYYY-MM-DD) * @param transactionType Optional transaction type filter * @returns AccountTransactionResponse * @throws Error if accountId is missing or API call fails */ async getAccountTransactions(accountId, fromDate = null, toDate = null, transactionType = null) { if (!accountId) { throw new Error("Missing required parameters"); } let url = `/za/pb/v1/accounts/${encodeURIComponent( accountId )}/transactions`; const params = new URLSearchParams(); if (fromDate) params.append("fromDate", fromDate); if (toDate) params.append("toDate", toDate); if (transactionType) params.append("transactionType", transactionType); if ([fromDate, toDate, transactionType].some(Boolean)) { url += `?${params.toString()}`; } const endpoint = createEndpoint(this.host, url); const token = this.token || await this.getToken(); return fetchGet(endpoint, token); } }; async function fetchGet(endpoint, token) { const response = await (0, import_node_fetch.default)(endpoint, { method: "GET", signal: AbortSignal.timeout(3e4), headers: { Authorization: "Bearer " + token, "content-type": "application/json" } }); if (response.status !== 200) { if (response.status === 404) { throw new Error("Card not found"); } throw new Error(response.statusText); } return await response.json(); } async function fetchPost(endpoint, token, body) { const response = await (0, import_node_fetch.default)(endpoint, { method: "POST", signal: AbortSignal.timeout(3e4), headers: { Authorization: "Bearer " + token, "content-type": "application/json" }, body: JSON.stringify(body) }); if (response.status !== 200) { if (response.status === 404) { throw new Error("Card not found"); } throw new Error(response.statusText); } return await response.json(); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { InvestecPbApi });