-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathindex.js
More file actions
98 lines (85 loc) · 2.24 KB
/
Copy pathindex.js
File metadata and controls
98 lines (85 loc) · 2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"use strict";
const fs = require("fs");
const path = require("path");
const DATA_PATH = path.join(__dirname, "data", "australian-postcodes.csv");
const STATES = ["ACT", "NSW", "NT", "QLD", "SA", "TAS", "VIC", "WA"];
let _records = null;
let _byPostcode = null;
let _bySuburb = null;
let _byState = null;
function parseCsv(text) {
// The bundled CSV has no embedded commas/newlines/quotes — a tiny parser is fine.
const lines = text.replace(/\r\n/g, "\n").split("\n");
const header = lines.shift().split(",").map((h) => h.toLowerCase());
const out = [];
for (const line of lines) {
if (!line) continue;
const cols = line.split(",");
const row = {};
for (let i = 0; i < header.length; i++) {
row[header[i]] = cols[i] !== undefined ? cols[i] : "";
}
out.push(row);
}
return out;
}
function load() {
if (_records) return _records;
const text = fs.readFileSync(DATA_PATH, "utf8");
_records = parseCsv(text);
_byPostcode = new Map();
_bySuburb = new Map();
_byState = new Map();
for (const r of _records) {
pushTo(_byPostcode, r.postcode, r);
pushTo(_bySuburb, r.suburb.toUpperCase(), r);
pushTo(_byState, r.state, r);
}
return _records;
}
function pushTo(map, key, value) {
const list = map.get(key);
if (list) list.push(value); else map.set(key, [value]);
}
function all() {
return load().slice();
}
function findByPostcode(postcode) {
load();
const key = String(postcode).padStart(4, "0");
return (_byPostcode.get(key) || []).slice();
}
function findBySuburb(suburb, opts = {}) {
load();
const key = String(suburb).toUpperCase().trim();
let rows = (_bySuburb.get(key) || []).slice();
if (opts.state) {
const st = String(opts.state).toUpperCase();
rows = rows.filter((r) => r.state === st);
}
return rows;
}
function postcodeFor(suburb, state) {
const rows = findBySuburb(suburb, { state });
return rows[0] ? rows[0].postcode : null;
}
function allInState(state) {
load();
return (_byState.get(String(state).toUpperCase()) || []).slice();
}
function reload() {
_records = null;
_byPostcode = null;
_bySuburb = null;
_byState = null;
return load();
}
module.exports = {
STATES,
all,
findByPostcode,
findBySuburb,
postcodeFor,
allInState,
reload,
};