@fin.cx/opendata 3.6.0 → 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 (78) hide show
  1. package/.smartconfig.json +20 -20
  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 -2
  32. package/dist_ts/index.js +1 -3
  33. package/dist_ts/plugins.d.ts +2 -20
  34. package/dist_ts/plugins.js +3 -22
  35. package/package.json +33 -37
  36. package/readme.md +159 -126
  37. package/ts/00_commitinfo_data.ts +2 -2
  38. package/ts/handelsregister/classes.handelsregisterclient.ts +474 -0
  39. package/ts/handelsregister/classes.handelsregistererror.ts +82 -0
  40. package/ts/handelsregister/classes.portalsession.ts +191 -0
  41. package/ts/handelsregister/classes.slidingwindowgate.ts +74 -0
  42. package/ts/handelsregister/constants.ts +30 -0
  43. package/ts/handelsregister/data.codelists.ts +640 -0
  44. package/ts/handelsregister/forms.ts +99 -0
  45. package/ts/handelsregister/html.ts +113 -0
  46. package/ts/handelsregister/index.ts +27 -0
  47. package/ts/handelsregister/interfaces.ts +272 -0
  48. package/ts/handelsregister/parse.searchresults.ts +241 -0
  49. package/ts/handelsregister/parse.structuredcontent.ts +338 -0
  50. package/ts/handelsregister/plugins.ts +15 -0
  51. package/ts/handelsregister/references.ts +115 -0
  52. package/ts/index.ts +0 -2
  53. package/ts/plugins.ts +0 -39
  54. package/dist_ts/classes.businessrecord.d.ts +0 -38
  55. package/dist_ts/classes.businessrecord.js +0 -90
  56. package/dist_ts/classes.handelsregister.d.ts +0 -134
  57. package/dist_ts/classes.handelsregister.js +0 -307
  58. package/dist_ts/classes.jsonldata.d.ts +0 -43
  59. package/dist_ts/classes.jsonldata.js +0 -68
  60. package/dist_ts/classes.main.opendata.d.ts +0 -25
  61. package/dist_ts/classes.main.opendata.js +0 -91
  62. package/dist_ts/laws/classes.lawrecord.d.ts +0 -24
  63. package/dist_ts/laws/classes.lawrecord.js +0 -181
  64. package/dist_ts/laws/classes.lawservice.d.ts +0 -52
  65. package/dist_ts/laws/classes.lawservice.js +0 -740
  66. package/dist_ts/laws/index.d.ts +0 -3
  67. package/dist_ts/laws/index.js +0 -4
  68. package/dist_ts/laws/interfaces.law.d.ts +0 -35
  69. package/dist_ts/laws/interfaces.law.js +0 -2
  70. package/readme.hints.md +0 -89
  71. package/ts/classes.businessrecord.ts +0 -67
  72. package/ts/classes.handelsregister.ts +0 -385
  73. package/ts/classes.jsonldata.ts +0 -114
  74. package/ts/classes.main.opendata.ts +0 -120
  75. package/ts/laws/classes.lawrecord.ts +0 -81
  76. package/ts/laws/classes.lawservice.ts +0 -1010
  77. package/ts/laws/index.ts +0 -3
  78. package/ts/laws/interfaces.law.ts +0 -48
package/.smartconfig.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "githost": "gitlab.com",
6
6
  "gitscope": "fin.cx",
7
7
  "gitrepo": "opendata",
8
- "description": "A comprehensive TypeScript library that manages open business data for German companies by integrating MongoDB, processing JSONL bulk data, and automating browser interactions for Handelsregister data retrieval.",
8
+ "description": "Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, and stock and crypto prices and fundamentals from several providers.",
9
9
  "npmPackagename": "@fin.cx/opendata",
10
10
  "license": "MIT",
11
11
  "projectDomain": "fin.cx",
@@ -14,31 +14,31 @@
14
14
  "open data",
15
15
  "German companies",
16
16
  "business data",
17
- "MongoDB",
18
- "JSONL",
19
- "bulk processing",
20
- "data management",
21
- "automation",
22
- "browser automation",
23
17
  "Handelsregister",
24
- "web scraping",
25
- "file processing",
18
+ "register portal",
19
+ "commercial register",
20
+ "XJustiz",
26
21
  "business registry",
