-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservice.ts
More file actions
154 lines (129 loc) · 5.28 KB
/
service.ts
File metadata and controls
154 lines (129 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import { withServiceErrorHandling } from "../../utilities/error";
import { IFemaRiskIndexTransaction } from "./transaction";
import * as fs from "fs";
import * as path from "path";
import Papa from "papaparse";
import { FemaRiskIndexDataResult, InsertFemaRiskIndexDataInput } from "./types";
import AdmZip from "adm-zip";
export interface IFemaRiskIndexService {
updateFemaRiskIndexData(): Promise<void>;
getFemaRiskIndexData(): Promise<FemaRiskIndexDataResult>;
}
export class FemaRiskIndexService implements IFemaRiskIndexService {
private femaRiskIndexTransaction: IFemaRiskIndexTransaction;
private localDownloadPath: string = "./tmp/download.zip";
constructor(transaction: IFemaRiskIndexTransaction) {
this.femaRiskIndexTransaction = transaction;
}
async getFemaRiskIndexData(): Promise<FemaRiskIndexDataResult> {
return await this.femaRiskIndexTransaction.fetchFemaIndexData();
}
updateFemaRiskIndexData = withServiceErrorHandling(async (): Promise<void> => {
const unzipedPath = "./tmp/unziped";
await this.downloadFemaCSV();
this.unzipFile(this.localDownloadPath, unzipedPath);
const payload = await this.parseFemaCSV(unzipedPath + "/NRI_Table_Counties.csv");
await this.femaRiskIndexTransaction.dropFemaRiskIndexData();
await this.femaRiskIndexTransaction.insertFemaRiskIndexData(payload);
await this.deleteAllFilesInFolder("./tmp");
});
private async parseFemaCSV(filePath: string): Promise<InsertFemaRiskIndexDataInput> {
try {
// Read the file from the filesystem
const file = Bun.file(filePath);
const fileContent = await file.text();
// Parse the CSV content using PapaParse
const results = Papa.parse<{
STCOFIPS: string;
RISK_RATNG: string;
EAL_RATNG: string;
SOVI_RATNG: string;
RESL_RATNG: string;
CFLD_RISKR: string;
DRGT_RISKR: string;
WFIR_RISKR: string;
}>(fileContent, {
header: true,
dynamicTyping: false,
skipEmptyLines: true,
});
if (results.errors.length > 0) {
console.error("Parse errors:", results.errors);
}
return results.data.map((row) => {
return {
countyFipsCode: row.STCOFIPS,
riskRating: row.RISK_RATNG,
ealRating: row.EAL_RATNG,
socialVuln: row.SOVI_RATNG,
communityResilience: row.RESL_RATNG,
coastalFlooding: row.CFLD_RISKR,
drought: row.DRGT_RISKR,
wildFire: row.WFIR_RISKR,
};
});
} catch (error) {
console.error("Error reading or parsing file:", error);
throw error;
}
}
private async deleteAllFilesInFolder(folderPath: string): Promise<void> {
try {
if (!fs.existsSync(folderPath)) {
return;
}
const files = fs.readdirSync(folderPath);
//For each file in the directory, delete the file
for (const file of files) {
const filePath = path.join(folderPath, file);
const stat = fs.statSync(filePath);
if (stat.isFile()) {
fs.unlinkSync(filePath);
} else if (stat.isDirectory()) {
fs.rmSync(filePath, { recursive: true, force: true });
}
}
} catch (error) {
console.error("Error deleting files:", error);
throw error;
}
}
private async unzipFile(zipPath: string, outputDir: string): Promise<void> {
try {
if (!fs.existsSync(zipPath)) {
throw new Error(`Zip file not found at: ${zipPath}`);
}
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const zip = new AdmZip(zipPath);
zip.extractAllTo(outputDir, true);
} catch (error) {
console.error("Error unzipping file:", error);
throw error;
}
}
private async downloadFemaCSV(): Promise<void> {
const url =
"https://hazards.fema.gov/nri/Content/StaticDocuments/DataDownload//NRI_Table_Counties/NRI_Table_Counties.zip";
try {
// Create directory if it doesn't exist
const dir = path.dirname(this.localDownloadPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to download: ${response.status} ${response.statusText}`);
}
const arrayBuffer = await response.arrayBuffer();
await Bun.write(this.localDownloadPath, arrayBuffer);
} catch (error) {
if (fs.existsSync(this.localDownloadPath)) {
fs.unlinkSync(this.localDownloadPath);
}
console.error("Error downloading file:", error);
throw error;
}
}
}