UNPKG

tickethead-sdk

Version:

SDK for the Tickethead API

354 lines 15.4 kB
"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