@fin.cx/opendata 3.5.1 → 4.0.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.
Files changed (87) hide show
  1. package/{npmextra.json → .smartconfig.json} +24 -18
  2. package/dist_ts/00_commitinfo_data.js +3 -3
  3. package/dist_ts/handelsregister/classes.handelsregisterclient.d.ts +64 -0
  4. package/dist_ts/handelsregister/classes.handelsregisterclient.js +397 -0
  5. package/dist_ts/handelsregister/classes.handelsregistererror.d.ts +56 -0
  6. package/dist_ts/handelsregister/classes.handelsregistererror.js +37 -0
  7. package/dist_ts/handelsregister/classes.portalsession.d.ts +46 -0
  8. package/dist_ts/handelsregister/classes.portalsession.js +160 -0
  9. package/dist_ts/handelsregister/classes.slidingwindowgate.d.ts +32 -0
  10. package/dist_ts/handelsregister/classes.slidingwindowgate.js +55 -0
  11. package/dist_ts/handelsregister/constants.d.ts +13 -0
  12. package/dist_ts/handelsregister/constants.js +19 -0
  13. package/dist_ts/handelsregister/data.codelists.d.ts +29 -0
  14. package/dist_ts/handelsregister/data.codelists.js +616 -0
  15. package/dist_ts/handelsregister/forms.d.ts +27 -0
  16. package/dist_ts/handelsregister/forms.js +77 -0
  17. package/dist_ts/handelsregister/html.d.ts +26 -0
  18. package/dist_ts/handelsregister/html.js +82 -0
  19. package/dist_ts/handelsregister/index.d.ts +9 -0
  20. package/dist_ts/handelsregister/index.js +10 -0
  21. package/dist_ts/handelsregister/interfaces.d.ts +240 -0
  22. package/dist_ts/handelsregister/interfaces.js +2 -0
  23. package/dist_ts/handelsregister/parse.searchresults.d.ts +35 -0
  24. package/dist_ts/handelsregister/parse.searchresults.js +175 -0
  25. package/dist_ts/handelsregister/parse.structuredcontent.d.ts +6 -0
  26. package/dist_ts/handelsregister/parse.structuredcontent.js +306 -0
  27. package/dist_ts/handelsregister/plugins.d.ts +4 -0
  28. package/dist_ts/handelsregister/plugins.js +8 -0
  29. package/dist_ts/handelsregister/references.d.ts +34 -0
  30. package/dist_ts/handelsregister/references.js +76 -0
  31. package/dist_ts/index.d.ts +0 -1
  32. package/dist_ts/index.js +1 -2
  33. package/dist_ts/plugins.d.ts +2 -14
  34. package/dist_ts/plugins.js +8 -16
  35. package/dist_ts/stocks/classes.baseproviderservice.js +8 -8
  36. package/dist_ts/stocks/classes.fundamentalsservice.js +9 -9
  37. package/dist_ts/stocks/classes.stockdataservice.js +23 -23
  38. package/dist_ts/stocks/classes.stockservice.js +9 -9
  39. package/dist_ts/stocks/providers/provider.coingecko.d.ts +1 -1
  40. package/dist_ts/stocks/providers/provider.coingecko.js +45 -39
  41. package/dist_ts/stocks/providers/provider.marketstack.d.ts +3 -3
  42. package/dist_ts/stocks/providers/provider.marketstack.js +20 -16
  43. package/dist_ts/stocks/providers/provider.secedgar.d.ts +1 -1
  44. package/dist_ts/stocks/providers/provider.secedgar.js +22 -22
  45. package/dist_ts/stocks/providers/provider.yahoo.d.ts +2 -2
  46. package/dist_ts/stocks/providers/provider.yahoo.js +14 -13
  47. package/package.json +30 -31
  48. package/readme.md +327 -676
  49. package/ts/00_commitinfo_data.ts +2 -2
  50. package/ts/handelsregister/classes.handelsregisterclient.ts +474 -0
  51. package/ts/handelsregister/classes.handelsregistererror.ts +82 -0
  52. package/ts/handelsregister/classes.portalsession.ts +191 -0
  53. package/ts/handelsregister/classes.slidingwindowgate.ts +74 -0
  54. package/ts/handelsregister/constants.ts +30 -0
  55. package/ts/handelsregister/data.codelists.ts +640 -0
  56. package/ts/handelsregister/forms.ts +99 -0
  57. package/ts/handelsregister/html.ts +113 -0
  58. package/ts/handelsregister/index.ts +27 -0
  59. package/ts/handelsregister/interfaces.ts +272 -0
  60. package/ts/handelsregister/parse.searchresults.ts +241 -0
  61. package/ts/handelsregister/parse.structuredcontent.ts +338 -0
  62. package/ts/handelsregister/plugins.ts +15 -0
  63. package/ts/handelsregister/references.ts +115 -0
  64. package/ts/index.ts +0 -1
  65. package/ts/plugins.ts +9 -29
  66. package/ts/stocks/classes.fundamentalsservice.ts +1 -1
  67. package/ts/stocks/classes.stockdataservice.ts +17 -7
  68. package/ts/stocks/classes.stockservice.ts +2 -2
  69. package/ts/stocks/providers/provider.marketstack.ts +9 -7
  70. package/ts/stocks/providers/provider.secedgar.ts +2 -2
  71. package/ts/stocks/providers/provider.yahoo.ts +3 -3
  72. package/dist_ts/classes.businessrecord.d.ts +0 -38
  73. package/dist_ts/classes.businessrecord.js +0 -47
  74. package/dist_ts/classes.germanbusinessdata.d.ts +0 -9
  75. package/dist_ts/classes.germanbusinessdata.js +0 -78
  76. package/dist_ts/classes.handelsregister.d.ts +0 -132
  77. package/dist_ts/classes.handelsregister.js +0 -288
  78. package/dist_ts/classes.jsonldata.d.ts +0 -43
  79. package/dist_ts/classes.jsonldata.js +0 -65
  80. package/dist_ts/classes.main.opendata.d.ts +0 -24
  81. package/dist_ts/classes.main.opendata.js +0 -58
  82. package/readme.hints.md +0 -89
  83. package/readme.plan.md +0 -193
  84. package/ts/classes.businessrecord.ts +0 -67
  85. package/ts/classes.handelsregister.ts +0 -360
  86. package/ts/classes.jsonldata.ts +0 -113
  87. package/ts/classes.main.opendata.ts +0 -87
