@foxy.io/sdk
Version:
Universal SDK for a full server-side and a limited in-browser access to Foxy hAPI.
177 lines (176 loc) • 8.11 kB
JavaScript
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());
});
};
import { Request, fetch } from 'cross-fetch';
import { v8n } from '../core/v8n.js';
import * as Core from '../core/index.js';
/**
* Customer API for adding custom functionality to websites and web apps with our Customer Portal.
*
* **IMPORTANT**: this client is not compatible with the beta version of Customer API.
* If you're still on beta, please consider updating your code to the latest stable version.
* You can use @foxy.io/sdk prior to 1.0.0-beta.15 or a custom API client until you transition.
*/
export class API extends Core.API {
constructor(params) {
super(Object.assign(Object.assign({}, params), { fetch: (...args) => this.__fetch(...args) }));
}
/**
* Creates a Customer Portal session for a customer with the given credentials.
* Incorrect email and password will trigger `Core.API.AuthError` with code `UNAUTHORIZED`.
*
* @param credentials Customer email and password (one-time code).
*/
signIn(credentials) {
return __awaiter(this, void 0, void 0, function* () {
API.v8n.credentials.check(credentials);
const response = yield this.fetch(new URL('./authenticate', this.base).toString(), {
body: JSON.stringify(credentials),
method: 'POST',
});
if (response.ok) {
const session = yield response.json();
const storedSession = Object.assign(Object.assign({}, session), { date_created: new Date().toISOString() });
this.storage.setItem(API.SESSION, JSON.stringify(storedSession));
}
else {
const code = response.status === 401 ? 'UNAUTHORIZED' : 'UNKNOWN';
throw new Core.API.AuthError({ code });
}
});
}
/**
* Creates a new customer account with the given credentials.
* If the email is already taken, `Core.API.AuthError` with code `UNAVAILABLE` will be thrown.
* If customer registration is disabled, `Core.API.AuthError` with code `UNAUTHORIZED` will be thrown.
* If the provided form data is invalid (e.g. captcha is expired), `Core.API.AuthError` with code `INVALID_FORM` will be thrown.
*
* @param params Customer information.
*/
signUp(params) {
return __awaiter(this, void 0, void 0, function* () {
API.v8n.signUpParams.check(params);
const url = new URL('./sign_up', this.base);
const response = yield this.fetch(url.toString(), {
method: 'POST',
body: JSON.stringify(params),
});
if (!response.ok) {
if (response.status === 400)
throw new Core.API.AuthError({ code: 'INVALID_FORM' });
if (response.status === 401)
throw new Core.API.AuthError({ code: 'UNAUTHORIZED' });
if (response.status === 403)
throw new Core.API.AuthError({ code: 'UNAVAILABLE' });
throw new Core.API.AuthError({ code: 'UNKNOWN' });
}
});
}
/**
* Initiates password reset for a customer with the given email.
* If such customer exists, they will receive an email from Foxy with further instructions.
*
* @param params Password reset parameters.
* @param params.email Customer email.
*/
sendPasswordResetEmail(params) {
return __awaiter(this, void 0, void 0, function* () {
API.v8n.email.check(params.email);
const response = yield this.fetch(new URL('./forgot_password', this.base).toString(), {
body: JSON.stringify(params),
method: 'POST',
});
if (!response.ok)
throw new Core.API.AuthError({ code: 'UNKNOWN' });
});
}
/** Destroys current session and clears local session data. */
signOut() {
return __awaiter(this, void 0, void 0, function* () {
const response = yield this.fetch(new URL('./authenticate', this.base).toString(), { method: 'DELETE' });
if (!response.ok)
throw new Core.API.AuthError({ code: 'UNKNOWN' });
this.storage.clear();
this.cache.clear();
});
}
/**
* When logged in with a temporary password, this property getter will return `true`.
* Will return `false` if password reset is not required or if the session has not been
* initiated, or if the session was initiated before the introduction of this feature.
*
* @returns {boolean} Password reset requirement.
*/
get usesTemporaryPassword() {
const session = this.storage.getItem(API.SESSION);
if (session)
return !!JSON.parse(session).force_password_reset;
return false;
}
set usesTemporaryPassword(value) {
API.v8n.boolean.check(value);
const session = this.storage.getItem(API.SESSION);
if (session) {
const storedSession = JSON.parse(session);
storedSession.force_password_reset = value;
this.storage.setItem(API.SESSION, JSON.stringify(storedSession));
}
}
__fetch(input, init) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let session = JSON.parse((_a = this.storage.getItem(API.SESSION)) !== null && _a !== void 0 ? _a : 'null');
const request = new Request(input, init);
if (session !== null) {
const expiresAt = new Date(session.date_created).getTime() + session.expires_in * 1000;
const now = Date.now();
if (expiresAt < now) {
this.console.info('Session has expired, signing out.');
this.storage.clear();
this.cache.clear();
session = null;
}
else {
request.headers.set('Authorization', `Bearer ${session.session_token}`);
}
}
request.headers.set('Content-Type', 'application/json');
request.headers.set('FOXY-API-VERSION', '1');
this.console.trace(`${request.method} ${request.url}`);
const response = yield fetch(request);
if (session && response.ok) {
const refreshedSession = Object.assign(Object.assign({}, session), { date_created: new Date().toISOString() });
this.storage.setItem(API.SESSION, JSON.stringify(refreshedSession));
}
return response;
});
}
}
/** Storage key for session data. */
API.SESSION = 'session';
/** Validators for the method arguments in this class (internal). */
API.v8n = Object.assign({}, Core.API.v8n, {
signUpParams: v8n().schema({
verification: v8n().schema({
token: v8n().string(),
type: v8n().passesAnyOf(v8n().exact('hcaptcha')),
}),
first_name: v8n().optional(v8n().string().maxLength(50)),
last_name: v8n().optional(v8n().string().maxLength(50)),
password: v8n().string().maxLength(50),
email: v8n().string().maxLength(100),
}),
credentials: v8n().schema({
email: v8n().string(),
newPassword: v8n().optional(v8n().string()),
password: v8n().string(),
}),
boolean: v8n().boolean(),
email: v8n().string(),
});