@shipengine/connect
Version:
The official developer tooling for building ShipEngine connect apps
103 lines • 5.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createGetRatesHandler = void 0;
const tslib_1 = require("tslib");
const path_1 = require("path");
const fs_1 = require("fs");
const connect_carrier_api_1 = require("@shipengine/connect-carrier-api");
const create_dynamic_carrier_1 = tslib_1.__importDefault(require("./create-dynamic-carrier"));
const base_rate_context_1 = require("./base-rate-context");
const runNativeRatingLocally = process.env.LOCAL_NATIVE_RATING
? process.env.LOCAL_NATIVE_RATING !== 'false'
: process.env.NODE_ENV !== 'production';
const createImplementation = (basePath) => {
const logicPath = (0, path_1.join)(basePath, connect_carrier_api_1.rateLogicName);
if (!(0, fs_1.existsSync)(logicPath)) {
return undefined;
}
const rawImplementation = (0, fs_1.readFileSync)(logicPath, 'utf8');
return (0, create_dynamic_carrier_1.default)(rawImplementation);
};
const createNativeRatingHandler = (carrier, getRatesHandler) => {
if (!carrier.NativeRating) {
console.log('Carrier does NOT have a Native Rating property in its config');
return getRatesHandler;
}
const basePath = carrier.NativeRating.Path;
if (!basePath) {
console.log('Carrier does NOT have a Native Rating path set');
return getRatesHandler;
}
if (!(0, fs_1.existsSync)(basePath)) {
console.log(`Path for Native Rating '${basePath}' does not exist`);
return getRatesHandler;
}
try {
const buildContext = (0, base_rate_context_1.createContextBuilder)(basePath);
const defaultImplementation = createImplementation(basePath);
const rateCards = Object.fromEntries(carrier.NativeRating.RateCards?.map((card) => {
const impl = createImplementation((0, path_1.join)(basePath, card.Id)) || defaultImplementation;
if (!impl) {
throw new Error(`Cannot find default nor card specific rating logic for rate card ${card.Id}`);
}
const context = buildContext(card);
const rateShipments = (req) => impl.rateShipments(context, [{ id: 'rate-request', shipment: req }]);
return [card.Id, rateShipments];
}) || []);
const defaultRateCardId = carrier.NativeRating.DefaultRateCardId;
const defaultRateCard = defaultRateCardId ? rateCards[defaultRateCardId] : undefined;
if (defaultRateCardId && !defaultRateCard) {
throw new Error(`Could not find a rate card definition for default rate card ${defaultRateCardId}`);
}
return async (req) => {
const rateCardId = req.metadata?.['native-rating-rate-card'];
// If a rate card isn't specified and we don't have a default rate card, use the GetRates implementation
if (!rateCardId && !defaultRateCard) {
return getRatesHandler?.(req);
}
const rateShipments = rateCardId ? rateCards[rateCardId] : defaultRateCard;
if (!rateShipments) {
throw new Error(`Could not find rate card ${rateCardId}`);
}
const results = await rateShipments(req);
const rateResult = results.find((x) => x.id === 'rate-request');
if (!rateResult) {
throw new Error(`Could not find rate for request 'rate-request'. Ensure you return the request id with your rates.`);
}
return {
rates: rateResult.rates,
metadata: {
error: rateResult.error,
},
};
};
}
catch (err) {
console.warn(err?.message);
return getRatesHandler;
}
};
const createGetRatesHandler = (definition) => {
if (!runNativeRatingLocally) {
return definition.GetRates;
}
const nativeRatingCarriers = definition.Metadata.Carriers.map((x) => ({
apiCode: x.ApiCode || x.Name,
handler: createNativeRatingHandler(x, definition.GetRates),
})).filter((x) => x.handler !== undefined);
// If there aren't any native rating implementations found, return whatever is defined in the definition
// This is what should happen in production because the Kong gateway should route any rate requests for NR
// carriers directly to the Native Rating service
if (nativeRatingCarriers.length === 0) {
return definition.GetRates;
}
// If there's only a single carrier defined, just return the Native Rating handler so that we can avoid
// requiring the "carrier_code" property be set on the "metadata" object when testing
if (definition.Metadata.Carriers.length === 1) {
return nativeRatingCarriers[0].handler;
}
const implementationLookup = Object.fromEntries(nativeRatingCarriers.map((x) => [x.apiCode, x.handler]));
return (req) => implementationLookup[req.metadata?.['carrier_code']]?.(req);
};
exports.createGetRatesHandler = createGetRatesHandler;
//# sourceMappingURL=create-get-rates-handler.js.map