@webority-technologies/mobile-core 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/formatters/index.js +18 -0
- package/lib/commonjs/formatters/phone.js +83 -88
- package/lib/commonjs/index.js +18 -0
- package/lib/commonjs/storage/index.js +1 -1
- package/lib/module/formatters/index.js +1 -1
- package/lib/module/formatters/phone.js +65 -87
- package/lib/module/index.js +1 -1
- package/lib/module/storage/index.js +1 -1
- package/lib/typescript/commonjs/formatters/index.d.ts +2 -2
- package/lib/typescript/commonjs/formatters/phone.d.ts +30 -8
- package/lib/typescript/commonjs/index.d.ts +2 -2
- package/lib/typescript/commonjs/storage/index.d.ts +1 -1
- package/lib/typescript/module/formatters/index.d.ts +2 -2
- package/lib/typescript/module/formatters/phone.d.ts +30 -8
- package/lib/typescript/module/index.d.ts +2 -2
- package/lib/typescript/module/storage/index.d.ts +1 -1
- package/package.json +3 -2
|
@@ -69,12 +69,30 @@ Object.defineProperty(exports, "getInitials", {
|
|
|
69
69
|
return _initials.getInitials;
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
|
+
Object.defineProperty(exports, "isValidPhoneNumber", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _phone.isValidPhoneNumber;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
72
78
|
Object.defineProperty(exports, "normalizePhone", {
|
|
73
79
|
enumerable: true,
|
|
74
80
|
get: function () {
|
|
75
81
|
return _phone.normalizePhone;
|
|
76
82
|
}
|
|
77
83
|
});
|
|
84
|
+
Object.defineProperty(exports, "parsePhoneNumber", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _phone.parsePhoneNumber;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, "parsePhoneNumberFromString", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _phone.parsePhoneNumberFromString;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
78
96
|
var _currency = require("./currency.js");
|
|
79
97
|
var _date = require("./date.js");
|
|
80
98
|
var _initials = require("./initials.js");
|
|
@@ -5,7 +5,42 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.detectPhoneCountry = void 0;
|
|
7
7
|
exports.formatPhone = formatPhone;
|
|
8
|
+
Object.defineProperty(exports, "isValidPhoneNumber", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () {
|
|
11
|
+
return _max.isValidPhoneNumber;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
8
14
|
exports.normalizePhone = void 0;
|
|
15
|
+
Object.defineProperty(exports, "parsePhoneNumber", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () {
|
|
18
|
+
return _max.parsePhoneNumber;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
Object.defineProperty(exports, "parsePhoneNumberFromString", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return _max.parsePhoneNumberFromString;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
var _max = require("libphonenumber-js/max");
|
|
28
|
+
/**
|
|
29
|
+
* The bare 'libphonenumber-js' entry point actually resolves to the library's
|
|
30
|
+
* OWN slimmed-down min/ metadata internally, not its full data - './max' is
|
|
31
|
+
* the variant with complete per-country metadata. Since the reason this
|
|
32
|
+
* module exists is validation and formatting accuracy, the more accurate
|
|
33
|
+
* variant wins throughout this file, not just for validation.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Re-exported under our own name rather than importing CountryCode directly
|
|
38
|
+
* everywhere, so a future need to diverge (or re-narrow) has one place to do
|
|
39
|
+
* it. Every ISO 3166-1 alpha-2 code libphonenumber-js recognises - formatPhone
|
|
40
|
+
* and detectPhoneCountry below are genuinely correct for all of them, not a
|
|
41
|
+
* curated subset.
|
|
42
|
+
*/
|
|
43
|
+
|
|
9
44
|
/**
|
|
10
45
|
* Strip everything except digits and a leading `+` (preserved if present).
|
|
11
46
|
*/
|
|
@@ -18,82 +53,32 @@ const normalizePhone = input => {
|
|
|
18
53
|
const digits = trimmed.replace(/\D/g, '');
|
|
19
54
|
return hasPlus ? `+${digits}` : digits;
|
|
20
55
|
};
|
|
21
|
-
exports.normalizePhone = normalizePhone;
|
|
22
|
-
const groupIndianMobile = digits => {
|
|
23
|
-
// Indian mobile is 10 digits: format as `XXXXX XXXXX`.
|
|
24
|
-
if (digits.length !== 10) {
|
|
25
|
-
return digits;
|
|
26
|
-
}
|
|
27
|
-
return `${digits.slice(0, 5)} ${digits.slice(5)}`;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Longest calling code first so a 3-digit code is never shadowed by a shorter one.
|
|
31
|
-
const COUNTRY_RULES = [{
|
|
32
|
-
country: 'AE',
|
|
33
|
-
callingCode: '971',
|
|
34
|
-
nationalLength: 9,
|
|
35
|
-
group: n => `${n.slice(0, 2)} ${n.slice(2, 5)} ${n.slice(5)}`
|
|
36
|
-
}, {
|
|
37
|
-
country: 'IN',
|
|
38
|
-
callingCode: '91',
|
|
39
|
-
nationalLength: 10,
|
|
40
|
-
group: groupIndianMobile
|
|
41
|
-
}, {
|
|
42
|
-
country: 'GB',
|
|
43
|
-
callingCode: '44',
|
|
44
|
-
nationalLength: 10,
|
|
45
|
-
group: n => `${n.slice(0, 4)} ${n.slice(4, 7)} ${n.slice(7)}`
|
|
46
|
-
}, {
|
|
47
|
-
country: 'AU',
|
|
48
|
-
callingCode: '61',
|
|
49
|
-
nationalLength: 9,
|
|
50
|
-
group: n => `${n.slice(0, 3)} ${n.slice(3, 6)} ${n.slice(6)}`
|
|
51
|
-
}, {
|
|
52
|
-
country: 'SG',
|
|
53
|
-
callingCode: '65',
|
|
54
|
-
nationalLength: 8,
|
|
55
|
-
group: n => `${n.slice(0, 4)} ${n.slice(4)}`
|
|
56
|
-
}, {
|
|
57
|
-
country: 'US',
|
|
58
|
-
callingCode: '1',
|
|
59
|
-
nationalLength: 10,
|
|
60
|
-
group: n => `(${n.slice(0, 3)}) ${n.slice(3, 6)}-${n.slice(6)}`
|
|
61
|
-
},
|
|
62
|
-
// US and CA share a calling code and are indistinguishable from it alone;
|
|
63
|
-
// this row only serves an explicit `country: 'CA'` override, never detection
|
|
64
|
-
// (it sits after the US row, and findRuleByCallingCode returns the first match).
|
|
65
|
-
{
|
|
66
|
-
country: 'CA',
|
|
67
|
-
callingCode: '1',
|
|
68
|
-
nationalLength: 10,
|
|
69
|
-
group: n => `(${n.slice(0, 3)}) ${n.slice(3, 6)}-${n.slice(6)}`
|
|
70
|
-
}];
|
|
71
|
-
const findRuleByCallingCode = rest => COUNTRY_RULES.find(rule => rest.startsWith(rule.callingCode));
|
|
72
|
-
const findRuleByCountry = country => COUNTRY_RULES.find(rule => rule.country === country);
|
|
73
56
|
|
|
74
57
|
/**
|
|
75
58
|
* Detect the country of a phone number: from its own `+` country code when
|
|
76
59
|
* present, otherwise from `defaultCountryCode`. Returns null when neither
|
|
77
|
-
*
|
|
60
|
+
* parses to a recognised country.
|
|
78
61
|
*/
|
|
62
|
+
exports.normalizePhone = normalizePhone;
|
|
79
63
|
const detectPhoneCountry = (input, defaultCountryCode = '+91') => {
|
|
80
64
|
const normalized = normalizePhone(input);
|
|
81
65
|
if (!normalized) {
|
|
82
66
|
return null;
|
|
83
67
|
}
|
|
84
68
|
if (normalized.startsWith('+')) {
|
|
85
|
-
return
|
|
69
|
+
return (0, _max.parsePhoneNumberFromString)(normalized)?.country ?? null;
|
|
86
70
|
}
|
|
87
71
|
const normalizedDefault = normalizePhone(defaultCountryCode);
|
|
88
72
|
if (!normalizedDefault.startsWith('+')) {
|
|
89
73
|
return null;
|
|
90
74
|
}
|
|
91
|
-
return
|
|
75
|
+
return (0, _max.parsePhoneNumberFromString)(normalizedDefault + normalized)?.country ?? null;
|
|
92
76
|
};
|
|
93
77
|
exports.detectPhoneCountry = detectPhoneCountry;
|
|
94
78
|
const bestEffortGroup = rest => {
|
|
95
|
-
//
|
|
96
|
-
// the country code (first 1-3
|
|
79
|
+
// Not a parseable number at all (garbage input, or a real number that's an
|
|
80
|
+
// unsupported length for its country): split the country code (first 1-3
|
|
81
|
+
// digits) and group the rest in 4s, rather than returning nothing.
|
|
97
82
|
const ccLen = rest.length > 11 ? 3 : rest.length > 10 ? 2 : 1;
|
|
98
83
|
const cc = rest.slice(0, ccLen);
|
|
99
84
|
const number = rest.slice(ccLen);
|
|
@@ -102,13 +87,18 @@ const bestEffortGroup = rest => {
|
|
|
102
87
|
};
|
|
103
88
|
|
|
104
89
|
/**
|
|
105
|
-
* Format a phone number for human display
|
|
90
|
+
* Format a phone number for human display, via libphonenumber-js's own
|
|
91
|
+
* per-country formatting rather than a hand-rolled grouping table - correct
|
|
92
|
+
* for every country it recognises, not a curated subset.
|
|
106
93
|
*
|
|
107
|
-
* -
|
|
108
|
-
* -
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
94
|
+
* - A number that already carries a `+` country code formats for that country.
|
|
95
|
+
* - A bare national number formats for `options.country` when given, else for
|
|
96
|
+
* the country implied by `defaultCountryCode` (default `+91`).
|
|
97
|
+
* - `includeCountryCode` controls international vs national format; defaults
|
|
98
|
+
* to international whenever the country was detected rather than passed in
|
|
99
|
+
* explicitly as `options.country`, and to national when it was.
|
|
100
|
+
* - Input libphonenumber-js can't parse into a valid number for the resolved
|
|
101
|
+
* country falls back to a best-effort `+CC NNNN NNNN…` digit grouping.
|
|
112
102
|
*/
|
|
113
103
|
|
|
114
104
|
function formatPhone(input, arg) {
|
|
@@ -121,35 +111,40 @@ function formatPhone(input, arg) {
|
|
|
121
111
|
}
|
|
122
112
|
const options = typeof arg === 'string' ? {} : arg ?? {};
|
|
123
113
|
const defaultCountryCode = typeof arg === 'string' ? arg : options.defaultCountryCode ?? '+91';
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const body = activeRule.group(national);
|
|
133
|
-
return includeCc ? `+${activeRule.callingCode} ${body}` : body;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return bestEffortGroup(rest);
|
|
137
|
-
}
|
|
114
|
+
const hasOwnCountryCode = normalized.startsWith('+');
|
|
115
|
+
let parsed;
|
|
116
|
+
// What to best-effort group if parsing fails to produce a valid number.
|
|
117
|
+
// Defaults to the plain input; the defaultCountryCode branch below points
|
|
118
|
+
// it at the combined digits instead, so a bare number that turns out
|
|
119
|
+
// invalid for its detected country still shows that country's code rather
|
|
120
|
+
// than silently discarding it.
|
|
121
|
+
let fallbackRest = normalized;
|
|
138
122
|
if (options.country) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
123
|
+
// parsePhoneNumberFromString ignores this hint when normalized already
|
|
124
|
+
// carries its own +, so a real E.164 number is never overridden by a
|
|
125
|
+
// wrong or stale options.country.
|
|
126
|
+
parsed = (0, _max.parsePhoneNumberFromString)(normalized, options.country);
|
|
127
|
+
} else if (hasOwnCountryCode) {
|
|
128
|
+
parsed = (0, _max.parsePhoneNumberFromString)(normalized);
|
|
129
|
+
} else {
|
|
130
|
+
const normalizedDefault = normalizePhone(defaultCountryCode);
|
|
131
|
+
if (normalizedDefault.startsWith('+')) {
|
|
132
|
+
const combined = normalizedDefault + normalized;
|
|
133
|
+
parsed = (0, _max.parsePhoneNumberFromString)(combined);
|
|
134
|
+
fallbackRest = combined;
|
|
135
|
+
} else {
|
|
136
|
+
parsed = undefined;
|
|
144
137
|
}
|
|
145
|
-
return normalized.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
146
138
|
}
|
|
147
139
|
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
140
|
+
// International by default whenever the country came from the number
|
|
141
|
+
// itself (or from defaultCountryCode); national by default only when a
|
|
142
|
+
// bare number relied on an explicit options.country to resolve at all.
|
|
143
|
+
const includeCcDefault = hasOwnCountryCode || !options.country;
|
|
144
|
+
if (parsed?.isValid()) {
|
|
145
|
+
const includeCc = options.includeCountryCode ?? includeCcDefault;
|
|
146
|
+
return includeCc ? parsed.formatInternational() : parsed.formatNational();
|
|
151
147
|
}
|
|
152
|
-
|
|
153
|
-
return normalized.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
148
|
+
return fallbackRest.startsWith('+') ? bestEffortGroup(fallbackRest.slice(1)) : fallbackRest.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
154
149
|
}
|
|
155
150
|
//# sourceMappingURL=phone.js.map
|
package/lib/commonjs/index.js
CHANGED
|
@@ -321,6 +321,12 @@ Object.defineProperty(exports, "isUrl", {
|
|
|
321
321
|
return _index7.isUrl;
|
|
322
322
|
}
|
|
323
323
|
});
|
|
324
|
+
Object.defineProperty(exports, "isValidPhoneNumber", {
|
|
325
|
+
enumerable: true,
|
|
326
|
+
get: function () {
|
|
327
|
+
return _index3.isValidPhoneNumber;
|
|
328
|
+
}
|
|
329
|
+
});
|
|
324
330
|
Object.defineProperty(exports, "logCurl", {
|
|
325
331
|
enumerable: true,
|
|
326
332
|
get: function () {
|
|
@@ -351,6 +357,18 @@ Object.defineProperty(exports, "parseDeepLink", {
|
|
|
351
357
|
return _index2.parseDeepLink;
|
|
352
358
|
}
|
|
353
359
|
});
|
|
360
|
+
Object.defineProperty(exports, "parsePhoneNumber", {
|
|
361
|
+
enumerable: true,
|
|
362
|
+
get: function () {
|
|
363
|
+
return _index3.parsePhoneNumber;
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
Object.defineProperty(exports, "parsePhoneNumberFromString", {
|
|
367
|
+
enumerable: true,
|
|
368
|
+
get: function () {
|
|
369
|
+
return _index3.parsePhoneNumberFromString;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
354
372
|
Object.defineProperty(exports, "publicClient", {
|
|
355
373
|
enumerable: true,
|
|
356
374
|
get: function () {
|
|
@@ -196,7 +196,7 @@ const getAllKeys = async () => {
|
|
|
196
196
|
* All operations swallow errors (logging them) and return a falsy result
|
|
197
197
|
* so that storage problems never crash the app.
|
|
198
198
|
*
|
|
199
|
-
* Backed by
|
|
199
|
+
* Backed by `expo-sqlite/kv-store` by default;
|
|
200
200
|
* override with `setStorageImplementation()` for MMKV or custom adapters.
|
|
201
201
|
*/
|
|
202
202
|
const Storage = exports.Storage = {
|
|
@@ -4,5 +4,5 @@ export { formatCurrency } from "./currency.js";
|
|
|
4
4
|
export { formatDate, formatDateTime, formatRelativeTime, formatTime } from "./date.js";
|
|
5
5
|
export { getInitials } from "./initials.js";
|
|
6
6
|
export { formatCompactNumber, formatNumber, formatPercent } from "./number.js";
|
|
7
|
-
export { detectPhoneCountry, formatPhone, normalizePhone } from "./phone.js";
|
|
7
|
+
export { detectPhoneCountry, formatPhone, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from "./phone.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The bare 'libphonenumber-js' entry point actually resolves to the library's
|
|
5
|
+
* OWN slimmed-down min/ metadata internally, not its full data - './max' is
|
|
6
|
+
* the variant with complete per-country metadata. Since the reason this
|
|
7
|
+
* module exists is validation and formatting accuracy, the more accurate
|
|
8
|
+
* variant wins throughout this file, not just for validation.
|
|
9
|
+
*/
|
|
10
|
+
import { parsePhoneNumberFromString } from 'libphonenumber-js/max';
|
|
11
|
+
export { isValidPhoneNumber, parsePhoneNumber, parsePhoneNumberFromString } from 'libphonenumber-js/max';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Re-exported under our own name rather than importing CountryCode directly
|
|
15
|
+
* everywhere, so a future need to diverge (or re-narrow) has one place to do
|
|
16
|
+
* it. Every ISO 3166-1 alpha-2 code libphonenumber-js recognises - formatPhone
|
|
17
|
+
* and detectPhoneCountry below are genuinely correct for all of them, not a
|
|
18
|
+
* curated subset.
|
|
19
|
+
*/
|
|
20
|
+
|
|
3
21
|
/**
|
|
4
22
|
* Strip everything except digits and a leading `+` (preserved if present).
|
|
5
23
|
*/
|
|
@@ -12,62 +30,11 @@ export const normalizePhone = input => {
|
|
|
12
30
|
const digits = trimmed.replace(/\D/g, '');
|
|
13
31
|
return hasPlus ? `+${digits}` : digits;
|
|
14
32
|
};
|
|
15
|
-
const groupIndianMobile = digits => {
|
|
16
|
-
// Indian mobile is 10 digits: format as `XXXXX XXXXX`.
|
|
17
|
-
if (digits.length !== 10) {
|
|
18
|
-
return digits;
|
|
19
|
-
}
|
|
20
|
-
return `${digits.slice(0, 5)} ${digits.slice(5)}`;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// Longest calling code first so a 3-digit code is never shadowed by a shorter one.
|
|
24
|
-
const COUNTRY_RULES = [{
|
|
25
|
-
country: 'AE',
|
|
26
|
-
callingCode: '971',
|
|
27
|
-
nationalLength: 9,
|
|
28
|
-
group: n => `${n.slice(0, 2)} ${n.slice(2, 5)} ${n.slice(5)}`
|
|
29
|
-
}, {
|
|
30
|
-
country: 'IN',
|
|
31
|
-
callingCode: '91',
|
|
32
|
-
nationalLength: 10,
|
|
33
|
-
group: groupIndianMobile
|
|
34
|
-
}, {
|
|
35
|
-
country: 'GB',
|
|
36
|
-
callingCode: '44',
|
|
37
|
-
nationalLength: 10,
|
|
38
|
-
group: n => `${n.slice(0, 4)} ${n.slice(4, 7)} ${n.slice(7)}`
|
|
39
|
-
}, {
|
|
40
|
-
country: 'AU',
|
|
41
|
-
callingCode: '61',
|
|
42
|
-
nationalLength: 9,
|
|
43
|
-
group: n => `${n.slice(0, 3)} ${n.slice(3, 6)} ${n.slice(6)}`
|
|
44
|
-
}, {
|
|
45
|
-
country: 'SG',
|
|
46
|
-
callingCode: '65',
|
|
47
|
-
nationalLength: 8,
|
|
48
|
-
group: n => `${n.slice(0, 4)} ${n.slice(4)}`
|
|
49
|
-
}, {
|
|
50
|
-
country: 'US',
|
|
51
|
-
callingCode: '1',
|
|
52
|
-
nationalLength: 10,
|
|
53
|
-
group: n => `(${n.slice(0, 3)}) ${n.slice(3, 6)}-${n.slice(6)}`
|
|
54
|
-
},
|
|
55
|
-
// US and CA share a calling code and are indistinguishable from it alone;
|
|
56
|
-
// this row only serves an explicit `country: 'CA'` override, never detection
|
|
57
|
-
// (it sits after the US row, and findRuleByCallingCode returns the first match).
|
|
58
|
-
{
|
|
59
|
-
country: 'CA',
|
|
60
|
-
callingCode: '1',
|
|
61
|
-
nationalLength: 10,
|
|
62
|
-
group: n => `(${n.slice(0, 3)}) ${n.slice(3, 6)}-${n.slice(6)}`
|
|
63
|
-
}];
|
|
64
|
-
const findRuleByCallingCode = rest => COUNTRY_RULES.find(rule => rest.startsWith(rule.callingCode));
|
|
65
|
-
const findRuleByCountry = country => COUNTRY_RULES.find(rule => rule.country === country);
|
|
66
33
|
|
|
67
34
|
/**
|
|
68
35
|
* Detect the country of a phone number: from its own `+` country code when
|
|
69
36
|
* present, otherwise from `defaultCountryCode`. Returns null when neither
|
|
70
|
-
*
|
|
37
|
+
* parses to a recognised country.
|
|
71
38
|
*/
|
|
72
39
|
export const detectPhoneCountry = (input, defaultCountryCode = '+91') => {
|
|
73
40
|
const normalized = normalizePhone(input);
|
|
@@ -75,17 +42,18 @@ export const detectPhoneCountry = (input, defaultCountryCode = '+91') => {
|
|
|
75
42
|
return null;
|
|
76
43
|
}
|
|
77
44
|
if (normalized.startsWith('+')) {
|
|
78
|
-
return
|
|
45
|
+
return parsePhoneNumberFromString(normalized)?.country ?? null;
|
|
79
46
|
}
|
|
80
47
|
const normalizedDefault = normalizePhone(defaultCountryCode);
|
|
81
48
|
if (!normalizedDefault.startsWith('+')) {
|
|
82
49
|
return null;
|
|
83
50
|
}
|
|
84
|
-
return
|
|
51
|
+
return parsePhoneNumberFromString(normalizedDefault + normalized)?.country ?? null;
|
|
85
52
|
};
|
|
86
53
|
const bestEffortGroup = rest => {
|
|
87
|
-
//
|
|
88
|
-
// the country code (first 1-3
|
|
54
|
+
// Not a parseable number at all (garbage input, or a real number that's an
|
|
55
|
+
// unsupported length for its country): split the country code (first 1-3
|
|
56
|
+
// digits) and group the rest in 4s, rather than returning nothing.
|
|
89
57
|
const ccLen = rest.length > 11 ? 3 : rest.length > 10 ? 2 : 1;
|
|
90
58
|
const cc = rest.slice(0, ccLen);
|
|
91
59
|
const number = rest.slice(ccLen);
|
|
@@ -94,13 +62,18 @@ const bestEffortGroup = rest => {
|
|
|
94
62
|
};
|
|
95
63
|
|
|
96
64
|
/**
|
|
97
|
-
* Format a phone number for human display
|
|
65
|
+
* Format a phone number for human display, via libphonenumber-js's own
|
|
66
|
+
* per-country formatting rather than a hand-rolled grouping table - correct
|
|
67
|
+
* for every country it recognises, not a curated subset.
|
|
98
68
|
*
|
|
99
|
-
* -
|
|
100
|
-
* -
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
69
|
+
* - A number that already carries a `+` country code formats for that country.
|
|
70
|
+
* - A bare national number formats for `options.country` when given, else for
|
|
71
|
+
* the country implied by `defaultCountryCode` (default `+91`).
|
|
72
|
+
* - `includeCountryCode` controls international vs national format; defaults
|
|
73
|
+
* to international whenever the country was detected rather than passed in
|
|
74
|
+
* explicitly as `options.country`, and to national when it was.
|
|
75
|
+
* - Input libphonenumber-js can't parse into a valid number for the resolved
|
|
76
|
+
* country falls back to a best-effort `+CC NNNN NNNN…` digit grouping.
|
|
104
77
|
*/
|
|
105
78
|
|
|
106
79
|
export function formatPhone(input, arg) {
|
|
@@ -113,35 +86,40 @@ export function formatPhone(input, arg) {
|
|
|
113
86
|
}
|
|
114
87
|
const options = typeof arg === 'string' ? {} : arg ?? {};
|
|
115
88
|
const defaultCountryCode = typeof arg === 'string' ? arg : options.defaultCountryCode ?? '+91';
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const body = activeRule.group(national);
|
|
125
|
-
return includeCc ? `+${activeRule.callingCode} ${body}` : body;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return bestEffortGroup(rest);
|
|
129
|
-
}
|
|
89
|
+
const hasOwnCountryCode = normalized.startsWith('+');
|
|
90
|
+
let parsed;
|
|
91
|
+
// What to best-effort group if parsing fails to produce a valid number.
|
|
92
|
+
// Defaults to the plain input; the defaultCountryCode branch below points
|
|
93
|
+
// it at the combined digits instead, so a bare number that turns out
|
|
94
|
+
// invalid for its detected country still shows that country's code rather
|
|
95
|
+
// than silently discarding it.
|
|
96
|
+
let fallbackRest = normalized;
|
|
130
97
|
if (options.country) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
98
|
+
// parsePhoneNumberFromString ignores this hint when normalized already
|
|
99
|
+
// carries its own +, so a real E.164 number is never overridden by a
|
|
100
|
+
// wrong or stale options.country.
|
|
101
|
+
parsed = parsePhoneNumberFromString(normalized, options.country);
|
|
102
|
+
} else if (hasOwnCountryCode) {
|
|
103
|
+
parsed = parsePhoneNumberFromString(normalized);
|
|
104
|
+
} else {
|
|
105
|
+
const normalizedDefault = normalizePhone(defaultCountryCode);
|
|
106
|
+
if (normalizedDefault.startsWith('+')) {
|
|
107
|
+
const combined = normalizedDefault + normalized;
|
|
108
|
+
parsed = parsePhoneNumberFromString(combined);
|
|
109
|
+
fallbackRest = combined;
|
|
110
|
+
} else {
|
|
111
|
+
parsed = undefined;
|
|
136
112
|
}
|
|
137
|
-
return normalized.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
138
113
|
}
|
|
139
114
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
115
|
+
// International by default whenever the country came from the number
|
|
116
|
+
// itself (or from defaultCountryCode); national by default only when a
|
|
117
|
+
// bare number relied on an explicit options.country to resolve at all.
|
|
118
|
+
const includeCcDefault = hasOwnCountryCode || !options.country;
|
|
119
|
+
if (parsed?.isValid()) {
|
|
120
|
+
const includeCc = options.includeCountryCode ?? includeCcDefault;
|
|
121
|
+
return includeCc ? parsed.formatInternational() : parsed.formatNational();
|
|
143
122
|
}
|
|
144
|
-
|
|
145
|
-
return normalized.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
123
|
+
return fallbackRest.startsWith('+') ? bestEffortGroup(fallbackRest.slice(1)) : fallbackRest.replace(/(.{4})(?=.)/g, '$1 ').trim();
|
|
146
124
|
}
|
|
147
125
|
//# sourceMappingURL=phone.js.map
|
package/lib/module/index.js
CHANGED
|
@@ -29,7 +29,7 @@ export { getConfig, getConfigValue, resetConfig, setConfig } from "./config/inde
|
|
|
29
29
|
// Deep links
|
|
30
30
|
export { DeepLink, parseDeepLink, useDeepLink } from "./deepLink/index.js";
|
|
31
31
|
// Formatters
|
|
32
|
-
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, normalizePhone } from "./formatters/index.js";
|
|
32
|
+
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from "./formatters/index.js";
|
|
33
33
|
// Initialization
|
|
34
34
|
export { initWebority } from "./initSDK.js";
|
|
35
35
|
export { initUserAuth } from "./initUserAuth.js";
|
|
@@ -190,7 +190,7 @@ const getAllKeys = async () => {
|
|
|
190
190
|
* All operations swallow errors (logging them) and return a falsy result
|
|
191
191
|
* so that storage problems never crash the app.
|
|
192
192
|
*
|
|
193
|
-
* Backed by
|
|
193
|
+
* Backed by `expo-sqlite/kv-store` by default;
|
|
194
194
|
* override with `setStorageImplementation()` for MMKV or custom adapters.
|
|
195
195
|
*/
|
|
196
196
|
export const Storage = {
|
|
@@ -4,6 +4,6 @@ export type { DateInput, DateStyle, TimeStyle } from './date';
|
|
|
4
4
|
export { formatDate, formatDateTime, formatRelativeTime, formatTime } from './date';
|
|
5
5
|
export { getInitials } from './initials';
|
|
6
6
|
export { formatCompactNumber, formatNumber, formatPercent } from './number';
|
|
7
|
-
export type { FormatPhoneOptions, PhoneCountry } from './phone';
|
|
8
|
-
export { detectPhoneCountry, formatPhone, normalizePhone } from './phone';
|
|
7
|
+
export type { FormatPhoneOptions, PhoneCountry, PhoneNumber } from './phone';
|
|
8
|
+
export { detectPhoneCountry, formatPhone, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from './phone';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The bare 'libphonenumber-js' entry point actually resolves to the library's
|
|
3
|
+
* OWN slimmed-down min/ metadata internally, not its full data - './max' is
|
|
4
|
+
* the variant with complete per-country metadata. Since the reason this
|
|
5
|
+
* module exists is validation and formatting accuracy, the more accurate
|
|
6
|
+
* variant wins throughout this file, not just for validation.
|
|
7
|
+
*/
|
|
8
|
+
import { type CountryCode } from 'libphonenumber-js/max';
|
|
9
|
+
export type { PhoneNumber } from 'libphonenumber-js/max';
|
|
10
|
+
export { isValidPhoneNumber, parsePhoneNumber, parsePhoneNumberFromString } from 'libphonenumber-js/max';
|
|
11
|
+
/**
|
|
12
|
+
* Re-exported under our own name rather than importing CountryCode directly
|
|
13
|
+
* everywhere, so a future need to diverge (or re-narrow) has one place to do
|
|
14
|
+
* it. Every ISO 3166-1 alpha-2 code libphonenumber-js recognises - formatPhone
|
|
15
|
+
* and detectPhoneCountry below are genuinely correct for all of them, not a
|
|
16
|
+
* curated subset.
|
|
17
|
+
*/
|
|
18
|
+
export type PhoneCountry = CountryCode;
|
|
2
19
|
export interface FormatPhoneOptions {
|
|
3
20
|
defaultCountryCode?: string;
|
|
4
21
|
country?: PhoneCountry;
|
|
@@ -11,17 +28,22 @@ export declare const normalizePhone: (input: string) => string;
|
|
|
11
28
|
/**
|
|
12
29
|
* Detect the country of a phone number: from its own `+` country code when
|
|
13
30
|
* present, otherwise from `defaultCountryCode`. Returns null when neither
|
|
14
|
-
*
|
|
31
|
+
* parses to a recognised country.
|
|
15
32
|
*/
|
|
16
33
|
export declare const detectPhoneCountry: (input: string, defaultCountryCode?: string) => PhoneCountry | null;
|
|
17
34
|
/**
|
|
18
|
-
* Format a phone number for human display
|
|
35
|
+
* Format a phone number for human display, via libphonenumber-js's own
|
|
36
|
+
* per-country formatting rather than a hand-rolled grouping table - correct
|
|
37
|
+
* for every country it recognises, not a curated subset.
|
|
19
38
|
*
|
|
20
|
-
* -
|
|
21
|
-
* -
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
39
|
+
* - A number that already carries a `+` country code formats for that country.
|
|
40
|
+
* - A bare national number formats for `options.country` when given, else for
|
|
41
|
+
* the country implied by `defaultCountryCode` (default `+91`).
|
|
42
|
+
* - `includeCountryCode` controls international vs national format; defaults
|
|
43
|
+
* to international whenever the country was detected rather than passed in
|
|
44
|
+
* explicitly as `options.country`, and to national when it was.
|
|
45
|
+
* - Input libphonenumber-js can't parse into a valid number for the resolved
|
|
46
|
+
* country falls back to a best-effort `+CC NNNN NNNN…` digit grouping.
|
|
25
47
|
*/
|
|
26
48
|
export declare function formatPhone(input: string, defaultCountryCode?: string): string;
|
|
27
49
|
export declare function formatPhone(input: string, options?: FormatPhoneOptions): string;
|
|
@@ -28,8 +28,8 @@ export type { Config, Environment, LogLevel } from './config';
|
|
|
28
28
|
export { getConfig, getConfigValue, resetConfig, setConfig } from './config';
|
|
29
29
|
export type { DeepLinkConfig, DeepLinkRoute, ParsedLink } from './deepLink';
|
|
30
30
|
export { DeepLink, parseDeepLink, useDeepLink } from './deepLink';
|
|
31
|
-
export type { DateInput, DateStyle, FormatCurrencyOptions, FormatPhoneOptions, PhoneCountry, TimeStyle } from './formatters';
|
|
32
|
-
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, normalizePhone } from './formatters';
|
|
31
|
+
export type { DateInput, DateStyle, FormatCurrencyOptions, FormatPhoneOptions, PhoneCountry, PhoneNumber, TimeStyle } from './formatters';
|
|
32
|
+
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from './formatters';
|
|
33
33
|
export type { InitConfig } from './initSDK';
|
|
34
34
|
export { initWebority } from './initSDK';
|
|
35
35
|
export type { AuthActions } from './initUserAuth';
|
|
@@ -56,7 +56,7 @@ export interface StorageApi {
|
|
|
56
56
|
* All operations swallow errors (logging them) and return a falsy result
|
|
57
57
|
* so that storage problems never crash the app.
|
|
58
58
|
*
|
|
59
|
-
* Backed by
|
|
59
|
+
* Backed by `expo-sqlite/kv-store` by default;
|
|
60
60
|
* override with `setStorageImplementation()` for MMKV or custom adapters.
|
|
61
61
|
*/
|
|
62
62
|
export declare const Storage: StorageApi;
|
|
@@ -4,6 +4,6 @@ export type { DateInput, DateStyle, TimeStyle } from './date.js';
|
|
|
4
4
|
export { formatDate, formatDateTime, formatRelativeTime, formatTime } from './date.js';
|
|
5
5
|
export { getInitials } from './initials.js';
|
|
6
6
|
export { formatCompactNumber, formatNumber, formatPercent } from './number.js';
|
|
7
|
-
export type { FormatPhoneOptions, PhoneCountry } from './phone.js';
|
|
8
|
-
export { detectPhoneCountry, formatPhone, normalizePhone } from './phone.js';
|
|
7
|
+
export type { FormatPhoneOptions, PhoneCountry, PhoneNumber } from './phone.js';
|
|
8
|
+
export { detectPhoneCountry, formatPhone, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from './phone.js';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The bare 'libphonenumber-js' entry point actually resolves to the library's
|
|
3
|
+
* OWN slimmed-down min/ metadata internally, not its full data - './max' is
|
|
4
|
+
* the variant with complete per-country metadata. Since the reason this
|
|
5
|
+
* module exists is validation and formatting accuracy, the more accurate
|
|
6
|
+
* variant wins throughout this file, not just for validation.
|
|
7
|
+
*/
|
|
8
|
+
import { type CountryCode } from 'libphonenumber-js/max';
|
|
9
|
+
export type { PhoneNumber } from 'libphonenumber-js/max';
|
|
10
|
+
export { isValidPhoneNumber, parsePhoneNumber, parsePhoneNumberFromString } from 'libphonenumber-js/max';
|
|
11
|
+
/**
|
|
12
|
+
* Re-exported under our own name rather than importing CountryCode directly
|
|
13
|
+
* everywhere, so a future need to diverge (or re-narrow) has one place to do
|
|
14
|
+
* it. Every ISO 3166-1 alpha-2 code libphonenumber-js recognises - formatPhone
|
|
15
|
+
* and detectPhoneCountry below are genuinely correct for all of them, not a
|
|
16
|
+
* curated subset.
|
|
17
|
+
*/
|
|
18
|
+
export type PhoneCountry = CountryCode;
|
|
2
19
|
export interface FormatPhoneOptions {
|
|
3
20
|
defaultCountryCode?: string;
|
|
4
21
|
country?: PhoneCountry;
|
|
@@ -11,17 +28,22 @@ export declare const normalizePhone: (input: string) => string;
|
|
|
11
28
|
/**
|
|
12
29
|
* Detect the country of a phone number: from its own `+` country code when
|
|
13
30
|
* present, otherwise from `defaultCountryCode`. Returns null when neither
|
|
14
|
-
*
|
|
31
|
+
* parses to a recognised country.
|
|
15
32
|
*/
|
|
16
33
|
export declare const detectPhoneCountry: (input: string, defaultCountryCode?: string) => PhoneCountry | null;
|
|
17
34
|
/**
|
|
18
|
-
* Format a phone number for human display
|
|
35
|
+
* Format a phone number for human display, via libphonenumber-js's own
|
|
36
|
+
* per-country formatting rather than a hand-rolled grouping table - correct
|
|
37
|
+
* for every country it recognises, not a curated subset.
|
|
19
38
|
*
|
|
20
|
-
* -
|
|
21
|
-
* -
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
39
|
+
* - A number that already carries a `+` country code formats for that country.
|
|
40
|
+
* - A bare national number formats for `options.country` when given, else for
|
|
41
|
+
* the country implied by `defaultCountryCode` (default `+91`).
|
|
42
|
+
* - `includeCountryCode` controls international vs national format; defaults
|
|
43
|
+
* to international whenever the country was detected rather than passed in
|
|
44
|
+
* explicitly as `options.country`, and to national when it was.
|
|
45
|
+
* - Input libphonenumber-js can't parse into a valid number for the resolved
|
|
46
|
+
* country falls back to a best-effort `+CC NNNN NNNN…` digit grouping.
|
|
25
47
|
*/
|
|
26
48
|
export declare function formatPhone(input: string, defaultCountryCode?: string): string;
|
|
27
49
|
export declare function formatPhone(input: string, options?: FormatPhoneOptions): string;
|
|
@@ -28,8 +28,8 @@ export type { Config, Environment, LogLevel } from './config/index.js';
|
|
|
28
28
|
export { getConfig, getConfigValue, resetConfig, setConfig } from './config/index.js';
|
|
29
29
|
export type { DeepLinkConfig, DeepLinkRoute, ParsedLink } from './deepLink/index.js';
|
|
30
30
|
export { DeepLink, parseDeepLink, useDeepLink } from './deepLink/index.js';
|
|
31
|
-
export type { DateInput, DateStyle, FormatCurrencyOptions, FormatPhoneOptions, PhoneCountry, TimeStyle } from './formatters/index.js';
|
|
32
|
-
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, normalizePhone } from './formatters/index.js';
|
|
31
|
+
export type { DateInput, DateStyle, FormatCurrencyOptions, FormatPhoneOptions, PhoneCountry, PhoneNumber, TimeStyle } from './formatters/index.js';
|
|
32
|
+
export { detectPhoneCountry, formatCompactNumber, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatPhone, formatRelativeTime, formatTime, getInitials, isValidPhoneNumber, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString } from './formatters/index.js';
|
|
33
33
|
export type { InitConfig } from './initSDK.js';
|
|
34
34
|
export { initWebority } from './initSDK.js';
|
|
35
35
|
export type { AuthActions } from './initUserAuth.js';
|
|
@@ -56,7 +56,7 @@ export interface StorageApi {
|
|
|
56
56
|
* All operations swallow errors (logging them) and return a falsy result
|
|
57
57
|
* so that storage problems never crash the app.
|
|
58
58
|
*
|
|
59
|
-
* Backed by
|
|
59
|
+
* Backed by `expo-sqlite/kv-store` by default;
|
|
60
60
|
* override with `setStorageImplementation()` for MMKV or custom adapters.
|
|
61
61
|
*/
|
|
62
62
|
export declare const Storage: StorageApi;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority-technologies/mobile-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Platform layer for Webority React Native apps: HTTP clients, auth/token storage, config, logging, formatters, validators, network status, permissions, storage and version checks. No UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -133,7 +133,8 @@
|
|
|
133
133
|
"typecheck": "tsc --noEmit"
|
|
134
134
|
},
|
|
135
135
|
"dependencies": {
|
|
136
|
-
"axios": "^1.19.0"
|
|
136
|
+
"axios": "^1.19.0",
|
|
137
|
+
"libphonenumber-js": "^1.12.41"
|
|
137
138
|
},
|
|
138
139
|
"peerDependencies": {
|
|
139
140
|
"@op-engineering/op-sqlite": "*",
|