india-pincode 2.1.2 → 2.2.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.
Binary file
package/dist/index.d.mts CHANGED
@@ -10,6 +10,7 @@ declare enum ErrorCode {
10
10
  interface ApiError {
11
11
  code: ErrorCode;
12
12
  message: string;
13
+ suggestions?: string[];
13
14
  }
14
15
  interface ApiResponse<T> {
15
16
  success: boolean;
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ declare enum ErrorCode {
10
10
  interface ApiError {
11
11
  code: ErrorCode;
12
12
  message: string;
13
+ suggestions?: string[];
13
14
  }
14
15
  interface ApiResponse<T> {
15
16
  success: boolean;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var v=require('fs'),w=require('path'),U=require('zlib'),common=require('@nestjs/common');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var v__namespace=/*#__PURE__*/_interopNamespace(v);var w__namespace=/*#__PURE__*/_interopNamespace(w);var U__namespace=/*#__PURE__*/_interopNamespace(U);var A=(n,t,e,i)=>{for(var r=t,s=n.length-1,o;s>=0;s--)(o=n[s])&&(r=(o(r))||r);return r};var _=(a=>(a.INVALID_PINCODE="INVALID_PINCODE",a.PINCODE_NOT_FOUND="PINCODE_NOT_FOUND",a.STATE_NOT_FOUND="STATE_NOT_FOUND",a.DISTRICT_NOT_FOUND="DISTRICT_NOT_FOUND",a.INVALID_COORDINATES="INVALID_COORDINATES",a.INVALID_INPUT="INVALID_INPUT",a.NO_RESULTS="NO_RESULTS",a))(_||{});var $="INDIA",E=/^[1-9]\d{5}$/,F=/\s+\(?(?:B\.?O\.?|S\.?O\.?|H\.?O\.?|P\.?O\.?|G\.?P\.?O\.?|M\.?D\.?G\.?|R\.?M\.?S\.?)\)?\s*$/i,S=null;function Q(n){return !n||typeof n!="string"?"":n.replace(F,"").replace(/\s{2,}/g," ").trim()}function p(n){if(n==null)return "";let t=String(n).trim();return t==="NA"?"":t.replace(/\s{2,}/g," ")}function B(n){if(n==null)return null;let t=Number(n);return !Number.isFinite(t)||t===0?null:t}function z(n){return n===null||n>=-90&&n<=90}function k(n){return n===null||n>=-180&&n<=180}function q(n){let t=String(n).replace(/\./g,"").toUpperCase().trim();return ["BO","SO","HO","PO","GPO"].includes(t)?t:"BO"}function G(n){let t=p(n.p),e=Q(p(n.o)),i=p(n.i),r=p(n.s);if(!t||!e||!i||!r||!E.test(t))return null;let s=B(n.a),o=B(n.n);return !z(s)||!k(o)?null:{pincode:t,area:e,officeType:q(n.t),delivery:n.d===1,district:i,state:r,country:$,circle:p(n.c),region:p(n.r),division:p(n.v),latitude:s,longitude:o}}function H(n){return `${n.pincode}|${n.area.toLowerCase()}|${n.district.toLowerCase()}|${n.officeType}`}function O(){if(S)return S;let n=w__namespace.resolve(__dirname,"..","data","pincodes.json.gz"),t=v__namespace.readFileSync(n),e=JSON.parse(U__namespace.gunzipSync(t).toString("utf-8")),i=new Set,r=[];for(let s=0;s<e.length;s++){let o=G(e[s]);if(!o)continue;let a=H(o);i.has(a)||(i.add(a),r.push(o));}return S=r,S}function T(n){return typeof n=="string"&&E.test(n.trim())}function R(){S=null;}var x="INDIA";function f(n){return {success:true,data:n}}function u(n,t){return {success:false,data:null,error:{code:n,message:t}}}var h=class{constructor(){this._byPincode=null;this._byState=null;this._byDistrict=null;this._byArea=null;}indexByPincode(){return this._byPincode?this._byPincode:(this._byPincode=this.buildIndex(t=>t.pincode),this._byPincode)}indexByState(){return this._byState?this._byState:(this._byState=this.buildIndex(t=>t.state.toLowerCase()),this._byState)}indexByDistrict(){return this._byDistrict?this._byDistrict:(this._byDistrict=this.buildIndex(t=>t.district.toLowerCase()),this._byDistrict)}indexByArea(){return this._byArea?this._byArea:(this._byArea=this.buildIndex(t=>t.area.toLowerCase()),this._byArea)}buildIndex(t){let e=O(),i=new Map;for(let r=0;r<e.length;r++){let s=t(e[r]);if(!s)continue;let o=i.get(s);o?o.push(e[r]):i.set(s,[e[r]]);}return i}paginate(t,e){let i=Math.max(1,e?.limit??100),r=Math.max(1,e?.page??1),s=t;e?.officeType&&(s=s.filter(m=>m.officeType===e.officeType)),e?.deliveryOnly&&(s=s.filter(m=>m.delivery));let o=s.length,a=Math.ceil(o/i),y=(r-1)*i;return {data:s.slice(y,y+i),total:o,page:r,limit:i,totalPages:a}}getByPincode(t,e){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let i=t.trim();if(!T(i))return u("INVALID_PINCODE",`Invalid pincode "${i}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let r=this.indexByPincode().get(i);return !r||r.length===0?u("PINCODE_NOT_FOUND",`No data found for pincode "${i}".`):f(this.paginate(r,e))}getPincodeSummary(t){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let e=t.trim();if(!T(e))return u("INVALID_PINCODE",`Invalid pincode "${e}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let i=this.indexByPincode().get(e);if(!i||i.length===0)return u("PINCODE_NOT_FOUND",`No data found for pincode "${e}".`);let r=i[0];return f({pincode:e,district:r.district,state:r.state,country:x,areas:i.map(s=>({pincode:s.pincode,area:s.area,latitude:s.latitude,longitude:s.longitude})),deliveryAreas:i.filter(s=>s.delivery).length,hasCoordinates:i.some(s=>s.latitude!==null)})}getByState(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let i=this.indexByState().get(t.trim().toLowerCase());return !i||i.length===0?u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`):f(this.paginate(i,e))}getStateSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let e=this.indexByState().get(t.trim().toLowerCase());if(!e||e.length===0)return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`);let i=new Set,r=new Set;for(let s of e)s.district&&i.add(s.district),r.add(s.pincode);return f({state:e[0].state,country:x,totalDistricts:i.size,totalAreas:e.length,totalPincodes:r.size,districts:Array.from(i).sort()})}getAllStates(){let t=this.indexByState();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].state:e}).sort()}getByDistrict(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let i=this.indexByDistrict().get(t.trim().toLowerCase());return !i||i.length===0?u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`):f(this.paginate(i,e))}getDistrictSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let e=this.indexByDistrict().get(t.trim().toLowerCase());if(!e||e.length===0)return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`);let i=new Set;for(let r of e)i.add(r.pincode);return f({district:e[0].district,state:e[0].state,country:x,totalAreas:e.length,totalPincodes:i.size,pincodes:Array.from(i).sort()})}getDistrictsByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let r of e)r.district&&i.add(r.district);return Array.from(i).sort()}getAllDistricts(){let t=this.indexByDistrict();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].district:e}).sort()}getByArea(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Area name is required and must be a non-empty string.");let i=this.indexByArea().get(t.trim().toLowerCase());return !i||i.length===0?u("NO_RESULTS",`No data found for area "${t.trim()}".`):f(this.paginate(i,e))}getPincodesByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let r of e)i.add(r.pincode);return Array.from(i).sort()}getPincodesByDistrict(t){let e=this.indexByDistrict().get(t.toLowerCase())??[],i=new Set;for(let r of e)i.add(r.pincode);return Array.from(i).sort()}search(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Search query is required and must be a non-empty string.");let i=O(),r=t.trim().toLowerCase(),s=Math.max(1,e?.limit??100),o=Math.max(1,e?.page??1),a=e?.officeType,y=e?.deliveryOnly,l=[],m=o*s+s;for(let d=0;d<i.length&&l.length<m;d++){let c=i[d];a&&c.officeType!==a||y&&!c.delivery||(c.pincode.includes(r)||c.area.toLowerCase().includes(r)||c.district.toLowerCase().includes(r)||c.state.toLowerCase().includes(r)||c.circle.toLowerCase().includes(r)||c.region.toLowerCase().includes(r))&&l.push(c);}if(l.length===0)return u("NO_RESULTS",`No results found for "${t.trim()}".`);let D=l.length,P=Math.ceil(D/s),b=(o-1)*s;return f({data:l.slice(b,b+s),total:D,page:o,limit:s,totalPages:P})}findNearby(t,e,i=10,r=20){if(typeof t!="number"||typeof e!="number"||!Number.isFinite(t)||!Number.isFinite(e))return u("INVALID_COORDINATES","Latitude and longitude must be valid numbers.");if(t<-90||t>90||e<-180||e>180)return u("INVALID_COORDINATES",`Invalid coordinates (${t}, ${e}). Latitude must be -90 to 90, longitude -180 to 180.`);let s=O(),o=i/111,a=i/(111*Math.cos(N(t))),y=t-o,l=t+o,m=e-a,D=e+a,P=[];for(let d=0;d<s.length;d++){let c=s[d];if(c.latitude===null||c.longitude===null||c.latitude<y||c.latitude>l||c.longitude<m||c.longitude>D)continue;let C=X(t,e,c.latitude,c.longitude);C<=i&&P.push({...c,distanceKm:Math.round(C*100)/100});}P.sort((d,c)=>d.distanceKm-c.distanceKm);let b=P.slice(0,r);return b.length===0?u("NO_RESULTS",`No post offices found within ${i}km of (${t}, ${e}).`):f(b)}getTotalRecords(){return O().length}getTotalPincodes(){return this.indexByPincode().size}clearCache(){this._byPincode=null,this._byState=null,this._byDistrict=null,this._byArea=null,R();}};function N(n){return n*(Math.PI/180)}function X(n,t,e,i){let s=N(e-n),o=N(i-t),a=Math.sin(s/2)**2+Math.cos(N(n))*Math.cos(N(e))*Math.sin(o/2)**2;return 6371*2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}var L=null;function j(){return L||(L=new h),L}exports.PincodeService=class g{constructor(){this.engine=new h;}getByPincode(t,e){return this.engine.getByPincode(t,e)}getPincodeSummary(t){return this.engine.getPincodeSummary(t)}getByState(t,e){return this.engine.getByState(t,e)}getStateSummary(t){return this.engine.getStateSummary(t)}getAllStates(){return this.engine.getAllStates()}getByDistrict(t,e){return this.engine.getByDistrict(t,e)}getDistrictSummary(t){return this.engine.getDistrictSummary(t)}getDistrictsByState(t){return this.engine.getDistrictsByState(t)}getAllDistricts(){return this.engine.getAllDistricts()}getByArea(t,e){return this.engine.getByArea(t,e)}getPincodesByState(t){return this.engine.getPincodesByState(t)}getPincodesByDistrict(t){return this.engine.getPincodesByDistrict(t)}search(t,e){return this.engine.search(t,e)}findNearby(t,e,i,r){return this.engine.findNearby(t,e,i,r)}getTotalRecords(){return this.engine.getTotalRecords()}getTotalPincodes(){return this.engine.getTotalPincodes()}clearCache(){this.engine.clearCache();}};exports.PincodeService=A([common.Injectable()],exports.PincodeService);exports.PincodeModule=class I{};exports.PincodeModule=A([common.Global(),common.Module({providers:[exports.PincodeService],exports:[exports.PincodeService]})],exports.PincodeModule);exports.ErrorCode=_;exports.IndiaPincode=h;exports.clearDataCache=R;exports.getIndiaPincode=j;exports.isValidPincode=T;exports.loadData=O;//# sourceMappingURL=index.js.map
1
+ 'use strict';var h=require('fs'),L=require('path'),E=require('zlib'),common=require('@nestjs/common');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var h__namespace=/*#__PURE__*/_interopNamespace(h);var L__namespace=/*#__PURE__*/_interopNamespace(L);var E__namespace=/*#__PURE__*/_interopNamespace(E);var _=(r,t,e,i)=>{for(var n=t,s=r.length-1,o;s>=0;s--)(o=r[s])&&(n=(o(n))||n);return n};var x=(a=>(a.INVALID_PINCODE="INVALID_PINCODE",a.PINCODE_NOT_FOUND="PINCODE_NOT_FOUND",a.STATE_NOT_FOUND="STATE_NOT_FOUND",a.DISTRICT_NOT_FOUND="DISTRICT_NOT_FOUND",a.INVALID_COORDINATES="INVALID_COORDINATES",a.INVALID_INPUT="INVALID_INPUT",a.NO_RESULTS="NO_RESULTS",a))(x||{});var F="INDIA",M=/^[1-9]\d{5}$/,Q=/\s+\(?(?:B\.?O\.?|S\.?O\.?|H\.?O\.?|P\.?O\.?|G\.?P\.?O\.?|M\.?D\.?G\.?|R\.?M\.?S\.?)\)?\s*$/i,I=null;function z(r){return !r||typeof r!="string"?"":r.replace(Q,"").replace(/\s{2,}/g," ").trim()}function y(r){if(r==null)return "";let t=String(r).trim();return t==="NA"?"":t.replace(/\s{2,}/g," ")}function U(r){if(r==null)return null;let t=Number(r);return !Number.isFinite(t)||t===0?null:t}function k(r){return r===null||r>=-90&&r<=90}function q(r){return r===null||r>=-180&&r<=180}function j(r){let t=String(r).replace(/\./g,"").toUpperCase().trim();return ["BO","SO","HO","PO","GPO"].includes(t)?t:"BO"}function G(r){let t=y(r.p),e=z(y(r.o)),i=y(r.i),n=y(r.s);if(!t||!e||!i||!n||!M.test(t))return null;let s=U(r.a),o=U(r.n);return !k(s)||!q(o)?null:{pincode:t,area:e,officeType:j(r.t),delivery:r.d===1,district:i,state:n,country:F,circle:y(r.c),region:y(r.r),division:y(r.v),latitude:s,longitude:o}}function H(r){return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`}function P(){if(I)return I;let r=L__namespace.resolve(__dirname,"..","data","pincodes.json.gz"),t=L__namespace.resolve(__dirname,"..","data","pincodes.json"),e;if(h__namespace.existsSync(r))e=JSON.parse(E__namespace.gunzipSync(h__namespace.readFileSync(r)).toString("utf-8"));else if(h__namespace.existsSync(t))e=JSON.parse(h__namespace.readFileSync(t,"utf-8"));else throw new Error("india-pincode: data file not found (data/pincodes.json.gz or data/pincodes.json)");let i=new Set,n=[];for(let s=0;s<e.length;s++){let o=G(e[s]);if(!o)continue;let a=H(o);i.has(a)||(i.add(a),n.push(o));}return I=n,I}function R(r){return typeof r=="string"&&M.test(r.trim())}function C(){I=null;}var B="INDIA";function m(r){return {success:true,data:r}}function u(r,t,e){let i={code:r,message:t};return e&&e.length>0&&(i.suggestions=e,i.message+=` Did you mean: ${e.join(", ")}?`),{success:false,data:null,error:i}}function D(r,t,e,i=5){let n=t.toLowerCase(),s=n.split(/\s+/).filter(a=>a.length>=3),o=[];for(let[a,f]of r){if(!a)continue;let g=f[0]?f[0][e]:a,d=0;a.includes(n)&&(d+=10);for(let O of s)a.includes(O)&&(d+=3);n.includes(a)&&(d+=5),d>0&&o.push({name:g,score:d});}return o.sort((a,f)=>f.score-a.score).slice(0,i).map(a=>a.name)}var S=class{constructor(){this._byPincode=null;this._byState=null;this._byDistrict=null;this._byArea=null;}indexByPincode(){return this._byPincode?this._byPincode:(this._byPincode=this.buildIndex(t=>t.pincode),this._byPincode)}indexByState(){return this._byState?this._byState:(this._byState=this.buildIndex(t=>t.state.toLowerCase()),this._byState)}indexByDistrict(){return this._byDistrict?this._byDistrict:(this._byDistrict=this.buildIndex(t=>t.district.toLowerCase()),this._byDistrict)}indexByArea(){return this._byArea?this._byArea:(this._byArea=this.buildIndex(t=>t.area.toLowerCase()),this._byArea)}buildIndex(t){let e=P(),i=new Map;for(let n=0;n<e.length;n++){let s=t(e[n]);if(!s)continue;let o=i.get(s);o?o.push(e[n]):i.set(s,[e[n]]);}return i}paginate(t,e){let i=Math.max(1,e?.limit??100),n=Math.max(1,e?.page??1),s=t;e?.officeType&&(s=s.filter(d=>d.officeType===e.officeType)),e?.deliveryOnly&&(s=s.filter(d=>d.delivery));let o=s.length,a=Math.ceil(o/i),f=(n-1)*i;return {data:s.slice(f,f+i),total:o,page:n,limit:i,totalPages:a}}getByPincode(t,e){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let i=t.trim();if(!R(i))return u("INVALID_PINCODE",`Invalid pincode "${i}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let n=this.indexByPincode().get(i);return !n||n.length===0?u("PINCODE_NOT_FOUND",`No data found for pincode "${i}".`):m(this.paginate(n,e))}getPincodeSummary(t){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let e=t.trim();if(!R(e))return u("INVALID_PINCODE",`Invalid pincode "${e}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let i=this.indexByPincode().get(e);if(!i||i.length===0)return u("PINCODE_NOT_FOUND",`No data found for pincode "${e}".`);let n=i[0];return m({pincode:e,district:n.district,state:n.state,country:B,areas:i.map(s=>({pincode:s.pincode,area:s.area,latitude:s.latitude,longitude:s.longitude})),deliveryAreas:i.filter(s=>s.delivery).length,hasCoordinates:i.some(s=>s.latitude!==null)})}getByState(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let i=this.indexByState(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"state");return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`,s)}return m(this.paginate(n,e))}getStateSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let e=this.indexByState(),i=e.get(t.trim().toLowerCase());if(!i||i.length===0){let o=D(e,t.trim(),"state");return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`,o)}let n=new Set,s=new Set;for(let o of i)o.district&&n.add(o.district),s.add(o.pincode);return m({state:i[0].state,country:B,totalDistricts:n.size,totalAreas:i.length,totalPincodes:s.size,districts:Array.from(n).sort()})}getAllStates(){let t=this.indexByState();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].state:e}).sort()}getByDistrict(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let i=this.indexByDistrict(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"district");return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`,s)}return m(this.paginate(n,e))}getDistrictSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let e=this.indexByDistrict(),i=e.get(t.trim().toLowerCase());if(!i||i.length===0){let s=D(e,t.trim(),"district");return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`,s)}let n=new Set;for(let s of i)n.add(s.pincode);return m({district:i[0].district,state:i[0].state,country:B,totalAreas:i.length,totalPincodes:n.size,pincodes:Array.from(n).sort()})}getDistrictsByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let n of e)n.district&&i.add(n.district);return Array.from(i).sort()}getAllDistricts(){let t=this.indexByDistrict();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].district:e}).sort()}getByArea(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Area name is required and must be a non-empty string.");let i=this.indexByArea(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"area");return u("NO_RESULTS",`No data found for area "${t.trim()}".`,s)}return m(this.paginate(n,e))}getPincodesByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let n of e)i.add(n.pincode);return Array.from(i).sort()}getPincodesByDistrict(t){let e=this.indexByDistrict().get(t.toLowerCase())??[],i=new Set;for(let n of e)i.add(n.pincode);return Array.from(i).sort()}search(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Search query is required and must be a non-empty string.");let i=P(),n=t.trim().toLowerCase(),s=Math.max(1,e?.limit??100),o=Math.max(1,e?.page??1),a=e?.officeType,f=e?.deliveryOnly,g=[],d=o*s+s;for(let l=0;l<i.length&&g.length<d;l++){let c=i[l];a&&c.officeType!==a||f&&!c.delivery||(c.pincode.includes(n)||c.area.toLowerCase().includes(n)||c.district.toLowerCase().includes(n)||c.state.toLowerCase().includes(n)||c.circle.toLowerCase().includes(n)||c.region.toLowerCase().includes(n))&&g.push(c);}if(g.length===0)return u("NO_RESULTS",`No results found for "${t.trim()}".`);let O=g.length,b=Math.ceil(O/s),N=(o-1)*s;return m({data:g.slice(N,N+s),total:O,page:o,limit:s,totalPages:b})}findNearby(t,e,i=10,n=20){if(typeof t!="number"||typeof e!="number"||!Number.isFinite(t)||!Number.isFinite(e))return u("INVALID_COORDINATES","Latitude and longitude must be valid numbers.");if(t<-90||t>90||e<-180||e>180)return u("INVALID_COORDINATES",`Invalid coordinates (${t}, ${e}). Latitude must be -90 to 90, longitude -180 to 180.`);let s=P(),o=i/111,a=i/(111*Math.cos(A(t))),f=t-o,g=t+o,d=e-a,O=e+a,b=[];for(let l=0;l<s.length;l++){let c=s[l];if(c.latitude===null||c.longitude===null||c.latitude<f||c.latitude>g||c.longitude<d||c.longitude>O)continue;let v=X(t,e,c.latitude,c.longitude);v<=i&&b.push({...c,distanceKm:Math.round(v*100)/100});}b.sort((l,c)=>l.distanceKm-c.distanceKm);let N=b.slice(0,n);return N.length===0?u("NO_RESULTS",`No post offices found within ${i}km of (${t}, ${e}).`):m(N)}getTotalRecords(){return P().length}getTotalPincodes(){return this.indexByPincode().size}clearCache(){this._byPincode=null,this._byState=null,this._byDistrict=null,this._byArea=null,C();}};function A(r){return r*(Math.PI/180)}function X(r,t,e,i){let s=A(e-r),o=A(i-t),a=Math.sin(s/2)**2+Math.cos(A(r))*Math.cos(A(e))*Math.sin(o/2)**2;return 6371*2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}var w=null;function J(){return w||(w=new S),w}exports.PincodeService=class p{constructor(){this.engine=new S;}getByPincode(t,e){return this.engine.getByPincode(t,e)}getPincodeSummary(t){return this.engine.getPincodeSummary(t)}getByState(t,e){return this.engine.getByState(t,e)}getStateSummary(t){return this.engine.getStateSummary(t)}getAllStates(){return this.engine.getAllStates()}getByDistrict(t,e){return this.engine.getByDistrict(t,e)}getDistrictSummary(t){return this.engine.getDistrictSummary(t)}getDistrictsByState(t){return this.engine.getDistrictsByState(t)}getAllDistricts(){return this.engine.getAllDistricts()}getByArea(t,e){return this.engine.getByArea(t,e)}getPincodesByState(t){return this.engine.getPincodesByState(t)}getPincodesByDistrict(t){return this.engine.getPincodesByDistrict(t)}search(t,e){return this.engine.search(t,e)}findNearby(t,e,i,n){return this.engine.findNearby(t,e,i,n)}getTotalRecords(){return this.engine.getTotalRecords()}getTotalPincodes(){return this.engine.getTotalPincodes()}clearCache(){this.engine.clearCache();}};exports.PincodeService=_([common.Injectable()],exports.PincodeService);exports.PincodeModule=class T{};exports.PincodeModule=_([common.Global(),common.Module({providers:[exports.PincodeService],exports:[exports.PincodeService]})],exports.PincodeModule);exports.ErrorCode=x;exports.IndiaPincode=S;exports.clearDataCache=C;exports.getIndiaPincode=J;exports.isValidPincode=R;exports.loadData=P;//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/data-loader.ts","../src/pincode-lookup.ts","../src/pincode.service.ts","../src/pincode.module.ts"],"names":["ErrorCode","COUNTRY","PINCODE_REGEX","OFFICE_SUFFIX_REGEX","cachedData","sanitizeCityName","raw","trimStr","val","s","safeNum","n","isValidLatitude","lat","isValidLongitude","lng","normalizeOfficeType","upper","expand","rec","pincode","area","district","state","latitude","longitude","dedupKey","r","loadData","dataPath","w","compressed","v","U","seen","result","i","record","key","isValidPincode","clearDataCache","ok","data","fail","code","message","IndiaPincode","o","keyFn","index","arr","records","options","limit","page","filtered","total","totalPages","start","trimmed","first","districtSet","pincodeSet","idx","set","d","name","query","q","officeType","deliveryOnly","matches","maxScan","radiusKm","dLat","dLng","toRad","minLat","maxLat","minLng","maxLng","results","haversine","a","b","sliced","deg","lat1","lon1","lat2","lon2","dLon","_instance","getIndiaPincode","PincodeService","__decorateClass","Injectable","PincodeModule","Global","Module"],"mappings":"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","file":"index.js","sourcesContent":["// ─── Error handling ─────────────────────────────────────────────\nexport enum ErrorCode {\n INVALID_PINCODE = 'INVALID_PINCODE',\n PINCODE_NOT_FOUND = 'PINCODE_NOT_FOUND',\n STATE_NOT_FOUND = 'STATE_NOT_FOUND',\n DISTRICT_NOT_FOUND = 'DISTRICT_NOT_FOUND',\n INVALID_COORDINATES = 'INVALID_COORDINATES',\n INVALID_INPUT = 'INVALID_INPUT',\n NO_RESULTS = 'NO_RESULTS',\n}\n\nexport interface ApiError {\n code: ErrorCode;\n message: string;\n}\n\nexport interface ApiResponse<T> {\n success: boolean;\n data: T | null;\n error?: ApiError;\n}\n\n// ─── Normalized public type ─────────────────────────────────────\nexport interface PostOffice {\n pincode: string;\n area: string;\n officeType: OfficeType;\n delivery: boolean;\n district: string;\n state: string;\n country: string;\n circle: string;\n region: string;\n division: string;\n latitude: number | null;\n longitude: number | null;\n}\n\nexport type OfficeType = 'BO' | 'SO' | 'HO' | 'PO' | 'GPO';\n\n// ─── Query options ──────────────────────────────────────────────\nexport interface QueryOptions {\n /** Max results to return (default: 100) */\n limit?: number;\n /** Page number, 1-based (default: 1) */\n page?: number;\n /** Filter by office type */\n officeType?: OfficeType;\n /** Filter only delivery offices */\n deliveryOnly?: boolean;\n}\n\n// ─── Paginated result ───────────────────────────────────────────\nexport interface PaginatedResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ─── Location result (with distance) ────────────────────────────\nexport interface NearbyResult extends PostOffice {\n distanceKm: number;\n}\n\n// ─── Slim area shape (used in summaries) ────────────────────────\nexport interface AreaInfo {\n pincode: string;\n area: string;\n latitude: number | null;\n longitude: number | null;\n}\n\n// ─── Summary types ──────────────────────────────────────────────\nexport interface PincodeSummary {\n pincode: string;\n district: string;\n state: string;\n country: string;\n areas: AreaInfo[];\n deliveryAreas: number;\n hasCoordinates: boolean;\n}\n\nexport interface DistrictSummary {\n district: string;\n state: string;\n country: string;\n totalAreas: number;\n totalPincodes: number;\n pincodes: string[];\n}\n\nexport interface StateSummary {\n state: string;\n country: string;\n totalDistricts: number;\n totalAreas: number;\n totalPincodes: number;\n districts: string[];\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as zlib from 'zlib';\nimport { PostOffice, OfficeType } from './types';\n\nconst COUNTRY = 'INDIA';\nconst PINCODE_REGEX = /^[1-9]\\d{5}$/;\n\n/**\n * Regex to strip office-type suffixes from city names.\n * Handles: B.O, S.O, H.O, P.O, G.P.O, M.D.G, R.M.S and their\n * dot-less variants (BO, SO, HO, PO, GPO, MDG, RMS).\n */\nconst OFFICE_SUFFIX_REGEX =\n /\\s+\\(?(?:B\\.?O\\.?|S\\.?O\\.?|H\\.?O\\.?|P\\.?O\\.?|G\\.?P\\.?O\\.?|M\\.?D\\.?G\\.?|R\\.?M\\.?S\\.?)\\)?\\s*$/i;\n\n/** Compact JSON record shape (short keys for minimal file size) */\ninterface CompactRecord {\n c: string; // circlename\n r: string; // regionname\n v: string; // divisionname\n o: string; // officename\n p: string; // pincode\n t: string; // officetype\n d: number; // delivery (1 = yes, 0 = no)\n i: string; // district\n s: string; // statename\n a: number; // latitude (0 = not available)\n n: number; // longitude (0 = not available)\n}\n\nlet cachedData: PostOffice[] | null = null;\n\n// ─── Sanitization helpers ───────────────────────────────────────\n\n/** Strip office-type suffixes (B.O, S.O, H.O, etc.) and trim */\nfunction sanitizeCityName(raw: string): string {\n if (!raw || typeof raw !== 'string') return '';\n return raw.replace(OFFICE_SUFFIX_REGEX, '').replace(/\\s{2,}/g, ' ').trim();\n}\n\n/** Trim and collapse extra whitespace */\nfunction trimStr(val: unknown): string {\n if (val === null || val === undefined) return '';\n const s = String(val).trim();\n return s === 'NA' ? '' : s.replace(/\\s{2,}/g, ' ');\n}\n\n/** Parse a numeric field, returning null for invalid / NaN / 0 */\nfunction safeNum(val: unknown): number | null {\n if (val === null || val === undefined) return null;\n const n = Number(val);\n if (!Number.isFinite(n) || n === 0) return null;\n return n;\n}\n\n/** Validate latitude is within valid range */\nfunction isValidLatitude(lat: number | null): boolean {\n return lat === null || (lat >= -90 && lat <= 90);\n}\n\n/** Validate longitude is within valid range */\nfunction isValidLongitude(lng: number | null): boolean {\n return lng === null || (lng >= -180 && lng <= 180);\n}\n\n/** Normalize office type string to valid OfficeType */\nfunction normalizeOfficeType(raw: string): OfficeType {\n const upper = String(raw).replace(/\\./g, '').toUpperCase().trim();\n const valid: OfficeType[] = ['BO', 'SO', 'HO', 'PO', 'GPO'];\n return (valid.includes(upper as OfficeType) ? upper : 'BO') as OfficeType;\n}\n\n// ─── Expand & validate ──────────────────────────────────────────\n\n/** Expand a compact record into a validated PostOffice (or null if invalid) */\nfunction expand(rec: CompactRecord): PostOffice | null {\n const pincode = trimStr(rec.p);\n const area = sanitizeCityName(trimStr(rec.o));\n const district = trimStr(rec.i);\n const state = trimStr(rec.s);\n\n // Required field checks\n if (!pincode || !area || !district || !state) return null;\n\n // Pincode must be exactly 6 digits starting with 1-9\n if (!PINCODE_REGEX.test(pincode)) return null;\n\n const latitude = safeNum(rec.a);\n const longitude = safeNum(rec.n);\n\n // Reject out-of-range coordinates\n if (!isValidLatitude(latitude) || !isValidLongitude(longitude)) return null;\n\n return {\n pincode,\n area,\n officeType: normalizeOfficeType(rec.t),\n delivery: rec.d === 1,\n district,\n state,\n country: COUNTRY,\n circle: trimStr(rec.c),\n region: trimStr(rec.r),\n division: trimStr(rec.v),\n latitude,\n longitude,\n };\n}\n\n/** Build a dedup key for a record */\nfunction dedupKey(r: PostOffice): string {\n return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`;\n}\n\n/**\n * Loads, validates, sanitizes and deduplicates all pincode data.\n * Cached after first call — subsequent calls return instantly.\n *\n * Records that fail validation are silently dropped:\n * - Missing required fields (pincode, area, district, state)\n * - Invalid pincode format (must be 6 digits, starting 1–9)\n * - Out-of-range coordinates\n * - NaN / undefined / null in required fields\n * - Duplicate records (same pincode + area + district + officeType)\n */\nexport function loadData(): PostOffice[] {\n if (cachedData) return cachedData;\n\n const dataPath = path.resolve(__dirname, '..', 'data', 'pincodes.json.gz');\n const compressed = fs.readFileSync(dataPath);\n const raw: CompactRecord[] = JSON.parse(zlib.gunzipSync(compressed).toString('utf-8'));\n\n const seen = new Set<string>();\n const result: PostOffice[] = [];\n\n for (let i = 0; i < raw.length; i++) {\n const record = expand(raw[i]);\n if (!record) continue;\n\n const key = dedupKey(record);\n if (seen.has(key)) continue;\n\n seen.add(key);\n result.push(record);\n }\n\n cachedData = result;\n return cachedData;\n}\n\n/** Validates an Indian pincode format. Returns true if valid. */\nexport function isValidPincode(pincode: string): boolean {\n return typeof pincode === 'string' && PINCODE_REGEX.test(pincode.trim());\n}\n\n/** Clears all cached data (useful for testing / hot-reload). */\nexport function clearDataCache(): void {\n cachedData = null;\n}\n","import {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n ErrorCode,\n} from './types';\nimport { loadData, clearDataCache, isValidPincode } from './data-loader';\n\nconst COUNTRY = 'INDIA';\n\n// ─── Response helpers ─────────────────────────────────────────────\n\nfunction ok<T>(data: T): ApiResponse<T> {\n return { success: true, data };\n}\n\nfunction fail<T>(code: ErrorCode, message: string): ApiResponse<T> {\n return { success: false, data: null, error: { code, message } };\n}\n\n/**\n * High-performance Indian Pincode lookup engine.\n *\n * Architecture:\n * - All indexes are lazy-built on first access, then cached.\n * - Pincode → O(1) HashMap lookup.\n * - State / District / Area → O(1) index lookup.\n * - Geo-nearby → Haversine with early bounding-box pruning.\n * - All responses wrapped in ApiResponse with proper error codes.\n */\nexport class IndiaPincode {\n // ─── Indexes (lazy) ─────────────────────────────────────────\n private _byPincode: Map<string, PostOffice[]> | null = null;\n private _byState: Map<string, PostOffice[]> | null = null;\n private _byDistrict: Map<string, PostOffice[]> | null = null;\n private _byArea: Map<string, PostOffice[]> | null = null;\n\n // ─── Index builders ─────────────────────────────────────────\n private indexByPincode(): Map<string, PostOffice[]> {\n if (this._byPincode) return this._byPincode;\n this._byPincode = this.buildIndex((o) => o.pincode);\n return this._byPincode;\n }\n\n private indexByState(): Map<string, PostOffice[]> {\n if (this._byState) return this._byState;\n this._byState = this.buildIndex((o) => o.state.toLowerCase());\n return this._byState;\n }\n\n private indexByDistrict(): Map<string, PostOffice[]> {\n if (this._byDistrict) return this._byDistrict;\n this._byDistrict = this.buildIndex((o) => o.district.toLowerCase());\n return this._byDistrict;\n }\n\n private indexByArea(): Map<string, PostOffice[]> {\n if (this._byArea) return this._byArea;\n this._byArea = this.buildIndex((o) => o.area.toLowerCase());\n return this._byArea;\n }\n\n private buildIndex(keyFn: (o: PostOffice) => string): Map<string, PostOffice[]> {\n const data = loadData();\n const index = new Map<string, PostOffice[]>();\n for (let i = 0; i < data.length; i++) {\n const key = keyFn(data[i]);\n if (!key) continue;\n const arr = index.get(key);\n if (arr) arr.push(data[i]);\n else index.set(key, [data[i]]);\n }\n return index;\n }\n\n // ─── Helper: apply filters + pagination ─────────────────────\n private paginate(\n records: PostOffice[],\n options?: QueryOptions,\n ): PaginatedResult<PostOffice> {\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n let filtered = records;\n\n if (options?.officeType) {\n filtered = filtered.filter((r) => r.officeType === options.officeType);\n }\n if (options?.deliveryOnly) {\n filtered = filtered.filter((r) => r.delivery);\n }\n\n const total = filtered.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n const data = filtered.slice(start, start + limit);\n\n return { data, total, page, limit, totalPages };\n }\n\n // ═══════════════════════════════════════════════════════════════\n // PUBLIC API\n // ═══════════════════════════════════════════════════════════════\n\n // ─── Pincode lookup (O(1)) ──────────────────────────────────\n\n /** Get all post offices for a pincode. Returns error for invalid/missing pincodes. */\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a complete summary for a pincode. */\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n const first = records[0];\n return ok({\n pincode: trimmed,\n district: first.district,\n state: first.state,\n country: COUNTRY,\n areas: records.map((r) => ({\n pincode: r.pincode,\n area: r.area,\n latitude: r.latitude,\n longitude: r.longitude,\n })),\n deliveryAreas: records.filter((o) => o.delivery).length,\n hasCoordinates: records.some((o) => o.latitude !== null),\n });\n }\n\n // ─── State queries ──────────────────────────────────────────\n\n /** Get all post offices in a state. */\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const records = this.indexByState().get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a state — districts, pincode count, etc. */\n getStateSummary(state: string): ApiResponse<StateSummary> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const records = this.indexByState().get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`);\n }\n\n const districtSet = new Set<string>();\n const pincodeSet = new Set<string>();\n for (const r of records) {\n if (r.district) districtSet.add(r.district);\n pincodeSet.add(r.pincode);\n }\n\n return ok({\n state: records[0].state,\n country: COUNTRY,\n totalDistricts: districtSet.size,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n districts: Array.from(districtSet).sort(),\n });\n }\n\n /** Get all unique state names. */\n getAllStates(): string[] {\n const idx = this.indexByState();\n return Array.from(idx.keys())\n .filter((s) => s.length > 0)\n .map((s) => {\n const first = idx.get(s);\n return first ? first[0].state : s;\n })\n .sort();\n }\n\n // ─── District queries ───────────────────────────────────────\n\n /** Get all post offices in a district. */\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const records = this.indexByDistrict().get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a district. */\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const records = this.indexByDistrict().get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`);\n }\n\n const pincodeSet = new Set<string>();\n for (const r of records) pincodeSet.add(r.pincode);\n\n return ok({\n district: records[0].district,\n state: records[0].state,\n country: COUNTRY,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n pincodes: Array.from(pincodeSet).sort(),\n });\n }\n\n /** Get all districts for a state. */\n getDistrictsByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) {\n if (r.district) set.add(r.district);\n }\n return Array.from(set).sort();\n }\n\n /** Get all unique district names. */\n getAllDistricts(): string[] {\n const idx = this.indexByDistrict();\n return Array.from(idx.keys())\n .filter((d) => d.length > 0)\n .map((d) => {\n const first = idx.get(d);\n return first ? first[0].district : d;\n })\n .sort();\n }\n\n // ─── Area name queries ───────────────────────────────────────\n\n /** Get post offices by exact area name (case-insensitive). */\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!name || typeof name !== 'string' || !name.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Area name is required and must be a non-empty string.');\n }\n\n const records = this.indexByArea().get(name.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No data found for area \"${name.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n // ─── Pincode range queries ──────────────────────────────────\n\n /** Get all pincodes in a state. */\n getPincodesByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n /** Get all pincodes in a district. */\n getPincodesByDistrict(district: string): string[] {\n const records = this.indexByDistrict().get(district.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n // ─── Free-text search ───────────────────────────────────────\n\n /**\n * Search across pincode, area name, district, state.\n * Returns early once limit is reached — no wasted iteration.\n */\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!query || typeof query !== 'string' || !query.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Search query is required and must be a non-empty string.');\n }\n\n const data = loadData();\n const q = query.trim().toLowerCase();\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n const officeType = options?.officeType;\n const deliveryOnly = options?.deliveryOnly;\n\n const matches: PostOffice[] = [];\n const maxScan = (page * limit) + limit; // fetch enough for pagination\n\n for (let i = 0; i < data.length && matches.length < maxScan; i++) {\n const r = data[i];\n if (officeType && r.officeType !== officeType) continue;\n if (deliveryOnly && !r.delivery) continue;\n\n if (\n r.pincode.includes(q) ||\n r.area.toLowerCase().includes(q) ||\n r.district.toLowerCase().includes(q) ||\n r.state.toLowerCase().includes(q) ||\n r.circle.toLowerCase().includes(q) ||\n r.region.toLowerCase().includes(q)\n ) {\n matches.push(r);\n }\n }\n\n if (matches.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No results found for \"${query.trim()}\".`);\n }\n\n const total = matches.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n\n return ok({\n data: matches.slice(start, start + limit),\n total,\n page,\n limit,\n totalPages,\n });\n }\n\n // ─── Geo: nearby search ─────────────────────────────────────\n\n /**\n * Find post offices near a given coordinate.\n * Uses bounding-box pre-filter + Haversine for accuracy.\n * Returns sorted by distance ascending.\n */\n findNearby(\n lat: number,\n lng: number,\n radiusKm = 10,\n limit = 20,\n ): ApiResponse<NearbyResult[]> {\n if (typeof lat !== 'number' || typeof lng !== 'number' || !Number.isFinite(lat) || !Number.isFinite(lng)) {\n return fail(ErrorCode.INVALID_COORDINATES, 'Latitude and longitude must be valid numbers.');\n }\n if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {\n return fail(\n ErrorCode.INVALID_COORDINATES,\n `Invalid coordinates (${lat}, ${lng}). Latitude must be -90 to 90, longitude -180 to 180.`,\n );\n }\n const data = loadData();\n // Bounding-box pre-filter (1 degree ≈ 111 km)\n const dLat = radiusKm / 111;\n const dLng = radiusKm / (111 * Math.cos(toRad(lat)));\n const minLat = lat - dLat;\n const maxLat = lat + dLat;\n const minLng = lng - dLng;\n const maxLng = lng + dLng;\n\n const results: NearbyResult[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const r = data[i];\n if (r.latitude === null || r.longitude === null) continue;\n // Bounding box check (cheap)\n if (r.latitude < minLat || r.latitude > maxLat) continue;\n if (r.longitude < minLng || r.longitude > maxLng) continue;\n // Haversine (accurate)\n const d = haversine(lat, lng, r.latitude, r.longitude);\n if (d <= radiusKm) {\n results.push({ ...r, distanceKm: Math.round(d * 100) / 100 });\n }\n }\n\n results.sort((a, b) => a.distanceKm - b.distanceKm);\n const sliced = results.slice(0, limit);\n\n if (sliced.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No post offices found within ${radiusKm}km of (${lat}, ${lng}).`);\n }\n\n return ok(sliced);\n }\n\n // ─── Bulk / utility ─────────────────────────────────────────\n\n /** Total number of post office records loaded. */\n getTotalRecords(): number {\n return loadData().length;\n }\n\n /** Total number of unique pincodes. */\n getTotalPincodes(): number {\n return this.indexByPincode().size;\n }\n\n /** Clear all cached data and indexes — reloads fresh on next call. */\n clearCache(): void {\n this._byPincode = null;\n this._byState = null;\n this._byDistrict = null;\n this._byArea = null;\n clearDataCache();\n }\n}\n\n// ─── Haversine helpers ────────────────────────────────────────────\nfunction toRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\nfunction haversine(lat1: number, lon1: number, lat2: number, lon2: number): number {\n const R = 6371;\n const dLat = toRad(lat2 - lat1);\n const dLon = toRad(lon2 - lon1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;\n return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n}\n\n// ─── Singleton ────────────────────────────────────────────────────\nlet _instance: IndiaPincode | null = null;\n\n/** Returns a singleton IndiaPincode instance. */\nexport function getIndiaPincode(): IndiaPincode {\n if (!_instance) _instance = new IndiaPincode();\n return _instance;\n}\n","import { Injectable } from '@nestjs/common';\nimport { IndiaPincode } from './pincode-lookup';\nimport {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n} from './types';\n\n/**\n * NestJS Injectable service — wraps IndiaPincode for DI.\n * Import PincodeModule in your AppModule, then inject this anywhere.\n */\n@Injectable()\nexport class PincodeService {\n private readonly engine: IndiaPincode;\n\n constructor() {\n this.engine = new IndiaPincode();\n }\n\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByPincode(pincode, options);\n }\n\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n return this.engine.getPincodeSummary(pincode);\n }\n\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByState(state, options);\n }\n\n getStateSummary(state: string): ApiResponse<StateSummary> {\n return this.engine.getStateSummary(state);\n }\n\n getAllStates(): string[] {\n return this.engine.getAllStates();\n }\n\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByDistrict(district, options);\n }\n\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n return this.engine.getDistrictSummary(district);\n }\n\n getDistrictsByState(state: string): string[] {\n return this.engine.getDistrictsByState(state);\n }\n\n getAllDistricts(): string[] {\n return this.engine.getAllDistricts();\n }\n\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByArea(name, options);\n }\n\n getPincodesByState(state: string): string[] {\n return this.engine.getPincodesByState(state);\n }\n\n getPincodesByDistrict(district: string): string[] {\n return this.engine.getPincodesByDistrict(district);\n }\n\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.search(query, options);\n }\n\n findNearby(lat: number, lng: number, radiusKm?: number, limit?: number): ApiResponse<NearbyResult[]> {\n return this.engine.findNearby(lat, lng, radiusKm, limit);\n }\n\n getTotalRecords(): number {\n return this.engine.getTotalRecords();\n }\n\n getTotalPincodes(): number {\n return this.engine.getTotalPincodes();\n }\n\n clearCache(): void {\n this.engine.clearCache();\n }\n}\n","import { Module, Global } from '@nestjs/common';\nimport { PincodeService } from './pincode.service';\n\n/**\n * NestJS Module for Indian Pincode data.\n *\n * Usage in your NestJS app:\n * ```ts\n * import { PincodeModule } from 'india-pincode';\n *\n * @Module({\n * imports: [PincodeModule],\n * })\n * export class AppModule {}\n * ```\n *\n * Then inject PincodeService in any controller/service:\n * ```ts\n * constructor(private readonly pincodeService: PincodeService) {}\n * ```\n */\n@Global()\n@Module({\n providers: [PincodeService],\n exports: [PincodeService],\n})\nexport class PincodeModule {}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/data-loader.ts","../src/pincode-lookup.ts","../src/pincode.service.ts","../src/pincode.module.ts"],"names":["ErrorCode","COUNTRY","PINCODE_REGEX","OFFICE_SUFFIX_REGEX","cachedData","sanitizeCityName","raw","trimStr","val","s","safeNum","n","isValidLatitude","lat","isValidLongitude","lng","normalizeOfficeType","upper","expand","rec","pincode","area","district","state","latitude","longitude","dedupKey","loadData","gzPath","L","jsonPath","h","E","seen","result","i","record","key","isValidPincode","clearDataCache","ok","data","fail","code","message","suggestions","error","findSimilar","index","query","field","max","q","words","w","scored","records","originalName","score","word","b","IndiaPincode","o","keyFn","arr","options","limit","page","filtered","r","total","totalPages","start","trimmed","first","stateIndex","districtSet","pincodeSet","idx","districtIndex","set","d","name","areaIndex","officeType","deliveryOnly","matches","maxScan","radiusKm","dLat","dLng","toRad","minLat","maxLat","minLng","maxLng","results","haversine","a","sliced","deg","lat1","lon1","lat2","lon2","dLon","_instance","getIndiaPincode","PincodeService","__decorateClass","Injectable","PincodeModule","Global","Module"],"mappings":"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","file":"index.js","sourcesContent":["// ─── Error handling ─────────────────────────────────────────────\nexport enum ErrorCode {\n INVALID_PINCODE = 'INVALID_PINCODE',\n PINCODE_NOT_FOUND = 'PINCODE_NOT_FOUND',\n STATE_NOT_FOUND = 'STATE_NOT_FOUND',\n DISTRICT_NOT_FOUND = 'DISTRICT_NOT_FOUND',\n INVALID_COORDINATES = 'INVALID_COORDINATES',\n INVALID_INPUT = 'INVALID_INPUT',\n NO_RESULTS = 'NO_RESULTS',\n}\n\nexport interface ApiError {\n code: ErrorCode;\n message: string;\n suggestions?: string[];\n}\n\nexport interface ApiResponse<T> {\n success: boolean;\n data: T | null;\n error?: ApiError;\n}\n\n// ─── Normalized public type ─────────────────────────────────────\nexport interface PostOffice {\n pincode: string;\n area: string;\n officeType: OfficeType;\n delivery: boolean;\n district: string;\n state: string;\n country: string;\n circle: string;\n region: string;\n division: string;\n latitude: number | null;\n longitude: number | null;\n}\n\nexport type OfficeType = 'BO' | 'SO' | 'HO' | 'PO' | 'GPO';\n\n// ─── Query options ──────────────────────────────────────────────\nexport interface QueryOptions {\n /** Max results to return (default: 100) */\n limit?: number;\n /** Page number, 1-based (default: 1) */\n page?: number;\n /** Filter by office type */\n officeType?: OfficeType;\n /** Filter only delivery offices */\n deliveryOnly?: boolean;\n}\n\n// ─── Paginated result ───────────────────────────────────────────\nexport interface PaginatedResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ─── Location result (with distance) ────────────────────────────\nexport interface NearbyResult extends PostOffice {\n distanceKm: number;\n}\n\n// ─── Slim area shape (used in summaries) ────────────────────────\nexport interface AreaInfo {\n pincode: string;\n area: string;\n latitude: number | null;\n longitude: number | null;\n}\n\n// ─── Summary types ──────────────────────────────────────────────\nexport interface PincodeSummary {\n pincode: string;\n district: string;\n state: string;\n country: string;\n areas: AreaInfo[];\n deliveryAreas: number;\n hasCoordinates: boolean;\n}\n\nexport interface DistrictSummary {\n district: string;\n state: string;\n country: string;\n totalAreas: number;\n totalPincodes: number;\n pincodes: string[];\n}\n\nexport interface StateSummary {\n state: string;\n country: string;\n totalDistricts: number;\n totalAreas: number;\n totalPincodes: number;\n districts: string[];\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as zlib from 'zlib';\nimport { PostOffice, OfficeType } from './types';\n\nconst COUNTRY = 'INDIA';\nconst PINCODE_REGEX = /^[1-9]\\d{5}$/;\n\n/**\n * Regex to strip office-type suffixes from city names.\n * Handles: B.O, S.O, H.O, P.O, G.P.O, M.D.G, R.M.S and their\n * dot-less variants (BO, SO, HO, PO, GPO, MDG, RMS).\n */\nconst OFFICE_SUFFIX_REGEX =\n /\\s+\\(?(?:B\\.?O\\.?|S\\.?O\\.?|H\\.?O\\.?|P\\.?O\\.?|G\\.?P\\.?O\\.?|M\\.?D\\.?G\\.?|R\\.?M\\.?S\\.?)\\)?\\s*$/i;\n\n/** Compact JSON record shape (short keys for minimal file size) */\ninterface CompactRecord {\n c: string; // circlename\n r: string; // regionname\n v: string; // divisionname\n o: string; // officename\n p: string; // pincode\n t: string; // officetype\n d: number; // delivery (1 = yes, 0 = no)\n i: string; // district\n s: string; // statename\n a: number; // latitude (0 = not available)\n n: number; // longitude (0 = not available)\n}\n\nlet cachedData: PostOffice[] | null = null;\n\n// ─── Sanitization helpers ───────────────────────────────────────\n\n/** Strip office-type suffixes (B.O, S.O, H.O, etc.) and trim */\nfunction sanitizeCityName(raw: string): string {\n if (!raw || typeof raw !== 'string') return '';\n return raw.replace(OFFICE_SUFFIX_REGEX, '').replace(/\\s{2,}/g, ' ').trim();\n}\n\n/** Trim and collapse extra whitespace */\nfunction trimStr(val: unknown): string {\n if (val === null || val === undefined) return '';\n const s = String(val).trim();\n return s === 'NA' ? '' : s.replace(/\\s{2,}/g, ' ');\n}\n\n/** Parse a numeric field, returning null for invalid / NaN / 0 */\nfunction safeNum(val: unknown): number | null {\n if (val === null || val === undefined) return null;\n const n = Number(val);\n if (!Number.isFinite(n) || n === 0) return null;\n return n;\n}\n\n/** Validate latitude is within valid range */\nfunction isValidLatitude(lat: number | null): boolean {\n return lat === null || (lat >= -90 && lat <= 90);\n}\n\n/** Validate longitude is within valid range */\nfunction isValidLongitude(lng: number | null): boolean {\n return lng === null || (lng >= -180 && lng <= 180);\n}\n\n/** Normalize office type string to valid OfficeType */\nfunction normalizeOfficeType(raw: string): OfficeType {\n const upper = String(raw).replace(/\\./g, '').toUpperCase().trim();\n const valid: OfficeType[] = ['BO', 'SO', 'HO', 'PO', 'GPO'];\n return (valid.includes(upper as OfficeType) ? upper : 'BO') as OfficeType;\n}\n\n// ─── Expand & validate ──────────────────────────────────────────\n\n/** Expand a compact record into a validated PostOffice (or null if invalid) */\nfunction expand(rec: CompactRecord): PostOffice | null {\n const pincode = trimStr(rec.p);\n const area = sanitizeCityName(trimStr(rec.o));\n const district = trimStr(rec.i);\n const state = trimStr(rec.s);\n\n // Required field checks\n if (!pincode || !area || !district || !state) return null;\n\n // Pincode must be exactly 6 digits starting with 1-9\n if (!PINCODE_REGEX.test(pincode)) return null;\n\n const latitude = safeNum(rec.a);\n const longitude = safeNum(rec.n);\n\n // Reject out-of-range coordinates\n if (!isValidLatitude(latitude) || !isValidLongitude(longitude)) return null;\n\n return {\n pincode,\n area,\n officeType: normalizeOfficeType(rec.t),\n delivery: rec.d === 1,\n district,\n state,\n country: COUNTRY,\n circle: trimStr(rec.c),\n region: trimStr(rec.r),\n division: trimStr(rec.v),\n latitude,\n longitude,\n };\n}\n\n/** Build a dedup key for a record */\nfunction dedupKey(r: PostOffice): string {\n return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`;\n}\n\n/**\n * Loads, validates, sanitizes and deduplicates all pincode data.\n * Cached after first call — subsequent calls return instantly.\n *\n * Records that fail validation are silently dropped:\n * - Missing required fields (pincode, area, district, state)\n * - Invalid pincode format (must be 6 digits, starting 1–9)\n * - Out-of-range coordinates\n * - NaN / undefined / null in required fields\n * - Duplicate records (same pincode + area + district + officeType)\n */\nexport function loadData(): PostOffice[] {\n if (cachedData) return cachedData;\n\n const gzPath = path.resolve(__dirname, '..', 'data', 'pincodes.json.gz');\n const jsonPath = path.resolve(__dirname, '..', 'data', 'pincodes.json');\n\n let raw: CompactRecord[];\n if (fs.existsSync(gzPath)) {\n raw = JSON.parse(zlib.gunzipSync(fs.readFileSync(gzPath)).toString('utf-8'));\n } else if (fs.existsSync(jsonPath)) {\n raw = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));\n } else {\n throw new Error('india-pincode: data file not found (data/pincodes.json.gz or data/pincodes.json)');\n }\n\n const seen = new Set<string>();\n const result: PostOffice[] = [];\n\n for (let i = 0; i < raw.length; i++) {\n const record = expand(raw[i]);\n if (!record) continue;\n\n const key = dedupKey(record);\n if (seen.has(key)) continue;\n\n seen.add(key);\n result.push(record);\n }\n\n cachedData = result;\n return cachedData;\n}\n\n/** Validates an Indian pincode format. Returns true if valid. */\nexport function isValidPincode(pincode: string): boolean {\n return typeof pincode === 'string' && PINCODE_REGEX.test(pincode.trim());\n}\n\n/** Clears all cached data (useful for testing / hot-reload). */\nexport function clearDataCache(): void {\n cachedData = null;\n}\n","import {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n ErrorCode,\n} from './types';\nimport { loadData, clearDataCache, isValidPincode } from './data-loader';\n\nconst COUNTRY = 'INDIA';\n\n// ─── Response helpers ─────────────────────────────────────────────\n\nfunction ok<T>(data: T): ApiResponse<T> {\n return { success: true, data };\n}\n\nfunction fail<T>(code: ErrorCode, message: string, suggestions?: string[]): ApiResponse<T> {\n const error: { code: ErrorCode; message: string; suggestions?: string[] } = { code, message };\n if (suggestions && suggestions.length > 0) {\n error.suggestions = suggestions;\n error.message += ` Did you mean: ${suggestions.join(', ')}?`;\n }\n return { success: false, data: null, error };\n}\n\n/**\n * Find similar keys from an index map using substring + word matching.\n * Returns up to `max` original-cased names that partially match the query.\n */\nfunction findSimilar(\n index: Map<string, PostOffice[]>,\n query: string,\n field: 'district' | 'state' | 'area',\n max = 5,\n): string[] {\n const q = query.toLowerCase();\n const words = q.split(/\\s+/).filter((w) => w.length >= 3);\n const scored: { name: string; score: number }[] = [];\n\n for (const [key, records] of index) {\n if (!key) continue;\n const originalName = records[0] ? records[0][field] : key;\n\n let score = 0;\n\n // Exact substring match (highest)\n if (key.includes(q)) {\n score += 10;\n }\n\n // Individual word matches\n for (const word of words) {\n if (key.includes(word)) score += 3;\n }\n\n // Query is a substring of the key or vice versa\n if (q.includes(key)) score += 5;\n\n if (score > 0) {\n scored.push({ name: originalName, score });\n }\n }\n\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, max)\n .map((s) => s.name);\n}\n\n/**\n * High-performance Indian Pincode lookup engine.\n *\n * Architecture:\n * - All indexes are lazy-built on first access, then cached.\n * - Pincode → O(1) HashMap lookup.\n * - State / District / Area → O(1) index lookup.\n * - Geo-nearby → Haversine with early bounding-box pruning.\n * - All responses wrapped in ApiResponse with proper error codes.\n */\nexport class IndiaPincode {\n // ─── Indexes (lazy) ─────────────────────────────────────────\n private _byPincode: Map<string, PostOffice[]> | null = null;\n private _byState: Map<string, PostOffice[]> | null = null;\n private _byDistrict: Map<string, PostOffice[]> | null = null;\n private _byArea: Map<string, PostOffice[]> | null = null;\n\n // ─── Index builders ─────────────────────────────────────────\n private indexByPincode(): Map<string, PostOffice[]> {\n if (this._byPincode) return this._byPincode;\n this._byPincode = this.buildIndex((o) => o.pincode);\n return this._byPincode;\n }\n\n private indexByState(): Map<string, PostOffice[]> {\n if (this._byState) return this._byState;\n this._byState = this.buildIndex((o) => o.state.toLowerCase());\n return this._byState;\n }\n\n private indexByDistrict(): Map<string, PostOffice[]> {\n if (this._byDistrict) return this._byDistrict;\n this._byDistrict = this.buildIndex((o) => o.district.toLowerCase());\n return this._byDistrict;\n }\n\n private indexByArea(): Map<string, PostOffice[]> {\n if (this._byArea) return this._byArea;\n this._byArea = this.buildIndex((o) => o.area.toLowerCase());\n return this._byArea;\n }\n\n private buildIndex(keyFn: (o: PostOffice) => string): Map<string, PostOffice[]> {\n const data = loadData();\n const index = new Map<string, PostOffice[]>();\n for (let i = 0; i < data.length; i++) {\n const key = keyFn(data[i]);\n if (!key) continue;\n const arr = index.get(key);\n if (arr) arr.push(data[i]);\n else index.set(key, [data[i]]);\n }\n return index;\n }\n\n // ─── Helper: apply filters + pagination ─────────────────────\n private paginate(\n records: PostOffice[],\n options?: QueryOptions,\n ): PaginatedResult<PostOffice> {\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n let filtered = records;\n\n if (options?.officeType) {\n filtered = filtered.filter((r) => r.officeType === options.officeType);\n }\n if (options?.deliveryOnly) {\n filtered = filtered.filter((r) => r.delivery);\n }\n\n const total = filtered.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n const data = filtered.slice(start, start + limit);\n\n return { data, total, page, limit, totalPages };\n }\n\n // ═══════════════════════════════════════════════════════════════\n // PUBLIC API\n // ═══════════════════════════════════════════════════════════════\n\n // ─── Pincode lookup (O(1)) ──────────────────────────────────\n\n /** Get all post offices for a pincode. Returns error for invalid/missing pincodes. */\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a complete summary for a pincode. */\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n const first = records[0];\n return ok({\n pincode: trimmed,\n district: first.district,\n state: first.state,\n country: COUNTRY,\n areas: records.map((r) => ({\n pincode: r.pincode,\n area: r.area,\n latitude: r.latitude,\n longitude: r.longitude,\n })),\n deliveryAreas: records.filter((o) => o.delivery).length,\n hasCoordinates: records.some((o) => o.latitude !== null),\n });\n }\n\n // ─── State queries ──────────────────────────────────────────\n\n /** Get all post offices in a state. */\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const stateIndex = this.indexByState();\n const records = stateIndex.get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(stateIndex, state.trim(), 'state');\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a state — districts, pincode count, etc. */\n getStateSummary(state: string): ApiResponse<StateSummary> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const stateIndex = this.indexByState();\n const records = stateIndex.get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(stateIndex, state.trim(), 'state');\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`, suggestions);\n }\n\n const districtSet = new Set<string>();\n const pincodeSet = new Set<string>();\n for (const r of records) {\n if (r.district) districtSet.add(r.district);\n pincodeSet.add(r.pincode);\n }\n\n return ok({\n state: records[0].state,\n country: COUNTRY,\n totalDistricts: districtSet.size,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n districts: Array.from(districtSet).sort(),\n });\n }\n\n /** Get all unique state names. */\n getAllStates(): string[] {\n const idx = this.indexByState();\n return Array.from(idx.keys())\n .filter((s) => s.length > 0)\n .map((s) => {\n const first = idx.get(s);\n return first ? first[0].state : s;\n })\n .sort();\n }\n\n // ─── District queries ───────────────────────────────────────\n\n /** Get all post offices in a district. */\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const districtIndex = this.indexByDistrict();\n const records = districtIndex.get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(districtIndex, district.trim(), 'district');\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a district. */\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const districtIndex = this.indexByDistrict();\n const records = districtIndex.get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(districtIndex, district.trim(), 'district');\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`, suggestions);\n }\n\n const pincodeSet = new Set<string>();\n for (const r of records) pincodeSet.add(r.pincode);\n\n return ok({\n district: records[0].district,\n state: records[0].state,\n country: COUNTRY,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n pincodes: Array.from(pincodeSet).sort(),\n });\n }\n\n /** Get all districts for a state. */\n getDistrictsByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) {\n if (r.district) set.add(r.district);\n }\n return Array.from(set).sort();\n }\n\n /** Get all unique district names. */\n getAllDistricts(): string[] {\n const idx = this.indexByDistrict();\n return Array.from(idx.keys())\n .filter((d) => d.length > 0)\n .map((d) => {\n const first = idx.get(d);\n return first ? first[0].district : d;\n })\n .sort();\n }\n\n // ─── Area name queries ───────────────────────────────────────\n\n /** Get post offices by exact area name (case-insensitive). */\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!name || typeof name !== 'string' || !name.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Area name is required and must be a non-empty string.');\n }\n\n const areaIndex = this.indexByArea();\n const records = areaIndex.get(name.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(areaIndex, name.trim(), 'area');\n return fail(ErrorCode.NO_RESULTS, `No data found for area \"${name.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n // ─── Pincode range queries ──────────────────────────────────\n\n /** Get all pincodes in a state. */\n getPincodesByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n /** Get all pincodes in a district. */\n getPincodesByDistrict(district: string): string[] {\n const records = this.indexByDistrict().get(district.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n // ─── Free-text search ───────────────────────────────────────\n\n /**\n * Search across pincode, area name, district, state.\n * Returns early once limit is reached — no wasted iteration.\n */\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!query || typeof query !== 'string' || !query.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Search query is required and must be a non-empty string.');\n }\n\n const data = loadData();\n const q = query.trim().toLowerCase();\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n const officeType = options?.officeType;\n const deliveryOnly = options?.deliveryOnly;\n\n const matches: PostOffice[] = [];\n const maxScan = (page * limit) + limit; // fetch enough for pagination\n\n for (let i = 0; i < data.length && matches.length < maxScan; i++) {\n const r = data[i];\n if (officeType && r.officeType !== officeType) continue;\n if (deliveryOnly && !r.delivery) continue;\n\n if (\n r.pincode.includes(q) ||\n r.area.toLowerCase().includes(q) ||\n r.district.toLowerCase().includes(q) ||\n r.state.toLowerCase().includes(q) ||\n r.circle.toLowerCase().includes(q) ||\n r.region.toLowerCase().includes(q)\n ) {\n matches.push(r);\n }\n }\n\n if (matches.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No results found for \"${query.trim()}\".`);\n }\n\n const total = matches.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n\n return ok({\n data: matches.slice(start, start + limit),\n total,\n page,\n limit,\n totalPages,\n });\n }\n\n // ─── Geo: nearby search ─────────────────────────────────────\n\n /**\n * Find post offices near a given coordinate.\n * Uses bounding-box pre-filter + Haversine for accuracy.\n * Returns sorted by distance ascending.\n */\n findNearby(\n lat: number,\n lng: number,\n radiusKm = 10,\n limit = 20,\n ): ApiResponse<NearbyResult[]> {\n if (typeof lat !== 'number' || typeof lng !== 'number' || !Number.isFinite(lat) || !Number.isFinite(lng)) {\n return fail(ErrorCode.INVALID_COORDINATES, 'Latitude and longitude must be valid numbers.');\n }\n if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {\n return fail(\n ErrorCode.INVALID_COORDINATES,\n `Invalid coordinates (${lat}, ${lng}). Latitude must be -90 to 90, longitude -180 to 180.`,\n );\n }\n const data = loadData();\n // Bounding-box pre-filter (1 degree ≈ 111 km)\n const dLat = radiusKm / 111;\n const dLng = radiusKm / (111 * Math.cos(toRad(lat)));\n const minLat = lat - dLat;\n const maxLat = lat + dLat;\n const minLng = lng - dLng;\n const maxLng = lng + dLng;\n\n const results: NearbyResult[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const r = data[i];\n if (r.latitude === null || r.longitude === null) continue;\n // Bounding box check (cheap)\n if (r.latitude < minLat || r.latitude > maxLat) continue;\n if (r.longitude < minLng || r.longitude > maxLng) continue;\n // Haversine (accurate)\n const d = haversine(lat, lng, r.latitude, r.longitude);\n if (d <= radiusKm) {\n results.push({ ...r, distanceKm: Math.round(d * 100) / 100 });\n }\n }\n\n results.sort((a, b) => a.distanceKm - b.distanceKm);\n const sliced = results.slice(0, limit);\n\n if (sliced.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No post offices found within ${radiusKm}km of (${lat}, ${lng}).`);\n }\n\n return ok(sliced);\n }\n\n // ─── Bulk / utility ─────────────────────────────────────────\n\n /** Total number of post office records loaded. */\n getTotalRecords(): number {\n return loadData().length;\n }\n\n /** Total number of unique pincodes. */\n getTotalPincodes(): number {\n return this.indexByPincode().size;\n }\n\n /** Clear all cached data and indexes — reloads fresh on next call. */\n clearCache(): void {\n this._byPincode = null;\n this._byState = null;\n this._byDistrict = null;\n this._byArea = null;\n clearDataCache();\n }\n}\n\n// ─── Haversine helpers ────────────────────────────────────────────\nfunction toRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\nfunction haversine(lat1: number, lon1: number, lat2: number, lon2: number): number {\n const R = 6371;\n const dLat = toRad(lat2 - lat1);\n const dLon = toRad(lon2 - lon1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;\n return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n}\n\n// ─── Singleton ────────────────────────────────────────────────────\nlet _instance: IndiaPincode | null = null;\n\n/** Returns a singleton IndiaPincode instance. */\nexport function getIndiaPincode(): IndiaPincode {\n if (!_instance) _instance = new IndiaPincode();\n return _instance;\n}\n","import { Injectable } from '@nestjs/common';\nimport { IndiaPincode } from './pincode-lookup';\nimport {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n} from './types';\n\n/**\n * NestJS Injectable service — wraps IndiaPincode for DI.\n * Import PincodeModule in your AppModule, then inject this anywhere.\n */\n@Injectable()\nexport class PincodeService {\n private readonly engine: IndiaPincode;\n\n constructor() {\n this.engine = new IndiaPincode();\n }\n\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByPincode(pincode, options);\n }\n\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n return this.engine.getPincodeSummary(pincode);\n }\n\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByState(state, options);\n }\n\n getStateSummary(state: string): ApiResponse<StateSummary> {\n return this.engine.getStateSummary(state);\n }\n\n getAllStates(): string[] {\n return this.engine.getAllStates();\n }\n\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByDistrict(district, options);\n }\n\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n return this.engine.getDistrictSummary(district);\n }\n\n getDistrictsByState(state: string): string[] {\n return this.engine.getDistrictsByState(state);\n }\n\n getAllDistricts(): string[] {\n return this.engine.getAllDistricts();\n }\n\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByArea(name, options);\n }\n\n getPincodesByState(state: string): string[] {\n return this.engine.getPincodesByState(state);\n }\n\n getPincodesByDistrict(district: string): string[] {\n return this.engine.getPincodesByDistrict(district);\n }\n\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.search(query, options);\n }\n\n findNearby(lat: number, lng: number, radiusKm?: number, limit?: number): ApiResponse<NearbyResult[]> {\n return this.engine.findNearby(lat, lng, radiusKm, limit);\n }\n\n getTotalRecords(): number {\n return this.engine.getTotalRecords();\n }\n\n getTotalPincodes(): number {\n return this.engine.getTotalPincodes();\n }\n\n clearCache(): void {\n this.engine.clearCache();\n }\n}\n","import { Module, Global } from '@nestjs/common';\nimport { PincodeService } from './pincode.service';\n\n/**\n * NestJS Module for Indian Pincode data.\n *\n * Usage in your NestJS app:\n * ```ts\n * import { PincodeModule } from 'india-pincode';\n *\n * @Module({\n * imports: [PincodeModule],\n * })\n * export class AppModule {}\n * ```\n *\n * Then inject PincodeService in any controller/service:\n * ```ts\n * constructor(private readonly pincodeService: PincodeService) {}\n * ```\n */\n@Global()\n@Module({\n providers: [PincodeService],\n exports: [PincodeService],\n})\nexport class PincodeModule {}\n"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import*as v from'fs';import*as w from'path';import*as U from'zlib';import {Injectable,Global,Module}from'@nestjs/common';var A=(n,t,e,i)=>{for(var r=t,s=n.length-1,o;s>=0;s--)(o=n[s])&&(r=(o(r))||r);return r};var _=(a=>(a.INVALID_PINCODE="INVALID_PINCODE",a.PINCODE_NOT_FOUND="PINCODE_NOT_FOUND",a.STATE_NOT_FOUND="STATE_NOT_FOUND",a.DISTRICT_NOT_FOUND="DISTRICT_NOT_FOUND",a.INVALID_COORDINATES="INVALID_COORDINATES",a.INVALID_INPUT="INVALID_INPUT",a.NO_RESULTS="NO_RESULTS",a))(_||{});var $="INDIA",E=/^[1-9]\d{5}$/,F=/\s+\(?(?:B\.?O\.?|S\.?O\.?|H\.?O\.?|P\.?O\.?|G\.?P\.?O\.?|M\.?D\.?G\.?|R\.?M\.?S\.?)\)?\s*$/i,S=null;function Q(n){return !n||typeof n!="string"?"":n.replace(F,"").replace(/\s{2,}/g," ").trim()}function p(n){if(n==null)return "";let t=String(n).trim();return t==="NA"?"":t.replace(/\s{2,}/g," ")}function B(n){if(n==null)return null;let t=Number(n);return !Number.isFinite(t)||t===0?null:t}function z(n){return n===null||n>=-90&&n<=90}function k(n){return n===null||n>=-180&&n<=180}function q(n){let t=String(n).replace(/\./g,"").toUpperCase().trim();return ["BO","SO","HO","PO","GPO"].includes(t)?t:"BO"}function G(n){let t=p(n.p),e=Q(p(n.o)),i=p(n.i),r=p(n.s);if(!t||!e||!i||!r||!E.test(t))return null;let s=B(n.a),o=B(n.n);return !z(s)||!k(o)?null:{pincode:t,area:e,officeType:q(n.t),delivery:n.d===1,district:i,state:r,country:$,circle:p(n.c),region:p(n.r),division:p(n.v),latitude:s,longitude:o}}function H(n){return `${n.pincode}|${n.area.toLowerCase()}|${n.district.toLowerCase()}|${n.officeType}`}function O(){if(S)return S;let n=w.resolve(__dirname,"..","data","pincodes.json.gz"),t=v.readFileSync(n),e=JSON.parse(U.gunzipSync(t).toString("utf-8")),i=new Set,r=[];for(let s=0;s<e.length;s++){let o=G(e[s]);if(!o)continue;let a=H(o);i.has(a)||(i.add(a),r.push(o));}return S=r,S}function T(n){return typeof n=="string"&&E.test(n.trim())}function R(){S=null;}var x="INDIA";function f(n){return {success:true,data:n}}function u(n,t){return {success:false,data:null,error:{code:n,message:t}}}var h=class{constructor(){this._byPincode=null;this._byState=null;this._byDistrict=null;this._byArea=null;}indexByPincode(){return this._byPincode?this._byPincode:(this._byPincode=this.buildIndex(t=>t.pincode),this._byPincode)}indexByState(){return this._byState?this._byState:(this._byState=this.buildIndex(t=>t.state.toLowerCase()),this._byState)}indexByDistrict(){return this._byDistrict?this._byDistrict:(this._byDistrict=this.buildIndex(t=>t.district.toLowerCase()),this._byDistrict)}indexByArea(){return this._byArea?this._byArea:(this._byArea=this.buildIndex(t=>t.area.toLowerCase()),this._byArea)}buildIndex(t){let e=O(),i=new Map;for(let r=0;r<e.length;r++){let s=t(e[r]);if(!s)continue;let o=i.get(s);o?o.push(e[r]):i.set(s,[e[r]]);}return i}paginate(t,e){let i=Math.max(1,e?.limit??100),r=Math.max(1,e?.page??1),s=t;e?.officeType&&(s=s.filter(m=>m.officeType===e.officeType)),e?.deliveryOnly&&(s=s.filter(m=>m.delivery));let o=s.length,a=Math.ceil(o/i),y=(r-1)*i;return {data:s.slice(y,y+i),total:o,page:r,limit:i,totalPages:a}}getByPincode(t,e){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let i=t.trim();if(!T(i))return u("INVALID_PINCODE",`Invalid pincode "${i}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let r=this.indexByPincode().get(i);return !r||r.length===0?u("PINCODE_NOT_FOUND",`No data found for pincode "${i}".`):f(this.paginate(r,e))}getPincodeSummary(t){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let e=t.trim();if(!T(e))return u("INVALID_PINCODE",`Invalid pincode "${e}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let i=this.indexByPincode().get(e);if(!i||i.length===0)return u("PINCODE_NOT_FOUND",`No data found for pincode "${e}".`);let r=i[0];return f({pincode:e,district:r.district,state:r.state,country:x,areas:i.map(s=>({pincode:s.pincode,area:s.area,latitude:s.latitude,longitude:s.longitude})),deliveryAreas:i.filter(s=>s.delivery).length,hasCoordinates:i.some(s=>s.latitude!==null)})}getByState(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let i=this.indexByState().get(t.trim().toLowerCase());return !i||i.length===0?u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`):f(this.paginate(i,e))}getStateSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let e=this.indexByState().get(t.trim().toLowerCase());if(!e||e.length===0)return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`);let i=new Set,r=new Set;for(let s of e)s.district&&i.add(s.district),r.add(s.pincode);return f({state:e[0].state,country:x,totalDistricts:i.size,totalAreas:e.length,totalPincodes:r.size,districts:Array.from(i).sort()})}getAllStates(){let t=this.indexByState();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].state:e}).sort()}getByDistrict(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let i=this.indexByDistrict().get(t.trim().toLowerCase());return !i||i.length===0?u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`):f(this.paginate(i,e))}getDistrictSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let e=this.indexByDistrict().get(t.trim().toLowerCase());if(!e||e.length===0)return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`);let i=new Set;for(let r of e)i.add(r.pincode);return f({district:e[0].district,state:e[0].state,country:x,totalAreas:e.length,totalPincodes:i.size,pincodes:Array.from(i).sort()})}getDistrictsByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let r of e)r.district&&i.add(r.district);return Array.from(i).sort()}getAllDistricts(){let t=this.indexByDistrict();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].district:e}).sort()}getByArea(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Area name is required and must be a non-empty string.");let i=this.indexByArea().get(t.trim().toLowerCase());return !i||i.length===0?u("NO_RESULTS",`No data found for area "${t.trim()}".`):f(this.paginate(i,e))}getPincodesByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let r of e)i.add(r.pincode);return Array.from(i).sort()}getPincodesByDistrict(t){let e=this.indexByDistrict().get(t.toLowerCase())??[],i=new Set;for(let r of e)i.add(r.pincode);return Array.from(i).sort()}search(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Search query is required and must be a non-empty string.");let i=O(),r=t.trim().toLowerCase(),s=Math.max(1,e?.limit??100),o=Math.max(1,e?.page??1),a=e?.officeType,y=e?.deliveryOnly,l=[],m=o*s+s;for(let d=0;d<i.length&&l.length<m;d++){let c=i[d];a&&c.officeType!==a||y&&!c.delivery||(c.pincode.includes(r)||c.area.toLowerCase().includes(r)||c.district.toLowerCase().includes(r)||c.state.toLowerCase().includes(r)||c.circle.toLowerCase().includes(r)||c.region.toLowerCase().includes(r))&&l.push(c);}if(l.length===0)return u("NO_RESULTS",`No results found for "${t.trim()}".`);let D=l.length,P=Math.ceil(D/s),b=(o-1)*s;return f({data:l.slice(b,b+s),total:D,page:o,limit:s,totalPages:P})}findNearby(t,e,i=10,r=20){if(typeof t!="number"||typeof e!="number"||!Number.isFinite(t)||!Number.isFinite(e))return u("INVALID_COORDINATES","Latitude and longitude must be valid numbers.");if(t<-90||t>90||e<-180||e>180)return u("INVALID_COORDINATES",`Invalid coordinates (${t}, ${e}). Latitude must be -90 to 90, longitude -180 to 180.`);let s=O(),o=i/111,a=i/(111*Math.cos(N(t))),y=t-o,l=t+o,m=e-a,D=e+a,P=[];for(let d=0;d<s.length;d++){let c=s[d];if(c.latitude===null||c.longitude===null||c.latitude<y||c.latitude>l||c.longitude<m||c.longitude>D)continue;let C=X(t,e,c.latitude,c.longitude);C<=i&&P.push({...c,distanceKm:Math.round(C*100)/100});}P.sort((d,c)=>d.distanceKm-c.distanceKm);let b=P.slice(0,r);return b.length===0?u("NO_RESULTS",`No post offices found within ${i}km of (${t}, ${e}).`):f(b)}getTotalRecords(){return O().length}getTotalPincodes(){return this.indexByPincode().size}clearCache(){this._byPincode=null,this._byState=null,this._byDistrict=null,this._byArea=null,R();}};function N(n){return n*(Math.PI/180)}function X(n,t,e,i){let s=N(e-n),o=N(i-t),a=Math.sin(s/2)**2+Math.cos(N(n))*Math.cos(N(e))*Math.sin(o/2)**2;return 6371*2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}var L=null;function j(){return L||(L=new h),L}var g=class{constructor(){this.engine=new h;}getByPincode(t,e){return this.engine.getByPincode(t,e)}getPincodeSummary(t){return this.engine.getPincodeSummary(t)}getByState(t,e){return this.engine.getByState(t,e)}getStateSummary(t){return this.engine.getStateSummary(t)}getAllStates(){return this.engine.getAllStates()}getByDistrict(t,e){return this.engine.getByDistrict(t,e)}getDistrictSummary(t){return this.engine.getDistrictSummary(t)}getDistrictsByState(t){return this.engine.getDistrictsByState(t)}getAllDistricts(){return this.engine.getAllDistricts()}getByArea(t,e){return this.engine.getByArea(t,e)}getPincodesByState(t){return this.engine.getPincodesByState(t)}getPincodesByDistrict(t){return this.engine.getPincodesByDistrict(t)}search(t,e){return this.engine.search(t,e)}findNearby(t,e,i,r){return this.engine.findNearby(t,e,i,r)}getTotalRecords(){return this.engine.getTotalRecords()}getTotalPincodes(){return this.engine.getTotalPincodes()}clearCache(){this.engine.clearCache();}};g=A([Injectable()],g);var I=class{};I=A([Global(),Module({providers:[g],exports:[g]})],I);export{_ as ErrorCode,h as IndiaPincode,I as PincodeModule,g as PincodeService,R as clearDataCache,j as getIndiaPincode,T as isValidPincode,O as loadData};//# sourceMappingURL=index.mjs.map
1
+ import*as h from'fs';import*as L from'path';import*as E from'zlib';import {Injectable,Global,Module}from'@nestjs/common';var _=(r,t,e,i)=>{for(var n=t,s=r.length-1,o;s>=0;s--)(o=r[s])&&(n=(o(n))||n);return n};var x=(a=>(a.INVALID_PINCODE="INVALID_PINCODE",a.PINCODE_NOT_FOUND="PINCODE_NOT_FOUND",a.STATE_NOT_FOUND="STATE_NOT_FOUND",a.DISTRICT_NOT_FOUND="DISTRICT_NOT_FOUND",a.INVALID_COORDINATES="INVALID_COORDINATES",a.INVALID_INPUT="INVALID_INPUT",a.NO_RESULTS="NO_RESULTS",a))(x||{});var F="INDIA",M=/^[1-9]\d{5}$/,Q=/\s+\(?(?:B\.?O\.?|S\.?O\.?|H\.?O\.?|P\.?O\.?|G\.?P\.?O\.?|M\.?D\.?G\.?|R\.?M\.?S\.?)\)?\s*$/i,I=null;function z(r){return !r||typeof r!="string"?"":r.replace(Q,"").replace(/\s{2,}/g," ").trim()}function y(r){if(r==null)return "";let t=String(r).trim();return t==="NA"?"":t.replace(/\s{2,}/g," ")}function U(r){if(r==null)return null;let t=Number(r);return !Number.isFinite(t)||t===0?null:t}function k(r){return r===null||r>=-90&&r<=90}function q(r){return r===null||r>=-180&&r<=180}function j(r){let t=String(r).replace(/\./g,"").toUpperCase().trim();return ["BO","SO","HO","PO","GPO"].includes(t)?t:"BO"}function G(r){let t=y(r.p),e=z(y(r.o)),i=y(r.i),n=y(r.s);if(!t||!e||!i||!n||!M.test(t))return null;let s=U(r.a),o=U(r.n);return !k(s)||!q(o)?null:{pincode:t,area:e,officeType:j(r.t),delivery:r.d===1,district:i,state:n,country:F,circle:y(r.c),region:y(r.r),division:y(r.v),latitude:s,longitude:o}}function H(r){return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`}function P(){if(I)return I;let r=L.resolve(__dirname,"..","data","pincodes.json.gz"),t=L.resolve(__dirname,"..","data","pincodes.json"),e;if(h.existsSync(r))e=JSON.parse(E.gunzipSync(h.readFileSync(r)).toString("utf-8"));else if(h.existsSync(t))e=JSON.parse(h.readFileSync(t,"utf-8"));else throw new Error("india-pincode: data file not found (data/pincodes.json.gz or data/pincodes.json)");let i=new Set,n=[];for(let s=0;s<e.length;s++){let o=G(e[s]);if(!o)continue;let a=H(o);i.has(a)||(i.add(a),n.push(o));}return I=n,I}function R(r){return typeof r=="string"&&M.test(r.trim())}function C(){I=null;}var B="INDIA";function m(r){return {success:true,data:r}}function u(r,t,e){let i={code:r,message:t};return e&&e.length>0&&(i.suggestions=e,i.message+=` Did you mean: ${e.join(", ")}?`),{success:false,data:null,error:i}}function D(r,t,e,i=5){let n=t.toLowerCase(),s=n.split(/\s+/).filter(a=>a.length>=3),o=[];for(let[a,f]of r){if(!a)continue;let g=f[0]?f[0][e]:a,d=0;a.includes(n)&&(d+=10);for(let O of s)a.includes(O)&&(d+=3);n.includes(a)&&(d+=5),d>0&&o.push({name:g,score:d});}return o.sort((a,f)=>f.score-a.score).slice(0,i).map(a=>a.name)}var S=class{constructor(){this._byPincode=null;this._byState=null;this._byDistrict=null;this._byArea=null;}indexByPincode(){return this._byPincode?this._byPincode:(this._byPincode=this.buildIndex(t=>t.pincode),this._byPincode)}indexByState(){return this._byState?this._byState:(this._byState=this.buildIndex(t=>t.state.toLowerCase()),this._byState)}indexByDistrict(){return this._byDistrict?this._byDistrict:(this._byDistrict=this.buildIndex(t=>t.district.toLowerCase()),this._byDistrict)}indexByArea(){return this._byArea?this._byArea:(this._byArea=this.buildIndex(t=>t.area.toLowerCase()),this._byArea)}buildIndex(t){let e=P(),i=new Map;for(let n=0;n<e.length;n++){let s=t(e[n]);if(!s)continue;let o=i.get(s);o?o.push(e[n]):i.set(s,[e[n]]);}return i}paginate(t,e){let i=Math.max(1,e?.limit??100),n=Math.max(1,e?.page??1),s=t;e?.officeType&&(s=s.filter(d=>d.officeType===e.officeType)),e?.deliveryOnly&&(s=s.filter(d=>d.delivery));let o=s.length,a=Math.ceil(o/i),f=(n-1)*i;return {data:s.slice(f,f+i),total:o,page:n,limit:i,totalPages:a}}getByPincode(t,e){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let i=t.trim();if(!R(i))return u("INVALID_PINCODE",`Invalid pincode "${i}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let n=this.indexByPincode().get(i);return !n||n.length===0?u("PINCODE_NOT_FOUND",`No data found for pincode "${i}".`):m(this.paginate(n,e))}getPincodeSummary(t){if(!t||typeof t!="string")return u("INVALID_INPUT","Pincode is required and must be a string.");let e=t.trim();if(!R(e))return u("INVALID_PINCODE",`Invalid pincode "${e}". Indian pincodes must be exactly 6 digits starting with 1-9.`);let i=this.indexByPincode().get(e);if(!i||i.length===0)return u("PINCODE_NOT_FOUND",`No data found for pincode "${e}".`);let n=i[0];return m({pincode:e,district:n.district,state:n.state,country:B,areas:i.map(s=>({pincode:s.pincode,area:s.area,latitude:s.latitude,longitude:s.longitude})),deliveryAreas:i.filter(s=>s.delivery).length,hasCoordinates:i.some(s=>s.latitude!==null)})}getByState(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let i=this.indexByState(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"state");return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`,s)}return m(this.paginate(n,e))}getStateSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","State name is required and must be a non-empty string.");let e=this.indexByState(),i=e.get(t.trim().toLowerCase());if(!i||i.length===0){let o=D(e,t.trim(),"state");return u("STATE_NOT_FOUND",`No data found for state "${t.trim()}".`,o)}let n=new Set,s=new Set;for(let o of i)o.district&&n.add(o.district),s.add(o.pincode);return m({state:i[0].state,country:B,totalDistricts:n.size,totalAreas:i.length,totalPincodes:s.size,districts:Array.from(n).sort()})}getAllStates(){let t=this.indexByState();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].state:e}).sort()}getByDistrict(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let i=this.indexByDistrict(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"district");return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`,s)}return m(this.paginate(n,e))}getDistrictSummary(t){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","District name is required and must be a non-empty string.");let e=this.indexByDistrict(),i=e.get(t.trim().toLowerCase());if(!i||i.length===0){let s=D(e,t.trim(),"district");return u("DISTRICT_NOT_FOUND",`No data found for district "${t.trim()}".`,s)}let n=new Set;for(let s of i)n.add(s.pincode);return m({district:i[0].district,state:i[0].state,country:B,totalAreas:i.length,totalPincodes:n.size,pincodes:Array.from(n).sort()})}getDistrictsByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let n of e)n.district&&i.add(n.district);return Array.from(i).sort()}getAllDistricts(){let t=this.indexByDistrict();return Array.from(t.keys()).filter(e=>e.length>0).map(e=>{let i=t.get(e);return i?i[0].district:e}).sort()}getByArea(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Area name is required and must be a non-empty string.");let i=this.indexByArea(),n=i.get(t.trim().toLowerCase());if(!n||n.length===0){let s=D(i,t.trim(),"area");return u("NO_RESULTS",`No data found for area "${t.trim()}".`,s)}return m(this.paginate(n,e))}getPincodesByState(t){let e=this.indexByState().get(t.toLowerCase())??[],i=new Set;for(let n of e)i.add(n.pincode);return Array.from(i).sort()}getPincodesByDistrict(t){let e=this.indexByDistrict().get(t.toLowerCase())??[],i=new Set;for(let n of e)i.add(n.pincode);return Array.from(i).sort()}search(t,e){if(!t||typeof t!="string"||!t.trim())return u("INVALID_INPUT","Search query is required and must be a non-empty string.");let i=P(),n=t.trim().toLowerCase(),s=Math.max(1,e?.limit??100),o=Math.max(1,e?.page??1),a=e?.officeType,f=e?.deliveryOnly,g=[],d=o*s+s;for(let l=0;l<i.length&&g.length<d;l++){let c=i[l];a&&c.officeType!==a||f&&!c.delivery||(c.pincode.includes(n)||c.area.toLowerCase().includes(n)||c.district.toLowerCase().includes(n)||c.state.toLowerCase().includes(n)||c.circle.toLowerCase().includes(n)||c.region.toLowerCase().includes(n))&&g.push(c);}if(g.length===0)return u("NO_RESULTS",`No results found for "${t.trim()}".`);let O=g.length,b=Math.ceil(O/s),N=(o-1)*s;return m({data:g.slice(N,N+s),total:O,page:o,limit:s,totalPages:b})}findNearby(t,e,i=10,n=20){if(typeof t!="number"||typeof e!="number"||!Number.isFinite(t)||!Number.isFinite(e))return u("INVALID_COORDINATES","Latitude and longitude must be valid numbers.");if(t<-90||t>90||e<-180||e>180)return u("INVALID_COORDINATES",`Invalid coordinates (${t}, ${e}). Latitude must be -90 to 90, longitude -180 to 180.`);let s=P(),o=i/111,a=i/(111*Math.cos(A(t))),f=t-o,g=t+o,d=e-a,O=e+a,b=[];for(let l=0;l<s.length;l++){let c=s[l];if(c.latitude===null||c.longitude===null||c.latitude<f||c.latitude>g||c.longitude<d||c.longitude>O)continue;let v=X(t,e,c.latitude,c.longitude);v<=i&&b.push({...c,distanceKm:Math.round(v*100)/100});}b.sort((l,c)=>l.distanceKm-c.distanceKm);let N=b.slice(0,n);return N.length===0?u("NO_RESULTS",`No post offices found within ${i}km of (${t}, ${e}).`):m(N)}getTotalRecords(){return P().length}getTotalPincodes(){return this.indexByPincode().size}clearCache(){this._byPincode=null,this._byState=null,this._byDistrict=null,this._byArea=null,C();}};function A(r){return r*(Math.PI/180)}function X(r,t,e,i){let s=A(e-r),o=A(i-t),a=Math.sin(s/2)**2+Math.cos(A(r))*Math.cos(A(e))*Math.sin(o/2)**2;return 6371*2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}var w=null;function J(){return w||(w=new S),w}var p=class{constructor(){this.engine=new S;}getByPincode(t,e){return this.engine.getByPincode(t,e)}getPincodeSummary(t){return this.engine.getPincodeSummary(t)}getByState(t,e){return this.engine.getByState(t,e)}getStateSummary(t){return this.engine.getStateSummary(t)}getAllStates(){return this.engine.getAllStates()}getByDistrict(t,e){return this.engine.getByDistrict(t,e)}getDistrictSummary(t){return this.engine.getDistrictSummary(t)}getDistrictsByState(t){return this.engine.getDistrictsByState(t)}getAllDistricts(){return this.engine.getAllDistricts()}getByArea(t,e){return this.engine.getByArea(t,e)}getPincodesByState(t){return this.engine.getPincodesByState(t)}getPincodesByDistrict(t){return this.engine.getPincodesByDistrict(t)}search(t,e){return this.engine.search(t,e)}findNearby(t,e,i,n){return this.engine.findNearby(t,e,i,n)}getTotalRecords(){return this.engine.getTotalRecords()}getTotalPincodes(){return this.engine.getTotalPincodes()}clearCache(){this.engine.clearCache();}};p=_([Injectable()],p);var T=class{};T=_([Global(),Module({providers:[p],exports:[p]})],T);export{x as ErrorCode,S as IndiaPincode,T as PincodeModule,p as PincodeService,C as clearDataCache,J as getIndiaPincode,R as isValidPincode,P as loadData};//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/data-loader.ts","../src/pincode-lookup.ts","../src/pincode.service.ts","../src/pincode.module.ts"],"names":["ErrorCode","COUNTRY","PINCODE_REGEX","OFFICE_SUFFIX_REGEX","cachedData","sanitizeCityName","raw","trimStr","val","s","safeNum","n","isValidLatitude","lat","isValidLongitude","lng","normalizeOfficeType","upper","expand","rec","pincode","area","district","state","latitude","longitude","dedupKey","r","loadData","dataPath","compressed","seen","result","i","record","key","isValidPincode","clearDataCache","ok","data","fail","code","message","IndiaPincode","o","keyFn","index","arr","records","options","limit","page","filtered","total","totalPages","start","trimmed","first","districtSet","pincodeSet","idx","set","d","name","query","q","officeType","deliveryOnly","matches","maxScan","radiusKm","dLat","dLng","toRad","minLat","maxLat","minLng","maxLng","results","haversine","a","b","sliced","deg","lat1","lon1","lat2","lon2","dLon","_instance","getIndiaPincode","PincodeService","__decorateClass","Injectable","PincodeModule","Global","Module"],"mappings":"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","file":"index.mjs","sourcesContent":["// ─── Error handling ─────────────────────────────────────────────\nexport enum ErrorCode {\n INVALID_PINCODE = 'INVALID_PINCODE',\n PINCODE_NOT_FOUND = 'PINCODE_NOT_FOUND',\n STATE_NOT_FOUND = 'STATE_NOT_FOUND',\n DISTRICT_NOT_FOUND = 'DISTRICT_NOT_FOUND',\n INVALID_COORDINATES = 'INVALID_COORDINATES',\n INVALID_INPUT = 'INVALID_INPUT',\n NO_RESULTS = 'NO_RESULTS',\n}\n\nexport interface ApiError {\n code: ErrorCode;\n message: string;\n}\n\nexport interface ApiResponse<T> {\n success: boolean;\n data: T | null;\n error?: ApiError;\n}\n\n// ─── Normalized public type ─────────────────────────────────────\nexport interface PostOffice {\n pincode: string;\n area: string;\n officeType: OfficeType;\n delivery: boolean;\n district: string;\n state: string;\n country: string;\n circle: string;\n region: string;\n division: string;\n latitude: number | null;\n longitude: number | null;\n}\n\nexport type OfficeType = 'BO' | 'SO' | 'HO' | 'PO' | 'GPO';\n\n// ─── Query options ──────────────────────────────────────────────\nexport interface QueryOptions {\n /** Max results to return (default: 100) */\n limit?: number;\n /** Page number, 1-based (default: 1) */\n page?: number;\n /** Filter by office type */\n officeType?: OfficeType;\n /** Filter only delivery offices */\n deliveryOnly?: boolean;\n}\n\n// ─── Paginated result ───────────────────────────────────────────\nexport interface PaginatedResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ─── Location result (with distance) ────────────────────────────\nexport interface NearbyResult extends PostOffice {\n distanceKm: number;\n}\n\n// ─── Slim area shape (used in summaries) ────────────────────────\nexport interface AreaInfo {\n pincode: string;\n area: string;\n latitude: number | null;\n longitude: number | null;\n}\n\n// ─── Summary types ──────────────────────────────────────────────\nexport interface PincodeSummary {\n pincode: string;\n district: string;\n state: string;\n country: string;\n areas: AreaInfo[];\n deliveryAreas: number;\n hasCoordinates: boolean;\n}\n\nexport interface DistrictSummary {\n district: string;\n state: string;\n country: string;\n totalAreas: number;\n totalPincodes: number;\n pincodes: string[];\n}\n\nexport interface StateSummary {\n state: string;\n country: string;\n totalDistricts: number;\n totalAreas: number;\n totalPincodes: number;\n districts: string[];\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as zlib from 'zlib';\nimport { PostOffice, OfficeType } from './types';\n\nconst COUNTRY = 'INDIA';\nconst PINCODE_REGEX = /^[1-9]\\d{5}$/;\n\n/**\n * Regex to strip office-type suffixes from city names.\n * Handles: B.O, S.O, H.O, P.O, G.P.O, M.D.G, R.M.S and their\n * dot-less variants (BO, SO, HO, PO, GPO, MDG, RMS).\n */\nconst OFFICE_SUFFIX_REGEX =\n /\\s+\\(?(?:B\\.?O\\.?|S\\.?O\\.?|H\\.?O\\.?|P\\.?O\\.?|G\\.?P\\.?O\\.?|M\\.?D\\.?G\\.?|R\\.?M\\.?S\\.?)\\)?\\s*$/i;\n\n/** Compact JSON record shape (short keys for minimal file size) */\ninterface CompactRecord {\n c: string; // circlename\n r: string; // regionname\n v: string; // divisionname\n o: string; // officename\n p: string; // pincode\n t: string; // officetype\n d: number; // delivery (1 = yes, 0 = no)\n i: string; // district\n s: string; // statename\n a: number; // latitude (0 = not available)\n n: number; // longitude (0 = not available)\n}\n\nlet cachedData: PostOffice[] | null = null;\n\n// ─── Sanitization helpers ───────────────────────────────────────\n\n/** Strip office-type suffixes (B.O, S.O, H.O, etc.) and trim */\nfunction sanitizeCityName(raw: string): string {\n if (!raw || typeof raw !== 'string') return '';\n return raw.replace(OFFICE_SUFFIX_REGEX, '').replace(/\\s{2,}/g, ' ').trim();\n}\n\n/** Trim and collapse extra whitespace */\nfunction trimStr(val: unknown): string {\n if (val === null || val === undefined) return '';\n const s = String(val).trim();\n return s === 'NA' ? '' : s.replace(/\\s{2,}/g, ' ');\n}\n\n/** Parse a numeric field, returning null for invalid / NaN / 0 */\nfunction safeNum(val: unknown): number | null {\n if (val === null || val === undefined) return null;\n const n = Number(val);\n if (!Number.isFinite(n) || n === 0) return null;\n return n;\n}\n\n/** Validate latitude is within valid range */\nfunction isValidLatitude(lat: number | null): boolean {\n return lat === null || (lat >= -90 && lat <= 90);\n}\n\n/** Validate longitude is within valid range */\nfunction isValidLongitude(lng: number | null): boolean {\n return lng === null || (lng >= -180 && lng <= 180);\n}\n\n/** Normalize office type string to valid OfficeType */\nfunction normalizeOfficeType(raw: string): OfficeType {\n const upper = String(raw).replace(/\\./g, '').toUpperCase().trim();\n const valid: OfficeType[] = ['BO', 'SO', 'HO', 'PO', 'GPO'];\n return (valid.includes(upper as OfficeType) ? upper : 'BO') as OfficeType;\n}\n\n// ─── Expand & validate ──────────────────────────────────────────\n\n/** Expand a compact record into a validated PostOffice (or null if invalid) */\nfunction expand(rec: CompactRecord): PostOffice | null {\n const pincode = trimStr(rec.p);\n const area = sanitizeCityName(trimStr(rec.o));\n const district = trimStr(rec.i);\n const state = trimStr(rec.s);\n\n // Required field checks\n if (!pincode || !area || !district || !state) return null;\n\n // Pincode must be exactly 6 digits starting with 1-9\n if (!PINCODE_REGEX.test(pincode)) return null;\n\n const latitude = safeNum(rec.a);\n const longitude = safeNum(rec.n);\n\n // Reject out-of-range coordinates\n if (!isValidLatitude(latitude) || !isValidLongitude(longitude)) return null;\n\n return {\n pincode,\n area,\n officeType: normalizeOfficeType(rec.t),\n delivery: rec.d === 1,\n district,\n state,\n country: COUNTRY,\n circle: trimStr(rec.c),\n region: trimStr(rec.r),\n division: trimStr(rec.v),\n latitude,\n longitude,\n };\n}\n\n/** Build a dedup key for a record */\nfunction dedupKey(r: PostOffice): string {\n return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`;\n}\n\n/**\n * Loads, validates, sanitizes and deduplicates all pincode data.\n * Cached after first call — subsequent calls return instantly.\n *\n * Records that fail validation are silently dropped:\n * - Missing required fields (pincode, area, district, state)\n * - Invalid pincode format (must be 6 digits, starting 1–9)\n * - Out-of-range coordinates\n * - NaN / undefined / null in required fields\n * - Duplicate records (same pincode + area + district + officeType)\n */\nexport function loadData(): PostOffice[] {\n if (cachedData) return cachedData;\n\n const dataPath = path.resolve(__dirname, '..', 'data', 'pincodes.json.gz');\n const compressed = fs.readFileSync(dataPath);\n const raw: CompactRecord[] = JSON.parse(zlib.gunzipSync(compressed).toString('utf-8'));\n\n const seen = new Set<string>();\n const result: PostOffice[] = [];\n\n for (let i = 0; i < raw.length; i++) {\n const record = expand(raw[i]);\n if (!record) continue;\n\n const key = dedupKey(record);\n if (seen.has(key)) continue;\n\n seen.add(key);\n result.push(record);\n }\n\n cachedData = result;\n return cachedData;\n}\n\n/** Validates an Indian pincode format. Returns true if valid. */\nexport function isValidPincode(pincode: string): boolean {\n return typeof pincode === 'string' && PINCODE_REGEX.test(pincode.trim());\n}\n\n/** Clears all cached data (useful for testing / hot-reload). */\nexport function clearDataCache(): void {\n cachedData = null;\n}\n","import {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n ErrorCode,\n} from './types';\nimport { loadData, clearDataCache, isValidPincode } from './data-loader';\n\nconst COUNTRY = 'INDIA';\n\n// ─── Response helpers ─────────────────────────────────────────────\n\nfunction ok<T>(data: T): ApiResponse<T> {\n return { success: true, data };\n}\n\nfunction fail<T>(code: ErrorCode, message: string): ApiResponse<T> {\n return { success: false, data: null, error: { code, message } };\n}\n\n/**\n * High-performance Indian Pincode lookup engine.\n *\n * Architecture:\n * - All indexes are lazy-built on first access, then cached.\n * - Pincode → O(1) HashMap lookup.\n * - State / District / Area → O(1) index lookup.\n * - Geo-nearby → Haversine with early bounding-box pruning.\n * - All responses wrapped in ApiResponse with proper error codes.\n */\nexport class IndiaPincode {\n // ─── Indexes (lazy) ─────────────────────────────────────────\n private _byPincode: Map<string, PostOffice[]> | null = null;\n private _byState: Map<string, PostOffice[]> | null = null;\n private _byDistrict: Map<string, PostOffice[]> | null = null;\n private _byArea: Map<string, PostOffice[]> | null = null;\n\n // ─── Index builders ─────────────────────────────────────────\n private indexByPincode(): Map<string, PostOffice[]> {\n if (this._byPincode) return this._byPincode;\n this._byPincode = this.buildIndex((o) => o.pincode);\n return this._byPincode;\n }\n\n private indexByState(): Map<string, PostOffice[]> {\n if (this._byState) return this._byState;\n this._byState = this.buildIndex((o) => o.state.toLowerCase());\n return this._byState;\n }\n\n private indexByDistrict(): Map<string, PostOffice[]> {\n if (this._byDistrict) return this._byDistrict;\n this._byDistrict = this.buildIndex((o) => o.district.toLowerCase());\n return this._byDistrict;\n }\n\n private indexByArea(): Map<string, PostOffice[]> {\n if (this._byArea) return this._byArea;\n this._byArea = this.buildIndex((o) => o.area.toLowerCase());\n return this._byArea;\n }\n\n private buildIndex(keyFn: (o: PostOffice) => string): Map<string, PostOffice[]> {\n const data = loadData();\n const index = new Map<string, PostOffice[]>();\n for (let i = 0; i < data.length; i++) {\n const key = keyFn(data[i]);\n if (!key) continue;\n const arr = index.get(key);\n if (arr) arr.push(data[i]);\n else index.set(key, [data[i]]);\n }\n return index;\n }\n\n // ─── Helper: apply filters + pagination ─────────────────────\n private paginate(\n records: PostOffice[],\n options?: QueryOptions,\n ): PaginatedResult<PostOffice> {\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n let filtered = records;\n\n if (options?.officeType) {\n filtered = filtered.filter((r) => r.officeType === options.officeType);\n }\n if (options?.deliveryOnly) {\n filtered = filtered.filter((r) => r.delivery);\n }\n\n const total = filtered.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n const data = filtered.slice(start, start + limit);\n\n return { data, total, page, limit, totalPages };\n }\n\n // ═══════════════════════════════════════════════════════════════\n // PUBLIC API\n // ═══════════════════════════════════════════════════════════════\n\n // ─── Pincode lookup (O(1)) ──────────────────────────────────\n\n /** Get all post offices for a pincode. Returns error for invalid/missing pincodes. */\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a complete summary for a pincode. */\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n const first = records[0];\n return ok({\n pincode: trimmed,\n district: first.district,\n state: first.state,\n country: COUNTRY,\n areas: records.map((r) => ({\n pincode: r.pincode,\n area: r.area,\n latitude: r.latitude,\n longitude: r.longitude,\n })),\n deliveryAreas: records.filter((o) => o.delivery).length,\n hasCoordinates: records.some((o) => o.latitude !== null),\n });\n }\n\n // ─── State queries ──────────────────────────────────────────\n\n /** Get all post offices in a state. */\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const records = this.indexByState().get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a state — districts, pincode count, etc. */\n getStateSummary(state: string): ApiResponse<StateSummary> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const records = this.indexByState().get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`);\n }\n\n const districtSet = new Set<string>();\n const pincodeSet = new Set<string>();\n for (const r of records) {\n if (r.district) districtSet.add(r.district);\n pincodeSet.add(r.pincode);\n }\n\n return ok({\n state: records[0].state,\n country: COUNTRY,\n totalDistricts: districtSet.size,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n districts: Array.from(districtSet).sort(),\n });\n }\n\n /** Get all unique state names. */\n getAllStates(): string[] {\n const idx = this.indexByState();\n return Array.from(idx.keys())\n .filter((s) => s.length > 0)\n .map((s) => {\n const first = idx.get(s);\n return first ? first[0].state : s;\n })\n .sort();\n }\n\n // ─── District queries ───────────────────────────────────────\n\n /** Get all post offices in a district. */\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const records = this.indexByDistrict().get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a district. */\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const records = this.indexByDistrict().get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`);\n }\n\n const pincodeSet = new Set<string>();\n for (const r of records) pincodeSet.add(r.pincode);\n\n return ok({\n district: records[0].district,\n state: records[0].state,\n country: COUNTRY,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n pincodes: Array.from(pincodeSet).sort(),\n });\n }\n\n /** Get all districts for a state. */\n getDistrictsByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) {\n if (r.district) set.add(r.district);\n }\n return Array.from(set).sort();\n }\n\n /** Get all unique district names. */\n getAllDistricts(): string[] {\n const idx = this.indexByDistrict();\n return Array.from(idx.keys())\n .filter((d) => d.length > 0)\n .map((d) => {\n const first = idx.get(d);\n return first ? first[0].district : d;\n })\n .sort();\n }\n\n // ─── Area name queries ───────────────────────────────────────\n\n /** Get post offices by exact area name (case-insensitive). */\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!name || typeof name !== 'string' || !name.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Area name is required and must be a non-empty string.');\n }\n\n const records = this.indexByArea().get(name.trim().toLowerCase());\n if (!records || records.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No data found for area \"${name.trim()}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n // ─── Pincode range queries ──────────────────────────────────\n\n /** Get all pincodes in a state. */\n getPincodesByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n /** Get all pincodes in a district. */\n getPincodesByDistrict(district: string): string[] {\n const records = this.indexByDistrict().get(district.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n // ─── Free-text search ───────────────────────────────────────\n\n /**\n * Search across pincode, area name, district, state.\n * Returns early once limit is reached — no wasted iteration.\n */\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!query || typeof query !== 'string' || !query.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Search query is required and must be a non-empty string.');\n }\n\n const data = loadData();\n const q = query.trim().toLowerCase();\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n const officeType = options?.officeType;\n const deliveryOnly = options?.deliveryOnly;\n\n const matches: PostOffice[] = [];\n const maxScan = (page * limit) + limit; // fetch enough for pagination\n\n for (let i = 0; i < data.length && matches.length < maxScan; i++) {\n const r = data[i];\n if (officeType && r.officeType !== officeType) continue;\n if (deliveryOnly && !r.delivery) continue;\n\n if (\n r.pincode.includes(q) ||\n r.area.toLowerCase().includes(q) ||\n r.district.toLowerCase().includes(q) ||\n r.state.toLowerCase().includes(q) ||\n r.circle.toLowerCase().includes(q) ||\n r.region.toLowerCase().includes(q)\n ) {\n matches.push(r);\n }\n }\n\n if (matches.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No results found for \"${query.trim()}\".`);\n }\n\n const total = matches.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n\n return ok({\n data: matches.slice(start, start + limit),\n total,\n page,\n limit,\n totalPages,\n });\n }\n\n // ─── Geo: nearby search ─────────────────────────────────────\n\n /**\n * Find post offices near a given coordinate.\n * Uses bounding-box pre-filter + Haversine for accuracy.\n * Returns sorted by distance ascending.\n */\n findNearby(\n lat: number,\n lng: number,\n radiusKm = 10,\n limit = 20,\n ): ApiResponse<NearbyResult[]> {\n if (typeof lat !== 'number' || typeof lng !== 'number' || !Number.isFinite(lat) || !Number.isFinite(lng)) {\n return fail(ErrorCode.INVALID_COORDINATES, 'Latitude and longitude must be valid numbers.');\n }\n if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {\n return fail(\n ErrorCode.INVALID_COORDINATES,\n `Invalid coordinates (${lat}, ${lng}). Latitude must be -90 to 90, longitude -180 to 180.`,\n );\n }\n const data = loadData();\n // Bounding-box pre-filter (1 degree ≈ 111 km)\n const dLat = radiusKm / 111;\n const dLng = radiusKm / (111 * Math.cos(toRad(lat)));\n const minLat = lat - dLat;\n const maxLat = lat + dLat;\n const minLng = lng - dLng;\n const maxLng = lng + dLng;\n\n const results: NearbyResult[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const r = data[i];\n if (r.latitude === null || r.longitude === null) continue;\n // Bounding box check (cheap)\n if (r.latitude < minLat || r.latitude > maxLat) continue;\n if (r.longitude < minLng || r.longitude > maxLng) continue;\n // Haversine (accurate)\n const d = haversine(lat, lng, r.latitude, r.longitude);\n if (d <= radiusKm) {\n results.push({ ...r, distanceKm: Math.round(d * 100) / 100 });\n }\n }\n\n results.sort((a, b) => a.distanceKm - b.distanceKm);\n const sliced = results.slice(0, limit);\n\n if (sliced.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No post offices found within ${radiusKm}km of (${lat}, ${lng}).`);\n }\n\n return ok(sliced);\n }\n\n // ─── Bulk / utility ─────────────────────────────────────────\n\n /** Total number of post office records loaded. */\n getTotalRecords(): number {\n return loadData().length;\n }\n\n /** Total number of unique pincodes. */\n getTotalPincodes(): number {\n return this.indexByPincode().size;\n }\n\n /** Clear all cached data and indexes — reloads fresh on next call. */\n clearCache(): void {\n this._byPincode = null;\n this._byState = null;\n this._byDistrict = null;\n this._byArea = null;\n clearDataCache();\n }\n}\n\n// ─── Haversine helpers ────────────────────────────────────────────\nfunction toRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\nfunction haversine(lat1: number, lon1: number, lat2: number, lon2: number): number {\n const R = 6371;\n const dLat = toRad(lat2 - lat1);\n const dLon = toRad(lon2 - lon1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;\n return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n}\n\n// ─── Singleton ────────────────────────────────────────────────────\nlet _instance: IndiaPincode | null = null;\n\n/** Returns a singleton IndiaPincode instance. */\nexport function getIndiaPincode(): IndiaPincode {\n if (!_instance) _instance = new IndiaPincode();\n return _instance;\n}\n","import { Injectable } from '@nestjs/common';\nimport { IndiaPincode } from './pincode-lookup';\nimport {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n} from './types';\n\n/**\n * NestJS Injectable service — wraps IndiaPincode for DI.\n * Import PincodeModule in your AppModule, then inject this anywhere.\n */\n@Injectable()\nexport class PincodeService {\n private readonly engine: IndiaPincode;\n\n constructor() {\n this.engine = new IndiaPincode();\n }\n\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByPincode(pincode, options);\n }\n\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n return this.engine.getPincodeSummary(pincode);\n }\n\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByState(state, options);\n }\n\n getStateSummary(state: string): ApiResponse<StateSummary> {\n return this.engine.getStateSummary(state);\n }\n\n getAllStates(): string[] {\n return this.engine.getAllStates();\n }\n\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByDistrict(district, options);\n }\n\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n return this.engine.getDistrictSummary(district);\n }\n\n getDistrictsByState(state: string): string[] {\n return this.engine.getDistrictsByState(state);\n }\n\n getAllDistricts(): string[] {\n return this.engine.getAllDistricts();\n }\n\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByArea(name, options);\n }\n\n getPincodesByState(state: string): string[] {\n return this.engine.getPincodesByState(state);\n }\n\n getPincodesByDistrict(district: string): string[] {\n return this.engine.getPincodesByDistrict(district);\n }\n\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.search(query, options);\n }\n\n findNearby(lat: number, lng: number, radiusKm?: number, limit?: number): ApiResponse<NearbyResult[]> {\n return this.engine.findNearby(lat, lng, radiusKm, limit);\n }\n\n getTotalRecords(): number {\n return this.engine.getTotalRecords();\n }\n\n getTotalPincodes(): number {\n return this.engine.getTotalPincodes();\n }\n\n clearCache(): void {\n this.engine.clearCache();\n }\n}\n","import { Module, Global } from '@nestjs/common';\nimport { PincodeService } from './pincode.service';\n\n/**\n * NestJS Module for Indian Pincode data.\n *\n * Usage in your NestJS app:\n * ```ts\n * import { PincodeModule } from 'india-pincode';\n *\n * @Module({\n * imports: [PincodeModule],\n * })\n * export class AppModule {}\n * ```\n *\n * Then inject PincodeService in any controller/service:\n * ```ts\n * constructor(private readonly pincodeService: PincodeService) {}\n * ```\n */\n@Global()\n@Module({\n providers: [PincodeService],\n exports: [PincodeService],\n})\nexport class PincodeModule {}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/data-loader.ts","../src/pincode-lookup.ts","../src/pincode.service.ts","../src/pincode.module.ts"],"names":["ErrorCode","COUNTRY","PINCODE_REGEX","OFFICE_SUFFIX_REGEX","cachedData","sanitizeCityName","raw","trimStr","val","s","safeNum","n","isValidLatitude","lat","isValidLongitude","lng","normalizeOfficeType","upper","expand","rec","pincode","area","district","state","latitude","longitude","dedupKey","loadData","gzPath","jsonPath","seen","result","i","record","key","isValidPincode","clearDataCache","ok","data","fail","code","message","suggestions","error","findSimilar","index","query","field","max","q","words","w","scored","records","originalName","score","word","b","IndiaPincode","o","keyFn","arr","options","limit","page","filtered","r","total","totalPages","start","trimmed","first","stateIndex","districtSet","pincodeSet","idx","districtIndex","set","d","name","areaIndex","officeType","deliveryOnly","matches","maxScan","radiusKm","dLat","dLng","toRad","minLat","maxLat","minLng","maxLng","results","haversine","a","sliced","deg","lat1","lon1","lat2","lon2","dLon","_instance","getIndiaPincode","PincodeService","__decorateClass","Injectable","PincodeModule","Global","Module"],"mappings":"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","file":"index.mjs","sourcesContent":["// ─── Error handling ─────────────────────────────────────────────\nexport enum ErrorCode {\n INVALID_PINCODE = 'INVALID_PINCODE',\n PINCODE_NOT_FOUND = 'PINCODE_NOT_FOUND',\n STATE_NOT_FOUND = 'STATE_NOT_FOUND',\n DISTRICT_NOT_FOUND = 'DISTRICT_NOT_FOUND',\n INVALID_COORDINATES = 'INVALID_COORDINATES',\n INVALID_INPUT = 'INVALID_INPUT',\n NO_RESULTS = 'NO_RESULTS',\n}\n\nexport interface ApiError {\n code: ErrorCode;\n message: string;\n suggestions?: string[];\n}\n\nexport interface ApiResponse<T> {\n success: boolean;\n data: T | null;\n error?: ApiError;\n}\n\n// ─── Normalized public type ─────────────────────────────────────\nexport interface PostOffice {\n pincode: string;\n area: string;\n officeType: OfficeType;\n delivery: boolean;\n district: string;\n state: string;\n country: string;\n circle: string;\n region: string;\n division: string;\n latitude: number | null;\n longitude: number | null;\n}\n\nexport type OfficeType = 'BO' | 'SO' | 'HO' | 'PO' | 'GPO';\n\n// ─── Query options ──────────────────────────────────────────────\nexport interface QueryOptions {\n /** Max results to return (default: 100) */\n limit?: number;\n /** Page number, 1-based (default: 1) */\n page?: number;\n /** Filter by office type */\n officeType?: OfficeType;\n /** Filter only delivery offices */\n deliveryOnly?: boolean;\n}\n\n// ─── Paginated result ───────────────────────────────────────────\nexport interface PaginatedResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ─── Location result (with distance) ────────────────────────────\nexport interface NearbyResult extends PostOffice {\n distanceKm: number;\n}\n\n// ─── Slim area shape (used in summaries) ────────────────────────\nexport interface AreaInfo {\n pincode: string;\n area: string;\n latitude: number | null;\n longitude: number | null;\n}\n\n// ─── Summary types ──────────────────────────────────────────────\nexport interface PincodeSummary {\n pincode: string;\n district: string;\n state: string;\n country: string;\n areas: AreaInfo[];\n deliveryAreas: number;\n hasCoordinates: boolean;\n}\n\nexport interface DistrictSummary {\n district: string;\n state: string;\n country: string;\n totalAreas: number;\n totalPincodes: number;\n pincodes: string[];\n}\n\nexport interface StateSummary {\n state: string;\n country: string;\n totalDistricts: number;\n totalAreas: number;\n totalPincodes: number;\n districts: string[];\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as zlib from 'zlib';\nimport { PostOffice, OfficeType } from './types';\n\nconst COUNTRY = 'INDIA';\nconst PINCODE_REGEX = /^[1-9]\\d{5}$/;\n\n/**\n * Regex to strip office-type suffixes from city names.\n * Handles: B.O, S.O, H.O, P.O, G.P.O, M.D.G, R.M.S and their\n * dot-less variants (BO, SO, HO, PO, GPO, MDG, RMS).\n */\nconst OFFICE_SUFFIX_REGEX =\n /\\s+\\(?(?:B\\.?O\\.?|S\\.?O\\.?|H\\.?O\\.?|P\\.?O\\.?|G\\.?P\\.?O\\.?|M\\.?D\\.?G\\.?|R\\.?M\\.?S\\.?)\\)?\\s*$/i;\n\n/** Compact JSON record shape (short keys for minimal file size) */\ninterface CompactRecord {\n c: string; // circlename\n r: string; // regionname\n v: string; // divisionname\n o: string; // officename\n p: string; // pincode\n t: string; // officetype\n d: number; // delivery (1 = yes, 0 = no)\n i: string; // district\n s: string; // statename\n a: number; // latitude (0 = not available)\n n: number; // longitude (0 = not available)\n}\n\nlet cachedData: PostOffice[] | null = null;\n\n// ─── Sanitization helpers ───────────────────────────────────────\n\n/** Strip office-type suffixes (B.O, S.O, H.O, etc.) and trim */\nfunction sanitizeCityName(raw: string): string {\n if (!raw || typeof raw !== 'string') return '';\n return raw.replace(OFFICE_SUFFIX_REGEX, '').replace(/\\s{2,}/g, ' ').trim();\n}\n\n/** Trim and collapse extra whitespace */\nfunction trimStr(val: unknown): string {\n if (val === null || val === undefined) return '';\n const s = String(val).trim();\n return s === 'NA' ? '' : s.replace(/\\s{2,}/g, ' ');\n}\n\n/** Parse a numeric field, returning null for invalid / NaN / 0 */\nfunction safeNum(val: unknown): number | null {\n if (val === null || val === undefined) return null;\n const n = Number(val);\n if (!Number.isFinite(n) || n === 0) return null;\n return n;\n}\n\n/** Validate latitude is within valid range */\nfunction isValidLatitude(lat: number | null): boolean {\n return lat === null || (lat >= -90 && lat <= 90);\n}\n\n/** Validate longitude is within valid range */\nfunction isValidLongitude(lng: number | null): boolean {\n return lng === null || (lng >= -180 && lng <= 180);\n}\n\n/** Normalize office type string to valid OfficeType */\nfunction normalizeOfficeType(raw: string): OfficeType {\n const upper = String(raw).replace(/\\./g, '').toUpperCase().trim();\n const valid: OfficeType[] = ['BO', 'SO', 'HO', 'PO', 'GPO'];\n return (valid.includes(upper as OfficeType) ? upper : 'BO') as OfficeType;\n}\n\n// ─── Expand & validate ──────────────────────────────────────────\n\n/** Expand a compact record into a validated PostOffice (or null if invalid) */\nfunction expand(rec: CompactRecord): PostOffice | null {\n const pincode = trimStr(rec.p);\n const area = sanitizeCityName(trimStr(rec.o));\n const district = trimStr(rec.i);\n const state = trimStr(rec.s);\n\n // Required field checks\n if (!pincode || !area || !district || !state) return null;\n\n // Pincode must be exactly 6 digits starting with 1-9\n if (!PINCODE_REGEX.test(pincode)) return null;\n\n const latitude = safeNum(rec.a);\n const longitude = safeNum(rec.n);\n\n // Reject out-of-range coordinates\n if (!isValidLatitude(latitude) || !isValidLongitude(longitude)) return null;\n\n return {\n pincode,\n area,\n officeType: normalizeOfficeType(rec.t),\n delivery: rec.d === 1,\n district,\n state,\n country: COUNTRY,\n circle: trimStr(rec.c),\n region: trimStr(rec.r),\n division: trimStr(rec.v),\n latitude,\n longitude,\n };\n}\n\n/** Build a dedup key for a record */\nfunction dedupKey(r: PostOffice): string {\n return `${r.pincode}|${r.area.toLowerCase()}|${r.district.toLowerCase()}|${r.officeType}`;\n}\n\n/**\n * Loads, validates, sanitizes and deduplicates all pincode data.\n * Cached after first call — subsequent calls return instantly.\n *\n * Records that fail validation are silently dropped:\n * - Missing required fields (pincode, area, district, state)\n * - Invalid pincode format (must be 6 digits, starting 1–9)\n * - Out-of-range coordinates\n * - NaN / undefined / null in required fields\n * - Duplicate records (same pincode + area + district + officeType)\n */\nexport function loadData(): PostOffice[] {\n if (cachedData) return cachedData;\n\n const gzPath = path.resolve(__dirname, '..', 'data', 'pincodes.json.gz');\n const jsonPath = path.resolve(__dirname, '..', 'data', 'pincodes.json');\n\n let raw: CompactRecord[];\n if (fs.existsSync(gzPath)) {\n raw = JSON.parse(zlib.gunzipSync(fs.readFileSync(gzPath)).toString('utf-8'));\n } else if (fs.existsSync(jsonPath)) {\n raw = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));\n } else {\n throw new Error('india-pincode: data file not found (data/pincodes.json.gz or data/pincodes.json)');\n }\n\n const seen = new Set<string>();\n const result: PostOffice[] = [];\n\n for (let i = 0; i < raw.length; i++) {\n const record = expand(raw[i]);\n if (!record) continue;\n\n const key = dedupKey(record);\n if (seen.has(key)) continue;\n\n seen.add(key);\n result.push(record);\n }\n\n cachedData = result;\n return cachedData;\n}\n\n/** Validates an Indian pincode format. Returns true if valid. */\nexport function isValidPincode(pincode: string): boolean {\n return typeof pincode === 'string' && PINCODE_REGEX.test(pincode.trim());\n}\n\n/** Clears all cached data (useful for testing / hot-reload). */\nexport function clearDataCache(): void {\n cachedData = null;\n}\n","import {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n ErrorCode,\n} from './types';\nimport { loadData, clearDataCache, isValidPincode } from './data-loader';\n\nconst COUNTRY = 'INDIA';\n\n// ─── Response helpers ─────────────────────────────────────────────\n\nfunction ok<T>(data: T): ApiResponse<T> {\n return { success: true, data };\n}\n\nfunction fail<T>(code: ErrorCode, message: string, suggestions?: string[]): ApiResponse<T> {\n const error: { code: ErrorCode; message: string; suggestions?: string[] } = { code, message };\n if (suggestions && suggestions.length > 0) {\n error.suggestions = suggestions;\n error.message += ` Did you mean: ${suggestions.join(', ')}?`;\n }\n return { success: false, data: null, error };\n}\n\n/**\n * Find similar keys from an index map using substring + word matching.\n * Returns up to `max` original-cased names that partially match the query.\n */\nfunction findSimilar(\n index: Map<string, PostOffice[]>,\n query: string,\n field: 'district' | 'state' | 'area',\n max = 5,\n): string[] {\n const q = query.toLowerCase();\n const words = q.split(/\\s+/).filter((w) => w.length >= 3);\n const scored: { name: string; score: number }[] = [];\n\n for (const [key, records] of index) {\n if (!key) continue;\n const originalName = records[0] ? records[0][field] : key;\n\n let score = 0;\n\n // Exact substring match (highest)\n if (key.includes(q)) {\n score += 10;\n }\n\n // Individual word matches\n for (const word of words) {\n if (key.includes(word)) score += 3;\n }\n\n // Query is a substring of the key or vice versa\n if (q.includes(key)) score += 5;\n\n if (score > 0) {\n scored.push({ name: originalName, score });\n }\n }\n\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, max)\n .map((s) => s.name);\n}\n\n/**\n * High-performance Indian Pincode lookup engine.\n *\n * Architecture:\n * - All indexes are lazy-built on first access, then cached.\n * - Pincode → O(1) HashMap lookup.\n * - State / District / Area → O(1) index lookup.\n * - Geo-nearby → Haversine with early bounding-box pruning.\n * - All responses wrapped in ApiResponse with proper error codes.\n */\nexport class IndiaPincode {\n // ─── Indexes (lazy) ─────────────────────────────────────────\n private _byPincode: Map<string, PostOffice[]> | null = null;\n private _byState: Map<string, PostOffice[]> | null = null;\n private _byDistrict: Map<string, PostOffice[]> | null = null;\n private _byArea: Map<string, PostOffice[]> | null = null;\n\n // ─── Index builders ─────────────────────────────────────────\n private indexByPincode(): Map<string, PostOffice[]> {\n if (this._byPincode) return this._byPincode;\n this._byPincode = this.buildIndex((o) => o.pincode);\n return this._byPincode;\n }\n\n private indexByState(): Map<string, PostOffice[]> {\n if (this._byState) return this._byState;\n this._byState = this.buildIndex((o) => o.state.toLowerCase());\n return this._byState;\n }\n\n private indexByDistrict(): Map<string, PostOffice[]> {\n if (this._byDistrict) return this._byDistrict;\n this._byDistrict = this.buildIndex((o) => o.district.toLowerCase());\n return this._byDistrict;\n }\n\n private indexByArea(): Map<string, PostOffice[]> {\n if (this._byArea) return this._byArea;\n this._byArea = this.buildIndex((o) => o.area.toLowerCase());\n return this._byArea;\n }\n\n private buildIndex(keyFn: (o: PostOffice) => string): Map<string, PostOffice[]> {\n const data = loadData();\n const index = new Map<string, PostOffice[]>();\n for (let i = 0; i < data.length; i++) {\n const key = keyFn(data[i]);\n if (!key) continue;\n const arr = index.get(key);\n if (arr) arr.push(data[i]);\n else index.set(key, [data[i]]);\n }\n return index;\n }\n\n // ─── Helper: apply filters + pagination ─────────────────────\n private paginate(\n records: PostOffice[],\n options?: QueryOptions,\n ): PaginatedResult<PostOffice> {\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n let filtered = records;\n\n if (options?.officeType) {\n filtered = filtered.filter((r) => r.officeType === options.officeType);\n }\n if (options?.deliveryOnly) {\n filtered = filtered.filter((r) => r.delivery);\n }\n\n const total = filtered.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n const data = filtered.slice(start, start + limit);\n\n return { data, total, page, limit, totalPages };\n }\n\n // ═══════════════════════════════════════════════════════════════\n // PUBLIC API\n // ═══════════════════════════════════════════════════════════════\n\n // ─── Pincode lookup (O(1)) ──────────────────────────────────\n\n /** Get all post offices for a pincode. Returns error for invalid/missing pincodes. */\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a complete summary for a pincode. */\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n if (!pincode || typeof pincode !== 'string') {\n return fail(ErrorCode.INVALID_INPUT, 'Pincode is required and must be a string.');\n }\n\n const trimmed = pincode.trim();\n if (!isValidPincode(trimmed)) {\n return fail(\n ErrorCode.INVALID_PINCODE,\n `Invalid pincode \"${trimmed}\". Indian pincodes must be exactly 6 digits starting with 1-9.`,\n );\n }\n\n const records = this.indexByPincode().get(trimmed);\n if (!records || records.length === 0) {\n return fail(ErrorCode.PINCODE_NOT_FOUND, `No data found for pincode \"${trimmed}\".`);\n }\n\n const first = records[0];\n return ok({\n pincode: trimmed,\n district: first.district,\n state: first.state,\n country: COUNTRY,\n areas: records.map((r) => ({\n pincode: r.pincode,\n area: r.area,\n latitude: r.latitude,\n longitude: r.longitude,\n })),\n deliveryAreas: records.filter((o) => o.delivery).length,\n hasCoordinates: records.some((o) => o.latitude !== null),\n });\n }\n\n // ─── State queries ──────────────────────────────────────────\n\n /** Get all post offices in a state. */\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const stateIndex = this.indexByState();\n const records = stateIndex.get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(stateIndex, state.trim(), 'state');\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a state — districts, pincode count, etc. */\n getStateSummary(state: string): ApiResponse<StateSummary> {\n if (!state || typeof state !== 'string' || !state.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'State name is required and must be a non-empty string.');\n }\n\n const stateIndex = this.indexByState();\n const records = stateIndex.get(state.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(stateIndex, state.trim(), 'state');\n return fail(ErrorCode.STATE_NOT_FOUND, `No data found for state \"${state.trim()}\".`, suggestions);\n }\n\n const districtSet = new Set<string>();\n const pincodeSet = new Set<string>();\n for (const r of records) {\n if (r.district) districtSet.add(r.district);\n pincodeSet.add(r.pincode);\n }\n\n return ok({\n state: records[0].state,\n country: COUNTRY,\n totalDistricts: districtSet.size,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n districts: Array.from(districtSet).sort(),\n });\n }\n\n /** Get all unique state names. */\n getAllStates(): string[] {\n const idx = this.indexByState();\n return Array.from(idx.keys())\n .filter((s) => s.length > 0)\n .map((s) => {\n const first = idx.get(s);\n return first ? first[0].state : s;\n })\n .sort();\n }\n\n // ─── District queries ───────────────────────────────────────\n\n /** Get all post offices in a district. */\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const districtIndex = this.indexByDistrict();\n const records = districtIndex.get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(districtIndex, district.trim(), 'district');\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n /** Get a summary for a district. */\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n if (!district || typeof district !== 'string' || !district.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'District name is required and must be a non-empty string.');\n }\n\n const districtIndex = this.indexByDistrict();\n const records = districtIndex.get(district.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(districtIndex, district.trim(), 'district');\n return fail(ErrorCode.DISTRICT_NOT_FOUND, `No data found for district \"${district.trim()}\".`, suggestions);\n }\n\n const pincodeSet = new Set<string>();\n for (const r of records) pincodeSet.add(r.pincode);\n\n return ok({\n district: records[0].district,\n state: records[0].state,\n country: COUNTRY,\n totalAreas: records.length,\n totalPincodes: pincodeSet.size,\n pincodes: Array.from(pincodeSet).sort(),\n });\n }\n\n /** Get all districts for a state. */\n getDistrictsByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) {\n if (r.district) set.add(r.district);\n }\n return Array.from(set).sort();\n }\n\n /** Get all unique district names. */\n getAllDistricts(): string[] {\n const idx = this.indexByDistrict();\n return Array.from(idx.keys())\n .filter((d) => d.length > 0)\n .map((d) => {\n const first = idx.get(d);\n return first ? first[0].district : d;\n })\n .sort();\n }\n\n // ─── Area name queries ───────────────────────────────────────\n\n /** Get post offices by exact area name (case-insensitive). */\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!name || typeof name !== 'string' || !name.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Area name is required and must be a non-empty string.');\n }\n\n const areaIndex = this.indexByArea();\n const records = areaIndex.get(name.trim().toLowerCase());\n if (!records || records.length === 0) {\n const suggestions = findSimilar(areaIndex, name.trim(), 'area');\n return fail(ErrorCode.NO_RESULTS, `No data found for area \"${name.trim()}\".`, suggestions);\n }\n\n return ok(this.paginate(records, options));\n }\n\n // ─── Pincode range queries ──────────────────────────────────\n\n /** Get all pincodes in a state. */\n getPincodesByState(state: string): string[] {\n const records = this.indexByState().get(state.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n /** Get all pincodes in a district. */\n getPincodesByDistrict(district: string): string[] {\n const records = this.indexByDistrict().get(district.toLowerCase()) ?? [];\n const set = new Set<string>();\n for (const r of records) set.add(r.pincode);\n return Array.from(set).sort();\n }\n\n // ─── Free-text search ───────────────────────────────────────\n\n /**\n * Search across pincode, area name, district, state.\n * Returns early once limit is reached — no wasted iteration.\n */\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n if (!query || typeof query !== 'string' || !query.trim()) {\n return fail(ErrorCode.INVALID_INPUT, 'Search query is required and must be a non-empty string.');\n }\n\n const data = loadData();\n const q = query.trim().toLowerCase();\n const limit = Math.max(1, options?.limit ?? 100);\n const page = Math.max(1, options?.page ?? 1);\n const officeType = options?.officeType;\n const deliveryOnly = options?.deliveryOnly;\n\n const matches: PostOffice[] = [];\n const maxScan = (page * limit) + limit; // fetch enough for pagination\n\n for (let i = 0; i < data.length && matches.length < maxScan; i++) {\n const r = data[i];\n if (officeType && r.officeType !== officeType) continue;\n if (deliveryOnly && !r.delivery) continue;\n\n if (\n r.pincode.includes(q) ||\n r.area.toLowerCase().includes(q) ||\n r.district.toLowerCase().includes(q) ||\n r.state.toLowerCase().includes(q) ||\n r.circle.toLowerCase().includes(q) ||\n r.region.toLowerCase().includes(q)\n ) {\n matches.push(r);\n }\n }\n\n if (matches.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No results found for \"${query.trim()}\".`);\n }\n\n const total = matches.length;\n const totalPages = Math.ceil(total / limit);\n const start = (page - 1) * limit;\n\n return ok({\n data: matches.slice(start, start + limit),\n total,\n page,\n limit,\n totalPages,\n });\n }\n\n // ─── Geo: nearby search ─────────────────────────────────────\n\n /**\n * Find post offices near a given coordinate.\n * Uses bounding-box pre-filter + Haversine for accuracy.\n * Returns sorted by distance ascending.\n */\n findNearby(\n lat: number,\n lng: number,\n radiusKm = 10,\n limit = 20,\n ): ApiResponse<NearbyResult[]> {\n if (typeof lat !== 'number' || typeof lng !== 'number' || !Number.isFinite(lat) || !Number.isFinite(lng)) {\n return fail(ErrorCode.INVALID_COORDINATES, 'Latitude and longitude must be valid numbers.');\n }\n if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {\n return fail(\n ErrorCode.INVALID_COORDINATES,\n `Invalid coordinates (${lat}, ${lng}). Latitude must be -90 to 90, longitude -180 to 180.`,\n );\n }\n const data = loadData();\n // Bounding-box pre-filter (1 degree ≈ 111 km)\n const dLat = radiusKm / 111;\n const dLng = radiusKm / (111 * Math.cos(toRad(lat)));\n const minLat = lat - dLat;\n const maxLat = lat + dLat;\n const minLng = lng - dLng;\n const maxLng = lng + dLng;\n\n const results: NearbyResult[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const r = data[i];\n if (r.latitude === null || r.longitude === null) continue;\n // Bounding box check (cheap)\n if (r.latitude < minLat || r.latitude > maxLat) continue;\n if (r.longitude < minLng || r.longitude > maxLng) continue;\n // Haversine (accurate)\n const d = haversine(lat, lng, r.latitude, r.longitude);\n if (d <= radiusKm) {\n results.push({ ...r, distanceKm: Math.round(d * 100) / 100 });\n }\n }\n\n results.sort((a, b) => a.distanceKm - b.distanceKm);\n const sliced = results.slice(0, limit);\n\n if (sliced.length === 0) {\n return fail(ErrorCode.NO_RESULTS, `No post offices found within ${radiusKm}km of (${lat}, ${lng}).`);\n }\n\n return ok(sliced);\n }\n\n // ─── Bulk / utility ─────────────────────────────────────────\n\n /** Total number of post office records loaded. */\n getTotalRecords(): number {\n return loadData().length;\n }\n\n /** Total number of unique pincodes. */\n getTotalPincodes(): number {\n return this.indexByPincode().size;\n }\n\n /** Clear all cached data and indexes — reloads fresh on next call. */\n clearCache(): void {\n this._byPincode = null;\n this._byState = null;\n this._byDistrict = null;\n this._byArea = null;\n clearDataCache();\n }\n}\n\n// ─── Haversine helpers ────────────────────────────────────────────\nfunction toRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\nfunction haversine(lat1: number, lon1: number, lat2: number, lon2: number): number {\n const R = 6371;\n const dLat = toRad(lat2 - lat1);\n const dLon = toRad(lon2 - lon1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;\n return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n}\n\n// ─── Singleton ────────────────────────────────────────────────────\nlet _instance: IndiaPincode | null = null;\n\n/** Returns a singleton IndiaPincode instance. */\nexport function getIndiaPincode(): IndiaPincode {\n if (!_instance) _instance = new IndiaPincode();\n return _instance;\n}\n","import { Injectable } from '@nestjs/common';\nimport { IndiaPincode } from './pincode-lookup';\nimport {\n PostOffice,\n QueryOptions,\n PaginatedResult,\n NearbyResult,\n PincodeSummary,\n DistrictSummary,\n StateSummary,\n ApiResponse,\n} from './types';\n\n/**\n * NestJS Injectable service — wraps IndiaPincode for DI.\n * Import PincodeModule in your AppModule, then inject this anywhere.\n */\n@Injectable()\nexport class PincodeService {\n private readonly engine: IndiaPincode;\n\n constructor() {\n this.engine = new IndiaPincode();\n }\n\n getByPincode(pincode: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByPincode(pincode, options);\n }\n\n getPincodeSummary(pincode: string): ApiResponse<PincodeSummary> {\n return this.engine.getPincodeSummary(pincode);\n }\n\n getByState(state: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByState(state, options);\n }\n\n getStateSummary(state: string): ApiResponse<StateSummary> {\n return this.engine.getStateSummary(state);\n }\n\n getAllStates(): string[] {\n return this.engine.getAllStates();\n }\n\n getByDistrict(district: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByDistrict(district, options);\n }\n\n getDistrictSummary(district: string): ApiResponse<DistrictSummary> {\n return this.engine.getDistrictSummary(district);\n }\n\n getDistrictsByState(state: string): string[] {\n return this.engine.getDistrictsByState(state);\n }\n\n getAllDistricts(): string[] {\n return this.engine.getAllDistricts();\n }\n\n getByArea(name: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.getByArea(name, options);\n }\n\n getPincodesByState(state: string): string[] {\n return this.engine.getPincodesByState(state);\n }\n\n getPincodesByDistrict(district: string): string[] {\n return this.engine.getPincodesByDistrict(district);\n }\n\n search(query: string, options?: QueryOptions): ApiResponse<PaginatedResult<PostOffice>> {\n return this.engine.search(query, options);\n }\n\n findNearby(lat: number, lng: number, radiusKm?: number, limit?: number): ApiResponse<NearbyResult[]> {\n return this.engine.findNearby(lat, lng, radiusKm, limit);\n }\n\n getTotalRecords(): number {\n return this.engine.getTotalRecords();\n }\n\n getTotalPincodes(): number {\n return this.engine.getTotalPincodes();\n }\n\n clearCache(): void {\n this.engine.clearCache();\n }\n}\n","import { Module, Global } from '@nestjs/common';\nimport { PincodeService } from './pincode.service';\n\n/**\n * NestJS Module for Indian Pincode data.\n *\n * Usage in your NestJS app:\n * ```ts\n * import { PincodeModule } from 'india-pincode';\n *\n * @Module({\n * imports: [PincodeModule],\n * })\n * export class AppModule {}\n * ```\n *\n * Then inject PincodeService in any controller/service:\n * ```ts\n * constructor(private readonly pincodeService: PincodeService) {}\n * ```\n */\n@Global()\n@Module({\n providers: [PincodeService],\n exports: [PincodeService],\n})\nexport class PincodeModule {}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "india-pincode",
3
- "version": "2.1.2",
3
+ "version": "2.2.0",
4
4
  "description": "Ultra-fast lookup for Indian pincode data — state, city, district, latitude, longitude. Works standalone or as a NestJS module.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -18,7 +18,8 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "tsup",
21
- "prepublishOnly": "npm run build",
21
+ "compress-data": "node -e \"const zlib=require('zlib'),fs=require('fs'),p='data/pincodes.json';if(fs.existsSync(p)){fs.writeFileSync(p+'.gz',zlib.gzipSync(fs.readFileSync(p)));fs.unlinkSync(p);console.log('Compressed '+p+' → '+p+'.gz');}else{console.log('No pincodes.json found, skipping compression.');}\"",
22
+ "prepublishOnly": "npm run compress-data && npm run build",
22
23
  "dev": "tsup --watch"
23
24
  },
24
25
  "keywords": [