├── .babelrc ├── .github └── workflows │ └── build.js.yml ├── .gitignore ├── README.md ├── _config.yml ├── examples └── exmaples.js ├── package-lock.json ├── package.json ├── src └── index.js └── tests ├── get_couriers.test.js ├── get_tracking_url.test.js ├── is_valid.test.js ├── tracking_numbers.js └── validate_tracking_numbers.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"], 3 | "plugins": ["transform-object-rest-spread"], 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/build.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [master] 9 | pull_request: 10 | branches: [master] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [14.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v2 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - run: npm ci 27 | - run: npm run build --if-present 28 | - run: npm test 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | index.js 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## tracking-number-validation 2 | 3 | A simple way to validate tracking number for the following couriers. 4 | 5 | supported couriers: 6 | 7 | - ups 8 | - usps 9 | - dhl 10 | - fedex 11 | - ontrac 12 | 13 | ## Updates 14 | 15 | v2 api changes. 16 | checkout out v1 and v2 branches. 17 | 18 | v2 api: 19 | 20 | - getCourier(tracking) -> Array: [courier] //due to the similarity some times there is a match for more then 1 courier 21 | - getCourierOne: (tracking,courier) -> String: courier //not safe 22 | - isValid: (tracking) -> Boolean: true/false //return true if match one or more couriers 23 | - isCourier: (tracking,courier) -> Boolean: true/false 24 | - getTrackingUrl: (tracking,courier) -> String: url for tracking number. 25 | 26 | ## Usage 27 | 28 | v1 api: 29 | 30 | Nodejs: 31 | 32 | - npm i tracking-number-validation --save 33 | - const tnv = require('tracking-number-validation') 34 | - tnv.getCourier('1Z2869Y60397722027') -> return courier like ups 35 | - tnv.isValid('1Z2869Y60397722027','fedex') -> return true/false 36 | 37 | Javascript: 38 | 39 | - npm i tracking-number-validation --save 40 | - include main.js in your index.html 41 | 42 | ```html 43 | 44 | ``` 45 | 46 | - const courier = TNV.getCourier(tr) 47 | 48 | ### Demo 49 | 50 | [link](https://niradler.github.io/tracking-number-validation/) 51 | 52 | ### Tested Against 53 | 54 | UPS: 55 | 56 | - "1Z9999W99999999999": "ups", 57 | - "1Z12345E1512345676": "ups", 58 | - "1Z12345E0205271688": "ups", 59 | - "1Z12345E6605272234": "ups", 60 | - "1Z12345E0305271640": "ups", 61 | - "1Z12345E0393657226": "ups", 62 | - "1Z12345E1305277940": "ups", 63 | - "1Z12345E6205277936": "ups", 64 | - "1Z12345E1505270452": "ups", 65 | - "1Z648616E192760718": "ups", 66 | - "1ZWX0692YP40636269": "ups", 67 | - T9999999999: "ups", 68 | 69 | FEDEX: 70 | 71 | - "9999 9999 9999": "fedex", 72 | - "9999 9999 9999 999": "fedex", 73 | - "999999999999": "fedex", 74 | - "999999999999999": "fedex", 75 | - "661377569221": "fedex", 76 | - "624893691092": "fedex", 77 | - "61299995669352455464": "fedex", 78 | - "61299995669151880177": "fedex", 79 | 80 | USPS: 81 | 82 | - "9400 1000 0000 0000 0000 00": "usps", 83 | - "9205 5000 0000 0000 0000 00": "usps", 84 | - "9407 3000 0000 0000 0000 00": "usps", 85 | - "9303 3000 0000 0000 0000 00": "usps", 86 | - "82 000 000 00": "usps", 87 | - "EC 000 000 000 US": "usps", 88 | - "9270 1000 0000 0000 0000 00": "usps", 89 | - "EA 000 000 000 US": "usps", 90 | - "CP 000 000 000 US": "usps", 91 | - "9208 8000 0000 0000 0000 00": "usps", 92 | - "9202 1000 0000 0000 0000 00": "usps", 93 | - "9400100000000000000000": "usps", 94 | - "9205500000000000000000": "usps", 95 | - "9407300000000000000000": "usps", 96 | - "9303300000000000000000": "usps", 97 | - "8200000000": "usps", 98 | - EC000000000US: "usps", 99 | - "9270100000000000000000": "usps", 100 | - EA000000000US: "usps", 101 | - CP000000000US: "usps", 102 | - "9208800000000000000000": "usps", 103 | - "9202100000000000000000": "usps", 104 | - "92748963438592543475924253": "usps", 105 | 106 | ONTRAC: 107 | 108 | - C00000000000000: "ontrac", 109 | - C99999999999999: "ontrac", 110 | 111 | DHL: 112 | 113 | - "125-12345678": "dhl", 114 | - "125 12345678": "dhl", 115 | - "12512345678": "dhl", 116 | - SEA1234567: "dhl", 117 | - LAX1234567: "dhl", 118 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /examples/exmaples.js: -------------------------------------------------------------------------------- 1 | const tnv = require("../index"); 2 | 3 | let courier = tnv.getCourier("TBA502887274000"); 4 | console.log("getCourier:", courier); 5 | courier = tnv.getCourierOne("1Z2869Y60397722027"); 6 | console.log("getCourierOne:", courier); 7 | courier = tnv.isCourier("1Z2869Y60397722027", "ups"); 8 | console.log("isCourier:", courier); 9 | courier = tnv.isValid("1Z2869Y60397722027"); 10 | console.log("isValid:", courier); 11 | courier = tnv.getTrackingUrl("1Z2869Y60397722027"); 12 | console.log("getTrackingUrl:", courier); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tracking-number-validation", 3 | "version": "2.0.2", 4 | "description": "A simple way to validate tracking number for the following couriers.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "babel --presets env src -d ./ --ignore src/index.test.js", 8 | "dev": "babel --presets env src -d ./ --watch --ignore src/index.test.js", 9 | "test": "jest" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/niradler/tracking-number-validation" 14 | }, 15 | "keywords": [ 16 | "npm", 17 | "package", 18 | "tracking", 19 | "number", 20 | "dhl", 21 | "fedex", 22 | "usps", 23 | "ups", 24 | "validation" 25 | ], 26 | "author": "Nir Adler", 27 | "license": "MIT", 28 | "files": [ 29 | "index.js" 30 | ], 31 | "bugs": { 32 | "url": "https://github.com/niradler/tracking-number-validation/issues" 33 | }, 34 | "homepage": "https://github.com/niradler/tracking-number-validation", 35 | "dependencies": {}, 36 | "devDependencies": { 37 | "babel-cli": "^6.24.1", 38 | "babel-plugin-transform-object-rest-spread": "^6.23.0", 39 | "babel-preset-env": "^1.6.0", 40 | "jest": "^20.0.3" 41 | } 42 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const courier_info = { 2 | amazon: { 3 | patterns: [new RegExp(/^TB[A-D][0-9]{12}/)], 4 | }, 5 | ups: { 6 | patterns: [new RegExp(/\b(1Z ?[0-9A-Z]{3} ?[0-9A-Z]{3} ?[0-9A-Z]{2} ?[0-9A-Z]{4} ?[0-9A-Z]{3} ?[0-9A-Z]|T\d{3} ?\d{4} ?\d{3})\b/i)], 7 | tracking_url: "https://www.ups.com/mobile/track?trackingNumber=" 8 | }, 9 | usps: { 10 | patterns: [ 11 | new RegExp( 12 | /\b((420 ?\d{5} ?)?(91|92|93|94|95|01|03|04|70|23|13)\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4}( ?\d{2,6})?)\b/i 13 | ), 14 | new RegExp( 15 | /\b((M|P[A-Z]?|D[C-Z]|LK|E[A-C]|V[A-Z]|R[A-Z]|CP|CJ|LC|LJ) ?\d{3} ?\d{3} ?\d{3} ?[A-Z]?[A-Z]?)\b/i 16 | ), 17 | new RegExp(/\b(82 ?\d{3} ?\d{3} ?\d{2})\b/i), 18 | ], 19 | tracking_url: "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=", 20 | }, 21 | ontrac: { 22 | patterns: [new RegExp(/\b(C\d{14})\b/i)], 23 | tracking_url: "http://www.ontrac.com/trackres.asp?tracking_number=", 24 | }, 25 | dhl: { 26 | patterns: [ 27 | new RegExp( 28 | /\b(\d{4}[- ]?\d{4}[- ]?\d{2}|\d{3}[- ]?\d{8}|[A-Z]{3}\d{7})\b/i 29 | ), 30 | ], 31 | tracking_url: 32 | "http://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=", 33 | }, 34 | fedex: { 35 | patterns: [new RegExp(/\b(((96\d\d|6\d)\d{3} ?\d{4}|96\d{2}|\d{4}) ?\d{4} ?\d{4}( ?\d{3}|\d{15})?)\b/i)], 36 | tracking_url: "https://www.fedex.com/fedextrack/?tracknumbers=" 37 | } 38 | }; 39 | 40 | const getCourier = (tr) => 41 | Object.keys(courier_info).filter( 42 | (c) => courier_info[c].patterns.filter((p) => p.test(tr)).length > 0 43 | ); 44 | 45 | const getCourierOne = (tr) => getCourier(tr)[0]; 46 | 47 | const isCourier = (tr, courier) => 48 | getCourier(tr).indexOf(courier.toLowerCase()) > -1; 49 | 50 | const getTrackingUrl = (tr, courier) => { 51 | let link = null; 52 | if (courier) { 53 | link = courier_info[courier.toLowerCase()].tracking_url + tr; 54 | } else { 55 | const c = getCourier(tr)[0]; 56 | if (c && courier_info[c].tracking_url) 57 | link = courier_info[c].tracking_url + tr; 58 | } 59 | 60 | return link; 61 | }; 62 | 63 | const injectPatterns = (courier, patt) => 64 | !courier || !courier_info[courier.toLowerCase()] 65 | ? false 66 | : courier_info[courier.toLowerCase()].patterns.push(new RegExp(patt)); 67 | 68 | const isValid = (tr) => getCourier(tr).length > 0; 69 | 70 | const TNV = { 71 | getCourier, 72 | getCourierOne, 73 | isCourier, 74 | getTrackingUrl, 75 | injectPatterns, 76 | isValid, 77 | couriers: courier_info, 78 | }; 79 | 80 | if (typeof exports === "undefined") { 81 | window.TNV = TNV; 82 | } else { 83 | module.exports = TNV; 84 | } 85 | -------------------------------------------------------------------------------- /tests/get_couriers.test.js: -------------------------------------------------------------------------------- 1 | const tracking_numbers = require("./tracking_numbers"); 2 | const tnv = require("../index"); 3 | 4 | test("getCourier", () => { 5 | for (const key in tracking_numbers) { 6 | const courier = tnv.getCourier(key); 7 | 8 | expect(courier[0]).toBe(tracking_numbers[key]); 9 | } 10 | }); 11 | 12 | test("getCourierOne", () => { 13 | for (const key in tracking_numbers) { 14 | const courier = tnv.getCourierOne(key); 15 | 16 | expect(courier).toBe(tracking_numbers[key]); 17 | } 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /tests/get_tracking_url.test.js: -------------------------------------------------------------------------------- 1 | const tracking_numbers = require("./tracking_numbers"); 2 | const tnv = require("../index"); 3 | 4 | test("getTrackingUrl", () => { 5 | for (const key in tracking_numbers) { 6 | const url = tnv.getTrackingUrl(key); 7 | 8 | if (tracking_numbers[key] === "amazon") { 9 | expect(url).toBe(null); 10 | } else { 11 | expect(url.indexOf(tracking_numbers[key]) > -1).toBeTruthy(); 12 | } 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /tests/is_valid.test.js: -------------------------------------------------------------------------------- 1 | const tracking_numbers = require("./tracking_numbers"); 2 | const tnv = require("../index"); 3 | 4 | test("isValid", () => { 5 | for (const key in tracking_numbers) { 6 | const isValid = tnv.isValid(key); 7 | 8 | expect(isValid).toBe(true); 9 | } 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /tests/tracking_numbers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | //TEST UPS 3 | "1Z9999W99999999999": "ups", 4 | "1Z12345E1512345676": "ups", 5 | "1Z12345E0205271688": "ups", 6 | "1Z12345E6605272234": "ups", 7 | "1Z12345E0305271640": "ups", 8 | "1Z12345E0393657226": "ups", 9 | "1Z12345E1305277940": "ups", 10 | "1Z12345E6205277936": "ups", 11 | "1Z12345E1505270452": "ups", 12 | "1Z648616E192760718": "ups", 13 | "1ZWX0692YP40636269": "ups", 14 | T9999999999: "ups", 15 | //TEST FEDEX 16 | "9999 9999 9999": "fedex", 17 | "9999 9999 9999 999": "fedex", 18 | 999999999999: "fedex", 19 | 999999999999999: "fedex", 20 | 661377569221: "fedex", 21 | 624893691092: "fedex", 22 | "61299995669352455464": "fedex", 23 | "61299995669151880177": "fedex", 24 | "9622080430002481027200399594546820": "fedex", 25 | // "00408017007469": "fedex", 26 | //TEST USPS 27 | "9400 1000 0000 0000 0000 00": "usps", 28 | "9205 5000 0000 0000 0000 00": "usps", 29 | "9407 3000 0000 0000 0000 00": "usps", 30 | "9303 3000 0000 0000 0000 00": "usps", 31 | "82 000 000 00": "usps", 32 | "EC 000 000 000 US": "usps", 33 | "9270 1000 0000 0000 0000 00": "usps", 34 | "EA 000 000 000 US": "usps", 35 | "CP 000 000 000 US": "usps", 36 | "9208 8000 0000 0000 0000 00": "usps", 37 | "9202 1000 0000 0000 0000 00": "usps", 38 | "9400100000000000000000": "usps", 39 | "9205500000000000000000": "usps", 40 | "9407300000000000000000": "usps", 41 | "9303300000000000000000": "usps", 42 | 8200000000: "usps", 43 | EC000000000US: "usps", 44 | "9270100000000000000000": "usps", 45 | EA000000000US: "usps", 46 | CP000000000US: "usps", 47 | "9208800000000000000000": "usps", 48 | "9202100000000000000000": "usps", 49 | "92748963438592543475924253": "usps", 50 | //TEST ONTRAC 51 | C00000000000000: "ontrac", 52 | C99999999999999: "ontrac", 53 | //TEST DHL 54 | "125-12345678": "dhl", 55 | "125 12345678": "dhl", 56 | 12512345678: "dhl", 57 | SEA1234567: "dhl", 58 | LAX1234567: "dhl", 59 | TBA502887274000: "amazon", 60 | //https://stackoverflow.com/questions/619977/regular-expression-patterns-for-tracking-numbers 61 | // 'RE360192014US':'usps', 62 | // '70160910000108310009':'usps', 63 | // 'EL595811950US':'usps', 64 | // '9374889692090270407075':'usps', 65 | // '23153630000057728970':'usps', 66 | 67 | // '810132562702':'fedex', 68 | // '795223646324':'fedex', 69 | // '785037759224':'fedex', 70 | 71 | // 'K2479825491':'ups', 72 | // 'J4603636537':'ups', 73 | // '1Z87585E4391018698':'ups', 74 | }; 75 | -------------------------------------------------------------------------------- /tests/validate_tracking_numbers.test.js: -------------------------------------------------------------------------------- 1 | const tracking_numbers = require("./tracking_numbers"); 2 | const tnv = require("../index"); 3 | 4 | test("Validate Courier", () => { 5 | for (const key in tracking_numbers) { 6 | const courier = tnv.isCourier(key, tracking_numbers[key]); 7 | expect(courier).toBe(true); 8 | } 9 | }); 10 | --------------------------------------------------------------------------------