@enfuce/nextgen-sdk
v0.0.11
Published
Enfuce nextgen client SDK (TypeScript). One namespaced export per API.
Readme
@enfuce/nextgen-sdk
Enfuce nextgen client SDK for TypeScript. One namespaced export per API, so identically-named schemas across APIs never collide. Ships both CommonJS and ESM builds.
Installation
npm install @enfuce/nextgen-sdkUsage
Each API is exposed under its own namespace, and every module ships a fluent <Module>Client
(e.g. card.CardClient, exchangeRate.ExchangeRateClient) that wires an OAuth-enabled axios
instance to the module's configuration and exposes each API. Every request is authenticated with an
OAuth2 client_credentials bearer token:
import { oauth, card, config } from '@enfuce/nextgen-sdk';
// Set the tenant + environment once; the config helper derives every base URL (and the token URL) from it.
const te = { tenant: '<tenant>', environment: '<environment>' };
// One token manager (cached client-credentials grant) — reuse it across every module.
const clientCredentialsManager = oauth.clientCredentials({
tokenUrl: config.tokenUrl(te),
clientId: '<client-id>',
clientSecret: '<client-secret>',
scopes: ['issuer/cardholder.read'],
});
const client = card.CardClient.builder()
.baseUrl(config.issuerBaseUrl(te))
.oauth(clientCredentialsManager) // token on every request + reactive 401 retry
.configure((http) => { http.defaults.timeout = 10_000; }) // optional: timeout, proxy, headers …
.build();
const { data } = await client.getCardApi().getCard(cardId, '[email protected]');environment is the target platform — e.g. ext-uat1-sandbox (sandbox) or eu.live.prod
(production). One clientCredentialsManager authenticates every module, so build it once and reuse it
across all your clients. See Client customization for transport tuning
(timeouts, proxy, interceptors).
Keeping the token URL separate from the client identity? Pass a ClientCredentials — e.g. with the
config helper deriving the URL:
const clientCredentialsManager = oauth.clientCredentials(config.tokenUrl(te), {
clientId: '<client-id>',
clientSecret: '<client-secret>',
scopes: ['issuer/cardholder.read'],
});Inspecting scopes
oauth.availableScopes(...) discovers the scopes the client is entitled to — it requests a token
with no scope narrowing and resolves to the granted scopes (sorted, de-duplicated). oauth.scopesOf(...)
decodes the granted scopes from any JWT you already hold. Both yield an empty array for an opaque
(non-JWT) token and never throw. Server-side only.
import { oauth, config } from '@enfuce/nextgen-sdk';
// The client's full entitlement (a live, uncached token request):
const available = await oauth.availableScopes(config.tokenUrl(te), {
clientId: '<client-id>',
clientSecret: '<client-secret>',
});
// Or decode the scopes granted on a token you already hold:
const granted = oauth.scopesOf(await clientCredentialsManager.getToken());Client customization
.configure((http) => …) on any <Module>Client builder hands you the underlying axios instance for
full transport control — timeout, proxy, headers, request/response interceptors, etc. It composes
with .oauth(...); the OAuth token is attached independently via its own interceptor.
const client = card.CardClient.builder()
.baseUrl(config.issuerBaseUrl(te))
.oauth(clientCredentialsManager)
.configure((http) => {
http.defaults.headers.common['X-My-Header'] = 'value';
http.interceptors.request.use(myInterceptor);
})
.build();Prefer the lower level? Build your own axios and pass it through:
oauth.createOAuthAxios(clientCredentialsManager, axios.create({ timeout: 10_000 })), then
new card.GetCardApi(new card.Configuration({ basePath }), undefined, http).
Configuring timeouts
axios timeouts are a single value in milliseconds (applied per request). Set it on the axios
instance via .configure(...):
const client = card.CardClient.builder()
.baseUrl(config.issuerBaseUrl(te))
.oauth(clientCredentialsManager)
.configure((http) => { http.defaults.timeout = 10_000; }) // 10s
.build();API modules
Each module builds the same way — set its base URL with the matching accessor
(config.issuerBaseUrl, config.processorBaseUrl, or config.exchangeRateBaseUrl) and reuse the
shared clientCredentialsManager. Every call resolves to an axios response, so read .data.
Snippets assume te and clientCredentialsManager are in scope.
cardholder — issuerBaseUrl
import { cardholder, config } from '@enfuce/nextgen-sdk';
const client = cardholder.CardholderClient.builder().baseUrl(config.issuerBaseUrl(te)).oauth(clientCredentialsManager).build();
const { data: holder } = await client.getCardholderApi().getCardholderById(cardholderId, '[email protected]');
const { data: cards } = await client.getCardsByCardholderIdApi()
.getCardsByCardholderId(cardholderId, undefined, undefined, '[email protected]');card — issuerBaseUrl
import { card, config } from '@enfuce/nextgen-sdk';
const client = card.CardClient.builder().baseUrl(config.issuerBaseUrl(te)).oauth(clientCredentialsManager).build();
const { data } = await client.getCardApi().getCard(cardId, '[email protected]');
await client.updateCardApi().activateCard(cardId, undefined, '[email protected]'); // (id, idempotencyKey, auditUser)wallet — issuerBaseUrl
import { wallet, config } from '@enfuce/nextgen-sdk';
const client = wallet.WalletClient.builder().baseUrl(config.issuerBaseUrl(te)).oauth(clientCredentialsManager).build();
const { data: tokens } = await client.getTokensApi().getTokens(cardId, false, undefined, '[email protected]');pin — issuerBaseUrl
import { pin, config } from '@enfuce/nextgen-sdk';
const client = pin.PinClient.builder().baseUrl(config.issuerBaseUrl(te)).oauth(clientCredentialsManager).build();
const { data } = await client.pINOperationsUsingPKIApi().viewPin(viewPinRequestBody, '[email protected]');exchangeRate — exchangeRateBaseUrl
import { exchangeRate, config } from '@enfuce/nextgen-sdk';
const client = exchangeRate.ExchangeRateClient.builder().baseUrl(config.exchangeRateBaseUrl(te)).oauth(clientCredentialsManager).build();
const { data: currencies } = await client.getECBSupportedCurrenciesApi().getEcbSupportedCurrenciesV1();
const { data: rate } = await client.getECBExchangeRateApi().getEcbRateV1('EUR', 'USD');threeds — processorBaseUrl
import { threeds, config } from '@enfuce/nextgen-sdk';
const client = threeds.ThreedsClient.builder().baseUrl(config.processorBaseUrl(te)).oauth(clientCredentialsManager).build();
await client.threeDSApi().handleAuthenticationChallengeResult(challengeResultBody);cards — processorBaseUrl
import { cards, config } from '@enfuce/nextgen-sdk';
const client = cards.CardsClient.builder().baseUrl(config.processorBaseUrl(te)).oauth(clientCredentialsManager).build();
await client.cardsApi().resetPinCounter(cardId, sequenceNumber);Webhooks
These are the calls Enfuce makes to you: you host the endpoint and Enfuce POSTs to it. Such modules export only the payload types — there is no client to call, since your app receives these rather than requesting them. Use the types to type the inbound request body:
import type { issuerEvents } from '@enfuce/nextgen-sdk';
const event = JSON.parse(payload) as issuerEvents.CardEvent;authorisationControl is synchronous — Enfuce expects an approve/decline decision in the response,
so you both consume a type and return one (AuthResponseCode is a runtime value, import it, not
import type):
import { authorisationControl } from '@enfuce/nextgen-sdk';
const request = JSON.parse(payload) as authorisationControl.AuthRequestBody;
const decision: authorisationControl.AuthResponseBody = {
authResponseCode: authorisationControl.AuthResponseCode.Approved,
};| Namespace | Payload type(s) |
| --- | --- |
| issuerEvents | CardEvent, CardholderEvent, TokenEvent |
| authorisationControl | AuthRequestBody → AuthResponseBody (synchronous decision) |
| threedsOob | InitiateAuthenticationChallengeBody |
| transactionEvent | TransactionEvent |
A runnable Express example of all of the above (both the API modules and the webhook receivers) lives in
examples/backends/typescript.
File parsing
Enfuce delivers some data as a file rather than an HTTP API. These modules export only the
types — parse the file's JSON into them. clearingFileCopy is a clearing (settlement) file: a
FileData header plus a list of records.
import type { clearingFileCopy } from '@enfuce/nextgen-sdk';
const file = JSON.parse(clearingFileCopyJson) as clearingFileCopy.FileData;
file.records?.forEach((record) => { /* … */ });| Namespace | Type(s) |
| --- | --- |
| clearingFileCopy | FileData (clearing file header + records) |
Requirements
- Node.js
>=18 - TypeScript
^4.0 || ^5.0(works in Node and the browser)
License
MIT
