@shopana/novaposhta-mcp-server
Version:
MCP Server for Nova Poshta API integration with AI assistants
1,439 lines (1,423 loc) • 77.6 kB
JavaScript
#!/usr/bin/env node
// src/config.ts
function loadConfig(overrides = {}) {
const envApiKey = process.env.NOVA_POSHTA_API_KEY || process.env.NP_API_KEY;
const apiKey = overrides.apiKey ?? envApiKey;
return {
apiKey,
baseUrl: overrides.baseUrl ?? process.env.NOVA_POSHTA_BASE_URL ?? "https://api.novaposhta.ua/v2.0/json/",
logLevel: overrides.logLevel ?? process.env.LOG_LEVEL ?? "info",
timeout: overrides.timeout ?? Number.parseInt(process.env.TIMEOUT ?? "30000", 10)
};
}
// src/server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import {
CallToolRequestSchema,
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
isInitializeRequest
} from "@modelcontextprotocol/sdk/types.js";
// node_modules/@shopana/novaposhta-api-client/dist/core/client.js
function toHttpTransport(ctx) {
return {
async request(request) {
const { apiKey, ...rest } = request;
const finalRequest = {
...rest,
...apiKey ? { apiKey } : {}
};
const response = await ctx.transport({
url: ctx.baseUrl,
body: finalRequest
});
return response.data;
}
};
}
function createClient(ctx) {
const self = {};
self.use = function use(service) {
if (typeof service.attach === "function") {
service.attach(ctx);
}
const ns = service.namespace;
if (!ns || typeof ns !== "string") {
throw new Error('Service must define a string "namespace" property');
}
if (ns in self) {
throw new Error(`Namespace already installed on client: ${ns}`);
}
self[ns] = service;
return self;
};
return self;
}
// node_modules/@shopana/novaposhta-api-client/dist/types/enums.js
var NovaPoshtaModel;
(function(NovaPoshtaModel2) {
NovaPoshtaModel2["TrackingDocument"] = "TrackingDocumentGeneral";
NovaPoshtaModel2["InternetDocument"] = "InternetDocumentGeneral";
NovaPoshtaModel2["Common"] = "CommonGeneral";
NovaPoshtaModel2["Address"] = "AddressGeneral";
NovaPoshtaModel2["Counterparty"] = "CounterpartyGeneral";
NovaPoshtaModel2["ContactPerson"] = "ContactPersonGeneral";
NovaPoshtaModel2["ScanSheet"] = "ScanSheetGeneral";
NovaPoshtaModel2["AdditionalService"] = "AdditionalServiceGeneral";
})(NovaPoshtaModel || (NovaPoshtaModel = {}));
var NovaPoshtaMethod;
(function(NovaPoshtaMethod2) {
NovaPoshtaMethod2["GetStatusDocuments"] = "getStatusDocuments";
NovaPoshtaMethod2["GetDocumentsEWMovement"] = "getDocumentsEWMovement";
NovaPoshtaMethod2["Save"] = "save";
NovaPoshtaMethod2["Update"] = "update";
NovaPoshtaMethod2["Delete"] = "delete";
NovaPoshtaMethod2["GetDocumentPrice"] = "getDocumentPrice";
NovaPoshtaMethod2["GetDocumentDeliveryDate"] = "getDocumentDeliveryDate";
NovaPoshtaMethod2["GetDocumentList"] = "getDocumentList";
NovaPoshtaMethod2["GenerateReport"] = "generateReport";
NovaPoshtaMethod2["GetCargoTypes"] = "getCargoTypes";
NovaPoshtaMethod2["GetBackwardDeliveryCargoTypes"] = "getBackwardDeliveryCargoTypes";
NovaPoshtaMethod2["GetPalletsList"] = "getPalletsList";
NovaPoshtaMethod2["GetTypesOfPayersForRedelivery"] = "getTypesOfPayersForRedelivery";
NovaPoshtaMethod2["GetPackList"] = "getPackList";
NovaPoshtaMethod2["GetTiresWheelsList"] = "getTiresWheelsList";
NovaPoshtaMethod2["GetCargoDescriptionList"] = "getCargoDescriptionList";
NovaPoshtaMethod2["GetMessageCodeText"] = "getMessageCodeText";
NovaPoshtaMethod2["GetServiceTypes"] = "getServiceTypes";
NovaPoshtaMethod2["GetOwnershipFormsList"] = "getOwnershipFormsList";
NovaPoshtaMethod2["GetTimeIntervals"] = "getTimeIntervals";
NovaPoshtaMethod2["GetPickupTimeIntervals"] = "getPickupTimeIntervals";
NovaPoshtaMethod2["GetSettlements"] = "getSettlements";
NovaPoshtaMethod2["GetCities"] = "getCities";
NovaPoshtaMethod2["GetAreas"] = "getAreas";
NovaPoshtaMethod2["GetWarehouses"] = "getWarehouses";
NovaPoshtaMethod2["GetWarehouseTypes"] = "getWarehouseTypes";
NovaPoshtaMethod2["GetStreet"] = "getStreet";
NovaPoshtaMethod2["SearchSettlements"] = "searchSettlements";
NovaPoshtaMethod2["SearchSettlementStreets"] = "searchSettlementStreets";
NovaPoshtaMethod2["GetSettlementAreas"] = "getSettlementAreas";
NovaPoshtaMethod2["GetSettlementCountryRegion"] = "getSettlementCountryRegion";
})(NovaPoshtaMethod || (NovaPoshtaMethod = {}));
var PaymentMethod;
(function(PaymentMethod2) {
PaymentMethod2["Cash"] = "Cash";
PaymentMethod2["NonCash"] = "NonCash";
})(PaymentMethod || (PaymentMethod = {}));
var CargoType;
(function(CargoType2) {
CargoType2["Parcel"] = "Parcel";
CargoType2["Cargo"] = "Cargo";
CargoType2["Documents"] = "Documents";
CargoType2["TiresWheels"] = "TiresWheels";
CargoType2["Pallet"] = "Pallet";
})(CargoType || (CargoType = {}));
var ServiceType;
(function(ServiceType2) {
ServiceType2["DoorsDoors"] = "DoorsDoors";
ServiceType2["DoorsWarehouse"] = "DoorsWarehouse";
ServiceType2["WarehouseWarehouse"] = "WarehouseWarehouse";
ServiceType2["WarehouseDoors"] = "WarehouseDoors";
})(ServiceType || (ServiceType = {}));
var PayerType;
(function(PayerType2) {
PayerType2["Sender"] = "Sender";
PayerType2["Recipient"] = "Recipient";
PayerType2["ThirdPerson"] = "ThirdPerson";
})(PayerType || (PayerType = {}));
var DeliveryStatus;
(function(DeliveryStatus2) {
DeliveryStatus2[DeliveryStatus2["CreatedBySender"] = 1] = "CreatedBySender";
DeliveryStatus2[DeliveryStatus2["Deleted"] = 2] = "Deleted";
DeliveryStatus2[DeliveryStatus2["NotFound"] = 3] = "NotFound";
DeliveryStatus2[DeliveryStatus2["InSenderCityInterregional"] = 4] = "InSenderCityInterregional";
DeliveryStatus2[DeliveryStatus2["InSenderCityLocal"] = 41] = "InSenderCityLocal";
DeliveryStatus2[DeliveryStatus2["InTransitToRecipientCity"] = 5] = "InTransitToRecipientCity";
DeliveryStatus2[DeliveryStatus2["InRecipientCityAwaitingDelivery"] = 6] = "InRecipientCityAwaitingDelivery";
DeliveryStatus2[DeliveryStatus2["ArrivedAtWarehouse"] = 7] = "ArrivedAtWarehouse";
DeliveryStatus2[DeliveryStatus2["ArrivedAtPostomat"] = 8] = "ArrivedAtPostomat";
DeliveryStatus2[DeliveryStatus2["Received"] = 9] = "Received";
DeliveryStatus2[DeliveryStatus2["ReceivedAwaitingMoneyTransfer"] = 10] = "ReceivedAwaitingMoneyTransfer";
DeliveryStatus2[DeliveryStatus2["ReceivedAndMoneyTransferred"] = 11] = "ReceivedAndMoneyTransferred";
DeliveryStatus2[DeliveryStatus2["BeingPacked"] = 12] = "BeingPacked";
DeliveryStatus2[DeliveryStatus2["OnTheWayToRecipient"] = 101] = "OnTheWayToRecipient";
DeliveryStatus2[DeliveryStatus2["RefusedByRecipientReturnCreated"] = 102] = "RefusedByRecipientReturnCreated";
DeliveryStatus2[DeliveryStatus2["RefusedByRecipient"] = 103] = "RefusedByRecipient";
DeliveryStatus2[DeliveryStatus2["AddressChanged"] = 104] = "AddressChanged";
DeliveryStatus2[DeliveryStatus2["StorageTerminated"] = 105] = "StorageTerminated";
DeliveryStatus2[DeliveryStatus2["ReturnWaybillCreated"] = 106] = "ReturnWaybillCreated";
DeliveryStatus2[DeliveryStatus2["FailedDeliveryAttempt"] = 111] = "FailedDeliveryAttempt";
DeliveryStatus2[DeliveryStatus2["DeliveryRescheduledByRecipient"] = 112] = "DeliveryRescheduledByRecipient";
})(DeliveryStatus || (DeliveryStatus = {}));
var WarehouseType;
(function(WarehouseType2) {
WarehouseType2["Branch"] = "Branch";
WarehouseType2["Postomat"] = "Postomat";
WarehouseType2["PickupPoint"] = "PickupPoint";
})(WarehouseType || (WarehouseType = {}));
var SettlementType;
(function(SettlementType2) {
SettlementType2["City"] = "\u043C.";
SettlementType2["Town"] = "\u0441\u043C\u0442.";
SettlementType2["Village"] = "\u0441.";
SettlementType2["UrbanVillage"] = "\u0441\u0449.";
})(SettlementType || (SettlementType = {}));
var OwnershipForm;
(function(OwnershipForm2) {
OwnershipForm2["PrivatePerson"] = "PrivatePerson";
OwnershipForm2["Organization"] = "Organization";
})(OwnershipForm || (OwnershipForm = {}));
var CounterpartyType;
(function(CounterpartyType2) {
CounterpartyType2["PrivatePerson"] = "PrivatePerson";
CounterpartyType2["Organization"] = "Organization";
})(CounterpartyType || (CounterpartyType = {}));
var ContactPersonType;
(function(ContactPersonType2) {
ContactPersonType2["Sender"] = "Sender";
ContactPersonType2["Recipient"] = "Recipient";
})(ContactPersonType || (ContactPersonType = {}));
var TimeIntervalType;
(function(TimeIntervalType2) {
TimeIntervalType2["CityDeliveryTimeInterval1"] = "CityDeliveryTimeInterval1";
TimeIntervalType2["CityDeliveryTimeInterval2"] = "CityDeliveryTimeInterval2";
TimeIntervalType2["CityDeliveryTimeInterval3"] = "CityDeliveryTimeInterval3";
TimeIntervalType2["CityDeliveryTimeInterval4"] = "CityDeliveryTimeInterval4";
})(TimeIntervalType || (TimeIntervalType = {}));
var PickupTimeInterval;
(function(PickupTimeInterval2) {
PickupTimeInterval2["CityPickingTimeInterval1"] = "CityPickingTimeInterval1";
PickupTimeInterval2["CityPickingTimeInterval2"] = "CityPickingTimeInterval2";
PickupTimeInterval2["CityPickingTimeInterval3"] = "CityPickingTimeInterval3";
PickupTimeInterval2["CityPickingTimeInterval4"] = "CityPickingTimeInterval4";
})(PickupTimeInterval || (PickupTimeInterval = {}));
var BackwardDeliveryType;
(function(BackwardDeliveryType2) {
BackwardDeliveryType2["Money"] = "Money";
BackwardDeliveryType2["Documents"] = "Documents";
BackwardDeliveryType2["Cargo"] = "Cargo";
})(BackwardDeliveryType || (BackwardDeliveryType = {}));
var BackwardDeliverySubtype;
(function(BackwardDeliverySubtype2) {
BackwardDeliverySubtype2["MoneyTransfer"] = "MoneyTransfer";
BackwardDeliverySubtype2["DocumentsReturn"] = "DocumentsReturn";
BackwardDeliverySubtype2["CargoReturn"] = "CargoReturn";
})(BackwardDeliverySubtype || (BackwardDeliverySubtype = {}));
var AdditionalService;
(function(AdditionalService2) {
AdditionalService2["SaturdayDelivery"] = "SaturdayDelivery";
AdditionalService2["DeliveryByHand"] = "DeliveryByHand";
AdditionalService2["AfterpaymentOnGoodsCost"] = "AfterpaymentOnGoodsCost";
AdditionalService2["LocalExpress"] = "LocalExpress";
AdditionalService2["PreferredDeliveryDate"] = "PreferredDeliveryDate";
AdditionalService2["TimeInterval"] = "TimeInterval";
AdditionalService2["PackingNumber"] = "PackingNumber";
AdditionalService2["InfoRegClientBarcodes"] = "InfoRegClientBarcodes";
AdditionalService2["AccompanyingDocuments"] = "AccompanyingDocuments";
AdditionalService2["AdditionalInformation"] = "AdditionalInformation";
AdditionalService2["NumberOfFloorsLifting"] = "NumberOfFloorsLifting";
AdditionalService2["NumberOfFloorsDescent"] = "NumberOfFloorsDescent";
AdditionalService2["ForwardingCount"] = "ForwardingCount";
AdditionalService2["RedBoxBarcode"] = "RedBoxBarcode";
AdditionalService2["SpecialCargo"] = "SpecialCargo";
})(AdditionalService || (AdditionalService = {}));
var DocumentType;
(function(DocumentType2) {
DocumentType2["InternetDocument"] = "InternetDocument";
DocumentType2["ReturnDocument"] = "ReturnDocument";
DocumentType2["RedirectionDocument"] = "RedirectionDocument";
})(DocumentType || (DocumentType = {}));
var Currency;
(function(Currency2) {
Currency2["UAH"] = "UAH";
Currency2["USD"] = "USD";
Currency2["EUR"] = "EUR";
Currency2["RUB"] = "RUB";
})(Currency || (Currency = {}));
var Language;
(function(Language2) {
Language2["Ukrainian"] = "ua";
Language2["Russian"] = "ru";
})(Language || (Language = {}));
var DeliveryDay;
(function(DeliveryDay2) {
DeliveryDay2["Monday"] = "Delivery1";
DeliveryDay2["Tuesday"] = "Delivery2";
DeliveryDay2["Wednesday"] = "Delivery3";
DeliveryDay2["Thursday"] = "Delivery4";
DeliveryDay2["Friday"] = "Delivery5";
DeliveryDay2["Saturday"] = "Delivery6";
DeliveryDay2["Sunday"] = "Delivery7";
})(DeliveryDay || (DeliveryDay = {}));
var PackingType;
(function(PackingType2) {
PackingType2["Box"] = "Box";
PackingType2["Tube"] = "Tube";
PackingType2["Envelope"] = "Envelope";
PackingType2["Bag"] = "Bag";
})(PackingType || (PackingType = {}));
var TireWheelType;
(function(TireWheelType2) {
TireWheelType2["Tires"] = "Tires";
TireWheelType2["Wheels"] = "Wheels";
})(TireWheelType || (TireWheelType = {}));
var StreetType;
(function(StreetType2) {
StreetType2["Street"] = "\u0432\u0443\u043B.";
StreetType2["Avenue"] = "\u043F\u0440\u043E\u0441\u043F.";
StreetType2["Boulevard"] = "\u0431\u0443\u043B.";
StreetType2["Lane"] = "\u043F\u0440\u043E\u0432.";
StreetType2["Square"] = "\u043F\u043B.";
StreetType2["Embankment"] = "\u043D\u0430\u0431.";
})(StreetType || (StreetType = {}));
var NOVA_POSHTA_MODELS = Object.values(NovaPoshtaModel);
var NOVA_POSHTA_METHODS = Object.values(NovaPoshtaMethod);
var PAYMENT_METHODS = Object.values(PaymentMethod);
var CARGO_TYPES = Object.values(CargoType);
var SERVICE_TYPES = Object.values(ServiceType);
var PAYER_TYPES = Object.values(PayerType);
var DELIVERY_STATUSES = Object.values(DeliveryStatus);
// node_modules/@shopana/novaposhta-api-client/dist/services/waybillService.js
var WaybillService = class {
constructor() {
this.namespace = "waybill";
}
attach(ctx) {
this.transport = toHttpTransport(ctx);
this.apiKey = ctx.apiKey;
}
/**
* Create a standard waybill
*/
async create(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.Save,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Create a waybill with additional options and services
*/
async createWithOptions(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.Save,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Create a postomat waybill (with restrictions)
*/
async createForPostomat(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.Save,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Update an existing waybill
*/
async update(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.Update,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Delete waybills
*/
async delete(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.Delete,
methodProperties: {
DocumentRefs: request.documentRefs.join(",")
}
};
return await this.transport.request(apiRequest);
}
/**
* Calculate delivery date
*/
async getDeliveryDate(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.GetDocumentDeliveryDate,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Calculate delivery price
*/
async getPrice(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.GetDocumentPrice,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Batch create multiple waybills
*/
async createBatch(requests) {
const results = [];
for (const request of requests) {
try {
const result = await this.create(request);
results.push(result);
} catch (error) {
results.push({
success: false,
data: [],
errors: [error instanceof Error ? error.message : "Unknown error"],
warnings: [],
info: [],
messageCodes: [],
errorCodes: [],
warningCodes: [],
infoCodes: []
});
}
}
return results;
}
/**
* Batch delete multiple waybills
*/
async deleteBatch(documentRefs) {
return this.delete({ documentRefs });
}
/**
* Get estimated delivery cost and date in one request
*/
async getEstimate(request) {
const [price, deliveryDate] = await Promise.all([
this.getPrice(request),
this.getDeliveryDate({
serviceType: request.serviceType,
citySender: request.citySender,
cityRecipient: request.cityRecipient
})
]);
return { price, deliveryDate };
}
/**
* Validate waybill data without creating
*/
async validateWaybill(request) {
try {
return true;
} catch {
return false;
}
}
/**
* Check if postomat delivery is available for the request
*/
canDeliverToPostomat(request) {
if (!request.cargoType || !["Parcel", "Documents"].includes(request.cargoType)) {
return false;
}
if (!request.serviceType || !["DoorsWarehouse", "WarehouseWarehouse"].includes(request.serviceType)) {
return false;
}
if (request.cost && request.cost > 1e4) {
return false;
}
return true;
}
// =============================================================================
// LEGACY COMPATIBILITY METHODS
// =============================================================================
/**
* Create express waybill (legacy method for compatibility)
* @deprecated Use create() method instead
*/
async createExpressWaybill(request) {
return this.create(request);
}
/**
* Create waybill with options (legacy method for compatibility)
* @deprecated Use createWithOptions() method instead
*/
async createWaybillWithOptions(request) {
return this.createWithOptions(request);
}
/**
* Create postomat express waybill (legacy method for compatibility)
* @deprecated Use createForPostomat() method instead
*/
async createPoshtomatExpressWaybill(request) {
return this.createForPostomat(request);
}
/**
* Update express waybill (legacy method for compatibility)
* @deprecated Use update() method instead
*/
async updateExpressWaybill(request) {
return this.update(request);
}
/**
* Delete waybill (legacy method for compatibility)
* @deprecated Use delete() method instead
*/
async deleteWaybill(request) {
return this.delete(request);
}
/**
* Get delivery date (legacy method for compatibility)
* @deprecated Use getDeliveryDate() method instead
*/
async getDocumentDeliveryDate(request) {
return this.getDeliveryDate(request);
}
/**
* Get delivery price (legacy method for compatibility)
* @deprecated Use getPrice() method instead
*/
async getDeliveryPrice(request) {
return this.getPrice(request);
}
/**
* Get document price (legacy method for compatibility)
* @deprecated Use getPrice() method instead
*/
async getDocumentPrice(request) {
return this.getPrice(request);
}
};
// node_modules/@shopana/novaposhta-api-client/dist/services/trackingService.js
var TrackingService = class {
constructor() {
this.namespace = "tracking";
}
attach(ctx) {
this.transport = toHttpTransport(ctx);
this.apiKey = ctx.apiKey;
}
/**
* Track multiple documents
*/
async trackDocuments(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.TrackingDocument,
calledMethod: NovaPoshtaMethod.GetStatusDocuments,
methodProperties: {
Documents: request.documents.map((doc) => ({
DocumentNumber: doc.documentNumber,
Phone: doc.phone
}))
}
};
return await this.transport.request(apiRequest);
}
/**
* Track a single document by number
*/
async trackDocument(documentNumber, phone) {
const response = await this.trackDocuments({
documents: [{ documentNumber, phone }]
});
if (response.success && response.data.length > 0) {
return response.data[0] || null;
}
return null;
}
/**
* Get document movement history
*/
async getDocumentMovement(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.TrackingDocument,
calledMethod: NovaPoshtaMethod.GetDocumentsEWMovement,
methodProperties: {
Documents: request.documents.map((doc) => ({
DocumentNumber: doc.documentNumber,
Phone: doc.phone
})),
ShowDeliveryDetails: request.showDeliveryDetails ? "1" : "0"
}
};
return await this.transport.request(apiRequest);
}
/**
* Get list of documents for a date range
*/
async getDocumentList(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.InternetDocument,
calledMethod: NovaPoshtaMethod.GetDocumentList,
methodProperties: {
DateTimeFrom: request.dateTimeFrom,
DateTimeTo: request.dateTimeTo,
Page: request.page?.toString() || "1",
GetFullList: request.getFullList || "0",
DateTime: request.dateTime
}
};
return await this.transport.request(apiRequest);
}
/**
* Track multiple documents and return organized results
*/
async trackMultiple(documentNumbers) {
const documents = documentNumbers.map((num) => ({ documentNumber: num }));
const response = await this.trackDocuments({ documents });
const successful = [];
const failed = [];
if (response.success && response.data) {
response.data.forEach((item, index) => {
if (item && item.StatusCode !== DeliveryStatus.NotFound) {
successful.push(item);
} else {
failed.push(documentNumbers[index] || "unknown");
}
});
} else {
failed.push(...documentNumbers);
}
const statistics = this.calculateStatistics(successful);
return {
successful,
failed,
statistics
};
}
/**
* Filter tracking results by criteria
*/
filterTrackingResults(results, filter) {
return results.filter((result) => {
if (filter.status && filter.status.length > 0) {
if (!filter.status.includes(result.StatusCode)) {
return false;
}
}
if (filter.dateFrom || filter.dateTo) {
const resultDate = new Date(result.DateCreated);
if (filter.dateFrom && resultDate < new Date(filter.dateFrom)) {
return false;
}
if (filter.dateTo && resultDate > new Date(filter.dateTo)) {
return false;
}
}
if (filter.citySender && !result.CitySender.includes(filter.citySender)) {
return false;
}
if (filter.cityRecipient && !result.CityRecipient.includes(filter.cityRecipient)) {
return false;
}
return true;
});
}
/**
* Get tracking statistics for a set of results
*/
calculateStatistics(results) {
const stats = {
totalTracked: results.length,
delivered: 0,
inTransit: 0,
atWarehouse: 0,
failed: 0,
unknown: 0
};
results.forEach((result) => {
switch (result.StatusCode) {
case DeliveryStatus.Received:
case DeliveryStatus.ReceivedAwaitingMoneyTransfer:
case DeliveryStatus.ReceivedAndMoneyTransferred:
stats.delivered++;
break;
case DeliveryStatus.InTransitToRecipientCity:
case DeliveryStatus.OnTheWayToRecipient:
case DeliveryStatus.BeingPacked:
stats.inTransit++;
break;
case DeliveryStatus.ArrivedAtWarehouse:
case DeliveryStatus.ArrivedAtPostomat:
case DeliveryStatus.InRecipientCityAwaitingDelivery:
stats.atWarehouse++;
break;
case DeliveryStatus.RefusedByRecipient:
case DeliveryStatus.RefusedByRecipientReturnCreated:
case DeliveryStatus.FailedDeliveryAttempt:
stats.failed++;
break;
default:
stats.unknown++;
break;
}
});
return stats;
}
/**
* Check if document is delivered
*/
isDelivered(status) {
return [
DeliveryStatus.Received,
DeliveryStatus.ReceivedAwaitingMoneyTransfer,
DeliveryStatus.ReceivedAndMoneyTransferred
].includes(status.StatusCode);
}
/**
* Check if document is in transit
*/
isInTransit(status) {
return [
DeliveryStatus.InTransitToRecipientCity,
DeliveryStatus.OnTheWayToRecipient,
DeliveryStatus.BeingPacked
].includes(status.StatusCode);
}
/**
* Check if document is at warehouse/postomat
*/
isAtWarehouse(status) {
return [
DeliveryStatus.ArrivedAtWarehouse,
DeliveryStatus.ArrivedAtPostomat,
DeliveryStatus.InRecipientCityAwaitingDelivery
].includes(status.StatusCode);
}
/**
* Get human-readable status description
*/
getStatusDescription(status, language = "ua") {
const descriptions = {
[DeliveryStatus.CreatedBySender]: {
ua: "\u0421\u0442\u0432\u043E\u0440\u0435\u043D\u043E \u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043D\u0438\u043A\u043E\u043C",
ru: "\u0421\u043E\u0437\u0434\u0430\u043D\u043E \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u0435\u043B\u0435\u043C",
en: "Created by sender"
},
[DeliveryStatus.Deleted]: {
ua: "\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043E",
ru: "\u0423\u0434\u0430\u043B\u0435\u043D\u043E",
en: "Deleted"
},
[DeliveryStatus.NotFound]: {
ua: "\u041D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E",
ru: "\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E",
en: "Not found"
},
[DeliveryStatus.InTransitToRecipientCity]: {
ua: "\u041F\u0440\u044F\u043C\u0443\u0454 \u0434\u043E \u043C\u0456\u0441\u0442\u0430 \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430",
ru: "\u041D\u0430\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0432 \u0433\u043E\u0440\u043E\u0434 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F",
en: "En route to recipient city"
},
[DeliveryStatus.Received]: {
ua: "\u041E\u0442\u0440\u0438\u043C\u0430\u043D\u043E",
ru: "\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u043E",
en: "Delivered"
}
// Add more status descriptions as needed
};
return descriptions[status]?.[language] || `Unknown status: ${status}`;
}
/**
* Monitor documents with periodic updates
*/
async monitorDocuments(documentNumbers, callback, intervalMs = 3e5) {
const monitor = async () => {
try {
const response = await this.trackMultiple(documentNumbers);
callback(response.successful);
} catch (error) {
console.error("Error monitoring documents:", error);
}
};
await monitor();
const intervalId = setInterval(monitor, intervalMs);
return () => {
clearInterval(intervalId);
};
}
// =============================================================================
// LEGACY COMPATIBILITY METHODS
// =============================================================================
/**
* Track waybill (legacy method for compatibility)
* @deprecated Use trackDocument() or trackDocuments() method instead
*/
async trackWaybill(request) {
return this.trackDocuments({
documents: request.documents.map((doc) => ({
documentNumber: doc.documentNumber,
phone: doc.phone
}))
});
}
/**
* Get status documents (legacy method for compatibility)
* @deprecated Use trackDocuments() method instead
*/
async getStatusDocuments(request) {
return this.trackDocuments(request);
}
};
// node_modules/@shopana/novaposhta-api-client/dist/services/referenceService.js
var ReferenceService = class {
constructor() {
this.namespace = "reference";
}
attach(ctx) {
this.transport = toHttpTransport(ctx);
this.apiKey = ctx.apiKey;
}
/**
* Get cargo types
* @description Retrieves list of available cargo types
* @cacheable 24 hours
*/
async getCargoTypes(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetCargoTypes,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get pallets list
* @description Retrieves list of available pallets
* @cacheable 24 hours
*/
async getPalletsList(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetPalletsList,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get pack list
* @description Retrieves list of available packaging types
* @cacheable 24 hours
*/
async getPackList(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetPackList,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get tires and wheels list
* @description Retrieves list of available tires and wheels types
* @cacheable 24 hours
*/
async getTiresWheelsList(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetTiresWheelsList,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get cargo description list
* @description Retrieves list of cargo descriptions with optional search
* @cacheable 24 hours
*/
async getCargoDescriptionList(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetCargoDescriptionList,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get message code text
* @description Retrieves list of error codes and their descriptions
* @cacheable 24 hours
*/
async getMessageCodeText(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetMessageCodeText,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get service types
* @description Retrieves list of delivery service types
* @cacheable 24 hours
*/
async getServiceTypes(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetServiceTypes,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get ownership forms list
* @description Retrieves list of ownership forms
* @cacheable 24 hours
*/
async getOwnershipFormsList(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetOwnershipFormsList,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get time intervals
* @description Retrieves available time intervals for delivery
* @cacheable 1 hour
*/
async getTimeIntervals(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetTimeIntervals,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get pickup time intervals
* @description Retrieves available time intervals for pickup
* @cacheable 1 hour
*/
async getPickupTimeIntervals(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetPickupTimeIntervals,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get backward delivery cargo types
* @description Retrieves list of backward delivery cargo types
* @cacheable 24 hours
*/
async getBackwardDeliveryCargoTypes(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetBackwardDeliveryCargoTypes,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get types of payers for redelivery
* @description Retrieves list of payer types for redelivery
* @cacheable 24 hours
*/
async getTypesOfPayersForRedelivery(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Common,
calledMethod: NovaPoshtaMethod.GetTypesOfPayersForRedelivery,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
};
// node_modules/@shopana/novaposhta-api-client/dist/services/addressService.js
var AddressService = class {
constructor() {
this.namespace = "address";
}
attach(ctx) {
this.transport = toHttpTransport(ctx);
this.apiKey = ctx.apiKey;
}
/**
* Get settlements (areas)
* @description Retrieves list of settlement areas
* @cacheable 12 hours
*/
async getSettlements(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.GetSettlementAreas,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get settlement country regions
* @description Retrieves list of settlement regions for a specific area
* @cacheable 12 hours
*/
async getSettlementCountryRegion(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.GetSettlementCountryRegion,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get cities
* @description Retrieves list of cities with Nova Poshta offices
* @cacheable 12 hours
*/
async getCities(request = {}) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.GetCities,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Get streets
* @description Retrieves list of streets in a specific city
* @cacheable 12 hours
*/
async getStreet(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.GetStreet,
methodProperties: request
};
return await this.transport.request(apiRequest);
}
/**
* Search settlements online
* @description Performs online search for settlements
* @cacheable 1 hour
*/
async searchSettlements(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.SearchSettlements,
methodProperties: {
CityName: request.cityName,
Page: request.page.toString(),
Limit: request.limit.toString()
}
};
return await this.transport.request(apiRequest);
}
/**
* Search settlement streets online
* @description Performs online search for streets in a settlement
* @cacheable 1 hour
*/
async searchSettlementStreets(request) {
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.SearchSettlementStreets,
methodProperties: {
StreetName: request.streetName,
SettlementRef: request.settlementRef,
Limit: request.limit?.toString()
}
};
return await this.transport.request(apiRequest);
}
/**
* Get warehouses (branches and postomats)
* @description Retrieves list of Nova Poshta warehouses filtered by city, settlement, or other criteria
* @cacheable 1 hour
* @note API returns HTTP 303 Redirect with link to cached file for some cities
*/
async getWarehouses(request = {}) {
const methodProperties = {
Ref: request.ref,
CityName: request.cityName,
CityRef: request.cityRef,
SettlementRef: request.settlementRef,
WarehouseId: request.warehouseId,
FindByString: request.findByString,
TypeOfWarehouseRef: request.typeOfWarehouseRef,
BicycleParking: request.bicycleParking,
PostFinance: request.postFinance,
POSTerminal: request.posTerminal,
Page: request.page?.toString(),
Limit: request.limit?.toString(),
Language: request.language
};
const cleanProperties = Object.fromEntries(Object.entries(methodProperties).filter(([, value]) => value !== void 0 && value !== ""));
const apiRequest = {
...this.apiKey ? { apiKey: this.apiKey } : {},
modelName: NovaPoshtaModel.Address,
calledMethod: NovaPoshtaMethod.GetWarehouses,
methodProperties: cleanProperties
};
return await this.transport.request(apiRequest);
}
};
// node_modules/@shopana/novaposhta-transport-fetch/dist/index.js
import fetchPonyfill from "cross-fetch";
function createFetchHttpTransport(init) {
const doFetch = init?.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : fetchPonyfill);
const headers = { "Content-Type": "application/json", Accept: "application/json", ...init?.baseHeaders ?? {} };
async function transport({ url, body, signal }) {
const res = await doFetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
signal
});
const data = await res.json();
return { status: res.status, data };
}
return transport;
}
// src/server.ts
import { readFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import { createServer } from "http";
import { randomUUID } from "crypto";
// src/utils/logger.ts
var LEVEL_PRIORITY = {
debug: 10,
info: 20,
warn: 30,
error: 40
};
var Logger = class {
constructor(level = "info") {
this.level = level;
}
debug(message, extra) {
this.log("debug", message, extra);
}
info(message, extra) {
this.log("info", message, extra);
}
warn(message, extra) {
this.log("warn", message, extra);
}
error(message, extra) {
this.log("error", message, extra);
}
log(level, message, extra) {
if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.level]) {
return;
}
const payload = extra !== void 0 ? { message, extra } : { message };
console.error(JSON.stringify({ level, timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...payload }));
}
};
// src/utils/error-handler.ts
function formatError(error) {
if (isNovaPoshtaError(error)) {
const context = error.context ? ` Context: ${JSON.stringify(error.context)}` : "";
return `Nova Poshta API error (${error.code}): ${error.message}.${context}`;
}
if (error instanceof Error) {
return error.message;
}
return typeof error === "string" ? error : "Unknown error";
}
function toErrorResult(error, prefix = "Failed to execute tool") {
return {
content: [
{
type: "text",
text: `${prefix}: ${formatError(error)}`
}
],
isError: true
};
}
function isNovaPoshtaError(error) {
return Boolean(
error && typeof error === "object" && "code" in error && "message" in error
);
}
// src/utils/validation.ts
function isNonEmptyString(value) {
return typeof value === "string" && value.trim().length > 0;
}
function isTrackingNumber(value) {
return typeof value === "string" && /^\d{14}$/.test(value.trim());
}
function isPhoneNumber(value) {
return typeof value === "string" && /^380\d{9}$/.test(value.trim());
}
function isDateFormat(value) {
if (typeof value !== "string")
return false;
const trimmed = value.trim();
if (!/^\d{2}\.\d{2}\.\d{4}$/.test(trimmed))
return false;
const [day, month, year] = trimmed.split(".").map(Number);
if (month < 1 || month > 12)
return false;
if (day < 1 || day > 31)
return false;
if (year < 1900 || year > 2100)
return false;
return true;
}
function sanitizePhone(phone) {
let sanitized = phone.replace(/\D/g, "");
if (phone.startsWith("+")) {
sanitized = sanitized;
}
if (sanitized.startsWith("80")) {
sanitized = "3" + sanitized;
}
if (sanitized.startsWith("0")) {
sanitized = "38" + sanitized;
}
return sanitized;
}
function assertString(value, field) {
if (!isNonEmptyString(value)) {
throw new Error(`Field "${field}" must be a non-empty string`);
}
return value.trim();
}
function assertNumber(value, field) {
if (typeof value === "string" && value.trim() !== "") {
const parsed = Number(value);
if (!Number.isNaN(parsed)) {
return parsed;
}
}
if (typeof value !== "number" || Number.isNaN(value)) {
throw new Error(`Field "${field}" must be a valid number`);
}
return value;
}
function assertOptionalString(value, field) {
if (value === void 0 || value === null) {
return void 0;
}
return assertString(value, field);
}
function assertOptionalNumber(value, field) {
if (value === void 0 || value === null || value === "") {
return void 0;
}
return assertNumber(value, field);
}
// src/utils/tool-response.ts
function createTextResult(message, structuredContent) {
return {
content: [
{
type: "text",
text: message
}
],
...structuredContent ? { structuredContent } : {}
};
}
function formatAsJson(input) {
return JSON.stringify(input, null, 2);
}
// src/tools/address.ts
var addressTools = [
{
name: "address_search_cities",
description: "Find Nova Poshta cities by name or postal index.",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "Partial city name or postal code." },
page: { type: "number", description: "Page number (default 1)." },
limit: { type: "number", description: "Items per page (max 50)." }
},
required: ["query"]
}
},
{
name: "address_search_settlements",
description: "Search for settlements (city, town, village) with pagination.",
inputSchema: {
type: "object",
properties: {
cityName: { type: "string", description: "Settlement name or postal code." },
page: { type: "number", description: "Page number (default 1)." },
limit: { type: "number", description: "Items per page (1-500)." }
},
required: ["cityName"]
}
},
{
name: "address_search_streets",
description: "Search for streets inside a settlement.",
inputSchema: {
type: "object",
properties: {
settlementRef: { type: "string", description: "Settlement reference ID." },
streetName: { type: "string", description: "Street name or fragment." },
limit: { type: "number", description: "Max items to return (optional)." }
},
required: ["settlementRef", "streetName"]
}
},
{
name: "address_get_warehouses",
description: "List Nova Poshta warehouses (branches, postomats, pickup points) filtered by city, settlement, type, number, or search string.",
inputSchema: {
type: "object",
properties: {
ref: { type: "string", description: "Specific warehouse reference (returns single warehouse)." },
cityName: { type: "string", description: "City name filter." },
cityRef: { type: "string", description: "City reference from getCities." },
settlementRef: { type: "string", description: "Settlement reference from searchSettlements." },
warehouseId: { type: "string", description: 'Warehouse number (e.g., "1" for Branch #1).' },
findByString: { type: "string", description: "Search string for warehouse name, address, or street." },
typeOfWarehouseRef: { type: "string", description: "Filter by warehouse type (Branch, Postomat, Pickup Point)." },
bicycleParking: { type: "string", description: "Filter by bicycle parking availability (1/0)." },
postFinance: { type: "string", description: "Filter by NovaPay cash desk availability (1/0)." },
posTerminal: { type: "string", description: "Filter by POS terminal availability (1/0)." },
page: { type: "number", description: "Page number (default 1)." },
limit: { type: "number", description: "Items per page (default 50)." },
language: { type: "string", description: "Language code (UA, RU, EN)." }
},
required: []
}
}
];
function getAddressTools() {
return addressTools;
}
async function handleAddressTool(name, args, context) {
try {
switch (name) {
case "address_search_cities":
return await handleSearchCities(args, context);
case "address_search_settlements":
return await handleSearchSettlements(args, context);
case "address_search_streets":
return await handleSearchStreets(args, context);
case "address_get_warehouses":
return await handleGetWarehouses(args, context);
default:
throw new Error(`Unknown address tool: ${name}`);
}
} catch (error) {
return toErrorResult(error, `Address tool "${name}"`);
}
}
async function handleSearchCities(args, context) {
const query = assertString(args?.query, "query");
const page = assertOptionalNumber(args?.page, "page") ?? 1;
const limit = assertOptionalNumber(args?.limit, "limit") ?? 20;
const response = await context.client.address.getCities({
findByString: query,
page,
limit
});
const preview = response.data?.slice(0, 5).map((city) => {
const warehouses = city.Warehouses ?? 0;
return {
description: city.Description,
ref: city.Ref,
area: city.Area,
warehouses: Number(warehouses)
};
});
return createTextResult(formatAsJson({ total: response.data?.length ?? 0, preview }), { response });
}
async function handleSearchSettlements(args, context) {
const cityName = assertString(args?.cityName, "cityName");
const page = assertOptionalNumber(args?.page, "page") ?? 1;
const limit = assertOptionalNumber(args?.limit, "limit") ?? 50;
const response = await context.client.address.searchSettlements({
cityName,
page,
limit
});
const addresses = response.data?.[0]?.Addresses ?? [];
const preview = addresses.slice(0, 5).map((address) => ({
name: address.MainDescription,
area: address.Area,
region: address.Region,
warehouses: address.Warehouses,
settlementRef: address.Ref,
deliveryCity: address.DeliveryCity
}));
return createTextResult(formatAsJson({ total: addresses.length, preview }), { response });
}
async function handleSearchStreets(args, context) {
const settlementRef = assertString(args?.settlementRef, "settlementRef");
const streetName = assertString(args?.streetName, "streetName");
const limit = assertOptionalNumber(args?.limit, "limit");
const response = await context.client.address.searchSettlementStreets({
settlementRef,
streetName,
limit: limit ?? void 0
});
const addresses = response.data?.[0]?.Addresses ?? [];
const preview = addresses.slice(0, 5).map((street) => ({
name: street.SettlementStreetDescription,
present: street.Present,
location: street.Location
}));
return createTextResult(formatAsJson({ total: addresses.length, preview }), { response });
}
async function handleGetWarehouses(args, context) {
const ref = assertOptionalString(args?.ref, "ref");
const cityName = assertOptionalString(args?.cityName, "cityName");
const cityRef = assertOptionalString(args?.cityRef, "cityRef");
const settlementRef = assertOptionalString(args?.settlementRef, "settlementRef");
const warehouseId = assertOptionalString(args?.warehouseId, "warehouseId");
const findByString = assertOptionalString(args?.findByString, "findByString");
const typeOfWarehouseRef = assertOptionalString(args?.typeOfWarehouseRef, "typeOfWarehouseRef");
const bicycleParking = assertOptionalString(args?.bicycleParking, "bicycleParking");
const postFinance = assertOptionalString(args?.postFinance, "postFinance");
const posTerminal = assertOptionalString(args?.posTerminal, "posTerminal");
const language = assertOptionalString(args?.language, "language");
const page = assertOptionalNumber(args?.page, "page");
const limit = assertOptionalNumber(args?.limit, "limit");
if (!ref && !cityRef && !settlementRef) {
throw new Error("ref, cityRef, or settlementRef is required to list warehouses");
}
const response = await context.client.address.getWarehouses({
ref,
cityName,
cityRef,
settlementRef,
warehouseId,
findByString,