@jazzdev/dpd-local-sdk 1.0.10 → 1.0.12

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
@@ -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
@@ -379,11 +447,12 @@ console.log('DPD_ENCRYPTION_KEY=' + key);
379
447
 
380
448
  Complete adapter examples are available in the `examples/` directory:
381
449
 
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
450
+ - `examples/basic-usage.ts` - Complete workflow example
451
+ - `examples/regenerate-label.ts` - Label regeneration example
452
+ - `examples/firestore-adapter.ts` - Firestore database adapter
453
+ - `examples/firebase-storage-adapter.ts` - Firebase Storage adapter
454
+
455
+ 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
456
 
388
457
  ## Error Handling
389
458
 
package/dist/index.js CHANGED
@@ -336,9 +336,13 @@ async function authenticatedRequest(credentials, options) {
336
336
  let errorMessage = "Label generation failed";
337
337
  let errorCode = "UNKNOWN";
338
338
  if (errorObj) {
339
- if (errorObj.errorMessage) {
339
+ if (Array.isArray(errorObj)) {
340
+ const firstError = errorObj[0];
341
+ errorMessage = firstError?.errorMessage || errorMessage;
342
+ errorCode = firstError?.errorCode || errorCode;
343
+ } else if (errorObj.errorMessage) {
340
344
  errorMessage = errorObj.errorMessage;
341
- errorCode = errorObj.errorCode || errorObj.name || "UNKNOWN";
345
+ errorCode = errorObj.errorCode || errorObj.name || errorCode;
342
346
  } else if (errorObj.name) {
343
347
  errorMessage = errorObj.name;
344
348
  errorCode = errorObj.name;
@@ -563,12 +567,7 @@ async function createShipment(credentials, params, businessConfig) {
563
567
  async function generateLabel(credentials, params) {
564
568
  try {
565
569
  const { shipmentId, labelFormat } = params;
566
- console.log("\n\u{1F3F7}\uFE0F [SDK generateLabel] Starting label generation");
567
- console.log(` Shipment ID: ${shipmentId} (type: ${typeof shipmentId})`);
568
- console.log(` Format: ${labelFormat}`);
569
- console.log(` Accept Header: ${getAcceptHeader(labelFormat)}`);
570
570
  const endpoint = `${DPD_API.ENDPOINTS.LABEL}/${shipmentId}/label/`;
571
- console.log(` Endpoint: ${endpoint}`);
572
571
  const response = await authenticatedRequest(credentials, {
573
572
  method: "GET",
574
573
  endpoint,
@@ -576,35 +575,17 @@ async function generateLabel(credentials, params) {
576
575
  Accept: getAcceptHeader(labelFormat)
577
576
  }
578
577
  });
579
- console.log("\u{1F4E6} [SDK generateLabel] Raw response type:", typeof response);
580
- console.log(
581
- "\u{1F4E6} [SDK generateLabel] Raw response:",
582
- typeof response === "string" ? `String (${response.length} chars): ${response.substring(0, 200)}...` : response
583
- );
584
- if (typeof response === "object" && response.error) {
585
- const errorObj = response.error;
586
- console.error("\u274C [SDK generateLabel] DPD returned error object:", errorObj);
587
- const errorMessage = errorObj.errorMessage || errorObj.name || JSON.stringify(errorObj);
588
- return {
589
- success: false,
590
- error: `DPD API error: ${errorMessage}`
591
- };
592
- }
593
- if (!response || typeof response === "object" && !response.data) {
594
- console.error("\u274C [SDK generateLabel] No label data in response");
578
+ if (!response || typeof response !== "string") {
595
579
  return {
596
580
  success: false,
597
581
  error: "No label data received from DPD"
598
582
  };
599
583
  }
600
- const labelData = typeof response === "string" ? response : response.data;
601
- console.log(`\u2705 [SDK generateLabel] Success! Label data length: ${labelData.length} chars`);
602
584
  return {
603
585
  success: true,
604
- labelData
586
+ labelData: response
605
587
  };
606
588
  } catch (error) {
607
- console.error("\u{1F4A5} [SDK generateLabel] Exception:", error);
608
589
  return {
609
590
  success: false,
610
591
  error: error instanceof Error ? error.message : "Unknown error"
@@ -749,7 +730,7 @@ async function createCompleteShipment(orderId, params, config2, dbAdapter, stora
749
730
  }
750
731
  const labelResult = await generateAndUploadLabel(
751
732
  shipmentResult.shipmentId,
752
- "zpl",
733
+ config2.labels.format,
753
734
  config2.credentials,
754
735
  storageAdapter
755
736
  );
package/dist/index.mjs CHANGED
@@ -248,9 +248,13 @@ async function authenticatedRequest(credentials, options) {
248
248
  let errorMessage = "Label generation failed";
249
249
  let errorCode = "UNKNOWN";
250
250
  if (errorObj) {
251
- 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) {
252
256
  errorMessage = errorObj.errorMessage;
253
- errorCode = errorObj.errorCode || errorObj.name || "UNKNOWN";
257
+ errorCode = errorObj.errorCode || errorObj.name || errorCode;
254
258
  } else if (errorObj.name) {
255
259
  errorMessage = errorObj.name;
256
260
  errorCode = errorObj.name;
@@ -475,12 +479,7 @@ async function createShipment(credentials, params, businessConfig) {
475
479
  async function generateLabel(credentials, params) {
476
480
  try {
477
481
  const { shipmentId, labelFormat } = params;
478
- console.log("\n\u{1F3F7}\uFE0F [SDK generateLabel] Starting label generation");
479
- console.log(` Shipment ID: ${shipmentId} (type: ${typeof shipmentId})`);
480
- console.log(` Format: ${labelFormat}`);
481
- console.log(` Accept Header: ${getAcceptHeader(labelFormat)}`);
482
482
  const endpoint = `${DPD_API.ENDPOINTS.LABEL}/${shipmentId}/label/`;
483
- console.log(` Endpoint: ${endpoint}`);
484
483
  const response = await authenticatedRequest(credentials, {
485
484
  method: "GET",
486
485
  endpoint,
@@ -488,35 +487,17 @@ async function generateLabel(credentials, params) {
488
487
  Accept: getAcceptHeader(labelFormat)
489
488
  }
490
489
  });
491
- console.log("\u{1F4E6} [SDK generateLabel] Raw response type:", typeof response);
492
- console.log(
493
- "\u{1F4E6} [SDK generateLabel] Raw response:",
494
- typeof response === "string" ? `String (${response.length} chars): ${response.substring(0, 200)}...` : response
495
- );
496
- if (typeof response === "object" && response.error) {
497
- const errorObj = response.error;
498
- console.error("\u274C [SDK generateLabel] DPD returned error object:", errorObj);
499
- const errorMessage = errorObj.errorMessage || errorObj.name || JSON.stringify(errorObj);
500
- return {
501
- success: false,
502
- error: `DPD API error: ${errorMessage}`
503
- };
504
- }
505
- if (!response || typeof response === "object" && !response.data) {
506
- console.error("\u274C [SDK generateLabel] No label data in response");
490
+ if (!response || typeof response !== "string") {
507
491
  return {
508
492
  success: false,
509
493
  error: "No label data received from DPD"
510
494
  };
511
495
  }
512
- const labelData = typeof response === "string" ? response : response.data;
513
- console.log(`\u2705 [SDK generateLabel] Success! Label data length: ${labelData.length} chars`);
514
496
  return {
515
497
  success: true,
516
- labelData
498
+ labelData: response
517
499
  };
518
500
  } catch (error) {
519
- console.error("\u{1F4A5} [SDK generateLabel] Exception:", error);
520
501
  return {
521
502
  success: false,
522
503
  error: error instanceof Error ? error.message : "Unknown error"
@@ -661,7 +642,7 @@ async function createCompleteShipment(orderId, params, config2, dbAdapter, stora
661
642
  }
662
643
  const labelResult = await generateAndUploadLabel(
663
644
  shipmentResult.shipmentId,
664
- "zpl",
645
+ config2.labels.format,
665
646
  config2.credentials,
666
647
  storageAdapter
667
648
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jazzdev/dpd-local-sdk",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
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",
@@ -22,7 +22,8 @@
22
22
  "build": "tsup src/index.ts --format cjs,esm --dts --clean",
23
23
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
24
24
  "typecheck": "tsc --noEmit",
25
- "prepublishOnly": "npm run build"
25
+ "prepublishOnly": "npm run build",
26
+ "test:label": "tsx test-label-generation.ts"
26
27
  },
27
28
  "keywords": [
28
29
  "dpd",