UNPKG

streambird

Version:
698 lines (678 loc) 28.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var axios = _interopDefault(require('axios')); var jose = require('jose'); var version = "1.0.9"; class StreambirdError extends Error { constructor(code, message) { let msg = `(${code}):${message}`; super(msg); this.code = code; this.name = "StreambirdError"; } } class StreambirdApiError extends StreambirdError { constructor(errorMessage, statusCode, errorType) { super(errorMessage); this.name = "StreambirdApiError"; this.errorMessage = errorMessage; this.statusCode = statusCode; this.errorType = errorType; } static fromResponse(responseBody) { const innerErrorData = responseBody instanceof Object ? responseBody : {}; const innerError = innerErrorData instanceof Object ? innerErrorData : {}; const errorType = `${innerError.error_type || "unknown"}`; const errorMessage = `${innerError.error_message || responseBody}`; const statusCode = innerError.status_code || 0; return new StreambirdApiError(errorMessage, statusCode, errorType); } isClientError() { return this.statusCode < 500; } } const snakeCase = (camelCaseString) => camelCaseString.replace(/[A-Z]/g, char => `_${char.toLowerCase()}`); const camelCase = (snakeCaseString) => snakeCaseString .replace(/_[0-9]/g, underscoreDigit => underscoreDigit[1]) .replace(/_[a-z]/g, underscoreChar => underscoreChar[1].toUpperCase()); const deepMapObjectKeys = (value, f) => { if (!(value instanceof Object)) { return value; } else if (Array.isArray(value)) { return value.map(item => deepMapObjectKeys(item, f)); } else { return Object.keys(value).reduce((acc, key) => { acc[f(key)] = deepMapObjectKeys(value[key], f); return acc; }, {}); } }; const convertObjectToSnakeCase = (requestBody) => { // Converting to JSON and back first handles things like dates, circular references etc. requestBody = JSON.parse(JSON.stringify(requestBody)); return deepMapObjectKeys(requestBody, snakeCase); }; const convertObjectToCamelCase = (responseBody) => deepMapObjectKeys(responseBody, camelCase); var Method; (function (Method) { Method["GET"] = "get"; Method["POST"] = "post"; Method["PUT"] = "put"; Method["DELETE"] = "delete"; })(Method || (Method = {})); const isJson = (response) => (response.headers["content-type"] || "").includes("application/json"); const convertAxiosErrorToStreambirdError = async (error) => { if (!error.response) { return new StreambirdError("axios_convert", error.message || "An unknown error occurred making the request"); } // Received a 4XX or 5XX response. const response = error.response; const data = response.data; return StreambirdApiError.fromResponse(data); }; const handleResponse = async (request) => { try { const response = await request; const data = response.data; return isJson(response) ? convertObjectToCamelCase(data) : data; } catch (error) { throw await convertAxiosErrorToStreambirdError(error); } }; class Resource { constructor(name, axiosInstance) { this.name = name; this.axiosInstance = axiosInstance; } async request({ method, path = "", body, query }) { const request = this.axiosInstance({ method, url: `${this.name}/${path}`, data: body && convertObjectToSnakeCase(body), params: query && convertObjectToSnakeCase(query) }); return handleResponse(request); } } class MagicLinks extends Resource { constructor(axiosInstance) { super("auth/magic_links", axiosInstance); } async loginOrCreate(loginOrCreateRequest) { let bodyData = { 'email': loginOrCreateRequest.email }; if (loginOrCreateRequest.loginRedirectUrl && loginOrCreateRequest.loginRedirectUrl.length > 0) { bodyData['login_redirect_url'] = loginOrCreateRequest.loginRedirectUrl; } if (loginOrCreateRequest.registrationRedirectUrl && loginOrCreateRequest.registrationRedirectUrl.length > 0) { bodyData['registration_redirect_url'] = loginOrCreateRequest.registrationRedirectUrl; } if (loginOrCreateRequest.loginExpiresIn && loginOrCreateRequest.loginExpiresIn > 0) { bodyData['login_expires_in'] = loginOrCreateRequest.loginExpiresIn; } if (loginOrCreateRequest.registrationExpiresIn && loginOrCreateRequest.registrationExpiresIn > 0) { bodyData['registration_expires_in'] = loginOrCreateRequest.registrationExpiresIn; } if (loginOrCreateRequest.deviceFingerprint) { bodyData['device_fingerprint'] = loginOrCreateRequest.deviceFingerprint; } if (loginOrCreateRequest.requiresVerification !== null && loginOrCreateRequest.requiresVerification !== undefined) { bodyData['requires_verification'] = loginOrCreateRequest.requiresVerification; } return this.request({ method: Method.POST, body: bodyData, path: 'email/login_or_create' }); } async invite(inviteRequest) { let bodyData = { 'email': inviteRequest.email }; if (inviteRequest.firstName && inviteRequest.firstName.length > 0) { bodyData['first_name'] = inviteRequest.firstName; } if (inviteRequest.lastName && inviteRequest.lastName.length > 0) { bodyData['last_name'] = inviteRequest.lastName; } if (inviteRequest.middleName && inviteRequest.middleName.length > 0) { bodyData['middle_name'] = inviteRequest.middleName; } if (inviteRequest.inviteRedirectUrl) { bodyData['invite_redirect_url'] = inviteRequest.inviteRedirectUrl; } if (inviteRequest.inviteExpiresIn) { bodyData['invite_expires_in'] = inviteRequest.inviteExpiresIn; } if (inviteRequest.deviceFingerprint) { bodyData['device_fingerprint'] = inviteRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'email/invite' }); } async create(embeddableRequest) { let bodyData = { 'user_id': embeddableRequest.userId }; if (embeddableRequest.expiresIn) { bodyData['expires_in'] = embeddableRequest.expiresIn; } if (embeddableRequest.deviceFingerprint) { bodyData['device_fingerprint'] = embeddableRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'create' }); } async verify(verifyRequest) { let bodyData = { 'token': verifyRequest.token }; if (verifyRequest.sessionToken && verifyRequest.sessionToken.length > 0) { bodyData['session_token'] = verifyRequest.sessionToken; } if (verifyRequest.sessionJwt && verifyRequest.sessionJwt.length > 0) { bodyData['session_jwt'] = verifyRequest.sessionJwt; } if (verifyRequest.sessionExpiresIn) { bodyData['session_expires_in'] = verifyRequest.sessionExpiresIn; } if (verifyRequest.deviceFingerprint) { bodyData['device_fingerprint'] = verifyRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'verify' }); } } class OAuth extends Resource { constructor(axiosInstance) { super("auth/oauth", axiosInstance); } async google(request) { let params = `public_token=${request.publicToken}`; if (request.redirect) { params += `&redirect=${request.redirect}`; } if (request.loginRedirectUrl) { params += `&login_redirect_url=${request.loginRedirectUrl}`; } if (request.registrationRedirectUrl) { params += `&registration_redirect_url=${request.registrationRedirectUrl}`; } return this.request({ method: Method.GET, path: `google/begin?${params}` }); } async apple(request) { let params = `public_token=${request.publicToken}`; if (request.redirect) { params += `&redirect=${request.redirect}`; } if (request.loginRedirectUrl) { params += `&login_redirect_url=${request.loginRedirectUrl}`; } if (request.registrationRedirectUrl) { params += `&registration_redirect_url=${request.registrationRedirectUrl}`; } return this.request({ method: Method.GET, path: `apple/begin?${params}` }); } async microsoft(request) { let params = `public_token=${request.publicToken}`; if (request.redirect) { params += `&redirect=${request.redirect}`; } if (request.loginRedirectUrl) { params += `&login_redirect_url=${request.loginRedirectUrl}`; } if (request.registrationRedirectUrl) { params += `&registration_redirect_url=${request.registrationRedirectUrl}`; } return this.request({ method: Method.GET, path: `microsoft/begin?${params}` }); } async discord(request) { let params = `public_token=${request.publicToken}`; if (request.redirect) { params += `&redirect=${request.redirect}`; } if (request.loginRedirectUrl) { params += `&login_redirect_url=${request.loginRedirectUrl}`; } if (request.registrationRedirectUrl) { params += `&registration_redirect_url=${request.registrationRedirectUrl}`; } return this.request({ method: Method.GET, path: `discord/begin?${params}` }); } async github(request) { let params = `public_token=${request.publicToken}`; if (request.redirect) { params += `&redirect=${request.redirect}`; } if (request.loginRedirectUrl) { params += `&login_redirect_url=${request.loginRedirectUrl}`; } if (request.registrationRedirectUrl) { params += `&registration_redirect_url=${request.registrationRedirectUrl}`; } return this.request({ method: Method.GET, path: `github/begin?${params}` }); } async verify(oauthRequest) { let bodyData = { 'token': oauthRequest.token }; if (oauthRequest.sessionType) { bodyData['session_type'] = oauthRequest.sessionType; } if (oauthRequest.sessionToken) { bodyData['session_token'] = oauthRequest.sessionToken; } if (oauthRequest.sessionExpiresIn) { bodyData['session_expires_in'] = oauthRequest.sessionExpiresIn; } if (oauthRequest.sessionJwt) { bodyData['session_jwt'] = oauthRequest.sessionJwt; } return this.request({ method: Method.POST, body: bodyData, path: 'verify' }); } } class Email extends Resource { constructor(axiosInstance) { super("auth/otps", axiosInstance); } async loginOrCreate(loginOrCreateRequest) { let bodyData = { email: loginOrCreateRequest.email }; if (loginOrCreateRequest.expiresIn && loginOrCreateRequest.expiresIn > 0) { bodyData['expires_in'] = loginOrCreateRequest.expiresIn; } if (loginOrCreateRequest.deviceFingerprint) { bodyData['device_fingerprint'] = loginOrCreateRequest.deviceFingerprint; } if (loginOrCreateRequest.requiresVerification !== null && loginOrCreateRequest.requiresVerification !== undefined) { bodyData['requires_verification'] = loginOrCreateRequest.requiresVerification; } return this.request({ method: Method.POST, body: bodyData, path: 'email/login_or_create' }); } async send(sendRequest) { let bodyData = { email: sendRequest.email, }; if (sendRequest.expiresIn && sendRequest.expiresIn > 0) { bodyData['expires_in'] = sendRequest.expiresIn; } if (sendRequest.deviceFingerprint) { bodyData['device_fingerprint'] = sendRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'email/send' }); } } class SMS extends Resource { constructor(axiosInstance) { super("auth/otps", axiosInstance); } async loginOrCreate(sendRequest) { let bodyData = { phone_number: sendRequest.phoneNumber }; if (sendRequest.expiresIn && sendRequest.expiresIn > 0) { bodyData['expires_in'] = sendRequest.expiresIn; } if (sendRequest.deviceFingerprint) { bodyData['device_fingerprint'] = sendRequest.deviceFingerprint; } if (sendRequest.requiresVerification !== null && sendRequest.requiresVerification !== undefined) { bodyData['requires_verification'] = sendRequest.requiresVerification; } return this.request({ method: Method.POST, body: bodyData, path: 'sms/login_or_create' }); } async send(sendRequest) { let bodyData = { phone_number: sendRequest.phoneNumber, }; if (sendRequest.expiresIn && sendRequest.expiresIn > 0) { bodyData['expires_in'] = sendRequest.expiresIn; } if (sendRequest.deviceFingerprint) { bodyData['device_fingerprint'] = sendRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'sms/send' }); } } class OTPs extends Resource { constructor(axiosInstance) { super("auth/otps", axiosInstance); this.email = new Email(axiosInstance); this.sms = new SMS(axiosInstance); } async verify(otpVerifyRequest) { let bodyData = { otp: otpVerifyRequest.otp, method_id: otpVerifyRequest.methodId, }; if (otpVerifyRequest.deviceFingerprint) { bodyData['device_fingerprint'] = otpVerifyRequest.deviceFingerprint; } if (otpVerifyRequest.sessionExpiresIn && otpVerifyRequest.sessionExpiresIn > 0) { bodyData['session_expires_in'] = otpVerifyRequest.sessionExpiresIn; } return this.request({ method: Method.POST, body: bodyData, path: 'verify' }); } } class Sessions extends Resource { constructor(axiosInstance, jwkConfig) { super("", axiosInstance); this.sessionRequest = "https://streambird.io/jwt/session"; this.jwksGetKey = jwkConfig.jwksGetKey; } async list(userId) { return this.request({ method: Method.GET, path: `auth/sessions/list?user_id=${userId}` }); } async verify(verifyRequest) { let bodyData = {}; if (verifyRequest.sessionToken) { bodyData['session_expires_in'] = verifyRequest.sessionExpiresIn; } if (verifyRequest.sessionToken) { bodyData['session_token'] = verifyRequest.sessionToken; } if (verifyRequest.sessionJwt) { bodyData['session_jwt'] = verifyRequest.sessionJwt; } return this.request({ method: Method.POST, body: bodyData, path: 'auth/sessions/verify' }); } async delete(deleteRequest) { let bodyData = {}; if (deleteRequest.sessionId) { bodyData['session_id'] = deleteRequest.sessionId; } if (deleteRequest.sessionToken) { bodyData['session_token'] = deleteRequest.sessionToken; } if (deleteRequest.sessionJwt) { bodyData['session_jwt'] = deleteRequest.sessionJwt; } return this.request({ method: Method.DELETE, body: bodyData, path: 'auth/sessions/delete' }); } async jwks() { return this.request({ method: Method.GET, path: 'auth/jwks/default' }); } async verifyJwt(jwt, options) { try { const session = await this.verifyLocalJwt(jwt, options); return { session, sessionJwt: jwt, }; } catch (err) { if (err instanceof StreambirdError && err.code === "jwt_stale" /* JWT_STALE */) { return this.verify({ sessionJwt: jwt }); } throw err; } } async verifyLocalJwt(jwt, options) { const dateNow = (options === null || options === void 0 ? void 0 : options.currentDate) || new Date(); let payload; try { let jwtVerifyResult = await jose.jwtVerify(jwt, this.jwksGetKey, { clockTolerance: options === null || options === void 0 ? void 0 : options.clockTolerance, currentDate: dateNow }); payload = jwtVerifyResult.payload; } catch (error) { throw new StreambirdError("jwt_error" /* JWT_ERROR */, "Could not verify JWT"); } if (options === null || options === void 0 ? void 0 : options.maxTokenAge) { const iat = payload.iat; if (!iat) { throw new StreambirdError("jwt_error" /* JWT_ERROR */, "JWT was missing iat claim"); } const currentEpoch = +dateNow / 1000; if (currentEpoch - iat >= options.maxTokenAge) { throw new StreambirdError("jwt_stale" /* JWT_STALE */, `JWT issued ${iat} > ${options.maxTokenAge}`); } } return payload[this.sessionRequest]; } } class TOTPs extends Resource { constructor(axiosInstance) { super("auth/totps", axiosInstance); } async create(createRequest) { let bodyData = { user_id: createRequest.userId }; if (createRequest.expiresIn) { bodyData.expires_in = createRequest.expiresIn; } return this.request({ method: Method.POST, body: bodyData, path: 'create' }); } async verify(updateRequest) { let bodyData = { user_id: updateRequest.userId, totp: updateRequest.totp }; if (updateRequest.sessionExpiresIn) { bodyData['session_expires_in'] = updateRequest.sessionExpiresIn; } if (updateRequest.sessionToken) { bodyData['session_token'] = updateRequest.sessionToken; } if (updateRequest.sessionJwt) { bodyData['session_jwt'] = updateRequest.sessionJwt; } if (updateRequest.deviceFingerprint) { bodyData['device_fingerprint'] = updateRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'verify' }); } async recoveryCodes(codeRequest) { let bodyData = { user_id: codeRequest.userId }; return this.request({ method: Method.POST, body: bodyData, path: 'recovery_codes' }); } async recovery(recoveryRequest) { let bodyData = { user_id: recoveryRequest.userId, totp: recoveryRequest.totp }; if (recoveryRequest.sessionExpiresIn) { bodyData['session_expires_in'] = recoveryRequest.sessionExpiresIn; } if (recoveryRequest.sessionToken) { bodyData['session_token'] = recoveryRequest.sessionToken; } if (recoveryRequest.sessionJwt) { bodyData['session_jwt'] = recoveryRequest.sessionJwt; } if (recoveryRequest.deviceFingerprint) { bodyData['device_fingerprint'] = recoveryRequest.deviceFingerprint; } return this.request({ method: Method.POST, body: bodyData, path: 'recovery' }); } } class Users extends Resource { constructor(axiosInstance) { super("auth/users", axiosInstance); } async create(userRequest) { let bodyData = { 'requires_verification': userRequest.requiresVerification, 'include_user': userRequest.includeUser }; if (userRequest.email && userRequest.email.length > 0) { bodyData['email'] = userRequest.email; } if (userRequest.phoneNumber && userRequest.phoneNumber.length > 0) { bodyData['phone_number'] = userRequest.phoneNumber; } if (userRequest.firstName && userRequest.firstName.length > 0) { bodyData['first_name'] = userRequest.firstName; } if (userRequest.middleName && userRequest.middleName.length > 0) { bodyData['middle_name'] = userRequest.middleName; } if (userRequest.lastName && userRequest.lastName.length > 0) { bodyData['last_name'] = userRequest.lastName; } if (userRequest.walletType && userRequest.walletType.length > 0) { bodyData['wallet_type'] = userRequest.walletType; } return this.request({ method: Method.POST, body: bodyData, path: 'create' }); } async update(userId, options) { let bodyData = {}; if (options.firstName && options.firstName.trim().length > 0) { bodyData['first_name'] = options.firstName; } if (options.middleName && options.middleName.trim().length > 0) { bodyData['middle_name'] = options.middleName; } if (options.lastName && options.lastName.trim().length > 0) { bodyData['last_name'] = options.lastName; } if (options.emails) { bodyData['emails'] = []; options.emails && options.emails.map((email) => { bodyData['emails'].push({ email: email }); }); } if (options.phoneNumbers) { bodyData['phone_numbers'] = []; options.phoneNumbers && options.phoneNumbers.map((phoneNumber) => { bodyData['phone_numbers'].push({ phone_number: phoneNumber }); }); } return this.request({ method: Method.PUT, path: `${userId}/update`, body: bodyData }); } async get(userId) { return this.request({ method: Method.GET, path: `${userId}` }); } async delete(userId) { return this.request({ method: Method.DELETE, path: `${userId}/delete` }); } async deleteEmail(emailId) { return this.request({ method: Method.DELETE, path: `emails/${emailId}/delete` }); } async deletePhoneNumber(phoneNumberId) { return this.request({ method: Method.DELETE, path: `phone_numbers/${phoneNumberId}/delete` }); } async deleteWallet(walletId) { return this.request({ method: Method.DELETE, path: `wallets/${walletId}/delete` }); } async search(searchRequest) { let bodyData = {}; bodyData['limit'] = searchRequest.limit; if (searchRequest.startingAfter) { bodyData['starting_after'] = searchRequest.startingAfter; } if (searchRequest && searchRequest.filters) { bodyData['filters'] = {}; bodyData['filters']['operator'] = searchRequest.filters.operator; if (searchRequest.filters.fields) { let fieldsToAdd = []; searchRequest.filters.fields.map((field) => { let fieldObj = {}; fieldObj['field'] = field.field; fieldObj['operator'] = field.operator; if (field.value) { fieldObj['value'] = field.value; } if (field.secondValue) { fieldObj['second_value'] = field.secondValue; } if (field.values) { fieldObj['values'] = field.values; } fieldsToAdd.push(fieldObj); }); if (fieldsToAdd.length > 0) { bodyData['filters']['fields'] = fieldsToAdd; } } } return this.request({ method: Method.POST, body: bodyData, path: 'search' }); } async deleteWebAuthn(webauthnCredentialId) { return this.request({ method: Method.DELETE, path: `webauthn_credentials/${webauthnCredentialId}/delete` }); } async deleteTOTP(totpId) { return this.request({ method: Method.DELETE, path: `totps/${totpId}/delete` }); } } class Wallets extends Resource { constructor(axiosInstance) { super("auth/wallets", axiosInstance); } async beginRegistration(registrationRequest) { let bodyData = { 'wallet_type': registrationRequest.walletType, 'public_address': registrationRequest.publicAddress }; if (registrationRequest.userId) { bodyData['user_id'] = registrationRequest.userId; } return this.request({ method: Method.POST, body: bodyData, path: 'registrations/begin' }); } async verify(verifyRequest) { let bodyData = { 'wallet_type': verifyRequest.walletType, 'public_address': verifyRequest.publicAddress, 'signature': verifyRequest.signature }; if (verifyRequest.sessionToken) { bodyData['session_token'] = verifyRequest.sessionToken; } if (verifyRequest.sessionExpiresIn) { bodyData['session_expires_in'] = verifyRequest.sessionExpiresIn; } if (verifyRequest.sessionJwt) { bodyData['session_jwt'] = verifyRequest.sessionJwt; } return this.request({ method: Method.POST, body: bodyData, path: 'verify' }); } async create(createRequest) { let bodyData = { 'wallet_type': createRequest.walletType, 'user_id': createRequest.userId, }; return this.request({ method: Method.POST, body: bodyData, path: 'create' }); } } class Streambird { constructor({ apiKey, timeout = 30000, apiHostUrl }) { if (!apiKey) { throw new Error("No API key provided"); } const apiUrl = `https://api.streambird.io/v1/`; const baseURL = apiHostUrl || apiUrl; let jwkConfig = { jwksGetKey: jose.createRemoteJWKSet(new URL(`${baseURL}auth/jwks/default?api_key=${apiKey}`)) }; //const JWKS = jose.createRemoteJWKSet(new URL('http://localhost:11019/v1/auth/jwks/default?api_key=sk_pRqweh3wvWmJAAVYv7Z0T5iPLzFM4ql0muoyQcjOxGeN3p1r')) this.axiosInstance = axios.create({ baseURL: baseURL, headers: { "Content-Type": "application/json", "User-Agent": `streambird-node/${version}`, "Authorization": `Bearer ${apiKey}` }, timeout }); this.users = new Users(this.axiosInstance); this.magicLinks = new MagicLinks(this.axiosInstance); this.otps = new OTPs(this.axiosInstance); this.wallets = new Wallets(this.axiosInstance); this.sessions = new Sessions(this.axiosInstance, jwkConfig); this.oauth = new OAuth(this.axiosInstance); this.totps = new TOTPs(this.axiosInstance); } } exports.Streambird = Streambird; exports.StreambirdApiError = StreambirdApiError; exports.StreambirdError = StreambirdError; exports.Users = Users; //# sourceMappingURL=index.js.map