@innovayse/geo-atlas 2.1.0 → 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.
package/README.md CHANGED
@@ -43,6 +43,41 @@ const armenia = CountriesAtlas.find('AM')
43
43
  // { iso2: 'AM', name: 'Armenia', translations: { hy: 'Հայաստան', ru: 'Армения' }, ... }
44
44
  ```
45
45
 
46
+ ### Lightweight entry — country list without the city dataset (`/lite`)
47
+
48
+ `CountriesAtlas` bundles the per-country state/city dataset (~171 MB across ~250
49
+ code-split chunks) because of its `getStates*` methods. If you only need the
50
+ **country list** (names, translations, phone codes, currencies, timezones) —
51
+ which is the common case on server-rendered pages — import from `/lite`. It loads
52
+ only the small `atlas.json` and never references the per-country dataset, so
53
+ bundlers don't have to process (or run out of memory on) the 171 MB:
54
+
55
+ ```ts
56
+ import CountriesData from '@innovayse/geo-atlas/lite'
57
+
58
+ const countries = CountriesData.getCountries()
59
+ const armenia = CountriesData.find('AM')
60
+ const dialCode = CountriesData.callingCode('AM')
61
+ ```
62
+
63
+ `CountriesData` exposes every country-level method — `getCountries`, `find`,
64
+ `findByIso3`, `getTimezones`, `timezone`, `getCallingCodes`, `callingCode`,
65
+ `getCurrencies`, `currency`. `CountriesAtlas` extends it and adds `getStates`,
66
+ `getStatesAsync` and `state`.
67
+
68
+ ### Cities on demand (`/cities`)
69
+
70
+ When you actually need cities (typically a client-side interaction), load them
71
+ through the dedicated `/cities` entry. Import it **dynamically** so the 171 MB
72
+ dataset stays out of any server bundle:
73
+
74
+ ```ts
75
+ // e.g. inside onMounted / a click handler — browser only
76
+ const { getStatesForCountry } = await import('@innovayse/geo-atlas/cities')
77
+ const states = await getStatesForCountry('AM')
78
+ const cities = states.flatMap(s => s.cities ?? [])
79
+ ```
80
+
46
81
  ### Get states/regions — sync (Node.js / CJS)
47
82
 
48
83
  ```ts
@@ -135,34 +170,36 @@ const am = CountriesAtlas.callingCode('AM')
135
170
  | France (FR) | `+33 X XX XX XX XX` |
136
171
  | UK (GB) | `+44 XXXX XXXXXX` |
137
172
 
138
- ## Nuxt 3 / Vite Setup
139
-
140
- To prevent esbuild from processing the large JSON data files (which causes OOM crashes), exclude the package from Vite's dependency optimization:
141
-
142
- ```ts
143
- // nuxt.config.ts
144
- export default defineNuxtConfig({
145
- vite: {
146
- optimizeDeps: {
147
- exclude: ['@innovayse/geo-atlas']
148
- }
149
- }
150
- })
151
- ```
173
+ ## Nuxt 3 / Vite / SSR Setup
152
174
 
153
- Then use `getStatesAsync` for browser-side city loading:
175
+ The per-country dataset (~171 MB) is only reachable through the city/state
176
+ methods. On an SSR build, importing the full `CountriesAtlas` drags that dataset
177
+ into the **server** bundle, where rollup can run out of memory (SIGKILL / OOM).
178
+ Avoid it by splitting your imports by need:
154
179
 
