@jorsek/ezd-client
Version:
189 lines (163 loc) • 6.24 kB
text/typescript
import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
const rateLimit = require("axios-rate-limit");
import { parseCookies } from "nookies";
import "reflect-metadata";
import { getUserTokens } from "./browser_auth/auth";
import { Config } from "./Config";
import { Content } from "./resources/Content";
import { Contribute } from "./resources/Contribute";
import { Search } from "./resources/Search";
import { API_Config } from "./Types";
export interface IClientArgs {
org: string;
token: string;
rootMapId: string;
timeout?: number;
scheme?: string;
hostname?: string;
env?: string;
content_root?: string;
loginRedirect?: string;
loginRequired?: boolean;
interceptors?: Array<(axios: AxiosInstance) => void>;
rateLimit?: {
maxRequests?: number;
maxRPS: number;
}
}
const EZD_CLIENT_VERSION = "0.1.0";
const API_VERSION = "v1";
export default class Client {
public readonly base_url: string;
public content_axios: AxiosInstance;
public contribute_axios: AxiosInstance;
public content: Content;
public search: Search;
public contribute: Contribute;
public content_service_token: string;
public initial_args: IClientArgs;
constructor(args: IClientArgs) {
const {
org,
token,
rootMapId,
timeout = 3000,
scheme = "https://",
hostname = "content.easydita.com",
env = "latest",
content_root= "content",
interceptors = [],
rateLimit: rateLimitConfig = {
maxRPS: 5,
maxRequests: 2
}
} = args;
this.initial_args = args;
if (!org) {
throw new Error("easyDITA org not set");
}
if (!token) {
throw new Error("easyDITA token not set");
}
if (!rootMapId) {
throw new Error("easyDITA rootMapId not set");
}
this.base_url = `${scheme}${hostname}/org/${org}/env/${env}/map/${rootMapId}/`;
this.content_service_token = token;
const config: AxiosRequestConfig = {
baseURL: this.base_url,
timeout,
// withCredentials: true,
headers: {
// "X-EZD-Client": "JS/" + EZD_CLIENT_VERSION,
},
};
this.content_axios = rateLimit(Axios.create(config), rateLimitConfig);
this.content_axios.interceptors.request.use(intercepted_config => {
if (!intercepted_config.params) {
intercepted_config.params = {};
}
// intercepted_config.headers["Content-Type"] = "application/text";
intercepted_config.params.token = this.user_token() ? this.user_token() : this.content_service_token;
intercepted_config.params.link_root = content_root;
return intercepted_config;
});
interceptors.forEach(interceptor => interceptor(this.content_axios));
this.contribute_axios = Axios.create(config);
this.contribute_axios.interceptors.request.use(intercepted_config => {
if (!intercepted_config.params) {
intercepted_config.params = {};
}
intercepted_config.params.rootMapId = rootMapId;
intercepted_config.params.token = this.user_token();
return intercepted_config;
});
const portal_config = new Config(this.content_axios);
this.content = new Content({ axios: this.content_axios, config: portal_config });
this.search = new Search({ axios: this.content_axios, rootMapId, config: portal_config });
this.contribute = new Contribute({ axios: this.contribute_axios, config: portal_config });
}
public iframe_url() {
let s = this.base_url;
s = s.replace("https://", "");
s = s.replace("http://", "");
return s;
}
public user_token() {
if (typeof window !== "undefined") {
return getUserTokens().idToken;
} else {
return null;
}
}
public async login() {
// create an ezd session so the editor will load without asking user to login first
const response = await this.content_axios.post("/auth");
}
public async prepare(args): Promise<Client> {
const redirect_path = args.req ?
`${args.req.protocol}://${args.req.get("host")}${args.req.path}` :
`${window.location.protocol}//${window.location.host}${window.location.pathname}`;
const cookies = args.req ? args.req.cookies : parseCookies();
const token = (args.req && args.req.query.portal_auth_token) || (cookies && cookies.portal_auth_token); // Make sure to keep this order -- query param overrides cookie
const requireLogin = () => {
const destination = `${this.initial_args.loginRedirect}?redirect_to=${encodeURI(redirect_path)}`;
if (args.res) {
return args.res.redirect(destination);
} else {
window.location.href = destination;
return;
}
};
if (!token) {
if (this.initial_args.loginRequired) {
return requireLogin();
} else {
return this;
}
}
try {
const client = new Client({
...this.initial_args,
token,
});
await client.content.getSections();
if (args.req && args.req.query.portal_auth_token) {
args.res.cookie("portal_auth_token", args.req.query.portal_auth_token, {path: "/", domain: args.req.hostname});
}
return client;
} catch (e) {
if (e.response && e.response.status === 403) {
if (args.res) {
args.res.clearCookie("portal_auth_token");
}
if (this.initial_args.loginRedirect) {
return requireLogin();
}
return new Client(this.initial_args);
} else {
throw e;
}
}
}
}