Skip to content

CYRRUSCZ/client-data-structure

Repository files navigation

CYRRUS Client Data Structure

TypeScript library providing normalized, serializable DTOs for client data (persons and companies) used in CYRRUS DocHub API and Cytron business core system integrations.

Version: 9.x (Cytron-compatible) | Legacy: Version 8.x documentation

Installation

npm install @cyrrus/client-data-structure

Quick Start

import { ClientData } from '@cyrrus/client-data-structure'

// Create client data
const client = new ClientData({
    client: { type: 'person', isResident: true },
    personal: { firstName: 'John', lastName: 'Doe' },
    contact: { email: 'john@example.com' },
    address: { address: { street: '123 Main St', city: 'Prague' } },
    bankAccounts: []
})

// Serialize
const json = JSON.stringify(client)
const plain = client.toPlainObject()

// Validate (requires peer dependencies)
client.validate() // throws on error with details in error.cause

Data Structure

ClientData contains seven main components:

Component Type Usage Key Fields
client ClientInformation System metadata type, internalId, contactId, isResident, investmentParameters, brokerContactId
personal PersonalInformation Personal details firstName, lastName, dateOfBirth, birthNumber, citizenship
idCard IdCardInformation ID document number, type, issuedBy, validUntil
address AddressInformation Addresses address (postal), mailingAddress, useMailingAddress
contact ContactInformation Communication email, phoneNumber
bankAccounts BankAccount[] Bank accounts accountNumber, bankCode, iban, swift, currency
company CompanyInformation Company data name, ic, dic, lei, representatives[]

Client Types: person, company, selfemployed

  • Person/Self-employed: Uses personal, idCard
  • Company: Uses company with representatives[] array

See dataExamples/person.json and dataExamples/company.json for complete examples.

Validation

Validation is opt-in - install peer dependencies:

npm install ajv ajv-formats cdigit ibantools libphonenumber-js

All classes extend AbstractBase providing:

  • validate() - Throws with validation errors in error.cause
  • toJSONSchema() - Returns JSON Schema definition
  • toPlainObject() / toJSON() - Serialization

Architecture

Immutable Classes

  • Private readonly fields (#field) with public getters
  • No setters - instances cannot be mutated after creation
  • Constructor accepts Partial<XInput> with defaults

Helper Functions

  • getStringOrNull() - Normalizes strings, returns null for empty
  • getNormalizedDate() - Parses dates to YYYY-MM-DDTHH:MM:SS.SSSZ format (noon UTC)
  • getInstanceOfClass() - Handles both plain objects and class instances

Legal ID Sanitization

Legal identifiers are sanitized during construction using the internal legal ID normalizer.

  • Affects: PersonalInformation.birthNumber, CompanyInformation.ic, CompanyInformation.dic, CompanyInformation.lei
  • Behavior: trims, converts to uppercase, removes all non-alphanumeric characters
  • Invalid input type behavior: non-string values are normalized to null
new PersonalInformation({ birthNumber: ' 900101/1234 ' }).birthNumber // -> '9001011234'
new CompanyInformation({ ic: ' cz-123 45 678 ' }).ic // -> 'CZ12345678'
new CompanyInformation({ dic: 123456 as unknown as string }).dic // -> null

Type System

Each class exports three types:

  • XInput - Constructor input (partial/optional fields)
  • XOutput - Serialized output (plain object)
  • XJSONSchema - JSON Schema type definition

Migration from v8

Key breaking changes from version 8.x:

Change Type v8 v9 Location Notes
Field Rename dataOriginId internalId ClientInformation
Field Rename residency isResident ClientInformation
Field Rename foreign isForeign BankAccount
Field Rename added addedAt InvestmentParameter
Enum Value 'OP' 'id' IdCardInformation.type
Enum Value 'Pas' 'passport' IdCardInformation.type
Removed capitolId (removed) ClientInformation Capitol → Cytron
Removed brokerId (removed) ClientInformation Capitol → Cytron
Removed externalBrokerCapitolId (removed) ClientInformation Capitol → Cytron
Removed externalBrokerAgentCapitolId (removed) ClientInformation Capitol → Cytron
Removed crmId (removed) ClientInformation Capitol → Cytron
Removed bankAccountsConfirmedByAffidavit (removed) ClientInformation Moved to BankAccount
Removed investmentProfiles (removed) ClientInformation Simplified structure
Removed capitolId (removed) Representative Capitol → Cytron
Removed capitolContactId (removed) Representative Capitol → Cytron
Removed position (removed) Representative
Removed capitolId (removed) BankAccount Capitol → Cytron
Removed phonePassword (removed) ContactInformation
Added (new) contactId ClientInformation Set to null
Added (new) brokerContactId ClientInformation Set to null
Added (new) externalBrokerContactId ClientInformation Set to null
Added (new) externalBrokerAgentContactId ClientInformation Set to null
Added legislation preferredLanguage ClientInformation Field renamed/remapped
Added (new) cytronId Representative Set to null
Added (new) contactId Representative Set to null
Added (new) cytronId BankAccount Set to null
Added (new) isConfirmedByAffidavit BankAccount From client.bankAccountsConfirmedByAffidavit
Entity Removed InvestmentProfile (removed) - Simplified to InvestmentParameter only
Entity Removed InvestmentService (removed) - No longer supported

Country Code Normalization (ISO 3166-1 alpha-3 → alpha-2)

All country code fields now store and output ISO 3166-1 alpha-2 codes (e.g. 'CZ', 'SK', 'DE') instead of alpha-3 codes (e.g. 'CZE', 'SVK', 'DEU'). This aligns with the Cytron business core system which uses alpha-2 codes natively.

Affected fields: Address.country, IdCardInformation.country, PersonalInformation.birthNumberCountry, PersonalInformation.taxDomicile, PersonalInformation.citizenship, CompanyInformation.taxDomicile.

The constructors accept both alpha-2 and alpha-3 input — alpha-3 values are automatically normalized to alpha-2 on construction. Invalid or unrecognized country codes are stored as null.

// Both inputs produce the same stored alpha-2 code
new PersonalInformation({ citizenship: 'CZE' }).citizenship // → 'CZ'
new PersonalInformation({ citizenship: 'CZ' }).citizenship  // → 'CZ'
new PersonalInformation({ citizenship: 'xyz' }).citizenship // → null

Localized country names are available via dedicated getters and locale methods:

Class Czech name getter Localized name method
Address countryName localizedCountryName(locale)
IdCardInformation countryName localizedCountryName(locale)
PersonalInformation birthNumberCountryName, citizenshipCountryName, taxDomicileCountryName localizedBirthNumberCountryName(locale), localizedCitizenshipCountryName(locale), localizedTaxDomicileCountryName(locale)
const personal = new PersonalInformation({ citizenship: 'CZ' })
personal.citizenship             // → 'CZ'
personal.citizenshipCountryName  // → 'Česká republika' (Czech locale)
personal.localizedCitizenshipCountryName(AvailableLanguages.en_US) // → 'Czech Republic'

Migration impact: If your code stores or compares country codes, update any hardcoded alpha-3 literals to alpha-2. The fromLegacyClientData() migration helper handles this conversion automatically for v8 data.

Use migration helper:

import { fromLegacyClientData } from '@cyrrus/client-data-structure'

const v9Client = fromLegacyClientData(v8Data)

Development

npm run build  # Build ESM + CJS + types to dist/
npm test       # Run Jest tests (builds test bundle first)
npm run docs   # Generate TypeDoc documentation
npm run lint   # ESLint with TypeScript strict rules

Build Output: Dual-format (ESM .js + CJS .cjs) with source maps and type definitions

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors