powr-sdk-api
Version:
Shared API core library for PowrStack projects. Zero dependencies - works with Express, Next.js API routes, and other frameworks. All features are optional and install only what you need.
112 lines (110 loc) • 3.9 kB
JavaScript
;
const {
parsePhoneNumberFromString,
getCountries,
getCountryCallingCode
} = require('libphonenumber-js');
const DEFAULT_COUNTRY = 'IN';
const DEFAULT_COUNTRY_CODE = '91';
const CALLING_CODE_TO_COUNTRY = {
'91': 'IN',
'1': 'US',
'44': 'GB',
'971': 'AE',
'65': 'SG',
'61': 'AU'
};
function digitsOnly(value) {
return (value || '').replace(/\D/g, '');
}
function parsePhone(input, defaultCountry = DEFAULT_COUNTRY) {
var _parsed, _parsed2, _parsed3;
if (!input || typeof input !== 'string' || input.includes('@')) return null;
const trimmed = input.trim();
if (!trimmed) return null;
let parsed = parsePhoneNumberFromString(trimmed);
if (!((_parsed = parsed) !== null && _parsed !== void 0 && _parsed.isValid())) {
parsed = parsePhoneNumberFromString(trimmed, defaultCountry);
}
if (!((_parsed2 = parsed) !== null && _parsed2 !== void 0 && _parsed2.isValid()) && !trimmed.startsWith('+')) {
parsed = parsePhoneNumberFromString(`+${digitsOnly(trimmed)}`);
}
return (_parsed3 = parsed) !== null && _parsed3 !== void 0 && _parsed3.isValid() ? parsed : null;
}
function normalizePhone(input, defaultCountry = DEFAULT_COUNTRY) {
if (!input || typeof input !== 'string') return '';
if (input.includes('@')) return input.trim();
const parsed = parsePhone(input, defaultCountry);
return parsed ? parsed.format('E.164') : '';
}
/**
* Normalize a phone for DB storage. When the input has trailing junk
* (e.g. "7903658469 welcome"), extracts digits and parses those.
* Returns null when no valid phone can be derived — never returns raw input.
*/
function coercePhoneForStorage(input, defaultCountry = DEFAULT_COUNTRY) {
if (!input || typeof input !== 'string') return null;
if (input.includes('@')) return null;
const trimmed = input.trim();
if (!trimmed) return null;
const direct = normalizePhone(trimmed, defaultCountry);
if (direct) return direct;
const digits = digitsOnly(trimmed);
if (!digits) return null;
return normalizePhone(digits, defaultCountry) || null;
}
function isValidPhone(input, defaultCountry = DEFAULT_COUNTRY) {
if (!input || typeof input !== 'string' || input.includes('@')) return false;
return !!parsePhone(input, defaultCountry);
}
function getLocalPhoneNumber(input, defaultCountry = DEFAULT_COUNTRY) {
const parsed = parsePhone(input, defaultCountry);
return parsed ? parsed.nationalNumber : digitsOnly(input).slice(-15);
}
function legacyIndiaVariants(input) {
const digits = digitsOnly(input);
if (!digits) return [];
const variants = new Set();
if (digits.length === 10) {
variants.add(digits);
variants.add(`91${digits}`);
variants.add(`+91${digits}`);
variants.add(`0${digits}`);
}
if (digits.length === 12 && digits.startsWith('91')) {
const local = digits.slice(2);
variants.add(local);
variants.add(`+${digits}`);
variants.add(digits);
variants.add(`0${local}`);
}
return [...variants];
}
function getPhoneLookupVariants(input, defaultCountry = DEFAULT_COUNTRY) {
if (!input || typeof input !== 'string') return [];
if (input.includes('@')) return [input.trim()];
const variants = new Set([input.trim()]);
const parsed = parsePhone(input, defaultCountry);
if (parsed) {
const e164 = parsed.format('E.164');
variants.add(e164);
variants.add(e164.replace(/^\+/, ''));
variants.add(parsed.nationalNumber);
variants.add(`+${parsed.countryCallingCode}${parsed.nationalNumber}`);
variants.add(`${parsed.countryCallingCode}${parsed.nationalNumber}`);
}
legacyIndiaVariants(input).forEach(v => variants.add(v));
return [...variants].filter(Boolean);
}
module.exports = {
DEFAULT_COUNTRY,
DEFAULT_COUNTRY_CODE,
normalizePhone,
coercePhoneForStorage,
getLocalPhoneNumber,
isValidPhone,
getPhoneLookupVariants,
parsePhone,
getCountries,
getCountryCallingCode
};