@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.
- package/.smartconfig.json +20 -20
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/handelsregister/classes.handelsregisterclient.d.ts +64 -0
- package/dist_ts/handelsregister/classes.handelsregisterclient.js +397 -0
- package/dist_ts/handelsregister/classes.handelsregistererror.d.ts +56 -0
- package/dist_ts/handelsregister/classes.handelsregistererror.js +37 -0
- package/dist_ts/handelsregister/classes.portalsession.d.ts +46 -0
- package/dist_ts/handelsregister/classes.portalsession.js +160 -0
- package/dist_ts/handelsregister/classes.slidingwindowgate.d.ts +32 -0
- package/dist_ts/handelsregister/classes.slidingwindowgate.js +55 -0
- package/dist_ts/handelsregister/constants.d.ts +13 -0
- package/dist_ts/handelsregister/constants.js +19 -0
- package/dist_ts/handelsregister/data.codelists.d.ts +29 -0
- package/dist_ts/handelsregister/data.codelists.js +616 -0
- package/dist_ts/handelsregister/forms.d.ts +27 -0
- package/dist_ts/handelsregister/forms.js +77 -0
- package/dist_ts/handelsregister/html.d.ts +26 -0
- package/dist_ts/handelsregister/html.js +82 -0
- package/dist_ts/handelsregister/index.d.ts +9 -0
- package/dist_ts/handelsregister/index.js +10 -0
- package/dist_ts/handelsregister/interfaces.d.ts +240 -0
- package/dist_ts/handelsregister/interfaces.js +2 -0
- package/dist_ts/handelsregister/parse.searchresults.d.ts +35 -0
- package/dist_ts/handelsregister/parse.searchresults.js +175 -0
- package/dist_ts/handelsregister/parse.structuredcontent.d.ts +6 -0
- package/dist_ts/handelsregister/parse.structuredcontent.js +306 -0
- package/dist_ts/handelsregister/plugins.d.ts +4 -0
- package/dist_ts/handelsregister/plugins.js +8 -0
- package/dist_ts/handelsregister/references.d.ts +34 -0
- package/dist_ts/handelsregister/references.js +76 -0
- package/dist_ts/index.d.ts +0 -2
- package/dist_ts/index.js +1 -3
- package/dist_ts/plugins.d.ts +2 -20
- package/dist_ts/plugins.js +3 -22
- package/package.json +33 -37
- package/readme.md +159 -126
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/handelsregister/classes.handelsregisterclient.ts +474 -0
- package/ts/handelsregister/classes.handelsregistererror.ts +82 -0
- package/ts/handelsregister/classes.portalsession.ts +191 -0
- package/ts/handelsregister/classes.slidingwindowgate.ts +74 -0
- package/ts/handelsregister/constants.ts +30 -0
- package/ts/handelsregister/data.codelists.ts +640 -0
- package/ts/handelsregister/forms.ts +99 -0
- package/ts/handelsregister/html.ts +113 -0
- package/ts/handelsregister/index.ts +27 -0
- package/ts/handelsregister/interfaces.ts +272 -0
- package/ts/handelsregister/parse.searchresults.ts +241 -0
- package/ts/handelsregister/parse.structuredcontent.ts +338 -0
- package/ts/handelsregister/plugins.ts +15 -0
- package/ts/handelsregister/references.ts +115 -0
- package/ts/index.ts +0 -2
- package/ts/plugins.ts +0 -39
- package/dist_ts/classes.businessrecord.d.ts +0 -38
- package/dist_ts/classes.businessrecord.js +0 -90
- package/dist_ts/classes.handelsregister.d.ts +0 -134
- package/dist_ts/classes.handelsregister.js +0 -307
- package/dist_ts/classes.jsonldata.d.ts +0 -43
- package/dist_ts/classes.jsonldata.js +0 -68
- package/dist_ts/classes.main.opendata.d.ts +0 -25
- package/dist_ts/classes.main.opendata.js +0 -91
- package/dist_ts/laws/classes.lawrecord.d.ts +0 -24
- package/dist_ts/laws/classes.lawrecord.js +0 -181
- package/dist_ts/laws/classes.lawservice.d.ts +0 -52
- package/dist_ts/laws/classes.lawservice.js +0 -740
- package/dist_ts/laws/index.d.ts +0 -3
- package/dist_ts/laws/index.js +0 -4
- package/dist_ts/laws/interfaces.law.d.ts +0 -35
- package/dist_ts/laws/interfaces.law.js +0 -2
- package/readme.hints.md +0 -89
- package/ts/classes.businessrecord.ts +0 -67
- package/ts/classes.handelsregister.ts +0 -385
- package/ts/classes.jsonldata.ts +0 -114
- package/ts/classes.main.opendata.ts +0 -120
- package/ts/laws/classes.lawrecord.ts +0 -81
- package/ts/laws/classes.lawservice.ts +0 -1010
- package/ts/laws/index.ts +0 -3
- package/ts/laws/interfaces.law.ts +0 -48
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as html from './html.js';
|
|
2
|
+
|
|
3
|
+
/** an option of a select element */
|
|
4
|
+
export interface IFormOption {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** a form as a browser would submit it */
|
|
10
|
+
export interface IPortalForm {
|
|
11
|
+
id: string;
|
|
12
|
+
/** the action as the page states it, relative to the page */
|
|
13
|
+
action: string;
|
|
14
|
+
/** the successful controls with their current values, in document order */
|
|
15
|
+
fields: Array<[string, string]>;
|
|
16
|
+
/** the options of each select element, by name */
|
|
17
|
+
options: Map<string, IFormOption[]>;
|
|
18
|
+
/** the names of every control, including unchecked boxes and buttons */
|
|
19
|
+
controlNames: Set<string>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const skippedInputTypes = new Set(['submit', 'button', 'image', 'reset', 'file']);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Reads a form the way a browser collects it for submission: text and hidden inputs with their
|
|
26
|
+
* values, checked boxes and radios, textareas, and the selected (or first) option of each select.
|
|
27
|
+
*/
|
|
28
|
+
export const readForm = (documentArg: html.THtmlDocument, formIdArg: string): IPortalForm | undefined => {
|
|
29
|
+
const form = html.findById(documentArg, formIdArg);
|
|
30
|
+
if (!form || form.tagName !== 'form') {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const action = html.getAttribute(form, 'action');
|
|
34
|
+
if (!action) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const fields: Array<[string, string]> = [];
|
|
38
|
+
const options = new Map<string, IFormOption[]>();
|
|
39
|
+
const controlNames = new Set<string>();
|
|
40
|
+
for (const element of html.descendants(form)) {
|
|
41
|
+
const name = html.getAttribute(element, 'name');
|
|
42
|
+
if (!name) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (element.tagName === 'input') {
|
|
46
|
+
controlNames.add(name);
|
|
47
|
+
const type = (html.getAttribute(element, 'type') ?? 'text').toLowerCase();
|
|
48
|
+
if (skippedInputTypes.has(type)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (type === 'checkbox' || type === 'radio') {
|
|
52
|
+
if (html.getAttribute(element, 'checked') !== undefined) {
|
|
53
|
+
fields.push([name, html.getAttribute(element, 'value') ?? 'on']);
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
fields.push([name, html.getAttribute(element, 'value') ?? '']);
|
|
58
|
+
} else if (element.tagName === 'textarea') {
|
|
59
|
+
controlNames.add(name);
|
|
60
|
+
fields.push([name, element.childNodes.map((childArg) => ('value' in childArg ? childArg.value : '')).join('')]);
|
|
61
|
+
} else if (element.tagName === 'select') {
|
|
62
|
+
controlNames.add(name);
|
|
63
|
+
const selectOptions = html
|
|
64
|
+
.findAll(element, (optionArg) => optionArg.tagName === 'option')
|
|
65
|
+
.map((optionArg) => ({
|
|
66
|
+
value: html.getAttribute(optionArg, 'value') ?? html.textOf(optionArg),
|
|
67
|
+
label: html.textOf(optionArg),
|
|
68
|
+
selected: html.getAttribute(optionArg, 'selected') !== undefined,
|
|
69
|
+
}));
|
|
70
|
+
options.set(
|
|
71
|
+
name,
|
|
72
|
+
selectOptions.map((optionArg) => ({ value: optionArg.value, label: optionArg.label }))
|
|
73
|
+
);
|
|
74
|
+
const chosen = selectOptions.find((optionArg) => optionArg.selected) ?? selectOptions[0];
|
|
75
|
+
if (chosen) {
|
|
76
|
+
fields.push([name, chosen.value]);
|
|
77
|
+
}
|
|
78
|
+
} else if (element.tagName === 'button') {
|
|
79
|
+
controlNames.add(name);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { id: formIdArg, action, fields, options, controlNames };
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** sets a field to one value, replacing every earlier value of that name */
|
|
86
|
+
export const setField = (fieldsArg: Array<[string, string]>, nameArg: string, valueArg: string): void => {
|
|
87
|
+
const index = fieldsArg.findIndex(([fieldName]) => fieldName === nameArg);
|
|
88
|
+
const remaining = fieldsArg.filter(([fieldName]) => fieldName !== nameArg);
|
|
89
|
+
fieldsArg.length = 0;
|
|
90
|
+
fieldsArg.push(...remaining);
|
|
91
|
+
fieldsArg.splice(index >= 0 ? index : fieldsArg.length, 0, [nameArg, valueArg]);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/** removes every value of a field */
|
|
95
|
+
export const removeField = (fieldsArg: Array<[string, string]>, nameArg: string): void => {
|
|
96
|
+
const remaining = fieldsArg.filter(([fieldName]) => fieldName !== nameArg);
|
|
97
|
+
fieldsArg.length = 0;
|
|
98
|
+
fieldsArg.push(...remaining);
|
|
99
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
|
|
3
|
+
export type THtmlDocument = plugins.parse5.DefaultTreeAdapterTypes.Document;
|
|
4
|
+
export type THtmlElement = plugins.parse5.DefaultTreeAdapterTypes.Element;
|
|
5
|
+
type THtmlParentNode = plugins.parse5.DefaultTreeAdapterTypes.ParentNode;
|
|
6
|
+
type THtmlChildNode = plugins.parse5.DefaultTreeAdapterTypes.ChildNode;
|
|
7
|
+
|
|
8
|
+
export const parseHtml = (htmlArg: string): THtmlDocument => plugins.parse5.parse(htmlArg);
|
|
9
|
+
|
|
10
|
+
const isElement = (nodeArg: THtmlChildNode): nodeArg is THtmlElement => 'tagName' in nodeArg;
|
|
11
|
+
|
|
12
|
+
/** the element children of a node */
|
|
13
|
+
export const elementChildren = (nodeArg: THtmlParentNode): THtmlElement[] =>
|
|
14
|
+
nodeArg.childNodes.filter(isElement);
|
|
15
|
+
|
|
16
|
+
/** every element below a node, in document order */
|
|
17
|
+
export const descendants = (nodeArg: THtmlParentNode): THtmlElement[] => {
|
|
18
|
+
const result: THtmlElement[] = [];
|
|
19
|
+
const stack: THtmlElement[] = elementChildren(nodeArg).reverse();
|
|
20
|
+
while (stack.length > 0) {
|
|
21
|
+
const element = stack.pop() as THtmlElement;
|
|
22
|
+
result.push(element);
|
|
23
|
+
const children = element.tagName === 'template' ? [] : elementChildren(element);
|
|
24
|
+
for (let index = children.length - 1; index >= 0; index--) {
|
|
25
|
+
stack.push(children[index]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const getAttribute = (elementArg: THtmlElement, nameArg: string): string | undefined =>
|
|
32
|
+
elementArg.attrs.find((attrArg) => attrArg.name === nameArg)?.value;
|
|
33
|
+
|
|
34
|
+
export const hasClass = (elementArg: THtmlElement, classArg: string): boolean =>
|
|
35
|
+
(getAttribute(elementArg, 'class') ?? '').split(/\s+/).includes(classArg);
|
|
36
|
+
|
|
37
|
+
export const findById = (nodeArg: THtmlParentNode, idArg: string): THtmlElement | undefined =>
|
|
38
|
+
descendants(nodeArg).find((elementArg) => getAttribute(elementArg, 'id') === idArg);
|
|
39
|
+
|
|
40
|
+
export const findAll = (
|
|
41
|
+
nodeArg: THtmlParentNode,
|
|
42
|
+
predicateArg: (elementArg: THtmlElement) => boolean
|
|
43
|
+
): THtmlElement[] => descendants(nodeArg).filter(predicateArg);
|
|
44
|
+
|
|
45
|
+
export const findFirst = (
|
|
46
|
+
nodeArg: THtmlParentNode,
|
|
47
|
+
predicateArg: (elementArg: THtmlElement) => boolean
|
|
48
|
+
): THtmlElement | undefined => descendants(nodeArg).find(predicateArg);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* the raw text of a node and everything below it, scripts and styles left out: the text nodes in
|
|
52
|
+
* document order, separated by spaces. Walks the tree with its own stack, so no nesting depth a page
|
|
53
|
+
* can have exhausts the call stack.
|
|
54
|
+
*/
|
|
55
|
+
const rawText = (nodeArg: THtmlChildNode | THtmlParentNode): string => {
|
|
56
|
+
const pieces: string[] = [];
|
|
57
|
+
const stack: Array<THtmlChildNode | THtmlParentNode> = [nodeArg];
|
|
58
|
+
for (let node = stack.pop(); node !== undefined; node = stack.pop()) {
|
|
59
|
+
if ('value' in node && node.nodeName === '#text') {
|
|
60
|
+
pieces.push(node.value);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!('childNodes' in node)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if ('tagName' in node && (node.tagName === 'script' || node.tagName === 'style')) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
for (let index = node.childNodes.length - 1; index >= 0; index--) {
|
|
70
|
+
stack.push(node.childNodes[index]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return pieces.join(' ');
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** the text of a node with white space collapsed */
|
|
77
|
+
export const textOf = (nodeArg: THtmlChildNode | THtmlParentNode): string =>
|
|
78
|
+
rawText(nodeArg).replace(/\s+/g, ' ').trim();
|
|
79
|
+
|
|
80
|
+
/** the text of the text nodes directly inside an element */
|
|
81
|
+
export const ownTextOf = (elementArg: THtmlElement): string =>
|
|
82
|
+
elementArg.childNodes
|
|
83
|
+
.map((childArg) => ('value' in childArg && childArg.nodeName === '#text' ? childArg.value : ''))
|
|
84
|
+
.join(' ')
|
|
85
|
+
.replace(/\s+/g, ' ')
|
|
86
|
+
.trim();
|
|
87
|
+
|
|
88
|
+
/** the next element sibling */
|
|
89
|
+
export const nextElementSibling = (elementArg: THtmlElement): THtmlElement | undefined => {
|
|
90
|
+
const parent = elementArg.parentNode;
|
|
91
|
+
if (!parent) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const siblings = elementChildren(parent);
|
|
95
|
+
return siblings[siblings.indexOf(elementArg) + 1];
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** the previous element sibling */
|
|
99
|
+
export const previousElementSibling = (elementArg: THtmlElement): THtmlElement | undefined => {
|
|
100
|
+
const parent = elementArg.parentNode;
|
|
101
|
+
if (!parent) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const siblings = elementChildren(parent);
|
|
105
|
+
const index = siblings.indexOf(elementArg);
|
|
106
|
+
return index > 0 ? siblings[index - 1] : undefined;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** the language the document declares on its root element */
|
|
110
|
+
export const documentLanguage = (documentArg: THtmlDocument): string | undefined => {
|
|
111
|
+
const root = elementChildren(documentArg).find((elementArg) => elementArg.tagName === 'html');
|
|
112
|
+
return root ? getAttribute(root, 'lang') : undefined;
|
|
113
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from './interfaces.js';
|
|
2
|
+
export {
|
|
3
|
+
HandelsregisterError,
|
|
4
|
+
type IHandelsregisterErrorDetails,
|
|
5
|
+
type THandelsregisterErrorCode,
|
|
6
|
+
type THandelsregisterStep,
|
|
7
|
+
} from './classes.handelsregistererror.js';
|
|
8
|
+
export { HandelsregisterClient } from './classes.handelsregisterclient.js';
|
|
9
|
+
export { SlidingWindowGate, type ISlidingWindowGateOptions } from './classes.slidingwindowgate.js';
|
|
10
|
+
export {
|
|
11
|
+
portalMaximumHits,
|
|
12
|
+
portalRequestsPerHour,
|
|
13
|
+
registerDocuments,
|
|
14
|
+
registerTypes,
|
|
15
|
+
structuredContentNotice,
|
|
16
|
+
} from './constants.js';
|
|
17
|
+
export { registerCourts } from './data.codelists.js';
|
|
18
|
+
export {
|
|
19
|
+
findRegisterCourt,
|
|
20
|
+
formatRegisterReference,
|
|
21
|
+
parseRegisterNumber,
|
|
22
|
+
parseRegisterReferenceText,
|
|
23
|
+
type IParsedRegisterReferenceText,
|
|
24
|
+
type IRegisterNumberParts,
|
|
25
|
+
} from './references.js';
|
|
26
|
+
export { parseSearchResults, type IParsedSearchResults } from './parse.searchresults.js';
|
|
27
|
+
export { parseStructuredContent } from './parse.structuredcontent.js';
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The register types the register portal searches: Handelsregister A and B, Genossenschafts-,
|
|
3
|
+
* Partnerschafts-, Vereins- and Gesellschaftsregister.
|
|
4
|
+
*/
|
|
5
|
+
export type TRegisterType = 'HRA' | 'HRB' | 'GnR' | 'PR' | 'VR' | 'GsR';
|
|
6
|
+
|
|
7
|
+
/** a register court of the portal */
|
|
8
|
+
export interface IRegisterCourt {
|
|
9
|
+
/** XJustiz court code, for example `H1101` */
|
|
10
|
+
code: string;
|
|
11
|
+
/** the court's name as the portal writes it after "Amtsgericht", for example `Bremen` */
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** one register sheet, as the portal identifies it */
|
|
16
|
+
export interface IRegisterReference {
|
|
17
|
+
court: IRegisterCourt;
|
|
18
|
+
type: TRegisterType;
|
|
19
|
+
/**
|
|
20
|
+
* the register number as the portal shows it, with the location suffix where the court uses
|
|
21
|
+
* one: `35230 HB`, `999928 NM`, `12345`
|
|
22
|
+
*/
|
|
23
|
+
number: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** what a caller passes to identify one register sheet */
|
|
27
|
+
export interface IRegisterReferenceInput {
|
|
28
|
+
/** XJustiz court code, see `registerCourts` and `findRegisterCourt()` */
|
|
29
|
+
courtCode: string;
|
|
30
|
+
type: TRegisterType;
|
|
31
|
+
/** `35230`, `35230 HB` or `35230HB`; a location suffix is compared when it is given */
|
|
32
|
+
number: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** the documents the portal offers for an entry */
|
|
36
|
+
export type TRegisterDocument = 'AD' | 'CD' | 'HD' | 'DK' | 'UT' | 'VÖ' | 'SI';
|
|
37
|
+
|
|
38
|
+
/** an earlier name of an entry, from the portal's result list */
|
|
39
|
+
export interface IRegisterFormerName {
|
|
40
|
+
name: string;
|
|
41
|
+
/** the seat at the time, when the portal names one */
|
|
42
|
+
seat?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The state of a register sheet in the portal's result list:
|
|
47
|
+
* - `current`: the portal's "aktuell";
|
|
48
|
+
* - `closed`: the portal's "Geschlossenes Registerblatt". The entry was deleted, or its sheet was
|
|
49
|
+
* closed because the entity moved to another court, changed its legal form or merged. The list
|
|
50
|
+
* does not say which;
|
|
51
|
+
* - `other`: a word this version does not know; `sheetStatusText` carries it.
|
|
52
|
+
*/
|
|
53
|
+
export type TRegisterSheetStatus = 'current' | 'closed' | 'other';
|
|
54
|
+
|
|
55
|
+
/** one row of the portal's result list */
|
|
56
|
+
export interface IRegisterMatch {
|
|
57
|
+
reference: IRegisterReference;
|
|
58
|
+
/** the court that kept the sheet before ("früher Amtsgericht …"), as the portal names it */
|
|
59
|
+
formerCourt?: string;
|
|
60
|
+
/** the federal state of the register court, as the portal names it */
|
|
61
|
+
federalState: string;
|
|
62
|
+
/** the current name (Firma) */
|
|
63
|
+
name: string;
|
|
64
|
+
/** the seat, as the portal shows it */
|
|
65
|
+
seat: string;
|
|
66
|
+
sheetStatus: TRegisterSheetStatus;
|
|
67
|
+
/** the portal's own word for the sheet status, German */
|
|
68
|
+
sheetStatusText: string;
|
|
69
|
+
/** earlier names, as the portal numbers them */
|
|
70
|
+
formerNames: IRegisterFormerName[];
|
|
71
|
+
/** the documents the portal offers for this entry; `SI` is the structured register content */
|
|
72
|
+
documents: TRegisterDocument[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The portal's note on the structured register content. Every result carries it, because the
|
|
77
|
+
* structured content is not binding: the current printout (AD) is.
|
|
78
|
+
*/
|
|
79
|
+
export interface IStructuredContentNotice {
|
|
80
|
+
/** the portal's words, German, verbatim */
|
|
81
|
+
de: string;
|
|
82
|
+
/** the same in English */
|
|
83
|
+
en: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface IRegisterSearchResult {
|
|
87
|
+
/** every row the portal returned, in its order; never narrowed down to one */
|
|
88
|
+
matches: IRegisterMatch[];
|
|
89
|
+
/** the portal stopped at its maximum number of hits (100) and asked for a narrower search */
|
|
90
|
+
truncated: boolean;
|
|
91
|
+
/** the portal's notice above the list, German, when it shows one */
|
|
92
|
+
portalNotice?: string;
|
|
93
|
+
/** epoch ms: when the result list arrived */
|
|
94
|
+
retrievedAt: number;
|
|
95
|
+
/** requests of this call that count against the portal's limit of 60 per hour (always 1) */
|
|
96
|
+
countedRequests: number;
|
|
97
|
+
notice: IStructuredContentNotice;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The state of the legal entity, from the structured register content (XJustiz list
|
|
102
|
+
* reg.status-rechtstraeger):
|
|
103
|
+
* - `active` ("aktiv");
|
|
104
|
+
* - `deleted` ("gelöscht");
|
|
105
|
+
* - `in_liquidation`: dissolved and being wound up ("in Abwicklung");
|
|
106
|
+
* - `insolvent` ("insolvent");
|
|
107
|
+
* - `merged`: merged into an entity that is not registered;
|
|
108
|
+
* - `unknown`: a code this version does not know.
|
|
109
|
+
*/
|
|
110
|
+
export type TRegisterEntityState =
|
|
111
|
+
| 'active'
|
|
112
|
+
| 'deleted'
|
|
113
|
+
| 'in_liquidation'
|
|
114
|
+
| 'insolvent'
|
|
115
|
+
| 'merged'
|
|
116
|
+
| 'unknown';
|
|
117
|
+
|
|
118
|
+
export interface IRegisterEntityStatus {
|
|
119
|
+
state: TRegisterEntityState;
|
|
120
|
+
/** code of the XJustiz list reg.status-rechtstraeger */
|
|
121
|
+
code: string;
|
|
122
|
+
/** its German designation, when the code is known */
|
|
123
|
+
label?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface IRegisterLegalForm {
|
|
127
|
+
/** code of the XUnternehmen list of legal forms, for example `221110` */
|
|
128
|
+
code: string;
|
|
129
|
+
/** short designation, for example `GmbH`, when the code is known */
|
|
130
|
+
short?: string;
|
|
131
|
+
/** full designation, for example `Gesellschaft mit beschränkter Haftung`, when the code is known */
|
|
132
|
+
long?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface IRegisterSeat {
|
|
136
|
+
city: string;
|
|
137
|
+
/** ISO 3166-1 alpha-2, when the state key is known */
|
|
138
|
+
country?: string;
|
|
139
|
+
/** the BfJ state key as the content gives it; `000` is Germany */
|
|
140
|
+
countryKey?: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** a business address; private addresses are never read */
|
|
144
|
+
export interface IRegisterAddress {
|
|
145
|
+
street?: string;
|
|
146
|
+
houseNumber?: string;
|
|
147
|
+
postalCode?: string;
|
|
148
|
+
city?: string;
|
|
149
|
+
/** ISO 3166-1 alpha-2, when the state key is known */
|
|
150
|
+
country?: string;
|
|
151
|
+
/** the BfJ state key as the content gives it; `000` is Germany */
|
|
152
|
+
countryKey?: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Someone the structured content names as entitled to represent the entity. Only the name and the
|
|
157
|
+
* function are read: birth dates, places of residence and addresses of people never leave the parser.
|
|
158
|
+
*/
|
|
159
|
+
export interface IRegisterRepresentative {
|
|
160
|
+
/** for a person: title, given names, name prefix, family name and suffix; for an organisation its name */
|
|
161
|
+
name: string;
|
|
162
|
+
kind: 'person' | 'organisation';
|
|
163
|
+
/** the function, German, for example `Geschäftsführer(in)`; absent for a code this version does not know */
|
|
164
|
+
function?: string;
|
|
165
|
+
/** code of the XJustiz list gds.rollenbezeichnung */
|
|
166
|
+
functionCode: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** the register sheet as the structured content states it */
|
|
170
|
+
export interface IRegisterContentRegister {
|
|
171
|
+
courtCode?: string;
|
|
172
|
+
type?: string;
|
|
173
|
+
number?: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** the parsed structured register content (SI) of one entry */
|
|
177
|
+
export interface IRegisterStructuredContent {
|
|
178
|
+
/** whether the content describes the entity as an organisation or as a natural person */
|
|
179
|
+
entityKind: 'organisation' | 'person';
|
|
180
|
+
name: string;
|
|
181
|
+
legalForm?: IRegisterLegalForm;
|
|
182
|
+
seat?: IRegisterSeat;
|
|
183
|
+
address?: IRegisterAddress;
|
|
184
|
+
register: IRegisterContentRegister;
|
|
185
|
+
/** absent when the content states no status */
|
|
186
|
+
status?: IRegisterEntityStatus;
|
|
187
|
+
/** ISO date of the most recent entry on the sheet; the content states no date for the status itself */
|
|
188
|
+
lastEntryOn?: string;
|
|
189
|
+
/** whether the content names who may represent the entity */
|
|
190
|
+
representationStated: boolean;
|
|
191
|
+
representatives: IRegisterRepresentative[];
|
|
192
|
+
/** when the portal produced the content, as it states it (ISO 8601) */
|
|
193
|
+
producedAt?: string;
|
|
194
|
+
binding: false;
|
|
195
|
+
notice: IStructuredContentNotice;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface IRegisterEntry {
|
|
199
|
+
/** the entry's row in the portal's result list */
|
|
200
|
+
match: IRegisterMatch;
|
|
201
|
+
/** the parsed structured content; null when the portal offers none for this entry */
|
|
202
|
+
structuredContent: IRegisterStructuredContent | null;
|
|
203
|
+
/** epoch ms: when the last answer of the portal arrived */
|
|
204
|
+
retrievedAt: number;
|
|
205
|
+
/** requests of this call that count against the portal's limit: 2, or 1 without structured content */
|
|
206
|
+
countedRequests: number;
|
|
207
|
+
notice: IStructuredContentNotice;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** a search by the name (Firma) */
|
|
211
|
+
export interface IRegisterNameQuery {
|
|
212
|
+
/** keywords of the name */
|
|
213
|
+
name: string;
|
|
214
|
+
/** `all` keywords (default), `any` keyword, or the `exact` name */
|
|
215
|
+
match?: 'all' | 'any' | 'exact';
|
|
216
|
+
/** the seat or the place of a branch */
|
|
217
|
+
seat?: string;
|
|
218
|
+
type?: TRegisterType;
|
|
219
|
+
courtCode?: string;
|
|
220
|
+
/** also closed register sheets (deleted entries) */
|
|
221
|
+
includeClosed?: boolean;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** a search by register number; without a court, every court's entry with that number is returned */
|
|
225
|
+
export interface IRegisterNumberQuery {
|
|
226
|
+
type: TRegisterType;
|
|
227
|
+
/** `35230`, `35230 HB` or `35230HB`; with a location suffix only rows with that suffix are returned */
|
|
228
|
+
number: string;
|
|
229
|
+
courtCode?: string;
|
|
230
|
+
/** also closed register sheets (deleted entries) */
|
|
231
|
+
includeClosed?: boolean;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type TRegisterSearchQuery = IRegisterNameQuery | IRegisterNumberQuery;
|
|
235
|
+
|
|
236
|
+
/** the two kinds of request the portal's terms count: at most 60 together per hour */
|
|
237
|
+
export type TRegisterCountedRequestKind = 'search' | 'retrieval';
|
|
238
|
+
|
|
239
|
+
export interface IRegisterCountedRequest {
|
|
240
|
+
kind: TRegisterCountedRequestKind;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Decides whether the next counted request may be made. The client calls `acquire()` before
|
|
245
|
+
* every search and every retrieval, before the step contacts the portal. Resolve to allow the
|
|
246
|
+
* request; throw to refuse it, and nothing is sent. A `HandelsregisterError` reaches the caller
|
|
247
|
+
* with the refused step and the requests the call counted before it; any other error reaches the
|
|
248
|
+
* caller unchanged.
|
|
249
|
+
*/
|
|
250
|
+
export interface IRegisterRequestGate {
|
|
251
|
+
acquire(request: IRegisterCountedRequest): Promise<void>;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface IHandelsregisterClientOptions {
|
|
255
|
+
/** decides before every counted request whether it may be made; see `SlidingWindowGate` */
|
|
256
|
+
gate: IRegisterRequestGate;
|
|
257
|
+
/** default `https://www.handelsregister.de` */
|
|
258
|
+
portalUrl?: string;
|
|
259
|
+
/** sent as User-Agent; name your installation and a contact */
|
|
260
|
+
userAgent?: string;
|
|
261
|
+
/** limit for each HTTP request, including its body; default 20000 ms */
|
|
262
|
+
requestTimeoutMs?: number;
|
|
263
|
+
/** limit for each response body; default 5 MiB */
|
|
264
|
+
maxResponseBytes?: number;
|
|
265
|
+
/** clock for `retrievedAt`; default `Date.now` */
|
|
266
|
+
now?: () => number;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface IRegisterCallOptions {
|
|
270
|
+
/** aborts the call; a request already sent may still have counted */
|
|
271
|
+
signal?: AbortSignal;
|
|
272
|
+
}
|