From 5df34b7f5cd535bc171f1000d61ee7d84dd05c07 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Fri, 24 Jan 2025 14:48:31 +0100 Subject: [PATCH 01/34] feat: restrict character sets --- .../src/attributes/constants/CharacterSets.ts | 12 +++++++++++ .../src/attributes/types/AbstractString.ts | 12 +++++++++-- .../types/address/AbstractAddress.ts | 3 ++- .../src/attributes/types/address/City.ts | 5 +++-- .../attributes/types/address/HouseNumber.ts | 5 +++-- .../src/attributes/types/address/State.ts | 5 +++-- .../src/attributes/types/address/Street.ts | 5 +++-- .../src/attributes/types/address/ZipCode.ts | 5 +++-- .../affiliation/AffiliationOrganization.ts | 5 +++-- .../attributes/types/identity/DisplayName.ts | 5 +++-- .../src/attributes/types/name/BirthName.ts | 5 +++-- .../src/attributes/types/name/GivenName.ts | 5 +++-- .../attributes/types/name/HonorificPrefix.ts | 5 +++-- .../attributes/types/name/HonorificSuffix.ts | 5 +++-- .../src/attributes/types/name/MiddleName.ts | 5 +++-- .../src/attributes/types/name/Pseudonym.ts | 5 +++-- .../src/attributes/types/name/Surname.ts | 5 +++-- .../src/attributes/types/person/JobTitle.ts | 4 ++-- .../types/proprietary/ProprietaryBoolean.ts | 5 +++-- .../types/proprietary/ProprietaryCountry.ts | 5 +++-- .../proprietary/ProprietaryEMailAddress.ts | 5 +++-- .../proprietary/ProprietaryFileReference.ts | 5 +++-- .../types/proprietary/ProprietaryFloat.ts | 5 +++-- .../types/proprietary/ProprietaryHEXColor.ts | 5 +++-- .../types/proprietary/ProprietaryInteger.ts | 5 +++-- .../types/proprietary/ProprietaryJSON.ts | 5 +++-- .../types/proprietary/ProprietaryLanguage.ts | 5 +++-- .../proprietary/ProprietaryPhoneNumber.ts | 5 +++-- .../types/proprietary/ProprietaryString.ts | 5 +++-- .../types/proprietary/ProprietaryURL.ts | 5 +++-- .../types/proprietary/ProprietaryXML.ts | 5 +++-- .../attributes/types/relationship/Consent.ts | 3 ++- .../types/statement/StatementPredicate.ts | 4 +++- .../attributes/types/strings/AbstractName.ts | 20 +++++++++++++++++++ .../strings/AbstractNaturalPersonName.ts | 20 +++++++++++++++++++ 35 files changed, 152 insertions(+), 61 deletions(-) create mode 100644 packages/content/src/attributes/constants/CharacterSets.ts create mode 100644 packages/content/src/attributes/types/strings/AbstractName.ts create mode 100644 packages/content/src/attributes/types/strings/AbstractNaturalPersonName.ts diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts new file mode 100644 index 000000000..107ffffa3 --- /dev/null +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -0,0 +1,12 @@ +export const characterSets: Record = { + // DIN91379 character sets from https://xoev.de/schemata/din/91379/2022-08/din-norm-91379-datatypes.xsd + // datatype A for names of natural persons + din91379DatatypeA: + /^(\u0020|\u0027|[\u002C-\\u002E]|[\u0041-\u005A]|[\u0060-\u007A]|\u007E|\u00A8|\u00B4|\u00B7|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, + // datatype B for all names + din91379DatatypeB: + /^([\u0020-\u007E]|[\u00A1-\u00A3]|\u00A5|[\u00A7-\u00AC]|[\u00AE-\u00B7]|[\u00B9-\u00BB]|[\u00BF-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u20AC|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, + // datatype C for everything + din91379DatatypeC: + /^([\u0009-\u000A]|\u000D|[\u0020-\u007E]|[\u00A0-\u00AC]|[\u00AE-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u20AC|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/ +}; diff --git a/packages/content/src/attributes/types/AbstractString.ts b/packages/content/src/attributes/types/AbstractString.ts index 0eed500e9..d3cc057a3 100644 --- a/packages/content/src/attributes/types/AbstractString.ts +++ b/packages/content/src/attributes/types/AbstractString.ts @@ -1,5 +1,6 @@ import { serialize, validate } from "@js-soft/ts-serval"; import { AbstractAttributeValue, AbstractAttributeValueJSON, IAbstractAttributeValue } from "../AbstractAttributeValue"; +import { characterSets } from "../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../hints"; export interface AbstractStringJSON extends AbstractAttributeValueJSON { @@ -12,7 +13,7 @@ export interface IAbstractString extends IAbstractAttributeValue { export class AbstractString extends AbstractAttributeValue implements IAbstractString { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeC }) public value: string; public static override preFrom(value: any): any { @@ -26,7 +27,8 @@ export class AbstractString extends AbstractAttributeValue implements IAbstractS public static get valueHints(): ValueHints { return ValueHints.from({ - max: 100 + max: 100, + pattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") }); } @@ -37,3 +39,9 @@ export class AbstractString extends AbstractAttributeValue implements IAbstractS }); } } + +export const enum DIN91379CharacterSetRegex { + DatatypeA = "^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$", + DatatypeB = "^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$", + DatatypeC = "^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$" +} diff --git a/packages/content/src/attributes/types/address/AbstractAddress.ts b/packages/content/src/attributes/types/address/AbstractAddress.ts index 1fd7509e2..1d572149b 100644 --- a/packages/content/src/attributes/types/address/AbstractAddress.ts +++ b/packages/content/src/attributes/types/address/AbstractAddress.ts @@ -1,6 +1,7 @@ import { serialize, validate } from "@js-soft/ts-serval"; import { nameof } from "ts-simple-nameof"; import { AbstractComplexValue, AbstractComplexValueJSON, IAbstractComplexValue } from "../../AbstractComplexValue"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../../hints"; export interface AbstractAddressJSON extends AbstractComplexValueJSON { @@ -13,7 +14,7 @@ export interface IAbstractAddress extends IAbstractComplexValue { export abstract class AbstractAddress extends AbstractComplexValue implements IAbstractAddress { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeB }) public recipient: string; public static get valueHints(): ValueHints { diff --git a/packages/content/src/attributes/types/address/City.ts b/packages/content/src/attributes/types/address/City.ts index 524c85144..5f3ab5b84 100644 --- a/packages/content/src/attributes/types/address/City.ts +++ b/packages/content/src/attributes/types/address/City.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface CityJSON extends AbstractStringJSON { "@type": "City"; @@ -8,7 +9,7 @@ export interface CityJSON extends AbstractStringJSON { export interface ICity extends IAbstractString {} @type("City") -export class City extends AbstractString implements ICity { +export class City extends AbstractName implements ICity { public static from(value: ICity | Omit | string): City { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/address/HouseNumber.ts b/packages/content/src/attributes/types/address/HouseNumber.ts index fd8d7e02c..5d600ef59 100644 --- a/packages/content/src/attributes/types/address/HouseNumber.ts +++ b/packages/content/src/attributes/types/address/HouseNumber.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface HouseNumberJSON extends AbstractStringJSON { "@type": "HouseNumber"; @@ -8,7 +9,7 @@ export interface HouseNumberJSON extends AbstractStringJSON { export interface IHouseNumber extends IAbstractString {} @type("HouseNumber") -export class HouseNumber extends AbstractString implements IHouseNumber { +export class HouseNumber extends AbstractName implements IHouseNumber { public static from(value: IHouseNumber | Omit | string): HouseNumber { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/address/State.ts b/packages/content/src/attributes/types/address/State.ts index ed79d8590..c24da977e 100644 --- a/packages/content/src/attributes/types/address/State.ts +++ b/packages/content/src/attributes/types/address/State.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface StateJSON extends AbstractStringJSON { "@type": "State"; @@ -8,7 +9,7 @@ export interface StateJSON extends AbstractStringJSON { export interface IState extends IAbstractString {} @type("State") -export class State extends AbstractString implements IState { +export class State extends AbstractName implements IState { public static from(value: IState | Omit | string): State { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/address/Street.ts b/packages/content/src/attributes/types/address/Street.ts index 2e093c8a6..117784540 100644 --- a/packages/content/src/attributes/types/address/Street.ts +++ b/packages/content/src/attributes/types/address/Street.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface StreetJSON extends AbstractStringJSON { "@type": "Street"; @@ -8,7 +9,7 @@ export interface StreetJSON extends AbstractStringJSON { export interface IStreet extends IAbstractString {} @type("Street") -export class Street extends AbstractString implements IStreet { +export class Street extends AbstractName implements IStreet { public static from(value: IStreet | Omit | string): Street { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/address/ZipCode.ts b/packages/content/src/attributes/types/address/ZipCode.ts index 1a4f1e1a7..6cd79c638 100644 --- a/packages/content/src/attributes/types/address/ZipCode.ts +++ b/packages/content/src/attributes/types/address/ZipCode.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface ZipCodeJSON extends AbstractStringJSON { "@type": "ZipCode"; @@ -8,7 +9,7 @@ export interface ZipCodeJSON extends AbstractStringJSON { export interface IZipCode extends IAbstractString {} @type("ZipCode") -export class ZipCode extends AbstractString implements IZipCode { +export class ZipCode extends AbstractName implements IZipCode { public static from(value: IZipCode | Omit | string): ZipCode { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/affiliation/AffiliationOrganization.ts b/packages/content/src/attributes/types/affiliation/AffiliationOrganization.ts index bff5ed0fe..8838b6da1 100644 --- a/packages/content/src/attributes/types/affiliation/AffiliationOrganization.ts +++ b/packages/content/src/attributes/types/affiliation/AffiliationOrganization.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface AffiliationOrganizationJSON extends AbstractStringJSON { "@type": "AffiliationOrganization"; @@ -8,7 +9,7 @@ export interface AffiliationOrganizationJSON extends AbstractStringJSON { export interface IAffiliationOrganization extends IAbstractString {} @type("AffiliationOrganization") -export class AffiliationOrganization extends AbstractString implements IAffiliationOrganization { +export class AffiliationOrganization extends AbstractName implements IAffiliationOrganization { public static from(value: IAffiliationOrganization | Omit | string): AffiliationOrganization { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/identity/DisplayName.ts b/packages/content/src/attributes/types/identity/DisplayName.ts index 9cd43e84d..5505a1ddc 100644 --- a/packages/content/src/attributes/types/identity/DisplayName.ts +++ b/packages/content/src/attributes/types/identity/DisplayName.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface DisplayNameJSON extends AbstractStringJSON { "@type": "DisplayName"; @@ -8,7 +9,7 @@ export interface DisplayNameJSON extends AbstractStringJSON { export interface IDisplayName extends IAbstractString {} @type("DisplayName") -export class DisplayName extends AbstractString implements IDisplayName { +export class DisplayName extends AbstractName implements IDisplayName { public static from(value: IDisplayName | Omit | string): DisplayName { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/BirthName.ts b/packages/content/src/attributes/types/name/BirthName.ts index a5deec4d0..657e20ba1 100644 --- a/packages/content/src/attributes/types/name/BirthName.ts +++ b/packages/content/src/attributes/types/name/BirthName.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface BirthNameJSON extends AbstractStringJSON { "@type": "BirthName"; @@ -8,7 +9,7 @@ export interface BirthNameJSON extends AbstractStringJSON { export interface IBirthName extends IAbstractString {} @type("BirthName") -export class BirthName extends AbstractString implements IBirthName { +export class BirthName extends AbstractNaturalPersonName implements IBirthName { public static from(value: IBirthName | Omit | string): BirthName { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/GivenName.ts b/packages/content/src/attributes/types/name/GivenName.ts index 1615ee185..1e6e324c7 100644 --- a/packages/content/src/attributes/types/name/GivenName.ts +++ b/packages/content/src/attributes/types/name/GivenName.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface GivenNameJSON extends AbstractStringJSON { "@type": "GivenName"; @@ -8,7 +9,7 @@ export interface GivenNameJSON extends AbstractStringJSON { export interface IGivenName extends IAbstractString {} @type("GivenName") -export class GivenName extends AbstractString implements IGivenName { +export class GivenName extends AbstractNaturalPersonName implements IGivenName { public static from(value: IGivenName | Omit | string): GivenName { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/HonorificPrefix.ts b/packages/content/src/attributes/types/name/HonorificPrefix.ts index a962c80ef..a76cc2008 100644 --- a/packages/content/src/attributes/types/name/HonorificPrefix.ts +++ b/packages/content/src/attributes/types/name/HonorificPrefix.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface HonorificPrefixJSON extends AbstractStringJSON { "@type": "HonorificPrefix"; @@ -8,7 +9,7 @@ export interface HonorificPrefixJSON extends AbstractStringJSON { export interface IHonorificPrefix extends IAbstractString {} @type("HonorificPrefix") -export class HonorificPrefix extends AbstractString implements HonorificPrefix { +export class HonorificPrefix extends AbstractNaturalPersonName implements HonorificPrefix { public static from(value: HonorificPrefix | Omit | string): HonorificPrefix { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/HonorificSuffix.ts b/packages/content/src/attributes/types/name/HonorificSuffix.ts index 765f3070c..2681a6f38 100644 --- a/packages/content/src/attributes/types/name/HonorificSuffix.ts +++ b/packages/content/src/attributes/types/name/HonorificSuffix.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface HonorificSuffixJSON extends AbstractStringJSON { "@type": "HonorificSuffix"; @@ -8,7 +9,7 @@ export interface HonorificSuffixJSON extends AbstractStringJSON { export interface IHonorificSuffix extends IAbstractString {} @type("HonorificSuffix") -export class HonorificSuffix extends AbstractString implements IHonorificSuffix { +export class HonorificSuffix extends AbstractNaturalPersonName implements IHonorificSuffix { public static from(value: IHonorificSuffix | Omit | string): HonorificSuffix { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/MiddleName.ts b/packages/content/src/attributes/types/name/MiddleName.ts index 1359834f2..97df32da3 100644 --- a/packages/content/src/attributes/types/name/MiddleName.ts +++ b/packages/content/src/attributes/types/name/MiddleName.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface MiddleNameJSON extends AbstractStringJSON { "@type": "MiddleName"; @@ -8,7 +9,7 @@ export interface MiddleNameJSON extends AbstractStringJSON { export interface IMiddleName extends IAbstractString {} @type("MiddleName") -export class MiddleName extends AbstractString implements IMiddleName { +export class MiddleName extends AbstractNaturalPersonName implements IMiddleName { public static from(value: IMiddleName | Omit | string): MiddleName { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/Pseudonym.ts b/packages/content/src/attributes/types/name/Pseudonym.ts index c0ea1a1b9..4cba661f2 100644 --- a/packages/content/src/attributes/types/name/Pseudonym.ts +++ b/packages/content/src/attributes/types/name/Pseudonym.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface PseudonymJSON extends AbstractStringJSON { "@type": "Pseudonym"; @@ -8,7 +9,7 @@ export interface PseudonymJSON extends AbstractStringJSON { export interface IPseudonym extends IAbstractString {} @type("Pseudonym") -export class Pseudonym extends AbstractString implements IPseudonym { +export class Pseudonym extends AbstractNaturalPersonName implements IPseudonym { public static from(value: IPseudonym | Omit | string): Pseudonym { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/name/Surname.ts b/packages/content/src/attributes/types/name/Surname.ts index 27e850aeb..2b27a664c 100644 --- a/packages/content/src/attributes/types/name/Surname.ts +++ b/packages/content/src/attributes/types/name/Surname.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractNaturalPersonName } from "../strings/AbstractNaturalPersonName"; export interface SurnameJSON extends AbstractStringJSON { "@type": "Surname"; @@ -8,7 +9,7 @@ export interface SurnameJSON extends AbstractStringJSON { export interface ISurname extends IAbstractString {} @type("Surname") -export class Surname extends AbstractString implements ISurname { +export class Surname extends AbstractNaturalPersonName implements ISurname { public static from(value: ISurname | Omit | string): Surname { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/person/JobTitle.ts b/packages/content/src/attributes/types/person/JobTitle.ts index f9c8067ea..0d39690dd 100644 --- a/packages/content/src/attributes/types/person/JobTitle.ts +++ b/packages/content/src/attributes/types/person/JobTitle.ts @@ -1,5 +1,5 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractString as AbstractName, AbstractStringJSON, IAbstractString } from "../AbstractString"; export interface JobTitleJSON extends AbstractStringJSON { "@type": "JobTitle"; @@ -8,7 +8,7 @@ export interface JobTitleJSON extends AbstractStringJSON { export interface IJobTitle extends IAbstractString {} @type("JobTitle") -export class JobTitle extends AbstractString implements IJobTitle { +export class JobTitle extends AbstractName implements IJobTitle { public static from(value: IJobTitle | Omit | string): JobTitle { return this.fromAny(value); } diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryBoolean.ts b/packages/content/src/attributes/types/proprietary/ProprietaryBoolean.ts index bbc1d00f9..ac5c36448 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryBoolean.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryBoolean.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractBoolean, AbstractBooleanJSON, IAbstractBoolean } from "../AbstractBoolean"; import { @@ -17,11 +18,11 @@ export interface IProprietaryBoolean extends IProprietaryAttributeValue, IAbstra @type("ProprietaryBoolean") export class ProprietaryBoolean extends AbstractBoolean { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryCountry.ts b/packages/content/src/attributes/types/proprietary/ProprietaryCountry.ts index bcda1cb67..b0cce814c 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryCountry.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryCountry.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractCountry } from "../strings/AbstractCountry"; @@ -18,11 +19,11 @@ export interface IProprietaryCountry extends IProprietaryAttributeValue, IAbstra @type("ProprietaryCountry") export class ProprietaryCountry extends AbstractCountry { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryEMailAddress.ts b/packages/content/src/attributes/types/proprietary/ProprietaryEMailAddress.ts index f4fafde6d..18963a1d1 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryEMailAddress.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryEMailAddress.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractEMailAddress } from "../strings/AbstractEMailAddress"; @@ -18,11 +19,11 @@ export interface IProprietaryEMailAddress extends IProprietaryAttributeValue, IA @type("ProprietaryEMailAddress") export class ProprietaryEMailAddress extends AbstractEMailAddress { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryFileReference.ts b/packages/content/src/attributes/types/proprietary/ProprietaryFileReference.ts index f36f3bbba..e60eac452 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryFileReference.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryFileReference.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractFileReference } from "../strings"; @@ -18,11 +19,11 @@ export interface IProprietaryFileReference extends IProprietaryAttributeValue, I @type("ProprietaryFileReference") export class ProprietaryFileReference extends AbstractFileReference { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryFloat.ts b/packages/content/src/attributes/types/proprietary/ProprietaryFloat.ts index d4dde88d5..2ae549383 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryFloat.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryFloat.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractFloat, AbstractFloatJSON, IAbstractFloat } from "../AbstractFloat"; import { @@ -17,11 +18,11 @@ export interface IProprietaryFloat extends IProprietaryAttributeValue, IAbstract @type("ProprietaryFloat") export class ProprietaryFloat extends AbstractFloat { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryHEXColor.ts b/packages/content/src/attributes/types/proprietary/ProprietaryHEXColor.ts index 6b4be289d..675b8950a 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryHEXColor.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryHEXColor.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractHEXColor } from "../strings/AbstractHEXColor"; @@ -18,11 +19,11 @@ export interface IProprietaryHEXColor extends IProprietaryAttributeValue, IAbstr @type("ProprietaryHEXColor") export class ProprietaryHEXColor extends AbstractHEXColor { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryInteger.ts b/packages/content/src/attributes/types/proprietary/ProprietaryInteger.ts index 8f238f330..4ec3696d6 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryInteger.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryInteger.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractInteger, AbstractIntegerJSON, IAbstractInteger } from "../AbstractInteger"; import { @@ -17,11 +18,11 @@ export interface IProprietaryInteger extends IProprietaryAttributeValue, IAbstra @type("ProprietaryInteger") export class ProprietaryInteger extends AbstractInteger implements IProprietaryInteger { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts index db2bdaaea..58bf2c97a 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts @@ -1,5 +1,6 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { AbstractAttributeValue, AbstractAttributeValueJSON, IAbstractAttributeValue } from "../../AbstractAttributeValue"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../../hints"; import { PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH } from "./ProprietaryAttributeValue"; @@ -19,11 +20,11 @@ export interface IProprietaryJSON extends IAbstractAttributeValue { @type("ProprietaryJSON") export class ProprietaryJSON extends AbstractAttributeValue { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize({ any: true }) diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryLanguage.ts b/packages/content/src/attributes/types/proprietary/ProprietaryLanguage.ts index c8878d662..5b0f5af87 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryLanguage.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryLanguage.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractLanguage } from "../strings/AbstractLanguage"; @@ -18,11 +19,11 @@ export interface IProprietaryLanguage extends IProprietaryAttributeValue, IAbstr @type("ProprietaryLanguage") export class ProprietaryLanguage extends AbstractLanguage { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryPhoneNumber.ts b/packages/content/src/attributes/types/proprietary/ProprietaryPhoneNumber.ts index a4a9d02d0..ae9f843b1 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryPhoneNumber.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryPhoneNumber.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractPhoneNumber } from "../strings/AbstractPhoneNumber"; @@ -18,11 +19,11 @@ export interface IProprietaryPhoneNumber extends IProprietaryAttributeValue, IAb @type("ProprietaryPhoneNumber") export class ProprietaryPhoneNumber extends AbstractPhoneNumber { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryString.ts b/packages/content/src/attributes/types/proprietary/ProprietaryString.ts index 69c1d358a..e7e20372b 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryString.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryString.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; import { @@ -17,11 +18,11 @@ export interface IProprietaryString extends IProprietaryAttributeValue, IAbstrac @type("ProprietaryString") export class ProprietaryString extends AbstractString { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryURL.ts b/packages/content/src/attributes/types/proprietary/ProprietaryURL.ts index 58e6f8d69..52dd5bccb 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryURL.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryURL.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractURL } from "../strings/AbstractURL"; @@ -18,11 +19,11 @@ export interface IProprietaryURL extends IProprietaryAttributeValue, IAbstractSt @type("ProprietaryURL") export class ProprietaryURL extends AbstractURL { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryXML.ts b/packages/content/src/attributes/types/proprietary/ProprietaryXML.ts index 9eb59d4e9..a4dcb516c 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryXML.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryXML.ts @@ -1,4 +1,5 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { ValueHints, ValueHintsOverride } from "../../hints"; import { AbstractStringJSON, IAbstractString } from "../AbstractString"; import { AbstractXML } from "../strings/AbstractXML"; @@ -21,11 +22,11 @@ export interface IProprietaryXML extends IProprietaryAttributeValue, IAbstractSt @type("ProprietaryXML") export class ProprietaryXML extends AbstractXML { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() diff --git a/packages/content/src/attributes/types/relationship/Consent.ts b/packages/content/src/attributes/types/relationship/Consent.ts index 6f9a6b2b6..e29c51c33 100644 --- a/packages/content/src/attributes/types/relationship/Consent.ts +++ b/packages/content/src/attributes/types/relationship/Consent.ts @@ -1,5 +1,6 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { AbstractAttributeValue, AbstractAttributeValueJSON, IAbstractAttributeValue } from "../../AbstractAttributeValue"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsDataType, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../../hints"; export interface ConsentJSON extends AbstractAttributeValueJSON { @@ -15,7 +16,7 @@ export interface IConsent extends IAbstractAttributeValue { @type("Consent") export class Consent extends AbstractAttributeValue implements IConsent { @serialize() - @validate({ max: 2000 }) + @validate({ max: 2000, regExp: characterSets.din91379DatatypeC }) public consent: string; @serialize() diff --git a/packages/content/src/attributes/types/statement/StatementPredicate.ts b/packages/content/src/attributes/types/statement/StatementPredicate.ts index 64aba47d8..d4e9b031b 100644 --- a/packages/content/src/attributes/types/statement/StatementPredicate.ts +++ b/packages/content/src/attributes/types/statement/StatementPredicate.ts @@ -1,4 +1,5 @@ import { PrimitiveType, serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, ValueHints, ValueHintsValue } from "../../hints"; import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; @@ -25,7 +26,8 @@ export class StatementPredicate extends AbstractString { @serialize() @validate({ customValidator: StatementPredicate.validatePredicate, - allowedTypes: [PrimitiveType.String] + allowedTypes: [PrimitiveType.String], + regExp: characterSets.din91379DatatypeC }) public override value: Predicates | `z-${string}`; diff --git a/packages/content/src/attributes/types/strings/AbstractName.ts b/packages/content/src/attributes/types/strings/AbstractName.ts new file mode 100644 index 000000000..f147c6f90 --- /dev/null +++ b/packages/content/src/attributes/types/strings/AbstractName.ts @@ -0,0 +1,20 @@ +import { serialize, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../../constants/CharacterSets"; +import { ValueHints } from "../../hints"; +import { AbstractString } from "../AbstractString"; + +export abstract class AbstractName extends AbstractString { + @serialize() + @validate({ + max: 100, + regExp: characterSets.din91379DatatypeB + }) + public override value: string; + + public static override get valueHints(): ValueHints { + return super.valueHints.copyWith({ + max: 100, + pattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") + }); + } +} diff --git a/packages/content/src/attributes/types/strings/AbstractNaturalPersonName.ts b/packages/content/src/attributes/types/strings/AbstractNaturalPersonName.ts new file mode 100644 index 000000000..a20e38da0 --- /dev/null +++ b/packages/content/src/attributes/types/strings/AbstractNaturalPersonName.ts @@ -0,0 +1,20 @@ +import { serialize, validate } from "@js-soft/ts-serval"; +import { ValueHints } from "../../../attributes/hints"; +import { characterSets } from "../../constants/CharacterSets"; +import { AbstractString } from "../AbstractString"; + +export abstract class AbstractNaturalPersonName extends AbstractString { + @serialize() + @validate({ + max: 100, + regExp: characterSets.din91379DatatypeA + }) + public override value: string; + + public static override get valueHints(): ValueHints { + return super.valueHints.copyWith({ + max: 100, + pattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") + }); + } +} From c6eb2395b2f0ea23cfae0bb226c56354a78ee9ae Mon Sep 17 00:00:00 2001 From: mkuhn Date: Fri, 24 Jan 2025 17:11:28 +0100 Subject: [PATCH 02/34] feat: restrict value hints --- packages/content/src/attributes/hints/ValueHints.ts | 9 +++++---- packages/content/src/attributes/hints/ValueHintsValue.ts | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/content/src/attributes/hints/ValueHints.ts b/packages/content/src/attributes/hints/ValueHints.ts index 3510ce1d5..00539c477 100644 --- a/packages/content/src/attributes/hints/ValueHints.ts +++ b/packages/content/src/attributes/hints/ValueHints.ts @@ -1,5 +1,6 @@ import { ISerializable, PrimitiveType, Serializable, serialize, type, validate } from "@js-soft/ts-serval"; import { ContentJSON } from "../../ContentJSON"; +import { characterSets } from "../constants/CharacterSets"; import { IValueHintsValue, ValueHintsValue, ValueHintsValueJSON } from "./ValueHintsValue"; export interface ValueHintsJSON extends ContentJSON { @@ -48,7 +49,7 @@ function serializePropertyHints(hints: ValueHints | ValueHintsOverride, json: Va @type("ValueHints") export class ValueHints extends Serializable implements IValueHints { @serialize() - @validate({ nullable: true, max: 500 }) + @validate({ nullable: true, max: 500, regExp: characterSets.din91379DatatypeC }) public editHelp?: string; @serialize() @@ -67,7 +68,7 @@ export class ValueHints extends Serializable implements IValueHints { @validate({ nullable: true }) public values?: ValueHintsValue[]; - @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean] }) + @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], regExp: characterSets.din91379DatatypeC }) @serialize() public defaultValue?: number | string | boolean; @@ -104,7 +105,7 @@ export class ValueHints extends Serializable implements IValueHints { @type("ValueHintsOverride") export class ValueHintsOverride extends Serializable implements IValueHintsOverride { @serialize() - @validate({ nullable: true, max: 500 }) + @validate({ nullable: true, max: 500, regExp: characterSets.din91379DatatypeC }) public editHelp?: string; @serialize() @@ -124,7 +125,7 @@ export class ValueHintsOverride extends Serializable implements IValueHintsOverr public values?: ValueHintsValue[]; @serialize({ unionTypes: [Boolean, Number, String] }) - @validate({ nullable: true }) + @validate({ nullable: true, regExp: characterSets.din91379DatatypeC }) public defaultValue?: boolean | number | string; @serialize() diff --git a/packages/content/src/attributes/hints/ValueHintsValue.ts b/packages/content/src/attributes/hints/ValueHintsValue.ts index 83522ad19..bbf1e20a1 100644 --- a/packages/content/src/attributes/hints/ValueHintsValue.ts +++ b/packages/content/src/attributes/hints/ValueHintsValue.ts @@ -1,4 +1,5 @@ import { ISerializable, PrimitiveType, Serializable, serialize, type, validate } from "@js-soft/ts-serval"; +import { characterSets } from "../constants/CharacterSets"; export interface ValueHintsValueJSON { key: string | number | boolean; @@ -13,12 +14,13 @@ export interface IValueHintsValue extends ISerializable { @type("ValueHintsValue") export class ValueHintsValue extends Serializable implements IValueHintsValue { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeC }) public displayName: string; @validate({ allowedTypes: [PrimitiveType.String, PrimitiveType.Number, PrimitiveType.Boolean], - customValidator: ValueHintsValue.validateKey + customValidator: ValueHintsValue.validateKey, + regExp: characterSets.din91379DatatypeC }) @serialize() public key: string | number | boolean; From 3ae49a00f05a76bb6a1a87488397908838780d9f Mon Sep 17 00:00:00 2001 From: mkuhn Date: Fri, 24 Jan 2025 17:13:01 +0100 Subject: [PATCH 03/34] fix: remove wrong \ in regex --- packages/content/src/attributes/constants/CharacterSets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts index 107ffffa3..08534a399 100644 --- a/packages/content/src/attributes/constants/CharacterSets.ts +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -2,7 +2,7 @@ export const characterSets: Record = { // DIN91379 character sets from https://xoev.de/schemata/din/91379/2022-08/din-norm-91379-datatypes.xsd // datatype A for names of natural persons din91379DatatypeA: - /^(\u0020|\u0027|[\u002C-\\u002E]|[\u0041-\u005A]|[\u0060-\u007A]|\u007E|\u00A8|\u00B4|\u00B7|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, + /^(\u0020|\u0027|[\u002C-\u002E]|[\u0041-\u005A]|[\u0060-\u007A]|\u007E|\u00A8|\u00B4|\u00B7|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, // datatype B for all names din91379DatatypeB: /^([\u0020-\u007E]|[\u00A1-\u00A3]|\u00A5|[\u00A7-\u00AC]|[\u00AE-\u00B7]|[\u00B9-\u00BB]|[\u00BF-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u20AC|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, From 2b46a96b845f8267c58db6d472ad998b1a727e2f Mon Sep 17 00:00:00 2001 From: mkuhn Date: Sat, 25 Jan 2025 12:52:45 +0100 Subject: [PATCH 04/34] refactor: only use unicode codes when necessary --- packages/content/src/attributes/constants/CharacterSets.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts index 08534a399..878597451 100644 --- a/packages/content/src/attributes/constants/CharacterSets.ts +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -2,11 +2,11 @@ export const characterSets: Record = { // DIN91379 character sets from https://xoev.de/schemata/din/91379/2022-08/din-norm-91379-datatypes.xsd // datatype A for names of natural persons din91379DatatypeA: - /^(\u0020|\u0027|[\u002C-\u002E]|[\u0041-\u005A]|[\u0060-\u007A]|\u007E|\u00A8|\u00B4|\u00B7|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, + /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, // datatype B for all names din91379DatatypeB: - /^([\u0020-\u007E]|[\u00A1-\u00A3]|\u00A5|[\u00A7-\u00AC]|[\u00AE-\u00B7]|[\u00B9-\u00BB]|[\u00BF-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u20AC|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/, + /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, // datatype C for everything din91379DatatypeC: - /^([\u0009-\u000A]|\u000D|[\u0020-\u007E]|[\u00A0-\u00AC]|[\u00AE-\u017E]|[\u0187-\u0188]|\u018F|\u0197|[\u01A0-\u01A1]|[\u01AF-\u01B0]|\u01B7|[\u01CD-\u01DC]|[\u01DE-\u01DF]|[\u01E2-\u01F0]|[\u01F4-\u01F5]|[\u01F8-\u01FF]|[\u0212-\u0213]|[\u0218-\u021B]|[\u021E-\u021F]|[\u0227-\u0233]|\u0259|\u0268|\u0292|[\u02B9-\u02BA]|[\u02BE-\u02BF]|\u02C8|\u02CC|[\u1E02-\u1E03]|[\u1E06-\u1E07]|[\u1E0A-\u1E11]|\u1E17|[\u1E1C-\u1E2B]|[\u1E2F-\u1E37]|[\u1E3A-\u1E3B]|[\u1E40-\u1E49]|[\u1E52-\u1E5B]|[\u1E5E-\u1E63]|[\u1E6A-\u1E6F]|[\u1E80-\u1E87]|[\u1E8C-\u1E97]|\u1E9E|[\u1EA0-\u1EF9]|\u2019|\u2021|\u20AC|\u0041\u030B|\u0043(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0044\u0302|\u0046(\u0300|\u0304)|\u0047\u0300|\u0048(\u0304|\u0326|\u0331)|\u004A(\u0301|\u030C)|\u004B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0048|\u035F\u0068)|\u004C(\u0302|\u0325|\u0325\u0304|\u0326)|\u004D(\u0300|\u0302|\u0306|\u0310)|\u004E(\u0302|\u0304|\u0306|\u0326)|\u0050(\u0300|\u0304|\u0315|\u0323)|\u0052(\u0306|\u0325|\u0325\u0304)|\u0053(\u0300|\u0304|\u031B\u0304|\u0331)|\u0054(\u0300|\u0304|\u0308|\u0315|\u031B)|\u0055\u0307|\u005A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u0061\u030B|\u0063(\u0300|\u0304|\u0306|\u0308|\u0315|\u0323|\u0326|\u0328\u0306)|\u0064\u0302|\u0066(\u0300|\u0304)|\u0067\u0300|\u0068(\u0304|\u0326)|\u006A\u0301|\u006B(\u0300|\u0302|\u0304|\u0307|\u0315|\u031B|\u0326|\u035F\u0068)|\u006C(\u0302|\u0325|\u0325\u0304|\u0326)|\u006D(\u0300|\u0302|\u0306|\u0310)|\u006E(\u0302|\u0304|\u0306|\u0326)|\u0070(\u0300|\u0304|\u0315|\u0323)|\u0072(\u0306|\u0325|\u0325\u0304)|\u0073(\u0300|\u0304|\u031B\u0304|\u0331)|\u0074(\u0300|\u0304|\u0315|\u031B)|\u0075\u0307|\u007A(\u0300|\u0304|\u0306|\u0308|\u0327)|\u00C7\u0306|\u00DB\u0304|\u00E7\u0306|\u00FB\u0304|\u00FF\u0301|\u010C(\u0315|\u0323)|\u010D(\u0315|\u0323)|\u0113\u030D|\u012A\u0301|\u012B\u0301|\u014D\u030D|\u017D(\u0326|\u0327)|\u017E(\u0326|\u0327)|\u1E32\u0304|\u1E33\u0304|\u1E62\u0304|\u1E63\u0304|\u1E6C\u0304|\u1E6D\u0304|\u1EA0\u0308|\u1EA1\u0308|\u1ECC\u0308|\u1ECD\u0308|\u1EE4(\u0304|\u0308)|\u1EE5(\u0304|\u0308))*$/ + /^([\u0009-\u000A]|\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/ }; From aa821951e381edf11aa4484d267fcd61635ea675 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Sat, 25 Jan 2025 13:19:37 +0100 Subject: [PATCH 05/34] test: add first character set tests --- .../test/attributes/CharacterSets.test.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 packages/content/test/attributes/CharacterSets.test.ts diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts new file mode 100644 index 000000000..8f0873c95 --- /dev/null +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -0,0 +1,66 @@ +import { ParsingError } from "@js-soft/ts-serval"; +import { AffiliationOrganization, Consent, GivenName } from "../../src"; + +describe("Test valid Attributes", () => { + test("GivenName is considered as valid", () => { + const validGivenName = GivenName.from({ value: "Gräf" }); + expect(validGivenName.value.toString()).toBe("Gräf"); + }); + + test("AffiliationOrganization is considered as valid", () => { + const validOrganization = AffiliationOrganization.from({ value: "€" }); + expect(validOrganization.value.toString()).toBe("€"); + }); + + test("Consent is considered as valid", () => { + const consent = Consent.from({ consent: "\u0009" }); + expect(consent.consent.toString()).toBe("\u0009"); + }); +}); + +describe("Test invalid Attributes", () => { + test("GivenName is considered as invalid", () => { + const invalidCall = () => { + GivenName.from({ + value: "€" + }); + }; + expect(invalidCall).toThrow( + new ParsingError( + "GivenName", + "value", + "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" + ) + ); + }); + + test("AffiliationOrganization is considered as invalid", () => { + const invalidCall = () => { + AffiliationOrganization.from({ + value: "\u0009" + }); + }; + expect(invalidCall).toThrow( + new ParsingError( + "AffiliationOrganization", + "value", + "Value does not match regular expression /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" + ) + ); + }); + + test("Consent is considered as invalid", () => { + const invalidCall = () => { + Consent.from({ + consent: "\u0012" + }); + }; + expect(invalidCall).toThrow( + new ParsingError( + "Consent", + "consent", + "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" + ) + ); + }); +}); From aaf956bc6e800c587b47747574dd54653e86a2e2 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Mon, 27 Jan 2025 14:59:10 +0100 Subject: [PATCH 06/34] test: add more tests --- .../test/attributes/CharacterSets.test.ts | 151 ++++++++++++------ 1 file changed, 106 insertions(+), 45 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 8f0873c95..9e4023194 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -1,66 +1,127 @@ -import { ParsingError } from "@js-soft/ts-serval"; -import { AffiliationOrganization, Consent, GivenName } from "../../src"; +import { ParsingError, Serializable } from "@js-soft/ts-serval"; +import { Consent } from "../../src"; +import { characterSets } from "../../src/attributes/constants/CharacterSets"; -describe("Test valid Attributes", () => { - test("GivenName is considered as valid", () => { - const validGivenName = GivenName.from({ value: "Gräf" }); - expect(validGivenName.value.toString()).toBe("Gräf"); - }); +const mapping = [ + { + datatype: "A", + downloaded: + "( |'|[,-\.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", + ours: characterSets.din91379DatatypeA + }, + { + datatype: "B", + downloaded: + "([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", + ours: characterSets.din91379DatatypeB + }, + { + datatype: "C", + downloaded: + "([ - ]| |[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", + ours: characterSets.din91379DatatypeC + } +]; - test("AffiliationOrganization is considered as valid", () => { - const validOrganization = AffiliationOrganization.from({ value: "€" }); - expect(validOrganization.value.toString()).toBe("€"); - }); +test.each(mapping)("used regex matches the downloaded regex for datatype $datatype", ({ downloaded, ours }) => { + const jsCharacterSet = downloaded.replaceAll("&#x", "\\u").replaceAll(";", ""); + const oursToString = ours.toString(); + + expect(jsCharacterSet).toBe(oursToString); +}); +const errorMessageA = + "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; +const errorMessageB = + "Value does not match regular expression /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; +const errorMessageC = + "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; + +describe("Test Attributes", () => { test("Consent is considered as valid", () => { const consent = Consent.from({ consent: "\u0009" }); expect(consent.consent.toString()).toBe("\u0009"); }); -}); -describe("Test invalid Attributes", () => { - test("GivenName is considered as invalid", () => { + test("Consent is considered as invalid", () => { const invalidCall = () => { - GivenName.from({ - value: "€" + Consent.from({ + consent: "\u0012" }); }; - expect(invalidCall).toThrow( - new ParsingError( - "GivenName", - "value", - "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" - ) - ); + expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageC)); + }); + + const regularIdentityAttributeTypesA = ["BirthName", "GivenName", "HonorificPrefix", "HonorificSuffix", "MiddleName", "Pseudonym", "Surname"]; + const regularIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Street", "ZipCode", "AffiliationOrganization", "DisplayName", "JobTitle"]; + const regularIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; + + const testMapping = regularIdentityAttributeTypesA + .map((x) => ({ type: x, testValue: "Gräf", wrongTestValue: "€", errorMessage: errorMessageA })) + .concat(regularIdentityAttributeTypesB.map((x) => ({ type: x, testValue: "€", wrongTestValue: "z-\u0009", errorMessage: errorMessageB }))) + .concat(regularIdentityAttributeTypesC.map((x) => ({ type: x, testValue: "z-\u0009", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); + + test.each(testMapping)("$testValue is considered as valid for type $type", ({ type, testValue }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }); + expect((attribute as any).value).toBe(testValue); + }); + + test.each(testMapping)("$wrongTestValue is considered as invalid for type $type", ({ type, wrongTestValue, errorMessage }) => { + const invalidCall = () => Serializable.fromUnknown({ "@type": type, value: wrongTestValue }); + expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessage)); + }); + + const regularRelationshipAttributeTypesC = ["ProprietaryString", "ProprietaryJSON", "ProprietaryXML"]; + + test.each(regularRelationshipAttributeTypesC)("is considered as valid for type %s", (type) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u0009", title: "aTitle" }); + expect((attribute as any).value).toBe("z-\u0009"); + }); + + test.only.each(regularRelationshipAttributeTypesC)("is considered as invalid for type %s", (type) => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, value: "z-\u0012", title: "aTitle" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessageC)); + }); + + const proprietaryAttributeTypes = [ + { type: "ProprietaryBoolean", value: true }, + { type: "ProprietaryCountry", value: "DE" }, + { type: "ProprietaryEMailAddress", value: "email@email.de" }, + { type: "ProprietaryFileReference", value: "FIL123456789012345678901234567" }, + { type: "ProprietaryFloat", value: 1 }, + { type: "ProprietaryHEXColor", value: "#000000" }, + { type: "ProprietaryInteger", value: 1 }, + { type: "ProprietaryLanguage", value: "de" }, + { type: "ProprietaryPhoneNumber", value: "1234567890" }, + { type: "ProprietaryString", value: "aString" }, + { type: "ProprietaryURL", value: "mail.de" }, + { type: "ProprietaryJSON", value: "aString" }, + { type: "ProprietaryXML", value: "aString" } + ]; + + test.each(proprietaryAttributeTypes)("title is considered as valid for type $type", ({ type, value }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u0009" }); + expect((attribute as any).title).toBe("\u0009"); }); - test("AffiliationOrganization is considered as invalid", () => { + test.each(proprietaryAttributeTypes)("title is considered as invalid for type $type", ({ type, value }) => { const invalidCall = () => { - AffiliationOrganization.from({ - value: "\u0009" - }); + Serializable.fromUnknown({ "@type": type, value, title: "\u0012" }); }; - expect(invalidCall).toThrow( - new ParsingError( - "AffiliationOrganization", - "value", - "Value does not match regular expression /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" - ) - ); + expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); }); - test("Consent is considered as invalid", () => { + test.each(proprietaryAttributeTypes)("description is considered as valid for type $type", ({ type, value }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0009" }); + expect((attribute as any).description).toBe("\u0009"); + }); + + test.each(proprietaryAttributeTypes)("description is considered as invalid for type $type", ({ type, value }) => { const invalidCall = () => { - Consent.from({ - consent: "\u0012" - }); + Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0012" }); }; - expect(invalidCall).toThrow( - new ParsingError( - "Consent", - "consent", - "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/" - ) - ); + expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); }); }); From 5452b333c6941a4b251acaea50c826d7a9864309 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Mon, 27 Jan 2025 16:39:20 +0100 Subject: [PATCH 07/34] fix: import in JobTitle --- packages/content/src/attributes/types/person/JobTitle.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/content/src/attributes/types/person/JobTitle.ts b/packages/content/src/attributes/types/person/JobTitle.ts index 0d39690dd..a4cad9b81 100644 --- a/packages/content/src/attributes/types/person/JobTitle.ts +++ b/packages/content/src/attributes/types/person/JobTitle.ts @@ -1,5 +1,6 @@ import { type } from "@js-soft/ts-serval"; -import { AbstractString as AbstractName, AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractStringJSON, IAbstractString } from "../AbstractString"; +import { AbstractName } from "../strings/AbstractName"; export interface JobTitleJSON extends AbstractStringJSON { "@type": "JobTitle"; From 5414c8bef62274b5aac8dd655a045edd4ecee0ad Mon Sep 17 00:00:00 2001 From: mkuhn Date: Mon, 27 Jan 2025 16:39:51 +0100 Subject: [PATCH 08/34] fix: check regex in AbstractXML --- packages/content/src/attributes/types/strings/AbstractXML.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/content/src/attributes/types/strings/AbstractXML.ts b/packages/content/src/attributes/types/strings/AbstractXML.ts index 4793d21c7..d384c799f 100644 --- a/packages/content/src/attributes/types/strings/AbstractXML.ts +++ b/packages/content/src/attributes/types/strings/AbstractXML.ts @@ -1,10 +1,11 @@ import { serialize, validate } from "@js-soft/ts-serval"; import { RenderHints, RenderHintsDataType, RenderHintsEditType, ValueHints } from "../../../attributes/hints"; +import { characterSets } from "../../constants/CharacterSets"; import { AbstractString } from "../AbstractString"; export abstract class AbstractXML extends AbstractString { @serialize() - @validate({ max: 50000 }) + @validate({ max: 50000, regExp: characterSets.din91379DatatypeC }) public override value: string; public static override get valueHints(): ValueHints { From 667a23216f3d362cd51d2b65724efc67d83b5600 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 10:50:05 +0100 Subject: [PATCH 09/34] fix: undo JSON.stringify replacements --- .../src/attributes/types/proprietary/ProprietaryJSON.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts index 58bf2c97a..ac920efb0 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts @@ -53,10 +53,17 @@ export class ProprietaryJSON extends AbstractAttributeValue { function validateValue(value: any) { try { - const string = JSON.stringify(value); + const string = JSON.stringify(value, (_key, value) => (typeof value === "string" ? value : value)); if (string.length > 4096) { return "stringified value must not be longer than 4096 characters"; } + + // JSON.stringify replaces some characters with their code points (e. g. "\\u0012" instead of the character), hence transforming it back for the regex validation + const stringWithEscapedQuotations = string.replace(/(? Date: Tue, 28 Jan 2025 10:53:53 +0100 Subject: [PATCH 10/34] test: remove regex comparison --- .../test/attributes/CharacterSets.test.ts | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 9e4023194..7e1aa6620 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -1,34 +1,5 @@ import { ParsingError, Serializable } from "@js-soft/ts-serval"; import { Consent } from "../../src"; -import { characterSets } from "../../src/attributes/constants/CharacterSets"; - -const mapping = [ - { - datatype: "A", - downloaded: - "( |'|[,-\.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", - ours: characterSets.din91379DatatypeA - }, - { - datatype: "B", - downloaded: - "([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", - ours: characterSets.din91379DatatypeB - }, - { - datatype: "C", - downloaded: - "([ - ]| |[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*", - ours: characterSets.din91379DatatypeC - } -]; - -test.each(mapping)("used regex matches the downloaded regex for datatype $datatype", ({ downloaded, ours }) => { - const jsCharacterSet = downloaded.replaceAll("&#x", "\\u").replaceAll(";", ""); - const oursToString = ours.toString(); - - expect(jsCharacterSet).toBe(oursToString); -}); const errorMessageA = "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; From b957dffd5bee83eedcf209460a6f1de6d396d1e6 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 10:54:46 +0100 Subject: [PATCH 11/34] test: check error property, change test value to \r --- .../test/attributes/CharacterSets.test.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 7e1aa6620..48407fb3d 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -10,8 +10,8 @@ const errorMessageC = describe("Test Attributes", () => { test("Consent is considered as valid", () => { - const consent = Consent.from({ consent: "\u0009" }); - expect(consent.consent.toString()).toBe("\u0009"); + const consent = Consent.from({ consent: "\u000D" }); + expect(consent.consent.toString()).toBe("\u000D"); }); test("Consent is considered as invalid", () => { @@ -29,8 +29,8 @@ describe("Test Attributes", () => { const testMapping = regularIdentityAttributeTypesA .map((x) => ({ type: x, testValue: "Gräf", wrongTestValue: "€", errorMessage: errorMessageA })) - .concat(regularIdentityAttributeTypesB.map((x) => ({ type: x, testValue: "€", wrongTestValue: "z-\u0009", errorMessage: errorMessageB }))) - .concat(regularIdentityAttributeTypesC.map((x) => ({ type: x, testValue: "z-\u0009", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); + .concat(regularIdentityAttributeTypesB.map((x) => ({ type: x, testValue: "€", wrongTestValue: "z-\u000D", errorMessage: errorMessageB }))) + .concat(regularIdentityAttributeTypesC.map((x) => ({ type: x, testValue: "z-\u000D", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); test.each(testMapping)("$testValue is considered as valid for type $type", ({ type, testValue }) => { const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }); @@ -42,18 +42,22 @@ describe("Test Attributes", () => { expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessage)); }); - const regularRelationshipAttributeTypesC = ["ProprietaryString", "ProprietaryJSON", "ProprietaryXML"]; + const regularRelationshipAttributeTypesC = [ + { type: "ProprietaryString", errorProperty: "value" }, + { type: "ProprietaryJSON", errorProperty: "value:Object" }, + { type: "ProprietaryXML", errorProperty: "value" } + ]; - test.each(regularRelationshipAttributeTypesC)("is considered as valid for type %s", (type) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u0009", title: "aTitle" }); - expect((attribute as any).value).toBe("z-\u0009"); + test.each(regularRelationshipAttributeTypesC)("is considered as valid for type $type", ({ type }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }); + expect((attribute as any).value).toBe("z-\u000D"); }); - test.only.each(regularRelationshipAttributeTypesC)("is considered as invalid for type %s", (type) => { + test.each(regularRelationshipAttributeTypesC)("is considered as invalid for type $type", ({ type, errorProperty }) => { const invalidCall = () => { Serializable.fromUnknown({ "@type": type, value: "z-\u0012", title: "aTitle" }); }; - expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, errorProperty, errorMessageC)); }); const proprietaryAttributeTypes = [ @@ -73,8 +77,8 @@ describe("Test Attributes", () => { ]; test.each(proprietaryAttributeTypes)("title is considered as valid for type $type", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u0009" }); - expect((attribute as any).title).toBe("\u0009"); + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D" }); + expect((attribute as any).title).toBe("\u000D"); }); test.each(proprietaryAttributeTypes)("title is considered as invalid for type $type", ({ type, value }) => { @@ -85,8 +89,8 @@ describe("Test Attributes", () => { }); test.each(proprietaryAttributeTypes)("description is considered as valid for type $type", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0009" }); - expect((attribute as any).description).toBe("\u0009"); + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D" }); + expect((attribute as any).description).toBe("\u000D"); }); test.each(proprietaryAttributeTypes)("description is considered as invalid for type $type", ({ type, value }) => { From 9113192d5b12c782488d1e8509ae7a77d4b06365 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 10:55:25 +0100 Subject: [PATCH 12/34] refactor: add character set source warning --- packages/content/src/attributes/constants/CharacterSets.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts index 878597451..eded30ac0 100644 --- a/packages/content/src/attributes/constants/CharacterSets.ts +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -1,5 +1,6 @@ export const characterSets: Record = { // DIN91379 character sets from https://xoev.de/schemata/din/91379/2022-08/din-norm-91379-datatypes.xsd + // See the sources in the browser's dev mode, they're not equal to what's initially displayed // datatype A for names of natural persons din91379DatatypeA: /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, From 6c690bea3e74c8a2734c57b31c6522432b09189d Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 11:03:47 +0100 Subject: [PATCH 13/34] test: fix names containing numbers --- .../test/attributeValues/NameValueTests.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/content/test/attributeValues/NameValueTests.test.ts b/packages/content/test/attributeValues/NameValueTests.test.ts index 99e2c54bf..d016dc4e2 100644 --- a/packages/content/test/attributeValues/NameValueTests.test.ts +++ b/packages/content/test/attributeValues/NameValueTests.test.ts @@ -36,7 +36,7 @@ new GenericValueTest().runParametrized({ typeClass: PersonName, expectedJSON: { "@type": "PersonName", - givenName: "TestGivenName1 TestGivenName2", + givenName: "aTestGivenName anotherTestGivenName", middleName: "Middler", surname: "TestSurname", honorificPrefix: "Dr. Dr. rer. nat.", @@ -44,7 +44,7 @@ new GenericValueTest().runParametrized({ }, valueJSON: { "@type": "PersonName", - givenName: "TestGivenName1 TestGivenName2", + givenName: "aTestGivenName anotherTestGivenName", middleName: "Middler", surname: "TestSurname", honorificPrefix: "Dr. Dr. rer. nat.", @@ -54,7 +54,7 @@ new GenericValueTest().runParametrized({ "@type": "PersonName", givenName: { "@type": "GivenName", - value: "TestGivenName1 TestGivenName2" + value: "aTestGivenName anotherTestGivenName" }, middleName: { "@type": "MiddleName", @@ -74,11 +74,11 @@ new GenericValueTest().runParametrized({ } }, valueInterface: { - givenName: GivenName.fromAny("TestGivenName1 TestGivenName2"), + givenName: GivenName.fromAny("aTestGivenName anotherTestGivenName"), middleName: MiddleName.fromAny("Middler"), surname: Surname.fromAny("TestSurname"), honorificPrefix: HonorificPrefix.fromAny("Dr. Dr. rer. nat."), honorificSuffix: HonorificSuffix.fromAny("M.Sc.") }, - valueString: "Dr. Dr. rer. nat. TestGivenName1 TestGivenName2 Middler TestSurname M.Sc." + valueString: "Dr. Dr. rer. nat. aTestGivenName anotherTestGivenName Middler TestSurname M.Sc." }); From 5db6869bc231ec5522e77624a8e433cfe3d57101 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 11:27:16 +0100 Subject: [PATCH 14/34] test: fix more names containing numbers --- packages/runtime/test/consumption/attributes.test.ts | 6 +++--- packages/runtime/test/consumption/iqlQuery.test.ts | 6 +++--- packages/runtime/test/transport/relationships.test.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/runtime/test/consumption/attributes.test.ts b/packages/runtime/test/consumption/attributes.test.ts index 4c9e97ea3..206fa1423 100644 --- a/packages/runtime/test/consumption/attributes.test.ts +++ b/packages/runtime/test/consumption/attributes.test.ts @@ -1269,7 +1269,7 @@ describe(CreateRepositoryAttributeUseCase.name, () => { content: { value: { "@type": "GivenName", - value: "aGivenName2" + value: "anotherGivenName" }, tags: ["tag1", "tag2"], validFrom, @@ -1432,7 +1432,7 @@ describe(ShareRepositoryAttributeUseCase.name, () => { content: { value: { "@type": "Surname", - value: "Name 1" + value: "aSurname" } } }); @@ -1443,7 +1443,7 @@ describe(ShareRepositoryAttributeUseCase.name, () => { successorContent: { value: { "@type": "Surname", - value: "Name 2" + value: "anotherSurname" } } }) diff --git a/packages/runtime/test/consumption/iqlQuery.test.ts b/packages/runtime/test/consumption/iqlQuery.test.ts index 11fd92a3e..d950ce2ab 100644 --- a/packages/runtime/test/consumption/iqlQuery.test.ts +++ b/packages/runtime/test/consumption/iqlQuery.test.ts @@ -48,7 +48,7 @@ describe("IQL Query", () => { content: { value: { "@type": "GivenName", - value: "aGivenName1" + value: "aGivenName" }, tags: ["language:de"] } @@ -60,7 +60,7 @@ describe("IQL Query", () => { content: { value: { "@type": "GivenName", - value: "aGivenName2" + value: "aSecondGivenName" }, tags: ["language:en"] } @@ -71,7 +71,7 @@ describe("IQL Query", () => { content: { value: { "@type": "GivenName", - value: "aGivenName3" + value: "aThirdGivenName" }, tags: ["content:someContent"] } diff --git a/packages/runtime/test/transport/relationships.test.ts b/packages/runtime/test/transport/relationships.test.ts index b151c9b13..353a0bdc0 100644 --- a/packages/runtime/test/transport/relationships.test.ts +++ b/packages/runtime/test/transport/relationships.test.ts @@ -1012,7 +1012,7 @@ describe("RelationshipDecomposition", () => { await sendAndReceiveNotification(services1.transport, services2.transport, services2.consumption); - const randomName1 = await Random.string(7); + const randomName1 = await Random.string(7, "qwertzuiop"); await executeFullCreateAndShareRepositoryAttributeFlow(services1, services2, { content: { value: { @@ -1022,7 +1022,7 @@ describe("RelationshipDecomposition", () => { } }); - const randomName2 = await Random.string(7); + const randomName2 = await Random.string(7, "asdfghjkl"); await executeFullCreateAndShareRepositoryAttributeFlow(services2, services1, { content: { value: { From be054877ce5e01edd6a435215310d75663c790ce Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 12:15:31 +0100 Subject: [PATCH 15/34] refactor: test variable naming --- .../test/attributes/CharacterSets.test.ts | 154 +++++++++--------- 1 file changed, 76 insertions(+), 78 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 48407fb3d..e8ee965d3 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -8,95 +8,93 @@ const errorMessageB = const errorMessageC = "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; -describe("Test Attributes", () => { - test("Consent is considered as valid", () => { - const consent = Consent.from({ consent: "\u000D" }); - expect(consent.consent.toString()).toBe("\u000D"); - }); +test("Consent is considered as valid", () => { + const consent = Consent.from({ consent: "\u000D" }); + expect(consent.consent.toString()).toBe("\u000D"); +}); - test("Consent is considered as invalid", () => { - const invalidCall = () => { - Consent.from({ - consent: "\u0012" - }); - }; - expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageC)); - }); +test("Consent is considered as invalid", () => { + const invalidCall = () => { + Consent.from({ + consent: "\u0012" + }); + }; + expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageC)); +}); - const regularIdentityAttributeTypesA = ["BirthName", "GivenName", "HonorificPrefix", "HonorificSuffix", "MiddleName", "Pseudonym", "Surname"]; - const regularIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Street", "ZipCode", "AffiliationOrganization", "DisplayName", "JobTitle"]; - const regularIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; +const restrictedIdentityAttributeTypesA = ["BirthName", "GivenName", "HonorificPrefix", "HonorificSuffix", "MiddleName", "Pseudonym", "Surname"]; +const restrictedIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Street", "ZipCode", "AffiliationOrganization", "DisplayName", "JobTitle"]; +const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; - const testMapping = regularIdentityAttributeTypesA - .map((x) => ({ type: x, testValue: "Gräf", wrongTestValue: "€", errorMessage: errorMessageA })) - .concat(regularIdentityAttributeTypesB.map((x) => ({ type: x, testValue: "€", wrongTestValue: "z-\u000D", errorMessage: errorMessageB }))) - .concat(regularIdentityAttributeTypesC.map((x) => ({ type: x, testValue: "z-\u000D", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); +const identityAttributeTestParameters = restrictedIdentityAttributeTypesA + .map((type) => ({ type, testValue: "Gräf", wrongTestValue: "€", errorMessage: errorMessageA })) + .concat(restrictedIdentityAttributeTypesB.map((type) => ({ type, testValue: "€", wrongTestValue: "z-\u000D", errorMessage: errorMessageB }))) + .concat(restrictedIdentityAttributeTypesC.map((type) => ({ type, testValue: "z-\u000D", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); - test.each(testMapping)("$testValue is considered as valid for type $type", ({ type, testValue }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }); - expect((attribute as any).value).toBe(testValue); - }); +test.each(identityAttributeTestParameters)("$type is considered as valid", ({ type, testValue }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }); + expect((attribute as any).value).toBe(testValue); +}); - test.each(testMapping)("$wrongTestValue is considered as invalid for type $type", ({ type, wrongTestValue, errorMessage }) => { - const invalidCall = () => Serializable.fromUnknown({ "@type": type, value: wrongTestValue }); - expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessage)); - }); +test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ type, wrongTestValue, errorMessage }) => { + const invalidCall = () => Serializable.fromUnknown({ "@type": type, value: wrongTestValue }); + expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessage)); +}); - const regularRelationshipAttributeTypesC = [ - { type: "ProprietaryString", errorProperty: "value" }, - { type: "ProprietaryJSON", errorProperty: "value:Object" }, - { type: "ProprietaryXML", errorProperty: "value" } - ]; +const relationshipAttributeValueTestParameters = [ + { type: "ProprietaryString", propertyInErrorMessage: "value" }, + { type: "ProprietaryJSON", propertyInErrorMessage: "value:Object" }, + { type: "ProprietaryXML", propertyInErrorMessage: "value" } +]; - test.each(regularRelationshipAttributeTypesC)("is considered as valid for type $type", ({ type }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }); - expect((attribute as any).value).toBe("z-\u000D"); - }); +test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }); + expect((attribute as any).value).toBe("z-\u000D"); +}); - test.each(regularRelationshipAttributeTypesC)("is considered as invalid for type $type", ({ type, errorProperty }) => { - const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value: "z-\u0012", title: "aTitle" }); - }; - expect(invalidCall).toThrow(new ParsingError(type, errorProperty, errorMessageC)); - }); +test.each(relationshipAttributeValueTestParameters)("value of $type is considered as invalid", ({ type, propertyInErrorMessage }) => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, value: "z-\u0012", title: "aTitle" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, propertyInErrorMessage, errorMessageC)); +}); - const proprietaryAttributeTypes = [ - { type: "ProprietaryBoolean", value: true }, - { type: "ProprietaryCountry", value: "DE" }, - { type: "ProprietaryEMailAddress", value: "email@email.de" }, - { type: "ProprietaryFileReference", value: "FIL123456789012345678901234567" }, - { type: "ProprietaryFloat", value: 1 }, - { type: "ProprietaryHEXColor", value: "#000000" }, - { type: "ProprietaryInteger", value: 1 }, - { type: "ProprietaryLanguage", value: "de" }, - { type: "ProprietaryPhoneNumber", value: "1234567890" }, - { type: "ProprietaryString", value: "aString" }, - { type: "ProprietaryURL", value: "mail.de" }, - { type: "ProprietaryJSON", value: "aString" }, - { type: "ProprietaryXML", value: "aString" } - ]; +const proprietaryAttributeTypes = [ + { type: "ProprietaryBoolean", value: true }, + { type: "ProprietaryCountry", value: "DE" }, + { type: "ProprietaryEMailAddress", value: "email@email.de" }, + { type: "ProprietaryFileReference", value: "FIL123456789012345678901234567" }, + { type: "ProprietaryFloat", value: 1 }, + { type: "ProprietaryHEXColor", value: "#000000" }, + { type: "ProprietaryInteger", value: 1 }, + { type: "ProprietaryLanguage", value: "de" }, + { type: "ProprietaryPhoneNumber", value: "1234567890" }, + { type: "ProprietaryString", value: "aString" }, + { type: "ProprietaryURL", value: "mail.de" }, + { type: "ProprietaryJSON", value: "aString" }, + { type: "ProprietaryXML", value: "aString" } +]; - test.each(proprietaryAttributeTypes)("title is considered as valid for type $type", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D" }); - expect((attribute as any).title).toBe("\u000D"); - }); +test.each(proprietaryAttributeTypes)("title of $type is considered as valid", ({ type, value }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D" }); + expect((attribute as any).title).toBe("\u000D"); +}); - test.each(proprietaryAttributeTypes)("title is considered as invalid for type $type", ({ type, value }) => { - const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "\u0012" }); - }; - expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); - }); +test.each(proprietaryAttributeTypes)("title of $type is considered as invalid", ({ type, value }) => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, value, title: "\u0012" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); +}); - test.each(proprietaryAttributeTypes)("description is considered as valid for type $type", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D" }); - expect((attribute as any).description).toBe("\u000D"); - }); +test.each(proprietaryAttributeTypes)("description of $type is considered as valid", ({ type, value }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D" }); + expect((attribute as any).description).toBe("\u000D"); +}); - test.each(proprietaryAttributeTypes)("description is considered as invalid for type $type", ({ type, value }) => { - const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0012" }); - }; - expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); - }); +test.each(proprietaryAttributeTypes)("description of $type is considered as invalid", ({ type, value }) => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0012" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); }); From 2fd930ef11bb5d1c2155e11ac97bcf614539610a Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 14:00:14 +0100 Subject: [PATCH 16/34] test: change test value --- packages/content/test/attributes/CharacterSets.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index e8ee965d3..17a476313 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -27,7 +27,7 @@ const restrictedIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Stre const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; const identityAttributeTestParameters = restrictedIdentityAttributeTypesA - .map((type) => ({ type, testValue: "Gräf", wrongTestValue: "€", errorMessage: errorMessageA })) + .map((type) => ({ type, testValue: "Ä", wrongTestValue: "€", errorMessage: errorMessageA })) .concat(restrictedIdentityAttributeTypesB.map((type) => ({ type, testValue: "€", wrongTestValue: "z-\u000D", errorMessage: errorMessageB }))) .concat(restrictedIdentityAttributeTypesC.map((type) => ({ type, testValue: "z-\u000D", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); From 9cce0aff81981f6759cbcf77d3af4a696f60235d Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 14:12:54 +0100 Subject: [PATCH 17/34] feat: validate key of rel attribute --- .../src/attributes/RelationshipAttribute.ts | 3 +- .../test/attributes/CharacterSets.test.ts | 34 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/content/src/attributes/RelationshipAttribute.ts b/packages/content/src/attributes/RelationshipAttribute.ts index dabe29751..f03e8228f 100644 --- a/packages/content/src/attributes/RelationshipAttribute.ts +++ b/packages/content/src/attributes/RelationshipAttribute.ts @@ -2,6 +2,7 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { AbstractAttribute, AbstractAttributeJSON, IAbstractAttribute } from "./AbstractAttribute"; import { AttributeValues } from "./AttributeValueTypes"; import { RelationshipAttributeConfidentiality } from "./RelationshipAttributeConfidentiality"; +import { characterSets } from "./constants/CharacterSets"; export interface RelationshipAttributeJSON extends AbstractAttributeJSON { "@type": "RelationshipAttribute"; @@ -28,7 +29,7 @@ export class RelationshipAttribute { + const attribute = RelationshipAttribute.from({ + key: "\u000D", + confidentiality: RelationshipAttributeConfidentiality.Private, + value: { + "@type": "ProprietaryBoolean", + value: true, + title: "aTitle" + }, + "@type": "RelationshipAttribute", + owner: "theOwner" + }); + expect(attribute.key).toBe("\u000D"); +}); + +test("Key of RelationshipAttribute is invalid", () => { + const invalidCall = () => { + RelationshipAttribute.from({ + key: "\u0012", + confidentiality: RelationshipAttributeConfidentiality.Private, + value: { + "@type": "ProprietaryBoolean", + value: true, + title: "aTitle" + }, + "@type": "RelationshipAttribute", + owner: "theOwner" + }); + }; + expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageC)); +}); From a3bc11992f77cf9b1cc4a1ae3130f48eb8bbdb22 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 15:06:40 +0100 Subject: [PATCH 18/34] fix: missing valueHints adaptations --- .../content/src/attributes/types/address/AbstractAddress.ts | 4 +++- .../content/src/attributes/types/relationship/Consent.ts | 5 ++++- packages/content/src/attributes/types/strings/AbstractXML.ts | 5 +++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/content/src/attributes/types/address/AbstractAddress.ts b/packages/content/src/attributes/types/address/AbstractAddress.ts index 1d572149b..57672f8d4 100644 --- a/packages/content/src/attributes/types/address/AbstractAddress.ts +++ b/packages/content/src/attributes/types/address/AbstractAddress.ts @@ -20,7 +20,9 @@ export abstract class AbstractAddress extends AbstractComplexValue implements IA public static get valueHints(): ValueHints { return ValueHints.from({ propertyHints: { - [nameof((a) => a.recipient)]: ValueHints.from({}) + [nameof((a) => a.recipient)]: ValueHints.from({ + pattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") + }) } }); } diff --git a/packages/content/src/attributes/types/relationship/Consent.ts b/packages/content/src/attributes/types/relationship/Consent.ts index e29c51c33..fee1de11b 100644 --- a/packages/content/src/attributes/types/relationship/Consent.ts +++ b/packages/content/src/attributes/types/relationship/Consent.ts @@ -42,7 +42,10 @@ export class Consent extends AbstractAttributeValue implements IConsent { public static get valueHints(): ValueHints { return ValueHints.from({ propertyHints: { - consent: { max: 2000 }, + consent: { + max: 2000, + pattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") + }, link: { min: 3, max: 1024 diff --git a/packages/content/src/attributes/types/strings/AbstractXML.ts b/packages/content/src/attributes/types/strings/AbstractXML.ts index d384c799f..6a723c0fe 100644 --- a/packages/content/src/attributes/types/strings/AbstractXML.ts +++ b/packages/content/src/attributes/types/strings/AbstractXML.ts @@ -9,8 +9,9 @@ export abstract class AbstractXML extends AbstractString { public override value: string; public static override get valueHints(): ValueHints { - return ValueHints.from({ - max: 50000 + return super.valueHints.copyWith({ + max: 50000, + pattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") }); } From 5d0b199c9eec0ea2b977bbd49a28983189651f87 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 15:07:33 +0100 Subject: [PATCH 19/34] refactor: variable naming --- .../src/attributes/types/proprietary/ProprietaryJSON.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts index ac920efb0..09c26da36 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts @@ -53,14 +53,14 @@ export class ProprietaryJSON extends AbstractAttributeValue { function validateValue(value: any) { try { - const string = JSON.stringify(value, (_key, value) => (typeof value === "string" ? value : value)); + const string = JSON.stringify(value); if (string.length > 4096) { return "stringified value must not be longer than 4096 characters"; } // JSON.stringify replaces some characters with their code points (e. g. "\\u0012" instead of the character), hence transforming it back for the regex validation - const stringWithEscapedQuotations = string.replace(/(? Date: Tue, 28 Jan 2025 16:12:53 +0100 Subject: [PATCH 20/34] fix: move some checks to custom validators --- .../src/attributes/hints/ValueHints.ts | 10 +- .../src/attributes/hints/ValueHintsValue.ts | 10 +- .../test/attributes/CharacterSets.test.ts | 95 ++++++++++++++++--- 3 files changed, 98 insertions(+), 17 deletions(-) diff --git a/packages/content/src/attributes/hints/ValueHints.ts b/packages/content/src/attributes/hints/ValueHints.ts index 00539c477..7f5dc3371 100644 --- a/packages/content/src/attributes/hints/ValueHints.ts +++ b/packages/content/src/attributes/hints/ValueHints.ts @@ -68,7 +68,7 @@ export class ValueHints extends Serializable implements IValueHints { @validate({ nullable: true }) public values?: ValueHintsValue[]; - @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], regExp: characterSets.din91379DatatypeC }) + @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], customValidator: ValueHints.validateDefaultValue }) @serialize() public defaultValue?: number | string | boolean; @@ -100,6 +100,14 @@ export class ValueHints extends Serializable implements IValueHints { const propertyHints = { ...this.toJSON().propertyHints, ...overrideJson?.propertyHints }; return ValueHints.from({ ...this.toJSON(), ...overrideJson, propertyHints }); } + + private static validateDefaultValue(defaultValue: string | number | boolean) { + if (typeof defaultValue === "string" && !characterSets.din91379DatatypeC.test(defaultValue)) { + return "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; + } + + return undefined; + } } @type("ValueHintsOverride") diff --git a/packages/content/src/attributes/hints/ValueHintsValue.ts b/packages/content/src/attributes/hints/ValueHintsValue.ts index bbf1e20a1..8e9d5e36e 100644 --- a/packages/content/src/attributes/hints/ValueHintsValue.ts +++ b/packages/content/src/attributes/hints/ValueHintsValue.ts @@ -19,8 +19,7 @@ export class ValueHintsValue extends Serializable implements IValueHintsValue { @validate({ allowedTypes: [PrimitiveType.String, PrimitiveType.Number, PrimitiveType.Boolean], - customValidator: ValueHintsValue.validateKey, - regExp: characterSets.din91379DatatypeC + customValidator: ValueHintsValue.validateKey }) @serialize() public key: string | number | boolean; @@ -30,8 +29,11 @@ export class ValueHintsValue extends Serializable implements IValueHintsValue { } private static validateKey(key: string | number | boolean) { - if (typeof key === "string" && key.length > 100) { - return "The maximum length of a key is 200 characters."; + if (typeof key === "string") { + if (key.length > 100) return "The maximum length of a key is 100 characters."; + if (!characterSets.din91379DatatypeC.test(key)) { + return "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; + } } return undefined; diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index c51561398..4af0e83e0 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -1,5 +1,6 @@ import { ParsingError, Serializable } from "@js-soft/ts-serval"; -import { Consent, RelationshipAttribute, RelationshipAttributeConfidentiality } from "../../src"; +import { Consent, RelationshipAttribute, RelationshipAttributeConfidentiality, ValueHints, ValueHintsValue } from "../../src"; +import { characterSets } from "../../src/attributes/constants/CharacterSets"; const errorMessageA = "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; @@ -27,13 +28,36 @@ const restrictedIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Stre const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; const identityAttributeTestParameters = restrictedIdentityAttributeTypesA - .map((type) => ({ type, testValue: "Ä", wrongTestValue: "€", errorMessage: errorMessageA })) - .concat(restrictedIdentityAttributeTypesB.map((type) => ({ type, testValue: "€", wrongTestValue: "z-\u000D", errorMessage: errorMessageB }))) - .concat(restrictedIdentityAttributeTypesC.map((type) => ({ type, testValue: "z-\u000D", wrongTestValue: "\u0012", errorMessage: errorMessageC }))); - -test.each(identityAttributeTestParameters)("$type is considered as valid", ({ type, testValue }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }); - expect((attribute as any).value).toBe(testValue); + .map((type) => ({ + type, + testValue: "Ä", + wrongTestValue: "€", + errorMessage: errorMessageA, + valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") + })) + .concat( + restrictedIdentityAttributeTypesB.map((type) => ({ + type, + testValue: "€", + wrongTestValue: "z-\u000D", + errorMessage: errorMessageB, + valueHintsPattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") + })) + ) + .concat( + restrictedIdentityAttributeTypesC.map((type) => ({ + type, + testValue: "z-\u000D", + wrongTestValue: "\u0012", + errorMessage: errorMessageC, + valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") + })) + ); + +test.each(identityAttributeTestParameters)("$type is considered as valid", ({ type, testValue, valueHintsPattern }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }) as any; + expect(attribute.value).toBe(testValue); + expect(attribute.valueHints.pattern).toBe(valueHintsPattern); }); test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ type, wrongTestValue, errorMessage }) => { @@ -43,13 +67,16 @@ test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ const relationshipAttributeValueTestParameters = [ { type: "ProprietaryString", propertyInErrorMessage: "value" }, - { type: "ProprietaryJSON", propertyInErrorMessage: "value:Object" }, + { type: "ProprietaryJSON", propertyInErrorMessage: "value:Object", noValueHints: true }, { type: "ProprietaryXML", propertyInErrorMessage: "value" } ]; -test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }); - expect((attribute as any).value).toBe("z-\u000D"); +test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type, noValueHints }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }) as any; + expect(attribute.value).toBe("z-\u000D"); + if (!noValueHints) { + expect(attribute.valueHints.pattern).toBe(characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/")); + } }); test.each(relationshipAttributeValueTestParameters)("value of $type is considered as invalid", ({ type, propertyInErrorMessage }) => { @@ -130,3 +157,47 @@ test("Key of RelationshipAttribute is invalid", () => { }; expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageC)); }); + +test("ValueHints is valid", () => { + const validCall = () => { + ValueHints.from({ + defaultValue: "\u000D", + editHelp: "\u000D", + values: [ + { + key: "\u000D", + displayName: "\u000D" + } + ] + }); + }; + expect(validCall).not.toThrow(); +}); + +test("defaultValue of ValueHints is invalid", () => { + const invalidCall = () => { + ValueHints.from({ defaultValue: "\u0012" }); + }; + expect(invalidCall).toThrow(new ParsingError("ValueHints", "defaultValue:Object", errorMessageC)); +}); + +test("editHelp of ValueHints is invalid", () => { + const invalidCall = () => { + ValueHints.from({ editHelp: "\u0012" }); + }; + expect(invalidCall).toThrow(new ParsingError("ValueHints", "editHelp", errorMessageC)); +}); + +test("key of ValueHintsValue is invalid", () => { + const invalidCall = () => { + ValueHintsValue.from({ key: "\u0012", displayName: "aDisplayName" }); + }; + expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "key:Object", errorMessageC)); +}); + +test("displayName of ValueHintsValue is invalid", () => { + const invalidCall = () => { + ValueHintsValue.from({ key: "aKey", displayName: "\u0012" }); + }; + expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "displayName", errorMessageC)); +}); From a643b223b49358e09006d9bb558e262c075fc88f Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 16:23:56 +0100 Subject: [PATCH 21/34] refactor: remove conditional from test --- .../content/test/attributes/CharacterSets.test.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 4af0e83e0..70bf6a90d 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -66,17 +66,15 @@ test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ }); const relationshipAttributeValueTestParameters = [ - { type: "ProprietaryString", propertyInErrorMessage: "value" }, - { type: "ProprietaryJSON", propertyInErrorMessage: "value:Object", noValueHints: true }, - { type: "ProprietaryXML", propertyInErrorMessage: "value" } + { type: "ProprietaryString", propertyInErrorMessage: "value", valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") }, + { type: "ProprietaryJSON", propertyInErrorMessage: "value:Object", valueHintsPattern: undefined }, + { type: "ProprietaryXML", propertyInErrorMessage: "value", valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") } ]; -test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type, noValueHints }) => { +test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type, valueHintsPattern }) => { const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }) as any; expect(attribute.value).toBe("z-\u000D"); - if (!noValueHints) { - expect(attribute.valueHints.pattern).toBe(characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/")); - } + expect(attribute.valueHints.pattern).toBe(valueHintsPattern); }); test.each(relationshipAttributeValueTestParameters)("value of $type is considered as invalid", ({ type, propertyInErrorMessage }) => { From d1fd080ea5350ebd354a0193bd372a4a0626bcc1 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 28 Jan 2025 16:27:59 +0100 Subject: [PATCH 22/34] refactor: test variable naming --- .../test/attributes/CharacterSets.test.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 70bf6a90d..0943003a3 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -30,16 +30,16 @@ const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .map((type) => ({ type, - testValue: "Ä", - wrongTestValue: "€", + positiveTestValue: "Ä", + negativeTestValue: "€", errorMessage: errorMessageA, valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") })) .concat( restrictedIdentityAttributeTypesB.map((type) => ({ type, - testValue: "€", - wrongTestValue: "z-\u000D", + positiveTestValue: "€", + negativeTestValue: "z-\u000D", errorMessage: errorMessageB, valueHintsPattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") })) @@ -47,21 +47,21 @@ const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .concat( restrictedIdentityAttributeTypesC.map((type) => ({ type, - testValue: "z-\u000D", - wrongTestValue: "\u0012", + positiveTestValue: "z-\u000D", + negativeTestValue: "\u0012", errorMessage: errorMessageC, valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") })) ); -test.each(identityAttributeTestParameters)("$type is considered as valid", ({ type, testValue, valueHintsPattern }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: testValue }) as any; - expect(attribute.value).toBe(testValue); +test.each(identityAttributeTestParameters)("$type is considered as valid", ({ type, positiveTestValue, valueHintsPattern }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value: positiveTestValue }) as any; + expect(attribute.value).toBe(positiveTestValue); expect(attribute.valueHints.pattern).toBe(valueHintsPattern); }); -test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ type, wrongTestValue, errorMessage }) => { - const invalidCall = () => Serializable.fromUnknown({ "@type": type, value: wrongTestValue }); +test.each(identityAttributeTestParameters)("$type is considered as invalid", ({ type, negativeTestValue, errorMessage }) => { + const invalidCall = () => Serializable.fromUnknown({ "@type": type, value: negativeTestValue }); expect(invalidCall).toThrow(new ParsingError(type, "value", errorMessage)); }); From 4bc90d6109e5c892a4e549470b4adf3f88ff7dfd Mon Sep 17 00:00:00 2001 From: mkuhn Date: Wed, 29 Jan 2025 10:27:25 +0100 Subject: [PATCH 23/34] test: more variety in tested characters --- .../test/attributes/CharacterSets.test.ts | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 0943003a3..27fe29818 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -10,8 +10,8 @@ const errorMessageC = "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; test("Consent is considered as valid", () => { - const consent = Consent.from({ consent: "\u000D" }); - expect(consent.consent.toString()).toBe("\u000D"); + const consent = Consent.from({ consent: "z-\u000D¾£()," }); + expect(consent.consent.toString()).toBe("z-\u000D¾£(),"); }); test("Consent is considered as invalid", () => { @@ -30,7 +30,7 @@ const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .map((type) => ({ type, - positiveTestValue: "Ä", + positiveTestValue: "ÄĞǼẌ", negativeTestValue: "€", errorMessage: errorMessageA, valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") @@ -38,7 +38,7 @@ const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .concat( restrictedIdentityAttributeTypesB.map((type) => ({ type, - positiveTestValue: "€", + positiveTestValue: "µẄ€k͟hŽ̧", negativeTestValue: "z-\u000D", errorMessage: errorMessageB, valueHintsPattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") @@ -47,7 +47,7 @@ const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .concat( restrictedIdentityAttributeTypesC.map((type) => ({ type, - positiveTestValue: "z-\u000D", + positiveTestValue: "z-\u000D¾£(),", negativeTestValue: "\u0012", errorMessage: errorMessageC, valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") @@ -72,8 +72,8 @@ const relationshipAttributeValueTestParameters = [ ]; test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type, valueHintsPattern }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D", title: "aTitle" }) as any; - expect(attribute.value).toBe("z-\u000D"); + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D¾£(),", title: "aTitle" }) as any; + expect(attribute.value).toBe("z-\u000D¾£(),"); expect(attribute.valueHints.pattern).toBe(valueHintsPattern); }); @@ -101,32 +101,32 @@ const proprietaryAttributeTypes = [ ]; test.each(proprietaryAttributeTypes)("title of $type is considered as valid", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D" }); - expect((attribute as any).title).toBe("\u000D"); + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D¾£()," }); + expect((attribute as any).title).toBe("\u000D¾£(),"); }); test.each(proprietaryAttributeTypes)("title of $type is considered as invalid", ({ type, value }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "\u0012" }); + Serializable.fromUnknown({ "@type": type, value, title: "Ω" }); }; expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); }); test.each(proprietaryAttributeTypes)("description of $type is considered as valid", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D" }); - expect((attribute as any).description).toBe("\u000D"); + const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D¾£()," }); + expect((attribute as any).description).toBe("\u000D¾£(),"); }); test.each(proprietaryAttributeTypes)("description of $type is considered as invalid", ({ type, value }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u0012" }); + Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "Ω" }); }; expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); }); test("Key of RelationshipAttribute is valid", () => { const attribute = RelationshipAttribute.from({ - key: "\u000D", + key: "\u000D¾£(),", confidentiality: RelationshipAttributeConfidentiality.Private, value: { "@type": "ProprietaryBoolean", @@ -136,13 +136,13 @@ test("Key of RelationshipAttribute is valid", () => { "@type": "RelationshipAttribute", owner: "theOwner" }); - expect(attribute.key).toBe("\u000D"); + expect(attribute.key).toBe("\u000D¾£(),"); }); test("Key of RelationshipAttribute is invalid", () => { const invalidCall = () => { RelationshipAttribute.from({ - key: "\u0012", + key: "Б", confidentiality: RelationshipAttributeConfidentiality.Private, value: { "@type": "ProprietaryBoolean", @@ -159,12 +159,12 @@ test("Key of RelationshipAttribute is invalid", () => { test("ValueHints is valid", () => { const validCall = () => { ValueHints.from({ - defaultValue: "\u000D", - editHelp: "\u000D", + defaultValue: "\u000D¾£(),", + editHelp: "\u000D¾£(),", values: [ { - key: "\u000D", - displayName: "\u000D" + key: "\u000D¾£(),", + displayName: "\u000D¾£()," } ] }); @@ -174,28 +174,28 @@ test("ValueHints is valid", () => { test("defaultValue of ValueHints is invalid", () => { const invalidCall = () => { - ValueHints.from({ defaultValue: "\u0012" }); + ValueHints.from({ defaultValue: "™" }); }; expect(invalidCall).toThrow(new ParsingError("ValueHints", "defaultValue:Object", errorMessageC)); }); test("editHelp of ValueHints is invalid", () => { const invalidCall = () => { - ValueHints.from({ editHelp: "\u0012" }); + ValueHints.from({ editHelp: "™" }); }; expect(invalidCall).toThrow(new ParsingError("ValueHints", "editHelp", errorMessageC)); }); test("key of ValueHintsValue is invalid", () => { const invalidCall = () => { - ValueHintsValue.from({ key: "\u0012", displayName: "aDisplayName" }); + ValueHintsValue.from({ key: "™", displayName: "aDisplayName" }); }; expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "key:Object", errorMessageC)); }); test("displayName of ValueHintsValue is invalid", () => { const invalidCall = () => { - ValueHintsValue.from({ key: "aKey", displayName: "\u0012" }); + ValueHintsValue.from({ key: "aKey", displayName: "💩" }); }; expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "displayName", errorMessageC)); }); From b052ea0e3ae3f1928599d48e23f37c72382af7fa Mon Sep 17 00:00:00 2001 From: mkuhn Date: Wed, 29 Jan 2025 12:15:27 +0100 Subject: [PATCH 24/34] fix: make ValueHintsOverride work, add tests --- .../src/attributes/hints/ValueHints.ts | 22 +++---- .../test/attributes/CharacterSets.test.ts | 59 ++++++++++--------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/content/src/attributes/hints/ValueHints.ts b/packages/content/src/attributes/hints/ValueHints.ts index 7f5dc3371..b81f26777 100644 --- a/packages/content/src/attributes/hints/ValueHints.ts +++ b/packages/content/src/attributes/hints/ValueHints.ts @@ -68,7 +68,7 @@ export class ValueHints extends Serializable implements IValueHints { @validate({ nullable: true }) public values?: ValueHintsValue[]; - @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], customValidator: ValueHints.validateDefaultValue }) + @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], customValidator: validateDefaultValue }) @serialize() public defaultValue?: number | string | boolean; @@ -100,14 +100,6 @@ export class ValueHints extends Serializable implements IValueHints { const propertyHints = { ...this.toJSON().propertyHints, ...overrideJson?.propertyHints }; return ValueHints.from({ ...this.toJSON(), ...overrideJson, propertyHints }); } - - private static validateDefaultValue(defaultValue: string | number | boolean) { - if (typeof defaultValue === "string" && !characterSets.din91379DatatypeC.test(defaultValue)) { - return "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; - } - - return undefined; - } } @type("ValueHintsOverride") @@ -132,8 +124,8 @@ export class ValueHintsOverride extends Serializable implements IValueHintsOverr @validate({ nullable: true }) public values?: ValueHintsValue[]; - @serialize({ unionTypes: [Boolean, Number, String] }) - @validate({ nullable: true, regExp: characterSets.din91379DatatypeC }) + @serialize() + @validate({ nullable: true, allowedTypes: [PrimitiveType.Number, PrimitiveType.String, PrimitiveType.Boolean], customValidator: validateDefaultValue }) public defaultValue?: boolean | number | string; @serialize() @@ -156,3 +148,11 @@ export class ValueHintsOverride extends Serializable implements IValueHintsOverr return json; } } + +function validateDefaultValue(defaultValue: string | number | boolean) { + if (typeof defaultValue === "string" && !characterSets.din91379DatatypeC.test(defaultValue)) { + return "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; + } + + return undefined; +} diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 27fe29818..9b60f8b6a 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -1,5 +1,5 @@ import { ParsingError, Serializable } from "@js-soft/ts-serval"; -import { Consent, RelationshipAttribute, RelationshipAttributeConfidentiality, ValueHints, ValueHintsValue } from "../../src"; +import { Consent, RelationshipAttribute, RelationshipAttributeConfidentiality, ValueHintsValue } from "../../src"; import { characterSets } from "../../src/attributes/constants/CharacterSets"; const errorMessageA = @@ -30,7 +30,7 @@ const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .map((type) => ({ type, - positiveTestValue: "ÄĞǼẌ", + positiveTestValue: "ÄĞǼẌ\u0041\u0308", negativeTestValue: "€", errorMessage: errorMessageA, valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") @@ -156,34 +156,37 @@ test("Key of RelationshipAttribute is invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageC)); }); -test("ValueHints is valid", () => { - const validCall = () => { - ValueHints.from({ - defaultValue: "\u000D¾£(),", - editHelp: "\u000D¾£(),", - values: [ - { - key: "\u000D¾£(),", - displayName: "\u000D¾£()," - } - ] - }); - }; - expect(validCall).not.toThrow(); -}); +describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { + test("is valid", () => { + const validCall = () => { + Serializable.fromUnknown({ + "@type": type, + defaultValue: "\u000D¾£(),", + editHelp: "\u000D¾£(),", + values: [ + { + key: "\u000D¾£(),", + displayName: "\u000D¾£()," + } + ] + }); + }; + expect(validCall).not.toThrow(); + }); -test("defaultValue of ValueHints is invalid", () => { - const invalidCall = () => { - ValueHints.from({ defaultValue: "™" }); - }; - expect(invalidCall).toThrow(new ParsingError("ValueHints", "defaultValue:Object", errorMessageC)); -}); + test("defaultValue is invalid", () => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, defaultValue: "™" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, "defaultValue:Object", errorMessageC)); + }); -test("editHelp of ValueHints is invalid", () => { - const invalidCall = () => { - ValueHints.from({ editHelp: "™" }); - }; - expect(invalidCall).toThrow(new ParsingError("ValueHints", "editHelp", errorMessageC)); + test("editHelp is invalid", () => { + const invalidCall = () => { + Serializable.fromUnknown({ "@type": type, editHelp: "™" }); + }; + expect(invalidCall).toThrow(new ParsingError(type, "editHelp", errorMessageC)); + }); }); test("key of ValueHintsValue is invalid", () => { From 1fcb037b46b3357d46a7726e077f6a512ca588d9 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Wed, 29 Jan 2025 12:22:40 +0100 Subject: [PATCH 25/34] refactor: clearer datatype explanation --- packages/content/src/attributes/constants/CharacterSets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts index eded30ac0..331354225 100644 --- a/packages/content/src/attributes/constants/CharacterSets.ts +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -7,7 +7,7 @@ export const characterSets: Record = { // datatype B for all names din91379DatatypeB: /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, - // datatype C for everything + // datatype C for every mandatory character in the norm din91379DatatypeC: /^([\u0009-\u000A]|\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/ }; From 9d0fdc1b704295c4f895fbddbef12ba46eb55557 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Wed, 29 Jan 2025 15:33:31 +0100 Subject: [PATCH 26/34] feat: restrict some addresses --- .../types/address/DeliveryBoxAddress.ts | 9 +-- .../types/address/PostOfficeBoxAddress.ts | 5 +- .../test/attributes/CharacterSets.test.ts | 62 ++++++++++++++++++- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/packages/content/src/attributes/types/address/DeliveryBoxAddress.ts b/packages/content/src/attributes/types/address/DeliveryBoxAddress.ts index 1d7b0390b..d52576155 100644 --- a/packages/content/src/attributes/types/address/DeliveryBoxAddress.ts +++ b/packages/content/src/attributes/types/address/DeliveryBoxAddress.ts @@ -2,6 +2,7 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { nameof } from "ts-simple-nameof"; import { AbstractAttributeValue } from "../../AbstractAttributeValue"; import { COUNTRIES_ALPHA2_TO_ENGLISH_NAME } from "../../constants"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../../hints"; import { IPhoneNumber, PhoneNumber } from "../communication"; import { AbstractAddress, AbstractAddressJSON, IAbstractAddress } from "./AbstractAddress"; @@ -34,11 +35,11 @@ export interface IDeliveryBoxAddress extends IAbstractAddress { @type("DeliveryBoxAddress") export class DeliveryBoxAddress extends AbstractAddress implements IDeliveryBoxAddress { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeB }) public userId: string; @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeB }) public deliveryBoxId: string; @serialize({ customGenerator: AbstractAttributeValue.valueGenerator }) @@ -64,8 +65,8 @@ export class DeliveryBoxAddress extends AbstractAddress implements IDeliveryBoxA public static override get valueHints(): ValueHints { return super.valueHints.copyWith({ propertyHints: { - [nameof((d) => d.userId)]: ValueHints.from({}), - [nameof((d) => d.deliveryBoxId)]: ValueHints.from({}), + [nameof((d) => d.userId)]: ValueHints.from({ pattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") }), + [nameof((d) => d.deliveryBoxId)]: ValueHints.from({ pattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") }), [nameof((d) => d.zipCode)]: ZipCode.valueHints, [nameof((d) => d.city)]: City.valueHints, [nameof((d) => d.country)]: Country.valueHints, diff --git a/packages/content/src/attributes/types/address/PostOfficeBoxAddress.ts b/packages/content/src/attributes/types/address/PostOfficeBoxAddress.ts index b2426a2f9..9ab3752d3 100644 --- a/packages/content/src/attributes/types/address/PostOfficeBoxAddress.ts +++ b/packages/content/src/attributes/types/address/PostOfficeBoxAddress.ts @@ -2,6 +2,7 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { nameof } from "ts-simple-nameof"; import { AbstractAttributeValue } from "../../AbstractAttributeValue"; import { COUNTRIES_ALPHA2_TO_ENGLISH_NAME } from "../../constants"; +import { characterSets } from "../../constants/CharacterSets"; import { RenderHints, RenderHintsEditType, RenderHintsTechnicalType, ValueHints } from "../../hints"; import { AbstractAddress, AbstractAddressJSON, IAbstractAddress } from "./AbstractAddress"; import { City, ICity } from "./City"; @@ -29,7 +30,7 @@ export interface IPostOfficeBoxAddress extends IAbstractAddress { @type("PostOfficeBoxAddress") export class PostOfficeBoxAddress extends AbstractAddress implements IPostOfficeBoxAddress { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeB }) public boxId: string; @serialize({ customGenerator: AbstractAttributeValue.valueGenerator }) @@ -51,7 +52,7 @@ export class PostOfficeBoxAddress extends AbstractAddress implements IPostOffice public static override get valueHints(): ValueHints { return super.valueHints.copyWith({ propertyHints: { - [nameof((p) => p.boxId)]: ValueHints.from({}), + [nameof((p) => p.boxId)]: ValueHints.from({ pattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") }), [nameof((p) => p.zipCode)]: ZipCode.valueHints, [nameof((p) => p.city)]: City.valueHints, [nameof((p) => p.country)]: Country.valueHints, diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 9b60f8b6a..c21484da9 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -1,5 +1,14 @@ import { ParsingError, Serializable } from "@js-soft/ts-serval"; -import { Consent, RelationshipAttribute, RelationshipAttributeConfidentiality, ValueHintsValue } from "../../src"; +import { + Consent, + DeliveryBoxAddress, + IDeliveryBoxAddress, + IPostOfficeBoxAddress, + PostOfficeBoxAddress, + RelationshipAttribute, + RelationshipAttributeConfidentiality, + ValueHintsValue +} from "../../src"; import { characterSets } from "../../src/attributes/constants/CharacterSets"; const errorMessageA = @@ -23,6 +32,57 @@ test("Consent is considered as invalid", () => { expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageC)); }); +const correctDeliveryBoxAddress: IDeliveryBoxAddress = { + city: "aCity", + country: "DE", + deliveryBoxId: "aBoxId~0", + recipient: "aRecipient@7", + userId: "aUserId<6", + zipCode: "aZipCode" +}; + +test("DeliveryBoxAddress is considered as valid", () => { + const deliveryBoxAddress = DeliveryBoxAddress.from(correctDeliveryBoxAddress); + expect(deliveryBoxAddress.valueHints.propertyHints.deliveryBoxId.pattern).toBe(characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/")); + expect(deliveryBoxAddress.valueHints.propertyHints.recipient.pattern).toBe(characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/")); + expect(deliveryBoxAddress.valueHints.propertyHints.userId.pattern).toBe(characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/")); +}); + +test.each(["recipient", "userId", "deliveryBoxId"])("%s of DeliveryBoxAddress is considered as invalid", (propertyName) => { + const invalidCall = () => { + DeliveryBoxAddress.from({ + ...correctDeliveryBoxAddress, + [propertyName]: "invalidValue≥" + }); + }; + + expect(invalidCall).toThrow(new ParsingError("DeliveryBoxAddress", propertyName, errorMessageB)); +}); + +const correctPostOfficeBoxAddress: IPostOfficeBoxAddress = { + city: "aCity", + country: "DE", + boxId: "aBoxId#", + recipient: "aRecipient_", + zipCode: "aZipCode" +}; + +test("PostOfficeBoxAddress is considered as valid", () => { + const postOfficeBoxAddress = PostOfficeBoxAddress.from(correctPostOfficeBoxAddress); + expect(postOfficeBoxAddress.valueHints.propertyHints.boxId.pattern).toBe(characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/")); + expect(postOfficeBoxAddress.valueHints.propertyHints.recipient.pattern).toBe(characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/")); +}); + +test.each(["boxId", "recipient"])("%s of PostOfficeBoxAddress is considered as invalid", (propertyName) => { + const invalidCall = () => { + PostOfficeBoxAddress.from({ + ...correctPostOfficeBoxAddress, + [propertyName]: "invalidValue≤" + }); + }; + expect(invalidCall).toThrow(new ParsingError("PostOfficeBoxAddress", propertyName, errorMessageB)); +}); + const restrictedIdentityAttributeTypesA = ["BirthName", "GivenName", "HonorificPrefix", "HonorificSuffix", "MiddleName", "Pseudonym", "Surname"]; const restrictedIdentityAttributeTypesB = ["City", "HouseNumber", "State", "Street", "ZipCode", "AffiliationOrganization", "DisplayName", "JobTitle"]; const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", "StatementPredicate"]; From 5fb432ed0a72c263014974dd7f629b39fcd00a25 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Wed, 29 Jan 2025 16:05:34 +0100 Subject: [PATCH 27/34] feat: restrict attributeQueries --- .../attributes/RelationshipAttributeQuery.ts | 7 ++- .../ThirdPartyRelationshipAttributeQuery.ts | 3 +- .../test/attributes/CharacterSets.test.ts | 63 ++++++++++++++++--- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/packages/content/src/attributes/RelationshipAttributeQuery.ts b/packages/content/src/attributes/RelationshipAttributeQuery.ts index 83c38576a..eb8e60c69 100644 --- a/packages/content/src/attributes/RelationshipAttributeQuery.ts +++ b/packages/content/src/attributes/RelationshipAttributeQuery.ts @@ -2,6 +2,7 @@ import { ISerializable, Serializable, serialize, type, validate } from "@js-soft import { CoreAddress, CoreDate, ICoreAddress, ICoreDate } from "@nmshd/core-types"; import { AbstractAttributeQuery, AbstractAttributeQueryJSON, IAbstractAttributeQuery } from "./AbstractAttributeQuery"; import { AttributeValues } from "./AttributeValueTypes"; +import { characterSets } from "./constants/CharacterSets"; import { IValueHints, ValueHints, ValueHintsJSON } from "./hints"; import { RelationshipAttributeConfidentiality } from "./RelationshipAttributeConfidentiality"; import { PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH } from "./types/proprietary/ProprietaryAttributeValue"; @@ -30,7 +31,7 @@ export interface IRelationshipAttributeCreationHints extends ISerializable { @type("RelationshipAttributeCreationHints") export class RelationshipAttributeCreationHints extends Serializable implements IRelationshipAttributeCreationHints { @serialize() - @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH }) + @validate({ max: PROPRIETARY_ATTRIBUTE_MAX_TITLE_LENGTH, regExp: characterSets.din91379DatatypeC }) public title: string; @serialize() @@ -40,7 +41,7 @@ export class RelationshipAttributeCreationHints extends Serializable implements public valueType: AttributeValues.Relationship.TypeName; @serialize() - @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH }) + @validate({ nullable: true, max: PROPRIETARY_ATTRIBUTE_MAX_DESCRIPTION_LENGTH, regExp: characterSets.din91379DatatypeC }) public description?: string; @serialize() @@ -85,7 +86,7 @@ export interface IRelationshipAttributeQuery extends IAbstractAttributeQuery { @type("RelationshipAttributeQuery") export class RelationshipAttributeQuery extends AbstractAttributeQuery implements IRelationshipAttributeQuery { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeC }) public key: string; @serialize() diff --git a/packages/content/src/attributes/ThirdPartyRelationshipAttributeQuery.ts b/packages/content/src/attributes/ThirdPartyRelationshipAttributeQuery.ts index 64c61a634..839310b2d 100644 --- a/packages/content/src/attributes/ThirdPartyRelationshipAttributeQuery.ts +++ b/packages/content/src/attributes/ThirdPartyRelationshipAttributeQuery.ts @@ -1,6 +1,7 @@ import { serialize, type, validate } from "@js-soft/ts-serval"; import { CoreAddress, CoreDate, ICoreAddress, ICoreDate } from "@nmshd/core-types"; import { AbstractAttributeQuery, AbstractAttributeQueryJSON, IAbstractAttributeQuery } from "./AbstractAttributeQuery"; +import { characterSets } from "./constants/CharacterSets"; export interface ThirdPartyRelationshipAttributeQueryJSON extends AbstractAttributeQueryJSON { "@type": "ThirdPartyRelationshipAttributeQuery"; key: string; @@ -27,7 +28,7 @@ export enum ThirdPartyRelationshipAttributeQueryOwner { @type("ThirdPartyRelationshipAttributeQuery") export class ThirdPartyRelationshipAttributeQuery extends AbstractAttributeQuery implements IThirdPartyRelationshipAttributeQuery { @serialize() - @validate({ max: 100 }) + @validate({ max: 100, regExp: characterSets.din91379DatatypeC }) public key: string; @serialize() diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index c21484da9..7f078e08f 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -7,6 +7,8 @@ import { PostOfficeBoxAddress, RelationshipAttribute, RelationshipAttributeConfidentiality, + RelationshipAttributeQuery, + ThirdPartyRelationshipAttributeQuery, ValueHintsValue } from "../../src"; import { characterSets } from "../../src/attributes/constants/CharacterSets"; @@ -144,7 +146,7 @@ test.each(relationshipAttributeValueTestParameters)("value of $type is considere expect(invalidCall).toThrow(new ParsingError(type, propertyInErrorMessage, errorMessageC)); }); -const proprietaryAttributeTypes = [ +const proprietaryAttributeTestParameters = [ { type: "ProprietaryBoolean", value: true }, { type: "ProprietaryCountry", value: "DE" }, { type: "ProprietaryEMailAddress", value: "email@email.de" }, @@ -157,29 +159,30 @@ const proprietaryAttributeTypes = [ { type: "ProprietaryString", value: "aString" }, { type: "ProprietaryURL", value: "mail.de" }, { type: "ProprietaryJSON", value: "aString" }, - { type: "ProprietaryXML", value: "aString" } + { type: "ProprietaryXML", value: "aString" }, + { type: "RelationshipAttributeCreationHints", valueType: "ProprietaryBoolean", confidentiality: RelationshipAttributeConfidentiality.Private } ]; -test.each(proprietaryAttributeTypes)("title of $type is considered as valid", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "\u000D¾£()," }); +test.each(proprietaryAttributeTestParameters)("title of $type is considered as valid", ({ type, value, valueType, confidentiality }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "\u000D¾£()," }); expect((attribute as any).title).toBe("\u000D¾£(),"); }); -test.each(proprietaryAttributeTypes)("title of $type is considered as invalid", ({ type, value }) => { +test.each(proprietaryAttributeTestParameters)("title of $type is considered as invalid", ({ type, value, valueType, confidentiality }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "Ω" }); + Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "Ω" }); }; expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); }); -test.each(proprietaryAttributeTypes)("description of $type is considered as valid", ({ type, value }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "\u000D¾£()," }); +test.each(proprietaryAttributeTestParameters)("description of $type is considered as valid", ({ type, value, valueType, confidentiality }) => { + const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "\u000D¾£()," }); expect((attribute as any).description).toBe("\u000D¾£(),"); }); -test.each(proprietaryAttributeTypes)("description of $type is considered as invalid", ({ type, value }) => { +test.each(proprietaryAttributeTestParameters)("description of $type is considered as invalid", ({ type, value, valueType, confidentiality }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, title: "aTitle", description: "Ω" }); + Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "Ω" }); }; expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); }); @@ -216,6 +219,46 @@ test("Key of RelationshipAttribute is invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageC)); }); +test("Key of RelationshipAttributeQuery is valid", () => { + const attribute = RelationshipAttributeQuery.from({ + owner: "theOwner", + attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, + key: "\u000D¾£()," + }); + expect(attribute.key).toBe("\u000D¾£(),"); +}); + +test("Key of RelationshipAttributeQuery is invalid", () => { + const invalidCall = () => { + RelationshipAttributeQuery.from({ + owner: "theOwner", + attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, + key: "Б" + }); + }; + expect(invalidCall).toThrow(new ParsingError("RelationshipAttributeQuery", "key", errorMessageC)); +}); + +test("Key of ThirdPartyRelationshipAttributeQuery is valid", () => { + const attribute = ThirdPartyRelationshipAttributeQuery.from({ + owner: "", + thirdParty: ["aThirdParty"], + key: "\u000D¾£()," + }); + expect(attribute.key).toBe("\u000D¾£(),"); +}); + +test("Key of ThirdPartyRelationshipAttributeQuery is invalid", () => { + const invalidCall = () => { + ThirdPartyRelationshipAttributeQuery.from({ + owner: "", + thirdParty: ["aThirdParty"], + key: "Б" + }); + }; + expect(invalidCall).toThrow(new ParsingError("ThirdPartyRelationshipAttributeQuery", "key", errorMessageC)); +}); + describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { test("is valid", () => { const validCall = () => { From 8fbfbacc7ce45b5fe2d2e5b4480f95fbd96f8537 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Thu, 30 Jan 2025 10:48:05 +0100 Subject: [PATCH 28/34] test: don't test NFC normalization --- packages/content/test/attributes/CharacterSets.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 7f078e08f..6bf0e58ef 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -92,7 +92,7 @@ const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .map((type) => ({ type, - positiveTestValue: "ÄĞǼẌ\u0041\u0308", + positiveTestValue: "ÄĞǼẌ ", negativeTestValue: "€", errorMessage: errorMessageA, valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") From 00b6346e6aaf684dd87c818aaf36246925a7b730 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Thu, 30 Jan 2025 10:56:03 +0100 Subject: [PATCH 29/34] refactor: namings in the test --- .../test/attributes/CharacterSets.test.ts | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 6bf0e58ef..6945fabc8 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -13,25 +13,25 @@ import { } from "../../src"; import { characterSets } from "../../src/attributes/constants/CharacterSets"; -const errorMessageA = +const errorMessageDatatypeA = "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; -const errorMessageB = +const errorMessageDatatypeB = "Value does not match regular expression /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; -const errorMessageC = +const errorMessageDatatypeC = "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; test("Consent is considered as valid", () => { - const consent = Consent.from({ consent: "z-\u000D¾£()," }); - expect(consent.consent.toString()).toBe("z-\u000D¾£(),"); + const consent = Consent.from({ consent: "z-validValue\u000D¾£()," }); + expect(consent.consent.toString()).toBe("z-validValue\u000D¾£(),"); }); test("Consent is considered as invalid", () => { const invalidCall = () => { Consent.from({ - consent: "\u0012" + consent: "invalidValue\u0012" }); }; - expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("Consent", "consent", errorMessageDatatypeC)); }); const correctDeliveryBoxAddress: IDeliveryBoxAddress = { @@ -58,7 +58,7 @@ test.each(["recipient", "userId", "deliveryBoxId"])("%s of DeliveryBoxAddress is }); }; - expect(invalidCall).toThrow(new ParsingError("DeliveryBoxAddress", propertyName, errorMessageB)); + expect(invalidCall).toThrow(new ParsingError("DeliveryBoxAddress", propertyName, errorMessageDatatypeB)); }); const correctPostOfficeBoxAddress: IPostOfficeBoxAddress = { @@ -82,7 +82,7 @@ test.each(["boxId", "recipient"])("%s of PostOfficeBoxAddress is considered as i [propertyName]: "invalidValue≤" }); }; - expect(invalidCall).toThrow(new ParsingError("PostOfficeBoxAddress", propertyName, errorMessageB)); + expect(invalidCall).toThrow(new ParsingError("PostOfficeBoxAddress", propertyName, errorMessageDatatypeB)); }); const restrictedIdentityAttributeTypesA = ["BirthName", "GivenName", "HonorificPrefix", "HonorificSuffix", "MiddleName", "Pseudonym", "Surname"]; @@ -92,26 +92,26 @@ const restrictedIdentityAttributeTypesC = ["AffiliationRole", "AffiliationUnit", const identityAttributeTestParameters = restrictedIdentityAttributeTypesA .map((type) => ({ type, - positiveTestValue: "ÄĞǼẌ ", - negativeTestValue: "€", - errorMessage: errorMessageA, + positiveTestValue: "validValueÄĞǼẌ ", + negativeTestValue: "invalidValue€", + errorMessage: errorMessageDatatypeA, valueHintsPattern: characterSets.din91379DatatypeA.toString().slice(1, -1).replaceAll("/", "\\/") })) .concat( restrictedIdentityAttributeTypesB.map((type) => ({ type, - positiveTestValue: "µẄ€k͟hŽ̧", - negativeTestValue: "z-\u000D", - errorMessage: errorMessageB, + positiveTestValue: "validValueµẄ€k͟hŽ̧", + negativeTestValue: "z-invalidValue\u000D", + errorMessage: errorMessageDatatypeB, valueHintsPattern: characterSets.din91379DatatypeB.toString().slice(1, -1).replaceAll("/", "\\/") })) ) .concat( restrictedIdentityAttributeTypesC.map((type) => ({ type, - positiveTestValue: "z-\u000D¾£(),", - negativeTestValue: "\u0012", - errorMessage: errorMessageC, + positiveTestValue: "z-validValue\u000D¾£(),", + negativeTestValue: "invalidValue\u0012", + errorMessage: errorMessageDatatypeC, valueHintsPattern: characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/") })) ); @@ -134,16 +134,16 @@ const relationshipAttributeValueTestParameters = [ ]; test.each(relationshipAttributeValueTestParameters)("value of $type is considered as valid", ({ type, valueHintsPattern }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-\u000D¾£(),", title: "aTitle" }) as any; - expect(attribute.value).toBe("z-\u000D¾£(),"); + const attribute = Serializable.fromUnknown({ "@type": type, value: "z-validValue\u000D¾£(),", title: "aTitle" }) as any; + expect(attribute.value).toBe("z-validValue\u000D¾£(),"); expect(attribute.valueHints.pattern).toBe(valueHintsPattern); }); test.each(relationshipAttributeValueTestParameters)("value of $type is considered as invalid", ({ type, propertyInErrorMessage }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value: "z-\u0012", title: "aTitle" }); + Serializable.fromUnknown({ "@type": type, value: "z-invalidValue\u0012", title: "aTitle" }); }; - expect(invalidCall).toThrow(new ParsingError(type, propertyInErrorMessage, errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, propertyInErrorMessage, errorMessageDatatypeC)); }); const proprietaryAttributeTestParameters = [ @@ -164,32 +164,32 @@ const proprietaryAttributeTestParameters = [ ]; test.each(proprietaryAttributeTestParameters)("title of $type is considered as valid", ({ type, value, valueType, confidentiality }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "\u000D¾£()," }); - expect((attribute as any).title).toBe("\u000D¾£(),"); + const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "validValue\u000D¾£()," }); + expect((attribute as any).title).toBe("validValue\u000D¾£(),"); }); test.each(proprietaryAttributeTestParameters)("title of $type is considered as invalid", ({ type, value, valueType, confidentiality }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "Ω" }); + Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "invalidValueΩ" }); }; - expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, "title", errorMessageDatatypeC)); }); test.each(proprietaryAttributeTestParameters)("description of $type is considered as valid", ({ type, value, valueType, confidentiality }) => { - const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "\u000D¾£()," }); - expect((attribute as any).description).toBe("\u000D¾£(),"); + const attribute = Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "validValue\u000D¾£()," }); + expect((attribute as any).description).toBe("validValue\u000D¾£(),"); }); test.each(proprietaryAttributeTestParameters)("description of $type is considered as invalid", ({ type, value, valueType, confidentiality }) => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "Ω" }); + Serializable.fromUnknown({ "@type": type, value, valueType, confidentiality, title: "aTitle", description: "invalidValueΩ" }); }; - expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageDatatypeC)); }); test("Key of RelationshipAttribute is valid", () => { const attribute = RelationshipAttribute.from({ - key: "\u000D¾£(),", + key: "validValue\u000D¾£(),", confidentiality: RelationshipAttributeConfidentiality.Private, value: { "@type": "ProprietaryBoolean", @@ -199,13 +199,13 @@ test("Key of RelationshipAttribute is valid", () => { "@type": "RelationshipAttribute", owner: "theOwner" }); - expect(attribute.key).toBe("\u000D¾£(),"); + expect(attribute.key).toBe("validValue\u000D¾£(),"); }); test("Key of RelationshipAttribute is invalid", () => { const invalidCall = () => { RelationshipAttribute.from({ - key: "Б", + key: "invalidValueБ", confidentiality: RelationshipAttributeConfidentiality.Private, value: { "@type": "ProprietaryBoolean", @@ -216,16 +216,16 @@ test("Key of RelationshipAttribute is invalid", () => { owner: "theOwner" }); }; - expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageDatatypeC)); }); test("Key of RelationshipAttributeQuery is valid", () => { const attribute = RelationshipAttributeQuery.from({ owner: "theOwner", attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, - key: "\u000D¾£()," + key: "validValue\u000D¾£()," }); - expect(attribute.key).toBe("\u000D¾£(),"); + expect(attribute.key).toBe("validValue\u000D¾£(),"); }); test("Key of RelationshipAttributeQuery is invalid", () => { @@ -233,19 +233,19 @@ test("Key of RelationshipAttributeQuery is invalid", () => { RelationshipAttributeQuery.from({ owner: "theOwner", attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, - key: "Б" + key: "invalidValueБ" }); }; - expect(invalidCall).toThrow(new ParsingError("RelationshipAttributeQuery", "key", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("RelationshipAttributeQuery", "key", errorMessageDatatypeC)); }); test("Key of ThirdPartyRelationshipAttributeQuery is valid", () => { const attribute = ThirdPartyRelationshipAttributeQuery.from({ owner: "", thirdParty: ["aThirdParty"], - key: "\u000D¾£()," + key: "validValue\u000D¾£()," }); - expect(attribute.key).toBe("\u000D¾£(),"); + expect(attribute.key).toBe("validValue\u000D¾£(),"); }); test("Key of ThirdPartyRelationshipAttributeQuery is invalid", () => { @@ -253,10 +253,10 @@ test("Key of ThirdPartyRelationshipAttributeQuery is invalid", () => { ThirdPartyRelationshipAttributeQuery.from({ owner: "", thirdParty: ["aThirdParty"], - key: "Б" + key: "invalidValueБ" }); }; - expect(invalidCall).toThrow(new ParsingError("ThirdPartyRelationshipAttributeQuery", "key", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("ThirdPartyRelationshipAttributeQuery", "key", errorMessageDatatypeC)); }); describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { @@ -264,12 +264,12 @@ describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { const validCall = () => { Serializable.fromUnknown({ "@type": type, - defaultValue: "\u000D¾£(),", - editHelp: "\u000D¾£(),", + defaultValue: "validValue\u000D¾£(),", + editHelp: "validValue\u000D¾£(),", values: [ { - key: "\u000D¾£(),", - displayName: "\u000D¾£()," + key: "validValue\u000D¾£(),", + displayName: "validValue\u000D¾£()," } ] }); @@ -279,29 +279,29 @@ describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { test("defaultValue is invalid", () => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, defaultValue: "™" }); + Serializable.fromUnknown({ "@type": type, defaultValue: "invalidValue™" }); }; - expect(invalidCall).toThrow(new ParsingError(type, "defaultValue:Object", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, "defaultValue:Object", errorMessageDatatypeC)); }); test("editHelp is invalid", () => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, editHelp: "™" }); + Serializable.fromUnknown({ "@type": type, editHelp: "invalidValue™" }); }; - expect(invalidCall).toThrow(new ParsingError(type, "editHelp", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError(type, "editHelp", errorMessageDatatypeC)); }); }); test("key of ValueHintsValue is invalid", () => { const invalidCall = () => { - ValueHintsValue.from({ key: "™", displayName: "aDisplayName" }); + ValueHintsValue.from({ key: "invalidValue™", displayName: "aDisplayName" }); }; - expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "key:Object", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "key:Object", errorMessageDatatypeC)); }); test("displayName of ValueHintsValue is invalid", () => { const invalidCall = () => { - ValueHintsValue.from({ key: "aKey", displayName: "💩" }); + ValueHintsValue.from({ key: "aKey", displayName: "invalidValue💩" }); }; - expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "displayName", errorMessageC)); + expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "displayName", errorMessageDatatypeC)); }); From e17074f65a0c5d9fb859d4ac285a2303096d467f Mon Sep 17 00:00:00 2001 From: mkuhn Date: Thu, 30 Jan 2025 11:21:23 +0100 Subject: [PATCH 30/34] refactor: cleaner test names --- .../test/attributes/CharacterSets.test.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 6945fabc8..29c2e2d1f 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -154,11 +154,11 @@ const proprietaryAttributeTestParameters = [ { type: "ProprietaryFloat", value: 1 }, { type: "ProprietaryHEXColor", value: "#000000" }, { type: "ProprietaryInteger", value: 1 }, + { type: "ProprietaryJSON", value: "aString" }, { type: "ProprietaryLanguage", value: "de" }, { type: "ProprietaryPhoneNumber", value: "1234567890" }, { type: "ProprietaryString", value: "aString" }, { type: "ProprietaryURL", value: "mail.de" }, - { type: "ProprietaryJSON", value: "aString" }, { type: "ProprietaryXML", value: "aString" }, { type: "RelationshipAttributeCreationHints", valueType: "ProprietaryBoolean", confidentiality: RelationshipAttributeConfidentiality.Private } ]; @@ -187,7 +187,7 @@ test.each(proprietaryAttributeTestParameters)("description of $type is considere expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageDatatypeC)); }); -test("Key of RelationshipAttribute is valid", () => { +test("Key of RelationshipAttribute is considered as valid", () => { const attribute = RelationshipAttribute.from({ key: "validValue\u000D¾£(),", confidentiality: RelationshipAttributeConfidentiality.Private, @@ -202,7 +202,7 @@ test("Key of RelationshipAttribute is valid", () => { expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of RelationshipAttribute is invalid", () => { +test("Key of RelationshipAttribute is considered as invalid", () => { const invalidCall = () => { RelationshipAttribute.from({ key: "invalidValueБ", @@ -219,7 +219,7 @@ test("Key of RelationshipAttribute is invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageDatatypeC)); }); -test("Key of RelationshipAttributeQuery is valid", () => { +test("Key of RelationshipAttributeQuery is considered as valid", () => { const attribute = RelationshipAttributeQuery.from({ owner: "theOwner", attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, @@ -228,7 +228,7 @@ test("Key of RelationshipAttributeQuery is valid", () => { expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of RelationshipAttributeQuery is invalid", () => { +test("Key of RelationshipAttributeQuery is considered as invalid", () => { const invalidCall = () => { RelationshipAttributeQuery.from({ owner: "theOwner", @@ -239,7 +239,7 @@ test("Key of RelationshipAttributeQuery is invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttributeQuery", "key", errorMessageDatatypeC)); }); -test("Key of ThirdPartyRelationshipAttributeQuery is valid", () => { +test("Key of ThirdPartyRelationshipAttributeQuery is considered as valid", () => { const attribute = ThirdPartyRelationshipAttributeQuery.from({ owner: "", thirdParty: ["aThirdParty"], @@ -248,7 +248,7 @@ test("Key of ThirdPartyRelationshipAttributeQuery is valid", () => { expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of ThirdPartyRelationshipAttributeQuery is invalid", () => { +test("Key of ThirdPartyRelationshipAttributeQuery is considered as invalid", () => { const invalidCall = () => { ThirdPartyRelationshipAttributeQuery.from({ owner: "", @@ -260,7 +260,7 @@ test("Key of ThirdPartyRelationshipAttributeQuery is invalid", () => { }); describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { - test("is valid", () => { + test("is considered as valid", () => { const validCall = () => { Serializable.fromUnknown({ "@type": type, @@ -277,14 +277,14 @@ describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { expect(validCall).not.toThrow(); }); - test("defaultValue is invalid", () => { + test("defaultValue is considered as invalid", () => { const invalidCall = () => { Serializable.fromUnknown({ "@type": type, defaultValue: "invalidValue™" }); }; expect(invalidCall).toThrow(new ParsingError(type, "defaultValue:Object", errorMessageDatatypeC)); }); - test("editHelp is invalid", () => { + test("editHelp is considered as invalid", () => { const invalidCall = () => { Serializable.fromUnknown({ "@type": type, editHelp: "invalidValue™" }); }; @@ -292,14 +292,14 @@ describe.each(["ValueHints", "ValueHintsOverride"])("%s tests", (type) => { }); }); -test("key of ValueHintsValue is invalid", () => { +test("key of ValueHintsValue is considered as invalid", () => { const invalidCall = () => { ValueHintsValue.from({ key: "invalidValue™", displayName: "aDisplayName" }); }; expect(invalidCall).toThrow(new ParsingError("ValueHintsValue", "key:Object", errorMessageDatatypeC)); }); -test("displayName of ValueHintsValue is invalid", () => { +test("displayName of ValueHintsValue is considered as invalid", () => { const invalidCall = () => { ValueHintsValue.from({ key: "aKey", displayName: "invalidValue💩" }); }; From 324193292c271c5ec861482d9eec6f14a7d42184 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Sun, 2 Feb 2025 21:00:29 +0100 Subject: [PATCH 31/34] refactor: review comments --- .../src/attributes/constants/CharacterSets.ts | 6 +++--- .../content/test/attributes/CharacterSets.test.ts | 12 ++++++------ .../runtime/test/transport/relationships.test.ts | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/content/src/attributes/constants/CharacterSets.ts b/packages/content/src/attributes/constants/CharacterSets.ts index 331354225..39d07949e 100644 --- a/packages/content/src/attributes/constants/CharacterSets.ts +++ b/packages/content/src/attributes/constants/CharacterSets.ts @@ -1,13 +1,13 @@ export const characterSets: Record = { // DIN91379 character sets from https://xoev.de/schemata/din/91379/2022-08/din-norm-91379-datatypes.xsd // See the sources in the browser's dev mode, they're not equal to what's initially displayed - // datatype A for names of natural persons + // data type A for names of natural persons din91379DatatypeA: /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, - // datatype B for all names + // data type B for all names din91379DatatypeB: /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/, - // datatype C for every mandatory character in the norm + // data type C for every mandatory character in the norm din91379DatatypeC: /^([\u0009-\u000A]|\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/ }; diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 29c2e2d1f..8a9b9dbb2 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -187,7 +187,7 @@ test.each(proprietaryAttributeTestParameters)("description of $type is considere expect(invalidCall).toThrow(new ParsingError(type, "description", errorMessageDatatypeC)); }); -test("Key of RelationshipAttribute is considered as valid", () => { +test("key of RelationshipAttribute is considered as valid", () => { const attribute = RelationshipAttribute.from({ key: "validValue\u000D¾£(),", confidentiality: RelationshipAttributeConfidentiality.Private, @@ -202,7 +202,7 @@ test("Key of RelationshipAttribute is considered as valid", () => { expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of RelationshipAttribute is considered as invalid", () => { +test("key of RelationshipAttribute is considered as invalid", () => { const invalidCall = () => { RelationshipAttribute.from({ key: "invalidValueБ", @@ -219,7 +219,7 @@ test("Key of RelationshipAttribute is considered as invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttribute", "key", errorMessageDatatypeC)); }); -test("Key of RelationshipAttributeQuery is considered as valid", () => { +test("key of RelationshipAttributeQuery is considered as valid", () => { const attribute = RelationshipAttributeQuery.from({ owner: "theOwner", attributeCreationHints: { confidentiality: RelationshipAttributeConfidentiality.Private, title: "aTitle", valueType: "ProprietaryBoolean" }, @@ -228,7 +228,7 @@ test("Key of RelationshipAttributeQuery is considered as valid", () => { expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of RelationshipAttributeQuery is considered as invalid", () => { +test("key of RelationshipAttributeQuery is considered as invalid", () => { const invalidCall = () => { RelationshipAttributeQuery.from({ owner: "theOwner", @@ -239,7 +239,7 @@ test("Key of RelationshipAttributeQuery is considered as invalid", () => { expect(invalidCall).toThrow(new ParsingError("RelationshipAttributeQuery", "key", errorMessageDatatypeC)); }); -test("Key of ThirdPartyRelationshipAttributeQuery is considered as valid", () => { +test("key of ThirdPartyRelationshipAttributeQuery is considered as valid", () => { const attribute = ThirdPartyRelationshipAttributeQuery.from({ owner: "", thirdParty: ["aThirdParty"], @@ -248,7 +248,7 @@ test("Key of ThirdPartyRelationshipAttributeQuery is considered as valid", () => expect(attribute.key).toBe("validValue\u000D¾£(),"); }); -test("Key of ThirdPartyRelationshipAttributeQuery is considered as invalid", () => { +test("key of ThirdPartyRelationshipAttributeQuery is considered as invalid", () => { const invalidCall = () => { ThirdPartyRelationshipAttributeQuery.from({ owner: "", diff --git a/packages/runtime/test/transport/relationships.test.ts b/packages/runtime/test/transport/relationships.test.ts index 353a0bdc0..af9ebee76 100644 --- a/packages/runtime/test/transport/relationships.test.ts +++ b/packages/runtime/test/transport/relationships.test.ts @@ -1,6 +1,6 @@ import { ApplicationError, Result, sleep } from "@js-soft/ts-utils"; import { ReadAttributeRequestItemJSON, RelationshipAttributeConfidentiality, RelationshipTemplateContentJSON } from "@nmshd/content"; -import { IdentityDeletionProcessStatus, Random } from "@nmshd/transport"; +import { IdentityDeletionProcessStatus, Random, RandomCharacterRange } from "@nmshd/transport"; import assert from "assert"; import { DateTime } from "luxon"; import { @@ -1012,7 +1012,7 @@ describe("RelationshipDecomposition", () => { await sendAndReceiveNotification(services1.transport, services2.transport, services2.consumption); - const randomName1 = await Random.string(7, "qwertzuiop"); + const randomName1 = await Random.string(7, RandomCharacterRange.Alphabet); await executeFullCreateAndShareRepositoryAttributeFlow(services1, services2, { content: { value: { @@ -1022,7 +1022,7 @@ describe("RelationshipDecomposition", () => { } }); - const randomName2 = await Random.string(7, "asdfghjkl"); + const randomName2 = await Random.string(7, RandomCharacterRange.Alphabet); await executeFullCreateAndShareRepositoryAttributeFlow(services2, services1, { content: { value: { From 73e9a6af869c50d79fd9d1977cd9e80d2ff005b2 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Mon, 3 Feb 2025 14:23:18 +0100 Subject: [PATCH 32/34] refactor: remove unneeded code --- packages/content/src/attributes/types/AbstractString.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/content/src/attributes/types/AbstractString.ts b/packages/content/src/attributes/types/AbstractString.ts index d3cc057a3..de9687750 100644 --- a/packages/content/src/attributes/types/AbstractString.ts +++ b/packages/content/src/attributes/types/AbstractString.ts @@ -39,9 +39,3 @@ export class AbstractString extends AbstractAttributeValue implements IAbstractS }); } } - -export const enum DIN91379CharacterSetRegex { - DatatypeA = "^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$", - DatatypeB = "^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$", - DatatypeC = "^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$" -} From b33c8f4f53bb9d9e138a38116ec3e531f8707f67 Mon Sep 17 00:00:00 2001 From: mkuhn Date: Mon, 3 Feb 2025 14:23:59 +0100 Subject: [PATCH 33/34] refactor: import regex in test --- packages/content/test/attributes/CharacterSets.test.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/content/test/attributes/CharacterSets.test.ts b/packages/content/test/attributes/CharacterSets.test.ts index 8a9b9dbb2..2863f9f58 100644 --- a/packages/content/test/attributes/CharacterSets.test.ts +++ b/packages/content/test/attributes/CharacterSets.test.ts @@ -13,12 +13,9 @@ import { } from "../../src"; import { characterSets } from "../../src/attributes/constants/CharacterSets"; -const errorMessageDatatypeA = - "Value does not match regular expression /^( |'|[,-.]|[A-Z]|[`-z]|~|¨|´|·|[À-Ö]|[Ø-ö]|[ø-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; -const errorMessageDatatypeB = - "Value does not match regular expression /^([ -~]|[¡-£]|¥|[§-¬]|[®-·]|[¹-»]|[¿-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; -const errorMessageDatatypeC = - "Value does not match regular expression /^([\\u0009-\\u000A]|\\u000D|[ -~]|[ -¬]|[®-ž]|[Ƈ-ƈ]|Ə|Ɨ|[Ơ-ơ]|[Ư-ư]|Ʒ|[Ǎ-ǜ]|[Ǟ-ǟ]|[Ǣ-ǰ]|[Ǵ-ǵ]|[Ǹ-ǿ]|[Ȓ-ȓ]|[Ș-ț]|[Ȟ-ȟ]|[ȧ-ȳ]|ə|ɨ|ʒ|[ʹ-ʺ]|[ʾ-ʿ]|ˈ|ˌ|[Ḃ-ḃ]|[Ḇ-ḇ]|[Ḋ-ḑ]|ḗ|[Ḝ-ḫ]|[ḯ-ḷ]|[Ḻ-ḻ]|[Ṁ-ṉ]|[Ṓ-ṛ]|[Ṟ-ṣ]|[Ṫ-ṯ]|[Ẁ-ẇ]|[Ẍ-ẗ]|ẞ|[Ạ-ỹ]|’|‡|€|A̋|C(̀|̄|̆|̈|̕|̣|̦|̨̆)|D̂|F(̀|̄)|G̀|H(̄|̦|̱)|J(́|̌)|K(̀|̂|̄|̇|̕|̛|̦|͟H|͟h)|L(̂|̥|̥̄|̦)|M(̀|̂|̆|̐)|N(̂|̄|̆|̦)|P(̀|̄|̕|̣)|R(̆|̥|̥̄)|S(̀|̄|̛̄|̱)|T(̀|̄|̈|̕|̛)|U̇|Z(̀|̄|̆|̈|̧)|a̋|c(̀|̄|̆|̈|̕|̣|̦|̨̆)|d̂|f(̀|̄)|g̀|h(̄|̦)|j́|k(̀|̂|̄|̇|̕|̛|̦|͟h)|l(̂|̥|̥̄|̦)|m(̀|̂|̆|̐)|n(̂|̄|̆|̦)|p(̀|̄|̕|̣)|r(̆|̥|̥̄)|s(̀|̄|̛̄|̱)|t(̀|̄|̕|̛)|u̇|z(̀|̄|̆|̈|̧)|Ç̆|Û̄|ç̆|û̄|ÿ́|Č(̕|̣)|č(̕|̣)|ē̍|Ī́|ī́|ō̍|Ž(̦|̧)|ž(̦|̧)|Ḳ̄|ḳ̄|Ṣ̄|ṣ̄|Ṭ̄|ṭ̄|Ạ̈|ạ̈|Ọ̈|ọ̈|Ụ(̄|̈)|ụ(̄|̈))*$/"; +const errorMessageDatatypeA = `Value does not match regular expression ${characterSets.din91379DatatypeA.toString()}`; +const errorMessageDatatypeB = `Value does not match regular expression ${characterSets.din91379DatatypeB.toString()}`; +const errorMessageDatatypeC = `Value does not match regular expression ${characterSets.din91379DatatypeC.toString()}`; test("Consent is considered as valid", () => { const consent = Consent.from({ consent: "z-validValue\u000D¾£()," }); From f46b9805c248a7499b506bea00c7f705e10daa2a Mon Sep 17 00:00:00 2001 From: mkuhn Date: Tue, 4 Feb 2025 13:17:27 +0100 Subject: [PATCH 34/34] feat: don't validate ProprietaryXML/JSON --- .../types/proprietary/ProprietaryJSON.ts | 7 ------- .../attributes/types/strings/AbstractXML.ts | 6 ++---- .../test/attributes/CharacterSets.test.ts | 19 +++++++------------ 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts index 09c26da36..58bf2c97a 100644 --- a/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts +++ b/packages/content/src/attributes/types/proprietary/ProprietaryJSON.ts @@ -57,13 +57,6 @@ function validateValue(value: any) { if (string.length > 4096) { return "stringified value must not be longer than 4096 characters"; } - - // JSON.stringify replaces some characters with their code points (e. g. "\\u0012" instead of the character), hence transforming it back for the regex validation - const stringContainingStringifiedJSON = `"${string.replace(/(? { - const attribute = Serializable.fromUnknown({ "@type": type, value: "z-validValue\u000D¾£(),", title: "aTitle" }) as any; +test("value of ProprietaryString is considered as valid", () => { + const attribute = ProprietaryString.from({ value: "z-validValue\u000D¾£(),", title: "aTitle" }) as any; expect(attribute.value).toBe("z-validValue\u000D¾£(),"); - expect(attribute.valueHints.pattern).toBe(valueHintsPattern); + expect(attribute.valueHints.pattern).toBe(characterSets.din91379DatatypeC.toString().slice(1, -1).replaceAll("/", "\\/")); }); -test.each(relationshipAttributeValueTestParameters)("value of $type is considered as invalid", ({ type, propertyInErrorMessage }) => { +test("value of ProprietaryString is considered as invalid", () => { const invalidCall = () => { - Serializable.fromUnknown({ "@type": type, value: "z-invalidValue\u0012", title: "aTitle" }); + ProprietaryString.from({ value: "z-invalidValue\u0012", title: "aTitle" }); }; - expect(invalidCall).toThrow(new ParsingError(type, propertyInErrorMessage, errorMessageDatatypeC)); + expect(invalidCall).toThrow(new ParsingError("ProprietaryString", "value", errorMessageDatatypeC)); }); const proprietaryAttributeTestParameters = [