import Address from '../models/address';
import ApiKey from '../models/api_key';
import Batch from '../models/batch';
import Brand from '../models/brand';
import CarrierAccount from '../models/carrier_account';
import CarrierType from '../models/carrier_type';
import Claim from '../models/claim';
import CustomsInfo from '../models/customs_info';
import CustomsItem from '../models/customs_item';
import EasyPostObject from '../models/easypost_object';
import EndShipper from '../models/end_shipper';
import Event from '../models/event';
import Form from '../models/form';
import Insurance from '../models/insurance';
import Order from '../models/order';
import Parcel from '../models/parcel';
import Payload from '../models/payload';
import Pickup from '../models/pickup';
import PickupRate from '../models/pickup_rate';
import PostageLabel from '../models/postage_label';
import Rate from '../models/rate';
import Refund from '../models/refund';
import Report from '../models/report';
import ScanForm from '../models/scan_form';
import Shipment from '../models/shipment';
import Tracker from '../models/tracker';
import User from '../models/user';
import Webhook from '../models/webhook';
import EndOfPaginationError from '../errors/general/end_of_pagination_error';
/**
* A map of EasyPost object ID prefixes to their associated class names.
*/
const EASYPOST_OBJECT_ID_PREFIX_TO_CLASS_NAME_MAP = {
adr: Address,
ak: ApiKey,
batch: Batch,
brd: Brand,
ca: CarrierAccount,
cfrep: Report,
clm: Claim,
cstinfo: CustomsInfo,
cstitem: CustomsItem,
es: EndShipper,
evt: Event,
hook: Webhook,
ins: Insurance,
order: Order,
payload: Payload,
pickup: Pickup,
pickuprate: PickupRate,
pl: PostageLabel,
plrep: Report,
prcl: Parcel,
rate: Rate,
refrep: Report,
rfnd: Refund,
sf: ScanForm,
shp: Shipment,
shpinvrep: Report,
shprep: Report,
trk: Tracker,
trkrep: Report,
user: User,
};
/**
* A map of EasyPost services available to the client.
*/
const RESOURCES = {
Address,
ApiKey,
Batch,
Brand,
CarrierAccount,
CarrierType,
CustomsInfo,
CustomsItem,
EasyPostObject,
EndShipper,
Event,
Form,
Insurance,
Order,
Parcel,
Payload,
Pickup,
PickupRate,
PostageLabel,
Rate,
Refund,
Report,
ScanForm,
Shipment,
Tracker,
User,
Webhook,
};
export default (easypostClient) =>
/**
* The base class for all EasyPost client library services.
* @param {EasyPostClient} easypostClient The {@link EasyPostClient} instance to use for API calls.
*/
class BaseService {
/**
* Converts a JSON response and all its nested elements to associated {@link EasyPostObject}-based class instances.
* @internal
* @param {*} response The JSON response to convert (usually a `Map` or `Array`).
* @param {*} params The parameters passed when fetching the response
* @returns {*} An {@link EasyPostObject}-based class instance or an `Array` of {@link EasyPostObject}-based class instances.
*/
static _convertToEasyPostObject(response, params) {
if (Array.isArray(response)) {
return response.map((value) => {
if (typeof value === 'object') {
return this._convertToEasyPostObject(value, params);
}
return value;
});
}
if (typeof response === 'object' && response !== null) {
let classObject;
if (RESOURCES[response.object] !== undefined) {
classObject = new RESOURCES[response.object]();
} else if (
response.id !== undefined &&
EASYPOST_OBJECT_ID_PREFIX_TO_CLASS_NAME_MAP[
response.id.substr(0, response.id.indexOf('_'))
] !== undefined
) {
const className = response.id.substr(0, response.id.indexOf('_'));
classObject = new EASYPOST_OBJECT_ID_PREFIX_TO_CLASS_NAME_MAP[className]();
} else {
classObject = new EasyPostObject();
}
Object.keys(response).forEach((key) => {
classObject[key] = this._convertToEasyPostObject(response[key], params);
});
classObject._params = params;
return classObject;
}
return response;
}
/**
* Creates an EasyPost Object via the API.
* @internal
* @param {string} url The URL to send the API request to.
* @param {Object} params The parameters to send with the API request.
* @returns {EasyPostObject|Promise<never>} The created {@link EasyPostObject}-based class instance, or a `Promise` that rejects with an error.
*/
static async _create(url, params) {
try {
const response = await easypostClient._post(url, params);
return this._convertToEasyPostObject(response.body, params);
} catch (e) {
return Promise.reject(e);
}
}
/**
* Retrieve a list of records from the API.
* @internal
* @param {string} url The URL to send the API request to.
* @param {Object} [params] The parameters to send with the API request.
* @returns {EasyPostObject|EasyPostObject[]|Promise<never>} The retrieved {@link EasyPostObject}-based class instance(s), or a `Promise` that rejects with an error.
*/
static async _all(url, params = {}) {
try {
// eslint-disable-next-line no-param-reassign
const response = await easypostClient._get(url, params);
return this._convertToEasyPostObject(response.body, params);
} catch (e) {
return Promise.reject(e);
}
}
/**
* Retrieve a record from the API.
* @internal
* @param {string} url The URL to send the API request to.
* @returns {EasyPostObject|Promise<never>} The retrieved {@link EasyPostObject}-based class instance, or a `Promise` that rejects with an error.
*/
static async _retrieve(url) {
try {
const response = await easypostClient._get(url);
return this._convertToEasyPostObject(response.body);
} catch (e) {
return Promise.reject(e);
}
}
/**
* Retrieve the next page of specific collection of object
* @internal
* @param {string} url The URL to send the API request to.
* @param {Object} collection The collection of a specific object.
* @param {Number} pageSize The number of records to return on each page.
* @param {Object} optionalParams The optional param for additional value in the query string.
* @returns {EasyPostObject|Promise<never>} The retrieved {@link EasyPostObject}-based class instance, or a `Promise` that rejects with an error.
* TODO: Implement this function in EndShippers and Batches once the API supports them properly.
*/
static async _getNextPage(url, key, collection, pageSize = null, optionalParams = {}) {
const collectionArray = collection[key];
if (collectionArray == undefined || collectionArray.length == 0 || !collection.has_more) {
throw new EndOfPaginationError();
}
const defaultParams = collection._params ?? collectionArray[0]._params ?? {};
const params = {
...defaultParams,
page_size: defaultParams.page_size ?? pageSize,
before_id: collectionArray[collectionArray.length - 1].id,
...optionalParams,
};
const response = await this._all(url, params);
if (response == undefined || response[key].length == 0) {
throw new EndOfPaginationError();
}
return response;
}
};