27
- "data retrieval"
22
+ "data retrieval",
23
+ "stock prices",
24
+ "cryptocurrency",
25
+ "fundamentals"
28
26
  ]
29
27
  },
30
28
  "release": {
31
- "registries": [
32
- "https://verdaccio.lossless.digital",
33
- "https://registry.npmjs.org"
34
- ],
35
- "accessLevel": "public"
36
- }
29
+ "targets": {
30
+ "npm": {
31
+ "registries": [
32
+ "https://verdaccio.lossless.digital",
33
+ "https://registry.npmjs.org"
34
+ ],
35
+ "accessLevel": "public"
36
+ }
37
+ }
38
+ },
39
+ "schemaVersion": 2
37
40
  },
38
41
  "@git.zone/tsdoc": {
39
42
  "legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
40
- },
41
- "@ship.zone/szci": {
42
- "npmGlobalTools": []
43
43
  }
44
- }
44
+ }
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/opendata',
6
- version: '3.6.0',
7
- description: 'A comprehensive TypeScript library for accessing business data and real-time financial information. Features include German company data management with MongoDB integration, JSONL bulk processing, automated Handelsregister interactions, and real-time stock market data from multiple providers.'
6
+ version: '4.0.0',
7
+ description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, and stock and crypto prices and fundamentals from several providers.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHVTQUF1UztDQUNyVCxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDRNQUE0TTtDQUMxTixDQUFBIn0=
@@ -0,0 +1,64 @@
1
+ import type { IHandelsregisterClientOptions, IRegisterCallOptions, IRegisterEntry, IRegisterReferenceInput, IRegisterSearchResult, TRegisterSearchQuery } from './interfaces.js';
2
+ /**
3
+ * Looks up entries of the German commercial, cooperative, partnership, association and civil-law
4
+ * partnership registers on the register portal of the federal states (handelsregister.de), over
5
+ * plain HTTP and without storage.
6
+ *
7
+ * Every call opens its own visit to the portal and forgets it afterwards: nothing is cached or
8
+ * shared between calls. The client never repeats a request by itself, never logs, and asks its
9
+ * gate before every request the portal's terms count:
10
+ * - `search()` makes one counted search;
11
+ * - `getEntry()` makes one counted search and, when the portal offers structured content for the
12
+ * entry, one counted retrieval.
13
+ *
14
+ * Each search also loads the search form and the result list, two pages the terms do not count.
15
+ *
16
+ * The portal's terms allow single lookups for information only, at most 60 searches or
17
+ * retrievals per hour, and no systematic retrieval to build or update a copy of the registers.
18
+ */
19
+ export declare class HandelsregisterClient {
20
+ private gate;
21
+ private portalUrl;
22
+ private userAgent;
23
+ private requestTimeoutMs;
24
+ private maxResponseBytes;
25
+ private now;
26
+ constructor(optionsArg: IHandelsregisterClientOptions);
27
+ /**
28
+ * Searches the registers by name or by register number. Returns every row the portal lists, in
29
+ * its order, and whether the portal cut the list at its maximum. One counted search.
30
+ *
31
+ * A number is searched by its digits: rows with any location suffix are returned.
32
+ */
33
+ search(queryArg: TRegisterSearchQuery, optionsArg?: IRegisterCallOptions): Promise<IRegisterSearchResult>;
34
+ /**
35
+ * Retrieves one register sheet: its row in the result list and, when the portal offers it, the
36
+ * parsed structured content (SI). Closed sheets are included, so a deleted entry is found with
37
+ * its status. One counted search, plus one counted retrieval when there is structured content.
38
+ *
39
+ * Fails with `not_found` when no sheet has the number at that court (with the entries whose
40
+ * location suffix differs in `matches`), and with `ambiguous` when a number without suffix fits
41
+ * several sheets. Never picks one of several.
42
+ */
43
+ getEntry(referenceArg: IRegisterReferenceInput, optionsArg?: IRegisterCallOptions): Promise<IRegisterEntry>;
44
+ private openSession;
45
+ private planSearch;
46
+ /**
47
+ * Asks the gate for one counted request. A refusal that is a `HandelsregisterError` reaches the
48
+ * caller with the step it guarded and the requests the call had counted before it; any other
49
+ * error of the gate reaches the caller unchanged.
50
+ */
51
+ private acquireSlot;
52
+ private runSearch;
53
+ private pickRow;
54
+ private retrieveStructuredContent;
55
+ /** the structured content must describe the sheet of the row it was retrieved for */
56
+ private checkContentBelongsToRow;
57
+ private htmlDocumentOf;
58
+ /** the register courts the search form offers */
59
+ private courtsOf;
60
+ /** refuses with the portal's words when the page is its notice of a blocked retrieval */
61
+ private throwIfBlocked;
62
+ /** the message the search form shows, when the portal answered with the form again */
63
+ private searchFormMessage;
64
+ }
@@ -0,0 +1,397 @@
1
+ import { HandelsregisterError } from './classes.handelsregistererror.js';
2
+ import { PortalSession } from './classes.portalsession.js';
3
+ import { defaultMaxResponseBytes, defaultPortalUrl, defaultRequestTimeoutMs, defaultUserAgent, registerTypes, structuredContentNotice, } from './constants.js';
4
+ import { registerCourts } from './data.codelists.js';
5
+ import * as forms from './forms.js';
6
+ import * as html from './html.js';
7
+ import { readResultList } from './parse.searchresults.js';
8
+ import { parseStructuredContent } from './parse.structuredcontent.js';
9
+ import { parseRegisterNumber } from './references.js';
10
+ const searchFormPath = '/rp_web/erweitertesuche/welcome.xhtml';
11
+ const searchFormId = 'form';
12
+ const field = {
13
+ keywords: 'form:schlagwoerter',
14
+ keywordMode: 'form:schlagwortOptionen',
15
+ seat: 'form:NiederlassungSitz',
16
+ registerType: 'form:registerArt_input',
17
+ registerNumber: 'form:registerNummer',
18
+ court: 'form:registergericht_input',
19
+ pageSize: 'form:ergebnisseProSeite_input',
20
+ includeClosed: 'form:auchGeloeschte_input',
21
+ searchButton: 'form:btnSuche',
22
+ };
23
+ const searchFormMessagesId = 'form:messagesSuchMaske';
24
+ /**
25
+ * The page the portal shows when it refuses a retrieval: for the TOR network and for addresses it
26
+ * has blocked (the portal's FAQ, question 6)
27
+ */
28
+ const blockedRetrievalPattern = /Leider können wir den Dokumentenabruf[^.]*\./;
29
+ const keywordModes = { all: '1', any: '2', exact: '3' };
30
+ const maxKeywordLength = 500;
31
+ const invalidQuery = (messageArg) => new HandelsregisterError('invalid_query', messageArg, { countedRequests: 0 });
32
+ /** the error with the step and the counted requests of the call it ended */
33
+ const inCall = (errorArg, progressArg) => new HandelsregisterError(errorArg.code, errorArg.message, {
34
+ status: errorArg.status,
35
+ retryAt: errorArg.retryAt,
36
+ step: errorArg.step ?? progressArg.step,
37
+ countedRequests: progressArg.countedRequests,
38
+ matches: errorArg.matches,
39
+ portalMessage: errorArg.portalMessage,
40
+ cause: errorArg.cause,
41
+ });
42
+ const checkType = (typeArg) => {
43
+ if (typeArg === undefined) {
44
+ return undefined;
45
+ }
46
+ const type = registerTypes.find((knownArg) => knownArg === typeArg);
47
+ if (!type) {
48
+ throw invalidQuery(`Unknown register type; use one of ${registerTypes.join(', ')}.`);
49
+ }
50
+ return type;
51
+ };
52
+ const checkCourt = (courtCodeArg) => {
53
+ if (courtCodeArg === undefined) {
54
+ return '';
55
+ }
56
+ if (!registerCourts.some((courtArg) => courtArg.code === courtCodeArg)) {
57
+ throw invalidQuery('Unknown register court code; see registerCourts.');
58
+ }
59
+ return courtCodeArg;
60
+ };
61
+ const checkNumber = (numberArg) => {
62
+ const parts = parseRegisterNumber(numberArg);
63
+ if (!parts) {
64
+ throw invalidQuery('A register number is digits, optionally followed by a location suffix such as HB.');
65
+ }
66
+ return parts;
67
+ };
68
+ const decodeUtf8 = (bytesArg) => new TextDecoder('utf-8').decode(bytesArg);
69
+ /**
70
+ * Looks up entries of the German commercial, cooperative, partnership, association and civil-law
71
+ * partnership registers on the register portal of the federal states (handelsregister.de), over
72
+ * plain HTTP and without storage.
73
+ *
74
+ * Every call opens its own visit to the portal and forgets it afterwards: nothing is cached or
75
+ * shared between calls. The client never repeats a request by itself, never logs, and asks its
76
+ * gate before every request the portal's terms count:
77
+ * - `search()` makes one counted search;
78
+ * - `getEntry()` makes one counted search and, when the portal offers structured content for the
79
+ * entry, one counted retrieval.
80
+ *
81
+ * Each search also loads the search form and the result list, two pages the terms do not count.
82
+ *
83
+ * The portal's terms allow single lookups for information only, at most 60 searches or
84
+ * retrievals per hour, and no systematic retrieval to build or update a copy of the registers.
85
+ */
86
+ export class HandelsregisterClient {
87
+ gate;
88
+ portalUrl;
89
+ userAgent;
90
+ requestTimeoutMs;
91
+ maxResponseBytes;
92
+ now;
93
+ constructor(optionsArg) {
94
+ if (!optionsArg || !optionsArg.gate) {
95
+ throw new TypeError('HandelsregisterClient needs a gate; see SlidingWindowGate.');
96
+ }
97
+ this.gate = optionsArg.gate;
98
+ this.portalUrl = optionsArg.portalUrl ?? defaultPortalUrl;
99
+ this.userAgent = optionsArg.userAgent ?? defaultUserAgent;
100
+ this.requestTimeoutMs = optionsArg.requestTimeoutMs ?? defaultRequestTimeoutMs;
101
+ this.maxResponseBytes = optionsArg.maxResponseBytes ?? defaultMaxResponseBytes;
102
+ this.now = optionsArg.now ?? Date.now;
103
+ const protocol = new URL(this.portalUrl).protocol;
104
+ if (protocol !== 'https:' && protocol !== 'http:') {
105
+ throw new TypeError('portalUrl must be an http or https URL.');
106
+ }
107
+ }
108
+ /**
109
+ * Searches the registers by name or by register number. Returns every row the portal lists, in
110
+ * its order, and whether the portal cut the list at its maximum. One counted search.
111
+ *
112
+ * A number is searched by its digits: rows with any location suffix are returned.
113
+ */
114
+ async search(queryArg, optionsArg = {}) {
115
+ const plan = this.planSearch(queryArg);
116
+ const progress = { countedRequests: 0 };
117
+ const { list } = await this.runSearch(plan, progress, this.openSession(optionsArg, progress));
118
+ const result = {
119
+ matches: list.rows.map((rowArg) => rowArg.match),
120
+ truncated: list.truncated,
121
+ retrievedAt: this.now(),
122
+ countedRequests: progress.countedRequests,
123
+ notice: structuredContentNotice,
124
+ };
125
+ if (list.portalNotice) {
126
+ result.portalNotice = list.portalNotice;
127
+ }
128
+ return result;
129
+ }
130
+ /**
131
+ * Retrieves one register sheet: its row in the result list and, when the portal offers it, the
132
+ * parsed structured content (SI). Closed sheets are included, so a deleted entry is found with
133
+ * its status. One counted search, plus one counted retrieval when there is structured content.
134
+ *
135
+ * Fails with `not_found` when no sheet has the number at that court (with the entries whose
136
+ * location suffix differs in `matches`), and with `ambiguous` when a number without suffix fits
137
+ * several sheets. Never picks one of several.
138
+ */
139
+ async getEntry(referenceArg, optionsArg = {}) {
140
+ const type = checkType(referenceArg.type);
141
+ if (!type) {
142
+ throw invalidQuery('A reference needs a register type.');
143
+ }
144
+ const courtCode = checkCourt(referenceArg.courtCode);
145
+ if (!courtCode) {
146
+ throw invalidQuery('A reference needs a register court.');
147
+ }
148
+ const number = checkNumber(referenceArg.number);
149
+ const progress = { countedRequests: 0 };
150
+ const session = this.openSession(optionsArg, progress);
151
+ const outcome = await this.runSearch({ keywords: '', keywordMode: keywordModes.all, seat: '', registerType: type, digits: number.digits, courtCode, includeClosed: true }, progress, session);
152
+ const row = this.pickRow(outcome.list, { courtCode, type, number }, progress);
153
+ let structuredContent = null;
154
+ let retrievedAt = this.now();
155
+ if (row.match.documents.includes('SI')) {
156
+ structuredContent = await this.retrieveStructuredContent(row, outcome, session, progress);
157
+ retrievedAt = this.now();
158
+ }
159
+ return {
160
+ match: row.match,
161
+ structuredContent,
162
+ retrievedAt,
163
+ countedRequests: progress.countedRequests,
164
+ notice: structuredContentNotice,
165
+ };
166
+ }
167
+ openSession(optionsArg, progressArg) {
168
+ return new PortalSession({
169
+ portalUrl: this.portalUrl,
170
+ userAgent: this.userAgent,
171
+ requestTimeoutMs: this.requestTimeoutMs,
172
+ maxResponseBytes: this.maxResponseBytes,
173
+ signal: optionsArg.signal,
174
+ }, progressArg);
175
+ }
176
+ planSearch(queryArg) {
177
+ if ('name' in queryArg) {
178
+ const keywords = queryArg.name.replace(/\s+/g, ' ').trim();
179
+ if (!keywords) {
180
+ throw invalidQuery('A name search needs at least one keyword.');
181
+ }
182
+ if (keywords.length > maxKeywordLength) {
183
+ throw invalidQuery(`A name search takes at most ${maxKeywordLength} characters.`);
184
+ }
185
+ const mode = queryArg.match ?? 'all';
186
+ if (!(mode in keywordModes)) {
187
+ throw invalidQuery('match is all, any or exact.');
188
+ }
189
+ return {
190
+ keywords,
191
+ keywordMode: keywordModes[mode],
192
+ seat: (queryArg.seat ?? '').replace(/\s+/g, ' ').trim(),
193
+ registerType: checkType(queryArg.type) ?? '',
194
+ digits: '',
195
+ courtCode: checkCourt(queryArg.courtCode),
196
+ includeClosed: queryArg.includeClosed === true,
197
+ };
198
+ }
199
+ const type = checkType(queryArg.type);
200
+ if (!type) {
201
+ throw invalidQuery('A number search needs a register type.');
202
+ }
203
+ return {
204
+ keywords: '',
205
+ keywordMode: keywordModes.all,
206
+ seat: '',
207
+ registerType: type,
208
+ digits: checkNumber(queryArg.number).digits,
209
+ courtCode: checkCourt(queryArg.courtCode),
210
+ includeClosed: queryArg.includeClosed === true,
211
+ };
212
+ }
213
+ /**
214
+ * Asks the gate for one counted request. A refusal that is a `HandelsregisterError` reaches the
215
+ * caller with the step it guarded and the requests the call had counted before it; any other
216
+ * error of the gate reaches the caller unchanged.
217
+ */
218
+ async acquireSlot(kindArg, stepArg, progressArg) {
219
+ try {
220
+ await this.gate.acquire({ kind: kindArg });
221
+ }
222
+ catch (error) {
223
+ if (error instanceof HandelsregisterError) {
224
+ throw inCall(error, { step: stepArg, countedRequests: progressArg.countedRequests });
225
+ }
226
+ throw error;
227
+ }
228
+ }
229
+ async runSearch(planArg, progressArg, sessionArg) {
230
+ await this.acquireSlot('search', 'search', progressArg);
231
+ try {
232
+ progressArg.step = 'search_form';
233
+ const formPage = await sessionArg.get(sessionArg.resolve(searchFormPath));
234
+ const formDocument = this.htmlDocumentOf(formPage, 'The search form is not a web page.');
235
+ if (html.documentLanguage(formDocument) !== 'de') {
236
+ throw new HandelsregisterError('unexpected_response', 'The search form is not in German.');
237
+ }
238
+ const form = forms.readForm(formDocument, searchFormId);
239
+ if (!form) {
240
+ throw new HandelsregisterError('unexpected_response', 'The page holds no search form.');
241
+ }
242
+ const missing = Object.values(field).find((nameArg) => !form.controlNames.has(nameArg));
243
+ if (missing) {
244
+ throw new HandelsregisterError('unexpected_response', 'The search form lacks a field this version fills.');
245
+ }
246
+ const courts = this.courtsOf(form);
247
+ if (planArg.courtCode && !courts.some((courtArg) => courtArg.code === planArg.courtCode)) {
248
+ throw new HandelsregisterError('invalid_query', 'The portal does not offer this register court.');
249
+ }
250
+ if (planArg.registerType && !(form.options.get(field.registerType) ?? []).some((optionArg) => optionArg.value === planArg.registerType)) {
251
+ throw new HandelsregisterError('unexpected_response', 'The search form does not offer this register type.');
252
+ }
253
+ if (!(form.options.get(field.pageSize) ?? []).some((optionArg) => optionArg.value === '100')) {
254
+ throw new HandelsregisterError('unexpected_response', 'The search form does not offer 100 results per page.');
255
+ }
256
+ const fields = [...form.fields];
257
+ forms.setField(fields, field.keywords, planArg.keywords);
258
+ forms.setField(fields, field.keywordMode, planArg.keywordMode);
259
+ forms.setField(fields, field.seat, planArg.seat);
260
+ forms.setField(fields, field.registerType, planArg.registerType);
261
+ forms.setField(fields, field.registerNumber, planArg.digits);
262
+ forms.setField(fields, field.court, planArg.courtCode);
263
+ forms.setField(fields, field.pageSize, '100');
264
+ if (planArg.includeClosed) {
265
+ forms.setField(fields, field.includeClosed, 'on');
266
+ }
267
+ else {
268
+ forms.removeField(fields, field.includeClosed);
269
+ }
270
+ forms.setField(fields, field.searchButton, '');
271
+ progressArg.step = 'search';
272
+ progressArg.countedRequests += 1;
273
+ const resultPage = await sessionArg.post(sessionArg.resolve(form.action, formPage.url), fields);
274
+ progressArg.step = 'result_list';
275
+ const resultText = decodeUtf8(resultPage.body);
276
+ try {
277
+ return { list: readResultList(resultText, courts), pageUrl: resultPage.url };
278
+ }
279
+ catch (error) {
280
+ if (error instanceof HandelsregisterError && error.code === 'unexpected_response') {
281
+ this.throwIfBlocked(resultText);
282
+ const message = this.searchFormMessage(resultText);
283
+ if (message) {
284
+ throw new HandelsregisterError('unexpected_response', 'The portal answered the search with a message instead of a result list.', {
285
+ portalMessage: message,
286
+ });
287
+ }
288
+ }
289
+ throw error;
290
+ }
291
+ }
292
+ catch (error) {
293
+ throw error instanceof HandelsregisterError ? inCall(error, progressArg) : error;
294
+ }
295
+ }
296
+ pickRow(listArg, referenceArg, progressArg) {
297
+ const sameNumber = listArg.rows.filter((rowArg) => {
298
+ const reference = rowArg.match.reference;
299
+ const number = parseRegisterNumber(reference.number);
300
+ return reference.court.code === referenceArg.courtCode && reference.type === referenceArg.type && number?.digits === referenceArg.number.digits;
301
+ });
302
+ const fitting = referenceArg.number.suffix
303
+ ? sameNumber.filter((rowArg) => parseRegisterNumber(rowArg.match.reference.number)?.suffix === referenceArg.number.suffix)
304
+ : sameNumber;
305
+ const matches = sameNumber.map((rowArg) => rowArg.match);
306
+ if (fitting.length === 0) {
307
+ throw new HandelsregisterError('not_found', 'No register sheet has this number at this court.', {
308
+ step: 'result_list',
309
+ countedRequests: progressArg.countedRequests,
310
+ matches,
311
+ });
312
+ }
313
+ if (fitting.length > 1) {
314
+ throw new HandelsregisterError('ambiguous', 'Several register sheets have this number at this court.', {
315
+ step: 'result_list',
316
+ countedRequests: progressArg.countedRequests,
317
+ matches,
318
+ });
319
+ }
320
+ return fitting[0];
321
+ }
322
+ async retrieveStructuredContent(rowArg, outcomeArg, sessionArg, progressArg) {
323
+ await this.acquireSlot('retrieval', 'structured_content', progressArg);
324
+ try {
325
+ progressArg.step = 'structured_content';
326
+ const resultForm = outcomeArg.list.form;
327
+ const submission = rowArg.documentSubmissions.get('SI');
328
+ if (!resultForm || !submission) {
329
+ throw new HandelsregisterError('unexpected_response', 'The result list offers structured content without a way to retrieve it.');
330
+ }
331
+ const fields = [...resultForm.fields];
332
+ for (const [name, value] of submission) {
333
+ forms.setField(fields, name, value);
334
+ }
335
+ progressArg.countedRequests += 1;
336
+ const answer = await sessionArg.post(sessionArg.resolve(resultForm.action, outcomeArg.pageUrl), fields);
337
+ if (/html/i.test(answer.contentType)) {
338
+ this.throwIfBlocked(decodeUtf8(answer.body));
339
+ throw new HandelsregisterError('unexpected_response', 'The portal answered with a page instead of the structured content.');
340
+ }
341
+ let xml;
342
+ try {
343
+ xml = new TextDecoder('utf-8', { fatal: true }).decode(answer.body);
344
+ }
345
+ catch (error) {
346
+ throw new HandelsregisterError('invalid_structured_content', 'The structured content is not valid UTF-8.', { cause: error });
347
+ }
348
+ const content = parseStructuredContent(xml);
349
+ this.checkContentBelongsToRow(content, rowArg.match);
350
+ return content;
351
+ }
352
+ catch (error) {
353
+ throw error instanceof HandelsregisterError ? inCall(error, progressArg) : error;
354
+ }
355
+ }
356
+ /** the structured content must describe the sheet of the row it was retrieved for */
357
+ checkContentBelongsToRow(contentArg, matchArg) {
358
+ const reference = matchArg.reference;
359
+ const contentNumber = contentArg.register.number ? parseRegisterNumber(contentArg.register.number) : undefined;
360
+ const rowNumber = parseRegisterNumber(reference.number);
361
+ if ((contentArg.register.courtCode !== undefined && contentArg.register.courtCode !== reference.court.code) ||
362
+ (contentArg.register.type !== undefined && contentArg.register.type !== reference.type) ||
363
+ (contentNumber !== undefined && contentNumber.digits !== rowNumber?.digits)) {
364
+ throw new HandelsregisterError('unexpected_response', 'The structured content belongs to another register sheet.');
365
+ }
366
+ }
367
+ htmlDocumentOf(pageArg, messageArg) {
368
+ if (!/html/i.test(pageArg.contentType)) {
369
+ throw new HandelsregisterError('unexpected_response', messageArg);
370
+ }
371
+ return html.parseHtml(decodeUtf8(pageArg.body));
372
+ }
373
+ /** the register courts the search form offers */
374
+ courtsOf(formArg) {
375
+ return (formArg.options.get(field.court) ?? [])
376
+ .filter((optionArg) => optionArg.value !== '')
377
+ .map((optionArg) => ({ code: optionArg.value, name: optionArg.label }));
378
+ }
379
+ /** refuses with the portal's words when the page is its notice of a blocked retrieval */
380
+ throwIfBlocked(htmlArg) {
381
+ const document = html.parseHtml(htmlArg);
382
+ const notice = blockedRetrievalPattern.exec(html.textOf(document));
383
+ if (notice) {
384
+ throw new HandelsregisterError('refused', 'The register portal refused the retrieval from this address.', {
385
+ portalMessage: notice[0],
386
+ });
387
+ }
388
+ }
389
+ /** the message the search form shows, when the portal answered with the form again */
390
+ searchFormMessage(htmlArg) {
391
+ const document = html.parseHtml(htmlArg);
392
+ const messages = html.findById(document, searchFormMessagesId);
393
+ const text = messages ? html.textOf(messages) : '';
394
+ return text ? text : undefined;
395
+ }
396
+ }
397
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5oYW5kZWxzcmVnaXN0ZXJjbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9oYW5kZWxzcmVnaXN0ZXIvY2xhc3Nlcy5oYW5kZWxzcmVnaXN0ZXJjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG9CQUFvQixFQUE2QixNQUFNLG1DQUFtQyxDQUFDO0FBQ3BHLE9BQU8sRUFBRSxhQUFhLEVBQTRDLE1BQU0sNEJBQTRCLENBQUM7QUFDckcsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBQ3ZCLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsdUJBQXVCLEdBQ3hCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBZWxDLE9BQU8sRUFBRSxjQUFjLEVBQTJDLE1BQU0sMEJBQTBCLENBQUM7QUFDbkcsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdEUsT0FBTyxFQUFFLG1CQUFtQixFQUE2QixNQUFNLGlCQUFpQixDQUFDO0FBRWpGLE1BQU0sY0FBYyxHQUFHLHVDQUF1QyxDQUFDO0FBQy9ELE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQztBQUM1QixNQUFNLEtBQUssR0FBRztJQUNaLFFBQVEsRUFBRSxvQkFBb0I7SUFDOUIsV0FBVyxFQUFFLHlCQUF5QjtJQUN0QyxJQUFJLEVBQUUsd0JBQXdCO0lBQzlCLFlBQVksRUFBRSx3QkFBd0I7SUFDdEMsY0FBYyxFQUFFLHFCQUFxQjtJQUNyQyxLQUFLLEVBQUUsNEJBQTRCO0lBQ25DLFFBQVEsRUFBRSwrQkFBK0I7SUFDekMsYUFBYSxFQUFFLDJCQUEyQjtJQUMxQyxZQUFZLEVBQUUsZUFB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
@@ -0,0 +1,56 @@
1
+ import type { IRegisterMatch } from './interfaces.js';
2
+ /**
3
+ * Why a call failed:
4
+ * - `invalid_query`: the query or reference cannot be sent as it is (nothing was sent);
5
+ * - `rate_limited`: `SlidingWindowGate` refused the request; `retryAt` says when the next is possible;
6
+ * - `aborted`: the caller's signal aborted the call;
7
+ * - `timeout`: a request to the portal took longer than the client's limit;
8
+ * - `unreachable`: the portal could not be reached (name resolution, connection, TLS);
9
+ * - `refused`: the portal answered with an HTTP error, for example 403 when it blocks an address,
10
+ * 429 or 503 when it is overloaded (`status` carries the code), or with its notice that it refuses
11
+ * retrievals from this address (`portalMessage` carries its words);
12
+ * - `too_large`: an answer exceeded the client's size limit;
13
+ * - `unexpected_response`: an answer did not have the shape this version reads: the portal changed
14
+ * its pages, answered in another language, or showed an error page;
15
+ * - `not_found`: no register sheet matches the reference;
16
+ * - `ambiguous`: several register sheets match the reference; `matches` lists them;
17
+ * - `invalid_structured_content`: the structured register content could not be read.
18
+ */
19
+ export type THandelsregisterErrorCode = 'invalid_query' | 'rate_limited' | 'aborted' | 'timeout' | 'unreachable' | 'refused' | 'too_large' | 'unexpected_response' | 'not_found' | 'ambiguous' | 'invalid_structured_content';
20
+ /** the step of a call that failed */
21
+ export type THandelsregisterStep = 'search_form' | 'search' | 'result_list' | 'structured_content';
22
+ export interface IHandelsregisterErrorDetails {
23
+ status?: number;
24
+ retryAt?: number;
25
+ step?: THandelsregisterStep;
26
+ countedRequests?: number;
27
+ matches?: IRegisterMatch[];
28
+ portalMessage?: string;
29
+ cause?: unknown;
30
+ }
31
+ /**
32
+ * The typed error of the register client. Its message names the failure and never contains
33
+ * register data, so it can be logged.
34
+ */
35
+ export declare class HandelsregisterError extends Error {
36
+ readonly code: THandelsregisterErrorCode;
37
+ /** the HTTP status of a refusal */
38
+ readonly status?: number;
39
+ /** epoch ms of the next possible request (`rate_limited`) */
40
+ readonly retryAt?: number;
41
+ /** the step that failed */
42
+ readonly step?: THandelsregisterStep;
43
+ /**
44
+ * counted requests the call had sent before it failed. A request that was sent may have counted
45
+ * at the portal even when its answer did not arrive.
46
+ */
47
+ readonly countedRequests?: number;
48
+ /**
49
+ * the candidates of an `ambiguous` reference, and for `not_found` the entries with the same
50
+ * number whose location suffix differs
51
+ */
52
+ readonly matches?: IRegisterMatch[];
53
+ /** a message the portal showed instead of the expected page, German */
54
+ readonly portalMessage?: string;
55
+ constructor(codeArg: THandelsregisterErrorCode, messageArg: string, detailsArg?: IHandelsregisterErrorDetails);
56
+ }