@fin.cx/opendata 4.8.0 → 4.9.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/gleif/classes.gleifclient.d.ts +26 -0
- package/dist_ts/gleif/classes.gleifclient.js +214 -0
- package/dist_ts/gleif/classes.gleiferror.d.ts +6 -0
- package/dist_ts/gleif/classes.gleiferror.js +11 -0
- package/dist_ts/gleif/crosswalk.d.ts +7 -0
- package/dist_ts/gleif/crosswalk.js +25 -0
- package/dist_ts/gleif/csv.d.ts +2 -0
- package/dist_ts/gleif/csv.js +75 -0
- package/dist_ts/gleif/data.crosswalk.d.ts +12 -0
- package/dist_ts/gleif/data.crosswalk.js +1265 -0
- package/dist_ts/gleif/index.d.ts +6 -0
- package/dist_ts/gleif/index.js +7 -0
- package/dist_ts/gleif/interfaces.d.ts +101 -0
- package/dist_ts/gleif/interfaces.js +2 -0
- package/dist_ts/gleif/plugins.d.ts +1 -0
- package/dist_ts/gleif/plugins.js +3 -0
- package/dist_ts/gleif/records.d.ts +6 -0
- package/dist_ts/gleif/records.js +107 -0
- package/dist_ts/gleif/stream.zip.d.ts +2 -0
- package/dist_ts/gleif/stream.zip.js +54 -0
- package/dist_ts/plugins.d.ts +2 -0
- package/dist_ts/plugins.js +4 -1
- package/package.json +7 -2
- package/readme.md +76 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/gleif/classes.gleifclient.ts +170 -0
- package/ts/gleif/classes.gleiferror.ts +8 -0
- package/ts/gleif/crosswalk.ts +29 -0
- package/ts/gleif/csv.ts +60 -0
- package/ts/gleif/data.crosswalk.ts +1271 -0
- package/ts/gleif/index.ts +6 -0
- package/ts/gleif/interfaces.ts +107 -0
- package/ts/gleif/plugins.ts +2 -0
- package/ts/gleif/records.ts +104 -0
- package/ts/gleif/stream.zip.ts +43 -0
- package/ts/plugins.ts +4 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './interfaces.js';
|
|
2
|
+
export { GleifClient, gleifDeltaKinds, gleifGoldenCopyBaseUrl, gleifRestBaseUrl } from './classes.gleifclient.js';
|
|
3
|
+
export { GleifError, type TGleifErrorCode } from './classes.gleiferror.js';
|
|
4
|
+
export { parseGleifRestRecord } from './records.js';
|
|
5
|
+
export { courtFromRegistrationAuthority, registrationAuthorityFromCourt, parseRegistrationAuthorityEntityId, registerReferenceFromRegistrationAuthority } from './crosswalk.js';
|
|
6
|
+
export { germanRegistrationAuthorities, gleifUnmappedCourts, gleifRegistrationAuthoritiesSource } from './data.crosswalk.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './interfaces.js';
|
|
2
|
+
export { GleifClient, gleifDeltaKinds, gleifGoldenCopyBaseUrl, gleifRestBaseUrl } from './classes.gleifclient.js';
|
|
3
|
+
export { GleifError } from './classes.gleiferror.js';
|
|
4
|
+
export { parseGleifRestRecord } from './records.js';
|
|
5
|
+
export { courtFromRegistrationAuthority, registrationAuthorityFromCourt, parseRegistrationAuthorityEntityId, registerReferenceFromRegistrationAuthority } from './crosswalk.js';
|
|
6
|
+
export { germanRegistrationAuthorities, gleifUnmappedCourts, gleifRegistrationAuthoritiesSource } from './data.crosswalk.js';
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9nbGVpZi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbEgsT0FBTyxFQUFFLFVBQVUsRUFBd0IsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLDhCQUE4QixFQUFFLGtDQUFrQyxFQUFFLDBDQUEwQyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEwsT0FBTyxFQUFFLDZCQUE2QixFQUFFLG1CQUFtQixFQUFFLGtDQUFrQyxFQUFFLE1BQU0scUJBQXFCLENBQUMifQ==
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { TRegisterType } from '../handelsregister/interfaces.js';
|
|
2
|
+
export interface IGleifName {
|
|
3
|
+
name: string;
|
|
4
|
+
language?: string;
|
|
5
|
+
/** The published other-name type; absent for the legal name. */
|
|
6
|
+
type?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface IGleifAddress {
|
|
9
|
+
addressLines: string[];
|
|
10
|
+
city: string;
|
|
11
|
+
country: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
region?: string;
|
|
14
|
+
postalCode?: string;
|
|
15
|
+
addressNumber?: string;
|
|
16
|
+
addressNumberWithinBuilding?: string;
|
|
17
|
+
mailRouting?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Level 1 reference data, with source strings and ISO 8601 dates preserved. No persistence. */
|
|
20
|
+
export interface IGleifRecord {
|
|
21
|
+
lei: string;
|
|
22
|
+
legalName: IGleifName;
|
|
23
|
+
otherNames: IGleifName[];
|
|
24
|
+
transliteratedOtherNames: IGleifName[];
|
|
25
|
+
legalForm?: {
|
|
26
|
+
elfCode?: string;
|
|
27
|
+
other?: string;
|
|
28
|
+
};
|
|
29
|
+
legalAddress: IGleifAddress;
|
|
30
|
+
headquartersAddress: IGleifAddress;
|
|
31
|
+
jurisdiction?: string;
|
|
32
|
+
entityStatus: string;
|
|
33
|
+
entityCategory?: string;
|
|
34
|
+
registrationAuthority?: {
|
|
35
|
+
id?: string;
|
|
36
|
+
otherId?: string;
|
|
37
|
+
entityId?: string;
|
|
38
|
+
};
|
|
39
|
+
registrationStatus: string;
|
|
40
|
+
initialRegistrationDate: string;
|
|
41
|
+
lastUpdateDate: string;
|
|
42
|
+
}
|
|
43
|
+
export type TGleifDelta = 'IntraDay' | 'LastDay' | 'LastWeek' | 'LastMonth';
|
|
44
|
+
export type TGleifFileKind = 'GoldenCopy' | TGleifDelta;
|
|
45
|
+
/** The API's LEI-CDF 3.1 ZIP/CSV descriptor. `size` is compressed bytes. */
|
|
46
|
+
export interface IGleifGoldenCopyFile {
|
|
47
|
+
url: string;
|
|
48
|
+
format: 'csv';
|
|
49
|
+
cdfVersion: 'LEI_3.1';
|
|
50
|
+
kind: TGleifFileKind;
|
|
51
|
+
recordCount: number;
|
|
52
|
+
size: number;
|
|
53
|
+
}
|
|
54
|
+
export interface IGleifPublish {
|
|
55
|
+
/** UTC publication label exactly as returned, `YYYY-MM-DD HH:mm:ss`. */
|
|
56
|
+
publishDate: string;
|
|
57
|
+
fullFile: IGleifGoldenCopyFile;
|
|
58
|
+
deltaFiles: Record<TGleifDelta, IGleifGoldenCopyFile>;
|
|
59
|
+
}
|
|
60
|
+
export type TGleifFetch = (input: string, init: RequestInit) => Promise<Response>;
|
|
61
|
+
export interface IGleifClientOptions {
|
|
62
|
+
fetch?: TGleifFetch;
|
|
63
|
+
/** Default: https://goldencopy.gleif.org/api/v2 */
|
|
64
|
+
goldenCopyBaseUrl?: string;
|
|
65
|
+
/** Default: https://api.gleif.org/api/v1 */
|
|
66
|
+
restBaseUrl?: string;
|
|
67
|
+
userAgent?: string;
|
|
68
|
+
/** Per request, including streaming and consumer time; default 30 minutes. */
|
|
69
|
+
timeoutMs?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface IGleifReadOptions {
|
|
72
|
+
/** ISO 3166-1 alpha-2; compares the legal address's country, not the headquarters. */
|
|
73
|
+
country?: string;
|
|
74
|
+
/** Exact legal jurisdiction, e.g. DE or US-DE. Both filters, if given, must match. */
|
|
75
|
+
jurisdiction?: string;
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
/** Maximum CSV row size in Unicode code points, including the header; default 1,048,576. */
|
|
78
|
+
maxRowChars?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface IGleifStreamOptions extends IGleifReadOptions {
|
|
81
|
+
/** Default GoldenCopy; deltas overlap and are current records, not event histories. */
|
|
82
|
+
kind?: TGleifFileKind;
|
|
83
|
+
}
|
|
84
|
+
export interface IGleifRegisterNumber {
|
|
85
|
+
type: TRegisterType;
|
|
86
|
+
number: string;
|
|
87
|
+
}
|
|
88
|
+
export interface IGleifRegistrationAuthority {
|
|
89
|
+
raCode: string;
|
|
90
|
+
name: string;
|
|
91
|
+
jurisdiction: string;
|
|
92
|
+
registerName: string;
|
|
93
|
+
courtCode?: string;
|
|
94
|
+
/** Present exactly when this German RA has no court in opendata's list. */
|
|
95
|
+
unmappedReason?: string;
|
|
96
|
+
}
|
|
97
|
+
export interface IGleifUnmappedCourt {
|
|
98
|
+
courtCode: string;
|
|
99
|
+
name: string;
|
|
100
|
+
reason: string;
|
|
101
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { fflate } from '../plugins.js';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// External dependencies for this subpath only; no portal client or storage imports.
|
|
2
|
+
export { fflate } from '../plugins.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2dsZWlmL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0ZBQW9GO0FBQ3BGLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUMifQ==
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IGleifRecord } from './interfaces.js';
|
|
2
|
+
/** Maps the documented JSON:API attributes, not the differently shaped Golden Copy JSON. */
|
|
3
|
+
export declare const parseGleifRestRecord: (valueArg: unknown) => IGleifRecord;
|
|
4
|
+
/** Column names verified against the published LEI-CDF 3.1 CSV (the optional values may be empty). */
|
|
5
|
+
export declare const gleifCsvColumns: readonly ["LEI", "Entity.LegalName", "Entity.LegalName.xmllang", "Entity.LegalJurisdiction", "Entity.EntityStatus", "Entity.EntityCategory", "Entity.LegalForm.EntityLegalFormCode", "Entity.LegalForm.OtherLegalForm", "Entity.RegistrationAuthority.RegistrationAuthorityID", "Entity.RegistrationAuthority.OtherRegistrationAuthorityID", "Entity.RegistrationAuthority.RegistrationAuthorityEntityID", "Registration.RegistrationStatus", "Registration.InitialRegistrationDate", "Registration.LastUpdateDate", ...string[]];
|
|
6
|
+
export declare const csvRecordMapper: (headerArg: string[]) => ((rowArg: string[]) => IGleifRecord);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { GleifError } from './classes.gleiferror.js';
|
|
2
|
+
const bad = (labelArg) => { throw new GleifError('unexpected_answer', `Missing or invalid GLEIF ${labelArg}.`); };
|
|
3
|
+
const object = (valueArg, labelArg) => valueArg && typeof valueArg === 'object' && !Array.isArray(valueArg) ? valueArg : bad(labelArg);
|
|
4
|
+
const optional = (valueArg) => {
|
|
5
|
+
if (valueArg === undefined || valueArg === null || valueArg === '')
|
|
6
|
+
return undefined;
|
|
7
|
+
return typeof valueArg === 'string' ? valueArg : bad('string');
|
|
8
|
+
};
|
|
9
|
+
const required = (valueArg, labelArg) => optional(valueArg) ?? bad(labelArg);
|
|
10
|
+
const date = (valueArg, labelArg) => {
|
|
11
|
+
const value = required(valueArg, labelArg);
|
|
12
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value)))
|
|
13
|
+
bad(labelArg);
|
|
14
|
+
return value;
|
|
15
|
+
};
|
|
16
|
+
const compact = (valueArg) => Object.fromEntries(Object.entries(valueArg).filter(([, valueArg]) => valueArg !== undefined));
|
|
17
|
+
const name = (valueArg) => {
|
|
18
|
+
const value = object(valueArg, 'name');
|
|
19
|
+
return compact({ name: required(value.name, 'name'), language: optional(value.language), type: optional(value.type) });
|
|
20
|
+
};
|
|
21
|
+
const names = (valueArg) => {
|
|
22
|
+
if (valueArg === undefined || valueArg === null)
|
|
23
|
+
return [];
|
|
24
|
+
if (!Array.isArray(valueArg))
|
|
25
|
+
bad('names');
|
|
26
|
+
return valueArg.map(name);
|
|
27
|
+
};
|
|
28
|
+
const address = (valueArg) => {
|
|
29
|
+
const value = object(valueArg, 'address');
|
|
30
|
+
if (!Array.isArray(value.addressLines) || value.addressLines.length < 1)
|
|
31
|
+
bad('address lines');
|
|
32
|
+
return compact({
|
|
33
|
+
addressLines: value.addressLines.map((lineArg) => required(lineArg, 'address line')),
|
|
34
|
+
city: required(value.city, 'city'), country: required(value.country, 'country'),
|
|
35
|
+
language: optional(value.language), region: optional(value.region), postalCode: optional(value.postalCode),
|
|
36
|
+
addressNumber: optional(value.addressNumber), addressNumberWithinBuilding: optional(value.addressNumberWithinBuilding), mailRouting: optional(value.mailRouting),
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
/** Maps the documented JSON:API attributes, not the differently shaped Golden Copy JSON. */
|
|
40
|
+
export const parseGleifRestRecord = (valueArg) => {
|
|
41
|
+
const data = object(object(valueArg, 'response').data, 'data');
|
|
42
|
+
if (data.type !== 'lei-records')
|
|
43
|
+
bad('resource type');
|
|
44
|
+
const attributes = object(data.attributes, 'attributes');
|
|
45
|
+
const entity = object(attributes.entity, 'entity');
|
|
46
|
+
const registration = object(attributes.registration, 'registration');
|
|
47
|
+
const lei = required(attributes.lei, 'LEI');
|
|
48
|
+
if (!/^[A-Z0-9]{18}\d{2}$/.test(lei) || data.id !== lei)
|
|
49
|
+
bad('LEI');
|
|
50
|
+
const legalForm = entity.legalForm === undefined || entity.legalForm === null ? undefined : object(entity.legalForm, 'legal form');
|
|
51
|
+
const registeredAt = entity.registeredAt === undefined || entity.registeredAt === null ? undefined : object(entity.registeredAt, 'registration authority');
|
|
52
|
+
const form = legalForm ? compact({ elfCode: optional(legalForm.id), other: optional(legalForm.other) }) : undefined;
|
|
53
|
+
const authority = compact({ id: optional(registeredAt?.id), otherId: optional(registeredAt?.other), entityId: optional(entity.registeredAs) });
|
|
54
|
+
return compact({
|
|
55
|
+
lei, legalName: name(entity.legalName), otherNames: names(entity.otherNames), transliteratedOtherNames: names(entity.transliteratedOtherNames),
|
|
56
|
+
legalForm: form && Object.keys(form).length ? form : undefined,
|
|
57
|
+
legalAddress: address(entity.legalAddress), headquartersAddress: address(entity.headquartersAddress),
|
|
58
|
+
jurisdiction: optional(entity.jurisdiction), entityStatus: required(entity.status, 'entity status'), entityCategory: optional(entity.category),
|
|
59
|
+
registrationAuthority: Object.keys(authority).length ? authority : undefined,
|
|
60
|
+
registrationStatus: required(registration.status, 'registration status'),
|
|
61
|
+
initialRegistrationDate: date(registration.initialRegistrationDate, 'initial registration date'), lastUpdateDate: date(registration.lastUpdateDate, 'last update date'),
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
/** Column names verified against the published LEI-CDF 3.1 CSV (the optional values may be empty). */
|
|
65
|
+
export const gleifCsvColumns = [
|
|
66
|
+
'LEI', 'Entity.LegalName', 'Entity.LegalName.xmllang', 'Entity.LegalJurisdiction', 'Entity.EntityStatus', 'Entity.EntityCategory',
|
|
67
|
+
'Entity.LegalForm.EntityLegalFormCode', 'Entity.LegalForm.OtherLegalForm',
|
|
68
|
+
'Entity.RegistrationAuthority.RegistrationAuthorityID', 'Entity.RegistrationAuthority.OtherRegistrationAuthorityID', 'Entity.RegistrationAuthority.RegistrationAuthorityEntityID',
|
|
69
|
+
'Registration.RegistrationStatus', 'Registration.InitialRegistrationDate', 'Registration.LastUpdateDate',
|
|
70
|
+
...['Entity.LegalAddress', 'Entity.HeadquartersAddress'].flatMap((prefixArg) => ['FirstAddressLine', 'City', 'Country'].map((fieldArg) => `${prefixArg}.${fieldArg}`)),
|
|
71
|
+
];
|
|
72
|
+
export const csvRecordMapper = (headerArg) => {
|
|
73
|
+
if (new Set(headerArg).size !== headerArg.length || gleifCsvColumns.some((columnArg) => !headerArg.includes(columnArg))) {
|
|
74
|
+
throw new GleifError('invalid_csv', 'Missing or duplicate LEI-CDF 3.1 columns.');
|
|
75
|
+
}
|
|
76
|
+
const indices = new Map(headerArg.map((columnArg, indexArg) => [columnArg, indexArg]));
|
|
77
|
+
const nameColumns = (prefixArg) => headerArg.filter((columnArg) => new RegExp(`^${prefixArg.replaceAll('.', '\\.')}\\.\\d+$`).test(columnArg));
|
|
78
|
+
const otherColumns = nameColumns('Entity.OtherEntityNames.OtherEntityName');
|
|
79
|
+
const transliteratedColumns = nameColumns('Entity.TransliteratedOtherEntityNames.TransliteratedOtherEntityName');
|
|
80
|
+
return (rowArg) => {
|
|
81
|
+
if (rowArg.length !== headerArg.length)
|
|
82
|
+
throw new GleifError('invalid_csv', 'LEI-CDF CSV row has a different column count from its header.');
|
|
83
|
+
const get = (columnArg) => {
|
|
84
|
+
const index = indices.get(columnArg);
|
|
85
|
+
return index === undefined ? undefined : rowArg[index];
|
|
86
|
+
};
|
|
87
|
+
const nameOf = (prefixArg) => ({ name: get(prefixArg), language: get(`${prefixArg}.xmllang`), type: get(`${prefixArg}.type`) });
|
|
88
|
+
const addressOf = (prefixArg) => ({
|
|
89
|
+
addressLines: [get(`${prefixArg}.FirstAddressLine`), ...[1, 2, 3].map((indexArg) => get(`${prefixArg}.AdditionalAddressLine.${indexArg}`))].filter(Boolean),
|
|
90
|
+
city: get(`${prefixArg}.City`), country: get(`${prefixArg}.Country`), language: get(`${prefixArg}.xmllang`), region: get(`${prefixArg}.Region`), postalCode: get(`${prefixArg}.PostalCode`),
|
|
91
|
+
addressNumber: get(`${prefixArg}.AddressNumber`), addressNumberWithinBuilding: get(`${prefixArg}.AddressNumberWithinBuilding`), mailRouting: get(`${prefixArg}.MailRouting`),
|
|
92
|
+
});
|
|
93
|
+
const lei = get('LEI');
|
|
94
|
+
return parseGleifRestRecord({ data: { type: 'lei-records', id: lei, attributes: { lei, entity: {
|
|
95
|
+
legalName: nameOf('Entity.LegalName'), otherNames: otherColumns.filter((columnArg) => get(columnArg)).map(nameOf),
|
|
96
|
+
transliteratedOtherNames: transliteratedColumns.filter((columnArg) => get(columnArg)).map(nameOf),
|
|
97
|
+
legalForm: { id: get('Entity.LegalForm.EntityLegalFormCode'), other: get('Entity.LegalForm.OtherLegalForm') },
|
|
98
|
+
legalAddress: addressOf('Entity.LegalAddress'), headquartersAddress: addressOf('Entity.HeadquartersAddress'),
|
|
99
|
+
jurisdiction: get('Entity.LegalJurisdiction'), status: get('Entity.EntityStatus'), category: get('Entity.EntityCategory'),
|
|
100
|
+
registeredAt: { id: get('Entity.RegistrationAuthority.RegistrationAuthorityID'), other: get('Entity.RegistrationAuthority.OtherRegistrationAuthorityID') },
|
|
101
|
+
registeredAs: get('Entity.RegistrationAuthority.RegistrationAuthorityEntityID'),
|
|
102
|
+
}, registration: {
|
|
103
|
+
status: get('Registration.RegistrationStatus'), initialRegistrationDate: get('Registration.InitialRegistrationDate'), lastUpdateDate: get('Registration.LastUpdateDate'),
|
|
104
|
+
} } } });
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3Jkcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2dsZWlmL3JlY29yZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR3JELE1BQU0sR0FBRyxHQUFHLENBQUMsUUFBZ0IsRUFBUyxFQUFFLEdBQUcsTUFBTSxJQUFJLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSw0QkFBNEIsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNqSSxNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQWlCLEVBQUUsUUFBZ0IsRUFBMkIsRUFBRSxDQUM5RSxRQUFRLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBbUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQzdILE1BQU0sUUFBUSxHQUFHLENBQUMsUUFBaUIsRUFBc0IsRUFBRTtJQUN6RCxJQUFJLFFBQVEsS0FBSyxTQUFTLElBQUksUUFBUSxLQUFLLElBQUksSUFBSSxRQUFRLEtBQUssRUFBRTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ3JGLE9BQU8sT0FBTyxRQUFRLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNqRSxDQUFDLENBQUM7QUFDRixNQUFNLFFBQVEsR0FBRyxDQUFDLFFBQWlCLEVBQUUsUUFBZ0IsRUFBVSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUN0RyxNQUFNLElBQUksR0FBRyxDQUFDLFFBQWlCLEVBQUUsUUFBZ0IsRUFBVSxFQUFFO0lBQzNELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxRQUFRLEVB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
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { GleifError } from './classes.gleiferror.js';
|
|
3
|
+
/** One CSV member, incrementally inflated. Input slices bound each synchronous output batch. */
|
|
4
|
+
export async function* unzipCsv(sourceArg) {
|
|
5
|
+
let member;
|
|
6
|
+
let complete = false;
|
|
7
|
+
let failure;
|
|
8
|
+
let output = [];
|
|
9
|
+
const unzipper = new plugins.fflate.Unzip((fileArg) => {
|
|
10
|
+
if (member || !fileArg.name.toLowerCase().endsWith('.csv')) {
|
|
11
|
+
throw new GleifError('invalid_archive', 'Expected exactly one CSV member in the Golden Copy ZIP.');
|
|
12
|
+
}
|
|
13
|
+
member = fileArg;
|
|
14
|
+
fileArg.ondata = (errorArg, dataArg, finalArg) => {
|
|
15
|
+
if (errorArg)
|
|
16
|
+
failure = errorArg;
|
|
17
|
+
else if (dataArg.length)
|
|
18
|
+
output.push(dataArg);
|
|
19
|
+
if (finalArg)
|
|
20
|
+
complete = true;
|
|
21
|
+
};
|
|
22
|
+
fileArg.start();
|
|
23
|
+
});
|
|
24
|
+
unzipper.register(plugins.fflate.UnzipInflate);
|
|
25
|
+
try {
|
|
26
|
+
for await (const chunk of sourceArg) {
|
|
27
|
+
for (let offset = 0; offset < chunk.length; offset += 1024) {
|
|
28
|
+
unzipper.push(chunk.subarray(offset, offset + 1024));
|
|
29
|
+
if (failure)
|
|
30
|
+
throw failure;
|
|
31
|
+
const ready = output;
|
|
32
|
+
output = [];
|
|
33
|
+
for (const data of ready)
|
|
34
|
+
yield data;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
unzipper.push(new Uint8Array(), true);
|
|
38
|
+
if (failure)
|
|
39
|
+
throw failure;
|
|
40
|
+
for (const data of output)
|
|
41
|
+
yield data;
|
|
42
|
+
if (!member || !complete)
|
|
43
|
+
throw new GleifError('invalid_archive', 'Missing or truncated CSV member in Golden Copy ZIP.');
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof GleifError)
|
|
47
|
+
throw error;
|
|
48
|
+
throw new GleifError('invalid_archive', 'Could not stream the Golden Copy ZIP.', undefined, { cause: error });
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
member?.terminate();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyZWFtLnppcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2dsZWlmL3N0cmVhbS56aXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXJELGdHQUFnRztBQUNoRyxNQUFNLENBQUMsS0FBSyxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBb0M7SUFDbEUsSUFBSSxNQUE0QyxDQUFDO0lBQ2pELElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztJQUNyQixJQUFJLE9BQTBCLENBQUM7SUFDL0IsSUFBSSxNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUM5QixNQUFNLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7UUFDcEQsSUFBSSxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQzNELE1BQU0sSUFBSSxVQUFVLENBQUMsaUJBQWlCLEVBQUUseURBQXlELENBQUMsQ0FBQztRQUNyRyxDQUFDO1FBQ0QsTUFBTSxHQUFHLE9BQU8sQ0FBQztRQUNqQixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRTtZQUMvQyxJQUFJLFFBQVE7Z0JBQUUsT0FBTyxHQUFHLFFBQVEsQ0FBQztpQkFDNUIsSUFBSSxPQUFPLENBQUMsTUFBTTtnQkFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlDLElBQUksUUFBUTtnQkFBRSxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ2hDLENBQUMsQ0FBQztRQUNGLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztJQUNILFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUM7UUFDSCxJQUFJLEtBQUssRUFBRSxNQUFNLEtBQUssSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNwQyxLQUFLLElBQUksTUFBTSxHQUFHLENBQUMsRUFBRSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQzNELFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ3JELElBQUksT0FBTztvQkFBRSxNQUFNLE9BQU8sQ0FBQztnQkFDM0IsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDO2dCQUNyQixNQUFNLEdBQUcsRUFBRSxDQUFDO2dCQUNaLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSztvQkFBRSxNQUFNLElBQUksQ0FBQztZQUN2QyxDQUFDO1FBQ0gsQ0FBQztRQUNELFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxVQUFVLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFJLE9BQU87WUFBRSxNQUFNLE9BQU8sQ0FBQztRQUMzQixLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU07WUFBRSxNQUFNLElBQUksQ0FBQztRQUN0QyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsUUFBUTtZQUFFLE1BQU0sSUFBSSxVQUFVLENBQUMsaUJBQWlCLEVBQUUscURBQXFELENBQUMsQ0FBQztJQUMzSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksS0FBSyxZQUFZLFVBQVU7WUFBRSxNQUFNLEtBQUssQ0FBQztRQUM3QyxNQUFNLElBQUksVUFBVSxDQUFDLGlCQUFpQixFQUFFLHVDQUF1QyxFQUFFLFNBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2hILENBQUM7WUFBUyxDQUFDO1FBQ1QsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDIn0=
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -5,3 +5,5 @@ import * as smartpromise from '@push.rocks/smartpromise';
|
|
|
5
5
|
import * as smartrequest from '@push.rocks/smartrequest';
|
|
6
6
|
declare const getErrorMessage: (error: unknown) => string;
|
|
7
7
|
export { getErrorMessage, smartpath, smartpromise, smartrequest, };
|
|
8
|
+
import * as fflate from 'fflate';
|
|
9
|
+
export { fflate };
|
package/dist_ts/plugins.js
CHANGED
|
@@ -12,4 +12,7 @@ const getErrorMessage = (error) => {
|
|
|
12
12
|
return String(error);
|
|
13
13
|
};
|
|
14
14
|
export { getErrorMessage, smartpath, smartpromise, smartrequest, };
|
|
15
|
-
|
|
15
|
+
// third-party scope
|
|
16
|
+
import * as fflate from 'fflate';
|
|
17
|
+
export { fflate };
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBRWxDLE9BQU8sRUFDTCxJQUFJLEdBQ0wsQ0FBQTtBQUVELG9CQUFvQjtBQUNwQixPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBQ25ELE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUV6RCxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQWMsRUFBRSxFQUFFO0lBQ3pDLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRSxDQUFDO1FBQzNCLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUN2QixDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkIsQ0FBQyxDQUFDO0FBRUYsT0FBTyxFQUNMLGVBQWUsRUFDZixTQUFTLEVBQ1QsWUFBWSxFQUNaLFlBQVksR0FDYixDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyJ9
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fin.cx/opendata",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, published financial statements read from their HTML, PDF or ESEF documents, and stock and crypto prices and fundamentals from several providers.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist_ts/financialstatements/index.d.ts",
|
|
35
35
|
"import": "./dist_ts/financialstatements/index.js"
|
|
36
36
|
},
|
|
37
|
+
"./gleif": {
|
|
38
|
+
"types": "./dist_ts/gleif/index.d.ts",
|
|
39
|
+
"import": "./dist_ts/gleif/index.js"
|
|
40
|
+
},
|
|
37
41
|
"./package.json": "./package.json"
|
|
38
42
|
},
|
|
39
43
|
"type": "module",
|
|
@@ -42,7 +46,7 @@
|
|
|
42
46
|
"devDependencies": {
|
|
43
47
|
"@git.zone/tsbuild": "^6.0.2",
|
|
44
48
|
"@git.zone/tsrun": "^3.0.3",
|
|
45
|
-
"@git.zone/tstest": "^7.2.
|
|
49
|
+
"@git.zone/tstest": "^7.2.1",
|
|
46
50
|
"@push.rocks/qenv": "^6.1.3",
|
|
47
51
|
"@types/node": "26.6.4"
|
|
48
52
|
},
|
|
@@ -52,6 +56,7 @@
|
|
|
52
56
|
"@push.rocks/smartpromise": "^4.3.0",
|
|
53
57
|
"@push.rocks/smartrequest": "^5.0.1",
|
|
54
58
|
"@push.rocks/smartxml": "^2.1.0",
|
|
59
|
+
"fflate": "0.8.3",
|
|
55
60
|
"parse5": "^8.0.1",
|
|
56
61
|
"pdfjs-dist": "^6.3.289"
|
|
57
62
|
},
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`@fin.cx/opendata` is a TypeScript toolbox for open business and market data: stock and crypto prices, SEC fundamentals, lookups in the German registers through the register portal of the federal states, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index for index clauses, and the figures of published financial statements. It is built for programmers who want scriptable APIs and real workflows instead of a thin wrapper around one remote endpoint.
|
|
4
4
|
|
|
5
|
-
It gives you
|
|
5
|
+
It gives you nine practical lanes in one package:
|
|
6
6
|
|
|
7
7
|
- `StockPriceService` for stock and crypto prices with caching, retries, failover, historical ranges, and intraday support
|
|
8
8
|
- `FundamentalsService` and `StockDataService` for SEC fundamentals and combined price + fundamentals payloads
|
|
@@ -12,6 +12,7 @@ It gives you eight practical lanes in one package:
|
|
|
12
12
|
- VAT ID confirmation, from `@fin.cx/opendata/vatid`, over the BZSt's eVatR REST API (the confirmation of § 18e UStG, simple or qualified) and the European Commission's VIES REST API, without any storage
|
|
13
13
|
- the consumer price index, from `@fin.cx/opendata/cpi`, for the Verbraucherpreisindex für Deutschland of the Statistisches Bundesamt as the Deutsche Bundesbank republishes it, with the arithmetic of index clauses (Wertsicherungsklauseln, § 557b BGB), without any storage
|
|
14
14
|
- published financial statements, from `@fin.cx/opendata/financialstatements`, for the balance sheet and the income statement under the HGB from the HTML or the PDF the Unternehmensregister shows, and the facts of an ESEF report, read from a document the caller obtained, without any request or storage
|
|
15
|
+
- GLEIF Level 1 data, from `@fin.cx/opendata/gleif`, for streamed Golden Copy full/delta imports, single-LEI lookup, and German registration-authority codes mapped to XJustiz register courts
|
|
15
16
|
|
|
16
17
|
## Issue Reporting and Security
|
|
17
18
|
|
|
@@ -387,6 +388,78 @@ console.log({
|
|
|
387
388
|
});
|
|
388
389
|
```
|
|
389
390
|
|
|
391
|
+
### GLEIF Level 1 data (`@fin.cx/opendata/gleif`)
|
|
392
|
+
|
|
393
|
+
`GleifClient` discovers the current GLEIF Golden Copy publication, streams its LEI-CDF 3.1 ZIP/CSV records, or looks up one LEI through GLEIF's public JSON:API. It keeps no files or data. `fetch` is injectable; every request has a signal and a time limit, with no retries. Breaking a `for await` loop cancels the download. Only publication metadata and single-record JSON responses are collected (at most 2 MiB); the ZIP and CSV are read incrementally with backpressure and a default 1,048,576-character limit per CSV row. A completed stream checks the compressed byte and unfiltered record counts against the publication descriptor.
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
import {
|
|
397
|
+
GleifClient,
|
|
398
|
+
courtFromRegistrationAuthority,
|
|
399
|
+
registrationAuthorityFromCourt,
|
|
400
|
+
parseRegistrationAuthorityEntityId,
|
|
401
|
+
registerReferenceFromRegistrationAuthority,
|
|
402
|
+
} from '@fin.cx/opendata/gleif';
|
|
403
|
+
|
|
404
|
+
const gleif = new GleifClient({ userAgent: 'Example Books (+https://example.com/contact)' });
|
|
405
|
+
const publish = await gleif.getLatestPublish();
|
|
406
|
+
// Save this descriptor in your own store to identify the import's publication.
|
|
407
|
+
for await (const record of gleif.readGoldenCopy(publish.fullFile, { country: 'DE' })) {
|
|
408
|
+
console.log(record.lei, record.legalName.name, record.registrationAuthority);
|
|
409
|
+
}
|
|
410
|
+
// Or discover and stream in one call. Other kinds: GoldenCopy, LastDay, LastWeek, LastMonth.
|
|
411
|
+
for await (const record of gleif.streamRecords({ kind: 'IntraDay', jurisdiction: 'DE' })) {
|
|
412
|
+
console.log(record.lei, record.lastUpdateDate);
|
|
413
|
+
}
|
|
414
|
+
const record = await gleif.lookup('529900W18LQJJN6SJ336');
|
|
415
|
+
const court = courtFromRegistrationAuthority('RA000222'); // { code: 'H1101', name: 'Bremen' }
|
|
416
|
+
const raCode = registrationAuthorityFromCourt('H1101'); // RA000222
|
|
417
|
+
const number = parseRegistrationAuthorityEntityId('HRB 35230HB'); // { type: 'HRB', number: '35230 HB' }
|
|
418
|
+
const reference = registerReferenceFromRegistrationAuthority('RA000222', 'HRB 35230HB');
|
|
419
|
+
// IRegisterReference: { court, type: 'HRB', number: '35230 HB' }
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
The exact yielded/lookup contract is `IGleifRecord`:
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
interface IGleifRecord {
|
|
426
|
+
lei: string;
|
|
427
|
+
legalName: IGleifName;
|
|
428
|
+
otherNames: IGleifName[];
|
|
429
|
+
transliteratedOtherNames: IGleifName[];
|
|
430
|
+
legalForm?: { elfCode?: string; other?: string };
|
|
431
|
+
legalAddress: IGleifAddress;
|
|
432
|
+
headquartersAddress: IGleifAddress;
|
|
433
|
+
jurisdiction?: string;
|
|
434
|
+
entityStatus: string;
|
|
435
|
+
entityCategory?: string;
|
|
436
|
+
registrationAuthority?: { id?: string; otherId?: string; entityId?: string };
|
|
437
|
+
registrationStatus: string;
|
|
438
|
+
initialRegistrationDate: string;
|
|
439
|
+
lastUpdateDate: string;
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
`IGleifName` carries `name`, optional `language`, and optional published other-name `type`. `IGleifAddress` carries `addressLines`, `city`, `country`, and optional `language`, `region`, `postalCode`, `addressNumber`, `addressNumberWithinBuilding` and `mailRouting`. Empty optional source fields are absent, other-name lists are arrays, and dates remain the published ISO 8601 strings, including fractional seconds. ELF codes remain codes; no legal-form designation is invented. Status and category strings remain as published. `country` compares the legal address's ISO country, `jurisdiction` compares the exact legal jurisdiction; when both are supplied, both must match. Filtering happens after parsing each record, before yielding it.
|
|
444
|
+
|
|
445
|
+
The full file and delta descriptors are `IGleifGoldenCopyFile` (`url`, `format: 'csv'`, `cdfVersion: 'LEI_3.1'`, `kind`, `recordCount`, `size`). `getLatestPublish()` returns `IGleifPublish` (`publishDate`, `fullFile`, `deltaFiles`). Options include `fetch`, `goldenCopyBaseUrl`, `restBaseUrl`, `userAgent` and `timeoutMs` (default 30 minutes per request, including consumer time). Read calls accept `country`, `jurisdiction`, `signal` and `maxRowChars`. `lookup()` and discovery accept `signal`. `parseGleifRestRecord(json)` maps an already obtained JSON:API response without fetching. `GleifError` exposes `code` and, for HTTP errors, `httpStatus`.
|
|
446
|
+
|
|
447
|
+
GLEIF publishes full files three times daily and deltas for the preceding 8 hours (`IntraDay`), 24 hours (`LastDay`), 7 days (`LastWeek`) and 31 days (`LastMonth`). Level 1 deltas contain the current version of new or changed LEI records. They contain no per-record change kind: this module does not infer insert/update/delete events. The deletion flag described in the manual concerns Level 2 relationships, which this module does not read. A delta overlaps earlier windows; callers own their import checkpoint and idempotent persistence. Discovery selects the CSV format from GLEIF's descriptors rather than constructing file download URLs. Unsupported CDF versions or missing columns fail explicitly.
|
|
448
|
+
|
|
449
|
+
The generated German RA ↔ XJustiz crosswalk uses the official **GLEIF Registration Authorities List v1.9, 2026-09-30**. Its 177 German authorities contain 147 mapped courts and 30 non-court authorities with unmapped reasons. Of opendata's 150 court codes, 147 are mapped; `Y1303` (Arnstadt Zweigstelle Ilmenau), `Y1208` (Pößneck Zweigstelle Bad Lobenstein) and `R1105` (Langenfeld) have no distinct RA in that version. No parent/successor mapping is inferred. `germanRegistrationAuthorities`, `gleifUnmappedCourts` and `gleifRegistrationAuthoritiesSource` expose the list and its provenance. Unknown/unmapped codes and unparseable register identifiers return `undefined`. Register identifiers must state their type (HRA, HRB, GnR, PR, VR or GsR); leading zeros and location suffixes are preserved.
|
|
450
|
+
|
|
451
|
+
Reproduce the code list offline with `tsx scripts/generate.gleif-crosswalk.ts`, or verify it with `--check`. `--refresh` fetches only the small official RA CSV and updates the committed German subset and generated list. For a new RA-list version, update the version/date constants in the generator, review new names and mapping ambiguity, then refresh and run the exhaustive tests. The generator never contacts a register portal.
|
|
452
|
+
|
|
453
|
+
Official sources, read on 2026-10-13:
|
|
454
|
+
|
|
455
|
+
- [Golden Copy and Delta Files overview](https://www.gleif.org/en/lei-data/gleif-golden-copy) and [specification/user manual v2.2](https://www.gleif.org/lei-data/gleif-golden-copy/2022-02-23_gleif-golden-copy-and-delta-files_v2.2-final.pdf), especially §§1.5–1.6 and 2.2: ZIP compression, formats, delta windows and API discovery at `https://goldencopy.gleif.org/api/v2/golden-copies/publishes/latest`. `leidata-preview.gleif.org` is the documented legacy domain for the same API.
|
|
456
|
+
- [LEI-CDF 3.1 format](https://www.gleif.org/en/lei-data/access-and-use-lei-data/level-1-data-lei-cdf-3-1-format) and [official XSD](https://www.gleif.org/lei-data/access-and-use-lei-data/level-1-data-lei-cdf-3-1-format/2021-03-04_lei-cdf-v3-1.xsd). CSV uses the published dotted columns, including `Entity.LegalName`, numbered other/transliterated names, `Entity.RegistrationAuthority.RegistrationAuthorityID` / `RegistrationAuthorityEntityID`, `Entity.LegalForm.EntityLegalFormCode`, addresses and registration dates. The parser reads the header rather than assuming column positions; fixtures preserve all 338 published columns.
|
|
457
|
+
- [GLEIF REST API documentation](https://api.gleif.org/docs): `GET https://api.gleif.org/api/v1/lei-records/{lei}`, JSON:API `data.attributes.entity` and `data.attributes.registration`, including `registeredAt.id` and `registeredAs`.
|
|
458
|
+
- [RA-list publication page](https://www.gleif.org/en/about-lei/code-lists/gleif-registration-authorities-list) and [v1.9 CSV](https://www.gleif.org/lei-data/code-lists/gleif-registration-authorities-list/2026-09-30_ra-list-v1.9.csv).
|
|
459
|
+
- [GLEIF LEI Data Terms of Use](https://www.gleif.org/en/meta/lei-data-terms-of-use): data available through its access service are provided under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
460
|
+
|
|
461
|
+
Fixtures are 100 records each from the 2026-10-13 00:00 full and intra-day CSVs, publication descriptors, and the REST documentation's single-record response. Tests make no GLEIF requests; ZIPs are created from these small CSV samples in memory. Provenance is in `test/fixtures/gleif/readme.md`. Full-population imports and GLEIF request-rate limits have not been verified; only bounded live samples, documented shapes and offline fixtures were checked.
|
|
462
|
+
|
|
390
463
|
### Register Lookups (Handelsregister)
|
|
391
464
|
|
|
392
465
|
`HandelsregisterClient` speaks to the register portal of the federal states over plain HTTP, the way a browser would: it opens the search form, sends the search, reads the result list and, for one entry, downloads the structured register content (SI, an XJustiz XML file) and parses it.
|
|
@@ -690,7 +763,7 @@ Four holidays apply only in part of a state:
|
|
|
690
763
|
|
|
691
764
|
The package ships no market or register data. Prices and fundamentals come at run time from the providers you register (Marketstack, CoinGecko, SEC EDGAR), and register entries come at run time from the register portal of the federal states (handelsregister.de), one lookup at a time. Financial statements come from the caller: `@fin.cx/opendata/financialstatements` reads the documents it is given and fetches none.
|
|
692
765
|
|
|
693
|
-
The package carries two kinds of data: the holiday rules of `@fin.cx/opendata/holidays` (`ts/holidays/data.holidays.ts`), described at the end of this section, and the code tables that `@fin.cx/opendata/handelsregister` uses to decode the structured register content (`ts/handelsregister/data.codelists.ts`). The code tables are official code lists, published on XRepository (https://www.xrepository.de), and were taken on 2026-09-23:
|
|
766
|
+
The GLEIF module also carries the generated RA ↔ court crosswalk described above. The package carries two other kinds of data: the holiday rules of `@fin.cx/opendata/holidays` (`ts/holidays/data.holidays.ts`), described at the end of this section, and the code tables that `@fin.cx/opendata/handelsregister` uses to decode the structured register content (`ts/handelsregister/data.codelists.ts`). The code tables are official code lists, published on XRepository (https://www.xrepository.de), and were taken on 2026-09-23:
|
|
694
767
|
|
|
695
768
|
| Table | Code list | Issued by |
|
|
696
769
|
| --- | --- | --- |
|
|
@@ -767,7 +840,7 @@ The reader of `@fin.cx/opendata/financialstatements` follows the outlines of the
|
|
|
767
840
|
pnpm test
|
|
768
841
|
```
|
|
769
842
|
|
|
770
|
-
Some market data tests hit live remote services, so they may depend on network access or optional API credentials. The register lookup is tested against minimal hand-written pages and structured content with synthetic values only; the tests never contact the register portal. The VAT ID clients are tested against the answers the two services gave on 2026-09-27 to their documented test values (`test/fixtures/vatid/`); the tests never contact them. The consumer price index client is tested against the answers the Bundesbank's API gave on 2026-10-05 and two answers written by hand from them (`test/fixtures/cpi/`); the tests never contact it. The financial statement reader is tested against HTML statements written by hand in the shape of the register's (`test/fixtures/financialstatements/`), PDFs the tests write themselves, and ESEF reports and packages the tests write, all with synthetic values; the tests contact no register.
|
|
843
|
+
GLEIF tests use only small real published fixtures (`test/fixtures/gleif/`) and injected fetches, including cancellation, malformed input, optional names and exhaustive crosswalk coverage. Some market data tests hit live remote services, so they may depend on network access or optional API credentials. The register lookup is tested against minimal hand-written pages and structured content with synthetic values only; the tests never contact the register portal. The VAT ID clients are tested against the answers the two services gave on 2026-09-27 to their documented test values (`test/fixtures/vatid/`); the tests never contact them. The consumer price index client is tested against the answers the Bundesbank's API gave on 2026-10-05 and two answers written by hand from them (`test/fixtures/cpi/`); the tests never contact it. The financial statement reader is tested against HTML statements written by hand in the shape of the register's (`test/fixtures/financialstatements/`), PDFs the tests write themselves, and ESEF reports and packages the tests write, all with synthetic values; the tests contact no register.
|
|
771
844
|
|
|
772
845
|
## License and Legal Information
|
|
773
846
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/opendata',
|
|
6
|
-
version: '4.
|
|
6
|
+
version: '4.9.0',
|
|
7
7
|
description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, published financial statements read from their HTML, PDF or ESEF documents, and stock and crypto prices and fundamentals from several providers.'
|
|
8
8
|
}
|