@mountainpass/addressr 2.0.3 → 2.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.
@@ -8,9 +8,13 @@ exports.dropIndex = dropIndex;
8
8
  exports.fetchGnafFile = fetchGnafFile;
9
9
  exports.getAddress = getAddress;
10
10
  exports.getAddresses = getAddresses;
11
+ exports.getLocality = getLocality;
11
12
  exports.loadGnaf = loadGnaf;
12
13
  exports.mapAddressDetails = mapAddressDetails;
13
14
  exports.searchForAddress = searchForAddress;
15
+ exports.searchForLocality = searchForLocality;
16
+ exports.searchForPostcode = searchForPostcode;
17
+ exports.searchForState = searchForState;
14
18
  exports.setAddresses = setAddresses;
15
19
  exports.unzipFile = unzipFile;
16
20
  var _debug = _interopRequireDefault(require("debug"));
@@ -23,7 +27,7 @@ var _nodeStream = _interopRequireDefault(require("node:stream"));
23
27
  var _unzipStream = _interopRequireDefault(require("unzip-stream"));
24
28
  var _elasticsearch = require("../client/elasticsearch");
25
29
  var _streamDown = _interopRequireDefault(require("../utils/stream-down"));
26
- var _setLinkOptions = require("./setLinkOptions");
30
+ var _setLinkOptions = require("./set-link-options");
27
31
  var _keyv = require("keyv");
28
32
  var _keyvFile = require("keyv-file");
29
33
  var _nodeCrypto = _interopRequireDefault(require("node:crypto"));
@@ -54,10 +58,10 @@ const ONE_DAY_MS = 1000 * ONE_DAY_S;
54
58
  const THIRTY_DAYS_MS = ONE_DAY_MS * 30;
55
59
  const ES_INDEX_NAME = process.env.ES_INDEX_NAME || 'addressr';
56
60
  async function dropIndex() {
57
- await (0, _elasticsearch.dropIndex)(global.esClient);
61
+ await (0, _elasticsearch.dropIndex)(globalThis.esClient);
58
62
  }
59
63
  async function clearAddresses() {
60
- await (0, _elasticsearch.initIndex)(global.esClient, true);
64
+ await (0, _elasticsearch.initIndex)(globalThis.esClient, true);
61
65
  }
62
66
  async function setAddresses(addr) {
63
67
  await clearAddresses();
@@ -458,7 +462,7 @@ function mapGeo(geoSite, context, geoDefault) {
458
462
  })
459
463
  };
460
464
  }) : [];