@@ -1,360 +0,0 @@
1
- import type { BusinessRecord } from './classes.businessrecord.js';
2
- import type { OpenData } from './classes.main.opendata.js';
3
- import * as plugins from './plugins.js';
4
-
5
- /**
6
- * the HandlesRegister exposed as a class
7
- */
8
- export class HandelsRegister {
9
- private openDataRef: OpenData;
10
- private asyncExecutionStack = new plugins.lik.AsyncExecutionStack();
11
- private downloadDir: string;
12
- private uniqueDowloadFolder: string;
13
-
14
- // Puppeteer wrapper instance
15
- public smartbrowserInstance = new plugins.smartbrowser.SmartBrowser();
16
-
17
- constructor(openDataRef: OpenData, downloadDirArg: string) {
18
- this.openDataRef = openDataRef;
19
- this.downloadDir = downloadDirArg;
20
- this.uniqueDowloadFolder = plugins.path.join(this.downloadDir, plugins.smartunique.uniSimple());
21
- }
22
-
23
- public async start() {
24
- // Start the browser
25
- await plugins.smartfile.fs.ensureDir(this.uniqueDowloadFolder);
26
- await this.smartbrowserInstance.start();
27
- }
28
-
29
- public async stop() {
30
- // Stop the browser
31
- await plugins.smartfile.fs.remove(this.uniqueDowloadFolder);
32
- await this.smartbrowserInstance.stop();
33
- }
34
-
35
- /**
36
- * Creates a new page and configures it to allow file downloads
37
- * to a predefined path.
38
- */
39
- public getNewPage = async () => {
40
- const page = await this.smartbrowserInstance.headlessBrowser.newPage();
41
-
42
- // 1) Create a DevTools session for this page
43
- const cdpSession = await page.target().createCDPSession();
44
-
45
- // 2) Allow file downloads and set the download path
46
- await cdpSession.send('Page.setDownloadBehavior', {
47
- behavior: 'allow',
48
- downloadPath: this.uniqueDowloadFolder, // <-- Change this to your desired absolute path
49
- });
50
-
51
- // Optionally set viewport and go to page
52
- await page.setViewport({ width: 1920, height: 1080 });
53
- await page.goto('https://www.handelsregister.de/');
54
- return page;
55
- };
56
-
57
- private navigateToPage = async (
58
- pageArg: plugins.smartbrowser.smartpuppeteer.puppeteer.Page,
59
- pageNameArg: string
60
- ) => {
61
- try {
62
- await pageArg.evaluate((pageNameArg2) => {
63
- const elements = Array.from(document.querySelectorAll('.ui-menuitem-text > span'));
64
- const targetElement = elements.find((el) => el.textContent?.trim() === pageNameArg2);
65
- if (targetElement) {
66
- (targetElement as HTMLElement).click();
67
- }
68
- }, pageNameArg);
69
- console.log(`Navigated to the ${pageNameArg} page successfully.`);
70
- } catch (error) {
71
- console.error(`Failed to navigate to the ${pageNameArg} page:`, error);
72
- }
73
- };
74
-
75
- private waitForResults = async (pageArg: plugins.smartbrowser.smartpuppeteer.puppeteer.Page) => {
76
- await pageArg
77
- .waitForSelector('#ergebnissForm\\:selectedSuchErgebnisFormTable_data', {
78
- timeout: 30000,
79
- })
80
- .catch(async (err) => {
81
- await pageArg.screenshot({ path: `${this.downloadDir}/error.png` as `${string}.png` });
82
- throw err;
83
- });
84
-
85
- const businessRecords: BusinessRecord['data'][] = await pageArg.evaluate(() => {
86
- const rows = document.querySelectorAll(
87
- '#ergebnissForm\\:selectedSuchErgebnisFormTable_data > tr'
88
- );
89
- const records: BusinessRecord['data'][] = [];
90
-
91
- rows.forEach((row) => {
92
- const nameElement = row.querySelector('td.ui-panelgrid-cell span.marginLeft20');
93
- const cityElement = row.querySelector('td.ui-panelgrid-cell.sitzSuchErgebnisse span');
94
- const statusElement = row.querySelector('td.ui-panelgrid-cell span.verticalText');
95
- const registrationCourtElement = row.querySelector(
96
- 'td.ui-panelgrid-cell.fontTableNameSize'
97
- );
98
-
99
- const name = nameElement?.textContent?.trim();
100
- const city = cityElement?.textContent?.trim();
101
- const status = statusElement?.textContent?.trim();
102
- const registrationId = registrationCourtElement?.textContent?.trim();
103
-
104
- // Push parsed data into records array
105
- records.push({
106
- name,
107
- city,
108
- registrationId,
109
- businessType: status,
110
- });
111
- });
112
-
113
- return records;
114
- });
115
- return businessRecords;
116
- };
117
-
118
- private clickFindButton = async (pageArg: plugins.smartbrowser.smartpuppeteer.puppeteer.Page, resultsLimitArg: number = 100) => {
119
- try {
120
- // Wait for the button with the text "Find" to appear
121
- await pageArg.waitForSelector('span.ui-button-text.ui-c', { timeout: 5000 });
122
-
123
- // adjust to 100 results per page
124
- await pageArg.select('#form\\:ergebnisseProSeite_input', `${resultsLimitArg}`);
125
-
126
- // Locate and click the button using its text
127
- await pageArg.evaluate(() => {
128
- const buttons = Array.from(document.querySelectorAll('span.ui-button-text.ui-c'));
129
- const targetButton = buttons.find((button) => button.textContent?.trim() === 'Find');
130
- if (targetButton) {
131
- const parentButton = targetButton.closest('button') || targetButton;
132
- (parentButton as HTMLElement).click();
133
- }
134
- });
135
-
136
- console.log('Find button clicked successfully!');
137
- } catch (error) {
138
- console.error('Failed to find or click the "Find" button:', error);
139
- }
140
- };
141
-
142
- private async downloadFile(
143
- pageArg: plugins.smartbrowser.smartpuppeteer.puppeteer.Page,
144
- typeArg: 'SI' | 'AD'
145
- ) {
146
- // Trigger the file download by clicking on the relevant link
147
- await pageArg.evaluate((typeArg2) => {
148
- // Locate the table body
149
- const tableBody = document.querySelector(
150
- '#ergebnissForm\\:selectedSuchErgebnisFormTable_data'
151
- );
152
- if (!tableBody) {
153
- throw new Error('Table body not found');
154
- }
155
-
156
- // Locate the first row
157
- const firstRow = tableBody.querySelector('tr:nth-child(1)');
158
- if (!firstRow) {
159
- throw new Error('First row not found');
160
- }
161
-
162
- // Locate the last cell in the first row
163
- const lastCell = firstRow.querySelector('td:last-child');
164
- if (!lastCell) {
165
- throw new Error('Last cell not found in the first row');
166
- }
167
-
168
- // Locate the download links
169
- const adLink = lastCell.querySelector('a:first-of-type');
170
- const siLink = lastCell.querySelector('a:last-of-type');
171
- if (!siLink) {
172
- throw new Error('SI link not found in the last cell');
173
- }
174
-
175
- // Simulate a click on the last <a> element
176
- switch (typeArg2) {
177
- case 'AD':
178
- (adLink as HTMLElement).click();
179
- break;
180
- case 'SI':
181
- (siLink as HTMLElement).click();
182
- break;
183
- default:
184
- throw new Error('Invalid file type');
185
- }
186
- }, typeArg);
187
-
188
-
189
- await plugins.smartfile.fs.waitForFileToBeReady(this.uniqueDowloadFolder);
190
-
191
- const files = await plugins.smartfile.fs.fileTreeToObject(this.uniqueDowloadFolder, '**/*');
192
- const file = files[0];
193
-
194
- // lets clear the folder for the next download
195
- await plugins.smartfile.fs.ensureEmptyDir(this.uniqueDowloadFolder);
196
- switch (typeArg) {
197
- case 'AD':
198
- await file.rename(`ad.pdf`);
199
- break;
200
- case 'SI':
201
- await file.rename(`si.xml`);
202
- break;
203
- break;
204
- }
205
- return file;
206
- }
207
-
208
- /**
209
- * Helper method to parse the German registration string
210
- */
211
- private async parseGermanRegistration(
212
- input: string
213
- ): Promise<BusinessRecord['data']['germanParsedRegistration']> {
214
- // e.g. District court Berlin (Charlottenburg) HRB 123456
215
- const regex =
216
- /District court (\p{L}[\p{L}\s-]*?(?:\s*\([\p{L}\s-]+\))?)\s+(HRA|HRB|GnR|VR|PR|GsR)\s+(\d+)/u;
217
- const match = input.match(regex);
218
-
219
- if (match) {
220
- return {
221
- court: match[1],
222
- type: match[2] as 'HRA' | 'HRB', // Adjust if needed
223
- number: match[3],
224
- };
225
- }
226
- }
227
-
228
- /**
229
- * Search for a company by name and return basic info
230
- */
231
- public async searchCompany(companyNameArg: string, resultsLimitArg: number = 100) {
232
- return this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
233
- const page = await this.getNewPage();
234
- await this.navigateToPage(page, 'Normal search');
235
-
236
- try {
237
- // Wait for the textarea to appear
238
- await page.waitForSelector('#form\\:schlagwoerter', { timeout: 5000 });
239
-
240
- // Enter text into the textarea
241
- const inputText = companyNameArg;
242
- await page.evaluate((text) => {
243
- const textarea = document.querySelector<HTMLTextAreaElement>('#form\\:schlagwoerter');
244
- if (textarea) {
245
- textarea.value = text; // Set the value
246
- // Trigger the change event manually if required
247
- const event = new Event('change', { bubbles: true });
248
- textarea.dispatchEvent(event);
249
- }
250
- }, inputText);
251
-
252
- console.log('Text entered successfully!');
253
- } catch (error) {
254
- console.error('Failed to find or enter text into the textarea:', error);
255
- }
256
-
257
- try {
258
- // Wait for the radio button's label to appear
259
- await page.waitForSelector('label[for="form:schlagwortOptionen:0"]', { timeout: 5000 });
260
-
261
- // Click the label to select the radio button
262
- await page.evaluate(() => {
263
- const label = document.querySelector<HTMLLabelElement>(
264
- 'label[for="form:schlagwortOptionen:0"]'
265
- );
266
- if (label) {
267
- label.click();
268
- }
269
- });
270
-
271
- console.log('Radio button clicked successfully!');
272
- } catch (error) {
273
- console.error('Failed to find or click the radio button:', error);
274
- }
275
-
276
- await this.clickFindButton(page, resultsLimitArg);
277
-
278
- const businessRecords = await this.waitForResults(page);
279
-
280
- // Parse out the registration info
281
- for (const record of businessRecords) {
282
- if (record.registrationId) {
283
- record.germanParsedRegistration = await this.parseGermanRegistration(
284
- record.registrationId
285
- );
286
- }
287
- }
288
-
289
- await page.close();
290
- return businessRecords;
291
- }, 60000);
292
- }
293
-
294
- /**
295
- * Search for a specific company (known register type/number/court),
296
- * then click on an element that triggers a file download.
297
- */
298
- public async getSpecificCompany(companyArg: BusinessRecord['data']['germanParsedRegistration']) {
299
- return this.asyncExecutionStack.getExclusiveExecutionSlot(async () => {
300
- const page = await this.getNewPage();
301
- await this.navigateToPage(page, 'Normal search');
302
- await page.waitForSelector('#form\\:schlagwoerter', { timeout: 5000 });
303
-
304
- // 1) Type of Register (e.g. HRB, HRA, etc.)
305
- await page.waitForSelector('#form\\:registerArt_label');
306
- await page.click('#form\\:registerArt_label');
307
- await page.waitForSelector('#form\\:registerArt_items');
308
- await page.evaluate((type) => {
309
- const options = Array.from(document.querySelectorAll('#form\\:registerArt_items li'));
310
- const targetOption = options.find((option) => option.textContent?.trim() === type);
311
- (targetOption as HTMLElement)?.click();
312
- }, companyArg.type);
313
-
314
- // 2) Register number
315
- await page.waitForSelector('#form\\:registerNummer');
316
- await page.type('#form\\:registerNummer', companyArg.number);
317
-
318
- // 3) Register court
319
- await page.waitForSelector('#form\\:registergericht_label');
320
- await page.click('#form\\:registergericht_label');
321
- await page.waitForSelector('#form\\:registergericht_items');
322
- await page.evaluate((court) => {
323
- const options = Array.from(document.querySelectorAll('#form\\:registergericht_items li'));
324
- const targetOption = options.find((option) => option.textContent?.trim() === court);
325
- (targetOption as HTMLElement)?.click();
326
- }, companyArg.court);
327
-
328
- // Click 'Find'
329
- await this.clickFindButton(page);
330
-
331
- // Optionally grab the results, just for logging
332
- const businessRecords = await this.waitForResults(page);
333
- console.log(businessRecords);
334
-
335
- const files: plugins.smartfile.SmartFile[] = [];
336
-
337
- // download files
338
- files.push(await this.downloadFile(page, 'SI'));
339
- files.push(await this.downloadFile(page, 'AD'));
340
-
341
- // At this point, the file should have been downloaded automatically
342
- // to the path specified by `Page.setDownloadBehavior`
343
- await page.close();
344
-
345
- return {
346
- businessRecords,
347
- files,
348
- };
349
- }, 60000);
350
- }
351
-
352
- /**
353
- * get specific company by full name
354
- */
355
- public async getSpecificCompanyByName(companyNameArg: string) {
356
- const businessRecords = await this.searchCompany(companyNameArg, 1);
357
- const result = this.getSpecificCompany(businessRecords[0].germanParsedRegistration);
358
- return result;
359
- }
360
- }
@@ -1,113 +0,0 @@
1
- import * as plugins from './plugins.js';
2
- import type { OpenData } from './classes.main.opendata.js';
3
-
4
- export type SeedEntryType = {
5
- all_attributes: {
6
- _registerArt: string;
7
- _registerNummer: string;
8
- additional_data: {
9
- AD: boolean;
10
- CD: boolean;
11
- DK: boolean;
12
- HD: boolean;
13
- SI: boolean;
14
- UT: boolean;
15
- VÖ: boolean;
16
- };
17
- federal_state: string;
18
- native_company_number: string;
19
- registered_office: string;
20
- registrar: string;
21
- };
22
- company_number: string;
23
- current_status: string;
24
- jurisdiction_code: string;
25
- name: string;
26
- officers: {
27
- name: string;
28
- other_attributes: {
29
- city: string;
30
- firstname: string;
31
- flag: string;
32
- lastname: string;
33
- };
34
- position: string;
35
- start_date: string; // ISO 8601 date string
36
- type: string;
37
- }[];
38
- registered_address: string;
39
- retrieved_at: string; // ISO 8601 date string
40
- };
41
-
42
- export class JsonlDataProcessor<T> {
43
- private germanBusinessDataDir: string;
44
- public forEachFunction: (entryArg: T) => Promise<void>;
45
-
46
- constructor(germanBusinessDataDirArg: string, forEachFunctionArg: typeof this.forEachFunction) {
47
- this.germanBusinessDataDir = germanBusinessDataDirArg;
48
- this.forEachFunction = forEachFunctionArg;
49
- }
50
-
51
- // TODO: define a mapper as argument instead of hard-coding it
52
- public async processDataFromUrl(
53
- dataUrlArg = 'https://daten.offeneregister.de/de_companies_ocdata.jsonl.bz2'
54
- ) {
55
- const done = plugins.smartpromise.defer();
56
- const dataExists = await plugins.smartfile.fs.isDirectory(this.germanBusinessDataDir);
57
- if (!dataExists) {
58
- await plugins.smartfile.fs.ensureDir(this.germanBusinessDataDir);
59
- } else {
60
- }
61
-
62
- const smartarchive = await plugins.smartarchive.SmartArchive.fromArchiveUrl(dataUrlArg);
63
- const jsonlDataStream = await smartarchive.exportToStreamOfStreamFiles();
64
- let totalRecordsCounter = 0;
65
- let nextRest: string = '';
66
- jsonlDataStream.pipe(
67
- new plugins.smartstream.SmartDuplex({
68
- objectMode: true,
69
- writeFunction: async (chunkArg: plugins.smartfile.StreamFile, streamToolsArg) => {
70
- const readStream = await chunkArg.createReadStream();
71
- readStream.pipe(
72
- new plugins.smartstream.SmartDuplex({
73
- objectMode: true,
74
- writeFunction: async (chunkArg: Buffer, streamToolsArg) => {
75
- const currentString = nextRest + chunkArg.toString();
76
- const lines = currentString.split('\n');
77
- nextRest = lines.pop();
78
- console.log(`Got another ${lines.length} records.`);
79
- const concurrentProcessor = new plugins.smartarray.ConcurrentProcessor<string>(
80
- async (line) => {
81
- let entry: T;
82
- if (!line) return;
83
- try {
84
- entry = JSON.parse(line);
85
- } catch (err) {
86
- console.log(line);
87
- await plugins.smartdelay.delayFor(10000);
88
- }
89
- if (!entry) return;
90
- totalRecordsCounter++;
91
- if (totalRecordsCounter % 10000 === 0)
92
- console.log(`${totalRecordsCounter} total records.`);
93
- await this.forEachFunction(entry);
94
- },
95
- 1000
96
- );
97
- await concurrentProcessor.process(lines);
98
- },
99
- finalFunction: async (streamToolsArg) => {
100
- console.log(`finished processing ${totalRecordsCounter} records.`);
101
- if (nextRest) {
102
- JSON.parse(nextRest);
103
- };
104
- done.resolve();
105
- },
106
- })
107
- );
108
- },
109
- })
110
- );
111
- await done.promise;
112
- }
113
- }
@@ -1,87 +0,0 @@
1
- import { BusinessRecord } from './classes.businessrecord.js';
2
- import { HandelsRegister } from './classes.handelsregister.js';
3
- import { JsonlDataProcessor, type SeedEntryType } from './classes.jsonldata.js';
4
- import * as paths from './paths.js';
5
- import * as plugins from './plugins.js';
6
-
7
- export interface IOpenDataConfig {
8
- downloadDir: string;
9
- germanBusinessDataDir: string;
10
- nogitDir: string;
11
- }
12
-
13
- export class OpenData {
14
- public db: plugins.smartdata.SmartdataDb;
15
- private serviceQenv: plugins.qenv.Qenv;
16
- private config: IOpenDataConfig;
17
-
18
- public jsonLDataProcessor: JsonlDataProcessor<SeedEntryType>;
19
- public handelsregister: HandelsRegister;
20
-
21
- public CBusinessRecord = plugins.smartdata.setDefaultManagerForDoc(this, BusinessRecord);
22
-
23
- constructor(configArg: IOpenDataConfig) {
24
- if (!configArg) {
25
- throw new Error('@fin.cx/opendata: Configuration is required. You must provide downloadDir, germanBusinessDataDir, and nogitDir paths.');
26
- }
27
- if (!configArg.downloadDir || !configArg.germanBusinessDataDir || !configArg.nogitDir) {
28
- throw new Error('@fin.cx/opendata: All directory paths are required (downloadDir, germanBusinessDataDir, nogitDir).');
29
- }
30
- this.config = configArg;
31
- this.serviceQenv = new plugins.qenv.Qenv(paths.packageDir, this.config.nogitDir);
32
- }
33
-
34
- public async start() {
35
- // Ensure configured directories exist
36
- await plugins.smartfile.fs.ensureDir(this.config.nogitDir);
37
- await plugins.smartfile.fs.ensureDir(this.config.downloadDir);
38
- await plugins.smartfile.fs.ensureDir(this.config.germanBusinessDataDir);
39
-
40
- this.db = new plugins.smartdata.SmartdataDb({
41
- mongoDbUrl: await this.serviceQenv.getEnvVarOnDemand('MONGODB_URL'),
42
- mongoDbName: await this.serviceQenv.getEnvVarOnDemand('MONGODB_NAME'),
43
- mongoDbUser: await this.serviceQenv.getEnvVarOnDemand('MONGODB_USER'),
44
- mongoDbPass: await this.serviceQenv.getEnvVarOnDemand('MONGODB_PASS'),
45
- });
46
- await this.db.init();
47
- this.jsonLDataProcessor = new JsonlDataProcessor(
48
- this.config.germanBusinessDataDir,
49
- async (entryArg) => {
50
- const businessRecord = new this.CBusinessRecord();
51
- businessRecord.id = await this.CBusinessRecord.getNewId();
52
- businessRecord.data.name = entryArg.name;
53
- businessRecord.data.germanParsedRegistration = {
54
- court: entryArg.all_attributes.registered_office,
55
- number: entryArg.all_attributes._registerNummer,
56
- type: entryArg.all_attributes._registerArt as 'HRA' | 'HRB',
57
- };
58
- await businessRecord.save();
59
- }
60
- );
61
- this.handelsregister = new HandelsRegister(this, this.config.downloadDir);
62
- await this.handelsregister.start();
63
- }
64
-
65
- public async buildInitialDb() {
66
- await this.jsonLDataProcessor.processDataFromUrl();
67
- }
68
-
69
- public async slowValidateDb() {
70
-
71
- }
72
-
73
- public async validateSearchByName() {
74
-
75
- }
76
-
77
- public async searchDbByBusinessNameAndPostalCode(businessNameArg: string, postalCodeArg: string) {
78
-
79
- }
80
-
81
-
82
-
83
- public async stop() {
84
- await this.db.close();
85
- await this.handelsregister.stop();
86
- }
87
- }