155
180
  ```ts
156
181
  // composables/useCountries.ts
157
- import { CountriesAtlas } from '@innovayse/geo-atlas'
158
182
 
159
- // Asyncworks in browser (ESM dynamic import)
160
- const cities = await CountriesAtlas.getStatesAsync('AM')
183
+ // Server-safe: country list only never bundles the 171 MB dataset.
184
+ import CountriesData from '@innovayse/geo-atlas/lite'
185
+
186
+ const countries = CountriesData.getCountries()
187
+ const armenia = CountriesData.find('AM')
161
188
 
162
- // Sync works in Node.js / SSR only
163
- const cities = CountriesAtlas.getStates('AM')
189
+ // Cities: load on demand, browser side, via a dynamic import so the dataset
190
+ // stays out of the server bundle entirely.
191
+ async function loadCities(iso2: string) {
192
+ const { getStatesForCountry } = await import('@innovayse/geo-atlas/cities')
193
+ const states = await getStatesForCountry(iso2)
194
+ return states.flatMap(s => s.cities ?? [])
195
+ }
164
196
  ```
165
197
 
198
+ Keep server-rendered paths (`useAsyncData`, SSR templates) on `/lite`, and reach
199
+ for `/cities` only where the user actually opens a city selector. With this split
200
+ you no longer need any `optimizeDeps.exclude` / `nitro.externals` workaround for
201
+ the package.
202
+
166
203
  ## Multilingual Country/City Names
167
204
 
