lightrail-client
Version:
A Javascript and Typescript client for Lightrail
184 lines (183 loc) • 6.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateShopperToken = exports.request = exports.configure = exports.configuration = exports.webhooks = exports.transactions = exports.currencies = exports.values = exports.programs = exports.params = exports.model = exports.contacts = exports.LightrailRequestError = void 0;
const jsonwebtoken = require("jsonwebtoken");
const superagent = require("superagent");
const superagentLogger = require("superagent-logger");
const contacts = require("./contacts");
exports.contacts = contacts;
const model = require("./model");
exports.model = model;
const params = require("./params");
exports.params = params;
const programs = require("./programs");
exports.programs = programs;
const values = require("./values");
exports.values = values;
const currencies = require("./currencies");
exports.currencies = currencies;
const transactions = require("./transactions");
exports.transactions = transactions;
const webhooks = require("./webhooks");
exports.webhooks = webhooks;
const LightrailRequestError_1 = require("./LightrailRequestError");
Object.defineProperty(exports, "LightrailRequestError", { enumerable: true, get: function () { return LightrailRequestError_1.LightrailRequestError; } });
/**
* These values are all configurable from configure().
*/
exports.configuration = {
apiKey: null,
isBrowser: false,
restRoot: "https://api.lightrail.com/v2/",
sharedSecret: null,
webhookSecret: null,
logRequests: false,
additionalHeaders: {}
};
/**
* Configure the Lightrail client.
*/
function configure(options) {
if (!options) {
return;
}
if (options.apiKey !== undefined) {
if (typeof options.apiKey !== "string") {
throw new Error("apiKey must be a string");
}
exports.configuration.apiKey = options.apiKey;
}
if (options.isBrowser !== undefined) {
exports.configuration.isBrowser = options.isBrowser;
}
if (options.restRoot !== undefined) {
if (typeof options.restRoot !== "string") {
throw new Error("restRoot must be a string");
}
exports.configuration.restRoot = options.restRoot;
if (!exports.configuration.restRoot.endsWith("/")) {
exports.configuration.restRoot = exports.configuration.restRoot + "/";
}
}
if (options.sharedSecret !== undefined) {
if (typeof options.sharedSecret !== "string") {
throw new Error("sharedSecret must be a string");
}
exports.configuration.sharedSecret = options.sharedSecret;
}
if (options.webhookSecret !== undefined) {
if (typeof options.webhookSecret !== "string") {
throw new Error("webhookSecret must be a string");
}
exports.configuration.webhookSecret = options.webhookSecret;
}
if (options.additionalHeaders !== undefined) {
if (options.additionalHeaders === null || typeof options.additionalHeaders !== "object") {
throw new Error("additionalHeaders must be an object");
}
exports.configuration.additionalHeaders = options.additionalHeaders;
}
if (options.logRequests !== undefined) {
if (typeof options.logRequests !== "boolean") {
throw new Error("logRequests must be a boolean");
}
if (options.logRequests && !superagentLogger) {
throw new Error("logRequests is set to true but optional dependency superagent-logger was not found");
}
exports.configuration.logRequests = options.logRequests;
}
}
exports.configure = configure;
/**
* Initiate a new request to the Lightrail server.
*/
function request(method, path) {
if (!exports.configuration.apiKey && !exports.configuration.isBrowser) {
throw new Error("apiKey not set");
}
// We can do some fancy things with superagent here like request rate throttling.
let r = superagent(method, exports.configuration.restRoot + path)
.ok(() => true)
.retry();
if (exports.configuration.apiKey) {
r.set("Authorization", `Bearer ${exports.configuration.apiKey}`);
}
if (!exports.configuration.isBrowser) {
r.set("Lightrail-Client", `Lightrail-JavaScript/${process.env.npm_package_version}`);
}
if (exports.configuration.isBrowser) {
r.set("X-Requested-With", "XMLHttpRequest");
r.set("Expires", "-1");
r.set("Cache-Control", "no-cache,no-store,must-revalidate,max-age=-1,private");
}
if (exports.configuration.additionalHeaders) {
r.set(exports.configuration.additionalHeaders);
}
if (exports.configuration.logRequests && superagentLogger) {
r = r.use(superagentLogger);
}
return r;
}
exports.request = request;
/**
* Generate a shopper token that can be used to make Lightrail calls
* restricted to that particular shopper. The shopper can be defined by the
* contactId, or an empty string for anonymous.
*
* eg: `generateShopperToken("user-12345");`
* eg: `generateShopperToken("user-12345", {validityInSeconds: 43200});`
*
* @param contactId the ID of the contact
* @param options the number of seconds the shopper token will be valid for *OR* a GenerateShopperTokenOptions object
* @returns the shopper token
*/
function generateShopperToken(contactId, options) {
if (!exports.configuration.apiKey) {
throw new Error("apiKey not set");
}
if (!exports.configuration.sharedSecret) {
throw new Error("sharedSecret not set");
}
if (contactId == null) {
throw new Error("contactId must be a string (can be empty)");
}
let validityInSeconds = 43200;
let metadata;
if (options) {
if (typeof options.validityInSeconds === "number") {
validityInSeconds = options.validityInSeconds;
}
if (options.metadata) {
metadata = options.metadata;
}
}
if (validityInSeconds <= 0) {
throw new Error("validityInSeconds must be > 0");
}
const merchantJwtPayload = jsonwebtoken.decode(exports.configuration.apiKey);
if (!merchantJwtPayload || !merchantJwtPayload.g || !merchantJwtPayload.g.gui || !merchantJwtPayload.g.tmi) {
throw new Error("apiKey not valid");
}
const nowInSeconds = Date.now() / 1000;
return jsonwebtoken.sign({
g: {
gui: merchantJwtPayload.g.gui,
gmi: merchantJwtPayload.g.gmi,
tmi: merchantJwtPayload.g.tmi,
coi: contactId
},
metadata: metadata || undefined,
iss: "MERCHANT",
iat: nowInSeconds,
exp: nowInSeconds + validityInSeconds,
roles: ["shopper"]
}, exports.configuration.sharedSecret, {
header: {
alg: "HS256",
typ: "JWT",
ver: 3,
vav: 1
}
});
}
exports.generateShopperToken = generateShopperToken;