diff --git a/packages/content/src/attributes/AttributeValueTypes.ts b/packages/content/src/attributes/AttributeValueTypes.ts index fcd4dcaa6..2fb28709b 100644 --- a/packages/content/src/attributes/AttributeValueTypes.ts +++ b/packages/content/src/attributes/AttributeValueTypes.ts @@ -69,6 +69,7 @@ import { IPseudonym, ISchematizedXML, ISex, + ISocialInsuranceNumber, IStreetAddress, ISurname, IWebsite, @@ -116,6 +117,8 @@ import { SchematizedXMLJSON, Sex, SexJSON, + SocialInsuranceNumber, + SocialInsuranceNumberJSON, StreetAddress, StreetAddressJSON, Surname, @@ -153,6 +156,7 @@ export namespace AttributeValues { | PostOfficeBoxAddressJSON | PseudonymJSON | SexJSON + | SocialInsuranceNumberJSON | StreetAddressJSON | SurnameJSON | WebsiteJSON; @@ -181,6 +185,7 @@ export namespace AttributeValues { | IPostOfficeBoxAddress | IPseudonym | ISex + | ISocialInsuranceNumber | IStreetAddress | ISurname | IWebsite; @@ -209,6 +214,7 @@ export namespace AttributeValues { | PostOfficeBoxAddress | Pseudonym | Sex + | SocialInsuranceNumber | StreetAddress | Surname | Website; @@ -237,6 +243,7 @@ export namespace AttributeValues { PostOfficeBoxAddress, Pseudonym, Sex, + SocialInsuranceNumber, StreetAddress, Surname, Website @@ -266,6 +273,7 @@ export namespace AttributeValues { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" diff --git a/packages/content/src/attributes/types/identity/SocialInsuranceNumber.ts b/packages/content/src/attributes/types/identity/SocialInsuranceNumber.ts new file mode 100644 index 000000000..0762a8586 --- /dev/null +++ b/packages/content/src/attributes/types/identity/SocialInsuranceNumber.ts @@ -0,0 +1,40 @@ +import { serialize, type, validate } from "@js-soft/ts-serval"; +import { ValueHints } from "../../hints"; +import { AbstractString, AbstractStringJSON, IAbstractString } from "../AbstractString"; + +const MIN_SOCIAL_INSURANCE_NUMBER_LENGTH = 4; +const MAX_SOCIAL_INSURANCE_NUMBER_LENGTH = 32; + +export interface SocialInsuranceNumberJSON extends AbstractStringJSON { + "@type": "SocialInsuranceNumber"; +} + +export interface ISocialInsuranceNumber extends IAbstractString {} + +@type("SocialInsuranceNumber") +export class SocialInsuranceNumber extends AbstractString implements ISocialInsuranceNumber { + private static readonly regExp = new RegExp(/^[A-Z0-9]+$/); + @serialize() + @validate({ + min: MIN_SOCIAL_INSURANCE_NUMBER_LENGTH, + max: MAX_SOCIAL_INSURANCE_NUMBER_LENGTH, + regExp: SocialInsuranceNumber.regExp + }) + public override value: string; + + public static from(value: ISocialInsuranceNumber | Omit | string): SocialInsuranceNumber { + return this.fromAny(value); + } + + public static override get valueHints(): ValueHints { + return super.valueHints.copyWith({ + min: MIN_SOCIAL_INSURANCE_NUMBER_LENGTH, + max: MAX_SOCIAL_INSURANCE_NUMBER_LENGTH, + pattern: SocialInsuranceNumber.regExp.toString().slice(1, -1).replaceAll("/", "\\/") + }); + } + + public override toJSON(verbose?: boolean | undefined, serializeAsString?: boolean | undefined): SocialInsuranceNumberJSON { + return super.toJSON(verbose, serializeAsString) as SocialInsuranceNumberJSON; + } +} diff --git a/packages/content/src/attributes/types/identity/index.ts b/packages/content/src/attributes/types/identity/index.ts index 0aaf66eaa..94c87d578 100644 --- a/packages/content/src/attributes/types/identity/index.ts +++ b/packages/content/src/attributes/types/identity/index.ts @@ -1,3 +1,4 @@ export * from "./DisplayName"; export * from "./IdentityFileReference"; export * from "./SchematizedXML"; +export * from "./SocialInsuranceNumber"; diff --git a/packages/content/test/attributes/EMailAddress.test.ts b/packages/content/test/attributes/EMailAddress.test.ts index 465db38aa..4f822c590 100644 --- a/packages/content/test/attributes/EMailAddress.test.ts +++ b/packages/content/test/attributes/EMailAddress.test.ts @@ -28,7 +28,7 @@ describe("Test invalid EMailAddresses", () => { ); }); - test("returns an error when trying to create an Attribute Value Type EMailAddress wich is empty", function () { + test("returns an error when trying to create an Attribute Value Type EMailAddress which is empty", function () { const invalidEMailAddressCall = () => { EMailAddress.from({ value: "" diff --git a/packages/content/test/attributes/SocialInsuranceNumber.test.ts b/packages/content/test/attributes/SocialInsuranceNumber.test.ts new file mode 100644 index 000000000..39876ccdf --- /dev/null +++ b/packages/content/test/attributes/SocialInsuranceNumber.test.ts @@ -0,0 +1,42 @@ +import { ParsingError } from "@js-soft/ts-serval"; +import { SocialInsuranceNumber } from "../../src"; + +describe("Test valid SocialInsuranceNumbers", () => { + const validSocialInsuranceNumbers = ["123456789", "VALIDNUMBER", "VALIDNUMBER123456789"]; + + test.each(validSocialInsuranceNumbers)("SocialInsuranceNumber %s is recognized as valid", (number) => { + const validSocialInsuranceNumber = SocialInsuranceNumber.from({ value: number }); + expect(validSocialInsuranceNumber.value.toString()).toBe(number); + }); +}); + +describe("Test invalid SocialInsuranceNumbers", () => { + const invalidSocialInsuranceNumbers = ["lowercaseinvalidnumber", "INVALIDNUMBER_WITHSPECIALCHAR$"]; + + test.each(invalidSocialInsuranceNumbers)("SocialInsuranceNumber %s is recognized as invalid", (number) => { + const invalidSocialInsuranceNumberCall = () => { + SocialInsuranceNumber.from({ + value: number + }); + }; + expect(invalidSocialInsuranceNumberCall).toThrow(new ParsingError("SocialInsuranceNumber", "value", "Value does not match regular expression /^[A-Z0-9]+$/")); + }); + + test("returns an error when trying to create an Attribute Value Type SocialInsuranceNumber which is empty", function () { + const invalidSocialInsuranceNumberCall = () => { + SocialInsuranceNumber.from({ + value: "" + }); + }; + expect(invalidSocialInsuranceNumberCall).toThrow(new ParsingError("SocialInsuranceNumber", "value", "Value is shorter than 4 characters")); + }); + + test("returns an error when trying to create an Attribute Value Type SocialInsuranceNumber which is too long", function () { + const invalidSocialInsuranceNumberCall = () => { + SocialInsuranceNumber.from({ + value: "INVALIDNUMBERWITHTOOMANYCHARACTERS" + }); + }; + expect(invalidSocialInsuranceNumberCall).toThrow(new ParsingError("SocialInsuranceNumber", "value", "Value is longer than 32 characters")); + }); +}); diff --git a/packages/content/test/attributes/Website.test.ts b/packages/content/test/attributes/Website.test.ts index a629b836e..d4643226b 100644 --- a/packages/content/test/attributes/Website.test.ts +++ b/packages/content/test/attributes/Website.test.ts @@ -35,7 +35,7 @@ describe("Test invalid URLs", () => { ); }); - test("returns an error when trying to create an Attribute Value Type Website wich is empty", function () { + test("returns an error when trying to create an Attribute Value Type Website which is empty", function () { const invalidWebsiteCall = () => { Website.from({ value: "" diff --git a/packages/runtime/src/useCases/common/Schemas.ts b/packages/runtime/src/useCases/common/Schemas.ts index 85ca8ba58..03a3ed6a3 100644 --- a/packages/runtime/src/useCases/common/Schemas.ts +++ b/packages/runtime/src/useCases/common/Schemas.ts @@ -1170,6 +1170,9 @@ export const CanCreateOutgoingRequestRequest: any = { { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -1783,6 +1786,29 @@ export const CanCreateOutgoingRequestRequest: any = { ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -2112,6 +2138,7 @@ export const CanCreateOutgoingRequestRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -3209,6 +3236,9 @@ export const CompleteOutgoingRequestRequest: any = { { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -3822,6 +3852,29 @@ export const CompleteOutgoingRequestRequest: any = { ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -5234,6 +5287,9 @@ export const CreateAndCompleteOutgoingRequestFromRelationshipTemplateResponseReq { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -5847,6 +5903,29 @@ export const CreateAndCompleteOutgoingRequestFromRelationshipTemplateResponseReq ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -7876,6 +7955,9 @@ export const CreateOutgoingRequestRequest: any = { { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -8489,6 +8571,29 @@ export const CreateOutgoingRequestRequest: any = { ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -8818,6 +8923,7 @@ export const CreateOutgoingRequestRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -10921,6 +11027,9 @@ export const ReceivedIncomingRequestRequest: any = { { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -11534,6 +11643,29 @@ export const ReceivedIncomingRequestRequest: any = { ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -11863,6 +11995,7 @@ export const ReceivedIncomingRequestRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -13385,6 +13518,7 @@ export const ExecuteIdentityAttributeQueryRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -13491,6 +13625,7 @@ export const ExecuteIQLQueryRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -14961,6 +15096,9 @@ export const SucceedOwnIdentityAttributeRequest: any = { { "$ref": "#/definitions/SexJSON" }, + { + "$ref": "#/definitions/SocialInsuranceNumberJSON" + }, { "$ref": "#/definitions/StreetAddressJSON" }, @@ -15574,6 +15712,29 @@ export const SucceedOwnIdentityAttributeRequest: any = { ], "additionalProperties": false }, + "SocialInsuranceNumberJSON": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + }, "StreetAddressJSON": { "type": "object", "properties": { @@ -16449,6 +16610,7 @@ export const ValidateIQLQueryRequest: any = { "PostOfficeBoxAddress", "Pseudonym", "Sex", + "SocialInsuranceNumber", "StreetAddress", "Surname", "Website" @@ -20573,6 +20735,36 @@ export const SchematizedXML: any = { } } +export const SocialInsuranceNumber: any = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/SocialInsuranceNumber", + "definitions": { + "SocialInsuranceNumber": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "const": "SocialInsuranceNumber" + }, + "@context": { + "type": "string" + }, + "@version": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "@type", + "value" + ], + "additionalProperties": false + } + } +} + export const BirthName: any = { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/BirthName",