@cavoq/mcc-mnc-list 1.2.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/.github/workflows/release.yml +43 -0
- package/Dockerfile +19 -0
- package/LICENSE +22 -0
- package/README.md +160 -0
- package/eslint.config.js +17 -0
- package/fetch.js +249 -0
- package/index.js +102 -0
- package/mcc-mnc-list.json +41354 -0
- package/package.json +41 -0
- package/status-codes.json +16 -0
- package/types.d.ts +34 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: CI + Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
pull_request:
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
node-version: [20.x, 22.x]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: ${{ matrix.node-version }}
|
|
23
|
+
cache: npm
|
|
24
|
+
- run: npm ci
|
|
25
|
+
- run: npm test
|
|
26
|
+
|
|
27
|
+
publish-npm:
|
|
28
|
+
if: github.event_name == 'release'
|
|
29
|
+
needs: test
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
permissions:
|
|
32
|
+
contents: read
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-node@v4
|
|
36
|
+
with:
|
|
37
|
+
node-version: 20.x
|
|
38
|
+
registry-url: https://registry.npmjs.org/
|
|
39
|
+
cache: npm
|
|
40
|
+
- run: npm ci
|
|
41
|
+
- run: npm publish --access public
|
|
42
|
+
env:
|
|
43
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
FROM node:22-bookworm-slim
|
|
2
|
+
|
|
3
|
+
ENV NODE_ENV=production \
|
|
4
|
+
NPM_CONFIG_AUDIT=false \
|
|
5
|
+
NPM_CONFIG_FUND=false \
|
|
6
|
+
NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
7
|
+
|
|
8
|
+
WORKDIR /mnc-mcc-list
|
|
9
|
+
|
|
10
|
+
COPY package*.json ./
|
|
11
|
+
|
|
12
|
+
# `fetch.js` requires `jsdom`, which currently lives in devDependencies.
|
|
13
|
+
RUN npm install --include=dev --omit=optional && npm cache clean --force
|
|
14
|
+
|
|
15
|
+
COPY --chown=node:node . .
|
|
16
|
+
|
|
17
|
+
USER node
|
|
18
|
+
|
|
19
|
+
CMD ["node", "fetch.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Peter Bakondy
|
|
4
|
+
Copyright (c) 2026 David Stromberger
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# mcc-mnc-list
|
|
2
|
+
|
|
3
|
+
[](https://github.com/cavoq/mcc-mnc-list/actions/workflows/release.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@cavoq/mcc-mnc-list)
|
|
5
|
+
|
|
6
|
+
### 🌍 List of MCC and MNC codes from the up-to-date Wikipedia page
|
|
7
|
+
|
|
8
|
+
Maintained fork of the original `mcc-mnc-list` package.
|
|
9
|
+
|
|
10
|
+
Source: https://en.wikipedia.org/wiki/Mobile_country_code
|
|
11
|
+
|
|
12
|
+
## Definition
|
|
13
|
+
|
|
14
|
+
The ITU-T Recommendation E.212 defines mobile country codes as well as mobile network codes. The mobile country code consists of 3 decimal digits and the mobile network code consists of 2 or 3 decimal digits (for example: MNC of 001 is not the same as MNC of 01). The first digit of the mobile country code identifies the geographic region as follows (the digits 1 and 8 are not used):
|
|
15
|
+
|
|
16
|
+
- `0` - Test networks
|
|
17
|
+
- `2` - Europe
|
|
18
|
+
- `3` - North America and the Caribbean
|
|
19
|
+
- `4` - Asia and the Middle East
|
|
20
|
+
- `5` - Oceania
|
|
21
|
+
- `6` - Africa
|
|
22
|
+
- `7` - South and Central America
|
|
23
|
+
- `9` - World-wide (Satellite, Air - aboard aircraft, Maritime - aboard ships, Antarctica)
|
|
24
|
+
|
|
25
|
+
A mobile country code (MCC) is used in combination with a mobile network code (MNC) (also known as a "MCC / MNC tuple") to uniquely identify a mobile network operator (carrier) using the GSM (including GSM-R), UMTS, and LTE public land mobile networks. (*source: Wikipedia*)
|
|
26
|
+
|
|
27
|
+
## 📦 Install
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
$ npm install @cavoq/mcc-mnc-list
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 🐳 Docker
|
|
34
|
+
|
|
35
|
+
Build the image:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
docker build -t mcc-mnc-list .
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Run the fetch job in Docker:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
docker run --name mcc-mnc-list-fetch mcc-mnc-list
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Copy generated files to your host, then remove the container:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
docker cp mcc-mnc-list-fetch:/mnc-mcc-list/mcc-mnc-list.json ./mcc-mnc-list.json
|
|
51
|
+
docker cp mcc-mnc-list-fetch:/mnc-mcc-list/status-codes.json ./status-codes.json
|
|
52
|
+
docker rm mcc-mnc-list-fetch
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 🗂️ Data
|
|
56
|
+
|
|
57
|
+
### `mcc-mnc-list.json`
|
|
58
|
+
|
|
59
|
+
This file contains all the records fetched from the Wikipedia page.
|
|
60
|
+
|
|
61
|
+
Structure of a single record:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
{
|
|
65
|
+
"type": <String> - 'Test' / 'National' / 'International'
|
|
66
|
+
"countryName": <String> - country name
|
|
67
|
+
"countryCode": <String> - ISO 3166-1 country code
|
|
68
|
+
"mcc": <String> - mobile country code
|
|
69
|
+
"mnc": <String> - mobile network code
|
|
70
|
+
"brand": <String|null>
|
|
71
|
+
"operator": <String|null>
|
|
72
|
+
"status": <String> - status code ( see status-codes.json )
|
|
73
|
+
"bands": <String|null>
|
|
74
|
+
"notes": <String|null>
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
### `status-codes.json`
|
|
80
|
+
|
|
81
|
+
List ( `Array` ) of all the different Status Codes from MCC/MNC list.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## 🚀 Usage
|
|
86
|
+
|
|
87
|
+
## `.all()` : Array
|
|
88
|
+
|
|
89
|
+
Returns the full record list
|
|
90
|
+
|
|
91
|
+
## `.statusCodes()` : Array
|
|
92
|
+
|
|
93
|
+
Returns the status code list
|
|
94
|
+
|
|
95
|
+
## `.filter(filters)` : Array
|
|
96
|
+
|
|
97
|
+
Returns a filtered record list. `filters` is an object.
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
// get all the Operational mobile networks
|
|
101
|
+
let filters = { statusCode: 'Operational' }
|
|
102
|
+
|
|
103
|
+
// get all the records from Hungary
|
|
104
|
+
let filters = { mcc: '216' }
|
|
105
|
+
|
|
106
|
+
// get a specific network item ( specified with two keys )
|
|
107
|
+
let filters = { mcc: '216', mnc: '30' }
|
|
108
|
+
|
|
109
|
+
// get a specific network item ( specified with a joined key )
|
|
110
|
+
let filters = { mccmnc: '21630' }
|
|
111
|
+
|
|
112
|
+
// get all the Operational mobile networks from Hungary
|
|
113
|
+
let filters = { statusCode: 'Operational', mcc: '216' }
|
|
114
|
+
|
|
115
|
+
// get all the Operational mobile networks from US countryCode
|
|
116
|
+
let filters = { statusCode: 'Operational', countryCode: 'US' }
|
|
117
|
+
|
|
118
|
+
// get all the records
|
|
119
|
+
let filters = {}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## `.find(filters)` : Record | undefined
|
|
123
|
+
|
|
124
|
+
Returns the value of the first record in the array that satisfies the provided filters. Otherwise ``undefined`` is returned.
|
|
125
|
+
Filters are identical to the filters described in ``.filter(filters)``.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
## 🧪 Example
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
|
|
132
|
+
const mcc_mnc_list = require('@cavoq/mcc-mnc-list');
|
|
133
|
+
|
|
134
|
+
let records = mcc_mnc_list.all();
|
|
135
|
+
let statusCodes = mcc_mnc_list.statusCodes();
|
|
136
|
+
|
|
137
|
+
console.log(records.length);
|
|
138
|
+
// 2189
|
|
139
|
+
|
|
140
|
+
console.log(statusCodes.length);
|
|
141
|
+
// 12
|
|
142
|
+
|
|
143
|
+
console.log(mcc_mnc_list.filter({ mccmnc: '21630' }));
|
|
144
|
+
// [{
|
|
145
|
+
// "type": "National",
|
|
146
|
+
// "countryName": "Hungary",
|
|
147
|
+
// "countryCode": "HU",
|
|
148
|
+
// "mcc": "216",
|
|
149
|
+
// "mnc": "30",
|
|
150
|
+
// "brand": "T-Mobile",
|
|
151
|
+
// "operator": "Magyar Telekom Plc",
|
|
152
|
+
// "status": "Operational",
|
|
153
|
+
// "bands": "GSM 900 / GSM 1800 / UMTS 2100 / LTE 800 / LTE 1800 / LTE 2600",
|
|
154
|
+
// "notes": "Former WESTEL, Westel 900; MNC has the same numerical value as the area code"
|
|
155
|
+
// }]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 📄 License
|
|
159
|
+
|
|
160
|
+
**mcc-mnc-list** is licensed under the MIT Open Source license. For more information, see the LICENSE file in this repository.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const js = require("@eslint/js");
|
|
2
|
+
const globals = require("globals");
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
js.configs.recommended,
|
|
6
|
+
{
|
|
7
|
+
files: ["**/*.js"],
|
|
8
|
+
languageOptions: {
|
|
9
|
+
ecmaVersion: 8,
|
|
10
|
+
sourceType: "commonjs",
|
|
11
|
+
globals: Object.assign({}, globals.node),
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
"no-console": "off",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
package/fetch.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const jsdom = require("jsdom");
|
|
6
|
+
const { JSDOM } = jsdom;
|
|
7
|
+
|
|
8
|
+
const WIKI_URL = "https://en.wikipedia.org/wiki/Mobile_country_code";
|
|
9
|
+
const WIKI_URL_REGIONS = [
|
|
10
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_2xx_(Europe)",
|
|
11
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_3xx_(North_America)",
|
|
12
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_4xx_(Asia)",
|
|
13
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_5xx_(Oceania)",
|
|
14
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_6xx_(Africa)",
|
|
15
|
+
"https://en.wikipedia.org/wiki/Mobile_Network_Codes_in_ITU_region_7xx_(South_America)",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const MCC_MNC_OUTPUT_FILE = path.join(__dirname, "mcc-mnc-list.json");
|
|
19
|
+
const STATUS_CODES_OUTPUT_FILE = path.join(__dirname, "status-codes.json");
|
|
20
|
+
|
|
21
|
+
function fetch() {
|
|
22
|
+
let records = [];
|
|
23
|
+
let statusCodes = [];
|
|
24
|
+
|
|
25
|
+
const process = (region, records, statusCodes) =>
|
|
26
|
+
new Promise((resolve) => collect(resolve, region, records, statusCodes));
|
|
27
|
+
|
|
28
|
+
(async function loop() {
|
|
29
|
+
for (let i = 0; i < WIKI_URL_REGIONS.length; i++) {
|
|
30
|
+
const region = WIKI_URL_REGIONS[i];
|
|
31
|
+
await process(region, records, statusCodes);
|
|
32
|
+
console.log(region, records.length, statusCodes.length);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
await process(WIKI_URL, records, statusCodes, true);
|
|
36
|
+
console.log(WIKI_URL, records.length, statusCodes.length);
|
|
37
|
+
|
|
38
|
+
writeData(records, statusCodes);
|
|
39
|
+
})();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function collect(resolve, from, records, statusCodes, globals) {
|
|
43
|
+
JSDOM.fromURL(from).then((dom) => {
|
|
44
|
+
const { window } = dom;
|
|
45
|
+
var content = window.document.querySelector(
|
|
46
|
+
"#mw-content-text > .mw-parser-output"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (!content.hasChildNodes()) {
|
|
50
|
+
console.log("ERROR - empty content");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
content = removeCiteReferences(content);
|
|
55
|
+
|
|
56
|
+
const children = content.childNodes;
|
|
57
|
+
let recordType,
|
|
58
|
+
countryInfo = { name: null, code: null };
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < children.length; i++) {
|
|
61
|
+
let node = children[i];
|
|
62
|
+
|
|
63
|
+
if (!node.textContent.trim()) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (node.nodeName === "DIV") {
|
|
68
|
+
switch (node.classList.value) {
|
|
69
|
+
case "mw-heading mw-heading2":
|
|
70
|
+
recordType = getRecordType(node);
|
|
71
|
+
break;
|
|
72
|
+
case "mw-heading mw-heading4":
|
|
73
|
+
countryInfo = getCountryInfo(node);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (node.nodeName === "TABLE") {
|
|
79
|
+
if (globals && recordType === "National") {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let rows = node.querySelectorAll("tr");
|
|
84
|
+
|
|
85
|
+
for (let j = 1; j < rows.length; j++) {
|
|
86
|
+
let cols = rows[j].querySelectorAll("td");
|
|
87
|
+
|
|
88
|
+
if (cols.length < 7) {
|
|
89
|
+
// console.log('WARN invalid table row:', rows[j], node.textContent);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
Remove hidden child node of first cell:
|
|
95
|
+
|
|
96
|
+
<td><div style="overflow:hidden;width:0;height:0;margin:-1ex;float:right">
|
|
97
|
+
<h3><span class="mw-headline" id="United_States_of_America_-_US_-_313">United States of America - US - 313</span></h3>
|
|
98
|
+
</div>313
|
|
99
|
+
</td>
|
|
100
|
+
*/
|
|
101
|
+
const mccChild = cols[0].querySelector("div");
|
|
102
|
+
if (mccChild !== null) {
|
|
103
|
+
cols[0].removeChild(mccChild);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let status = cleanup(cols[4].textContent);
|
|
107
|
+
if (status === "Not Operational" || status === "Not opearational") {
|
|
108
|
+
status = "Not operational";
|
|
109
|
+
}
|
|
110
|
+
if (status === "operational") {
|
|
111
|
+
status = "Operational";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (status && statusCodes.indexOf(status) === -1) {
|
|
115
|
+
statusCodes.push(status);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
records.push({
|
|
119
|
+
type: recordType,
|
|
120
|
+
countryName: countryInfo.name,
|
|
121
|
+
countryCode: countryInfo.code,
|
|
122
|
+
mcc: cleanup(cols[0].textContent),
|
|
123
|
+
mnc: cleanup(cols[1].textContent),
|
|
124
|
+
brand: cleanup(cols[2].textContent),
|
|
125
|
+
operator: cleanup(cols[3].textContent),
|
|
126
|
+
status: status,
|
|
127
|
+
bands: cleanup(cols[5].textContent),
|
|
128
|
+
notes: cleanup(cols[6].textContent),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
resolve();
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function writeData(records, statusCodes) {
|
|
139
|
+
fs.writeFile(
|
|
140
|
+
MCC_MNC_OUTPUT_FILE,
|
|
141
|
+
JSON.stringify(records, null, 2),
|
|
142
|
+
(err) => {
|
|
143
|
+
if (err) {
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
console.log("MCC-MNC list saved to " + MCC_MNC_OUTPUT_FILE);
|
|
147
|
+
console.log("Total " + records.length + " records");
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
statusCodes.sort();
|
|
152
|
+
|
|
153
|
+
fs.writeFile(
|
|
154
|
+
STATUS_CODES_OUTPUT_FILE,
|
|
155
|
+
JSON.stringify(statusCodes, null, 2),
|
|
156
|
+
(err) => {
|
|
157
|
+
if (err) {
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
console.log("Status codes saved to " + STATUS_CODES_OUTPUT_FILE);
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function getRecordType(node) {
|
|
166
|
+
const recordTypeMap = {
|
|
167
|
+
"National operators": "National",
|
|
168
|
+
"Test networks": "Test",
|
|
169
|
+
"International operators": "International",
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const h2Node = Array.from(node.childNodes).find(
|
|
173
|
+
(child) => child.nodeName === "H2"
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
if (h2Node) {
|
|
177
|
+
const sectionName = h2Node.textContent.trim();
|
|
178
|
+
|
|
179
|
+
if (sectionName.length > 1) {
|
|
180
|
+
if (
|
|
181
|
+
sectionName === "See also" ||
|
|
182
|
+
sectionName === "External links" ||
|
|
183
|
+
sectionName === "National MNC Authorities"
|
|
184
|
+
) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return recordTypeMap[sectionName] || "other";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return "other";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function getCountryInfo(node) {
|
|
196
|
+
const h4Node = Array.from(node.childNodes).find(
|
|
197
|
+
(child) => child.nodeName === "H4"
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
let countryName = null;
|
|
201
|
+
let countryCode = null;
|
|
202
|
+
|
|
203
|
+
if (h4Node) {
|
|
204
|
+
const countryText = h4Node.textContent.trim();
|
|
205
|
+
const dashPos = countryText.indexOf("–");
|
|
206
|
+
|
|
207
|
+
if (dashPos !== -1) {
|
|
208
|
+
countryName = countryText.substring(0, dashPos).trim();
|
|
209
|
+
countryCode = countryText.substring(dashPos + 1).trim();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return { name: countryName, code: countryCode };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function removeCiteReferences(nodes) {
|
|
217
|
+
let links = nodes.querySelectorAll("a");
|
|
218
|
+
for (let i = 0; i < links.length; i++) {
|
|
219
|
+
let link = links[i];
|
|
220
|
+
let href = link.getAttribute("href");
|
|
221
|
+
if (href.substr(0, 10) === "#cite_note") {
|
|
222
|
+
link.remove();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return nodes;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function cleanup(str) {
|
|
230
|
+
str = str.trim();
|
|
231
|
+
str = removeCitationNeeded(str);
|
|
232
|
+
if (str.substr(0, 1) === "[" && str.substr(-1) === "]") {
|
|
233
|
+
// remove brackets-only like [7]
|
|
234
|
+
str = "";
|
|
235
|
+
}
|
|
236
|
+
if (str.substr(0, 1) != "[" && str.substr(-1) === "]") {
|
|
237
|
+
// remove postfix references like ...[7]
|
|
238
|
+
let index = str.lastIndexOf("[");
|
|
239
|
+
str = str.substr(0, index - 1).trim();
|
|
240
|
+
}
|
|
241
|
+
str = str.replace(/“/g, '"');
|
|
242
|
+
return str.length ? str : null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function removeCitationNeeded(str) {
|
|
246
|
+
return str.replace(/\[citation needed\]/g, "");
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
fetch();
|
package/index.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const records = require("./mcc-mnc-list.json");
|
|
4
|
+
const statusCodeList = require("./status-codes.json");
|
|
5
|
+
|
|
6
|
+
function all() {
|
|
7
|
+
return records;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function statusCodes() {
|
|
11
|
+
return statusCodeList;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function filter(filters) {
|
|
15
|
+
if (filters === undefined || filters === null) {
|
|
16
|
+
return records;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof filters !== "object") {
|
|
20
|
+
throw new TypeError("Invalid parameter (object expected)");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let statusCode, mcc, mnc, countryCode;
|
|
24
|
+
|
|
25
|
+
if (filters.statusCode) {
|
|
26
|
+
statusCode = filters.statusCode;
|
|
27
|
+
if (statusCodeList.indexOf(statusCode) === -1) {
|
|
28
|
+
throw new TypeError(
|
|
29
|
+
"Invalid statusCode parameter (not found in statusCode list)"
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (filters.mccmnc) {
|
|
35
|
+
let mccmnc;
|
|
36
|
+
if (
|
|
37
|
+
typeof filters.mccmnc === "string" ||
|
|
38
|
+
typeof filters.mccmnc === "number"
|
|
39
|
+
) {
|
|
40
|
+
mccmnc = String(filters.mccmnc);
|
|
41
|
+
} else {
|
|
42
|
+
throw new TypeError("Invalid mccmnc parameter (string expected)");
|
|
43
|
+
}
|
|
44
|
+
mcc = mccmnc.substr(0, 3);
|
|
45
|
+
mnc = mccmnc.substr(3);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (filters.mcc && mcc) {
|
|
49
|
+
throw new TypeError("Don't use mccmnc and mcc parameter at once");
|
|
50
|
+
}
|
|
51
|
+
if (filters.mnc && mnc) {
|
|
52
|
+
throw new TypeError("Don't use mccmnc and mnc parameter at once");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (filters.mcc) {
|
|
56
|
+
if (typeof filters.mcc === "string" || typeof filters.mcc === "number") {
|
|
57
|
+
mcc = String(filters.mcc);
|
|
58
|
+
} else {
|
|
59
|
+
throw new TypeError("Invalid mcc parameter (string expected)");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (filters.mnc) {
|
|
64
|
+
if (typeof filters.mnc === "string" || typeof filters.mnc === "number") {
|
|
65
|
+
mnc = String(filters.mnc);
|
|
66
|
+
} else {
|
|
67
|
+
throw new TypeError("Invalid mnc parameter (string expected)");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (filters.countryCode != undefined) {
|
|
72
|
+
if (typeof filters.countryCode === "string") {
|
|
73
|
+
countryCode = filters.countryCode;
|
|
74
|
+
} else {
|
|
75
|
+
throw new TypeError("Invalid countryCode parameter (string expected)");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let result = records;
|
|
80
|
+
|
|
81
|
+
if (statusCode) {
|
|
82
|
+
result = result.filter((record) => record["status"] === statusCode);
|
|
83
|
+
}
|
|
84
|
+
if (countryCode) {
|
|
85
|
+
result = result.filter((record) => record["countryCode"] === countryCode);
|
|
86
|
+
}
|
|
87
|
+
if (mcc) {
|
|
88
|
+
result = result.filter((record) => record["mcc"] === mcc);
|
|
89
|
+
}
|
|
90
|
+
if (mnc) {
|
|
91
|
+
result = result.filter((record) => record["mnc"] === mnc);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function find(filters) {
|
|
98
|
+
// return the first element of undefined, as filter will always return an array
|
|
99
|
+
return filter(filters)[0];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = { all, statusCodes, filter, find };
|