@mountainpass/addressr 2.1.1 → 2.1.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/lib/client/elasticsearch.js +3 -0
- package/lib/service/address-service.js +7 -23
- package/lib/src/waycharter-server.js +241 -10
- package/lib/version.js +1 -1
- package/package.json +1 -1
|
@@ -737,7 +737,8 @@ async function loadAddressDetails(file, expectedCount, context, {
|
|
|
737
737
|
sla,
|
|
738
738
|
ssla,
|
|
739
739
|
structured,
|
|
740
|
-
confidence: structured.structured.confidence
|
|
740
|
+
confidence: structured.structured.confidence,
|
|
741
|
+
locality_pid: row.LOCALITY_PID
|
|
741
742
|
});
|
|
742
743
|
}
|
|
743
744
|
if (indexingBody.length > 0) {
|
|
@@ -984,20 +985,13 @@ async function getPostcode(postcode) {
|
|
|
984
985
|
const searchResp = await globalThis.esClient.search({
|
|
985
986
|
index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
|
|
986
987
|
body: {
|
|
987
|
-
size:
|
|
988
|
+
size: 100,
|
|
988
989
|
query: {
|
|
989
990
|
term: {
|
|
990
991
|
postcodes: postcode
|
|
991
992
|
}
|
|
992
993
|
},
|
|
993
|
-
|
|
994
|
-
localities: {
|
|
995
|
-
terms: {
|
|
996
|
-
field: 'locality_name.raw',
|
|
997
|
-
size: 100
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
994
|
+
_source: ['locality_name', 'locality_pid']
|
|
1001
995
|
}
|
|
1002
996
|
});
|
|
1003
997
|
return searchResp;
|
|
@@ -1018,18 +1012,6 @@ async function getState(abbreviation) {
|
|
|
1018
1012
|
field: 'state_name',
|
|
1019
1013
|
size: 1
|
|
1020
1014
|
}
|
|
1021
|
-
},
|
|
1022
|
-
localities: {
|
|
1023
|
-
terms: {
|
|
1024
|
-
field: 'locality_name.raw',
|
|
1025
|
-
size: 1000
|
|
1026
|
-
}
|
|
1027
|
-
},
|
|
1028
|
-
postcodes: {
|
|
1029
|
-
terms: {
|
|
1030
|
-
field: 'postcodes',
|
|
1031
|
-
size: 1000
|
|
1032
|
-
}
|
|
1033
1015
|
}
|
|
1034
1016
|
}
|
|
1035
1017
|
}
|
|
@@ -1599,10 +1581,12 @@ async function getAddress(addressId) {
|
|
|
1599
1581
|
});
|
|
1600
1582
|
// TODO: store hash in address
|
|
1601
1583
|
const hash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(json)).digest('hex');
|
|
1584
|
+
const localityPid = jsonX.body._source.locality_pid;
|
|
1602
1585
|
return {
|
|
1603
1586
|
link,
|
|
1604
1587
|
json,
|
|
1605
|
-
hash
|
|
1588
|
+
hash,
|
|
1589
|
+
localityPid
|
|
1606
1590
|
};
|
|
1607
1591
|
} catch (error_) {
|
|
1608
1592
|
error('error getting record from elastic search', error_);
|
|
@@ -47,10 +47,37 @@ function startRest2Server() {
|
|
|
47
47
|
const {
|
|
48
48
|
json,
|
|
49
49
|
hash,
|
|
50
|
-
statusCode
|
|
50
|
+
statusCode,
|
|
51
|
+
localityPid
|
|
51
52
|
} = await (0, _addressService.getAddress)(pid);
|
|
53
|
+
const links = [];
|
|
54
|
+
if (localityPid) {
|
|
55
|
+
links.push({
|
|
56
|
+
rel: 'related',
|
|
57
|
+
uri: `/localities/${localityPid}`,
|
|
58
|
+
title: json.structured?.locality?.name || 'Locality'
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (json.structured) {
|
|
62
|
+
const s = json.structured;
|
|
63
|
+
if (s.postcode) {
|
|
64
|
+
links.push({
|
|
65
|
+
rel: 'related',
|
|
66
|
+
uri: `/postcodes/${s.postcode}`,
|
|
67
|
+
title: `Postcode ${s.postcode}`
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (s.state && s.state.abbreviation) {
|
|
71
|
+
links.push({
|
|
72
|
+
rel: 'related',
|
|
73
|
+
uri: `/states/${s.state.abbreviation}`,
|
|
74
|
+
title: s.state.name
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
52
78
|
return {
|
|
53
79
|
body: json,
|
|
80
|
+
links,
|
|
54
81
|
headers: {
|
|
55
82
|
etag: `"${_version.version}-${hash}"`,
|
|
56
83
|
'cache-control': `public, max-age=${ONE_WEEK}`
|
|
@@ -114,9 +141,25 @@ function startRest2Server() {
|
|
|
114
141
|
}) => {
|
|
115
142
|
const resp = await (0, _addressService.getLocality)(pid);
|
|
116
143
|
const source = resp.body._source;
|
|
144
|
+
const links = [];
|
|
145
|
+
if (source.primary_postcode) {
|
|
146
|
+
links.push({
|
|
147
|
+
rel: 'related',
|
|
148
|
+
uri: `/postcodes/${source.primary_postcode}`,
|
|
149
|
+
title: `Postcode ${source.primary_postcode}`
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (source.state_abbreviation) {
|
|
153
|
+
links.push({
|
|
154
|
+
rel: 'related',
|
|
155
|
+
uri: `/states/${source.state_abbreviation}`,
|
|
156
|
+
title: source.state_name
|
|
157
|
+
});
|
|
158
|
+
}
|
|
117
159
|
const hash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(source)).digest('hex');
|
|
118
160
|
return {
|
|
119
161
|
body: source,
|
|
162
|
+
links,
|
|
120
163
|
headers: {
|
|
121
164
|
etag: `"${_version.version}-${hash}"`,
|
|
122
165
|
'cache-control': `public, max-age=${ONE_WEEK}`
|
|
@@ -182,8 +225,14 @@ function startRest2Server() {
|
|
|
182
225
|
postcode
|
|
183
226
|
}) => {
|
|
184
227
|
const result = await (0, _addressService.getPostcode)(postcode);
|
|
185
|
-
const
|
|
186
|
-
|
|
228
|
+
const hits = result.body.hits.hits;
|
|
229
|
+
const localities = hits.map(h => ({
|
|
230
|
+
name: h._source.locality_name
|
|
231
|
+
}));
|
|
232
|
+
const links = hits.map(h => ({
|
|
233
|
+
rel: 'related',
|
|
234
|
+
uri: `/localities/${h._source.locality_pid}`,
|
|
235
|
+
title: h._source.locality_name
|
|
187
236
|
}));
|
|
188
237
|
const body = {
|
|
189
238
|
postcode,
|
|
@@ -192,6 +241,7 @@ function startRest2Server() {
|
|
|
192
241
|
const hash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(body)).digest('hex');
|
|
193
242
|
return {
|
|
194
243
|
body,
|
|
244
|
+
links,
|
|
195
245
|
headers: {
|
|
196
246
|
etag: `"${_version.version}-${hash}"`,
|
|
197
247
|
'cache-control': `public, max-age=${ONE_WEEK}`
|
|
@@ -233,15 +283,9 @@ function startRest2Server() {
|
|
|
233
283
|
}) => {
|
|
234
284
|
const result = await (0, _addressService.getState)(abbreviation);
|
|
235
285
|
const stateName = result.body.aggregations.state_name.buckets[0]?.key || abbreviation.toUpperCase();
|
|
236
|
-
const localities = result.body.aggregations.localities.buckets.map(l => ({
|
|
237
|
-
name: l.key
|
|
238
|
-
}));
|
|
239
|
-
const postcodes = result.body.aggregations.postcodes.buckets.map(p => p.key);
|
|
240
286
|
const body = {
|
|
241
287
|
abbreviation: abbreviation.toUpperCase(),
|
|
242
|
-
name: stateName
|
|
243
|
-
localities,
|
|
244
|
-
postcodes
|
|
288
|
+
name: stateName
|
|
245
289
|
};
|
|
246
290
|
const hash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(body)).digest('hex');
|
|
247
291
|
return {
|
|
@@ -293,12 +337,199 @@ function startRest2Server() {
|
|
|
293
337
|
};
|
|
294
338
|
}
|
|
295
339
|
});
|
|
340
|
+
waycharter.registerResourceType({
|
|
341
|
+
path: '/api-docs',
|
|
342
|
+
loader: async () => {
|
|
343
|
+
const spec = {
|
|
344
|
+
openapi: '3.0.3',
|
|
345
|
+
info: {
|
|
346
|
+
title: 'Addressr by Mountain Pass',
|
|
347
|
+
description: 'Free Australian Address Validation, Search and Autocomplete. This OpenAPI spec is supplementary — the HATEOAS link-driven API is the authoritative contract.',
|
|
348
|
+
version: _version.version
|
|
349
|
+
},
|
|
350
|
+
paths: {
|
|
351
|
+
'/addresses': {
|
|
352
|
+
get: {
|
|
353
|
+
summary: 'Search Addresses',
|
|
354
|
+
operationId: 'searchAddresses',
|
|
355
|
+
parameters: [{
|
|
356
|
+
name: 'q',
|
|
357
|
+
in: 'query',
|
|
358
|
+
required: true,
|
|
359
|
+
schema: {
|
|
360
|
+
type: 'string',
|
|
361
|
+
minLength: 3
|
|
362
|
+
},
|
|
363
|
+
description: 'Address search query'
|
|
364
|
+
}],
|
|
365
|
+
responses: {
|
|
366
|
+
200: {
|
|
367
|
+
description: 'List of matching addresses'
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
'/addresses/{pid}': {
|
|
373
|
+
get: {
|
|
374
|
+
summary: 'Get Address',
|
|
375
|
+
operationId: 'getAddress',
|
|
376
|
+
parameters: [{
|
|
377
|
+
name: 'pid',
|
|
378
|
+
in: 'path',
|
|
379
|
+
required: true,
|
|
380
|
+
schema: {
|
|
381
|
+
type: 'string'
|
|
382
|
+
},
|
|
383
|
+
description: 'Address persistent identifier'
|
|
384
|
+
}],
|
|
385
|
+
responses: {
|
|
386
|
+
200: {
|
|
387
|
+
description: 'Address details with structured data'
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
'/localities': {
|
|
393
|
+
get: {
|
|
394
|
+
summary: 'Search Localities',
|
|
395
|
+
operationId: 'searchLocalities',
|
|
396
|
+
parameters: [{
|
|
397
|
+
name: 'q',
|
|
398
|
+
in: 'query',
|
|
399
|
+
required: true,
|
|
400
|
+
schema: {
|
|
401
|
+
type: 'string',
|
|
402
|
+
minLength: 2
|
|
403
|
+
},
|
|
404
|
+
description: 'Locality/suburb name search query'
|
|
405
|
+
}],
|
|
406
|
+
responses: {
|
|
407
|
+
200: {
|
|
408
|
+
description: 'List of matching localities'
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
'/localities/{pid}': {
|
|
414
|
+
get: {
|
|
415
|
+
summary: 'Get Locality',
|
|
416
|
+
operationId: 'getLocality',
|
|
417
|
+
parameters: [{
|
|
418
|
+
name: 'pid',
|
|
419
|
+
in: 'path',
|
|
420
|
+
required: true,
|
|
421
|
+
schema: {
|
|
422
|
+
type: 'string'
|
|
423
|
+
},
|
|
424
|
+
description: 'Locality persistent identifier'
|
|
425
|
+
}],
|
|
426
|
+
responses: {
|
|
427
|
+
200: {
|
|
428
|
+
description: 'Locality details'
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
'/postcodes': {
|
|
434
|
+
get: {
|
|
435
|
+
summary: 'Search Postcodes',
|
|
436
|
+
operationId: 'searchPostcodes',
|
|
437
|
+
parameters: [{
|
|
438
|
+
name: 'q',
|
|
439
|
+
in: 'query',
|
|
440
|
+
required: false,
|
|
441
|
+
schema: {
|
|
442
|
+
type: 'string'
|
|
443
|
+
},
|
|
444
|
+
description: 'Postcode prefix search query. Omit to list all postcodes.'
|
|
445
|
+
}],
|
|
446
|
+
responses: {
|
|
447
|
+
200: {
|
|
448
|
+
description: 'List of matching postcodes with associated localities'
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
'/postcodes/{postcode}': {
|
|
454
|
+
get: {
|
|
455
|
+
summary: 'Get Postcode',
|
|
456
|
+
operationId: 'getPostcode',
|
|
457
|
+
parameters: [{
|
|
458
|
+
name: 'postcode',
|
|
459
|
+
in: 'path',
|
|
460
|
+
required: true,
|
|
461
|
+
schema: {
|
|
462
|
+
type: 'string'
|
|
463
|
+
},
|
|
464
|
+
description: 'Australian postcode'
|
|
465
|
+
}],
|
|
466
|
+
responses: {
|
|
467
|
+
200: {
|
|
468
|
+
description: 'Postcode details with associated localities'
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
'/states': {
|
|
474
|
+
get: {
|
|
475
|
+
summary: 'Search States',
|
|
476
|
+
operationId: 'searchStates',
|
|
477
|
+
parameters: [{
|
|
478
|
+
name: 'q',
|
|
479
|
+
in: 'query',
|
|
480
|
+
required: false,
|
|
481
|
+
schema: {
|
|
482
|
+
type: 'string'
|
|
483
|
+
},
|
|
484
|
+
description: 'State name or abbreviation search. Omit to list all states.'
|
|
485
|
+
}],
|
|
486
|
+
responses: {
|
|
487
|
+
200: {
|
|
488
|
+
description: 'List of matching states and territories'
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
'/states/{abbreviation}': {
|
|
494
|
+
get: {
|
|
495
|
+
summary: 'Get State',
|
|
496
|
+
operationId: 'getState',
|
|
497
|
+
parameters: [{
|
|
498
|
+
name: 'abbreviation',
|
|
499
|
+
in: 'path',
|
|
500
|
+
required: true,
|
|
501
|
+
schema: {
|
|
502
|
+
type: 'string'
|
|
503
|
+
},
|
|
504
|
+
description: 'State/territory abbreviation (e.g., NSW, VIC)'
|
|
505
|
+
}],
|
|
506
|
+
responses: {
|
|
507
|
+
200: {
|
|
508
|
+
description: 'State/territory details'
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
return {
|
|
516
|
+
body: spec,
|
|
517
|
+
headers: {
|
|
518
|
+
'cache-control': `public, max-age=${ONE_WEEK}`,
|
|
519
|
+
'content-type': 'application/json'
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
});
|
|
296
524
|
waycharter.registerResourceType({
|
|
297
525
|
path: '/',
|
|
298
526
|
loader: async () => {
|
|
299
527
|
return {
|
|
300
528
|
body: {},
|
|
301
529
|
links: [...addressesType.additionalPaths, ...localitiesType.additionalPaths, ...postcodesType.additionalPaths, ...statesType.additionalPaths, {
|
|
530
|
+
rel: 'https://addressr.io/rels/api-docs',
|
|
531
|
+
uri: '/api-docs'
|
|
532
|
+
}, {
|
|
302
533
|
rel: 'https://addressr.io/rels/health',
|
|
303
534
|
uri: '/health'
|
|
304
535
|
}],
|
package/lib/version.js
CHANGED