@ruhlabs/atolls 0.0.0-stage → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ruh Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,42 @@
1
- # Temporary Holding Version
1
+ # @ruhlabs/atolls
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Maldives' 20 administrative atolls and 5 cities as typed data, with lookup and address helpers. No dependencies, works in Node and the browser.
4
+
5
+ ```bash
6
+ npm install @ruhlabs/atolls
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```ts
12
+ import { ATOLLS, CITIES, getAtoll, parseIslandAddress, formatIslandAddress } from '@ruhlabs/atolls';
13
+
14
+ getAtoll('Haa Alif');
15
+ // {
16
+ // code: "HA", codeThaana: "ހއ", codeName: "Haa Alifu",
17
+ // officialName: "Thiladhunmathi Uthuruburi", latinLetter: "A",
18
+ // iso: "MV-07", capital: "Dhidhdhoo", aliases: ["Haa Alif"]
19
+ // }
20
+
21
+ // Any name or code works: "HA", "ha", "Haa Alif Atoll", "ހއ", "MV-07", "Thiladhunmathi Uthuruburi"
22
+ getAtoll('Gaaf Dhaal')?.capital; // "Thinadhoo"
23
+
24
+ parseIslandAddress('B. Eydhafushi'); // { atoll: { code: "B", ... }, island: "Eydhafushi" }
25
+ parseIslandAddress('ބ. އޭދަފުށި'); // works with Thaana codes too
26
+
27
+ formatIslandAddress('Baa', 'Eydhafushi'); // "B. Eydhafushi"
28
+ formatIslandAddress('B', 'އޭދަފުށި', { thaana: true }); // "ބ. އޭދަފުށި"
29
+
30
+ ATOLLS.map((a) => a.code); // ["HA", "HDh", "Sh", ..., "Gn", "S"], north to south
31
+ CITIES; // Malé, Addu, Fuvahmulah, Kulhudhuffushi, Thinadhoo
32
+ ```
33
+
34
+ Use it for atoll dropdowns, cleaning up addresses people type in, or showing atolls in Dhivehi.
35
+
36
+ ## Data
37
+
38
+ Atoll codes, official names, ISO 3166-2 codes and capitals follow Wikipedia's *Administrative divisions of the Maldives* (2026) and ISO 3166-2:MV. Please open an issue if anything has changed.
39
+
40
+ ## License
41
+
42
+ MIT © Ruh Labs
package/dist/index.cjs ADDED
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ATOLLS: () => ATOLLS,
24
+ CITIES: () => CITIES,
25
+ formatIslandAddress: () => formatIslandAddress,
26
+ getAtoll: () => getAtoll,
27
+ getCity: () => getCity,
28
+ parseIslandAddress: () => parseIslandAddress
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/data.ts
33
+ var ATOLLS = [
34
+ { code: "HA", codeThaana: "\u0780\u0787", codeName: "Haa Alifu", officialName: "Thiladhunmathi Uthuruburi", latinLetter: "A", iso: "MV-07", capital: "Dhidhdhoo", aliases: ["Haa Alif"] },
35
+ { code: "HDh", codeThaana: "\u0780\u078B", codeName: "Haa Dhaalu", officialName: "Thiladhunmathi Dhekunuburi", latinLetter: "B", iso: "MV-23", capital: "Kulhudhuffushi", aliases: ["Haa Dhaal"] },
36
+ { code: "Sh", codeThaana: "\u0781", codeName: "Shaviyani", officialName: "Miladhunmadulu Uthuruburi", latinLetter: "C", iso: "MV-24", capital: "Funadhoo", aliases: [] },
37
+ { code: "N", codeThaana: "\u0782", codeName: "Noonu", officialName: "Miladhunmadulu Dhekunuburi", latinLetter: "D", iso: "MV-25", capital: "Manadhoo", aliases: [] },
38
+ { code: "R", codeThaana: "\u0783", codeName: "Raa", officialName: "Maalhosmadulu Uthuruburi", latinLetter: "E", iso: "MV-13", capital: "Ungoofaaru", aliases: [] },
39
+ { code: "B", codeThaana: "\u0784", codeName: "Baa", officialName: "Maalhosmadulu Dhekunuburi", latinLetter: "F", iso: "MV-20", capital: "Eydhafushi", aliases: [] },
40
+ { code: "Lh", codeThaana: "\u0785", codeName: "Lhaviyani", officialName: "Faadhippolhu", latinLetter: "G", iso: "MV-03", capital: "Naifaru", aliases: [] },
41
+ { code: "K", codeThaana: "\u0786", codeName: "Kaafu", officialName: "Mal\xE9 Atholhu", latinLetter: "H", iso: "MV-26", capital: "Thulusdhoo", aliases: [] },
42
+ { code: "AA", codeThaana: "\u0787\u0787", codeName: "Alifu Alifu", officialName: "Ari Atholhu Uthuruburi", latinLetter: "U", iso: "MV-02", capital: "Rasdhoo", aliases: ["Alif Alif"] },
43
+ { code: "ADh", codeThaana: "\u0787\u078B", codeName: "Alifu Dhaalu", officialName: "Ari Atholhu Dhekunuburi", latinLetter: "I", iso: "MV-00", capital: "Mahibadhoo", aliases: ["Alif Dhaal", "Alif Dhaalu"] },
44
+ { code: "V", codeThaana: "\u0788", codeName: "Vaavu", officialName: "Felidhu Atholhu", latinLetter: "J", iso: "MV-04", capital: "Felidhoo", aliases: [] },
45
+ { code: "M", codeThaana: "\u0789", codeName: "Meemu", officialName: "Mulak Atholhu", latinLetter: "K", iso: "MV-12", capital: "Muli", aliases: [] },
46
+ { code: "F", codeThaana: "\u078A", codeName: "Faafu", officialName: "Nilandhe Atholhu Uthuruburi", latinLetter: "L", iso: "MV-14", capital: "Nilandhoo", aliases: [] },
47
+ { code: "Dh", codeThaana: "\u078B", codeName: "Dhaalu", officialName: "Nilandhe Atholhu Dhekunuburi", latinLetter: "M", iso: "MV-17", capital: "Kudahuvadhoo", aliases: [] },
48
+ { code: "Th", codeThaana: "\u078C", codeName: "Thaa", officialName: "Kolhumadulu", latinLetter: "N", iso: "MV-08", capital: "Veymandoo", aliases: [] },
49
+ { code: "L", codeThaana: "\u078D", codeName: "Laamu", officialName: "Haddhunmathi", latinLetter: "O", iso: "MV-05", capital: "Fonadhoo", aliases: [] },
50
+ { code: "GA", codeThaana: "\u078E\u0787", codeName: "Gaafu Alifu", officialName: "Huvadhu Atholhu Uthuruburi", latinLetter: "P", iso: "MV-27", capital: "Villingili", aliases: ["Gaafu Alif", "Gaaf Alif"] },
51
+ { code: "GDh", codeThaana: "\u078E\u078B", codeName: "Gaafu Dhaalu", officialName: "Huvadhu Atholhu Dhekunuburi", latinLetter: "Q", iso: "MV-28", capital: "Thinadhoo", aliases: ["Gaaf Dhaal", "Gaafu Dhaal"] },
52
+ { code: "Gn", codeThaana: "\u078F", codeName: "Gnaviyani", officialName: "Fuvahmulah City", latinLetter: "R", iso: "MV-29", capital: "Fuvahmulah", aliases: [] },
53
+ { code: "S", codeThaana: "\u0790", codeName: "Seenu", officialName: "Addu City", latinLetter: "S", iso: "MV-01", capital: "Hithadhoo", aliases: ["Addu"] }
54
+ ];
55
+ var CITIES = [
56
+ { name: "Mal\xE9", atoll: null, iso: "MV-MLE" },
57
+ { name: "Addu", atoll: "S" },
58
+ { name: "Fuvahmulah", atoll: "Gn" },
59
+ { name: "Kulhudhuffushi", atoll: "HDh" },
60
+ { name: "Thinadhoo", atoll: "GDh" }
61
+ ];
62
+
63
+ // src/index.ts
64
+ var normalize = (value) => value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\b(atoll|atholhu)\b/g, "").replace(/[^a-z0-9ހ-ޱ]/g, "");
65
+ var lookup = /* @__PURE__ */ new Map();
66
+ for (const atoll of ATOLLS) {
67
+ for (const key of [atoll.code, atoll.codeThaana, atoll.codeName, atoll.officialName, atoll.iso, ...atoll.aliases]) {
68
+ lookup.set(normalize(key), atoll);
69
+ }
70
+ }
71
+ function getAtoll(query) {
72
+ return lookup.get(normalize(query));
73
+ }
74
+ function getCity(name) {
75
+ const key = normalize(name.replace(/\bcity\b/i, ""));
76
+ return CITIES.find((city) => normalize(city.name) === key);
77
+ }
78
+ function parseIslandAddress(input) {
79
+ const match = /^\s*([^\s.]+)\s*[.\s]\s*(.+?)\s*$/u.exec(input);
80
+ if (!match) return void 0;
81
+ const [, code, island] = match;
82
+ const atoll = getAtoll(code);
83
+ return atoll ? { atoll, island } : void 0;
84
+ }
85
+ function formatIslandAddress(atoll, island, options = {}) {
86
+ const found = typeof atoll === "string" ? getAtoll(atoll) : atoll;
87
+ if (!found) throw new Error(`Unknown atoll: ${atoll}`);
88
+ return `${options.thaana ? found.codeThaana : found.code}. ${island.trim()}`;
89
+ }
90
+ // Annotate the CommonJS export names for ESM import in node:
91
+ 0 && (module.exports = {
92
+ ATOLLS,
93
+ CITIES,
94
+ formatIslandAddress,
95
+ getAtoll,
96
+ getCity,
97
+ parseIslandAddress
98
+ });
99
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/data.ts"],"sourcesContent":["import { ATOLLS, CITIES, type Atoll, type City } from './data.js';\n\nexport { ATOLLS, CITIES, type Atoll, type City };\n\nconst normalize = (value: string) =>\n\tvalue\n\t\t.normalize('NFD')\n\t\t.replace(/[̀-ͯ]/g, '') // drop accents (Malé → Male)\n\t\t.toLowerCase()\n\t\t.replace(/\\b(atoll|atholhu)\\b/g, '')\n\t\t.replace(/[^a-z0-9ހ-ޱ]/g, '');\n\nconst lookup = new Map<string, Atoll>();\nfor (const atoll of ATOLLS) {\n\tfor (const key of [atoll.code, atoll.codeThaana, atoll.codeName, atoll.officialName, atoll.iso, ...atoll.aliases]) {\n\t\tlookup.set(normalize(key), atoll);\n\t}\n}\n\n/**\n * Find an atoll by any of its names or codes: \"HA\", \"Haa Alifu\", \"Haa Alif Atoll\",\n * \"ހއ\", \"Thiladhunmathi Uthuruburi\" or \"MV-07\". Case and accents don't matter.\n */\nexport function getAtoll(query: string): Atoll | undefined {\n\treturn lookup.get(normalize(query));\n}\n\n/** The city with this name (\"Malé\", \"Addu City\"), if it is one of the five cities. */\nexport function getCity(name: string): City | undefined {\n\tconst key = normalize(name.replace(/\\bcity\\b/i, ''));\n\treturn CITIES.find((city) => normalize(city.name) === key);\n}\n\nexport interface ParsedIslandAddress {\n\tatoll: Atoll;\n\tisland: string;\n}\n\n/**\n * Split an island written with its atoll code, the way Maldivians write\n * addresses: \"B. Eydhafushi\", \"HDh Kulhudhuffushi\", \"GA.Villingili\", \"ބ. އޭދަފުށި\".\n *\n * Returns `undefined` if there's no recognisable atoll code in front.\n */\nexport function parseIslandAddress(input: string): ParsedIslandAddress | undefined {\n\tconst match = /^\\s*([^\\s.]+)\\s*[.\\s]\\s*(.+?)\\s*$/u.exec(input);\n\tif (!match) return undefined;\n\tconst [, code, island] = match;\n\tconst atoll = getAtoll(code!);\n\treturn atoll ? { atoll, island: island! } : undefined;\n}\n\n/** Format an island with its atoll code: (\"B\", \"Eydhafushi\") → \"B. Eydhafushi\". */\nexport function formatIslandAddress(atoll: string | Atoll, island: string, options: { thaana?: boolean } = {}): string {\n\tconst found = typeof atoll === 'string' ? getAtoll(atoll) : atoll;\n\tif (!found) throw new Error(`Unknown atoll: ${atoll}`);\n\treturn `${options.thaana ? found.codeThaana : found.code}. ${island.trim()}`;\n}\n","export interface Atoll {\n\t/** Code abbreviation used in addresses, e.g. \"HA\", \"Sh\", \"ADh\" */\n\tcode: string;\n\t/** Code letter(s) in Thaana, e.g. \"ހއ\" */\n\tcodeThaana: string;\n\t/** Code name, e.g. \"Haa Alifu\" */\n\tcodeName: string;\n\t/** Official name of the administrative division, e.g. \"Thiladhunmathi Uthuruburi\" */\n\tofficialName: string;\n\t/** Single Latin letter used in some official systems, e.g. \"A\" */\n\tlatinLetter: string;\n\t/** ISO 3166-2 code, e.g. \"MV-07\" */\n\tiso: string;\n\t/** Administrative capital island */\n\tcapital: string;\n\t/** Other spellings people use for the code name */\n\taliases: readonly string[];\n}\n\nexport interface City {\n\tname: string;\n\t/** Code of the atoll the city is in, or null for Malé (its own division) */\n\tatoll: string | null;\n\tiso?: string;\n}\n\n/**\n * The 20 administrative atolls, from north to south.\n *\n * Source: Wikipedia, \"Administrative divisions of the Maldives\" (2026) and ISO 3166-2:MV.\n */\nexport const ATOLLS: readonly Atoll[] = [\n\t{ code: 'HA', codeThaana: 'ހއ', codeName: 'Haa Alifu', officialName: 'Thiladhunmathi Uthuruburi', latinLetter: 'A', iso: 'MV-07', capital: 'Dhidhdhoo', aliases: ['Haa Alif'] },\n\t{ code: 'HDh', codeThaana: 'ހދ', codeName: 'Haa Dhaalu', officialName: 'Thiladhunmathi Dhekunuburi', latinLetter: 'B', iso: 'MV-23', capital: 'Kulhudhuffushi', aliases: ['Haa Dhaal'] },\n\t{ code: 'Sh', codeThaana: 'ށ', codeName: 'Shaviyani', officialName: 'Miladhunmadulu Uthuruburi', latinLetter: 'C', iso: 'MV-24', capital: 'Funadhoo', aliases: [] },\n\t{ code: 'N', codeThaana: 'ނ', codeName: 'Noonu', officialName: 'Miladhunmadulu Dhekunuburi', latinLetter: 'D', iso: 'MV-25', capital: 'Manadhoo', aliases: [] },\n\t{ code: 'R', codeThaana: 'ރ', codeName: 'Raa', officialName: 'Maalhosmadulu Uthuruburi', latinLetter: 'E', iso: 'MV-13', capital: 'Ungoofaaru', aliases: [] },\n\t{ code: 'B', codeThaana: 'ބ', codeName: 'Baa', officialName: 'Maalhosmadulu Dhekunuburi', latinLetter: 'F', iso: 'MV-20', capital: 'Eydhafushi', aliases: [] },\n\t{ code: 'Lh', codeThaana: 'ޅ', codeName: 'Lhaviyani', officialName: 'Faadhippolhu', latinLetter: 'G', iso: 'MV-03', capital: 'Naifaru', aliases: [] },\n\t{ code: 'K', codeThaana: 'ކ', codeName: 'Kaafu', officialName: 'Malé Atholhu', latinLetter: 'H', iso: 'MV-26', capital: 'Thulusdhoo', aliases: [] },\n\t{ code: 'AA', codeThaana: 'އއ', codeName: 'Alifu Alifu', officialName: 'Ari Atholhu Uthuruburi', latinLetter: 'U', iso: 'MV-02', capital: 'Rasdhoo', aliases: ['Alif Alif'] },\n\t{ code: 'ADh', codeThaana: 'އދ', codeName: 'Alifu Dhaalu', officialName: 'Ari Atholhu Dhekunuburi', latinLetter: 'I', iso: 'MV-00', capital: 'Mahibadhoo', aliases: ['Alif Dhaal', 'Alif Dhaalu'] },\n\t{ code: 'V', codeThaana: 'ވ', codeName: 'Vaavu', officialName: 'Felidhu Atholhu', latinLetter: 'J', iso: 'MV-04', capital: 'Felidhoo', aliases: [] },\n\t{ code: 'M', codeThaana: 'މ', codeName: 'Meemu', officialName: 'Mulak Atholhu', latinLetter: 'K', iso: 'MV-12', capital: 'Muli', aliases: [] },\n\t{ code: 'F', codeThaana: 'ފ', codeName: 'Faafu', officialName: 'Nilandhe Atholhu Uthuruburi', latinLetter: 'L', iso: 'MV-14', capital: 'Nilandhoo', aliases: [] },\n\t{ code: 'Dh', codeThaana: 'ދ', codeName: 'Dhaalu', officialName: 'Nilandhe Atholhu Dhekunuburi', latinLetter: 'M', iso: 'MV-17', capital: 'Kudahuvadhoo', aliases: [] },\n\t{ code: 'Th', codeThaana: 'ތ', codeName: 'Thaa', officialName: 'Kolhumadulu', latinLetter: 'N', iso: 'MV-08', capital: 'Veymandoo', aliases: [] },\n\t{ code: 'L', codeThaana: 'ލ', codeName: 'Laamu', officialName: 'Haddhunmathi', latinLetter: 'O', iso: 'MV-05', capital: 'Fonadhoo', aliases: [] },\n\t{ code: 'GA', codeThaana: 'ގއ', codeName: 'Gaafu Alifu', officialName: 'Huvadhu Atholhu Uthuruburi', latinLetter: 'P', iso: 'MV-27', capital: 'Villingili', aliases: ['Gaafu Alif', 'Gaaf Alif'] },\n\t{ code: 'GDh', codeThaana: 'ގދ', codeName: 'Gaafu Dhaalu', officialName: 'Huvadhu Atholhu Dhekunuburi', latinLetter: 'Q', iso: 'MV-28', capital: 'Thinadhoo', aliases: ['Gaaf Dhaal', 'Gaafu Dhaal'] },\n\t{ code: 'Gn', codeThaana: 'ޏ', codeName: 'Gnaviyani', officialName: 'Fuvahmulah City', latinLetter: 'R', iso: 'MV-29', capital: 'Fuvahmulah', aliases: [] },\n\t{ code: 'S', codeThaana: 'ސ', codeName: 'Seenu', officialName: 'Addu City', latinLetter: 'S', iso: 'MV-01', capital: 'Hithadhoo', aliases: ['Addu'] }\n];\n\n/** The five cities, each run by a city council. */\nexport const CITIES: readonly City[] = [\n\t{ name: 'Malé', atoll: null, iso: 'MV-MLE' },\n\t{ name: 'Addu', atoll: 'S' },\n\t{ name: 'Fuvahmulah', atoll: 'Gn' },\n\t{ name: 'Kulhudhuffushi', atoll: 'HDh' },\n\t{ name: 'Thinadhoo', atoll: 'GDh' }\n];\n"],"mappings":"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","names":[]}
@@ -0,0 +1,58 @@
1
+ interface Atoll {
2
+ /** Code abbreviation used in addresses, e.g. "HA", "Sh", "ADh" */
3
+ code: string;
4
+ /** Code letter(s) in Thaana, e.g. "ހއ" */
5
+ codeThaana: string;
6
+ /** Code name, e.g. "Haa Alifu" */
7
+ codeName: string;
8
+ /** Official name of the administrative division, e.g. "Thiladhunmathi Uthuruburi" */
9
+ officialName: string;
10
+ /** Single Latin letter used in some official systems, e.g. "A" */
11
+ latinLetter: string;
12
+ /** ISO 3166-2 code, e.g. "MV-07" */
13
+ iso: string;
14
+ /** Administrative capital island */
15
+ capital: string;
16
+ /** Other spellings people use for the code name */
17
+ aliases: readonly string[];
18
+ }
19
+ interface City {
20
+ name: string;
21
+ /** Code of the atoll the city is in, or null for Malé (its own division) */
22
+ atoll: string | null;
23
+ iso?: string;
24
+ }
25
+ /**
26
+ * The 20 administrative atolls, from north to south.
27
+ *
28
+ * Source: Wikipedia, "Administrative divisions of the Maldives" (2026) and ISO 3166-2:MV.
29
+ */
30
+ declare const ATOLLS: readonly Atoll[];
31
+ /** The five cities, each run by a city council. */
32
+ declare const CITIES: readonly City[];
33
+
34
+ /**
35
+ * Find an atoll by any of its names or codes: "HA", "Haa Alifu", "Haa Alif Atoll",
36
+ * "ހއ", "Thiladhunmathi Uthuruburi" or "MV-07". Case and accents don't matter.
37
+ */
38
+ declare function getAtoll(query: string): Atoll | undefined;
39
+ /** The city with this name ("Malé", "Addu City"), if it is one of the five cities. */
40
+ declare function getCity(name: string): City | undefined;
41
+ interface ParsedIslandAddress {
42
+ atoll: Atoll;
43
+ island: string;
44
+ }
45
+ /**
46
+ * Split an island written with its atoll code, the way Maldivians write
47
+ * addresses: "B. Eydhafushi", "HDh Kulhudhuffushi", "GA.Villingili", "ބ. އޭދަފުށި".
48
+ *
49
+ * Returns `undefined` if there's no recognisable atoll code in front.
50
+ */
51
+ declare function parseIslandAddress(input: string): ParsedIslandAddress | undefined;
52
+ /** Format an island with its atoll code: ("B", "Eydhafushi") → "B. Eydhafushi". */
53
+ declare function formatIslandAddress(atoll: string | Atoll, island: string, options?: {
54
+ thaana?: boolean;
55
+ }): string;
56
+
57
+ export { ATOLLS, CITIES, formatIslandAddress, getAtoll, getCity, parseIslandAddress };
58
+ export type { Atoll, City, ParsedIslandAddress };
@@ -0,0 +1,58 @@
1
+ interface Atoll {
2
+ /** Code abbreviation used in addresses, e.g. "HA", "Sh", "ADh" */
3
+ code: string;
4
+ /** Code letter(s) in Thaana, e.g. "ހއ" */
5
+ codeThaana: string;
6
+ /** Code name, e.g. "Haa Alifu" */
7
+ codeName: string;
8
+ /** Official name of the administrative division, e.g. "Thiladhunmathi Uthuruburi" */
9
+ officialName: string;
10
+ /** Single Latin letter used in some official systems, e.g. "A" */
11
+ latinLetter: string;
12
+ /** ISO 3166-2 code, e.g. "MV-07" */
13
+ iso: string;
14
+ /** Administrative capital island */
15
+ capital: string;
16
+ /** Other spellings people use for the code name */
17
+ aliases: readonly string[];
18
+ }
19
+ interface City {
20
+ name: string;
21
+ /** Code of the atoll the city is in, or null for Malé (its own division) */
22
+ atoll: string | null;
23
+ iso?: string;
24
+ }
25
+ /**
26
+ * The 20 administrative atolls, from north to south.
27
+ *
28
+ * Source: Wikipedia, "Administrative divisions of the Maldives" (2026) and ISO 3166-2:MV.
29
+ */
30
+ declare const ATOLLS: readonly Atoll[];
31
+ /** The five cities, each run by a city council. */
32
+ declare const CITIES: readonly City[];
33
+
34
+ /**
35
+ * Find an atoll by any of its names or codes: "HA", "Haa Alifu", "Haa Alif Atoll",
36
+ * "ހއ", "Thiladhunmathi Uthuruburi" or "MV-07". Case and accents don't matter.
37
+ */
38
+ declare function getAtoll(query: string): Atoll | undefined;
39
+ /** The city with this name ("Malé", "Addu City"), if it is one of the five cities. */
40
+ declare function getCity(name: string): City | undefined;
41
+ interface ParsedIslandAddress {
42
+ atoll: Atoll;
43
+ island: string;
44
+ }
45
+ /**
46
+ * Split an island written with its atoll code, the way Maldivians write
47
+ * addresses: "B. Eydhafushi", "HDh Kulhudhuffushi", "GA.Villingili", "ބ. އޭދަފުށި".
48
+ *
49
+ * Returns `undefined` if there's no recognisable atoll code in front.
50
+ */
51
+ declare function parseIslandAddress(input: string): ParsedIslandAddress | undefined;
52
+ /** Format an island with its atoll code: ("B", "Eydhafushi") → "B. Eydhafushi". */
53
+ declare function formatIslandAddress(atoll: string | Atoll, island: string, options?: {
54
+ thaana?: boolean;
55
+ }): string;
56
+
57
+ export { ATOLLS, CITIES, formatIslandAddress, getAtoll, getCity, parseIslandAddress };
58
+ export type { Atoll, City, ParsedIslandAddress };
package/dist/index.js ADDED
@@ -0,0 +1,67 @@
1
+ // src/data.ts
2
+ var ATOLLS = [
3
+ { code: "HA", codeThaana: "\u0780\u0787", codeName: "Haa Alifu", officialName: "Thiladhunmathi Uthuruburi", latinLetter: "A", iso: "MV-07", capital: "Dhidhdhoo", aliases: ["Haa Alif"] },
4
+ { code: "HDh", codeThaana: "\u0780\u078B", codeName: "Haa Dhaalu", officialName: "Thiladhunmathi Dhekunuburi", latinLetter: "B", iso: "MV-23", capital: "Kulhudhuffushi", aliases: ["Haa Dhaal"] },
5
+ { code: "Sh", codeThaana: "\u0781", codeName: "Shaviyani", officialName: "Miladhunmadulu Uthuruburi", latinLetter: "C", iso: "MV-24", capital: "Funadhoo", aliases: [] },
6
+ { code: "N", codeThaana: "\u0782", codeName: "Noonu", officialName: "Miladhunmadulu Dhekunuburi", latinLetter: "D", iso: "MV-25", capital: "Manadhoo", aliases: [] },
7
+ { code: "R", codeThaana: "\u0783", codeName: "Raa", officialName: "Maalhosmadulu Uthuruburi", latinLetter: "E", iso: "MV-13", capital: "Ungoofaaru", aliases: [] },
8
+ { code: "B", codeThaana: "\u0784", codeName: "Baa", officialName: "Maalhosmadulu Dhekunuburi", latinLetter: "F", iso: "MV-20", capital: "Eydhafushi", aliases: [] },
9
+ { code: "Lh", codeThaana: "\u0785", codeName: "Lhaviyani", officialName: "Faadhippolhu", latinLetter: "G", iso: "MV-03", capital: "Naifaru", aliases: [] },
10
+ { code: "K", codeThaana: "\u0786", codeName: "Kaafu", officialName: "Mal\xE9 Atholhu", latinLetter: "H", iso: "MV-26", capital: "Thulusdhoo", aliases: [] },
11
+ { code: "AA", codeThaana: "\u0787\u0787", codeName: "Alifu Alifu", officialName: "Ari Atholhu Uthuruburi", latinLetter: "U", iso: "MV-02", capital: "Rasdhoo", aliases: ["Alif Alif"] },
12
+ { code: "ADh", codeThaana: "\u0787\u078B", codeName: "Alifu Dhaalu", officialName: "Ari Atholhu Dhekunuburi", latinLetter: "I", iso: "MV-00", capital: "Mahibadhoo", aliases: ["Alif Dhaal", "Alif Dhaalu"] },
13
+ { code: "V", codeThaana: "\u0788", codeName: "Vaavu", officialName: "Felidhu Atholhu", latinLetter: "J", iso: "MV-04", capital: "Felidhoo", aliases: [] },
14
+ { code: "M", codeThaana: "\u0789", codeName: "Meemu", officialName: "Mulak Atholhu", latinLetter: "K", iso: "MV-12", capital: "Muli", aliases: [] },
15
+ { code: "F", codeThaana: "\u078A", codeName: "Faafu", officialName: "Nilandhe Atholhu Uthuruburi", latinLetter: "L", iso: "MV-14", capital: "Nilandhoo", aliases: [] },
16
+ { code: "Dh", codeThaana: "\u078B", codeName: "Dhaalu", officialName: "Nilandhe Atholhu Dhekunuburi", latinLetter: "M", iso: "MV-17", capital: "Kudahuvadhoo", aliases: [] },
17
+ { code: "Th", codeThaana: "\u078C", codeName: "Thaa", officialName: "Kolhumadulu", latinLetter: "N", iso: "MV-08", capital: "Veymandoo", aliases: [] },
18
+ { code: "L", codeThaana: "\u078D", codeName: "Laamu", officialName: "Haddhunmathi", latinLetter: "O", iso: "MV-05", capital: "Fonadhoo", aliases: [] },
19
+ { code: "GA", codeThaana: "\u078E\u0787", codeName: "Gaafu Alifu", officialName: "Huvadhu Atholhu Uthuruburi", latinLetter: "P", iso: "MV-27", capital: "Villingili", aliases: ["Gaafu Alif", "Gaaf Alif"] },
20
+ { code: "GDh", codeThaana: "\u078E\u078B", codeName: "Gaafu Dhaalu", officialName: "Huvadhu Atholhu Dhekunuburi", latinLetter: "Q", iso: "MV-28", capital: "Thinadhoo", aliases: ["Gaaf Dhaal", "Gaafu Dhaal"] },
21
+ { code: "Gn", codeThaana: "\u078F", codeName: "Gnaviyani", officialName: "Fuvahmulah City", latinLetter: "R", iso: "MV-29", capital: "Fuvahmulah", aliases: [] },
22
+ { code: "S", codeThaana: "\u0790", codeName: "Seenu", officialName: "Addu City", latinLetter: "S", iso: "MV-01", capital: "Hithadhoo", aliases: ["Addu"] }
23
+ ];
24
+ var CITIES = [
25
+ { name: "Mal\xE9", atoll: null, iso: "MV-MLE" },
26
+ { name: "Addu", atoll: "S" },
27
+ { name: "Fuvahmulah", atoll: "Gn" },
28
+ { name: "Kulhudhuffushi", atoll: "HDh" },
29
+ { name: "Thinadhoo", atoll: "GDh" }
30
+ ];
31
+
32
+ // src/index.ts
33
+ var normalize = (value) => value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\b(atoll|atholhu)\b/g, "").replace(/[^a-z0-9ހ-ޱ]/g, "");
34
+ var lookup = /* @__PURE__ */ new Map();
35
+ for (const atoll of ATOLLS) {
36
+ for (const key of [atoll.code, atoll.codeThaana, atoll.codeName, atoll.officialName, atoll.iso, ...atoll.aliases]) {
37
+ lookup.set(normalize(key), atoll);
38
+ }
39
+ }
40
+ function getAtoll(query) {
41
+ return lookup.get(normalize(query));
42
+ }
43
+ function getCity(name) {
44
+ const key = normalize(name.replace(/\bcity\b/i, ""));
45
+ return CITIES.find((city) => normalize(city.name) === key);
46
+ }
47
+ function parseIslandAddress(input) {
48
+ const match = /^\s*([^\s.]+)\s*[.\s]\s*(.+?)\s*$/u.exec(input);
49
+ if (!match) return void 0;
50
+ const [, code, island] = match;
51
+ const atoll = getAtoll(code);
52
+ return atoll ? { atoll, island } : void 0;
53
+ }
54
+ function formatIslandAddress(atoll, island, options = {}) {
55
+ const found = typeof atoll === "string" ? getAtoll(atoll) : atoll;
56
+ if (!found) throw new Error(`Unknown atoll: ${atoll}`);
57
+ return `${options.thaana ? found.codeThaana : found.code}. ${island.trim()}`;
58
+ }
59
+ export {
60
+ ATOLLS,
61
+ CITIES,
62
+ formatIslandAddress,
63
+ getAtoll,
64
+ getCity,
65
+ parseIslandAddress
66
+ };
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/data.ts","../src/index.ts"],"sourcesContent":["export interface Atoll {\n\t/** Code abbreviation used in addresses, e.g. \"HA\", \"Sh\", \"ADh\" */\n\tcode: string;\n\t/** Code letter(s) in Thaana, e.g. \"ހއ\" */\n\tcodeThaana: string;\n\t/** Code name, e.g. \"Haa Alifu\" */\n\tcodeName: string;\n\t/** Official name of the administrative division, e.g. \"Thiladhunmathi Uthuruburi\" */\n\tofficialName: string;\n\t/** Single Latin letter used in some official systems, e.g. \"A\" */\n\tlatinLetter: string;\n\t/** ISO 3166-2 code, e.g. \"MV-07\" */\n\tiso: string;\n\t/** Administrative capital island */\n\tcapital: string;\n\t/** Other spellings people use for the code name */\n\taliases: readonly string[];\n}\n\nexport interface City {\n\tname: string;\n\t/** Code of the atoll the city is in, or null for Malé (its own division) */\n\tatoll: string | null;\n\tiso?: string;\n}\n\n/**\n * The 20 administrative atolls, from north to south.\n *\n * Source: Wikipedia, \"Administrative divisions of the Maldives\" (2026) and ISO 3166-2:MV.\n */\nexport const ATOLLS: readonly Atoll[] = [\n\t{ code: 'HA', codeThaana: 'ހއ', codeName: 'Haa Alifu', officialName: 'Thiladhunmathi Uthuruburi', latinLetter: 'A', iso: 'MV-07', capital: 'Dhidhdhoo', aliases: ['Haa Alif'] },\n\t{ code: 'HDh', codeThaana: 'ހދ', codeName: 'Haa Dhaalu', officialName: 'Thiladhunmathi Dhekunuburi', latinLetter: 'B', iso: 'MV-23', capital: 'Kulhudhuffushi', aliases: ['Haa Dhaal'] },\n\t{ code: 'Sh', codeThaana: 'ށ', codeName: 'Shaviyani', officialName: 'Miladhunmadulu Uthuruburi', latinLetter: 'C', iso: 'MV-24', capital: 'Funadhoo', aliases: [] },\n\t{ code: 'N', codeThaana: 'ނ', codeName: 'Noonu', officialName: 'Miladhunmadulu Dhekunuburi', latinLetter: 'D', iso: 'MV-25', capital: 'Manadhoo', aliases: [] },\n\t{ code: 'R', codeThaana: 'ރ', codeName: 'Raa', officialName: 'Maalhosmadulu Uthuruburi', latinLetter: 'E', iso: 'MV-13', capital: 'Ungoofaaru', aliases: [] },\n\t{ code: 'B', codeThaana: 'ބ', codeName: 'Baa', officialName: 'Maalhosmadulu Dhekunuburi', latinLetter: 'F', iso: 'MV-20', capital: 'Eydhafushi', aliases: [] },\n\t{ code: 'Lh', codeThaana: 'ޅ', codeName: 'Lhaviyani', officialName: 'Faadhippolhu', latinLetter: 'G', iso: 'MV-03', capital: 'Naifaru', aliases: [] },\n\t{ code: 'K', codeThaana: 'ކ', codeName: 'Kaafu', officialName: 'Malé Atholhu', latinLetter: 'H', iso: 'MV-26', capital: 'Thulusdhoo', aliases: [] },\n\t{ code: 'AA', codeThaana: 'އއ', codeName: 'Alifu Alifu', officialName: 'Ari Atholhu Uthuruburi', latinLetter: 'U', iso: 'MV-02', capital: 'Rasdhoo', aliases: ['Alif Alif'] },\n\t{ code: 'ADh', codeThaana: 'އދ', codeName: 'Alifu Dhaalu', officialName: 'Ari Atholhu Dhekunuburi', latinLetter: 'I', iso: 'MV-00', capital: 'Mahibadhoo', aliases: ['Alif Dhaal', 'Alif Dhaalu'] },\n\t{ code: 'V', codeThaana: 'ވ', codeName: 'Vaavu', officialName: 'Felidhu Atholhu', latinLetter: 'J', iso: 'MV-04', capital: 'Felidhoo', aliases: [] },\n\t{ code: 'M', codeThaana: 'މ', codeName: 'Meemu', officialName: 'Mulak Atholhu', latinLetter: 'K', iso: 'MV-12', capital: 'Muli', aliases: [] },\n\t{ code: 'F', codeThaana: 'ފ', codeName: 'Faafu', officialName: 'Nilandhe Atholhu Uthuruburi', latinLetter: 'L', iso: 'MV-14', capital: 'Nilandhoo', aliases: [] },\n\t{ code: 'Dh', codeThaana: 'ދ', codeName: 'Dhaalu', officialName: 'Nilandhe Atholhu Dhekunuburi', latinLetter: 'M', iso: 'MV-17', capital: 'Kudahuvadhoo', aliases: [] },\n\t{ code: 'Th', codeThaana: 'ތ', codeName: 'Thaa', officialName: 'Kolhumadulu', latinLetter: 'N', iso: 'MV-08', capital: 'Veymandoo', aliases: [] },\n\t{ code: 'L', codeThaana: 'ލ', codeName: 'Laamu', officialName: 'Haddhunmathi', latinLetter: 'O', iso: 'MV-05', capital: 'Fonadhoo', aliases: [] },\n\t{ code: 'GA', codeThaana: 'ގއ', codeName: 'Gaafu Alifu', officialName: 'Huvadhu Atholhu Uthuruburi', latinLetter: 'P', iso: 'MV-27', capital: 'Villingili', aliases: ['Gaafu Alif', 'Gaaf Alif'] },\n\t{ code: 'GDh', codeThaana: 'ގދ', codeName: 'Gaafu Dhaalu', officialName: 'Huvadhu Atholhu Dhekunuburi', latinLetter: 'Q', iso: 'MV-28', capital: 'Thinadhoo', aliases: ['Gaaf Dhaal', 'Gaafu Dhaal'] },\n\t{ code: 'Gn', codeThaana: 'ޏ', codeName: 'Gnaviyani', officialName: 'Fuvahmulah City', latinLetter: 'R', iso: 'MV-29', capital: 'Fuvahmulah', aliases: [] },\n\t{ code: 'S', codeThaana: 'ސ', codeName: 'Seenu', officialName: 'Addu City', latinLetter: 'S', iso: 'MV-01', capital: 'Hithadhoo', aliases: ['Addu'] }\n];\n\n/** The five cities, each run by a city council. */\nexport const CITIES: readonly City[] = [\n\t{ name: 'Malé', atoll: null, iso: 'MV-MLE' },\n\t{ name: 'Addu', atoll: 'S' },\n\t{ name: 'Fuvahmulah', atoll: 'Gn' },\n\t{ name: 'Kulhudhuffushi', atoll: 'HDh' },\n\t{ name: 'Thinadhoo', atoll: 'GDh' }\n];\n","import { ATOLLS, CITIES, type Atoll, type City } from './data.js';\n\nexport { ATOLLS, CITIES, type Atoll, type City };\n\nconst normalize = (value: string) =>\n\tvalue\n\t\t.normalize('NFD')\n\t\t.replace(/[̀-ͯ]/g, '') // drop accents (Malé → Male)\n\t\t.toLowerCase()\n\t\t.replace(/\\b(atoll|atholhu)\\b/g, '')\n\t\t.replace(/[^a-z0-9ހ-ޱ]/g, '');\n\nconst lookup = new Map<string, Atoll>();\nfor (const atoll of ATOLLS) {\n\tfor (const key of [atoll.code, atoll.codeThaana, atoll.codeName, atoll.officialName, atoll.iso, ...atoll.aliases]) {\n\t\tlookup.set(normalize(key), atoll);\n\t}\n}\n\n/**\n * Find an atoll by any of its names or codes: \"HA\", \"Haa Alifu\", \"Haa Alif Atoll\",\n * \"ހއ\", \"Thiladhunmathi Uthuruburi\" or \"MV-07\". Case and accents don't matter.\n */\nexport function getAtoll(query: string): Atoll | undefined {\n\treturn lookup.get(normalize(query));\n}\n\n/** The city with this name (\"Malé\", \"Addu City\"), if it is one of the five cities. */\nexport function getCity(name: string): City | undefined {\n\tconst key = normalize(name.replace(/\\bcity\\b/i, ''));\n\treturn CITIES.find((city) => normalize(city.name) === key);\n}\n\nexport interface ParsedIslandAddress {\n\tatoll: Atoll;\n\tisland: string;\n}\n\n/**\n * Split an island written with its atoll code, the way Maldivians write\n * addresses: \"B. Eydhafushi\", \"HDh Kulhudhuffushi\", \"GA.Villingili\", \"ބ. އޭދަފުށި\".\n *\n * Returns `undefined` if there's no recognisable atoll code in front.\n */\nexport function parseIslandAddress(input: string): ParsedIslandAddress | undefined {\n\tconst match = /^\\s*([^\\s.]+)\\s*[.\\s]\\s*(.+?)\\s*$/u.exec(input);\n\tif (!match) return undefined;\n\tconst [, code, island] = match;\n\tconst atoll = getAtoll(code!);\n\treturn atoll ? { atoll, island: island! } : undefined;\n}\n\n/** Format an island with its atoll code: (\"B\", \"Eydhafushi\") → \"B. Eydhafushi\". */\nexport function formatIslandAddress(atoll: string | Atoll, island: string, options: { thaana?: boolean } = {}): string {\n\tconst found = typeof atoll === 'string' ? getAtoll(atoll) : atoll;\n\tif (!found) throw new Error(`Unknown atoll: ${atoll}`);\n\treturn `${options.thaana ? found.codeThaana : found.code}. ${island.trim()}`;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,47 @@
1
1
  {
2
2
  "name": "@ruhlabs/atolls",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Maldivian administrative atolls and cities: codes, names, capitals and address parsing",
5
+ "license": "MIT",
6
+ "author": "Ruh Labs",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ruhlabs/devtools.git",
10
+ "directory": "packages/atolls"
11
+ },
12
+ "keywords": [
13
+ "maldives",
14
+ "atolls",
15
+ "islands",
16
+ "address",
17
+ "ruhlabs"
18
+ ],
19
+ "type": "module",
20
+ "main": "./dist/index.cjs",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "import": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "require": {
30
+ "types": "./dist/index.d.cts",
31
+ "default": "./dist/index.cjs"
32
+ }
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "sideEffects": false,
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "test": "vitest run",
45
+ "typecheck": "tsc --noEmit"
46
+ }
6
47
  }