text-to-map 1.1.13 → 1.1.16

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { importCities } from "../open-data-sync/cities";
2
+ import { defaultBinOptions } from "./constants";
3
+ importCities(defaultBinOptions)
4
+ .then(() => {
5
+ console.log("Completed");
6
+ })
7
+ .catch((error) => {
8
+ console.log(error);
9
+ });
@@ -36,7 +36,6 @@ function main() {
36
36
  };
37
37
  console.time("downloadAndImportAllLatestAddressPoints");
38
38
  const { municipality } = yield getNewMunicipality("Česká Lípa");
39
- console.log(municipality.founder.schools[0].locations);
40
39
  const addressPoints = yield parseOrdinanceToAddressPoints(lines, {
41
40
  // currentMunicipality: municipality,
42
41
  }, reportErrors, reportWarnings);
@@ -11,7 +11,7 @@ import { AddressPointType, createSingleLineAddress } from "czech-address";
11
11
  import { SeriesType, isNegativeSeriesSpec, isRange, isSeriesSpecArray, } from "../street-markdown/types";
12
12
  import { findClosestString } from "../utils/helpers";
13
13
  import jtsk2wgs84 from "../utils/jtsk2wgs84";
14
- import { extractKeyValuesPairs, generate2DPlaceholders, getKnexDb, insertMultipleRows, isMysql, isSqlite, nonEmptyOrNull, } from "./db";
14
+ import { extractKeyValuesPairs, generate2DPlaceholders, getKnexDb, insertMultipleRows, isMysql, isSqlite, nonEmptyOrNull, rawQuery, } from "./db";
15
15
  import { getFounderCityCode } from "./founders";
16
16
  import { MunicipalityType } from "./types";
17
17
  const DescriptiveType = "č.p.";
@@ -80,7 +80,7 @@ export const commitAddressPoints = (buffer) => __awaiter(void 0, void 0, void 0,
80
80
  });
81
81
  const placeHolders = generate2DPlaceholders(columnNames.length, buffer.length);
82
82
  const knex = getKnexDb();
83
- yield knex.raw(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO address_point (${columnNames.join(",")}) VALUES ${placeHolders} ${!isMysql(knex) ? "ON CONFLICT (id) DO NOTHING" : ""}`, params);
83
+ yield rawQuery(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO address_point (${columnNames.join(",")}) VALUES ${placeHolders} ${!isMysql(knex) ? "ON CONFLICT (id) DO NOTHING" : ""}`, params);
84
84
  return buffer.length;
85
85
  });
