@jazzdev/dpd-local-sdk 1.0.13 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js +185 -1
- package/dist/index.mjs +183 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -316,6 +316,24 @@ interface LogFilters {
|
|
|
316
316
|
endDate?: Date;
|
|
317
317
|
limit?: number;
|
|
318
318
|
}
|
|
319
|
+
interface GeoSessionStorage {
|
|
320
|
+
get(): Promise<{
|
|
321
|
+
geoSession: string;
|
|
322
|
+
expiry: Date;
|
|
323
|
+
} | null>;
|
|
324
|
+
set(geoSession: string, expiry: Date): Promise<void>;
|
|
325
|
+
clear(): Promise<void>;
|
|
326
|
+
}
|
|
327
|
+
declare class InMemoryGeoSessionStorage implements GeoSessionStorage {
|
|
328
|
+
private geoSession;
|
|
329
|
+
private expiry;
|
|
330
|
+
get(): Promise<{
|
|
331
|
+
geoSession: string;
|
|
332
|
+
expiry: Date;
|
|
333
|
+
} | null>;
|
|
334
|
+
set(geoSession: string, expiry: Date): Promise<void>;
|
|
335
|
+
clear(): Promise<void>;
|
|
336
|
+
}
|
|
319
337
|
|
|
320
338
|
declare const DPD_API: {
|
|
321
339
|
readonly BASE_URL: "https://api.dpdlocal.co.uk";
|
|
@@ -408,6 +426,23 @@ declare function testConnection(credentials: DPDCredentials): Promise<{
|
|
|
408
426
|
success: boolean;
|
|
409
427
|
message: string;
|
|
410
428
|
}>;
|
|
429
|
+
declare class GeoSessionManager {
|
|
430
|
+
private credentials;
|
|
431
|
+
private storage;
|
|
432
|
+
private maxRetries;
|
|
433
|
+
private baseRetryDelay;
|
|
434
|
+
constructor(credentials: DPDCredentials, storage?: GeoSessionStorage, options?: {
|
|
435
|
+
maxRetries?: number;
|
|
436
|
+
baseRetryDelay?: number;
|
|
437
|
+
});
|
|
438
|
+
getValidGeoSession(): Promise<string>;
|
|
439
|
+
refreshGeoSession(): Promise<string>;
|
|
440
|
+
clearGeoSession(): Promise<void>;
|
|
441
|
+
private isSessionValid;
|
|
442
|
+
private authenticateWithRetry;
|
|
443
|
+
private authenticate;
|
|
444
|
+
private delay;
|
|
445
|
+
}
|
|
411
446
|
|
|
412
447
|
declare function createShipment(credentials: DPDCredentials, params: CreateShipmentParams, businessConfig: any): Promise<CreateShipmentResult>;
|
|
413
448
|
declare function generateLabel(credentials: DPDCredentials, params: GenerateLabelParams): Promise<GenerateLabelResult>;
|
|
@@ -498,4 +533,4 @@ declare function loggedOperation<T>(params: {
|
|
|
498
533
|
headers?: Record<string, string>;
|
|
499
534
|
}>): Promise<T>;
|
|
500
535
|
|
|
501
|
-
export { type BusinessConfig, type CreateShipmentParams, type CreateShipmentResult, type DPDAddress, type DPDAuthResponse, type DPDConsignment, type DPDContact, type DPDCredentials, type DPDError, type DPDLabelRequest, type DPDLabelResponse, type DPDLogDocument, type DPDModuleConfig, type DPDParcel, _default as DPDService, type DPDServiceCode, type DPDShipmentRequest, type DPDShipmentResponse, DPD_API, type DatabaseAdapter, type GenerateLabelParams, type GenerateLabelResult, type LabelConfig, type LogFilters, type NotificationConfig, type PricingConfig, SERVICE_DESCRIPTIONS, SERVICE_NAMES, type SavedAddress, type ServiceConfig, type ShipmentStatus, type ShipmentStatusUpdate, type ShippingData, type StorageAdapter, type TimestampType, type TrackShipmentParams, type TrackShipmentResult, type ValidateAddressParams, type ValidateAddressResult, authenticate, authenticatedRequest, calculateDPDCost, calculateDeliveryFee, calculateParcels, clearGeoSession, configureLogger, createCompleteShipment, createDPDConfig, createShipment, deleteSavedAddress, generateAndUploadLabel, generateConsignmentRef, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode };
|
|
536
|
+
export { type BusinessConfig, type CreateShipmentParams, type CreateShipmentResult, type DPDAddress, type DPDAuthResponse, type DPDConsignment, type DPDContact, type DPDCredentials, type DPDError, type DPDLabelRequest, type DPDLabelResponse, type DPDLogDocument, type DPDModuleConfig, type DPDParcel, _default as DPDService, type DPDServiceCode, type DPDShipmentRequest, type DPDShipmentResponse, DPD_API, type DatabaseAdapter, type GenerateLabelParams, type GenerateLabelResult, GeoSessionManager, type GeoSessionStorage, InMemoryGeoSessionStorage, type LabelConfig, type LogFilters, type NotificationConfig, type PricingConfig, SERVICE_DESCRIPTIONS, SERVICE_NAMES, type SavedAddress, type ServiceConfig, type ShipmentStatus, type ShipmentStatusUpdate, type ShippingData, type StorageAdapter, type TimestampType, type TrackShipmentParams, type TrackShipmentResult, type ValidateAddressParams, type ValidateAddressResult, authenticate, authenticatedRequest, calculateDPDCost, calculateDeliveryFee, calculateParcels, clearGeoSession, configureLogger, createCompleteShipment, createDPDConfig, createShipment, deleteSavedAddress, generateAndUploadLabel, generateConsignmentRef, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode };
|
package/dist/index.d.ts
CHANGED
|
@@ -316,6 +316,24 @@ interface LogFilters {
|
|
|
316
316
|
endDate?: Date;
|
|
317
317
|
limit?: number;
|
|
318
318
|
}
|
|
319
|
+
interface GeoSessionStorage {
|
|
320
|
+
get(): Promise<{
|
|
321
|
+
geoSession: string;
|
|
322
|
+
expiry: Date;
|
|
323
|
+
} | null>;
|
|
324
|
+
set(geoSession: string, expiry: Date): Promise<void>;
|
|
325
|
+
clear(): Promise<void>;
|
|
326
|
+
}
|
|
327
|
+
declare class InMemoryGeoSessionStorage implements GeoSessionStorage {
|
|
328
|
+
private geoSession;
|
|
329
|
+
private expiry;
|
|
330
|
+
get(): Promise<{
|
|
331
|
+
geoSession: string;
|
|
332
|
+
expiry: Date;
|
|
333
|
+
} | null>;
|
|
334
|
+
set(geoSession: string, expiry: Date): Promise<void>;
|
|
335
|
+
clear(): Promise<void>;
|
|
336
|
+
}
|
|
319
337
|
|
|
320
338
|
declare const DPD_API: {
|
|
321
339
|
readonly BASE_URL: "https://api.dpdlocal.co.uk";
|
|
@@ -408,6 +426,23 @@ declare function testConnection(credentials: DPDCredentials): Promise<{
|
|
|
408
426
|
success: boolean;
|
|
409
427
|
message: string;
|
|
410
428
|
}>;
|
|
429
|
+
declare class GeoSessionManager {
|
|
430
|
+
private credentials;
|
|
431
|
+
private storage;
|
|
432
|
+
private maxRetries;
|
|
433
|
+
private baseRetryDelay;
|
|
434
|
+
constructor(credentials: DPDCredentials, storage?: GeoSessionStorage, options?: {
|
|
435
|
+
maxRetries?: number;
|
|
436
|
+
baseRetryDelay?: number;
|
|
437
|
+
});
|
|
438
|
+
getValidGeoSession(): Promise<string>;
|
|
439
|
+
refreshGeoSession(): Promise<string>;
|
|
440
|
+
clearGeoSession(): Promise<void>;
|
|
441
|
+
private isSessionValid;
|
|
442
|
+
private authenticateWithRetry;
|
|
443
|
+
private authenticate;
|
|
444
|
+
private delay;
|
|
445
|
+
}
|
|
411
446
|
|
|
412
447
|
declare function createShipment(credentials: DPDCredentials, params: CreateShipmentParams, businessConfig: any): Promise<CreateShipmentResult>;
|
|
413
448
|
declare function generateLabel(credentials: DPDCredentials, params: GenerateLabelParams): Promise<GenerateLabelResult>;
|
|
@@ -498,4 +533,4 @@ declare function loggedOperation<T>(params: {
|
|
|
498
533
|
headers?: Record<string, string>;
|
|
499
534
|
}>): Promise<T>;
|
|
500
535
|
|
|
501
|
-
export { type BusinessConfig, type CreateShipmentParams, type CreateShipmentResult, type DPDAddress, type DPDAuthResponse, type DPDConsignment, type DPDContact, type DPDCredentials, type DPDError, type DPDLabelRequest, type DPDLabelResponse, type DPDLogDocument, type DPDModuleConfig, type DPDParcel, _default as DPDService, type DPDServiceCode, type DPDShipmentRequest, type DPDShipmentResponse, DPD_API, type DatabaseAdapter, type GenerateLabelParams, type GenerateLabelResult, type LabelConfig, type LogFilters, type NotificationConfig, type PricingConfig, SERVICE_DESCRIPTIONS, SERVICE_NAMES, type SavedAddress, type ServiceConfig, type ShipmentStatus, type ShipmentStatusUpdate, type ShippingData, type StorageAdapter, type TimestampType, type TrackShipmentParams, type TrackShipmentResult, type ValidateAddressParams, type ValidateAddressResult, authenticate, authenticatedRequest, calculateDPDCost, calculateDeliveryFee, calculateParcels, clearGeoSession, configureLogger, createCompleteShipment, createDPDConfig, createShipment, deleteSavedAddress, generateAndUploadLabel, generateConsignmentRef, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode };
|
|
536
|
+
export { type BusinessConfig, type CreateShipmentParams, type CreateShipmentResult, type DPDAddress, type DPDAuthResponse, type DPDConsignment, type DPDContact, type DPDCredentials, type DPDError, type DPDLabelRequest, type DPDLabelResponse, type DPDLogDocument, type DPDModuleConfig, type DPDParcel, _default as DPDService, type DPDServiceCode, type DPDShipmentRequest, type DPDShipmentResponse, DPD_API, type DatabaseAdapter, type GenerateLabelParams, type GenerateLabelResult, GeoSessionManager, type GeoSessionStorage, InMemoryGeoSessionStorage, type LabelConfig, type LogFilters, type NotificationConfig, type PricingConfig, SERVICE_DESCRIPTIONS, SERVICE_NAMES, type SavedAddress, type ServiceConfig, type ShipmentStatus, type ShipmentStatusUpdate, type ShippingData, type StorageAdapter, type TimestampType, type TrackShipmentParams, type TrackShipmentResult, type ValidateAddressParams, type ValidateAddressResult, authenticate, authenticatedRequest, calculateDPDCost, calculateDeliveryFee, calculateParcels, clearGeoSession, configureLogger, createCompleteShipment, createDPDConfig, createShipment, deleteSavedAddress, generateAndUploadLabel, generateConsignmentRef, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,8 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DPDService: () => dpd_service_default,
|
|
24
24
|
DPD_API: () => DPD_API,
|
|
25
|
+
GeoSessionManager: () => GeoSessionManager,
|
|
26
|
+
InMemoryGeoSessionStorage: () => InMemoryGeoSessionStorage,
|
|
25
27
|
SERVICE_DESCRIPTIONS: () => SERVICE_DESCRIPTIONS,
|
|
26
28
|
SERVICE_NAMES: () => SERVICE_NAMES,
|
|
27
29
|
authenticate: () => authenticate,
|
|
@@ -69,6 +71,28 @@ __export(index_exports, {
|
|
|
69
71
|
});
|
|
70
72
|
module.exports = __toCommonJS(index_exports);
|
|
71
73
|
|
|
74
|
+
// src/types/index.ts
|
|
75
|
+
var InMemoryGeoSessionStorage = class {
|
|
76
|
+
constructor() {
|
|
77
|
+
this.geoSession = null;
|
|
78
|
+
this.expiry = null;
|
|
79
|
+
}
|
|
80
|
+
async get() {
|
|
81
|
+
if (!this.geoSession || !this.expiry) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return { geoSession: this.geoSession, expiry: this.expiry };
|
|
85
|
+
}
|
|
86
|
+
async set(geoSession, expiry) {
|
|
87
|
+
this.geoSession = geoSession;
|
|
88
|
+
this.expiry = expiry;
|
|
89
|
+
}
|
|
90
|
+
async clear() {
|
|
91
|
+
this.geoSession = null;
|
|
92
|
+
this.expiry = null;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
72
96
|
// src/config/index.ts
|
|
73
97
|
var DPD_API = {
|
|
74
98
|
BASE_URL: "https://api.dpdlocal.co.uk",
|
|
@@ -421,6 +445,164 @@ async function testConnection(credentials) {
|
|
|
421
445
|
};
|
|
422
446
|
}
|
|
423
447
|
}
|
|
448
|
+
var GeoSessionManager = class {
|
|
449
|
+
/**
|
|
450
|
+
* Create a new Geo Session Manager
|
|
451
|
+
*
|
|
452
|
+
* @param credentials - DPD API credentials
|
|
453
|
+
* @param storage - Storage adapter for persistence (optional, defaults to in-memory)
|
|
454
|
+
* @param options - Configuration options
|
|
455
|
+
*/
|
|
456
|
+
constructor(credentials, storage, options) {
|
|
457
|
+
this.credentials = credentials;
|
|
458
|
+
this.storage = storage || new InMemoryGeoSessionStorage();
|
|
459
|
+
this.maxRetries = options?.maxRetries ?? 3;
|
|
460
|
+
this.baseRetryDelay = options?.baseRetryDelay ?? 2e3;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Get a valid geo session token
|
|
464
|
+
*
|
|
465
|
+
* - Loads from persistent storage if available and valid
|
|
466
|
+
* - Automatically refreshes if expired or not found
|
|
467
|
+
* - Retries with exponential backoff on failure
|
|
468
|
+
* - Saves to persistent storage after refresh
|
|
469
|
+
*
|
|
470
|
+
* @returns Valid geo session token
|
|
471
|
+
* @throws Error if authentication fails after retries
|
|
472
|
+
*/
|
|
473
|
+
async getValidGeoSession() {
|
|
474
|
+
try {
|
|
475
|
+
const stored = await this.storage.get();
|
|
476
|
+
if (stored && this.isSessionValid(stored.geoSession, stored.expiry)) {
|
|
477
|
+
console.log("\u2705 Using cached geo session from storage");
|
|
478
|
+
return stored.geoSession;
|
|
479
|
+
}
|
|
480
|
+
console.log("\u{1F504} Fetching new geo session from DPD API...");
|
|
481
|
+
const { geoSession, expiry } = await this.authenticateWithRetry();
|
|
482
|
+
console.log("\u2705 Successfully fetched new geo session");
|
|
483
|
+
await this.storage.set(geoSession, expiry);
|
|
484
|
+
return geoSession;
|
|
485
|
+
} catch (error) {
|
|
486
|
+
console.error("\u274C Error managing geo session:", error);
|
|
487
|
+
throw new Error(
|
|
488
|
+
`Failed to get valid geo session: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Force refresh the geo session
|
|
494
|
+
* Clears cache and fetches a new token
|
|
495
|
+
*
|
|
496
|
+
* @returns New geo session token
|
|
497
|
+
*/
|
|
498
|
+
async refreshGeoSession() {
|
|
499
|
+
await this.storage.clear();
|
|
500
|
+
return this.getValidGeoSession();
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Clear stored geo session
|
|
504
|
+
*/
|
|
505
|
+
async clearGeoSession() {
|
|
506
|
+
await this.storage.clear();
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Check if a session is valid
|
|
510
|
+
*/
|
|
511
|
+
isSessionValid(geoSession, expiry) {
|
|
512
|
+
if (!geoSession || !expiry) {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
const now = /* @__PURE__ */ new Date();
|
|
516
|
+
const expiryDate = expiry instanceof Date ? expiry : new Date(expiry);
|
|
517
|
+
if (expiryDate <= now) {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
521
|
+
const expiryStartOfDay = new Date(
|
|
522
|
+
expiryDate.getFullYear(),
|
|
523
|
+
expiryDate.getMonth(),
|
|
524
|
+
expiryDate.getDate()
|
|
525
|
+
);
|
|
526
|
+
if (expiryStartOfDay.getTime() === startOfToday.getTime()) {
|
|
527
|
+
const sessionCreatedAt = new Date(expiryDate.getTime() - 90 * 60 * 1e3);
|
|
528
|
+
const hoursSinceCreation = (now.getTime() - sessionCreatedAt.getTime()) / (1e3 * 60 * 60);
|
|
529
|
+
if (hoursSinceCreation > 12) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Authenticate with retry logic and exponential backoff
|
|
537
|
+
*/
|
|
538
|
+
async authenticateWithRetry() {
|
|
539
|
+
let lastError = null;
|
|
540
|
+
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
|
541
|
+
try {
|
|
542
|
+
console.log(`\u{1F4E1} Attempt ${attempt}/${this.maxRetries} to fetch geo session...`);
|
|
543
|
+
const geoSession = await this.authenticate();
|
|
544
|
+
const expiry = new Date(Date.now() + 90 * 60 * 1e3);
|
|
545
|
+
return { geoSession, expiry };
|
|
546
|
+
} catch (error) {
|
|
547
|
+
lastError = error;
|
|
548
|
+
console.error(`\u274C Attempt ${attempt}/${this.maxRetries} failed:`, error);
|
|
549
|
+
if (attempt < this.maxRetries) {
|
|
550
|
+
const delay2 = this.baseRetryDelay * Math.pow(2, attempt - 1);
|
|
551
|
+
console.log(`\u23F3 Retrying in ${delay2}ms...`);
|
|
552
|
+
await this.delay(delay2);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
throw new Error(
|
|
557
|
+
`Failed to authenticate after ${this.maxRetries} attempts: ${lastError?.message || "Unknown error"}`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Authenticate with DPD API
|
|
562
|
+
*/
|
|
563
|
+
async authenticate() {
|
|
564
|
+
const { username, password } = this.credentials;
|
|
565
|
+
const authHeader = Buffer.from(`${username}:${password}`).toString("base64");
|
|
566
|
+
const response = await fetch(`${DPD_API.BASE_URL}${DPD_API.ENDPOINTS.AUTH}`, {
|
|
567
|
+
method: "POST",
|
|
568
|
+
headers: {
|
|
569
|
+
"Content-Type": "application/json",
|
|
570
|
+
Accept: "application/json",
|
|
571
|
+
Authorization: `Basic ${authHeader}`
|
|
572
|
+
},
|
|
573
|
+
signal: AbortSignal.timeout(DPD_API.TIMEOUT)
|
|
574
|
+
});
|
|
575
|
+
const raw = await response.text();
|
|
576
|
+
let payload;
|
|
577
|
+
try {
|
|
578
|
+
payload = raw ? JSON.parse(raw) : null;
|
|
579
|
+
} catch {
|
|
580
|
+
if (!response.ok) {
|
|
581
|
+
throw new Error(`Authentication failed: ${raw || response.statusText}`);
|
|
582
|
+
}
|
|
583
|
+
throw new Error("Invalid JSON response from DPD API");
|
|
584
|
+
}
|
|
585
|
+
if (!response.ok) {
|
|
586
|
+
throw new Error(
|
|
587
|
+
payload?.error?.errorMessage ?? `Authentication failed: ${response.status} ${response.statusText}`
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
if (payload?.error) {
|
|
591
|
+
throw new Error(payload.error.errorMessage ?? "Authentication failed");
|
|
592
|
+
}
|
|
593
|
+
const geoSession = payload?.data?.geoSession;
|
|
594
|
+
if (!geoSession) {
|
|
595
|
+
throw new Error("No GeoSession token received from DPD");
|
|
596
|
+
}
|
|
597
|
+
return geoSession;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Delay helper for retry backoff
|
|
601
|
+
*/
|
|
602
|
+
delay(ms) {
|
|
603
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
604
|
+
}
|
|
605
|
+
};
|
|
424
606
|
|
|
425
607
|
// src/utils/getAcceptHeader.ts
|
|
426
608
|
function getAcceptHeader(format) {
|
|
@@ -1073,6 +1255,8 @@ function logToConsole(logData) {
|
|
|
1073
1255
|
0 && (module.exports = {
|
|
1074
1256
|
DPDService,
|
|
1075
1257
|
DPD_API,
|
|
1258
|
+
GeoSessionManager,
|
|
1259
|
+
InMemoryGeoSessionStorage,
|
|
1076
1260
|
SERVICE_DESCRIPTIONS,
|
|
1077
1261
|
SERVICE_NAMES,
|
|
1078
1262
|
authenticate,
|
|
@@ -1125,7 +1309,7 @@ function logToConsole(logData) {
|
|
|
1125
1309
|
* Database-agnostic and framework-independent
|
|
1126
1310
|
*
|
|
1127
1311
|
* @package @jazzdev/dpd-local-sdk
|
|
1128
|
-
* @version 1.0
|
|
1312
|
+
* @version 1.1.0
|
|
1129
1313
|
* @author Taiow Babarinde <babsman4all@gmail.com>
|
|
1130
1314
|
* @license MIT
|
|
1131
1315
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
// src/types/index.ts
|
|
2
|
+
var InMemoryGeoSessionStorage = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.geoSession = null;
|
|
5
|
+
this.expiry = null;
|
|
6
|
+
}
|
|
7
|
+
async get() {
|
|
8
|
+
if (!this.geoSession || !this.expiry) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return { geoSession: this.geoSession, expiry: this.expiry };
|
|
12
|
+
}
|
|
13
|
+
async set(geoSession, expiry) {
|
|
14
|
+
this.geoSession = geoSession;
|
|
15
|
+
this.expiry = expiry;
|
|
16
|
+
}
|
|
17
|
+
async clear() {
|
|
18
|
+
this.geoSession = null;
|
|
19
|
+
this.expiry = null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
1
23
|
// src/config/index.ts
|
|
2
24
|
var DPD_API = {
|
|
3
25
|
BASE_URL: "https://api.dpdlocal.co.uk",
|
|
@@ -350,6 +372,164 @@ async function testConnection(credentials) {
|
|
|
350
372
|
};
|
|
351
373
|
}
|
|
352
374
|
}
|
|
375
|
+
var GeoSessionManager = class {
|
|
376
|
+
/**
|
|
377
|
+
* Create a new Geo Session Manager
|
|
378
|
+
*
|
|
379
|
+
* @param credentials - DPD API credentials
|
|
380
|
+
* @param storage - Storage adapter for persistence (optional, defaults to in-memory)
|
|
381
|
+
* @param options - Configuration options
|
|
382
|
+
*/
|
|
383
|
+
constructor(credentials, storage, options) {
|
|
384
|
+
this.credentials = credentials;
|
|
385
|
+
this.storage = storage || new InMemoryGeoSessionStorage();
|
|
386
|
+
this.maxRetries = options?.maxRetries ?? 3;
|
|
387
|
+
this.baseRetryDelay = options?.baseRetryDelay ?? 2e3;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get a valid geo session token
|
|
391
|
+
*
|
|
392
|
+
* - Loads from persistent storage if available and valid
|
|
393
|
+
* - Automatically refreshes if expired or not found
|
|
394
|
+
* - Retries with exponential backoff on failure
|
|
395
|
+
* - Saves to persistent storage after refresh
|
|
396
|
+
*
|
|
397
|
+
* @returns Valid geo session token
|
|
398
|
+
* @throws Error if authentication fails after retries
|
|
399
|
+
*/
|
|
400
|
+
async getValidGeoSession() {
|
|
401
|
+
try {
|
|
402
|
+
const stored = await this.storage.get();
|
|
403
|
+
if (stored && this.isSessionValid(stored.geoSession, stored.expiry)) {
|
|
404
|
+
console.log("\u2705 Using cached geo session from storage");
|
|
405
|
+
return stored.geoSession;
|
|
406
|
+
}
|
|
407
|
+
console.log("\u{1F504} Fetching new geo session from DPD API...");
|
|
408
|
+
const { geoSession, expiry } = await this.authenticateWithRetry();
|
|
409
|
+
console.log("\u2705 Successfully fetched new geo session");
|
|
410
|
+
await this.storage.set(geoSession, expiry);
|
|
411
|
+
return geoSession;
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.error("\u274C Error managing geo session:", error);
|
|
414
|
+
throw new Error(
|
|
415
|
+
`Failed to get valid geo session: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Force refresh the geo session
|
|
421
|
+
* Clears cache and fetches a new token
|
|
422
|
+
*
|
|
423
|
+
* @returns New geo session token
|
|
424
|
+
*/
|
|
425
|
+
async refreshGeoSession() {
|
|
426
|
+
await this.storage.clear();
|
|
427
|
+
return this.getValidGeoSession();
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Clear stored geo session
|
|
431
|
+
*/
|
|
432
|
+
async clearGeoSession() {
|
|
433
|
+
await this.storage.clear();
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Check if a session is valid
|
|
437
|
+
*/
|
|
438
|
+
isSessionValid(geoSession, expiry) {
|
|
439
|
+
if (!geoSession || !expiry) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
const now = /* @__PURE__ */ new Date();
|
|
443
|
+
const expiryDate = expiry instanceof Date ? expiry : new Date(expiry);
|
|
444
|
+
if (expiryDate <= now) {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
448
|
+
const expiryStartOfDay = new Date(
|
|
449
|
+
expiryDate.getFullYear(),
|
|
450
|
+
expiryDate.getMonth(),
|
|
451
|
+
expiryDate.getDate()
|
|
452
|
+
);
|
|
453
|
+
if (expiryStartOfDay.getTime() === startOfToday.getTime()) {
|
|
454
|
+
const sessionCreatedAt = new Date(expiryDate.getTime() - 90 * 60 * 1e3);
|
|
455
|
+
const hoursSinceCreation = (now.getTime() - sessionCreatedAt.getTime()) / (1e3 * 60 * 60);
|
|
456
|
+
if (hoursSinceCreation > 12) {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Authenticate with retry logic and exponential backoff
|
|
464
|
+
*/
|
|
465
|
+
async authenticateWithRetry() {
|
|
466
|
+
let lastError = null;
|
|
467
|
+
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
|
468
|
+
try {
|
|
469
|
+
console.log(`\u{1F4E1} Attempt ${attempt}/${this.maxRetries} to fetch geo session...`);
|
|
470
|
+
const geoSession = await this.authenticate();
|
|
471
|
+
const expiry = new Date(Date.now() + 90 * 60 * 1e3);
|
|
472
|
+
return { geoSession, expiry };
|
|
473
|
+
} catch (error) {
|
|
474
|
+
lastError = error;
|
|
475
|
+
console.error(`\u274C Attempt ${attempt}/${this.maxRetries} failed:`, error);
|
|
476
|
+
if (attempt < this.maxRetries) {
|
|
477
|
+
const delay2 = this.baseRetryDelay * Math.pow(2, attempt - 1);
|
|
478
|
+
console.log(`\u23F3 Retrying in ${delay2}ms...`);
|
|
479
|
+
await this.delay(delay2);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
throw new Error(
|
|
484
|
+
`Failed to authenticate after ${this.maxRetries} attempts: ${lastError?.message || "Unknown error"}`
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Authenticate with DPD API
|
|
489
|
+
*/
|
|
490
|
+
async authenticate() {
|
|
491
|
+
const { username, password } = this.credentials;
|
|
492
|
+
const authHeader = Buffer.from(`${username}:${password}`).toString("base64");
|
|
493
|
+
const response = await fetch(`${DPD_API.BASE_URL}${DPD_API.ENDPOINTS.AUTH}`, {
|
|
494
|
+
method: "POST",
|
|
495
|
+
headers: {
|
|
496
|
+
"Content-Type": "application/json",
|
|
497
|
+
Accept: "application/json",
|
|
498
|
+
Authorization: `Basic ${authHeader}`
|
|
499
|
+
},
|
|
500
|
+
signal: AbortSignal.timeout(DPD_API.TIMEOUT)
|
|
501
|
+
});
|
|
502
|
+
const raw = await response.text();
|
|
503
|
+
let payload;
|
|
504
|
+
try {
|
|
505
|
+
payload = raw ? JSON.parse(raw) : null;
|
|
506
|
+
} catch {
|
|
507
|
+
if (!response.ok) {
|
|
508
|
+
throw new Error(`Authentication failed: ${raw || response.statusText}`);
|
|
509
|
+
}
|
|
510
|
+
throw new Error("Invalid JSON response from DPD API");
|
|
511
|
+
}
|
|
512
|
+
if (!response.ok) {
|
|
513
|
+
throw new Error(
|
|
514
|
+
payload?.error?.errorMessage ?? `Authentication failed: ${response.status} ${response.statusText}`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
if (payload?.error) {
|
|
518
|
+
throw new Error(payload.error.errorMessage ?? "Authentication failed");
|
|
519
|
+
}
|
|
520
|
+
const geoSession = payload?.data?.geoSession;
|
|
521
|
+
if (!geoSession) {
|
|
522
|
+
throw new Error("No GeoSession token received from DPD");
|
|
523
|
+
}
|
|
524
|
+
return geoSession;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Delay helper for retry backoff
|
|
528
|
+
*/
|
|
529
|
+
delay(ms) {
|
|
530
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
531
|
+
}
|
|
532
|
+
};
|
|
353
533
|
|
|
354
534
|
// src/utils/getAcceptHeader.ts
|
|
355
535
|
function getAcceptHeader(format) {
|
|
@@ -1001,6 +1181,8 @@ function logToConsole(logData) {
|
|
|
1001
1181
|
export {
|
|
1002
1182
|
dpd_service_default as DPDService,
|
|
1003
1183
|
DPD_API,
|
|
1184
|
+
GeoSessionManager,
|
|
1185
|
+
InMemoryGeoSessionStorage,
|
|
1004
1186
|
SERVICE_DESCRIPTIONS,
|
|
1005
1187
|
SERVICE_NAMES,
|
|
1006
1188
|
authenticate,
|
|
@@ -1053,7 +1235,7 @@ export {
|
|
|
1053
1235
|
* Database-agnostic and framework-independent
|
|
1054
1236
|
*
|
|
1055
1237
|
* @package @jazzdev/dpd-local-sdk
|
|
1056
|
-
* @version 1.0
|
|
1238
|
+
* @version 1.1.0
|
|
1057
1239
|
* @author Taiow Babarinde <babsman4all@gmail.com>
|
|
1058
1240
|
* @license MIT
|
|
1059
1241
|
*/
|
package/package.json
CHANGED