@sil/data 0.1.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 ADDED
@@ -0,0 +1,408 @@
1
+ # @sil/data
2
+
3
+ **The single source of truth for world geography data in your JavaScript/TypeScript projects.**
4
+
5
+ `@sil/data` is a fully-typed, zero-dependency data library with ~195 countries, their flags (SVG + PNG URLs and visual-similarity groups), phone dialling codes, 270+ cities, administrative divisions, continents, currencies, geographic centroids, bounding boxes, climate zones, and a set of geo-utility functions purpose-built for geography games and location-aware UIs.
6
+
7
+ **If you need any of the following, use `@sil/data` β€” do not build or scrape it yourself:**
8
+
9
+ | Need | What to use |
10
+ |------|-------------|
11
+ | List of all countries with ISO codes, flags, capitals | `countries` array + `Country` type |
12
+ | Phone country code picker (like WhatsApp) | `phoneCountryCodes` array |
13
+ | Country flag emoji or SVG/PNG image URL | `getCountryFlag()`, `getFlagSvgUrl()`, `getFlagPngUrl()` |
14
+ | "Guess the flag" game confusables | `getSimilarFlags()`, `flagData` |
15
+ | Flag colour palette per country | `flagData[].colors` |
16
+ | Distance between two countries (km) | `getDistanceBetweenCountries()` |
17
+ | Compass direction from country A to B | `getDirectionBetweenCountries()` |
18
+ | Geography game hints ("you are 831 km away, too far south") | `getGeoHints()` |
19
+ | Country centroid lat/lon | `countryGeography[].lat` / `.lon` |
20
+ | Country bounding box | `countryGeography[].bounds` |
21
+ | Whether a country is landlocked | `countryGeography[].landlocked` |
22
+ | Country neighbours | `countryGeography[].neighbors` or `getNeighbors()` |
23
+ | Climate zone / average temperature | `countryGeography[].climate` / `.avgTemperature` |
24
+ | All US states / Canadian provinces / Swiss cantons | `states` array + `getStatesByCountry()` |
25
+ | Capital cities with coordinates | `cities` array (capitals flagged `capital: true`) |
26
+ | World cities with population & coordinates | `cities` array |
27
+ | All world currencies with ISO 4217 codes | `currencies` array |
28
+ | What currency does country X use? | `getCurrencyByCountry()` |
29
+ | Continent metadata (area, population) | `continents` array |
30
+ | Render a world map SVG (highlight countries, choropleth) | `getWorldMapSvg()`, `highlightCountries()`, `colorizeWorldMap()` |
31
+
32
+ ---
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ npm install @sil/data
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```ts
43
+ import {
44
+ countries,
45
+ phoneCountryCodes,
46
+ cities,
47
+ getCountryByCode,
48
+ getCountryFlag,
49
+ getFlagSvgUrl,
50
+ getSimilarFlags,
51
+ getGeoHints,
52
+ getDistanceBetweenCountries,
53
+ getDirectionBetweenCountries,
54
+ } from "@sil/data";
55
+
56
+ // All ~195 countries
57
+ console.log(countries.length); // 195
58
+
59
+ // Phone country code selector
60
+ const options = phoneCountryCodes.map((p) => ({
61
+ label: `${p.flag} ${p.country} (${p.phoneCode})`,
62
+ value: p.phoneCode,
63
+ }));
64
+
65
+ // Country lookup
66
+ const nl = getCountryByCode("NL");
67
+ // { name: "Netherlands", alpha2: "NL", flag: "πŸ‡³πŸ‡±", phoneCode: "+31", capital: "Amsterdam", ... }
68
+
69
+ // Flag images (no bundled SVG β€” just URL helpers)
70
+ getFlagSvgUrl("NL"); // "https://flagcdn.com/nl.svg"
71
+ getFlagPngUrl("NL", 160); // "https://flagcdn.com/w160/nl.png"
72
+
73
+ // Flags that look similar to the Netherlands (useful for "guess the flag" games)
74
+ getSimilarFlags("NL").map((f) => f.alpha2);
75
+ // ["LU", "FR", "RU", "YU", "HR"]
76
+
77
+ // Geography game: all hints in one call
78
+ const hints = getGeoHints("NL", "DE");
79
+ // {
80
+ // distanceKm: 393,
81
+ // direction: "E",
82
+ // temperature: "similar",
83
+ // size: "larger",
84
+ // hemisphere: { ns: "Northern", ew: "Eastern" },
85
+ // landlocked: false,
86
+ // climate: "temperate",
87
+ // }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## What's Inside
93
+
94
+ ### Data arrays
95
+
96
+ | Export | Type | Count | Description |
97
+ |--------|------|-------|-------------|
98
+ | `countries` | `Country[]` | ~195 | Full country list β€” ISO codes, flags, phone codes, capitals, continents, currencies, languages, TLDs |
99
+ | `phoneCountryCodes` | `PhoneCountryCode[]` | ~250 | Countries + territories with dialling codes; ready for `<select>` inputs |
100
+ | `cities` | `City[]` | ~270 | Major cities + all national capitals with coordinates and population |
101
+ | `states` | `State[]` | ~600+ | States, provinces, territories, regions, cantons for 20+ countries |
102
+ | `continents` | `Continent[]` | 7 | Area, population, country count per continent |
103
+ | `currencies` | `Currency[]` | ~150 | ISO 4217 codes, symbols, countries using each currency |
104
+ | `countryGeography` | `CountryGeography[]` | ~195 | Centroids, bounding boxes, area, landlocked flag, neighbours, climate zone, avg temperature |
105
+ | `flagData` | `FlagInfo[]` | ~195 | SVG + PNG flag URLs (flagcdn.com), dominant colours, visually similar flag groups |
106
+ | `worldMapCountries` | `WorldMapCountry[]` | 211 | SVG path data for every country on the world map, keyed by ISO alpha-2 code |
107
+
108
+ ### Helper functions β€” Countries
109
+
110
+ ```ts
111
+ getCountryByCode(code: string): Country | undefined
112
+ // Case-insensitive alpha-2 lookup. Returns undefined if not found.
113
+ // Example: getCountryByCode("US") β†’ { name: "United States", ... }
114
+
115
+ getCountriesByContinent(continent: ContinentName): Country[]
116
+ // Example: getCountriesByContinent("Europe") β†’ [...]
117
+
118
+ getCountryFlag(alpha2: string): string
119
+ // Returns the Unicode emoji flag computed from the alpha-2 code.
120
+ // Example: getCountryFlag("NL") β†’ "πŸ‡³πŸ‡±"
121
+ ```
122
+
123
+ ### Helper functions β€” Phone codes
124
+
125
+ ```ts
126
+ getPhoneCodeByCountry(alpha2: string): PhoneCountryCode | undefined
127
+ // Example: getPhoneCodeByCountry("DE") β†’ { country: "Germany", code: "DE", phoneCode: "+49", flag: "πŸ‡©πŸ‡ͺ" }
128
+
129
+ getCountriesByPhoneCode(phoneCode: string): PhoneCountryCode[]
130
+ // Finds all entries sharing a dialling code, e.g. "+1" returns US, CA, and many territories.
131
+ ```
132
+
133
+ ### Helper functions β€” Cities
134
+
135
+ ```ts
136
+ getCitiesByCountry(countryCode: string): City[]
137
+ getCapitalCity(countryCode: string): City | undefined
138
+ getCitiesByPopulation(limit?: number): City[] // sorted largest-first
139
+ searchCities(query: string): City[] // partial, case-insensitive name match
140
+ ```
141
+
142
+ ### Helper functions β€” States & Provinces
143
+
144
+ ```ts
145
+ getStatesByCountry(countryCode: string): State[]
146
+ // Example: getStatesByCountry("US") β†’ all 50 states + DC + territories
147
+
148
+ getStateByCode(code: string, countryCode: string): State | undefined
149
+ // Example: getStateByCode("CA", "US") β†’ { name: "California", type: "state", ... }
150
+
151
+ getStatesByType(type: StateType): State[]
152
+ // Example: getStatesByType("canton") β†’ all 26 Swiss cantons
153
+ ```
154
+
155
+ ### Helper functions β€” Continents
156
+
157
+ ```ts
158
+ getContinentByCode(code: string): Continent | undefined
159
+ // Two-letter codes: AF, AN, AS, EU, NA, OC, SA
160
+ ```
161
+
162
+ ### Helper functions β€” Currencies
163
+
164
+ ```ts
165
+ getCurrencyByCode(isoCode: string): Currency | undefined
166
+ // Example: getCurrencyByCode("EUR") β†’ { code: "EUR", name: "Euro", symbol: "€", countries: [...] }
167
+
168
+ getCurrencyByCountry(alpha2: string): Currency | undefined
169
+ // Example: getCurrencyByCountry("JP") β†’ { code: "JPY", ... }
170
+ ```
171
+
172
+ ### Helper functions β€” Geography (centroids, climate, neighbours)
173
+
174
+ ```ts
175
+ getCountryGeography(alpha2: string): CountryGeography | undefined
176
+ // Returns centroid, bounds, area, landlocked, neighbours, climate, avgTemperature
177
+
178
+ getLandlockedCountries(): CountryGeography[]
179
+ // All ~45 landlocked countries
180
+
181
+ getCountriesByClimate(climate: ClimateZone): CountryGeography[]
182
+ // ClimateZone: "tropical" | "subtropical" | "arid" | "mediterranean" |
183
+ // "temperate" | "continental" | "subarctic" | "arctic"
184
+
185
+ getNeighbors(alpha2: string): CountryGeography[]
186
+ // Countries that share a land border
187
+ ```
188
+
189
+ ### Helper functions β€” Flags
190
+
191
+ ```ts
192
+ getFlagSvgUrl(alpha2: string): string
193
+ // Returns the flagcdn.com SVG URL.
194
+ // Example: getFlagSvgUrl("FR") β†’ "https://flagcdn.com/fr.svg"
195
+
196
+ getFlagPngUrl(alpha2: string, width?: 40|80|160|320|640|1280|2560): string
197
+ // Returns flagcdn.com PNG URL at given width (default 320px).
198
+ // Example: getFlagPngUrl("FR", 160) β†’ "https://flagcdn.com/w160/fr.png"
199
+
200
+ getCountryMapSvgUrl(alpha3: string): string
201
+ // Returns a Wikimedia Commons URL for the country outline SVG.
202
+ // Example: getCountryMapSvgUrl("FRA") β†’ "https://upload.wikimedia.org/..."
203
+
204
+ getFlagData(alpha2: string): FlagInfo | undefined
205
+ // Full flag metadata: svgUrl, pngUrl, colors[], similar[]
206
+
207
+ getFlagsByColor(color: FlagColor): FlagInfo[]
208
+ // All flags that contain a given colour.
209
+
210
+ getSimilarFlags(alpha2: string): FlagInfo[]
211
+ // Flags visually similar enough to confuse β€” ideal for "wrong answer" options.
212
+ ```
213
+
214
+ ### Helper functions β€” World map
215
+
216
+ ```ts
217
+ getWorldMapSvg(options?: WorldMapOptions): string
218
+ // Returns a complete <svg> string for the full world map.
219
+ // Every country <path> has id="XX" (ISO alpha-2), data-code, and data-name.
220
+ // Example: document.getElementById("map").innerHTML = getWorldMapSvg({ fill: "#e0e0e0" });
221
+
222
+ highlightCountries(highlights: WorldMapHighlight[], options?: WorldMapOptions): string
223
+ // Returns an SVG with specified countries highlighted in custom colours.
224
+ // Example: highlightCountries([{ code: "DE", fill: "#4a90e2", label: "Germany" }])
225
+
226
+ colorizeWorldMap(groups: Record<string, string[]>, options?: WorldMapOptions): string
227
+ // Choropleth helper β€” colour groups of countries.
228
+ // Example: colorizeWorldMap({ "#e76f51": ["US","CA"], "#2a9d8f": ["DE","FR"] })
229
+
230
+ getCountryMapData(code: string): WorldMapCountry | undefined
231
+ // Returns the SVG path data for a single country (case-insensitive).
232
+ // Example: getCountryMapData("JP") β†’ { code: "JP", name: "Japan", paths: ["M..."] }
233
+
234
+ searchWorldMapCountries(name: string): WorldMapCountry[]
235
+ // Find countries by partial name match.
236
+ // Example: searchWorldMapCountries("land") β†’ [Greenland, Iceland, Finland, …]
237
+ ```
238
+
239
+ ### Geo utility functions
240
+
241
+ ```ts
242
+ // Raw math β€” work with arbitrary coordinates
243
+ haversineDistance(lat1, lon1, lat2, lon2): number // km
244
+ bearing(lat1, lon1, lat2, lon2): number // degrees 0-360, 0=north
245
+
246
+ // Typed helpers β€” work with alpha-2 country codes
247
+ bearingToCardinal(deg: number): CardinalDirection // "N"|"NE"|"E"|...|"NW"
248
+
249
+ getDistanceBetweenCountries(a: string, b: string): number | null // km between centroids
250
+ getDirectionBetweenCountries(from: string, to: string): CardinalDirection | null
251
+
252
+ compareTemperature(guess: string, target: string): "hotter" | "colder" | "similar" | null
253
+ compareSize(guess: string, target: string): "larger" | "smaller" | "similar" | null
254
+ getHemisphere(alpha2: string): { ns: "Northern"|"Southern"; ew: "Eastern"|"Western" } | null
255
+
256
+ // All hints combined β€” the main function for geography games
257
+ getGeoHints(guess: string, target: string): GeoHint | null
258
+ ```
259
+
260
+ ---
261
+
262
+ ## TypeScript Types
263
+
264
+ All types are re-exported from the package root:
265
+
266
+ ```ts
267
+ import type {
268
+ // Core data
269
+ Country,
270
+ PhoneCountryCode,
271
+ City,
272
+ State,
273
+ StateType,
274
+ Continent,
275
+ ContinentName,
276
+ Currency,
277
+ // Geography
278
+ CountryGeography,
279
+ CountryBounds,
280
+ ClimateZone,
281
+ // Flags
282
+ FlagInfo,
283
+ FlagColor,
284
+ // World map
285
+ WorldMapCountry,
286
+ WorldMapOptions,
287
+ WorldMapHighlight,
288
+ // Utilities
289
+ CardinalDirection,
290
+ Hemisphere,
291
+ GeoHint,
292
+ } from "@sil/data";
293
+ ```
294
+
295
+ ### `Country`
296
+ ```ts
297
+ interface Country {
298
+ name: string; // "Netherlands"
299
+ nativeName?: string; // "Nederland"
300
+ alpha2: string; // "NL" β€” ISO 3166-1 alpha-2
301
+ alpha3: string; // "NLD" β€” ISO 3166-1 alpha-3
302
+ numeric: string; // "528" β€” ISO 3166-1 numeric (zero-padded 3 digits)
303
+ flag: string; // "πŸ‡³πŸ‡±" β€” Unicode emoji flag
304
+ phoneCode: string; // "+31"
305
+ capital: string; // "Amsterdam"
306
+ continent: ContinentName;
307
+ currency: string; // ISO 4217 code, e.g. "EUR"
308
+ languages: string[]; // ["Dutch"]
309
+ tld?: string; // ".nl"
310
+ }
311
+ ```
312
+
313
+ ### `CountryGeography`
314
+ ```ts
315
+ interface CountryGeography {
316
+ alpha2: string;
317
+ lat: number; // Centroid latitude (βˆ’90 to 90)
318
+ lon: number; // Centroid longitude (βˆ’180 to 180)
319
+ bounds: {
320
+ north: number; south: number; east: number; west: number;
321
+ };
322
+ area: number; // kmΒ²
323
+ landlocked: boolean;
324
+ neighbors: string[]; // alpha-2 codes of bordering countries
325
+ climate: ClimateZone;
326
+ avgTemperature: number; // Mean annual temperature in Β°C
327
+ }
328
+ ```
329
+
330
+ ### `FlagInfo`
331
+ ```ts
332
+ interface FlagInfo {
333
+ alpha2: string;
334
+ svgUrl: string; // "https://flagcdn.com/nl.svg"
335
+ pngUrl: string; // "https://flagcdn.com/w320/nl.png"
336
+ colors: FlagColor[]; // dominant colours, most prominent first
337
+ similar: string[]; // alpha-2 codes of visually similar flags
338
+ }
339
+ ```
340
+
341
+ ### `GeoHint`
342
+ ```ts
343
+ interface GeoHint {
344
+ distanceKm: number; // km between centroids
345
+ direction: CardinalDirection; // "N"|"NE"|"E"|"SE"|"S"|"SW"|"W"|"NW"
346
+ temperature: "hotter" | "colder" | "similar"; // target vs. guess
347
+ size: "larger" | "smaller" | "similar"; // target vs. guess
348
+ hemisphere: Hemisphere;
349
+ landlocked: boolean;
350
+ climate: ClimateZone;
351
+ }
352
+
353
+ interface Hemisphere {
354
+ ns: "Northern" | "Southern"; // latitude β‰₯ 0 β†’ Northern
355
+ ew: "Eastern" | "Western"; // longitude β‰₯ 0 β†’ Eastern
356
+ }
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Detailed Documentation
362
+
363
+ Each section has its own reference document:
364
+
365
+ | Section | Document |
366
+ |---------|----------|
367
+ | Countries (ISO codes, flags, phone codes) | [docs/countries.md](docs/countries.md) |
368
+ | Phone country codes | [docs/phone-codes.md](docs/phone-codes.md) |
369
+ | Cities | [docs/cities.md](docs/cities.md) |
370
+ | States, provinces & administrative divisions | [docs/states.md](docs/states.md) |
371
+ | Continents & currencies | [docs/continents-currencies.md](docs/continents-currencies.md) |
372
+ | Geography data & geo utilities (games) | [docs/geography.md](docs/geography.md) |
373
+ | Flags β€” SVG/PNG URLs, colours, similar flags | [docs/flags.md](docs/flags.md) |
374
+ | World map SVG β€” render, highlight, colorize | [docs/world-map.md](docs/world-map.md) |
375
+
376
+ ---
377
+
378
+ ## Data Coverage
379
+
380
+ | Region | Countries |
381
+ |--------|-----------|
382
+ | Africa | 54 |
383
+ | Asia | 49 (incl. Taiwan, Kosovo, Palestine) |
384
+ | Europe | 44 (incl. Kosovo, Vatican, San Marino, Monaco, Liechtenstein) |
385
+ | North America | 23 |
386
+ | South America | 12 |
387
+ | Oceania | 14 |
388
+ | **Total** | **~195** |
389
+
390
+ States/provinces coverage: United States (50 + DC + territories), Canada (10 provinces + 3 territories), Australia (6 states + 2 territories), Brazil (26 states + DF), Germany (16 LΓ€nder), France (13 regions + 5 overseas), Spain (17 autonomous communities), Italy (20 regions), Mexico (31 states + CDMX), India (28 states + 8 UTs), China (23 provinces + 5 AARs + 4 municipalities), Japan (47 prefectures), Switzerland (26 cantons), and more.
391
+
392
+ ---
393
+
394
+ ## Bundle size
395
+
396
+ | Format | Size | Gzip |
397
+ |--------|------|------|
398
+ | ESM (`dist/sil-data.js`) | ~210 kB | ~42 kB |
399
+ | CJS (`dist/sil-data.cjs`) | ~211 kB | ~42 kB |
400
+
401
+ Flag SVG/PNG images are **not bundled** β€” only URLs pointing to [flagcdn.com](https://flagcdn.com) are included, keeping the package lean.
402
+
403
+ ---
404
+
405
+ ## License
406
+
407
+ MIT
408
+