@heuristical/trackit
Version:
This module allows you to connect to many shipping carriers like UPS and FedEx and download tracking data for your packages in a common schema
190 lines • 8.86 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FedexClient = void 0;
const xml2js_1 = require("xml2js");
const underscore_1 = require("underscore");
const moment_timezone_1 = __importDefault(require("moment-timezone"));
const shipper_1 = require("./shipper");
class FedexClient extends shipper_1.ShipperClient {
constructor(options) {
super();
this.STATUS_MAP = new Map([
['AA', shipper_1.STATUS_TYPES.EN_ROUTE],
['AD', shipper_1.STATUS_TYPES.EN_ROUTE],
['AF', shipper_1.STATUS_TYPES.EN_ROUTE],
['AP', shipper_1.STATUS_TYPES.SHIPPING],
['EO', shipper_1.STATUS_TYPES.EN_ROUTE],
['EP', shipper_1.STATUS_TYPES.SHIPPING],
['FD', shipper_1.STATUS_TYPES.EN_ROUTE],
['HL', shipper_1.STATUS_TYPES.DELIVERED],
['IT', shipper_1.STATUS_TYPES.EN_ROUTE],
['LO', shipper_1.STATUS_TYPES.EN_ROUTE],
['OC', shipper_1.STATUS_TYPES.SHIPPING],
['DL', shipper_1.STATUS_TYPES.DELIVERED],
['DP', shipper_1.STATUS_TYPES.EN_ROUTE],
['DS', shipper_1.STATUS_TYPES.EN_ROUTE],
['ED', shipper_1.STATUS_TYPES.OUT_FOR_DELIVERY],
['OD', shipper_1.STATUS_TYPES.OUT_FOR_DELIVERY],
['PF', shipper_1.STATUS_TYPES.EN_ROUTE],
['PL', shipper_1.STATUS_TYPES.EN_ROUTE],
['PU', shipper_1.STATUS_TYPES.EN_ROUTE],
['SF', shipper_1.STATUS_TYPES.EN_ROUTE],
['AR', shipper_1.STATUS_TYPES.EN_ROUTE],
['CD', shipper_1.STATUS_TYPES.EN_ROUTE],
['CC', shipper_1.STATUS_TYPES.EN_ROUTE],
['DE', shipper_1.STATUS_TYPES.DELAYED],
['CA', shipper_1.STATUS_TYPES.DELAYED],
['CH', shipper_1.STATUS_TYPES.DELAYED],
['DY', shipper_1.STATUS_TYPES.DELAYED],
['SE', shipper_1.STATUS_TYPES.DELAYED],
['AX', shipper_1.STATUS_TYPES.EN_ROUTE],
['OF', shipper_1.STATUS_TYPES.EN_ROUTE],
['RR', shipper_1.STATUS_TYPES.EN_ROUTE],
['OX', shipper_1.STATUS_TYPES.EN_ROUTE],
['CP', shipper_1.STATUS_TYPES.EN_ROUTE]
]);
this.options = options;
this.parser = new xml2js_1.Parser();
this.builder = new xml2js_1.Builder({ renderOpts: { pretty: false } });
}
get key() { return this.options.key; }
;
get password() { return this.options.password; }
;
get account() { return this.options.account; }
;
get meter() { return this.options.meter; }
;
generateRequest(trk, reference) {
if (reference == null) {
reference = 'n/a';
}
return this.builder.buildObject({
'ns:TrackRequest': {
$: {
'xmlns:ns': 'http://fedex.com/ws/track/v5',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation': 'http://fedex.com/ws/track/v4 TrackService_v4.xsd'
},
'ns:WebAuthenticationDetail': {
'ns:UserCredential': {
'ns:Key': this.key,
'ns:Password': this.password
}
},
'ns:ClientDetail': {
'ns:AccountNumber': this.account,
'ns:MeterNumber': this.meter
},
'ns:TransactionDetail': {
'ns:CustomerTransactionId': reference
},
'ns:Version': {
'ns:ServiceId': 'trck',
'ns:Major': 5,
'ns:Intermediate': 0,
'ns:Minor': 0
},
'ns:PackageIdentifier': {
'ns:Value': trk,
'ns:Type': 'TRACKING_NUMBER_OR_DOORTAG'
},
'ns:IncludeDetailedScans': true
}
});
}
validateResponse(response, cb) {
function handleResponse(xmlErr, trackResult) {
var _a, _b;
if ((xmlErr != null) || (trackResult == null)) {
return cb(xmlErr);
}
const notifications = trackResult.TrackReply != null ? trackResult.TrackReply.Notifications : undefined;
const success = underscore_1.find(notifications, notice => { var _a; return ((_a = notice === null || notice === void 0 ? void 0 : notice.Code) === null || _a === void 0 ? void 0 : _a[0]) === '0'; });
if (!success) {
return cb(notifications || 'invalid reply');
}
return cb(null, (_b = (_a = trackResult === null || trackResult === void 0 ? void 0 : trackResult.TrackReply) === null || _a === void 0 ? void 0 : _a.TrackDetails) === null || _b === void 0 ? void 0 : _b[0]);
}
this.parser.reset();
return this.parser.parseString(response, handleResponse);
}
presentAddress(address) {
if (address == null) {
return;
}
let city = address.City != null ? address.City[0] : undefined;
if (city != null) {
city = city.replace('FEDEX SMARTPOST ', '');
}
const stateCode = address.StateOrProvinceCode != null ? address.StateOrProvinceCode[0] : undefined;
const countryCode = address.CountryCode != null ? address.CountryCode[0] : undefined;
const postalCode = address.PostalCode != null ? address.PostalCode[0] : undefined;
return this.presentLocation({ city, stateCode, countryCode, postalCode });
}
getStatus(shipment) {
var _a;
const statusCode = (_a = shipment === null || shipment === void 0 ? void 0 : shipment.StatusCode) === null || _a === void 0 ? void 0 : _a[0];
if (statusCode == null) {
return;
}
return this.STATUS_MAP.has(statusCode) ? this.STATUS_MAP.get(statusCode) : shipper_1.STATUS_TYPES.UNKNOWN;
}
getActivitiesAndStatus(shipment) {
const activities = [];
for (const rawActivity of ((shipment === null || shipment === void 0 ? void 0 : shipment.Events) || [])) {
let datetime, timestamp;
const location = this.presentAddress(rawActivity.Address != null ? rawActivity.Address[0] : undefined);
const rawTimestamp = rawActivity.Timestamp != null ? rawActivity.Timestamp[0] : undefined;
if (rawTimestamp != null) {
const eventTime = moment_timezone_1.default(rawTimestamp);
timestamp = eventTime.toDate();
datetime = rawTimestamp.slice(0, 19);
}
const details = rawActivity.EventDescription != null ? rawActivity.EventDescription[0] : undefined;
if ((details != null) && (timestamp != null)) {
const activity = { timestamp, datetime, location, details };
activities.push(activity);
}
}
return { activities, status: this.getStatus(shipment) };
}
getEta(shipment) {
var _a;
const ts = (_a = shipment === null || shipment === void 0 ? void 0 : shipment.EstimatedDeliveryTimestamp) === null || _a === void 0 ? void 0 : _a[0];
if (ts == null) {
return;
}
return moment_timezone_1.default(`${ts.slice(0, 19)}Z`).toDate();
}
getService(shipment) {
return (shipment === null || shipment === void 0 ? void 0 : shipment.ServiceInfo) ? shipment === null || shipment === void 0 ? void 0 : shipment.ServiceInfo[0] : undefined;
}
getWeight(shipment) {
var _a, _b, _c;
const weightData = (_a = shipment === null || shipment === void 0 ? void 0 : shipment.PackageWeight) === null || _a === void 0 ? void 0 : _a[0];
if (weightData == null) {
return;
}
const units = (_b = weightData === null || weightData === void 0 ? void 0 : weightData.Units) === null || _b === void 0 ? void 0 : _b[0];
const value = (_c = weightData === null || weightData === void 0 ? void 0 : weightData.Value) === null || _c === void 0 ? void 0 : _c[0];
if ((units != null) && (value != null)) {
return `${value} ${units}`;
}
}
getDestination(shipment) {
return this.presentAddress(shipment.DestinationAddress != null ? shipment.DestinationAddress[0] : undefined);
}
requestOptions({ trackingNumber, reference }) {
return {
method: 'POST',
uri: 'https://ws.fedex.com/xml',
body: this.generateRequest(trackingNumber, reference)
};
}
}
exports.FedexClient = FedexClient;
//# sourceMappingURL=fedex.js.map