@jazzdev/dpd-local-sdk 1.0.11 → 1.0.13

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > TypeScript SDK for integrating DPD Local shipping services into your application. Database-agnostic, framework-independent, and production-ready.
4
4
 
5
- [![npm version](https://badge.fury.io/js/%40your-org%2Fdpd-local-sdk.svg)](https://www.npmjs.com/package/@jazzdev/dpd-local-sdk)
5
+ [![npm version](https://badge.fury.io/js/%40jazzdev%2Fdpd-local-sdk.svg)](https://www.npmjs.com/package/@jazzdev/dpd-local-sdk)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.3+-blue.svg)](https://www.typescriptlang.org/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
 
@@ -201,6 +201,9 @@ const result = await createCompleteShipment(
201
201
 
202
202
  if (result.success) {
203
203
  console.log('Shipment created!');
204
+ console.log('Shipment ID:', result.shipmentId); // Save this for label regeneration
205
+ console.log('Consignment Number:', result.consignmentNumber); // 10-digit reference
206
+ console.log('Parcel Number:', result.parcelNumber); // 14-digit tracking number
204
207
  console.log('Tracking URL:', result.trackingUrl);
205
208
  console.log('Label URL:', result.labelUrl);
206
209
  } else {
@@ -208,6 +211,71 @@ if (result.success) {
208
211
  }
209
212
  ```
210
213
 
214
+ ## Understanding DPD Identifiers
215
+
216
+ When you create a shipment with DPD, you receive three different identifiers:
217
+
218
+ 1. **shipmentId** - DPD's internal shipment identifier (numeric)
219
+ - Required for label regeneration
220
+ - Save this in your database!
221
+
222
+ 2. **consignmentNumber** - 10-digit reference number (e.g., `6504286395`)
223
+ - Used for internal tracking
224
+
225
+ 3. **parcelNumber** - 14-digit tracking number (e.g., `15976504286395`)
226
+ - What customers use to track their delivery
227
+ - Used in the tracking URL
228
+
229
+ ```typescript
230
+ // When creating a shipment, save ALL identifiers:
231
+ const result = await createCompleteShipment(...);
232
+
233
+ if (result.success) {
234
+ await saveToDatabase({
235
+ shipmentId: result.shipmentId, // Save for label regeneration
236
+ consignmentNumber: result.consignmentNumber,
237
+ parcelNumber: result.parcelNumber, // Give to customer for tracking
238
+ trackingUrl: result.trackingUrl,
239
+ });
240
+ }
241
+ ```
242
+
243
+ ### Regenerating Labels
244
+
245
+ If you need to regenerate a label (e.g., printer jam), use the `shipmentId`:
246
+
247
+ ```typescript
248
+ import { generateLabel } from '@jazzdev/dpd-local-sdk';
249
+
250
+ const result = await generateLabel(credentials, {
251
+ shipmentId: '12345678', // Use the shipmentId, not consignment/parcel number
252
+ labelFormat: 'zpl' // or 'clp', 'html'
253
+ });
254
+ ```
255
+
256
+ ### Testing Label Generation
257
+
258
+ A test script is included to verify label generation:
259
+
260
+ ```bash
261
+ # Using npm script
262
+ npm run test:label <shipmentId> [format]
263
+
264
+ # Or directly with tsx
265
+ npx tsx test-label-generation.ts <shipmentId> [format]
266
+
267
+ # Examples
268
+ npm run test:label 12345678
269
+ npm run test:label 12345678 html
270
+ npm run test:label 12345678 zpl
271
+ ```
272
+
273
+ The script will:
274
+ - Validate your DPD credentials
275
+ - Generate the label in the specified format
276
+ - Save it to a file (`label-<shipmentId>.<format>`)
277
+ - Display a preview of the label content
278
+
211
279
  ## API Reference
212
280
 
213
281
  ### Configuration
@@ -351,39 +419,35 @@ app.post('/api/shipping/create', async (req, res) => {
351
419
  });
352
420
  ```
353
421
 
354
- ## Environment Variables
355
-
356
- ```env
357
- # DPD Credentials (Required)
358
- DPD_ACCOUNT_NUMBER=your_account_number
359
- DPD_USERNAME=your_username
360
- DPD_PASSWORD=your_password
361
-
362
- # Encryption (Required in production)
363
- DPD_ENCRYPTION_KEY=your_32_byte_hex_key
364
-
365
- # Optional
366
- NODE_ENV=production
367
- ```
422
+ ## Configuration
368
423
 
369
- ### Generating Encryption Key
424
+ The SDK requires DPD credentials which you pass directly to the configuration:
370
425
 
371
426
  ```typescript
372
- import { generateEncryptionKey } from '@jazzdev/dpd-local-sdk';
373
-
374
- const key = generateEncryptionKey();
375
- console.log('DPD_ENCRYPTION_KEY=' + key);
427
+ const config = createDPDConfig({
428
+ credentials: {
429
+ accountNumber: 'YOUR_ACCOUNT_NUMBER',
430
+ username: 'YOUR_USERNAME',
431
+ password: 'YOUR_PASSWORD',
432
+ },
433
+ business: {
434
+ // Your business details
435
+ }
436
+ });
376
437
  ```
377
438
 
439
+ **Important**: Credentials are passed programmatically - the SDK itself doesn't read from environment variables. How you store and retrieve credentials in your application is up to you.
440
+
378
441
  ## Adapter Examples
379
442
 
380
443
  Complete adapter examples are available in the `examples/` directory:
381
444
 
382
- - `examples/firestore-adapter.ts` - Firestore implementation
383
- - `examples/mongodb-adapter.ts` - MongoDB implementation
384
- - `examples/postgresql-adapter.ts` - PostgreSQL implementation
385
- - `examples/firebase-storage-adapter.ts` - Firebase Storage implementation
386
- - `examples/s3-storage-adapter.ts` - AWS S3 implementation
445
+ - `examples/basic-usage.ts` - Complete workflow example
446
+ - `examples/regenerate-label.ts` - Label regeneration example
447
+ - `examples/firestore-adapter.ts` - Firestore database adapter
448
+ - `examples/firebase-storage-adapter.ts` - Firebase Storage adapter
449
+
450
+ For other databases (MongoDB, PostgreSQL, etc.), implement the `DatabaseAdapter` interface following the Firestore example as a reference. The adapter pattern is database-agnostic by design.
387
451
 
388
452
  ## Error Handling
389
453
 
@@ -429,7 +493,7 @@ import type {
429
493
 
430
494
  ## Contributing
431
495
 
432
- Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details.
496
+ Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/TheJazzDev/dpd-local-sdk).
433
497
 
434
498
  ## License
435
499
 
@@ -438,8 +502,8 @@ MIT © [Taiow Babarinde](https://github.com/TheJazzDev)
438
502
  ## Support
439
503
 
440
504
  - 📧 Email: babsman4all@gmail.com
441
- - 🐛 Issues: [GitHub Issues](https://github.com/TheJazzDev/dpd-local-sdk.git/issues)
505
+ - 🐛 Issues: [GitHub Issues](https://github.com/TheJazzDev/dpd-local-sdk/issues)
442
506
 
443
507
  ## Changelog
444
508
 
445
- See [CHANGELOG.md](CHANGELOG.md) for release history.
509
+ See [CHANGELOG.md](https://github.com/TheJazzDev/dpd-local-sdk/blob/main/CHANGELOG.md) for release history.
package/dist/index.d.mts CHANGED
@@ -452,30 +452,6 @@ declare const _default: {
452
452
  getAuthStatus: typeof getAuthStatus;
453
453
  };
454
454
 
455
- declare function generateEncryptionKey(): string;
456
- declare function encrypt(text: string): string;
457
- declare function decrypt(encryptedHex: string): string;
458
- declare function encryptCredentials(credentials: {
459
- accountNumber: string;
460
- username: string;
461
- password: string;
462
- }): {
463
- accountNumber: string;
464
- username: string;
465
- passwordHash: string;
466
- };
467
- declare function decryptCredentials(encryptedCredentials: {
468
- accountNumber: string;
469
- username: string;
470
- passwordHash: string;
471
- }): {
472
- accountNumber: string;
473
- username: string;
474
- password: string;
475
- };
476
- declare function hash(data: string): string;
477
- declare function verifyHash(data: string, hashToVerify: string): boolean;
478
-
479
455
  interface LoggerConfig {
480
456
  enabled: boolean;
481
457
  logToConsole: boolean;
@@ -522,4 +498,4 @@ declare function loggedOperation<T>(params: {
522
498
  headers?: Record<string, string>;
523
499
  }>): Promise<T>;
524
500
 
525
- 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, decrypt, decryptCredentials, deleteSavedAddress, encrypt, encryptCredentials, generateAndUploadLabel, generateConsignmentRef, generateEncryptionKey, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, hash, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode, verifyHash };
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 };
package/dist/index.d.ts CHANGED
@@ -452,30 +452,6 @@ declare const _default: {
452
452
  getAuthStatus: typeof getAuthStatus;
453
453
  };
454
454
 
455
- declare function generateEncryptionKey(): string;
456
- declare function encrypt(text: string): string;
457
- declare function decrypt(encryptedHex: string): string;
458
- declare function encryptCredentials(credentials: {
459
- accountNumber: string;
460
- username: string;
461
- password: string;
462
- }): {
463
- accountNumber: string;
464
- username: string;
465
- passwordHash: string;
466
- };
467
- declare function decryptCredentials(encryptedCredentials: {
468
- accountNumber: string;
469
- username: string;
470
- passwordHash: string;
471
- }): {
472
- accountNumber: string;
473
- username: string;
474
- password: string;
475
- };
476
- declare function hash(data: string): string;
477
- declare function verifyHash(data: string, hashToVerify: string): boolean;
478
-
479
455
  interface LoggerConfig {
480
456
  enabled: boolean;
481
457
  logToConsole: boolean;
@@ -522,4 +498,4 @@ declare function loggedOperation<T>(params: {
522
498
  headers?: Record<string, string>;
523
499
  }>): Promise<T>;
524
500
 
525
- 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, decrypt, decryptCredentials, deleteSavedAddress, encrypt, encryptCredentials, generateAndUploadLabel, generateConsignmentRef, generateEncryptionKey, generateLabel, getAuthStatus, getEstimatedDeliveryDate, getGeoSession, getLabelUrl, getNextCollectionDate, getSavedAddress, getSavedAddresses, getServiceDescription, getServiceName, getTokenExpiry, getTrackingUrl, hasValidToken, hash, isValidServiceCode, logOperation, loggedOperation, meetsMinimumOrderValue, qualifiesForFreeDelivery, regenerateLabel, saveAddress, setLoggerAdapter, startTimer, testConnection, testDPDConnection, trackShipment, updateSavedAddress, validateAddress, validateDeliveryAddress, validateServiceCode, verifyHash };
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 };
package/dist/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
@@ -44,14 +34,9 @@ __export(index_exports, {
44
34
  createCompleteShipment: () => createCompleteShipment,
45
35
  createDPDConfig: () => createDPDConfig,
46
36
  createShipment: () => createShipment,
47
- decrypt: () => decrypt,
48
- decryptCredentials: () => decryptCredentials,
49
37
  deleteSavedAddress: () => deleteSavedAddress,
50
- encrypt: () => encrypt,
51
- encryptCredentials: () => encryptCredentials,
52
38
  generateAndUploadLabel: () => generateAndUploadLabel,
53
39
  generateConsignmentRef: () => generateConsignmentRef,
54
- generateEncryptionKey: () => generateEncryptionKey,
55
40
  generateLabel: () => generateLabel,
56
41
  getAuthStatus: () => getAuthStatus,
57
42
  getEstimatedDeliveryDate: () => getEstimatedDeliveryDate,
@@ -65,7 +50,6 @@ __export(index_exports, {
65
50
  getTokenExpiry: () => getTokenExpiry,
66
51
  getTrackingUrl: () => getTrackingUrl,
67
52
  hasValidToken: () => hasValidToken,
68
- hash: () => hash,
69
53
  isValidServiceCode: () => isValidServiceCode,
70
54
  logOperation: () => logOperation,
71
55
  loggedOperation: () => loggedOperation,
@@ -81,8 +65,7 @@ __export(index_exports, {
81
65
  updateSavedAddress: () => updateSavedAddress,
82
66
  validateAddress: () => validateAddress,
83
67
  validateDeliveryAddress: () => validateDeliveryAddress,
84
- validateServiceCode: () => validateServiceCode,
85
- verifyHash: () => verifyHash
68
+ validateServiceCode: () => validateServiceCode
86
69
  });
87
70
  module.exports = __toCommonJS(index_exports);
88
71
 
@@ -324,10 +307,6 @@ async function authenticatedRequest(credentials, options) {
324
307
  const isLabelRequest = acceptHeader === "text/vnd.zebra-zpl" || acceptHeader === "text/vnd.citizen-clp" || acceptHeader === "text/vnd.eltron-epl" || acceptHeader === "text/html";
325
308
  let data = null;
326
309
  if (isLabelRequest) {
327
- console.log("\u{1F3F7}\uFE0F [SDK auth] Label request detected");
328
- console.log(` HTTP Status: ${response.status} ${response.statusText}`);
329
- console.log(` Response length: ${raw.length} chars`);
330
- console.log(` Response preview (first 300 chars): ${raw.substring(0, 300)}`);
331
310
  if (!response.ok) {
332
311
  throw new Error(
333
312
  `Label request failed: ${response.status} ${response.statusText}`
@@ -335,20 +314,18 @@ async function authenticatedRequest(credentials, options) {
335
314
  }
336
315
  try {
337
316
  const parsed = JSON.parse(raw);
338
- console.log("\u{1F50D} [SDK auth] Label request - parsed JSON response:", parsed);
339
317
  if (parsed?.error || parsed?.data === null) {
340
- console.log("\u26A0\uFE0F [SDK auth] Detected error response:", {
341
- hasError: !!parsed?.error,
342
- dataIsNull: parsed?.data === null,
343
- errorObj: parsed?.error
344
- });
345
318
  const errorObj = parsed?.error;
346
319
  let errorMessage = "Label generation failed";
347
320
  let errorCode = "UNKNOWN";
348
321
  if (errorObj) {
349
- if (errorObj.errorMessage) {
322
+ if (Array.isArray(errorObj)) {
323
+ const firstError = errorObj[0];
324
+ errorMessage = firstError?.errorMessage || errorMessage;
325
+ errorCode = firstError?.errorCode || errorCode;
326
+ } else if (errorObj.errorMessage) {
350
327
  errorMessage = errorObj.errorMessage;
351
- errorCode = errorObj.errorCode || errorObj.name || "UNKNOWN";
328
+ errorCode = errorObj.errorCode || errorObj.name || errorCode;
352
329
  } else if (errorObj.name) {
353
330
  errorMessage = errorObj.name;
354
331
  errorCode = errorObj.name;
@@ -359,7 +336,6 @@ async function authenticatedRequest(credentials, options) {
359
336
  }
360
337
  }
361
338
  }
362
- console.error(`\u274C [SDK auth] Throwing error - Code: ${errorCode}, Message: ${errorMessage}`);
363
339
  throw new Error(`DPD API Error ${errorCode}: ${errorMessage}`);
364
340
  }
365
341
  if (parsed?.data) {
@@ -574,12 +550,7 @@ async function createShipment(credentials, params, businessConfig) {
574
550
  async function generateLabel(credentials, params) {
575
551
  try {
576
552
  const { shipmentId, labelFormat } = params;
577
- console.log("\n\u{1F3F7}\uFE0F [SDK generateLabel] Starting label generation");
578
- console.log(` Shipment ID: ${shipmentId} (type: ${typeof shipmentId})`);
579
- console.log(` Format: ${labelFormat}`);
580
- console.log(` Accept Header: ${getAcceptHeader(labelFormat)}`);
581
553
  const endpoint = `${DPD_API.ENDPOINTS.LABEL}/${shipmentId}/label/`;
582
- console.log(` Endpoint: ${endpoint}`);
583
554
  const response = await authenticatedRequest(credentials, {
584
555
  method: "GET",
585
556
  endpoint,
@@ -587,35 +558,17 @@ async function generateLabel(credentials, params) {
587
558
  Accept: getAcceptHeader(labelFormat)
588
559
  }
589
560
  });
590
- console.log("\u{1F4E6} [SDK generateLabel] Raw response type:", typeof response);
591
- console.log(
592
- "\u{1F4E6} [SDK generateLabel] Raw response:",
593
- typeof response === "string" ? `String (${response.length} chars): ${response.substring(0, 200)}...` : response
594
- );
595
- if (typeof response === "object" && response.error) {
596
- const errorObj = response.error;
597
- console.error("\u274C [SDK generateLabel] DPD returned error object:", errorObj);
598
- const errorMessage = errorObj.errorMessage || errorObj.name || JSON.stringify(errorObj);
599
- return {
600
- success: false,
601
- error: `DPD API error: ${errorMessage}`
602
- };
603
- }
604
- if (!response || typeof response === "object" && !response.data) {
605
- console.error("\u274C [SDK generateLabel] No label data in response");
561
+ if (!response || typeof response !== "string") {
606
562
  return {
607
563
  success: false,
608
564
  error: "No label data received from DPD"
609
565
  };
610
566
  }
611
- const labelData = typeof response === "string" ? response : response.data;
612
- console.log(`\u2705 [SDK generateLabel] Success! Label data length: ${labelData.length} chars`);
613
567
  return {
614
568
  success: true,
615
- labelData
569
+ labelData: response
616
570
  };
617
571
  } catch (error) {
618
- console.error("\u{1F4A5} [SDK generateLabel] Exception:", error);
619
572
  return {
620
573
  success: false,
621
574
  error: error instanceof Error ? error.message : "Unknown error"
@@ -760,7 +713,7 @@ async function createCompleteShipment(orderId, params, config2, dbAdapter, stora
760
713
  }
761
714
  const labelResult = await generateAndUploadLabel(
762
715
  shipmentResult.shipmentId,
763
- "zpl",
716
+ config2.labels.format,
764
717
  config2.credentials,
765
718
  storageAdapter
766
719
  );
@@ -953,97 +906,6 @@ var dpd_service_default = {
953
906
  getAuthStatus
954
907
  };
955
908
 
956
- // src/utils/encryption.ts
957
- var import_crypto = __toESM(require("crypto"));
958
- var ALGORITHM = "aes-256-gcm";
959
- var KEY_LENGTH = 32;
960
- var IV_LENGTH = 16;
961
- var SALT_LENGTH = 64;
962
- var TAG_LENGTH = 16;
963
- var TAG_POSITION = SALT_LENGTH + IV_LENGTH;
964
- var ENCRYPTED_POSITION = TAG_POSITION + TAG_LENGTH;
965
- function getEncryptionKey() {
966
- const envKey = process.env.DPD_ENCRYPTION_KEY;
967
- if (envKey) {
968
- return Buffer.from(envKey, "hex");
969
- }
970
- if (process.env.NODE_ENV !== "production") {
971
- console.warn(
972
- "\u26A0\uFE0F Using default encryption key. Set DPD_ENCRYPTION_KEY in production!"
973
- );
974
- return import_crypto.default.scryptSync("dpd-dev-key", "salt", KEY_LENGTH);
975
- }
976
- throw new Error(
977
- "DPD_ENCRYPTION_KEY environment variable is required in production"
978
- );
979
- }
980
- function generateEncryptionKey() {
981
- const key = import_crypto.default.randomBytes(KEY_LENGTH);
982
- return key.toString("hex");
983
- }
984
- function encrypt(text) {
985
- try {
986
- const salt = import_crypto.default.randomBytes(SALT_LENGTH);
987
- const iv = import_crypto.default.randomBytes(IV_LENGTH);
988
- const key = import_crypto.default.scryptSync(getEncryptionKey(), salt, KEY_LENGTH);
989
- const cipher = import_crypto.default.createCipheriv(ALGORITHM, key, iv);
990
- const encrypted = Buffer.concat([
991
- cipher.update(text, "utf8"),
992
- cipher.final()
993
- ]);
994
- const tag = cipher.getAuthTag();
995
- const result = Buffer.concat([salt, iv, tag, encrypted]);
996
- return result.toString("hex");
997
- } catch (error) {
998
- console.error("Encryption error:", error);
999
- throw new Error("Failed to encrypt data");
1000
- }
1001
- }
1002
- function decrypt(encryptedHex) {
1003
- try {
1004
- const data = Buffer.from(encryptedHex, "hex");
1005
- const salt = data.subarray(0, SALT_LENGTH);
1006
- const iv = data.subarray(SALT_LENGTH, TAG_POSITION);
1007
- const tag = data.subarray(TAG_POSITION, ENCRYPTED_POSITION);
1008
- const encrypted = data.subarray(ENCRYPTED_POSITION);
1009
- const key = import_crypto.default.scryptSync(getEncryptionKey(), salt, KEY_LENGTH);
1010
- const decipher = import_crypto.default.createDecipheriv(ALGORITHM, key, iv);
1011
- decipher.setAuthTag(tag);
1012
- const decrypted = Buffer.concat([
1013
- decipher.update(encrypted),
1014
- decipher.final()
1015
- ]);
1016
- return decrypted.toString("utf8");
1017
- } catch (error) {
1018
- console.error("Decryption error:", error);
1019
- throw new Error("Failed to decrypt data");
1020
- }
1021
- }
1022
- function encryptCredentials(credentials) {
1023
- return {
1024
- accountNumber: credentials.accountNumber,
1025
- username: credentials.username,
1026
- passwordHash: encrypt(credentials.password)
1027
- };
1028
- }
1029
- function decryptCredentials(encryptedCredentials) {
1030
- return {
1031
- accountNumber: encryptedCredentials.accountNumber,
1032
- username: encryptedCredentials.username,
1033
- password: decrypt(encryptedCredentials.passwordHash)
1034
- };
1035
- }
1036
- function hash(data) {
1037
- return import_crypto.default.createHash("sha256").update(data).digest("hex");
1038
- }
1039
- function verifyHash(data, hashToVerify) {
1040
- const computed = hash(data);
1041
- return import_crypto.default.timingSafeEqual(
1042
- Buffer.from(computed),
1043
- Buffer.from(hashToVerify)
1044
- );
1045
- }
1046
-
1047
909
  // src/utils/logger.ts
1048
910
  var defaultConfig = {
1049
911
  enabled: true,
@@ -1223,14 +1085,9 @@ function logToConsole(logData) {
1223
1085
  createCompleteShipment,
1224
1086
  createDPDConfig,
1225
1087
  createShipment,
1226
- decrypt,
1227
- decryptCredentials,
1228
1088
  deleteSavedAddress,
1229
- encrypt,
1230
- encryptCredentials,
1231
1089
  generateAndUploadLabel,
1232
1090
  generateConsignmentRef,
1233
- generateEncryptionKey,
1234
1091
  generateLabel,
1235
1092
  getAuthStatus,
1236
1093
  getEstimatedDeliveryDate,
@@ -1244,7 +1101,6 @@ function logToConsole(logData) {
1244
1101
  getTokenExpiry,
1245
1102
  getTrackingUrl,
1246
1103
  hasValidToken,
1247
- hash,
1248
1104
  isValidServiceCode,
1249
1105
  logOperation,
1250
1106
  loggedOperation,
@@ -1260,8 +1116,7 @@ function logToConsole(logData) {
1260
1116
  updateSavedAddress,
1261
1117
  validateAddress,
1262
1118
  validateDeliveryAddress,
1263
- validateServiceCode,
1264
- verifyHash
1119
+ validateServiceCode
1265
1120
  });
1266
1121
  /**
1267
1122
  * DPD Local SDK
@@ -1270,7 +1125,7 @@ function logToConsole(logData) {
1270
1125
  * Database-agnostic and framework-independent
1271
1126
  *
1272
1127
  * @package @jazzdev/dpd-local-sdk
1273
- * @version 1.0.0
1274
- * @author Your Name
1128
+ * @version 1.0.12
1129
+ * @author Taiow Babarinde <babsman4all@gmail.com>
1275
1130
  * @license MIT
1276
1131
  */
package/dist/index.mjs CHANGED
@@ -236,10 +236,6 @@ async function authenticatedRequest(credentials, options) {
236
236
  const isLabelRequest = acceptHeader === "text/vnd.zebra-zpl" || acceptHeader === "text/vnd.citizen-clp" || acceptHeader === "text/vnd.eltron-epl" || acceptHeader === "text/html";
237
237
  let data = null;
238
238
  if (isLabelRequest) {
239
- console.log("\u{1F3F7}\uFE0F [SDK auth] Label request detected");
240
- console.log(` HTTP Status: ${response.status} ${response.statusText}`);
241
- console.log(` Response length: ${raw.length} chars`);
242
- console.log(` Response preview (first 300 chars): ${raw.substring(0, 300)}`);
243
239
  if (!response.ok) {
244
240
  throw new Error(
245
241
  `Label request failed: ${response.status} ${response.statusText}`
@@ -247,20 +243,18 @@ async function authenticatedRequest(credentials, options) {
247
243
  }
248
244
  try {
249
245
  const parsed = JSON.parse(raw);
250
- console.log("\u{1F50D} [SDK auth] Label request - parsed JSON response:", parsed);
251
246
  if (parsed?.error || parsed?.data === null) {
252
- console.log("\u26A0\uFE0F [SDK auth] Detected error response:", {
253
- hasError: !!parsed?.error,
254
- dataIsNull: parsed?.data === null,
255
- errorObj: parsed?.error
256
- });
257
247
  const errorObj = parsed?.error;
258
248
  let errorMessage = "Label generation failed";
259
249
  let errorCode = "UNKNOWN";
260
250
  if (errorObj) {
261
- if (errorObj.errorMessage) {
251
+ if (Array.isArray(errorObj)) {
252
+ const firstError = errorObj[0];
253
+ errorMessage = firstError?.errorMessage || errorMessage;
254
+ errorCode = firstError?.errorCode || errorCode;
255
+ } else if (errorObj.errorMessage) {
262
256
  errorMessage = errorObj.errorMessage;
263
- errorCode = errorObj.errorCode || errorObj.name || "UNKNOWN";
257
+ errorCode = errorObj.errorCode || errorObj.name || errorCode;
264
258
  } else if (errorObj.name) {
265
259
  errorMessage = errorObj.name;
266
260
  errorCode = errorObj.name;
@@ -271,7 +265,6 @@ async function authenticatedRequest(credentials, options) {
271
265
  }
272
266
  }
273
267
  }
274
- console.error(`\u274C [SDK auth] Throwing error - Code: ${errorCode}, Message: ${errorMessage}`);
275
268
  throw new Error(`DPD API Error ${errorCode}: ${errorMessage}`);
276
269
  }
277
270
  if (parsed?.data) {
@@ -486,12 +479,7 @@ async function createShipment(credentials, params, businessConfig) {
486
479
  async function generateLabel(credentials, params) {
487
480
  try {
488
481
  const { shipmentId, labelFormat } = params;
489
- console.log("\n\u{1F3F7}\uFE0F [SDK generateLabel] Starting label generation");
490
- console.log(` Shipment ID: ${shipmentId} (type: ${typeof shipmentId})`);
491
- console.log(` Format: ${labelFormat}`);
492
- console.log(` Accept Header: ${getAcceptHeader(labelFormat)}`);
493
482
  const endpoint = `${DPD_API.ENDPOINTS.LABEL}/${shipmentId}/label/`;
494
- console.log(` Endpoint: ${endpoint}`);
495
483
  const response = await authenticatedRequest(credentials, {
496
484
  method: "GET",
497
485
  endpoint,
@@ -499,35 +487,17 @@ async function generateLabel(credentials, params) {
499
487
  Accept: getAcceptHeader(labelFormat)
500
488
  }
501
489
  });
502
- console.log("\u{1F4E6} [SDK generateLabel] Raw response type:", typeof response);
503
- console.log(
504
- "\u{1F4E6} [SDK generateLabel] Raw response:",
505
- typeof response === "string" ? `String (${response.length} chars): ${response.substring(0, 200)}...` : response
506
- );
507
- if (typeof response === "object" && response.error) {
508
- const errorObj = response.error;
509
- console.error("\u274C [SDK generateLabel] DPD returned error object:", errorObj);
510
- const errorMessage = errorObj.errorMessage || errorObj.name || JSON.stringify(errorObj);
511
- return {
512
- success: false,
513
- error: `DPD API error: ${errorMessage}`
514
- };
515
- }
516
- if (!response || typeof response === "object" && !response.data) {
517
- console.error("\u274C [SDK generateLabel] No label data in response");
490
+ if (!response || typeof response !== "string") {
518
491
  return {
519
492
  success: false,
520
493
  error: "No label data received from DPD"
521
494
  };
522
495
  }
523
- const labelData = typeof response === "string" ? response : response.data;
524
- console.log(`\u2705 [SDK generateLabel] Success! Label data length: ${labelData.length} chars`);
525
496
  return {
526
497
  success: true,
527
- labelData
498
+ labelData: response
528
499
  };
529
500
  } catch (error) {
530
- console.error("\u{1F4A5} [SDK generateLabel] Exception:", error);
531
501
  return {
532
502
  success: false,
533
503
  error: error instanceof Error ? error.message : "Unknown error"
@@ -672,7 +642,7 @@ async function createCompleteShipment(orderId, params, config2, dbAdapter, stora
672
642
  }
673
643
  const labelResult = await generateAndUploadLabel(
674
644
  shipmentResult.shipmentId,
675
- "zpl",
645
+ config2.labels.format,
676
646
  config2.credentials,
677
647
  storageAdapter
678
648
  );
@@ -865,97 +835,6 @@ var dpd_service_default = {
865
835
  getAuthStatus
866
836
  };
867
837
 
868
- // src/utils/encryption.ts
869
- import crypto from "crypto";
870
- var ALGORITHM = "aes-256-gcm";
871
- var KEY_LENGTH = 32;
872
- var IV_LENGTH = 16;
873
- var SALT_LENGTH = 64;
874
- var TAG_LENGTH = 16;
875
- var TAG_POSITION = SALT_LENGTH + IV_LENGTH;
876
- var ENCRYPTED_POSITION = TAG_POSITION + TAG_LENGTH;
877
- function getEncryptionKey() {
878
- const envKey = process.env.DPD_ENCRYPTION_KEY;
879
- if (envKey) {
880
- return Buffer.from(envKey, "hex");
881
- }
882
- if (process.env.NODE_ENV !== "production") {
883
- console.warn(
884
- "\u26A0\uFE0F Using default encryption key. Set DPD_ENCRYPTION_KEY in production!"
885
- );
886
- return crypto.scryptSync("dpd-dev-key", "salt", KEY_LENGTH);
887
- }
888
- throw new Error(
889
- "DPD_ENCRYPTION_KEY environment variable is required in production"
890
- );
891
- }
892
- function generateEncryptionKey() {
893
- const key = crypto.randomBytes(KEY_LENGTH);
894
- return key.toString("hex");
895
- }
896
- function encrypt(text) {
897
- try {
898
- const salt = crypto.randomBytes(SALT_LENGTH);
899
- const iv = crypto.randomBytes(IV_LENGTH);
900
- const key = crypto.scryptSync(getEncryptionKey(), salt, KEY_LENGTH);
901
- const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
902
- const encrypted = Buffer.concat([
903
- cipher.update(text, "utf8"),
904
- cipher.final()
905
- ]);
906
- const tag = cipher.getAuthTag();
907
- const result = Buffer.concat([salt, iv, tag, encrypted]);
908
- return result.toString("hex");
909
- } catch (error) {
910
- console.error("Encryption error:", error);
911
- throw new Error("Failed to encrypt data");
912
- }
913
- }
914
- function decrypt(encryptedHex) {
915
- try {
916
- const data = Buffer.from(encryptedHex, "hex");
917
- const salt = data.subarray(0, SALT_LENGTH);
918
- const iv = data.subarray(SALT_LENGTH, TAG_POSITION);
919
- const tag = data.subarray(TAG_POSITION, ENCRYPTED_POSITION);
920
- const encrypted = data.subarray(ENCRYPTED_POSITION);
921
- const key = crypto.scryptSync(getEncryptionKey(), salt, KEY_LENGTH);
922
- const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
923
- decipher.setAuthTag(tag);
924
- const decrypted = Buffer.concat([
925
- decipher.update(encrypted),
926
- decipher.final()
927
- ]);
928
- return decrypted.toString("utf8");
929
- } catch (error) {
930
- console.error("Decryption error:", error);
931
- throw new Error("Failed to decrypt data");
932
- }
933
- }
934
- function encryptCredentials(credentials) {
935
- return {
936
- accountNumber: credentials.accountNumber,
937
- username: credentials.username,
938
- passwordHash: encrypt(credentials.password)
939
- };
940
- }
941
- function decryptCredentials(encryptedCredentials) {
942
- return {
943
- accountNumber: encryptedCredentials.accountNumber,
944
- username: encryptedCredentials.username,
945
- password: decrypt(encryptedCredentials.passwordHash)
946
- };
947
- }
948
- function hash(data) {
949
- return crypto.createHash("sha256").update(data).digest("hex");
950
- }
951
- function verifyHash(data, hashToVerify) {
952
- const computed = hash(data);
953
- return crypto.timingSafeEqual(
954
- Buffer.from(computed),
955
- Buffer.from(hashToVerify)
956
- );
957
- }
958
-
959
838
  // src/utils/logger.ts
960
839
  var defaultConfig = {
961
840
  enabled: true,
@@ -1134,14 +1013,9 @@ export {
1134
1013
  createCompleteShipment,
1135
1014
  createDPDConfig,
1136
1015
  createShipment,
1137
- decrypt,
1138
- decryptCredentials,
1139
1016
  deleteSavedAddress,
1140
- encrypt,
1141
- encryptCredentials,
1142
1017
  generateAndUploadLabel,
1143
1018
  generateConsignmentRef,
1144
- generateEncryptionKey,
1145
1019
  generateLabel,
1146
1020
  getAuthStatus,
1147
1021
  getEstimatedDeliveryDate,
@@ -1155,7 +1029,6 @@ export {
1155
1029
  getTokenExpiry,
1156
1030
  getTrackingUrl,
1157
1031
  hasValidToken,
1158
- hash,
1159
1032
  isValidServiceCode,
1160
1033
  logOperation,
1161
1034
  loggedOperation,
@@ -1171,8 +1044,7 @@ export {
1171
1044
  updateSavedAddress,
1172
1045
  validateAddress,
1173
1046
  validateDeliveryAddress,
1174
- validateServiceCode,
1175
- verifyHash
1047
+ validateServiceCode
1176
1048
  };
1177
1049
  /**
1178
1050
  * DPD Local SDK
@@ -1181,7 +1053,7 @@ export {
1181
1053
  * Database-agnostic and framework-independent
1182
1054
  *
1183
1055
  * @package @jazzdev/dpd-local-sdk
1184
- * @version 1.0.0
1185
- * @author Your Name
1056
+ * @version 1.0.12
1057
+ * @author Taiow Babarinde <babsman4all@gmail.com>
1186
1058
  * @license MIT
1187
1059
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jazzdev/dpd-local-sdk",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "TypeScript SDK for DPD Local shipping API integration - database-agnostic and framework-independent",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -15,14 +15,14 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "README.md",
18
- "LICENSE",
19
- "CHANGELOG.md"
18
+ "LICENSE"
20
19
  ],
21
20
  "scripts": {
22
21
  "build": "tsup src/index.ts --format cjs,esm --dts --clean",
23
22
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
24
23
  "typecheck": "tsc --noEmit",
25
- "prepublishOnly": "npm run build"
24
+ "prepublishOnly": "npm run build",
25
+ "test:label": "tsx test-label-generation.ts"
26
26
  },
27
27
  "keywords": [
28
28
  "dpd",
@@ -42,12 +42,12 @@
42
42
  "license": "MIT",
43
43
  "repository": {
44
44
  "type": "git",
45
- "url": "https://github.com/TheJazzDev/dpd-local-sdk.git"
45
+ "url": "https://github.com/TheJazzDev/dpd-local-sdk"
46
46
  },
47
47
  "bugs": {
48
- "url": "https://github.com/TheJazzDev/dpd-local-sdk.git/issues"
48
+ "url": "https://github.com/TheJazzDev/dpd-local-sdk/issues"
49
49
  },
50
- "homepage": "https://github.com/TheJazzDev/dpd-local-sdk.git#readme",
50
+ "homepage": "https://github.com/TheJazzDev/dpd-local-sdk#readme",
51
51
  "devDependencies": {
52
52
  "@types/node": "^20.0.0",
53
53
  "dotenv": "^17.2.3",
package/CHANGELOG.md DELETED
@@ -1,38 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [1.0.0] - 2024-01-04
9
-
10
- ### Added
11
- - Initial release of DPD Local SDK
12
- - Complete DPD API integration (authentication, shipments, labels, tracking)
13
- - Database-agnostic adapter pattern
14
- - TypeScript-first design with full type definitions
15
- - Address validation using postcodes.io API
16
- - Automatic token management and caching
17
- - Request retry logic with exponential backoff
18
- - Comprehensive error handling
19
- - Detailed logging system
20
- - Encryption utilities for sensitive data
21
- - Configuration factory function
22
- - Helper functions for pricing, dates, and tracking
23
- - Example adapters for Firestore and Firebase Storage
24
- - Complete documentation and usage examples
25
-
26
- ### Features
27
- - ✅ Create shipments with DPD
28
- - ✅ Generate and upload shipping labels (thermal/A4)
29
- - ✅ Validate UK delivery addresses
30
- - ✅ Save and manage customer addresses
31
- - ✅ Calculate shipping costs and delivery fees
32
- - ✅ Track shipments
33
- - ✅ Multi-parcel support
34
- - ✅ Service selection (Next Day, By 12 PM)
35
- - ✅ Customer notifications (email, SMS via DPD)
36
- - ✅ Comprehensive logging and audit trail
37
-
38
- [1.0.0]: https://github.com/your-org/dpd-local-sdk/releases/tag/v1.0.0