digipinjs
Version:
A comprehensive TypeScript library for encoding and decoding Indian geographic coordinates into DIGIPIN format (Indian Postal Digital PIN system). Features CLI tools, caching, batch processing, and Express middleware for seamless integration.
163 lines (162 loc) • 6.52 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const core_1 = require("./core");
const chalk_1 = __importDefault(require("chalk"));
// Helper function to convert decimal degrees to DMS
function toDMS(decimal, isLatitude) {
const absolute = Math.abs(decimal);
const degrees = Math.floor(absolute);
const minutesNotTruncated = (absolute - degrees) * 60;
const minutes = Math.floor(minutesNotTruncated);
const seconds = ((minutesNotTruncated - minutes) * 60).toFixed(2);
const direction = isLatitude
? (decimal >= 0 ? 'N' : 'S')
: (decimal >= 0 ? 'E' : 'W');
return `${degrees}° ${minutes}' ${seconds}" ${direction}`;
}
// Helper function to format coordinates
function formatCoords(coords, format = 'degrees') {
if (format === 'dms') {
return `Latitude: ${toDMS(coords.latitude, true)}\nLongitude: ${toDMS(coords.longitude, false)}`;
}
return `Latitude: ${chalk_1.default.cyan(coords.latitude.toFixed(6))}°\nLongitude: ${chalk_1.default.cyan(coords.longitude.toFixed(6))}°`;
}
// Helper function to handle errors
function handleError(error) {
console.error(chalk_1.default.red('\nError:'), error.message);
if (error.message === 'Latitude out of range') {
console.error(chalk_1.default.yellow('Valid latitude range is 2.5° to 38.5°'));
}
else if (error.message === 'Longitude out of range') {
console.error(chalk_1.default.yellow('Valid longitude range is 63.5° to 99.5°'));
}
else if (error.message === 'Invalid DIGIPIN') {
console.error(chalk_1.default.yellow('DIGIPIN must be 10 characters long (excluding hyphens)'));
console.error(chalk_1.default.yellow('Format: XXX-XXX-XXXX where X is one of: F,C,9,8,J,3,2,7,K,4,5,6,L,M,P,T'));
}
else if (error.message === 'Invalid character') {
console.error(chalk_1.default.yellow('DIGIPIN can only contain these characters: F,C,9,8,J,3,2,7,K,4,5,6,L,M,P,T'));
}
process.exit(1);
}
// Helper function to validate coordinates
function validateCoordinates(lat, lng) {
if (isNaN(lat) || isNaN(lng)) {
throw new Error('Invalid coordinates: must be numbers');
}
if (lat < 2.5 || lat > 38.5) {
throw new Error('Latitude out of range');
}
if (lng < 63.5 || lng > 99.5) {
throw new Error('Longitude out of range');
}
}
const encodeCommand = {
command: 'encode',
describe: 'Convert latitude/longitude to DIGIPIN',
builder: (yargs) => {
return yargs
.option('lat', {
type: 'number',
demandOption: true,
describe: 'Latitude (2.5° to 38.5°)'
})
.option('lng', {
type: 'number',
demandOption: true,
describe: 'Longitude (63.5° to 99.5°)'
})
.option('verbose', {
type: 'boolean',
default: false,
describe: 'Show detailed information'
})
.option('format', {
type: 'string',
choices: ['degrees', 'dms'],
default: 'degrees',
describe: 'Coordinate format for verbose output'
});
},
handler: (argv) => {
try {
validateCoordinates(argv.lat, argv.lng);
const pin = (0, core_1.getDigiPin)(argv.lat, argv.lng);
if (argv.verbose) {
console.log(chalk_1.default.green('\nInput Coordinates:'));
console.log(formatCoords({ latitude: argv.lat, longitude: argv.lng }, argv.format));
console.log(chalk_1.default.green('\nGenerated DIGIPIN:'), chalk_1.default.cyan(pin));
console.log(chalk_1.default.green('\nDIGIPIN Format:'), 'XXX-XXX-XXXX');
console.log(chalk_1.default.green('Valid Characters:'), 'F,C,9,8,J,3,2,7,K,4,5,6,L,M,P,T');
}
else {
console.log(chalk_1.default.cyan('\nDIGIPIN:'), pin);
}
}
catch (error) {
handleError(error);
}
}
};
const decodeCommand = {
command: 'decode',
describe: 'Convert DIGIPIN to latitude/longitude',
builder: (yargs) => {
return yargs
.option('pin', {
type: 'string',
demandOption: true,
describe: 'DIGIPIN to decode (format: XXX-XXX-XXXX)'
})
.option('verbose', {
type: 'boolean',
default: false,
describe: 'Show detailed information'
})
.option('format', {
type: 'string',
choices: ['degrees', 'dms'],
default: 'degrees',
describe: 'Coordinate format for output'
});
},
handler: (argv) => {
try {
if (argv.verbose) {
console.log(chalk_1.default.green('\nInput DIGIPIN:'), chalk_1.default.cyan(argv.pin));
console.log(chalk_1.default.green('DIGIPIN Format:'), 'XXX-XXX-XXXX');
console.log(chalk_1.default.green('Valid Characters:'), 'F,C,9,8,J,3,2,7,K,4,5,6,L,M,P,T');
}
const coords = (0, core_1.getLatLngFromDigiPin)(argv.pin);
if (argv.verbose) {
console.log(chalk_1.default.green('\nDecoded Coordinates:'));
console.log(formatCoords(coords, argv.format));
console.log(chalk_1.default.green('\nCoordinate Bounds:'));
console.log(chalk_1.default.yellow('Latitude:'), '2.5° to 38.5°');
console.log(chalk_1.default.yellow('Longitude:'), '63.5° to 99.5°');
}
else {
console.log(chalk_1.default.green('\nCoordinates:'));
console.log(formatCoords(coords, argv.format));
}
}
catch (error) {
handleError(error);
}
}
};
// Main CLI implementation
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
.command(encodeCommand)
.command(decodeCommand)
.demandCommand(1, chalk_1.default.yellow('Please specify a command: encode or decode'))
.help()
.version()
.epilog(chalk_1.default.gray('For more information, visit: https://github.com/your-org/digipin-wrapper'))
.argv;