@rallisf1/greek-postal-code-db 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 Greek Postal Code DB contributors
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 ADDED
@@ -0,0 +1,14 @@
1
+ # @rallisf1/greek-postal-code-db
2
+
3
+ Read-only Greek postal-code data for Node.js 22.5+ and Bun. The published package includes its SQLite database.
4
+
5
+ ```ts
6
+ import { createPostalCodeClient } from '@rallisf1/greek-postal-code-db';
7
+
8
+ const client = createPostalCodeClient();
9
+ const location = client.getPostcode('10431', { include: { hierarchy: true, streets: true } });
10
+ const municipalities = client.searchMunicipalities('Αθην', { include: { hierarchy: true } });
11
+ client.close();
12
+ ```
13
+
14
+ All list and search methods accept `include: { hierarchy: true }` to attach their parent chain. See the exported TypeScript types for the complete API.
Binary file
@@ -0,0 +1,135 @@
1
+ export interface NamedEntity {
2
+ id: number;
3
+ name: string;
4
+ }
5
+ export interface CodedEntity extends NamedEntity {
6
+ /** Present only when the caller requested `includeOfficialCode`. */
7
+ officialCode?: string | null;
8
+ }
9
+ export interface DecentralizedAdministration extends NamedEntity {
10
+ }
11
+ export interface RegionHierarchy {
12
+ decentralizedAdministration: DecentralizedAdministration | null;
13
+ }
14
+ export interface RegionalUnitHierarchy extends RegionHierarchy {
15
+ region: Region | null;
16
+ }
17
+ export interface MunicipalityHierarchy extends RegionalUnitHierarchy {
18
+ regionalUnit: RegionalUnit | null;
19
+ }
20
+ export interface MunicipalityChildHierarchy extends MunicipalityHierarchy {
21
+ municipality: Municipality | null;
22
+ }
23
+ export interface Region extends NamedEntity {
24
+ hierarchy?: RegionHierarchy;
25
+ }
26
+ export interface RegionalUnit extends CodedEntity {
27
+ hierarchy?: RegionalUnitHierarchy;
28
+ }
29
+ export interface Municipality extends CodedEntity {
30
+ hierarchy?: MunicipalityHierarchy;
31
+ }
32
+ export interface MunicipalUnit extends CodedEntity {
33
+ hierarchy?: MunicipalityChildHierarchy;
34
+ }
35
+ export interface Community extends CodedEntity {
36
+ hierarchy?: MunicipalityChildHierarchy;
37
+ }
38
+ export interface Street {
39
+ id: number;
40
+ postcode: string;
41
+ name: string;
42
+ oddStart: string | null;
43
+ oddEnd: string | null;
44
+ evenStart: string | null;
45
+ evenEnd: string | null;
46
+ }
47
+ export interface PostcodeLocation {
48
+ postcode: string;
49
+ latitude: number | null;
50
+ longitude: number | null;
51
+ localArea: string | null;
52
+ municipalUnitId: number | null;
53
+ communityId: number | null;
54
+ municipalityId: number | null;
55
+ }
56
+ export interface PostcodeHierarchy {
57
+ municipalUnit: MunicipalUnit | null;
58
+ community: Community | null;
59
+ municipality: Municipality | null;
60
+ regionalUnit: RegionalUnit | null;
61
+ region: Region | null;
62
+ decentralizedAdministration: DecentralizedAdministration | null;
63
+ }
64
+ export interface PostcodeResult extends PostcodeLocation {
65
+ hierarchy?: PostcodeHierarchy;
66
+ streets?: Street[];
67
+ }
68
+ export interface ListOptions {
69
+ limit?: number;
70
+ include?: {
71
+ hierarchy?: boolean;
72
+ };
73
+ }
74
+ export interface CodedListOptions extends ListOptions {
75
+ includeOfficialCode?: boolean;
76
+ }
77
+ export interface RegionalUnitOptions extends CodedListOptions {
78
+ regionId?: number;
79
+ }
80
+ export interface MunicipalityOptions extends CodedListOptions {
81
+ regionalUnitId?: number;
82
+ }
83
+ export interface MunicipalityChildOptions extends CodedListOptions {
84
+ municipalityId?: number;
85
+ }
86
+ export interface PostcodeLookupOptions {
87
+ include?: {
88
+ hierarchy?: boolean;
89
+ streets?: boolean;
90
+ };
91
+ }
92
+ export type EntityReference = string | number;
93
+ export interface AddressInput {
94
+ postcode: string;
95
+ street?: string;
96
+ houseNumber?: string | number;
97
+ municipality?: EntityReference;
98
+ municipalUnit?: EntityReference;
99
+ community?: EntityReference;
100
+ regionalUnit?: EntityReference;
101
+ region?: EntityReference;
102
+ }
103
+ export type ValidationStatus = 'valid' | 'invalid' | 'not_evaluated';
104
+ export interface ValidationResult<T> {
105
+ status: ValidationStatus;
106
+ input: unknown;
107
+ matches?: T[];
108
+ reason?: string;
109
+ }
110
+ export interface AddressValidation {
111
+ postcode: ValidationResult<PostcodeLocation>;
112
+ street?: ValidationResult<Street>;
113
+ houseNumber?: ValidationResult<Street>;
114
+ municipality?: ValidationResult<Municipality>;
115
+ municipalUnit?: ValidationResult<MunicipalUnit>;
116
+ community?: ValidationResult<Community>;
117
+ regionalUnit?: ValidationResult<RegionalUnit>;
118
+ region?: ValidationResult<Region>;
119
+ }
120
+ export interface PostalCodeClient {
121
+ close(): void;
122
+ listRegions(options?: ListOptions): Region[];
123
+ listRegionalUnits(options?: RegionalUnitOptions): RegionalUnit[];
124
+ listMunicipalities(options?: MunicipalityOptions): Municipality[];
125
+ listMunicipalUnits(options?: MunicipalityChildOptions): MunicipalUnit[];
126
+ listCommunities(options?: MunicipalityChildOptions): Community[];
127
+ searchRegions(query: string, options?: ListOptions): Region[];
128
+ searchRegionalUnits(query: string, options?: RegionalUnitOptions): RegionalUnit[];
129
+ searchMunicipalities(query: string, options?: MunicipalityOptions): Municipality[];
130
+ searchMunicipalUnits(query: string, options?: MunicipalityChildOptions): MunicipalUnit[];
131
+ searchCommunities(query: string, options?: MunicipalityChildOptions): Community[];
132
+ getPostcode(postcode: string, options?: PostcodeLookupOptions): PostcodeResult | null;
133
+ validateAddress(address: AddressInput): AddressValidation;
134
+ }
135
+ export declare function createPostalCodeClient(): PostalCodeClient;
package/dist/index.js ADDED
@@ -0,0 +1,264 @@
1
+ // src/index.ts
2
+ import { createRequire } from "node:module";
3
+ import { fileURLToPath } from "node:url";
4
+ import { resolve } from "node:path";
5
+ var require2 = createRequire(import.meta.url);
6
+ var databasePath = resolve(fileURLToPath(new URL("../data/library.sqlite", import.meta.url)));
7
+ function openDatabase() {
8
+ if (typeof process !== "undefined" && process.versions.bun) {
9
+ const { Database } = require2("bun:sqlite");
10
+ return new Database(databasePath, { readonly: true });
11
+ }
12
+ const { DatabaseSync } = require2("node:sqlite");
13
+ return new DatabaseSync(databasePath, { readOnly: true });
14
+ }
15
+ function normalizeName(value) {
16
+ return value.normalize("NFD").replace(/\p{M}/gu, "").toLocaleLowerCase("el").replace(/[^\p{L}\p{N}]+/gu, "");
17
+ }
18
+ function limitRows(rows, limit) {
19
+ if (limit === undefined)
20
+ return rows;
21
+ if (!Number.isInteger(limit) || limit <= 0)
22
+ throw new RangeError("limit must be a positive integer");
23
+ return rows.slice(0, limit);
24
+ }
25
+ function entity(row, includeOfficialCode) {
26
+ const base = { id: Number(row.id), name: String(row.name) };
27
+ return includeOfficialCode ? { ...base, officialCode: row.official_code === null || row.official_code === undefined ? null : String(row.official_code) } : base;
28
+ }
29
+ function codedEntity(row) {
30
+ return entity(row, true);
31
+ }
32
+ function street(row) {
33
+ return {
34
+ id: Number(row.id),
35
+ postcode: String(row.postcode),
36
+ name: String(row.name),
37
+ oddStart: nullableString(row.odd_start),
38
+ oddEnd: nullableString(row.odd_end),
39
+ evenStart: nullableString(row.even_start),
40
+ evenEnd: nullableString(row.even_end)
41
+ };
42
+ }
43
+ function location(row) {
44
+ return {
45
+ postcode: String(row.postcode),
46
+ latitude: nullableNumber(row.latitude),
47
+ longitude: nullableNumber(row.longitude),
48
+ localArea: nullableString(row.local_area),
49
+ municipalUnitId: nullableNumber(row.municipal_unit_id),
50
+ communityId: nullableNumber(row.community_id),
51
+ municipalityId: nullableNumber(row.municipality_id)
52
+ };
53
+ }
54
+ function nullableString(value) {
55
+ return value === null || value === undefined ? null : String(value);
56
+ }
57
+ function nullableNumber(value) {
58
+ return value === null || value === undefined ? null : Number(value);
59
+ }
60
+ function isPostcode(value) {
61
+ return /^\d{5}$/.test(value);
62
+ }
63
+ function rangeNumber(value) {
64
+ if (value === null)
65
+ return null;
66
+ const match = /^\s*(\d+)/u.exec(value);
67
+ return match ? Number(match[1]) : null;
68
+ }
69
+ function containsHouseNumber(row, value) {
70
+ const isOdd = value % 2 === 1;
71
+ const start = rangeNumber(isOdd ? row.oddStart : row.evenStart);
72
+ const endText = isOdd ? row.oddEnd : row.evenEnd;
73
+ const end = rangeNumber(endText);
74
+ if (start === null || end === null && normalizeName(endText ?? "") !== "τελ")
75
+ return null;
76
+ return value >= start && (normalizeName(endText ?? "") === "τελ" || value <= end);
77
+ }
78
+ function createPostalCodeClient() {
79
+ const db = openDatabase();
80
+ let closed = false;
81
+ const ensureOpen = () => {
82
+ if (closed)
83
+ throw new Error("PostalCodeClient is closed");
84
+ };
85
+ const all = (sql, ...parameters) => {
86
+ ensureOpen();
87
+ return db.prepare(sql).all(...parameters);
88
+ };
89
+ const get = (sql, ...parameters) => {
90
+ ensureOpen();
91
+ return db.prepare(sql).get(...parameters);
92
+ };
93
+ function withHierarchy(table, item, includeHierarchy) {
94
+ return includeHierarchy ? { ...item, hierarchy: getEntityHierarchy(table, item.id) } : item;
95
+ }
96
+ function listEntities(table, foreignKey, parentId, options, includeOfficialCode) {
97
+ const sql = foreignKey && parentId !== undefined ? `SELECT id, name${includeOfficialCode ? ", official_code" : ""} FROM ${table} WHERE ${foreignKey} = ? ORDER BY name, id` : `SELECT id, name${includeOfficialCode ? ", official_code" : ""} FROM ${table} ORDER BY name, id`;
98
+ const rows = foreignKey && parentId !== undefined ? all(sql, parentId) : all(sql);
99
+ return limitRows(rows.map((row) => withHierarchy(table, entity(row, includeOfficialCode), options.include?.hierarchy === true)), options.limit);
100
+ }
101
+ function searchEntities(table, foreignKey, query, parentId, options, includeOfficialCode) {
102
+ const normalizedQuery = normalizeName(query);
103
+ if (!normalizedQuery)
104
+ return [];
105
+ return listEntities(table, foreignKey, parentId, {}, includeOfficialCode).filter((item) => normalizeName(item.name).startsWith(normalizedQuery)).slice(0, options.limit === undefined ? undefined : checkedLimit(options.limit)).map((item) => withHierarchy(table, item, options.include?.hierarchy === true));
106
+ }
107
+ function checkedLimit(limit) {
108
+ if (!Number.isInteger(limit) || limit <= 0)
109
+ throw new RangeError("limit must be a positive integer");
110
+ return limit;
111
+ }
112
+ function regionalUnitHierarchy(regionalUnitId) {
113
+ const regionalUnit = get("SELECT id, name, region_id, official_code FROM regional_units WHERE id = ?", regionalUnitId);
114
+ const region = regionalUnit ? get("SELECT id, name, decentralized_administration_id FROM regions WHERE id = ?", Number(regionalUnit.region_id)) : undefined;
115
+ const decentralizedAdministration = region ? get("SELECT id, name FROM decentralized_administrations WHERE id = ?", Number(region.decentralized_administration_id)) : undefined;
116
+ return {
117
+ region: region ? entity(region, false) : null,
118
+ decentralizedAdministration: decentralizedAdministration ? entity(decentralizedAdministration, false) : null
119
+ };
120
+ }
121
+ function municipalityHierarchy(municipalityId) {
122
+ const municipality = get("SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?", municipalityId);
123
+ if (!municipality)
124
+ return { regionalUnit: null, region: null, decentralizedAdministration: null };
125
+ const regionalUnit = get("SELECT id, name, region_id, official_code FROM regional_units WHERE id = ?", Number(municipality.regional_unit_id));
126
+ const ancestors = regionalUnit ? regionalUnitHierarchy(Number(regionalUnit.id)) : { region: null, decentralizedAdministration: null };
127
+ return { regionalUnit: regionalUnit ? codedEntity(regionalUnit) : null, ...ancestors };
128
+ }
129
+ function municipalityChildHierarchy(municipalityId) {
130
+ const municipality = get("SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?", municipalityId);
131
+ const ancestors = municipality ? municipalityHierarchy(Number(municipality.id)) : { regionalUnit: null, region: null, decentralizedAdministration: null };
132
+ return { municipality: municipality ? codedEntity(municipality) : null, ...ancestors };
133
+ }
134
+ function getEntityHierarchy(table, id) {
135
+ if (table === "regions") {
136
+ const region = get("SELECT decentralized_administration_id FROM regions WHERE id = ?", id);
137
+ const decentralizedAdministration = region ? get("SELECT id, name FROM decentralized_administrations WHERE id = ?", Number(region.decentralized_administration_id)) : undefined;
138
+ return { decentralizedAdministration: decentralizedAdministration ? entity(decentralizedAdministration, false) : null };
139
+ }
140
+ if (table === "regional_units")
141
+ return regionalUnitHierarchy(id);
142
+ if (table === "municipalities")
143
+ return municipalityHierarchy(id);
144
+ const child = get(`SELECT municipality_id FROM ${table} WHERE id = ?`, id);
145
+ return child ? municipalityChildHierarchy(Number(child.municipality_id)) : { municipality: null, regionalUnit: null, region: null, decentralizedAdministration: null };
146
+ }
147
+ function getHierarchy(current) {
148
+ const municipalUnit = current.municipalUnitId === null ? null : get("SELECT id, name, official_code FROM municipal_units WHERE id = ?", current.municipalUnitId);
149
+ const community = current.communityId === null ? null : get("SELECT id, name, official_code FROM communities WHERE id = ?", current.communityId);
150
+ const municipality = current.municipalityId === null ? null : get("SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?", current.municipalityId);
151
+ const ancestors = municipality ? municipalityHierarchy(Number(municipality.id)) : { regionalUnit: null, region: null, decentralizedAdministration: null };
152
+ return {
153
+ municipalUnit: municipalUnit ? codedEntity(municipalUnit) : null,
154
+ community: community ? codedEntity(community) : null,
155
+ municipality: municipality ? codedEntity(municipality) : null,
156
+ ...ancestors
157
+ };
158
+ }
159
+ function getPostcode(postcode, options = {}) {
160
+ if (!isPostcode(postcode))
161
+ return null;
162
+ const row = get("SELECT postcode, latitude, longitude, local_area, municipal_unit_id, community_id, municipality_id FROM locations WHERE postcode = ?", postcode);
163
+ if (!row)
164
+ return null;
165
+ const result = location(row);
166
+ if (options.include?.hierarchy)
167
+ result.hierarchy = getHierarchy(result);
168
+ if (options.include?.streets)
169
+ result.streets = all("SELECT id, postcode, name, odd_start, odd_end, even_start, even_end FROM streets WHERE postcode = ? ORDER BY name, id", postcode).map(street);
170
+ return result;
171
+ }
172
+ function validateReference(table, reference, linked) {
173
+ if (typeof reference === "string" && !normalizeName(reference)) {
174
+ return { status: "invalid", input: reference, matches: [], reason: "reference_must_not_be_empty" };
175
+ }
176
+ const matches = typeof reference === "number" ? all(`SELECT id, name${table === "regions" ? "" : ", official_code"} FROM ${table} WHERE id = ?`, reference).map((row) => entity(row, table !== "regions")) : all(`SELECT id, name${table === "regions" ? "" : ", official_code"} FROM ${table} ORDER BY name, id`).map((row) => entity(row, table !== "regions")).filter((candidate) => normalizeName(candidate.name).startsWith(normalizeName(reference)));
177
+ return { status: linked !== null && matches.some((candidate) => candidate.id === linked.id) ? "valid" : "invalid", input: reference, matches, reason: linked === null ? "postcode_has_no_linked_entity" : undefined };
178
+ }
179
+ function notEvaluated(input, reason) {
180
+ return { status: "not_evaluated", input, reason };
181
+ }
182
+ function validateAddress(address) {
183
+ const result = { postcode: { status: "invalid", input: address.postcode } };
184
+ const postcode = getPostcode(address.postcode, { include: { hierarchy: true, streets: address.street !== undefined || address.houseNumber !== undefined } });
185
+ if (!isPostcode(address.postcode))
186
+ result.postcode.reason = "postcode_must_be_exactly_five_digits";
187
+ else if (!postcode)
188
+ result.postcode.reason = "postcode_not_found";
189
+ else
190
+ result.postcode = { status: "valid", input: address.postcode, matches: [postcode] };
191
+ if (!postcode) {
192
+ if (address.street !== undefined)
193
+ result.street = notEvaluated(address.street, "postcode_not_found");
194
+ if (address.houseNumber !== undefined)
195
+ result.houseNumber = notEvaluated(address.houseNumber, "postcode_not_found");
196
+ for (const key of ["municipality", "municipalUnit", "community", "regionalUnit", "region"])
197
+ if (address[key] !== undefined)
198
+ result[key] = notEvaluated(address[key], "postcode_not_found");
199
+ return result;
200
+ }
201
+ const hierarchy = postcode.hierarchy;
202
+ if (address.municipality !== undefined)
203
+ result.municipality = validateReference("municipalities", address.municipality, hierarchy.municipality);
204
+ if (address.municipalUnit !== undefined)
205
+ result.municipalUnit = validateReference("municipal_units", address.municipalUnit, hierarchy.municipalUnit);
206
+ if (address.community !== undefined)
207
+ result.community = validateReference("communities", address.community, hierarchy.community);
208
+ if (address.regionalUnit !== undefined)
209
+ result.regionalUnit = validateReference("regional_units", address.regionalUnit, hierarchy.regionalUnit);
210
+ if (address.region !== undefined)
211
+ result.region = validateReference("regions", address.region, hierarchy.region);
212
+ if (address.street !== undefined) {
213
+ const streetInput = address.street;
214
+ const matches = (postcode.streets ?? []).filter((candidate) => normalizeName(candidate.name) === normalizeName(streetInput));
215
+ result.street = { status: matches.length ? "valid" : "invalid", input: streetInput, matches, reason: matches.length ? undefined : "street_not_found_for_postcode" };
216
+ }
217
+ if (address.houseNumber !== undefined) {
218
+ if (!result.street || result.street.status !== "valid")
219
+ result.houseNumber = notEvaluated(address.houseNumber, "street_is_required_and_must_be_valid");
220
+ else {
221
+ const number = typeof address.houseNumber === "number" ? address.houseNumber : /^\d+$/u.test(address.houseNumber) ? Number(address.houseNumber) : NaN;
222
+ if (!Number.isInteger(number) || number <= 0)
223
+ result.houseNumber = { status: "invalid", input: address.houseNumber, reason: "house_number_must_be_a_positive_integer" };
224
+ else {
225
+ const checks = result.street.matches.map((candidate) => containsHouseNumber(candidate, number));
226
+ const usableChecks = checks.filter((check) => check !== null);
227
+ result.houseNumber = {
228
+ status: usableChecks.length === 0 || usableChecks.some(Boolean) ? "valid" : "invalid",
229
+ input: address.houseNumber,
230
+ matches: result.street.matches,
231
+ reason: usableChecks.length === 0 ? "street_has_no_usable_range" : undefined
232
+ };
233
+ }
234
+ }
235
+ }
236
+ return result;
237
+ }
238
+ return {
239
+ close() {
240
+ if (!closed) {
241
+ db.close();
242
+ closed = true;
243
+ }
244
+ },
245
+ listRegions: (options = {}) => listEntities("regions", null, undefined, options, false),
246
+ listRegionalUnits: (options = {}) => listEntities("regional_units", "region_id", options.regionId, options, options.includeOfficialCode === true),
247
+ listMunicipalities: (options = {}) => listEntities("municipalities", "regional_unit_id", options.regionalUnitId, options, options.includeOfficialCode === true),
248
+ listMunicipalUnits: (options = {}) => listEntities("municipal_units", "municipality_id", options.municipalityId, options, options.includeOfficialCode === true),
249
+ listCommunities: (options = {}) => listEntities("communities", "municipality_id", options.municipalityId, options, options.includeOfficialCode === true),
250
+ searchRegions: (query, options = {}) => searchEntities("regions", null, query, undefined, options, false),
251
+ searchRegionalUnits: (query, options = {}) => searchEntities("regional_units", "region_id", query, options.regionId, options, options.includeOfficialCode === true),
252
+ searchMunicipalities: (query, options = {}) => searchEntities("municipalities", "regional_unit_id", query, options.regionalUnitId, options, options.includeOfficialCode === true),
253
+ searchMunicipalUnits: (query, options = {}) => searchEntities("municipal_units", "municipality_id", query, options.municipalityId, options, options.includeOfficialCode === true),
254
+ searchCommunities: (query, options = {}) => searchEntities("communities", "municipality_id", query, options.municipalityId, options, options.includeOfficialCode === true),
255
+ getPostcode,
256
+ validateAddress
257
+ };
258
+ }
259
+ export {
260
+ createPostalCodeClient
261
+ };
262
+
263
+ //# debugId=62711313008DC31764756E2164756E21
264
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": [
5
+ "import { createRequire } from 'node:module';\nimport { fileURLToPath } from 'node:url';\nimport { resolve } from 'node:path';\n\ntype SqlValue = string | number | null;\ntype SqlRow = Record<string, unknown>;\n\ninterface Statement {\n all(...parameters: SqlValue[]): SqlRow[];\n get(...parameters: SqlValue[]): SqlRow | undefined;\n}\n\ninterface ReadonlyDatabase {\n prepare(sql: string): Statement;\n close(): void;\n}\n\nexport interface NamedEntity {\n id: number;\n name: string;\n}\n\nexport interface CodedEntity extends NamedEntity {\n /** Present only when the caller requested `includeOfficialCode`. */\n officialCode?: string | null;\n}\n\nexport interface DecentralizedAdministration extends NamedEntity {}\n\nexport interface RegionHierarchy {\n decentralizedAdministration: DecentralizedAdministration | null;\n}\n\nexport interface RegionalUnitHierarchy extends RegionHierarchy {\n region: Region | null;\n}\n\nexport interface MunicipalityHierarchy extends RegionalUnitHierarchy {\n regionalUnit: RegionalUnit | null;\n}\n\nexport interface MunicipalityChildHierarchy extends MunicipalityHierarchy {\n municipality: Municipality | null;\n}\n\nexport interface Region extends NamedEntity {\n hierarchy?: RegionHierarchy;\n}\n\nexport interface RegionalUnit extends CodedEntity {\n hierarchy?: RegionalUnitHierarchy;\n}\n\nexport interface Municipality extends CodedEntity {\n hierarchy?: MunicipalityHierarchy;\n}\n\nexport interface MunicipalUnit extends CodedEntity {\n hierarchy?: MunicipalityChildHierarchy;\n}\n\nexport interface Community extends CodedEntity {\n hierarchy?: MunicipalityChildHierarchy;\n}\n\nexport interface Street {\n id: number;\n postcode: string;\n name: string;\n oddStart: string | null;\n oddEnd: string | null;\n evenStart: string | null;\n evenEnd: string | null;\n}\n\nexport interface PostcodeLocation {\n postcode: string;\n latitude: number | null;\n longitude: number | null;\n localArea: string | null;\n municipalUnitId: number | null;\n communityId: number | null;\n municipalityId: number | null;\n}\n\nexport interface PostcodeHierarchy {\n municipalUnit: MunicipalUnit | null;\n community: Community | null;\n municipality: Municipality | null;\n regionalUnit: RegionalUnit | null;\n region: Region | null;\n decentralizedAdministration: DecentralizedAdministration | null;\n}\n\nexport interface PostcodeResult extends PostcodeLocation {\n hierarchy?: PostcodeHierarchy;\n streets?: Street[];\n}\n\nexport interface ListOptions {\n limit?: number;\n include?: {\n hierarchy?: boolean;\n };\n}\n\nexport interface CodedListOptions extends ListOptions {\n includeOfficialCode?: boolean;\n}\n\nexport interface RegionalUnitOptions extends CodedListOptions {\n regionId?: number;\n}\n\nexport interface MunicipalityOptions extends CodedListOptions {\n regionalUnitId?: number;\n}\n\nexport interface MunicipalityChildOptions extends CodedListOptions {\n municipalityId?: number;\n}\n\nexport interface PostcodeLookupOptions {\n include?: {\n hierarchy?: boolean;\n streets?: boolean;\n };\n}\n\nexport type EntityReference = string | number;\n\nexport interface AddressInput {\n postcode: string;\n street?: string;\n houseNumber?: string | number;\n municipality?: EntityReference;\n municipalUnit?: EntityReference;\n community?: EntityReference;\n regionalUnit?: EntityReference;\n region?: EntityReference;\n}\n\nexport type ValidationStatus = 'valid' | 'invalid' | 'not_evaluated';\n\nexport interface ValidationResult<T> {\n status: ValidationStatus;\n input: unknown;\n matches?: T[];\n reason?: string;\n}\n\nexport interface AddressValidation {\n postcode: ValidationResult<PostcodeLocation>;\n street?: ValidationResult<Street>;\n houseNumber?: ValidationResult<Street>;\n municipality?: ValidationResult<Municipality>;\n municipalUnit?: ValidationResult<MunicipalUnit>;\n community?: ValidationResult<Community>;\n regionalUnit?: ValidationResult<RegionalUnit>;\n region?: ValidationResult<Region>;\n}\n\nexport interface PostalCodeClient {\n close(): void;\n listRegions(options?: ListOptions): Region[];\n listRegionalUnits(options?: RegionalUnitOptions): RegionalUnit[];\n listMunicipalities(options?: MunicipalityOptions): Municipality[];\n listMunicipalUnits(options?: MunicipalityChildOptions): MunicipalUnit[];\n listCommunities(options?: MunicipalityChildOptions): Community[];\n searchRegions(query: string, options?: ListOptions): Region[];\n searchRegionalUnits(query: string, options?: RegionalUnitOptions): RegionalUnit[];\n searchMunicipalities(query: string, options?: MunicipalityOptions): Municipality[];\n searchMunicipalUnits(query: string, options?: MunicipalityChildOptions): MunicipalUnit[];\n searchCommunities(query: string, options?: MunicipalityChildOptions): Community[];\n getPostcode(postcode: string, options?: PostcodeLookupOptions): PostcodeResult | null;\n validateAddress(address: AddressInput): AddressValidation;\n}\n\nconst require = createRequire(import.meta.url);\nconst databasePath = resolve(fileURLToPath(new URL('../data/library.sqlite', import.meta.url)));\n\nfunction openDatabase(): ReadonlyDatabase {\n if (typeof process !== 'undefined' && process.versions.bun) {\n const { Database } = require('bun:sqlite') as { Database: new (path: string, options: { readonly: boolean }) => ReadonlyDatabase };\n return new Database(databasePath, { readonly: true });\n }\n const { DatabaseSync } = require('node:sqlite') as { DatabaseSync: new (path: string, options: { readOnly: boolean }) => ReadonlyDatabase };\n return new DatabaseSync(databasePath, { readOnly: true });\n}\n\nfunction normalizeName(value: string): string {\n return value\n .normalize('NFD')\n .replace(/\\p{M}/gu, '')\n .toLocaleLowerCase('el')\n .replace(/[^\\p{L}\\p{N}]+/gu, '');\n}\n\nfunction limitRows<T>(rows: T[], limit: number | undefined): T[] {\n if (limit === undefined) return rows;\n if (!Number.isInteger(limit) || limit <= 0) throw new RangeError('limit must be a positive integer');\n return rows.slice(0, limit);\n}\n\nfunction entity(row: SqlRow, includeOfficialCode: boolean): NamedEntity | CodedEntity {\n const base: NamedEntity = { id: Number(row.id), name: String(row.name) };\n return includeOfficialCode ? { ...base, officialCode: row.official_code === null || row.official_code === undefined ? null : String(row.official_code) } : base;\n}\n\nfunction codedEntity(row: SqlRow): CodedEntity {\n return entity(row, true) as CodedEntity;\n}\n\nfunction street(row: SqlRow): Street {\n return {\n id: Number(row.id), postcode: String(row.postcode), name: String(row.name),\n oddStart: nullableString(row.odd_start), oddEnd: nullableString(row.odd_end),\n evenStart: nullableString(row.even_start), evenEnd: nullableString(row.even_end)\n };\n}\n\nfunction location(row: SqlRow): PostcodeLocation {\n return {\n postcode: String(row.postcode), latitude: nullableNumber(row.latitude), longitude: nullableNumber(row.longitude), localArea: nullableString(row.local_area),\n municipalUnitId: nullableNumber(row.municipal_unit_id), communityId: nullableNumber(row.community_id), municipalityId: nullableNumber(row.municipality_id)\n };\n}\n\nfunction nullableString(value: unknown): string | null { return value === null || value === undefined ? null : String(value); }\nfunction nullableNumber(value: unknown): number | null { return value === null || value === undefined ? null : Number(value); }\nfunction isPostcode(value: string): boolean { return /^\\d{5}$/.test(value); }\n\nfunction rangeNumber(value: string | null): number | null {\n if (value === null) return null;\n const match = /^\\s*(\\d+)/u.exec(value);\n return match ? Number(match[1]) : null;\n}\n\nfunction containsHouseNumber(row: Street, value: number): boolean | null {\n const isOdd = value % 2 === 1;\n const start = rangeNumber(isOdd ? row.oddStart : row.evenStart);\n const endText = isOdd ? row.oddEnd : row.evenEnd;\n const end = rangeNumber(endText);\n if (start === null || (end === null && normalizeName(endText ?? '') !== 'τελ')) return null;\n return value >= start && (normalizeName(endText ?? '') === 'τελ' || value <= (end as number));\n}\n\nexport function createPostalCodeClient(): PostalCodeClient {\n const db = openDatabase();\n let closed = false;\n const ensureOpen = () => { if (closed) throw new Error('PostalCodeClient is closed'); };\n const all = (sql: string, ...parameters: SqlValue[]) => { ensureOpen(); return db.prepare(sql).all(...parameters); };\n const get = (sql: string, ...parameters: SqlValue[]) => { ensureOpen(); return db.prepare(sql).get(...parameters); };\n\n function withHierarchy<T extends NamedEntity>(table: string, item: T, includeHierarchy: boolean): T {\n return includeHierarchy ? { ...item, hierarchy: getEntityHierarchy(table, item.id) } as T : item;\n }\n\n function listEntities(table: string, foreignKey: string | null, parentId: number | undefined, options: ListOptions, includeOfficialCode: boolean): (NamedEntity | CodedEntity)[] {\n const sql = foreignKey && parentId !== undefined\n ? `SELECT id, name${includeOfficialCode ? ', official_code' : ''} FROM ${table} WHERE ${foreignKey} = ? ORDER BY name, id`\n : `SELECT id, name${includeOfficialCode ? ', official_code' : ''} FROM ${table} ORDER BY name, id`;\n const rows = foreignKey && parentId !== undefined ? all(sql, parentId) : all(sql);\n return limitRows(rows.map((row) => withHierarchy(table, entity(row, includeOfficialCode), options.include?.hierarchy === true)), options.limit);\n }\n\n function searchEntities(table: string, foreignKey: string | null, query: string, parentId: number | undefined, options: ListOptions, includeOfficialCode: boolean): (NamedEntity | CodedEntity)[] {\n const normalizedQuery = normalizeName(query);\n if (!normalizedQuery) return [];\n return listEntities(table, foreignKey, parentId, {}, includeOfficialCode)\n .filter((item) => normalizeName(item.name).startsWith(normalizedQuery))\n .slice(0, options.limit === undefined ? undefined : checkedLimit(options.limit))\n .map((item) => withHierarchy(table, item, options.include?.hierarchy === true));\n }\n\n function checkedLimit(limit: number): number {\n if (!Number.isInteger(limit) || limit <= 0) throw new RangeError('limit must be a positive integer');\n return limit;\n }\n\n function regionalUnitHierarchy(regionalUnitId: number): RegionalUnitHierarchy {\n const regionalUnit = get('SELECT id, name, region_id, official_code FROM regional_units WHERE id = ?', regionalUnitId);\n const region = regionalUnit ? get('SELECT id, name, decentralized_administration_id FROM regions WHERE id = ?', Number(regionalUnit.region_id)) : undefined;\n const decentralizedAdministration = region ? get('SELECT id, name FROM decentralized_administrations WHERE id = ?', Number(region.decentralized_administration_id)) : undefined;\n return {\n region: region ? entity(region, false) as Region : null,\n decentralizedAdministration: decentralizedAdministration ? entity(decentralizedAdministration, false) as DecentralizedAdministration : null\n };\n }\n\n function municipalityHierarchy(municipalityId: number): MunicipalityHierarchy {\n const municipality = get('SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?', municipalityId);\n if (!municipality) return { regionalUnit: null, region: null, decentralizedAdministration: null };\n const regionalUnit = get('SELECT id, name, region_id, official_code FROM regional_units WHERE id = ?', Number(municipality.regional_unit_id));\n const ancestors = regionalUnit ? regionalUnitHierarchy(Number(regionalUnit.id)) : { region: null, decentralizedAdministration: null };\n return { regionalUnit: regionalUnit ? codedEntity(regionalUnit) as RegionalUnit : null, ...ancestors };\n }\n\n function municipalityChildHierarchy(municipalityId: number): MunicipalityChildHierarchy {\n const municipality = get('SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?', municipalityId);\n const ancestors = municipality ? municipalityHierarchy(Number(municipality.id)) : { regionalUnit: null, region: null, decentralizedAdministration: null };\n return { municipality: municipality ? codedEntity(municipality) as Municipality : null, ...ancestors };\n }\n\n function getEntityHierarchy(table: string, id: number): RegionHierarchy | RegionalUnitHierarchy | MunicipalityHierarchy | MunicipalityChildHierarchy {\n if (table === 'regions') {\n const region = get('SELECT decentralized_administration_id FROM regions WHERE id = ?', id);\n const decentralizedAdministration = region ? get('SELECT id, name FROM decentralized_administrations WHERE id = ?', Number(region.decentralized_administration_id)) : undefined;\n return { decentralizedAdministration: decentralizedAdministration ? entity(decentralizedAdministration, false) as DecentralizedAdministration : null };\n }\n if (table === 'regional_units') return regionalUnitHierarchy(id);\n if (table === 'municipalities') return municipalityHierarchy(id);\n const child = get(`SELECT municipality_id FROM ${table} WHERE id = ?`, id);\n return child ? municipalityChildHierarchy(Number(child.municipality_id)) : { municipality: null, regionalUnit: null, region: null, decentralizedAdministration: null };\n }\n\n function getHierarchy(current: PostcodeLocation): PostcodeHierarchy {\n const municipalUnit = current.municipalUnitId === null ? null : get('SELECT id, name, official_code FROM municipal_units WHERE id = ?', current.municipalUnitId);\n const community = current.communityId === null ? null : get('SELECT id, name, official_code FROM communities WHERE id = ?', current.communityId);\n const municipality = current.municipalityId === null ? null : get('SELECT id, name, regional_unit_id, official_code FROM municipalities WHERE id = ?', current.municipalityId);\n const ancestors = municipality ? municipalityHierarchy(Number(municipality.id)) : { regionalUnit: null, region: null, decentralizedAdministration: null };\n return {\n municipalUnit: municipalUnit ? codedEntity(municipalUnit) : null, community: community ? codedEntity(community) : null,\n municipality: municipality ? codedEntity(municipality) : null, ...ancestors\n };\n }\n\n function getPostcode(postcode: string, options: PostcodeLookupOptions = {}): PostcodeResult | null {\n if (!isPostcode(postcode)) return null;\n const row = get('SELECT postcode, latitude, longitude, local_area, municipal_unit_id, community_id, municipality_id FROM locations WHERE postcode = ?', postcode);\n if (!row) return null;\n const result: PostcodeResult = location(row);\n if (options.include?.hierarchy) result.hierarchy = getHierarchy(result);\n if (options.include?.streets) result.streets = all('SELECT id, postcode, name, odd_start, odd_end, even_start, even_end FROM streets WHERE postcode = ? ORDER BY name, id', postcode).map(street);\n return result;\n }\n\n function validateReference<T extends NamedEntity>(table: string, reference: EntityReference, linked: T | null): ValidationResult<T> {\n if (typeof reference === 'string' && !normalizeName(reference)) {\n return { status: 'invalid', input: reference, matches: [], reason: 'reference_must_not_be_empty' };\n }\n const matches = typeof reference === 'number'\n ? all(`SELECT id, name${table === 'regions' ? '' : ', official_code'} FROM ${table} WHERE id = ?`, reference).map((row) => entity(row, table !== 'regions') as T)\n : all(`SELECT id, name${table === 'regions' ? '' : ', official_code'} FROM ${table} ORDER BY name, id`).map((row) => entity(row, table !== 'regions') as T).filter((candidate) => normalizeName(candidate.name).startsWith(normalizeName(reference)));\n return { status: linked !== null && matches.some((candidate) => candidate.id === linked.id) ? 'valid' : 'invalid', input: reference, matches, reason: linked === null ? 'postcode_has_no_linked_entity' : undefined };\n }\n\n function notEvaluated<T>(input: unknown, reason: string): ValidationResult<T> { return { status: 'not_evaluated', input, reason }; }\n\n function validateAddress(address: AddressInput): AddressValidation {\n const result: AddressValidation = { postcode: { status: 'invalid', input: address.postcode } };\n const postcode = getPostcode(address.postcode, { include: { hierarchy: true, streets: address.street !== undefined || address.houseNumber !== undefined } });\n if (!isPostcode(address.postcode)) result.postcode.reason = 'postcode_must_be_exactly_five_digits';\n else if (!postcode) result.postcode.reason = 'postcode_not_found';\n else result.postcode = { status: 'valid', input: address.postcode, matches: [postcode] };\n\n if (!postcode) {\n if (address.street !== undefined) result.street = notEvaluated(address.street, 'postcode_not_found');\n if (address.houseNumber !== undefined) result.houseNumber = notEvaluated(address.houseNumber, 'postcode_not_found');\n for (const key of ['municipality', 'municipalUnit', 'community', 'regionalUnit', 'region'] as const) if (address[key] !== undefined) result[key] = notEvaluated(address[key], 'postcode_not_found') as never;\n return result;\n }\n\n const hierarchy = postcode.hierarchy as PostcodeHierarchy;\n if (address.municipality !== undefined) result.municipality = validateReference<Municipality>('municipalities', address.municipality, hierarchy.municipality);\n if (address.municipalUnit !== undefined) result.municipalUnit = validateReference<MunicipalUnit>('municipal_units', address.municipalUnit, hierarchy.municipalUnit);\n if (address.community !== undefined) result.community = validateReference<Community>('communities', address.community, hierarchy.community);\n if (address.regionalUnit !== undefined) result.regionalUnit = validateReference<RegionalUnit>('regional_units', address.regionalUnit, hierarchy.regionalUnit);\n if (address.region !== undefined) result.region = validateReference<Region>('regions', address.region, hierarchy.region);\n\n if (address.street !== undefined) {\n const streetInput = address.street;\n const matches = (postcode.streets ?? []).filter((candidate) => normalizeName(candidate.name) === normalizeName(streetInput));\n result.street = { status: matches.length ? 'valid' : 'invalid', input: streetInput, matches, reason: matches.length ? undefined : 'street_not_found_for_postcode' };\n }\n if (address.houseNumber !== undefined) {\n if (!result.street || result.street.status !== 'valid') result.houseNumber = notEvaluated(address.houseNumber, 'street_is_required_and_must_be_valid');\n else {\n const number = typeof address.houseNumber === 'number' ? address.houseNumber : /^\\d+$/u.test(address.houseNumber) ? Number(address.houseNumber) : NaN;\n if (!Number.isInteger(number) || number <= 0) result.houseNumber = { status: 'invalid', input: address.houseNumber, reason: 'house_number_must_be_a_positive_integer' };\n else {\n const checks = result.street.matches!.map((candidate) => containsHouseNumber(candidate, number));\n const usableChecks = checks.filter((check): check is boolean => check !== null);\n result.houseNumber = {\n status: usableChecks.length === 0 || usableChecks.some(Boolean) ? 'valid' : 'invalid', input: address.houseNumber,\n matches: result.street.matches, reason: usableChecks.length === 0 ? 'street_has_no_usable_range' : undefined\n };\n }\n }\n }\n return result;\n }\n\n return {\n close() { if (!closed) { db.close(); closed = true; } },\n listRegions: (options = {}) => listEntities('regions', null, undefined, options, false) as Region[],\n listRegionalUnits: (options = {}) => listEntities('regional_units', 'region_id', options.regionId, options, options.includeOfficialCode === true) as RegionalUnit[],\n listMunicipalities: (options = {}) => listEntities('municipalities', 'regional_unit_id', options.regionalUnitId, options, options.includeOfficialCode === true) as Municipality[],\n listMunicipalUnits: (options = {}) => listEntities('municipal_units', 'municipality_id', options.municipalityId, options, options.includeOfficialCode === true) as MunicipalUnit[],\n listCommunities: (options = {}) => listEntities('communities', 'municipality_id', options.municipalityId, options, options.includeOfficialCode === true) as Community[],\n searchRegions: (query, options = {}) => searchEntities('regions', null, query, undefined, options, false) as Region[],\n searchRegionalUnits: (query, options = {}) => searchEntities('regional_units', 'region_id', query, options.regionId, options, options.includeOfficialCode === true) as RegionalUnit[],\n searchMunicipalities: (query, options = {}) => searchEntities('municipalities', 'regional_unit_id', query, options.regionalUnitId, options, options.includeOfficialCode === true) as Municipality[],\n searchMunicipalUnits: (query, options = {}) => searchEntities('municipal_units', 'municipality_id', query, options.municipalityId, options, options.includeOfficialCode === true) as MunicipalUnit[],\n searchCommunities: (query, options = {}) => searchEntities('communities', 'municipality_id', query, options.municipalityId, options, options.includeOfficialCode === true) as Community[],\n getPostcode,\n validateAddress\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "62711313008DC31764756E2164756E21",
9
+ "names": []
10
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@rallisf1/greek-postal-code-db",
3
+ "version": "0.1.0",
4
+ "description": "Read-only Node.js and Bun client for Greek postal-code data",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "data/library.sqlite",
16
+ "LICENSE",
17
+ "README.md"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "engines": {
23
+ "node": ">=22.5.0"
24
+ },
25
+ "scripts": {
26
+ "build": "copyfiles -u 1 ../library.sqlite data/ && bun build ./src/index.ts --outdir ./dist --target node --format esm --sourcemap && tsc -p tsconfig.json",
27
+ "test": "bun run build && node --test test/contract.test.mjs && bun test test/contract.test.mjs",
28
+ "prepack": "bun run build"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.0.0",
32
+ "copyfiles": "^2.4.1",
33
+ "typescript": "^5.0.0"
34
+ }
35
+ }