thaizip 0.5.1 → 0.7.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/README.md +90 -213
- package/dist/data.cjs +108 -34
- package/dist/data.d.cts +16 -0
- package/dist/data.d.ts +16 -0
- package/dist/data.js +108 -34
- package/dist/index.cjs +327 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -20
- package/dist/index.d.ts +160 -20
- package/dist/index.js +322 -104
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +374 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +111 -0
- package/dist/react.d.ts +111 -0
- package/dist/react.js +372 -0
- package/dist/react.js.map +1 -0
- package/package.json +9 -4
package/dist/data.js
CHANGED
|
@@ -25,8 +25,8 @@ var init_defaultData = __esm({
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
// src/core/normalizer.ts
|
|
28
|
-
var TONE_MARKS = /[
|
|
29
|
-
var ADDRESS_PREFIXES = /^(
|
|
28
|
+
var TONE_MARKS = /[่-๋็์]/g;
|
|
29
|
+
var ADDRESS_PREFIXES = /^(จังหวัด|อำเภอ|ตำบล|แขวง|เขต|จ\.|อ\.|ต\.|ข\.)/;
|
|
30
30
|
function normalizeThaiAddressText(input) {
|
|
31
31
|
if (!input) return "";
|
|
32
32
|
let text = input.trim();
|
|
@@ -54,7 +54,56 @@ function extractTrigramsNormalized(text) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// src/core/indexer.ts
|
|
57
|
-
function
|
|
57
|
+
function typeErr(table, id, field, expected, value) {
|
|
58
|
+
return new TypeError(`[thaizip] ${table} ${id}: expected ${expected} for ${field}, got ${typeof value}`);
|
|
59
|
+
}
|
|
60
|
+
function validateRawData(data) {
|
|
61
|
+
const { provinces, amphures, tambons } = data;
|
|
62
|
+
for (let i = 0; i < provinces.length; i++) {
|
|
63
|
+
const p2 = provinces[i];
|
|
64
|
+
if (typeof p2.id !== "number") throw typeErr("province", p2.id, "id", "number", p2.id);
|
|
65
|
+
if (typeof p2.name_th !== "string") throw typeErr("province", p2.id, "name_th", "string", p2.name_th);
|
|
66
|
+
if (typeof p2.name_en !== "string") throw typeErr("province", p2.id, "name_en", "string", p2.name_en);
|
|
67
|
+
}
|
|
68
|
+
for (let i = 0; i < amphures.length; i++) {
|
|
69
|
+
const a2 = amphures[i];
|
|
70
|
+
if (typeof a2.id !== "number") throw typeErr("amphure", a2.id, "id", "number", a2.id);
|
|
71
|
+
if (typeof a2.name_th !== "string") throw typeErr("amphure", a2.id, "name_th", "string", a2.name_th);
|
|
72
|
+
if (typeof a2.name_en !== "string") throw typeErr("amphure", a2.id, "name_en", "string", a2.name_en);
|
|
73
|
+
if (typeof a2.province_id !== "number") throw typeErr("amphure", a2.id, "province_id", "number", a2.province_id);
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < tambons.length; i++) {
|
|
76
|
+
const t2 = tambons[i];
|
|
77
|
+
if (typeof t2.id !== "number") throw typeErr("tambon", t2.id, "id", "number", t2.id);
|
|
78
|
+
if (typeof t2.name_th !== "string") throw typeErr("tambon", t2.id, "name_th", "string", t2.name_th);
|
|
79
|
+
if (typeof t2.name_en !== "string") throw typeErr("tambon", t2.id, "name_en", "string", t2.name_en);
|
|
80
|
+
const zipType = typeof t2.zip_code;
|
|
81
|
+
if (zipType !== "string" && zipType !== "number") {
|
|
82
|
+
throw typeErr("tambon", t2.id, "zip_code", "string or number", t2.zip_code);
|
|
83
|
+
}
|
|
84
|
+
if (typeof t2.amphure_id !== "number") throw typeErr("tambon", t2.id, "amphure_id", "number", t2.amphure_id);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function addTrigrams(map, trigrams, idx) {
|
|
88
|
+
for (const trigram of trigrams) {
|
|
89
|
+
let set = map.get(trigram);
|
|
90
|
+
if (!set) {
|
|
91
|
+
set = /* @__PURE__ */ new Set();
|
|
92
|
+
map.set(trigram, set);
|
|
93
|
+
}
|
|
94
|
+
set.add(idx);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function combinedTrigrams(nameTh, nameEn) {
|
|
98
|
+
const s = /* @__PURE__ */ new Set();
|
|
99
|
+
for (const t2 of extractTrigrams(nameTh)) s.add(t2);
|
|
100
|
+
for (const t2 of extractTrigrams(nameEn)) s.add(t2);
|
|
101
|
+
return s;
|
|
102
|
+
}
|
|
103
|
+
function buildThaiAddressIndex(data, options) {
|
|
104
|
+
if (options?.validate !== false) {
|
|
105
|
+
validateRawData(data);
|
|
106
|
+
}
|
|
58
107
|
const { provinces, amphures, tambons } = data;
|
|
59
108
|
const provMap = new Map(
|
|
60
109
|
provinces.filter((p2) => !p2.deleted_at).map((p2) => [p2.id, p2])
|
|
@@ -62,20 +111,33 @@ function buildThaiAddressIndex(data) {
|
|
|
62
111
|
const ampMap = new Map(
|
|
63
112
|
amphures.filter((a2) => !a2.deleted_at).map((a2) => [a2.id, a2])
|
|
64
113
|
);
|
|
114
|
+
const provTrigrams = /* @__PURE__ */ new Map();
|
|
115
|
+
for (const [id, prov] of provMap) {
|
|
116
|
+
provTrigrams.set(id, combinedTrigrams(prov.name_th, prov.name_en));
|
|
117
|
+
}
|
|
118
|
+
const ampTrigrams = /* @__PURE__ */ new Map();
|
|
119
|
+
for (const [id, amp] of ampMap) {
|
|
120
|
+
ampTrigrams.set(id, combinedTrigrams(amp.name_th, amp.name_en));
|
|
121
|
+
}
|
|
65
122
|
const records = [];
|
|
66
123
|
const map = /* @__PURE__ */ new Map();
|
|
67
124
|
const zipIndex = /* @__PURE__ */ new Map();
|
|
125
|
+
const normTambon = [];
|
|
126
|
+
const normTambonEn = [];
|
|
127
|
+
const byProvince = /* @__PURE__ */ new Map();
|
|
128
|
+
const byAmphure = /* @__PURE__ */ new Map();
|
|
68
129
|
for (const tambon of tambons) {
|
|
69
130
|
if (tambon.deleted_at) continue;
|
|
70
131
|
const amphure = ampMap.get(tambon.amphure_id);
|
|
71
132
|
if (!amphure) {
|
|
72
|
-
|
|
73
|
-
`[thaizip] skipping tambon id=${tambon.id} (${tambon.name_th}): amphure_id=${tambon.amphure_id} not found or deleted`
|
|
74
|
-
);
|
|
133
|
+
if (options?.onSkip) options.onSkip(tambon);
|
|
75
134
|
continue;
|
|
76
135
|
}
|
|
77
136
|
const province = provMap.get(amphure.province_id);
|
|
78
|
-
if (!province)
|
|
137
|
+
if (!province) {
|
|
138
|
+
if (options?.onSkip) options.onSkip(tambon);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
79
141
|
const record = {
|
|
80
142
|
provinceId: province.id,
|
|
81
143
|
provinceNameTh: province.name_th,
|
|
@@ -93,43 +155,55 @@ function buildThaiAddressIndex(data) {
|
|
|
93
155
|
const existing = zipIndex.get(record.zipCode);
|
|
94
156
|
if (existing) existing.push(idx);
|
|
95
157
|
else zipIndex.set(record.zipCode, [idx]);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
set.add(idx);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
158
|
+
const provList = byProvince.get(province.id);
|
|
159
|
+
if (provList) provList.push(idx);
|
|
160
|
+
else byProvince.set(province.id, [idx]);
|
|
161
|
+
const ampList = byAmphure.get(amphure.id);
|
|
162
|
+
if (ampList) ampList.push(idx);
|
|
163
|
+
else byAmphure.set(amphure.id, [idx]);
|
|
164
|
+
const normTh = normalizeThaiAddressText(record.tambonNameTh);
|
|
165
|
+
normTambon.push(normTh);
|
|
166
|
+
addTrigrams(map, extractTrigramsNormalized(normTh), idx);
|
|
167
|
+
const normEn = normalizeThaiAddressText(record.tambonNameEn);
|
|
168
|
+
normTambonEn.push(normEn);
|
|
169
|
+
addTrigrams(map, extractTrigramsNormalized(normEn), idx);
|
|
170
|
+
addTrigrams(map, extractTrigrams(record.zipCode), idx);
|
|
171
|
+
addTrigrams(map, provTrigrams.get(province.id), idx);
|
|
172
|
+
addTrigrams(map, ampTrigrams.get(amphure.id), idx);
|
|
115
173
|
}
|
|
116
|
-
return { map, records, zipIndex };
|
|
174
|
+
return { map, records, zipIndex, normTambon, normTambonEn, byProvince, byAmphure };
|
|
117
175
|
}
|
|
118
176
|
|
|
119
177
|
// src/data/loader.ts
|
|
120
178
|
var cached = null;
|
|
179
|
+
var inflightPromise = null;
|
|
180
|
+
var loadGeneration = 0;
|
|
121
181
|
function clearDefaultIndex() {
|
|
122
182
|
cached = null;
|
|
183
|
+
inflightPromise = null;
|
|
184
|
+
loadGeneration++;
|
|
123
185
|
}
|
|
124
186
|
async function loadDefaultIndex() {
|
|
125
187
|
if (cached) return cached;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
188
|
+
if (!inflightPromise) {
|
|
189
|
+
const gen = loadGeneration;
|
|
190
|
+
inflightPromise = Promise.resolve().then(() => (init_defaultData(), defaultData_exports)).then(({ p: p2, a: a2, t: t2 }) => {
|
|
191
|
+
const index = buildThaiAddressIndex({
|
|
192
|
+
provinces: p2.map(([id, name_th, name_en]) => ({ id, name_th, name_en, geography_id: 0, deleted_at: null })),
|
|
193
|
+
amphures: a2.map(([id, name_th, name_en, province_id]) => ({ id, name_th, name_en, province_id, deleted_at: null })),
|
|
194
|
+
tambons: t2.map(([id, name_th, name_en, amphure_id, zip_code]) => ({ id, name_th, name_en, amphure_id, zip_code, deleted_at: null }))
|
|
195
|
+
}, { validate: false });
|
|
196
|
+
if (loadGeneration === gen) {
|
|
197
|
+
cached = index;
|
|
198
|
+
inflightPromise = null;
|
|
199
|
+
}
|
|
200
|
+
return index;
|
|
201
|
+
}).catch((err) => {
|
|
202
|
+
if (loadGeneration === gen) inflightPromise = null;
|
|
203
|
+
throw err;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return inflightPromise;
|
|
133
207
|
}
|
|
134
208
|
|
|
135
209
|
export { clearDefaultIndex, loadDefaultIndex };
|