461
- const def = geoDefault && !foundDefault ? geoDefault.map(geo => {
465
+ const defaults = geoDefault && !foundDefault ? geoDefault.map(geo => {
462
466
  return {
463
467
  default: true,
464
468
  ...(geo.GEOCODE_TYPE_CODE !== '' && {
@@ -475,7 +479,7 @@ function mapGeo(geoSite, context, geoDefault) {
475
479
  })
476
480
  };
477
481
  }) : [];
478
- return sites.concat(def);
482
+ return [...sites, ...defaults];
479
483
  }
480
484
  function mapToSla(fla) {
481
485
  return fla.join(', ');
@@ -706,6 +710,13 @@ async function loadAddressDetails(file, expectedCount, context, {
706
710
  }
707
711
  const indexingBody = [];
708
712
  for (const row of chunk.data) {
713
+ // Accumulate postcodes per locality for the locality index
714
+ if (context.postcodesByLocality && row.LOCALITY_PID && row.POSTCODE) {
715
+ if (!context.postcodesByLocality[row.LOCALITY_PID]) {
716
+ context.postcodesByLocality[row.LOCALITY_PID] = new Set();
717
+ }
718
+ context.postcodesByLocality[row.LOCALITY_PID].add(row.POSTCODE);
719
+ }
709
720
  const item = mapAddressDetails(row, context, actualCount, expectedCount);
710
721
  items.push(item);
711
722
  actualCount += 1;
@@ -819,7 +830,7 @@ async function loadAddressDetails(file, expectedCount, context, {
819
830
  }
820
831
  async function searchForAddress(searchString, p, pageSize = PAGE_SIZE) {
821
832
  // const searchString = '657 The Entrance Road'; //'2/25 TOTTERDE'; // 'UNT 2, BELCONNEN';
822
- const searchResp = await global.esClient.search({
833
+ const searchResp = await globalThis.esClient.search({
823
834
  index: ES_INDEX_NAME,
824
835
  body: {
825
836
  from: (p - 1 || 0) * pageSize,
@@ -875,6 +886,132 @@ async function searchForAddress(searchString, p, pageSize = PAGE_SIZE) {
875
886
  logger('hits', JSON.stringify(searchResp.body.hits, undefined, 2));
876
887
  return searchResp;
877
888
  }
889
+ async function searchForLocality(searchString, p, pageSize = PAGE_SIZE) {
890
+ const searchResp = await globalThis.esClient.search({
891
+ index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
892
+ body: {
893
+ from: (p - 1 || 0) * pageSize,
894
+ size: pageSize,
895
+ query: {
896
+ bool: {
897
+ ...(searchString && {
898
+ should: [{
899
+ multi_match: {
900
+ fields: ['locality_name'],
901
+ query: searchString,
902
+ fuzziness: 'AUTO',
903
+ type: 'bool_prefix',
904
+ lenient: true,
905
+ operator: 'AND'
906
+ }
907
+ }, {
908
+ multi_match: {
909
+ fields: ['locality_name'],
910
+ query: searchString,
911
+ type: 'phrase_prefix',
912
+ lenient: true,
913
+ operator: 'AND'
914
+ }
915
+ }]
916
+ })
917
+ }
918
+ },
919
+ sort: ['_score', {
920
+ 'locality_name.raw': {
921
+ order: 'asc'
922
+ }
923
+ }]
924
+ }
925
+ });
926
+ logger('locality hits', JSON.stringify(searchResp.body.hits, undefined, 2));
927
+ return searchResp;
928
+ }
929
+ async function getLocality(pid) {
930
+ const resp = await globalThis.esClient.get({
931
+ index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
932
+ id: `/localities/${pid}`
933
+ });
934
+ return resp;
935
+ }
936
+ async function searchForPostcode(searchString) {
937
+ const searchResp = await globalThis.esClient.search({
938
+ index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
939
+ body: {
940
+ from: 0,
941
+ size: 0,
942
+ query: {
943
+ bool: {
944
+ filter: [{
945
+ prefix: {
946
+ postcodes: searchString
947
+ }
948
+ }]
949
+ }
950
+ },
951
+ aggs: {
952
+ postcodes: {
953
+ terms: {
954
+ field: 'postcodes',
955
+ size: 20
956
+ },
957
+ aggs: {
958
+ localities: {
959
+ terms: {
960
+ field: 'locality_name.raw',
961
+ size: 100
962
+ }
963
+ }
964
+ }
965
+ }
966
+ }
967
+ }
968
+ });
969
+ logger('postcode hits', JSON.stringify(searchResp.body.aggregations, undefined, 2));
970
+ return searchResp;
971
+ }
972
+ async function searchForState(searchString) {
973
+ const query = searchString ? {
974
+ bool: {
975
+ should: [{
976
+ prefix: {
977
+ state_abbreviation: searchString.toUpperCase()
978
+ }
979
+ }, {
980
+ wildcard: {
981
+ state_name: `*${searchString.toUpperCase()}*`
982
+ }
983
+ }]
984
+ }
985
+ } : {
986
+ match_all: {}
987
+ };
988
+ const searchResp = await globalThis.esClient.search({
989
+ index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
990
+ body: {
991
+ from: 0,
992
+ size: 0,
993
+ query,
994
+ aggs: {
995
+ states: {
996
+ terms: {
997
+ field: 'state_abbreviation',
998
+ size: 20
999
+ },
1000
+ aggs: {
1001
+ state_name: {
1002
+ terms: {
1003
+ field: 'state_name',
1004
+ size: 1
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ });
1012
+ logger('state hits', JSON.stringify(searchResp.body.aggregations, undefined, 2));
1013
+ return searchResp;
1014
+ }
878
1015
  async function sendIndexRequest(indexingBody, initialBackoff = Number.parseInt(process.env.ADDRESSR_INDEX_BACKOFF || '30000'), {
879
1016
  refresh = false
880
1017
  } = {}) {
@@ -882,7 +1019,7 @@ async function sendIndexRequest(indexingBody, initialBackoff = Number.parseInt(p
882
1019
  // eslint-disable-next-line no-constant-condition
883
1020
  for (let count = 0; true; count++) {
884
1021
  try {
885
- const resp = await global.esClient.bulk({
1022
+ const resp = await globalThis.esClient.bulk({
886
1023
  refresh,
887
1024
  body: indexingBody,
888
1025
  timeout: process.env.ADDRESSR_INDEX_TIMEOUT || '300s'
@@ -962,17 +1099,17 @@ function buildSynonyms(context) {
962
1099
  const {
963
1100
  readdir
964
1101
  } = require('node:fs').promises;
965
- async function getFiles(currentDir, baseDir) {
966
- const dir = _nodePath.default.resolve(baseDir, currentDir);
967
- logger(`reading ${dir} (${currentDir} in ${baseDir})`);
968
- const dirents = await readdir(dir, {
1102
+ async function getFiles(currentDirectory, baseDirectory) {
1103
+ const directory = _nodePath.default.resolve(baseDirectory, currentDirectory);
1104
+ logger(`reading ${directory} (${currentDirectory} in ${baseDirectory})`);
1105
+ const dirents = await readdir(directory, {
969
1106
  withFileTypes: true
970
1107
  });
971
1108
  const files = await Promise.all(dirents.map(dirent => {
972
- const res = `${currentDir}/${dirent.name}`;
973
- return dirent.isDirectory() ? getFiles(res, baseDir) : res;
1109
+ const result = `${currentDirectory}/${dirent.name}`;
1110
+ return dirent.isDirectory() ? getFiles(result, baseDirectory) : result;
974
1111
  }));
975
- return Array.prototype.concat(...files);
1112
+ return files.flat();
976
1113
  }
977
1114
  function countFileLines(filePath) {
978
1115
  return new Promise((resolve, reject) => {
@@ -1024,11 +1161,13 @@ async function loadGnafData(directory, {
1024
1161
  // throw new Error(`Cannot file '${countsFile}' or '${contentsFile}'`)
1025
1162
  // }
1026
1163
  }
1027
- const loadContext = {};
1164
+ const loadContext = {
1165
+ postcodesByLocality: {}
1166
+ };
1028
1167
  await loadAuthFiles(files, directory, loadContext, filesCounts);
1029
1168
  // loadContext now contains all the auth files, so we can build the synonyms
1030
1169
  const synonyms = buildSynonyms(loadContext);
1031
- await (0, _elasticsearch.initIndex)(global.esClient, process.env.ES_CLEAR_INDEX || false, synonyms);
1170
+ await (0, _elasticsearch.initIndex)(globalThis.esClient, process.env.ES_CLEAR_INDEX || false, synonyms);
1032
1171
  const addressDetailFiles = files.filter(f => f.match(/ADDRESS_DETAIL/) && f.match(/\/Standard\//));
1033
1172
  logger('addressDetailFiles', addressDetailFiles);
1034
1173
  for (const detailFile of addressDetailFiles) {
@@ -1074,6 +1213,51 @@ async function loadGnafData(directory, {
1074
1213
  });
1075
1214
  }
1076
1215
  }
1216
+
1217
+ // Phase 2: Index localities (separate post-load phase)
1218
+ // Failures here must not affect address loading above
1219
+ try {
1220
+ await (0, _elasticsearch.initLocalityIndex)(globalThis.esClient, process.env.ES_CLEAR_INDEX || false, synonyms);
1221
+ const localityIndexingBody = [];
1222
+ for (const detailFile of addressDetailFiles) {
1223
+ const state = _nodePath.default.basename(detailFile, _nodePath.default.extname(detailFile)).replace(/_.*/, '');
1224
+ if (COVERED_STATES.length === 0 || COVERED_STATES.includes(state)) {
1225
+ const stateName = await loadState(files, directory, state);
1226
+ const localities = await loadLocality(files, directory, state);
1227
+ for (const l of localities) {
1228
+ if (l.LOCALITY_NAME === '') continue;
1229
+ localityIndexingBody.push({
1230
+ index: {
1231
+ _index: _elasticsearch.ES_LOCALITY_INDEX_NAME,
1232
+ _id: `/localities/${l.LOCALITY_PID}`
1233
+ }
1234
+ });
1235
+ // Derive postcodes: prefer accumulated from ADDRESS_DETAIL,
1236
+ // fall back to PRIMARY_POSTCODE from LOCALITY table
1237
+ const accumulatedPostcodes = loadContext.postcodesByLocality[l.LOCALITY_PID];
1238
+ const postcodes = accumulatedPostcodes ? [...accumulatedPostcodes] : l.PRIMARY_POSTCODE ? [l.PRIMARY_POSTCODE] : [];
1239
+ localityIndexingBody.push({
1240
+ locality_name: l.LOCALITY_NAME,
1241
+ locality_class_code: l.LOCALITY_CLASS_CODE,
1242
+ locality_class_name: localityClassCodeToName(l.LOCALITY_CLASS_CODE, loadContext),
1243
+ primary_postcode: postcodes[0] || '',
1244
+ postcodes,
1245
+ state_abbreviation: state,
1246
+ state_name: stateName,
1247
+ locality_pid: l.LOCALITY_PID
1248
+ });
1249
+ }
1250
+ }
1251
+ }
1252
+ if (localityIndexingBody.length > 0) {
1253
+ await sendIndexRequest(localityIndexingBody, undefined, {
1254
+ refresh: true
1255
+ });
1256
+ }
1257
+ logger('Locality indexing complete');
1258
+ } catch (error_) {
1259
+ error('Locality indexing failed (address loading unaffected):', error_);
1260
+ }
1077
1261
  }
1078
1262
  async function fileExists(countsFile) {
1079
1263
  try {
@@ -1306,14 +1490,14 @@ async function loadGnaf({
1306
1490
  if (contents.length === 0) {
1307
1491
  throw new Error(`Data dir '${unzipped}' is empty`);
1308
1492
  }
1309
- const gnafDir = await (0, _glob.glob)('**/G-NAF/', {
1493
+ const gnafDirectory = await (0, _glob.glob)('**/G-NAF/', {
1310
1494
  cwd: unzipped
1311
1495
  });
1312
- console.log(gnafDir);
1313
- if (gnafDir.length === 0) {
1496
+ console.log(gnafDirectory);
1497
+ if (gnafDirectory.length === 0) {
1314
1498
  throw new Error(`Cannot find 'G-NAF' directory in Data dir '${unzipped}'`);
1315
1499
  }
1316
- mainDirectory = _nodePath.default.dirname(`${unzipped}/${gnafDir[0].slice(0, -1)}`);
1500
+ mainDirectory = _nodePath.default.dirname(`${unzipped}/${gnafDirectory[0].slice(0, -1)}`);
1317
1501
  }
1318
1502
  logger('Main Data dir', mainDirectory);
1319
1503
  await loadGnafData(mainDirectory, {
@@ -1330,7 +1514,7 @@ async function loadGnaf({
1330
1514
  **/
1331
1515
  async function getAddress(addressId) {
1332
1516
  try {
1333
- const jsonX = await global.esClient.get({
1517
+ const jsonX = await globalThis.esClient.get({
1334
1518
  index: ES_INDEX_NAME,
1335
1519
  id: `/addresses/${addressId}`
1336
1520
  });
@@ -2,20 +2,20 @@
2
2
 
3
3
  var _debug = _interopRequireDefault(require("debug"));
4
4
  var _elasticsearch = require("../client/elasticsearch");
5
- var _printVersion = require("../service/printVersion");
6
- var _waycharterServer = require("./waycharterServer");
5
+ var _printVersion = require("../service/print-version");
6
+ var _waycharterServer = require("./waycharter-server");
7
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  const logger = (0, _debug.default)('api');
9
- (0, _waycharterServer.startRest2Server)().then(() => {
9
+ (0, _waycharterServer.startRest2Server)().then(async () => {
10
10
  logger('connecting es client');
11
- const p1 = (0, _elasticsearch.esConnect)().then(esClient => {
12
- global.esClient = esClient;
13
- logger('es client connected');
14
- });
15
- p1.then(() => {
16
- console.log('=======================');
17
- console.log('Addressr - API Server 2');
18
- console.log('=======================');
19
- (0, _printVersion.printVersion)();
20
- });
11
+ const esClient = await (0, _elasticsearch.esConnect)();
12
+ globalThis.esClient = esClient;
13
+ logger('es client connected');
14
+ console.log('=======================');
15
+ console.log('Addressr - API Server 2');
16
+ console.log('=======================');
17
+ (0, _printVersion.printVersion)();
18
+ }).catch(error => {
19
+ console.error('Failed to start server:', error);
20
+ throw error;
21
21
  });
@@ -107,6 +107,140 @@ function startRest2Server() {
107
107
  parameters: ['q']
108
108
  }]
109
109
  });
110
+ const localitiesType = waycharter.registerCollection({
111
+ itemPath: '/:pid',
112
+ itemLoader: async ({
113
+ pid
114
+ }) => {
115
+ const resp = await (0, _addressService.getLocality)(pid);
116
+ const source = resp.body._source;
117
+ const hash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(source)).digest('hex');
118
+ return {
119
+ body: source,
120
+ headers: {
121
+ etag: `"${_version.version}-${hash}"`,
122
+ 'cache-control': `public, max-age=${ONE_WEEK}`
123
+ },
124
+ status: 200
125
+ };
126
+ },
127
+ collectionPath: '/localities',
128
+ collectionLoader: async ({
129
+ page,
130
+ q
131
+ }) => {
132
+ if (q && q.length > 1) {
133
+ const foundLocalities = await (0, _addressService.searchForLocality)(q, page + 1, PAGE_SIZE);
134
+ const body = foundLocalities.body.hits.hits.map(h => {
135
+ return {
136
+ name: h._source.locality_name,
137
+ state: {
138
+ name: h._source.state_name,
139
+ abbreviation: h._source.state_abbreviation
140
+ },
141
+ ...(h._source.locality_class_code && {
142
+ class: {
143
+ code: h._source.locality_class_code,
144
+ name: h._source.locality_class_name
145
+ }
146
+ }),
147
+ ...(h._source.primary_postcode && {
148
+ postcode: h._source.primary_postcode
149
+ }),
150
+ score: h._score,
151
+ pid: h._id.replace('/localities/', '')
152
+ };
153
+ });
154
+ const responseHash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(body)).digest('hex');
155
+ return {
156
+ body,
157
+ hasMore: page < foundLocalities.body.hits.total.value / PAGE_SIZE - 1,
158
+ headers: {
159
+ etag: `"${_version.version}-${responseHash}"`,
160
+ 'cache-control': `public, max-age=${ONE_WEEK}`
161
+ }
162
+ };
163
+ } else {
164
+ return {
165
+ body: [],
166
+ hasMore: false,
167
+ headers: {
168
+ etag: `"${_version.version}"`,
169
+ 'cache-control': `public, max-age=${ONE_WEEK}`
170
+ }
171
+ };
172
+ }
173
+ },
174
+ filters: [{
175
+ rel: 'https://addressr.io/rels/locality-search',
176
+ parameters: ['q']
177
+ }]
178
+ });
179
+ const postcodesType = waycharter.registerCollection({
180
+ collectionPath: '/postcodes',
181
+ collectionLoader: async ({
182
+ q
183
+ }) => {
184
+ if (q && q.length > 2) {
185
+ const result = await (0, _addressService.searchForPostcode)(q);
186
+ const buckets = result.body.aggregations.postcodes.buckets;
187
+ const body = buckets.map(bucket => ({
188
+ postcode: bucket.key,
189
+ localities: bucket.localities.buckets.map(l => ({
190
+ name: l.key
191
+ }))
192
+ }));
193
+ const responseHash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(body)).digest('hex');
194
+ return {
195
+ body,
196
+ hasMore: false,
197
+ headers: {
198
+ etag: `"${_version.version}-${responseHash}"`,
199
+ 'cache-control': `public, max-age=${ONE_WEEK}`
200
+ }
201
+ };
202
+ } else {
203
+ return {
204
+ body: [],
205
+ hasMore: false,
206
+ headers: {
207
+ etag: `"${_version.version}"`,
208
+ 'cache-control': `public, max-age=${ONE_WEEK}`
209
+ }
210
+ };
211
+ }
212
+ },
213
+ filters: [{
214
+ rel: 'https://addressr.io/rels/postcode-search',
215
+ parameters: ['q']
216
+ }]
217
+ });
218
+ const statesType = waycharter.registerCollection({
219
+ collectionPath: '/states',
220
+ collectionLoader: async ({
221
+ q
222
+ }) => {
223
+ const result = await (0, _addressService.searchForState)(q && q.length > 1 ? q : undefined);
224
+ const buckets = result.body.aggregations.states.buckets;
225
+ const body = buckets.map(bucket => ({
226
+ abbreviation: bucket.key,
227
+ name: bucket.state_name.buckets[0]?.key || bucket.key
228
+ }));
229
+ const responseHash = _nodeCrypto.default.createHash('md5').update(JSON.stringify(body)).digest('hex');
230
+ return {
231
+ body,
232
+ hasMore: false,
233
+ headers: {
234
+ etag: `"${_version.version}-${responseHash}"`,
235
+ 'cache-control': `public, max-age=${ONE_WEEK}`
236
+ }
237
+ };
238
+ },
239
+ filters: [{
240
+ rel: 'https://addressr.io/rels/state-search',
241
+ parameters: ['q']
242
+ }]
243
+ });
110
244
  waycharter.registerResourceType({
111
245
  path: '/health',
112
246
  loader: async () => {
@@ -127,7 +261,7 @@ function startRest2Server() {
127
261
  loader: async () => {
128
262
  return {
129
263
  body: {},
130
- links: [...addressesType.additionalPaths, {
264
+ links: [...addressesType.additionalPaths, ...localitiesType.additionalPaths, ...postcodesType.additionalPaths, ...statesType.additionalPaths, {
131
265
  rel: 'https://addressr.io/rels/health',
132
266
  uri: '/health'
133
267
  }],
package/lib/swagger.js CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.startServer = startServer;
7
7
  exports.stopServer = stopServer;
8
- exports.swaggerDoc = void 0;
8
+ exports.swaggerDocument = void 0;
9
9
  exports.swaggerInit = swaggerInit;
10
10
  var _debug = _interopRequireDefault(require("debug"));
11
11
  var _express = _interopRequireDefault(require("express"));
@@ -32,12 +32,12 @@ var options = {
32
32
 
33
33
  // The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
34
34
  var spec = (0, _nodeFs.readFileSync)(_nodePath.default.join(__dirname, 'api/swagger.yaml'), 'utf8');
35
- var swaggerDoc = exports.swaggerDoc = (0, _jsYaml.load)(spec);
36
- global.swaggerDoc = swaggerDoc;
35
+ var swaggerDocument = exports.swaggerDocument = (0, _jsYaml.load)(spec);
36
+ globalThis.swaggerDocument = swaggerDocument;
37
37
  function swaggerInit() {
38
38
  // Initialize the Swagger middleware
39
39
  return new Promise(resolve => {
40
- (0, _swaggerTools.initializeMiddleware)(swaggerDoc, function (middleware) {
40
+ (0, _swaggerTools.initializeMiddleware)(swaggerDocument, function (middleware) {
41
41
  // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
42
42
  const metaData = middleware.swaggerMetadata();
43
43
  app.use(metaData);
@@ -55,7 +55,7 @@ function swaggerInit() {
55
55
  // apiDocs: '/api-docs',
56
56
  // swaggerUi: '/docs',
57
57
  }));
58
- app.use(function (error_, request, res, next) {
58
+ app.use(function (error_, request, response, next) {
59
59
  if (error_.failedValidation) {
60
60
  // handle validation errror
61
61
  const rehydratedError = Object.assign({}, error_);
@@ -70,13 +70,13 @@ function swaggerInit() {
70
70
  delete rehydratedError.results;
71
71
  }
72
72
  error('error!!!', error_.message, JSON.stringify(rehydratedError, undefined, 2));
73
- res.status(error_.code === 'SCHEMA_VALIDATION_FAILED' ? '500' : '400').json(rehydratedError);
73
+ response.status(error_.code === 'SCHEMA_VALIDATION_FAILED' ? '500' : '400').json(rehydratedError);
74
74
  } else {
75
75
  next();
76
76
  }
77
77
  });
78
- global.swaggerApp = app;
79
- global.swaggerMiddleware = middleware;
78
+ globalThis.swaggerApp = app;
79
+ globalThis.swaggerMiddleware = middleware;
80
80
  resolve({
81
81
  app,
82
82
  middleware
@@ -2,21 +2,19 @@
2
2
 
3
3
  var _progress = _interopRequireDefault(require("progress"));
4
4
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
5
- const {
6
- parse
7
- } = require('node:url');
8
5
  const http = require('node:https');
9
6
  const fs = require('node:fs');
10
7
  const pathUtil = require('node:path');
11
- module.exports = function (url, path, size) {
12
- const uri = parse(url);
8
+ module.exports = function streamDown(url, path, size) {
9
+ const uri = new URL(url);
13
10
  if (!path) {
14
- path = pathUtil.basename(uri.path);
11
+ path = pathUtil.basename(uri.pathname);
15
12
  }
16
- const file = fs.createWriteStream(path);
13
+ const file = fs.createWriteStream(path); // eslint-disable-line security/detect-non-literal-fs-filename -- path is internal
14
+
17
15
  return new Promise(function (resolve, reject) {
18
- http.get(uri.href).on('response', function (res) {
19
- const length = res.headers['content-length'] ? Number.parseInt(res.headers['content-length'], 10) : size;
16
+ http.get(uri.toString()).on('response', function (response) {
17
+ const length = response.headers['content-length'] ? Number.parseInt(response.headers['content-length'], 10) : size;
20
18
  // let downloaded = 0;
21
19
  // let percent = 0;
22
20
  var bar = new _progress.default(' downloading [:bar] :rate/bps :percent :etas', {
@@ -25,7 +23,7 @@ module.exports = function (url, path, size) {
25
23
  width: 20,
26
24
  total: length
27
25
  });
28
- res.on('data', function (chunk) {
26
+ response.on('data', function (chunk) {
29
27
  file.write(chunk);
30
28
  // downloaded += chunk.length;
31
29
  //percent = ((100.0 * downloaded) / len).toFixed(2);
@@ -39,8 +37,8 @@ module.exports = function (url, path, size) {
39
37
  // );
40
38
  }).on('end', function () {
41
39
  file.end();
42
- console.log(`\n${uri.path} downloaded to: ${path}`);
43
- resolve(res);
40
+ console.log(`\n${uri.pathname} downloaded to: ${path}`);
41
+ resolve(response);
44
42
  }).on('error', function (error) {
45
43
  reject(error);
46
44
  });
package/lib/version.js CHANGED
@@ -5,4 +5,4 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = void 0;
7
7
  // Generated by genversion.
8
- const version = exports.version = '2.0.3';
8
+ const version = exports.version = '2.1.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mountainpass/addressr",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "Australian Address Validation, Search and Autocomplete",
5
5
  "author": {
6
6
  "name": "Mountain Pass",
@@ -7,5 +7,5 @@ if (!satisfies(process.version, version)) {
7
7
  console.log(
8
8
  `Required node version ${version} not satisfied with current version ${process.version}.`,
9
9
  );
10
- process.exit(1);
10
+ process.exit(1); // eslint-disable-line no-process-exit, n/no-process-exit -- postinstall version check
11
11
  }