86
86
  export const insertCities = (buffer) => __awaiter(void 0, void 0, void 0, function* () {
@@ -129,8 +129,7 @@ const addressPointSelect = `
129
129
  LEFT JOIN prague_district p ON a.prague_district_code = p.code
130
130
  LEFT JOIN municipality_part m ON a.municipality_part_code = m.code`;
131
131
  export const getAddressPointById = (addressPointId) => __awaiter(void 0, void 0, void 0, function* () {
132
- const knex = getKnexDb();
133
- const row = yield knex.raw(`${addressPointSelect}
132
+ const row = yield rawQuery(`${addressPointSelect}
134
133
  WHERE a.id = ?`, [addressPointId]);
135
134
  if (row.length === 0) {
136
135
  return null;
@@ -144,7 +143,7 @@ export const checkStreetExists = (streetName, founder) => __awaiter(void 0, void
144
143
  const errors = [];
145
144
  // we check the whole city
146
145
  const cityCode = yield getFounderCityCode(founder);
147
- const rowList = yield knex.raw(`SELECT name AS street_name
146
+ const rowList = yield rawQuery(`SELECT name AS street_name
148
147
  FROM street
149
148
  WHERE city_code = ? AND name = ? ${isSqlite(knex) ? "COLLATE NOCASE" : ""}`, [cityCode, streetName]);
150
149
  if (rowList.length > 0) {
@@ -207,7 +206,7 @@ export const findAddressPoints = (params) => __awaiter(void 0, void 0, void 0, f
207
206
  (params.type === FindAddressPointsType.WholeMunicipalityNoStreetName
208
207
  ? " AND a.street_code IS NULL"
209
208
  : "");
210
- const queryResult = yield knex.raw(`SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
209
+ const queryResult = yield rawQuery(`SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
211
210
  a.orientational_number, a.orientational_number_letter, c.name AS city_name,
212
211
  d.name AS district_name, m.name AS municipality_part_name, p.name AS prague_district_name,
213
212
  a.postal_code, a.wgs84_latitude, a.wgs84_longitude
@@ -0,0 +1,2 @@
1
+ export declare const insertCityPositions: (data: string[][]) => Promise<number>;
2
+ export declare const insertCities: (buffer: string[][]) => Promise<number>;
@@ -0,0 +1,48 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import chunk from "lodash/chunk";
11
+ import { extractKeyValuesPairs, insertMultipleRows, rawQuery } from "./db";
12
+ const citiesColumn = {
13
+ cityName: 0,
14
+ cityCode: 1,
15
+ countyName: 2,
16
+ countyCode: 3,
17
+ regionName: 4,
18
+ regionCode: 5,
19
+ postalCode: 6,
20
+ latitude: 7,
21
+ longitude: 8,
22
+ };
23
+ export const insertCityPositions = (data) => __awaiter(void 0, void 0, void 0, function* () {
24
+ let changes = 0;
25
+ // cities are most likely already inserted, but in case they're not,
26
+ // we need to insert them before updating them with region data
27
+ changes += yield insertCities(data);
28
+ const prev = changes;
29
+ for (const arrayChunk of chunk(data, 1000)) {
30
+ const queries = [];
31
+ for (const row of arrayChunk) {
32
+ queries.push(rawQuery(`UPDATE city SET wgs84_latitude = ?, wgs84_longitude = ? WHERE code = ?`, [
33
+ row[citiesColumn.latitude],
34
+ row[citiesColumn.longitude],
35
+ row[citiesColumn.cityCode],
36
+ ]));
37
+ }
38
+ yield Promise.all(queries);
39
+ changes += queries.length;
40
+ console.log(`Done ${changes - prev} / ${data.length} rows...`);
41
+ }
42
+ return changes;
43
+ });
44
+ export const insertCities = (buffer) => __awaiter(void 0, void 0, void 0, function* () {
45
+ return yield insertMultipleRows(extractKeyValuesPairs(buffer, citiesColumn.cityCode, [
46
+ citiesColumn.cityName,
47
+ ]), "city", ["code", "name"]);
48
+ });
package/dist/db/db.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare const initDb: (config?: Partial<DbConfig>) => Promise<Knex>;
20
20
  export declare const clearDb: (config?: Partial<DbConfig>) => Promise<Knex>;
21
21
  export declare const disconnectKnex: () => Promise<void>;
22
22
  export declare const nonEmptyOrNull: (value: string) => string | null;
23
+ export declare const rawQuery: (query: string, ...bindings: readonly Knex.RawBinding[]) => Promise<any[]>;
23
24
  /**
24
25
  * Efficiently insert multiple rows. If preventDuplicatesByFirstColumn is true, the first
25
26
  * column should be unique (PK or UNIQUE).
package/dist/db/db.js CHANGED
@@ -57,6 +57,7 @@ export const getKnexDb = (config = {}) => {
57
57
  client: DbClient[SupportedDbType.postgres],
58
58
  connection: _knexDbConfig.pgConnectionString,
59
59
  useNullAsDefault: true,
60
+ debug: _knexDbConfig.verbose,
60
61
  });
61
62
  }
62
63
  else if (_knexDbConfig.dbType === SupportedDbType.mysql) {
@@ -71,6 +72,7 @@ export const getKnexDb = (config = {}) => {
71
72
  database,
72
73
  },
73
74
  useNullAsDefault: true,
75
+ debug: _knexDbConfig.verbose,
74
76
  });
75
77
  }
76
78
  else {
@@ -141,6 +143,11 @@ const getEnvConfig = () => {
141
143
  export const nonEmptyOrNull = (value) => {
142
144
  return value ? value : null;
143
145
  };
146
+ export const rawQuery = (query, ...bindings) => __awaiter(void 0, void 0, void 0, function* () {
147
+ const knex = getKnexDb();
148
+ const result = yield knex.raw(query, ...bindings);
149
+ return isMysql(knex) ? result[0] : result;
150
+ });
144
151
  /**
145
152
  * Efficiently insert multiple rows. If preventDuplicatesByFirstColumn is true, the first
146
153
  * column should be unique (PK or UNIQUE).
@@ -152,7 +159,7 @@ export const insertMultipleRows = (rows, table, columnNames, preventDuplicates =
152
159
  const insertPlaceholders = generate2DPlaceholders(columnNames.length, rows.length);
153
160
  const knex = getKnexDb();
154
161
  const onConfict = preventDuplicates && !isMysql(knex) ? `ON CONFLICT DO NOTHING` : "";
155
- yield knex.raw(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO ${table} (${columnNames.join(",")}) VALUES ${insertPlaceholders} ${onConfict}`, rows.flat());
162
+ yield rawQuery(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO ${table} (${columnNames.join(",")}) VALUES ${insertPlaceholders} ${onConfict}`, rows.flat());
156
163
  return rows.length;
157
164
  });
158
165
  /**
@@ -0,0 +1,25 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ export function up(knex) {
11
+ return __awaiter(this, void 0, void 0, function* () {
12
+ yield knex.schema.alterTable("city", (t) => {
13
+ t.double("wgs84_latitude").nullable();
14
+ t.double("wgs84_longitude").nullable();
15
+ });
16
+ });
17
+ }
18
+ export function down(knex) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ yield knex.schema.alterTable("city", (t) => {
21
+ t.dropColumn("wgs84_latitude");
22
+ t.dropColumn("wgs84_longitude");
23
+ });
24
+ });
25
+ }
@@ -47,5 +47,6 @@ export declare enum SyncPart {
47
47
  AddressPoints = "address-points",
48
48
  Schools = "schools",
49
49
  Regions = "regions",
50
- Streets = "streets"
50
+ Streets = "streets",
51
+ Cities = "cities"
51
52
  }
package/dist/db/types.js CHANGED
@@ -16,4 +16,5 @@ export var SyncPart;
16
16
  SyncPart["Schools"] = "schools";
17
17
  SyncPart["Regions"] = "regions";
18
18
  SyncPart["Streets"] = "streets";
19
+ SyncPart["Cities"] = "cities";
19
20
  })(SyncPart || (SyncPart = {}));
package/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { clearDb, initDb } from "./db/db";
2
2
  import { downloadAndImportAddressPoints } from "./open-data-sync/address-points";
3
+ import { importCities } from "./open-data-sync/cities";
3
4
  import { downloadAndImportRegions } from "./open-data-sync/regions";
4
5
  import { downloadAndImportSchools } from "./open-data-sync/schools";
5
6
  import { downloadAndImportStreets } from "./open-data-sync/streets";
6
7
  import { OpenDataSyncOptionsPartial } from "./utils/helpers";
7
- export * from "./street-markdown/types";
8
8
  export * from "./street-markdown/smd";
9
+ export * from "./street-markdown/types";
9
10
  /**
10
11
  * Download and import all open data to SQLite DB. The DB file will be located
11
12
  * in the `dataDir` folder.
@@ -18,4 +19,4 @@ export * from "./street-markdown/smd";
18
19
  * ```
19
20
  */
20
21
  export declare function downloadAndImportEverything(options?: OpenDataSyncOptionsPartial, syncStreets?: boolean): Promise<void>;
21
- export { initDb, downloadAndImportAddressPoints, clearDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions, };
22
+ export { clearDb, downloadAndImportAddressPoints, downloadAndImportRegions, downloadAndImportSchools, downloadAndImportStreets, importCities, initDb, };
package/dist/index.js CHANGED
@@ -8,12 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { clearDb, initDb } from "./db/db";
11
- import { downloadAndImportAddressPoints, } from "./open-data-sync/address-points";
11
+ import { downloadAndImportAddressPoints } from "./open-data-sync/address-points";
12
+ import { importCities } from "./open-data-sync/cities";
12
13
  import { downloadAndImportRegions } from "./open-data-sync/regions";
13
14
  import { downloadAndImportSchools } from "./open-data-sync/schools";
14
15
  import { downloadAndImportStreets } from "./open-data-sync/streets";
15
- export * from "./street-markdown/types";
16
16
  export * from "./street-markdown/smd";
17
+ export * from "./street-markdown/types";
17
18
  /**
18
19
  * Download and import all open data to SQLite DB. The DB file will be located
19
20
  * in the `dataDir` folder.
@@ -31,9 +32,10 @@ export function downloadAndImportEverything(options = {}, syncStreets = true) {
31
32
  yield downloadAndImportAddressPoints(options);
32
33
  yield downloadAndImportSchools(options);
33
34
  yield downloadAndImportRegions(options);
35
+ yield importCities(options);
34
36
  if (syncStreets) {
35
37
  yield downloadAndImportStreets(options);
36
38
  }
37
39
  });
38
40
  }
39
- export { initDb, downloadAndImportAddressPoints, clearDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions, };
41
+ export { clearDb, downloadAndImportAddressPoints, downloadAndImportRegions, downloadAndImportSchools, downloadAndImportStreets, importCities, initDb, };
@@ -0,0 +1,2 @@
1
+ import { OpenDataSyncOptionsPartial } from "../utils/helpers";
2
+ export declare const importCities: (options?: OpenDataSyncOptionsPartial) => Promise<void>;
@@ -0,0 +1,40 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { parse } from "csv-parse";
11
+ import iconv from "iconv-lite";
12
+ import { pipeline } from "stream/promises";
13
+ import { SyncPart } from "../db/types";
14
+ import { prepareOptions, } from "../utils/helpers";
15
+ import { runSyncPart } from "./common";
16
+ import { createReadStream } from "fs";
17
+ import { insertCityPositions } from "../db/cities";
18
+ import { fileURLToPath } from "url";
19
+ import { dirname, join } from "path";
20
+ const importDataToDb = (options) => __awaiter(void 0, void 0, void 0, function* () {
21
+ console.log("Starting to parse CSV file...");
22
+ const __filename = fileURLToPath(import.meta.url);
23
+ const __dirname = dirname(__filename);
24
+ // source: https://github.com/33bcdd/souradnice-mest/blob/master/souradnice.csv
25
+ const csvStream = createReadStream(join(__dirname, "..", "souradnice.csv"));
26
+ const rows = [];
27
+ const parseStream = parse({ delimiter: ",", fromLine: 2 }).on("data", (data) => {
28
+ rows.push(data);
29
+ });
30
+ yield pipeline(csvStream, iconv.decodeStream("utf-8"), parseStream);
31
+ console.log("Parsing completed. Starting to import data to DB...");
32
+ yield insertCityPositions(rows);
33
+ console.log(`Import completed. Total imported rows: ${rows.length}`);
34
+ });
35
+ export const importCities = (options = {}) => __awaiter(void 0, void 0, void 0, function* () {
36
+ yield runSyncPart(SyncPart.Regions, [], () => __awaiter(void 0, void 0, void 0, function* () {
37
+ const completeOptions = prepareOptions(options);
38
+ yield importDataToDb(completeOptions);
39
+ }));
40
+ });