@flopay/shared 1.3.0 → 1.3.2
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/README.md +28 -0
- package/dist/index.cjs +119 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.mjs +105 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -175,3 +175,31 @@ throw validationError('Email is required', 'email');
|
|
|
175
175
|
| `getCurrencyByCountry(countryCode)` | Returns `CurrencyInfo` for a country code, falls back to USD |
|
|
176
176
|
| `isValidPublishableKey(key)` | Returns `true` if the key matches `pk_(test|live)_...` |
|
|
177
177
|
| `isValidSecretKey(key)` | Returns `true` if the key matches `sk_(test|live)_...` |
|
|
178
|
+
|
|
179
|
+
### Postal Code Helpers
|
|
180
|
+
|
|
181
|
+
Country-aware postcode format validation, a **faithful mirror of the billing API's own validator** — `is-valid-postal-code.validator.ts` (TeamFloPay/backend#895), same pinned [`validator`](https://www.npmjs.com/package/validator)`@13.15.35` `isPostalCode`, same country→ISO-2 normalization, same fail-open rules — so the SDK never blocks a postcode the server accepts nor opens its submit gate on one the server's `PATCH …/account` will reject with a 400. `@flopay/react`'s AVS block uses these to block a malformed postcode before the card is captured and to show the expected format inline.
|
|
182
|
+
|
|
183
|
+
| Export | Description |
|
|
184
|
+
|--------|-------------|
|
|
185
|
+
| `getPostalCodeLabel(countryCode)` | Country-appropriate field label (`'ZIP Code'`, `'Postcode'`, `'Eircode'`, …); defaults to `'Postal Code'` |
|
|
186
|
+
| `isPostalCodeSupported(country)` | `true` when `validator` has a postcode pattern for the country. Normalization matches the backend: a **2-letter code is passed straight through** (so `'UK'`, not a `validator` locale, → `false`); non-2-letter names resolve via the backend's `COUNTRY_ALIASES` (`'United Kingdom'` → `GB`). Unresolvable / no-postcode countries return `false` |
|
|
187
|
+
| `isValidPostalCode(country, postalCode)` | `true` when the (trimmed) postcode matches the country's format. **Fails open** in exactly the backend's three cases: blank/whitespace postcode, unresolvable country, or an unsupported `validator` locale. Callers distinguish "required" (empty) from "malformed" by checking emptiness + `isPostalCodeSupported` themselves — an empty value fails open here, as it does server-side |
|
|
188
|
+
| `getPostalCodeExample(country)` | The example postcode the backend embeds in its 400 message (US `12345 or 12345-6789`, GB `SW1A 1AA`, CA `A1A 1A1`, …), or `undefined` when there is none. Kept verbatim in sync with the backend's `POSTAL_CODE_EXAMPLES` so the SDK's inline hint and the server's rejection message never contradict |
|
|
189
|
+
| `getStateFromPostalCode(country, postalCode)` | Derives a US state / CA province code from a postcode for AVS enrichment; `null` for other countries or a malformed code |
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { isPostalCodeSupported, isValidPostalCode, getPostalCodeExample } from '@flopay/shared';
|
|
193
|
+
|
|
194
|
+
isPostalCodeSupported('US'); // true
|
|
195
|
+
isPostalCodeSupported('AE'); // false — UAE has no postcodes
|
|
196
|
+
isPostalCodeSupported('United Kingdom'); // true — full name → GB
|
|
197
|
+
isPostalCodeSupported('UK'); // false — 2-letter passthrough (not a validator locale)
|
|
198
|
+
isValidPostalCode('GB', 'SW1A 1AA'); // true
|
|
199
|
+
isValidPostalCode('GB', '12345'); // false — US shape in GB
|
|
200
|
+
isValidPostalCode('AE', ''); // true — fail open, never blocks
|
|
201
|
+
isValidPostalCode('US', ''); // true — blank fails open (enforce "required" separately)
|
|
202
|
+
getPostalCodeExample('CA'); // 'A1A 1A1'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
> **Runtime dependency.** Unlike the rest of `@flopay/shared`, these helpers pull in `validator` (imported via the `validator/lib/isPostalCode.js` submodule so bundlers only include the one check). It installs transitively when you depend on `@flopay/shared`.
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,7 +17,15 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
18
|
-
var
|
|
20
|
+
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
26
|
+
mod2
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
@@ -75,6 +85,7 @@ __export(index_exports, {
|
|
|
75
85
|
getCountryByCode: () => getCountryByCode,
|
|
76
86
|
getCurrencyByCountry: () => getCurrencyByCountry,
|
|
77
87
|
getFloPayEnvironment: () => getFloPayEnvironment,
|
|
88
|
+
getPostalCodeExample: () => getPostalCodeExample,
|
|
78
89
|
getPostalCodeLabel: () => getPostalCodeLabel,
|
|
79
90
|
getStateFromPostalCode: () => getStateFromPostalCode,
|
|
80
91
|
getStateLabel: () => getStateLabel,
|
|
@@ -83,7 +94,9 @@ __export(index_exports, {
|
|
|
83
94
|
hasVendoredStripeMethodLogo: () => hasVendoredStripeMethodLogo,
|
|
84
95
|
isAVSEnabled: () => isAVSEnabled,
|
|
85
96
|
isAVSFieldVisible: () => isAVSFieldVisible,
|
|
97
|
+
isPostalCodeSupported: () => isPostalCodeSupported,
|
|
86
98
|
isSetupIntentClientSecret: () => isSetupIntentClientSecret,
|
|
99
|
+
isValidPostalCode: () => isValidPostalCode,
|
|
87
100
|
isValidPublishableKey: () => isValidPublishableKey,
|
|
88
101
|
isValidSecretKey: () => isValidSecretKey,
|
|
89
102
|
needsStripeMethodExplicitConfirm: () => needsStripeMethodExplicitConfirm,
|
|
@@ -183,7 +196,7 @@ var PAYMENT_METHOD_LOGOS = {
|
|
|
183
196
|
};
|
|
184
197
|
|
|
185
198
|
// src/constants.ts
|
|
186
|
-
var SDK_VERSION = "1.3.
|
|
199
|
+
var SDK_VERSION = "1.3.2";
|
|
187
200
|
var FLO_SDK_VERSION_HEADER = "x-flo-sdk-version";
|
|
188
201
|
var BILLING_API_URL_STAGING = "https://api.stage.flopay.com";
|
|
189
202
|
var BILLING_API_URL_PRODUCTION = "https://api.flopay.com";
|
|
@@ -1960,6 +1973,107 @@ function getStateFromPostalCode(country, postalCode) {
|
|
|
1960
1973
|
}
|
|
1961
1974
|
}
|
|
1962
1975
|
|
|
1976
|
+
// src/postal-code-validation.ts
|
|
1977
|
+
var isPostalCodeModule = __toESM(require("validator/lib/isPostalCode.js"), 1);
|
|
1978
|
+
var mod = isPostalCodeModule;
|
|
1979
|
+
var isPostalCode = typeof mod.default === "function" ? mod.default : mod.default?.default;
|
|
1980
|
+
if (typeof isPostalCode !== "function") {
|
|
1981
|
+
throw new Error(
|
|
1982
|
+
"validator/lib/isPostalCode.js interop failed: unexpected module shape. This likely means the bundler's CJS/ESM interop changed."
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
var SUPPORTED_LOCALES = new Set(
|
|
1986
|
+
mod.locales.map((code) => code.toUpperCase())
|
|
1987
|
+
);
|
|
1988
|
+
var COUNTRY_ALIASES = {
|
|
1989
|
+
AUSTRALIA: "AU",
|
|
1990
|
+
BRAZIL: "BR",
|
|
1991
|
+
CANADA: "CA",
|
|
1992
|
+
CH: "CH",
|
|
1993
|
+
DENMARK: "DK",
|
|
1994
|
+
DE: "DE",
|
|
1995
|
+
DEUTSCHLAND: "DE",
|
|
1996
|
+
FRANCE: "FR",
|
|
1997
|
+
GB: "GB",
|
|
1998
|
+
GERMANY: "DE",
|
|
1999
|
+
GREATBRITAIN: "GB",
|
|
2000
|
+
GREAT_BRITAIN: "GB",
|
|
2001
|
+
INDIA: "IN",
|
|
2002
|
+
IRELAND: "IE",
|
|
2003
|
+
ITALY: "IT",
|
|
2004
|
+
JAPAN: "JP",
|
|
2005
|
+
MEXICO: "MX",
|
|
2006
|
+
NETHERLANDS: "NL",
|
|
2007
|
+
NEWZEALAND: "NZ",
|
|
2008
|
+
NORWAY: "NO",
|
|
2009
|
+
POLAND: "PL",
|
|
2010
|
+
PORTUGAL: "PT",
|
|
2011
|
+
SINGAPORE: "SG",
|
|
2012
|
+
SOUTHAFRICA: "ZA",
|
|
2013
|
+
SPAIN: "ES",
|
|
2014
|
+
SWEDEN: "SE",
|
|
2015
|
+
SWITZERLAND: "CH",
|
|
2016
|
+
UK: "GB",
|
|
2017
|
+
UNITEDKINGDOM: "GB",
|
|
2018
|
+
UNITEDSTATES: "US",
|
|
2019
|
+
US: "US",
|
|
2020
|
+
USA: "US",
|
|
2021
|
+
"UNITED STATES": "US",
|
|
2022
|
+
"UNITED KINGDOM": "GB",
|
|
2023
|
+
"GREAT BRITAIN": "GB",
|
|
2024
|
+
ENGLAND: "GB"
|
|
2025
|
+
};
|
|
2026
|
+
function normalizeCountryToIso2(country) {
|
|
2027
|
+
const upper = (country ?? "").trim().toUpperCase();
|
|
2028
|
+
if (!upper) return null;
|
|
2029
|
+
if (upper.length === 2) return upper;
|
|
2030
|
+
return COUNTRY_ALIASES[upper] ?? null;
|
|
2031
|
+
}
|
|
2032
|
+
var POSTAL_CODE_EXAMPLES = {
|
|
2033
|
+
AU: "2000",
|
|
2034
|
+
BR: "01000-000",
|
|
2035
|
+
CA: "A1A 1A1",
|
|
2036
|
+
CH: "8001",
|
|
2037
|
+
DE: "10115",
|
|
2038
|
+
DK: "1050",
|
|
2039
|
+
ES: "28001",
|
|
2040
|
+
FR: "75008",
|
|
2041
|
+
GB: "SW1A 1AA",
|
|
2042
|
+
IE: "D02 X285",
|
|
2043
|
+
IN: "110001",
|
|
2044
|
+
IT: "00118",
|
|
2045
|
+
JP: "100-0001",
|
|
2046
|
+
MX: "06500",
|
|
2047
|
+
NL: "1012 JS",
|
|
2048
|
+
NO: "0150",
|
|
2049
|
+
NZ: "6011",
|
|
2050
|
+
PL: "00-001",
|
|
2051
|
+
PT: "1100-148",
|
|
2052
|
+
SE: "111 22",
|
|
2053
|
+
SG: "018989",
|
|
2054
|
+
US: "12345 or 12345-6789",
|
|
2055
|
+
ZA: "8001"
|
|
2056
|
+
};
|
|
2057
|
+
function isPostalCodeSupported(country) {
|
|
2058
|
+
const iso2 = normalizeCountryToIso2(country);
|
|
2059
|
+
return iso2 !== null && SUPPORTED_LOCALES.has(iso2);
|
|
2060
|
+
}
|
|
2061
|
+
function isValidPostalCode(country, postalCode) {
|
|
2062
|
+
const trimmed = (postalCode ?? "").trim();
|
|
2063
|
+
if (!trimmed) return true;
|
|
2064
|
+
const iso2 = normalizeCountryToIso2(country);
|
|
2065
|
+
if (iso2 === null || !SUPPORTED_LOCALES.has(iso2)) return true;
|
|
2066
|
+
try {
|
|
2067
|
+
return isPostalCode(trimmed, iso2);
|
|
2068
|
+
} catch {
|
|
2069
|
+
return true;
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
function getPostalCodeExample(country) {
|
|
2073
|
+
const iso2 = normalizeCountryToIso2(country);
|
|
2074
|
+
return iso2 ? POSTAL_CODE_EXAMPLES[iso2] : void 0;
|
|
2075
|
+
}
|
|
2076
|
+
|
|
1963
2077
|
// src/checkout-payload.ts
|
|
1964
2078
|
function nonBlank(value) {
|
|
1965
2079
|
if (typeof value !== "string") return void 0;
|
|
@@ -2217,6 +2331,7 @@ function isSetupIntentClientSecret(clientSecret) {
|
|
|
2217
2331
|
getCountryByCode,
|
|
2218
2332
|
getCurrencyByCountry,
|
|
2219
2333
|
getFloPayEnvironment,
|
|
2334
|
+
getPostalCodeExample,
|
|
2220
2335
|
getPostalCodeLabel,
|
|
2221
2336
|
getStateFromPostalCode,
|
|
2222
2337
|
getStateLabel,
|
|
@@ -2225,7 +2340,9 @@ function isSetupIntentClientSecret(clientSecret) {
|
|
|
2225
2340
|
hasVendoredStripeMethodLogo,
|
|
2226
2341
|
isAVSEnabled,
|
|
2227
2342
|
isAVSFieldVisible,
|
|
2343
|
+
isPostalCodeSupported,
|
|
2228
2344
|
isSetupIntentClientSecret,
|
|
2345
|
+
isValidPostalCode,
|
|
2229
2346
|
isValidPublishableKey,
|
|
2230
2347
|
isValidSecretKey,
|
|
2231
2348
|
needsStripeMethodExplicitConfirm,
|