|
| 1 | +import fs from "fs"; |
| 2 | +import { join } from "path"; |
| 3 | +import { sql } from "kysely"; |
| 4 | +import { AreaSetCode } from "@/server/models/AreaSet"; |
| 5 | +import { |
| 6 | + createAreaSet, |
| 7 | + findAreaSetByCode, |
| 8 | +} from "@/server/repositories/AreaSet"; |
| 9 | +import { db } from "@/server/services/database"; |
| 10 | +import logger from "@/server/services/logger"; |
| 11 | +import { getBaseDir } from "@/server/utils"; |
| 12 | + |
| 13 | +const AREA_SET_CODE = AreaSetCode.UKC24; |
| 14 | + |
| 15 | +const importCountries = async () => { |
| 16 | + const countriesGeojsonPath = join( |
| 17 | + getBaseDir(), |
| 18 | + "resources", |
| 19 | + "areaSets", |
| 20 | + "countries.geojson", |
| 21 | + ); |
| 22 | + if (!fs.existsSync(countriesGeojsonPath)) { |
| 23 | + logger.error( |
| 24 | + `File not found: ${countriesGeojsonPath}. Download from https://www.data.gov.uk/dataset/c0ebe11c-0c81-4eed-81b3-a0394d4116a9/countries-december-2024-boundaries-uk-bgc1`, |
| 25 | + ); |
| 26 | + return; |
| 27 | + } |
| 28 | + let areaSet = await findAreaSetByCode(AREA_SET_CODE); |
| 29 | + if (!areaSet) { |
| 30 | + areaSet = await createAreaSet({ |
| 31 | + name: "UK Countries", |
| 32 | + code: AREA_SET_CODE, |
| 33 | + }); |
| 34 | + logger.info(`Inserted area set ${AREA_SET_CODE}`); |
| 35 | + } else { |
| 36 | + logger.info(`Using area set ${AREA_SET_CODE}`); |
| 37 | + } |
| 38 | + const geojson = fs.readFileSync(countriesGeojsonPath, "utf8"); |
| 39 | + const areas = JSON.parse(geojson) as { |
| 40 | + features: { |
| 41 | + properties: { CTRY24NM: string; CTRY24CD: string }; |
| 42 | + geometry: unknown; |
| 43 | + }[]; |
| 44 | + }; |
| 45 | + const count = areas.features.length; |
| 46 | + for (let i = 0; i < count; i++) { |
| 47 | + const feature = areas.features[i]; |
| 48 | + const code = feature.properties.CTRY24CD; |
| 49 | + const name = feature.properties.CTRY24NM; |
| 50 | + await sql`INSERT INTO area (name, code, geography, area_set_id) |
| 51 | + VALUES ( |
| 52 | + ${name}, |
| 53 | + ${code}, |
| 54 | + ST_Transform( |
| 55 | + ST_SetSRID( |
| 56 | + ST_GeomFromGeoJSON(${JSON.stringify(feature.geometry)}), |
| 57 | + 27700 -- Set the original EPSG:27700 (British National Grid) |
| 58 | + ), |
| 59 | + 4326 -- Convert to WGS 84 |
| 60 | + )::geography, |
| 61 | + ${areaSet.id} |
| 62 | + ) |
| 63 | + ON CONFLICT (code, area_set_id) DO UPDATE SET geography = EXCLUDED.geography; |
| 64 | + `.execute(db); |
| 65 | + |
| 66 | + const percentComplete = Math.floor((i * 100) / count); |
| 67 | + logger.info(`Inserted area ${code}. ${percentComplete}% complete`); |
| 68 | + } |
| 69 | +}; |
| 70 | + |
| 71 | +export default importCountries; |
0 commit comments