tickethead-sdk
Version:
SDK for the Tickethead API
354 lines • 15.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SDK = void 0;
const jwt_decode_1 = require("jwt-decode");
const query_string_1 = __importDefault(require("query-string"));
const event_1 = require("./event");
const order_1 = require("./order");
const ticket_1 = require("./ticket");
const account_1 = require("./account");
const payment_1 = require("./payment");
const blockchain_1 = require("./blockchain");
const validator_1 = require("./validator");
const common_1 = require("./common");
const auth_1 = require("./auth");
const venue_1 = require("./venue");
const credential_factory_1 = require("./credential/credential-factory");
const service_1 = require("./upload/service");
const orderbook_1 = require("./orderbook");
const nft_1 = require("./nft");
const notification_1 = require("./notification");
const service_2 = require("./pdf/service");
const aggregator_1 = require("./aggregator");
const events_1 = __importDefault(require("events"));
/**
* BAM services class. The BAM instance holds the API URLs, the authorization token
* and keeps track of the API version used.
*/
class SDK {
constructor(baseUrl, version = 'v1', retryOptions, cacheOptions, camelCaseResponse = true) {
this.baseUrl = baseUrl;
this.version = version;
// Subscribe to this so you can react to the changes in the lifecycle
/** Emits `authorizationChanged`, `logout` ,`initialized`, `organizerChanged`, `tenantChanged`, `tokenRefreshed`, `credentialsExpired` */
this.eventEmitter = new events_1.default();
let orgDefault;
switch (baseUrl) {
case common_1.BaseUrl.ThProd:
case common_1.BaseUrl.ThStaging:
case common_1.BaseUrl.ThDev:
orgDefault = 'tickethead';
break;
}
const options = {
baseUrl,
retryOptions,
cacheOptions,
camelCaseResponse,
};
this.client = (0, common_1.buildClient)(options);
this.tenantClient = (0, common_1.buildClient)(Object.assign(Object.assign({}, options), { tenantName: orgDefault }));
// Global services
this.auth = new auth_1.AuthService(this.client, version);
this.account = new account_1.AccountService(this.client, version);
this.venue = new venue_1.VenueService(this.client, version);
this.upload = new service_1.UploadService(this.client, version);
this.validator = new validator_1.ValidatorService(this.client, version);
this.nft = new nft_1.NftService(this.client, version);
this.pdf = new service_2.PdfService(this.client, version);
this.aggregator = new aggregator_1.AggregatorService(this.client, version);
// Per-tenant services
this.event = new event_1.EventService(this.tenantClient, version);
this.order = new order_1.OrderService(this.tenantClient, version);
this.payment = new payment_1.PaymentService(this.tenantClient, version);
this.blockchain = new blockchain_1.BlockchainService(this.tenantClient, version);
this.ticket = new ticket_1.TicketService(this.tenantClient, version);
this.orderbook = new orderbook_1.OrderbookService(this.tenantClient, version);
// Hybrids
this.notification = new notification_1.NotificationService(this.client, this.tenantClient, version);
}
get credentials() {
return this._credentials;
}
get tenant() {
return this._tenant;
}
/**
* Sets the tenant used by tenant-specific services.
*
* @param tenantName Name of a tenant to be set
*/
set tenant(tenantName) {
this._tenant = tenantName;
// Organizer name is reset to tenant name, as in the general case it no longer corresponds
this._organizer = tenantName;
this.tenantClient.defaults.baseURL = (0, common_1.createBaseUrl)(this.baseUrl, tenantName);
this.eventEmitter.emit('tenantChanged', { tenantName });
}
get organizer() {
return this._organizer;
}
get deviceId() {
return this._deviceId;
}
set deviceId(deviceId) {
this._deviceId = deviceId;
this.client.defaults.headers['x-device-id'] = deviceId;
this.tenantClient.defaults.headers['x-device-id'] = deviceId;
}
/**
* You can use the object in the response to construct JwtCredentials.
*/
getToken() {
var _a;
return (_a = this.credentials) === null || _a === void 0 ? void 0 : _a.getToken();
}
static getTokenPayload(token) {
return (0, jwt_decode_1.jwtDecode)(token);
}
/**
* Used to store the state of the SDK.
* Can be used via the build method to restore state.
*/
serialize() {
return {
version: this.version,
baseUrl: this.baseUrl,
organizer: this.organizer,
credentials: this.credentials,
};
}
/**
* Factory method for initializing the SDK.
* Can be used in conjunction with the serialize method to restore state.
*/
static build(params) {
return __awaiter(this, void 0, void 0, function* () {
const { baseUrl, version = 'v1', organizer, retry, cache, camelCaseResponse, } = params;
const sdk = new SDK(baseUrl, version, retry, cache, camelCaseResponse);
if (params.organizer)
yield sdk.useOrganizer(organizer);
if (params.credentials) {
const creds = isCredential(params.credentials)
? params.credentials
: credential_factory_1.CredentialFactory.build(params.credentials);
yield sdk.authorize(creds);
}
sdk.eventEmitter.emit('initialized', { params });
return sdk;
});
}
/**
* Sets the organizer used on the instance. Any event, payment, reporting or websocket API call
* will be made to the organizer's tenant API.
*
* @param organizerName Name of an organizer to be set on the instance
*/
useOrganizer(organizerName) {
return __awaiter(this, void 0, void 0, function* () {
if (organizerName === this._organizer) {
// No need to refresh the token if it is for the selected organizer
return;
}
const organizer = yield this.account.getOrganizer({ id: organizerName });
// Second term is to support the no case conversion use case
this.tenant =
organizer.organizationName || organizer.organization_name;
// Ordering is important as using the tenant setter resets the organizer name
this._organizer = organizer.name;
// Refresh the token, fetching the permissions for the specified organizer
// For guest and service tokens, this does not change anything
// If there are no credentials at all, there is no point in doing this
if (this._credentials) {
yield this.authorize(this._credentials, this._organizer);
}
this.eventEmitter.emit('organizerChanged', {
organizerName,
tenantName: this.tenant,
});
});
}
/**
* Authorizes the SDK instance with a JWT obtained from the API.
* For user or organizer based login supply `PasswordCredentials`.
* For internal service authentication use `ServiceCredentials` with the appropriate organizer ID.
* For logging in with a wallet, use `WalletCredentials` aka the private key and certificate.
* For guest login use the parameterless version of `authorize`.
*
* @param credentials User, organizer, service or wallet credentials.
* @param organizer The organizer name of the organizer for which the token is requested.
*/
authorize(credentials, organizer) {
return __awaiter(this, void 0, void 0, function* () {
this._credentials = credentials;
if (organizer) {
this._organizer = organizer;
}
const jwt = yield credentials.authorize(this.auth, this.organizer);
// Set the auth headers
this.setAuthorization(jwt);
// This is an instance of jjs programming
const refreshFunction = () => __awaiter(this, void 0, void 0, function* () {
if (this.credentials.isRefreshable()) {
try {
const newJwt = yield this.credentials.refreshToken(this.auth, this.organizer);
this.eventEmitter.emit('tokenRefreshed', { jwt: newJwt });
return newJwt.token;
}
catch (error) {
this.eventEmitter.emit('credentialsExpired', this.credentials);
throw error;
}
}
else {
this.eventEmitter.emit('credentialsExpired', this.credentials);
return this._credentials.getToken().token;
}
});
(0, common_1.setAxiosUpdateTokenFunction)(this.client, refreshFunction);
(0, common_1.setAxiosUpdateTokenFunction)(this.tenantClient, refreshFunction);
return jwt;
});
}
/** Removes all authorization from the SDK */
logout() {
this._credentials = undefined;
// Remove the auth headers
delete this.client.defaults.headers['Authorization'];
delete this.tenantClient.defaults.headers['Authorization'];
// Remove the update functions
(0, common_1.setAxiosUpdateTokenFunction)(this.client, common_1.nopUpdate);
(0, common_1.setAxiosUpdateTokenFunction)(this.tenantClient, common_1.nopUpdate);
this.eventEmitter.emit('logout');
}
/** Returns true if the SDK has an authorization set */
get isLoggedIn() {
return this._credentials != null;
}
/**
* Sets the Bearer header of the calls to the specified token.
* You can also use the authorize method with JwtCredentials.
*
* @param jwt JWT to use for calls to the BAM services
*/
setAuthorization(jwt) {
// Set the auth headers
this.client.defaults.headers['Authorization'] = `Bearer ${jwt.token}`;
this.tenantClient.defaults.headers['Authorization'] = `Bearer ${jwt.token}`;
this.eventEmitter.emit('authorizationChanged', { jwt });
}
/**
* Returns the status of currently used BAM services.
* This includes global services and the services for the current tenant.
*/
health() {
return __awaiter(this, void 0, void 0, function* () {
const accHealth = this.account.health();
const eventHealth = this.event.health();
const venueHealth = this.venue.health();
const paymentHealth = this.payment.health();
const blockchainHealth = this.blockchain.health();
// Await at the same time so its parallel
const [account, event, payment, blockchain, venue] = yield Promise.all([
accHealth,
eventHealth,
paymentHealth,
blockchainHealth,
venueHealth,
]);
// This needs to be changed if a service is extracted from another service
// This is mapped so there are no redundant calls to services
return {
auth: account,
account: account,
payment: payment,
event: event,
order: event,
blockchain: blockchain,
venue: venue,
};
});
}
/**
* Returns events with secure tickets for the authorized enrolled user.
*
* @param req.date Filter events by `end_at` date comparing with `midnight`. Expected values are `future`, `past` and `all`.
* @returns
*/
getMyEvents(req) {
return __awaiter(this, void 0, void 0, function* () {
const query = query_string_1.default.stringify({
date: req.date,
});
const res = yield this.client.get(`${this.version}/my_events?${query}`);
return res.data.data;
});
}
/**
* Returns data that needs to be imported to the local validation server.
*/
getImportData(request) {
return __awaiter(this, void 0, void 0, function* () {
const event = yield this.event.getEvent({
id: request.eventId,
organizer_id: request.organizerId,
});
const [venue, qrCodes, validators] = yield Promise.all([
this.venue.getVenue({
id: parseInt(event.venueId),
}),
this.event.getQrCodes({
id: request.eventId,
organizer_id: request.organizerId,
}),
this.validator.getExportedValidators({ id: request.organizerId }, {
event_id: request.eventId,
}),
]);
const importedValidators = validators.map((v) => {
// Casing issue regarding the blockchain service...
const wallet = Object.assign(Object.assign({}, v.wallet), { private_key: v.wallet.privateKey, privateKey: undefined });
return Object.assign(Object.assign({}, v), { wallet });
});
return {
event: {
event,
qr_codes: qrCodes,
},
venue: {
venue,
},
account: {
validators: importedValidators,
},
};
});
}
/**
* Enable sending the current version to the backend and checking against the configured minimum version
*
* @param version Version which is sent to the backend and checked against the minimum version. Format 'X.Y.Z'
*/
enableMinimumVersionCheck(version) {
// set x-app-version headers
this.client.defaults.headers['x-app-version'] = version;
this.tenantClient.defaults.headers['x-app-version'] = version;
}
}
exports.SDK = SDK;
function isCredential(credential) {
return (credential === null || credential === void 0 ? void 0 : credential.authorize) !== undefined;
}
//# sourceMappingURL=sdk.js.map