168
205
  ```ts
@@ -0,0 +1,12 @@
1
+ import type { State } from './types/state.interface';
2
+ /**
3
+ * Load the states (with their cities) for a country by ISO2 code.
4
+ *
5
+ * Resolves the per-country data chunk via the code-split `countryLoaders`
6
+ * registry, so only the requested country's JSON is fetched at runtime.
7
+ *
8
+ * @param {string} iso2 - ISO2 code of the country (case-insensitive).
9
+ * @returns {Promise<State[]>} - Promise resolving to the country's states, or an empty array if unavailable.
10
+ */
11
+ export declare function getStatesForCountry(iso2: string): Promise<State[]>;
12
+ export type { State } from './types/state.interface';
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getStatesForCountry = void 0;
16
+ /**
17
+ * @packageDocumentation
18
+ * @module touchestate/geo-atlas/cities
19
+ *
20
+ * @description On-demand per-country state/city loader. This entry point
21
+ * references `countryLoaders`, which pulls in the per-country JSON dataset
22
+ * (~171 MB across ~250 code-split chunks). Import it only from client/browser
23
+ * paths where the data is actually needed — keep it out of server-rendered
24
+ * bundles by importing it dynamically (e.g. `await import('...cities')`).
25
+ *
26
+ * @license MIT
27
+ *
28
+ * @example
29
+ * const { getStatesForCountry } = await import('@touchestate/geo-atlas/cities');
30
+ * const states = await getStatesForCountry('AM');
31
+ */
32
+ const countryLoaders_1 = __importDefault(require("./helpers/countryLoaders"));
33
+ /**
34
+ * Load the states (with their cities) for a country by ISO2 code.
35
+ *
36
+ * Resolves the per-country data chunk via the code-split `countryLoaders`
37
+ * registry, so only the requested country's JSON is fetched at runtime.
38
+ *
39
+ * @param {string} iso2 - ISO2 code of the country (case-insensitive).
40
+ * @returns {Promise<State[]>} - Promise resolving to the country's states, or an empty array if unavailable.
41
+ */
42
+ function getStatesForCountry(iso2) {
43
+ var _a, _b;
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ const loader = countryLoaders_1.default[iso2.toLowerCase()];
46
+ if (!loader)
47
+ return [];
48
+ try {
49
+ const mod = yield loader();
50
+ const data = (_a = mod.default) !== null && _a !== void 0 ? _a : mod;
51
+ return (_b = data.states) !== null && _b !== void 0 ? _b : [];
52
+ }
53
+ catch (_c) {
54
+ return [];
55
+ }
56
+ });
57
+ }
58
+ exports.getStatesForCountry = getStatesForCountry;
@@ -1,38 +1,17 @@
1
- import { Country } from '../types/country.interface';
2
- import { Currency } from '../types/currency.type';
3
- import { PhoneCode } from '../types/phone-code.interface';
1
+ import { CountriesData } from './CountriesData';
4
2
  import { State } from '../types/state.interface';
5
- import { Timezone } from '../types/timezone.type';
6
3
  /**
7
- * Main helper class for querying countries, states, cities, timezones,
8
- * calling codes and currencies from the offline geo-atlas dataset.
4
+ * Full offline geo-atlas helper.
5
+ *
6
+ * Extends {@link CountriesData} (country list / phone / currency / timezone —
7
+ * all from the small bundled `atlas.json`) and adds per-country state & city
8
+ * access. The state/city methods pull data through `countryLoaders`, which
9
+ * references every per-country JSON file (~171 MB total). Because that import
10
+ * lives here and NOT in `CountriesData`, consumers that only need the country
11
+ * list can import `CountriesData` (or the `/lite` entry) and avoid bundling the
12
+ * per-country dataset entirely.
9
13
  */
10
- export declare class CountriesAtlas {
11
- /** Internal countries array loaded from the bundled atlas.json. */
12
- private countries;
13
- /** Initializes the atlas by loading the bundled country data. */
14
- constructor();
15
- /**
16
- * Retrieve all countries with specified properties, or all countries if no properties are specified.
17
- *
18
- * @param {string[]} properties - Array of properties to retrieve.
19
- * @return {Country[]} - Array of country objects with specified properties or all countries.
20
- */
21
- getCountries(properties?: string[]): Country[];
22
- /**
23
- * Find a country by its ISO2 code.
24
- *
25
- * @param {string} iso2 - ISO2 code of the country to find.
26
- * @return {Country | undefined} - Country object or undefined if not found.
27
- */
28
- find(iso2: string): Country | undefined;
29
- /**
30
- * Find a country by its ISO3 code.
31
- *
32
- * @param {string} iso3 - ISO3 code of the country to find.
33
- * @return {Country | undefined} - Country object or undefined if not found.
34
- */
35
- findByIso3(iso3: string): Country | undefined;
14
+ export declare class CountriesAtlas extends CountriesData {
36
15
  /**
37
16
  * Retrieve all states of a country by its ISO2 code.
38
17
  *
@@ -59,45 +38,6 @@ export declare class CountriesAtlas {
59
38
  * @returns {State | undefined} - State object or undefined if not found.
60
39
  */
61
40
  state(iso2: string, stateCode: string): State | undefined;
62
- /**
63
- * Retrieve all timezones of all available countries.
64
- *
65
- * @returns {Timezone[]} - Array of timezone objects.
66
- */
67
- getTimezones(): Timezone[];
68
- /**
69
- * Retrieve all timezones of a country by its ISO2 code.
70
- *
71
- * @param {string} iso2 - ISO2 code of the country.
72
- * @returns {Timezone[] | undefined} - Array of timezone objects or undefined if not found.
73
- */
74
- timezone(iso2: string): Timezone[] | undefined;
75
- /**
76
- * Retrieve all calling codes of all available countries.
77
- *
78
- * @returns {PhoneCode[]} - Array of phone code objects.
79
- */
80
- getCallingCodes(): PhoneCode[];
81
- /**
82
- * Retrieve calling codes of a country by its ISO2 code.
83
- *
84
- * @param {string} iso2 - ISO2 code of the country.
85
- * @returns {PhoneCode | undefined} - Phone code object or undefined if not found.
86
- */
87
- callingCode(iso2: string): PhoneCode | undefined;
88
- /**
89
- * Retrieve all currencies of all available countries.
90
- *
91
- * @returns {Currency[]} - Array of currency objects.
92
- */
93
- getCurrencies(): Currency[];
94
- /**
95
- * Retrieve currency of a country by its ISO2 code.
96
- *
97
- * @param {string} iso2 - ISO2 code of the country.
98
- * @returns {Currency | undefined} - Currency object or undefined if not found.
99
- */
100
- currency(iso2: string): Currency | undefined;
101
41
  }
102
42
  declare const _default: CountriesAtlas;
103
43
  export default _default;
@@ -13,66 +13,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.CountriesAtlas = void 0;
16
- const atlas_json_1 = __importDefault(require("../data/atlas.json"));
16
+ const CountriesData_1 = require("./CountriesData");
17
17
  const countryLoaders_1 = __importDefault(require("./countryLoaders"));
18
18
  /**
19
- * Main helper class for querying countries, states, cities, timezones,
20
- * calling codes and currencies from the offline geo-atlas dataset.
19
+ * Full offline geo-atlas helper.
20
+ *
21
+ * Extends {@link CountriesData} (country list / phone / currency / timezone —
22
+ * all from the small bundled `atlas.json`) and adds per-country state & city
23
+ * access. The state/city methods pull data through `countryLoaders`, which
24
+ * references every per-country JSON file (~171 MB total). Because that import
25
+ * lives here and NOT in `CountriesData`, consumers that only need the country
26
+ * list can import `CountriesData` (or the `/lite` entry) and avoid bundling the
27
+ * per-country dataset entirely.
21
28
  */
22
- class CountriesAtlas {
23
- /** Initializes the atlas by loading the bundled country data. */
24
- constructor() {
25
- this.countries = atlas_json_1.default;
26
- }
27
- /**
28
- * Retrieve all countries with specified properties, or all countries if no properties are specified.
29
- *
30
- * @param {string[]} properties - Array of properties to retrieve.
31
- * @return {Country[]} - Array of country objects with specified properties or all countries.
32
- */
33
- getCountries(properties) {
34
- if (properties) {
35
- return this.countries.map(country => {
36
- const newCountry = {};
37
- properties.forEach(property => {
38
- newCountry[property] = country[property];
39
- });
40
- return newCountry;
41
- });
42
- }
43
- return this.countries;
44
- }
45
- /**
46
- * Find a country by its ISO2 code.
47
- *
48
- * @param {string} iso2 - ISO2 code of the country to find.
49
- * @return {Country | undefined} - Country object or undefined if not found.
50
- */
51
- find(iso2) {
52
- return this.countries.find(country => { var _a; return ((_a = country.iso2) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === iso2.toUpperCase(); });
53
- }
54
- /**
55
- * Find a country by its ISO3 code.
56
- *
57
- * @param {string} iso3 - ISO3 code of the country to find.
58
- * @return {Country | undefined} - Country object or undefined if not found.
59
- */
60
- findByIso3(iso3) {
61
- return this.countries.find(country => { var _a; return ((_a = country.iso3) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === iso3.toUpperCase(); });
62
- }
63
- // getStates(iso2: string): Promise<State[]> | undefined {
64
- // const country = this.find(iso2)
65
- // if (country) {
66
- // return import(`../data/countries/${country.iso2?.toLowerCase()}.json`)
67
- // .then(statesData => {
68
- // return statesData.states
69
- // })
70
- // .catch(() => {
71
- // return undefined
72
- // })
73
- // }
74
- // return undefined
75
- // }
29
+ class CountriesAtlas extends CountriesData_1.CountriesData {
76
30
  /**
77
31
  * Retrieve all states of a country by its ISO2 code.
78
32
  *
@@ -122,18 +76,6 @@ class CountriesAtlas {
122
76
  }
123
77
  });
124
78
  }
125
- // state(iso2: string, stateCode: string): Promise<State | undefined> | undefined {
126
- // const country = this.find(iso2);
127
- // if (country) {
128
- // return import(`../data/countries/${country.iso2?.toLowerCase()}.json`)
129
- // .then((statesData: StateData) => {
130
- // const state = statesData.states.find((s: State) => s.state_code?.toUpperCase() === stateCode);
131
- // return state ? state : undefined;
132
- // })
133
- // .catch(() => undefined);
134
- // }
135
- // return undefined;
136
- // }
137
79
  /**
138
80
  * Find a state by its state code and country ISO2 code.
139
81
  *
@@ -156,98 +98,6 @@ class CountriesAtlas {
156
98
  }
157
99
  return undefined;
158
100
  }
159
- /**
160
- * Retrieve all timezones of all available countries.
161
- *
162
- * @returns {Timezone[]} - Array of timezone objects.
163
- */
164
- getTimezones() {
165
- const timezoneSet = new Set();
166
- this.countries.forEach(country => {
167
- var _a;
168
- (_a = country.timezones) === null || _a === void 0 ? void 0 : _a.forEach(timezone => {
169
- timezoneSet.add(timezone);
170
- });
171
- });
172
- return Array.from(timezoneSet);
173
- }
174
- /**
175
- * Retrieve all timezones of a country by its ISO2 code.
176
- *
177
- * @param {string} iso2 - ISO2 code of the country.
178
- * @returns {Timezone[] | undefined} - Array of timezone objects or undefined if not found.
179
- */
180
- timezone(iso2) {
181
- const country = this.find(iso2);
182
- if (country) {
183
- return country.timezones;
184
- }
185
- return undefined;
186
- }
187
- /**
188
- * Retrieve all calling codes of all available countries.
189
- *
190
- * @returns {PhoneCode[]} - Array of phone code objects.
191
- */
192
- getCallingCodes() {
193
- return this.getCountries(['name', 'phone', 'iso2', 'phone_format']).map(country => {
194
- var _a;
195
- return Object.assign(Object.assign({}, country), { phone_code: `+${country.phone}`, flag: `flag flag-${(_a = country.iso2) === null || _a === void 0 ? void 0 : _a.toLowerCase()}` });
196
- });
197
- }
198
- /**
199
- * Retrieve calling codes of a country by its ISO2 code.
200
- *
201
- * @param {string} iso2 - ISO2 code of the country.
202
- * @returns {PhoneCode | undefined} - Phone code object or undefined if not found.
203
- */
204
- callingCode(iso2) {
205
- var _a;
206
- const country = this.find(iso2);
207
- if (country) {
208
- return {
209
- name: country.name,
210
- phone: country.phone,
211
- iso2: country.iso2,
212
- phone_code: `+${country.phone}`,
213
- flag: `flag flag-${(_a = country.iso2) === null || _a === void 0 ? void 0 : _a.toLowerCase()}`,
214
- phone_format: country.phone_format
215
- };
216
- }
217
- return undefined;
218
- }
219
- /**
220
- * Retrieve all currencies of all available countries.
221
- *
222
- * @returns {Currency[]} - Array of currency objects.
223
- */
224
- getCurrencies() {
225
- return this.getCountries(['name', 'iso2', 'currency', 'currency_symbol', 'currency_name']).map(country => {
226
- var _a;
227
- return Object.assign(Object.assign({}, country), { flag: `flag flag-${(_a = country.iso2) === null || _a === void 0 ? void 0 : _a.toLowerCase()}` });
228
- });
229
- }
230
- /**
231
- * Retrieve currency of a country by its ISO2 code.
232
- *
233
- * @param {string} iso2 - ISO2 code of the country.
234
- * @returns {Currency | undefined} - Currency object or undefined if not found.
235
- */
236
- currency(iso2) {
237
- var _a;
238
- const country = this.find(iso2);
239
- if (country) {
240
- return {
241
- name: country.name,
242
- iso2: country.iso2,
243
- currency: country.currency,
244
- currency_symbol: country.currency_symbol,
245
- currency_name: country.currency_name,
246
- flag: `flag flag-${(_a = country.iso2) === null || _a === void 0 ? void 0 : _a.toLowerCase()}`
247
- };
248
- }
249
- return undefined;
250
- }
251
101
  }
252
102
  exports.CountriesAtlas = CountriesAtlas;
253
103
  exports.default = new CountriesAtlas();
@@ -0,0 +1,86 @@
1
+ import { Country } from '../types/country.interface';
2
+ import { Currency } from '../types/currency.type';
3
+ import { PhoneCode } from '../types/phone-code.interface';
4
+ import { Timezone } from '../types/timezone.type';
5
+ /**
6
+ * Lightweight country-list helper.
7
+ *
8
+ * Loads ONLY the bundled `atlas.json` (the country list plus per-country
9
+ * metadata: names, translations, phone, currency, timezones). It deliberately
10
+ * does NOT import the per-country state/city loaders (`countryLoaders`), so
11
+ * importing this class never drags the ~171 MB of per-country state/city JSON
12
+ * into a consumer's bundle.
13
+ *
14
+ * Use this when you only need countries, phone codes, currencies or timezones
15
+ * — e.g. on a server-rendered path. When you need states/cities, use
16
+ * `CountriesAtlas` (which extends this) or the `@touchestate/geo-atlas/cities`
17
+ * entry point.
18
+ */
19
+ export declare class CountriesData {
20
+ /** Internal countries array loaded from the bundled atlas.json. */
21
+ protected countries: Country[];
22
+ /** Initializes the atlas by loading the bundled country data. */
23
+ constructor();
24
+ /**
25
+ * Retrieve all countries with specified properties, or all countries if no properties are specified.
26
+ *
27
+ * @param {string[]} properties - Array of properties to retrieve.
28
+ * @return {Country[]} - Array of country objects with specified properties or all countries.
29
+ */
30
+ getCountries(properties?: string[]): Country[];
31
+ /**
32
+ * Find a country by its ISO2 code.
33
+ *
34
+ * @param {string} iso2 - ISO2 code of the country to find.
35
+ * @return {Country | undefined} - Country object or undefined if not found.
36
+ */
37
+ find(iso2: string): Country | undefined;
38
+ /**
39
+ * Find a country by its ISO3 code.
40
+ *
41
+ * @param {string} iso3 - ISO3 code of the country to find.
42
+ * @return {Country | undefined} - Country object or undefined if not found.
43
+ */
44
+ findByIso3(iso3: string): Country | undefined;
45
+ /**
46
+ * Retrieve all timezones of all available countries.
47
+ *
48
+ * @returns {Timezone[]} - Array of timezone objects.
49
+ */
50
+ getTimezones(): Timezone[];
51
+ /**
52
+ * Retrieve all timezones of a country by its ISO2 code.
53
+ *
54
+ * @param {string} iso2 - ISO2 code of the country.
55
+ * @returns {Timezone[] | undefined} - Array of timezone objects or undefined if not found.
56
+ */
57
+ timezone(iso2: string): Timezone[] | undefined;
58
+ /**
59
+ * Retrieve all calling codes of all available countries.
60
+ *
61
+ * @returns {PhoneCode[]} - Array of phone code objects.
62
+ */
63
+ getCallingCodes(): PhoneCode[];
64
+ /**
65
+ * Retrieve calling codes of a country by its ISO2 code.
66
+ *
67
+ * @param {string} iso2 - ISO2 code of the country.
68
+ * @returns {PhoneCode | undefined} - Phone code object or undefined if not found.
69
+ */
70
+ callingCode(iso2: string): PhoneCode | undefined;
71
+ /**
72
+ * Retrieve all currencies of all available countries.
73
+ *
74
+ * @returns {Currency[]} - Array of currency objects.
75
+ */
76
+ getCurrencies(): Currency[];
77
+ /**
78
+ * Retrieve currency of a country by its ISO2 code.
79
+ *
80
+ * @param {string} iso2 - ISO2 code of the country.
81
+ * @returns {Currency | undefined} - Currency object or undefined if not found.
82
+ */
83
+ currency(iso2: string): Currency | undefined;
84
+ }
85
+ declare const _default: CountriesData;
86
+ export default _default;