@frankieone/one-sdk 0.1.0-poc.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +25 -0
  2. package/dist/index.esm.js +2 -0
  3. package/dist/index.esm.js.map +1 -0
  4. package/dist/index.umd.js +2 -0
  5. package/dist/index.umd.js.map +1 -0
  6. package/dist/types/api/ExternalIdvClient.d.ts +19 -0
  7. package/dist/types/api/FrankieApiClient.d.ts +54 -0
  8. package/dist/types/api/index.d.ts +1 -0
  9. package/dist/types/facades/POC/reactComponent.d.ts +644 -0
  10. package/dist/types/facades/POC/routing.d.ts +3 -0
  11. package/dist/types/facades/POC/viewWrapper.d.ts +4 -0
  12. package/dist/types/facades/POC/webEntry.d.ts +6 -0
  13. package/dist/types/index.d.ts +11 -0
  14. package/dist/types/models/Address.d.ts +67 -0
  15. package/dist/types/models/Admin.d.ts +1295 -0
  16. package/dist/types/models/Applicant.d.ts +115 -0
  17. package/dist/types/models/CheckSummary.d.ts +164 -0
  18. package/dist/types/models/ConfigurationReader.d.ts +7 -0
  19. package/dist/types/models/Core.d.ts +2725 -0
  20. package/dist/types/models/Document.d.ts +112 -0
  21. package/dist/types/models/General.d.ts +196 -0
  22. package/dist/types/models/Organisation.d.ts +36 -0
  23. package/dist/types/models/Profile.d.ts +27 -0
  24. package/dist/types/models/SupportingDocument.d.ts +95 -0
  25. package/dist/types/models/User.d.ts +27 -0
  26. package/dist/types/models/index.d.ts +14 -0
  27. package/dist/types/models/transformers/apiState.d.ts +23 -0
  28. package/dist/types/models/utils/address.d.ts +2 -0
  29. package/dist/types/models/utils/base64.d.ts +11 -0
  30. package/dist/types/models/utils/buildCycleUtils.d.ts +1 -0
  31. package/dist/types/models/utils/constants.d.ts +75 -0
  32. package/dist/types/models/utils/date.d.ts +5 -0
  33. package/dist/types/models/utils/getCountryDetails.d.ts +9 -0
  34. package/dist/types/models/utils/getDocumentDetails.d.ts +8 -0
  35. package/dist/types/models/utils/helper.d.ts +4 -0
  36. package/dist/types/models/utils/index.d.ts +11 -0
  37. package/dist/types/models/utils/isEmpty.d.ts +5 -0
  38. package/dist/types/models/utils/sanitiser.d.ts +8 -0
  39. package/dist/types/modules/router/ReactDictionaryRouter.d.ts +15 -0
  40. package/dist/types/modules/router/common/routing.d.ts +25 -0
  41. package/dist/types/modules/store/ReactInMemoryStore.d.ts +24 -0
  42. package/dist/types/uiComponents/reactWeb.d.ts +8 -0
  43. package/dist/types/utils/base64.d.ts +11 -0
  44. package/dist/types/utils/env2Url.d.ts +1 -0
  45. package/package.json +64 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/models/ConfigurationReader.ts","../src/models/utils/sanitiser.ts","../src/models/Address.ts","../src/models/utils/address.ts","../src/models/utils/getCountryDetails.ts","../src/models/Profile.ts","../src/models/Applicant.ts","../src/models/Document.ts","../src/models/transformers/apiState.ts","../src/models/SupportingDocument.ts","../src/models/CheckSummary.ts","../src/models/General.ts","../src/models/Organisation.ts","../src/api/ExternalIdvClient.ts","../src/api/FrankieApiClient.ts","../src/utils/base64.ts","../src/modules/router/common/routing.ts","../src/modules/router/ReactDictionaryRouter.ts","../src/modules/store/ReactInMemoryStore.ts","../src/uiComponents/reactWeb.tsx","../src/facades/POC/viewWrapper.ts","../src/utils/env2Url.ts","../src/facades/POC/routing.ts","../src/facades/POC/reactComponent.ts","../src/index.ts","../src/facades/POC/webEntry.ts"],"sourcesContent":["import dot from \"dot-object\";\nimport {\n ConfigurationReader as IConfigurationReader,\n ExpandDot,\n Path,\n StrObject,\n} from \"../interfaces\";\n\nexport class ConfigurationReader<Config extends StrObject> implements IConfigurationReader<Config> {\n private parsedConfiguration: ExpandDot<Config>;\n constructor(original: Config) {\n this.parsedConfiguration = dot.object(original) as ExpandDot<Config>;\n }\n // fix type inference here.\n read<Value = unknown>(path: Path<Config>): Value | undefined;\n read<Value = unknown>(\n path: Path<Config>,\n fallback: Exclude<Value, undefined>\n ): Exclude<Value, undefined>;\n read<Value = unknown>(\n path: Path<Config>,\n fallback?: Exclude<Value, undefined>\n ): Exclude<Value, undefined> {\n return dot.pick(path as any, this.parsedConfiguration, false) ?? fallback;\n }\n}\n","import sanitizeHtml from \"sanitize-html\";\nimport { parse as htmlParser } from \"node-html-parser\";\n\nexport declare type Sanitiser = typeof sanitizeHtml;\nexport declare type SanitiserOptions = Parameters<Sanitiser>[1];\nexport const mkHtmlSanitiser = Object.assign(\n function (options: SanitiserOptions = {}): (dirty: string) => string {\n const defaultOptions: SanitiserOptions = {\n disallowedTagsMode: \"discard\",\n ...options,\n };\n return (dirty: string) => sanitizeHtml(dirty, defaultOptions);\n },\n {\n defaults: sanitizeHtml.defaults,\n }\n);\n\nexport function stripOutScriptTagFromString(content: string) {\n let stripped: string = content;\n stripped = stripped.replace(/<script[^>]*>/gi, \"<!-- <removed script>\");\n stripped = stripped.replace(/<\\/script>/gi, \"</removed script> -->\");\n return stripped;\n // const html = htmlParser(content, { comment: true, blockTextElements: { script: false } });\n // return html.toString();\n}\nexport function mkAnchorsTargetBlank(content: string) {\n const html = htmlParser(content, { comment: true });\n const as = html.querySelectorAll(\"a\");\n as.forEach((a) => a.setAttribute(\"target\", \"_blank\"));\n return html.toString();\n}\n","import { Core } from \"./Core\";\nimport { isEmptyAddress, getAustralianStateDetails, getCountryDetails } from \"./utils\";\n\nexport interface IAddressPayload {\n buildingName: string | null;\n postalCode: string | null;\n state: string | null;\n streetName: string | null;\n streetNumber: string | null;\n streetType: string | null;\n suburb: string | null;\n town: string | null;\n unitNumber: string | null;\n addressType: Core[\"AddressObject\"][\"addressType\"] | null;\n country: string | null;\n addressId: string | null;\n longForm: string | null;\n data?: { [k: string]: any };\n isAddedByCustomer?: boolean | null;\n}\n\nexport class Address implements IAddressPayload {\n buildingName: string | null = null;\n postalCode: string | null = null;\n state: string | null = null;\n streetNumber: string | null = null;\n streetType: string | null = null;\n suburb: string | null = null;\n town: string | null = null;\n unitNumber: string | null = null;\n addressType: Core[\"AddressObject\"][\"addressType\"] | null = null;\n _streetName: string | null = null;\n country: string | null = null;\n addressId: string | null = null;\n data: { [k: string]: any } = {};\n isAddedByCustomer: boolean | null = null;\n\n constructor();\n constructor(a: IAddressConstructor);\n constructor(a?: IAddressConstructor) {\n if (!a) return;\n this.buildingName = a.buildingName || null;\n this.postalCode = a.postalCode || null;\n this.state = a.state || null;\n this.streetNumber = a.streetNumber || null;\n this.streetType = a.streetType || null;\n this.suburb = a.suburb || null;\n this.town = a.town || null;\n this.unitNumber = a.unitNumber || null;\n this.addressType = a.addressType || null;\n this._streetName = a.streetName || null;\n this.country = a.country || null;\n this.addressId = a?.addressId?.toLowerCase() || null;\n this.isAddedByCustomer = a?.isAddedByCustomer || null;\n }\n\n set streetName(name: string | null) {\n if (name !== null) this.data.longForm = null;\n this._streetName = name;\n }\n\n get streetName(): string | null {\n return this._streetName ?? null;\n }\n\n get isIncomplete(): boolean {\n return isEmptyAddress(this);\n }\n\n hasExplicitLongForm(): boolean {\n return Boolean(this.data.longForm);\n }\n\n set longForm(value: string | null) {\n // save longForm to data\n this.data.longForm = value;\n }\n\n get longForm(): string | null {\n if (this.data.longForm) return this.data.longForm ?? null;\n if (this.isIncomplete) return null;\n const {\n buildingName,\n unitNumber,\n streetNumber,\n streetName,\n streetType,\n suburb,\n state,\n postalCode,\n country,\n town,\n } = this;\n\n const stateName = (() => {\n if (!state) return null;\n if (country === \"AUS\") return getAustralianStateDetails(state)?.label ?? state;\n return state;\n })();\n const countryName = (country && getCountryDetails(country)?.label) || null;\n const numbers = [unitNumber, streetNumber].filter(Boolean).join(\"/\");\n const unitLine = [buildingName, numbers].filter(Boolean).join(\", \");\n const streetLine = [unitLine, streetName, streetType].filter(Boolean).join(\" \");\n const stateLine = [town, stateName, postalCode].filter(Boolean).join(\" \");\n\n return [streetLine, suburb, stateLine, countryName].filter(Boolean).join(\", \");\n }\n clone(): Address {\n const payload = this.toJSON();\n const instance = Address.fromJSON(payload);\n return instance;\n }\n toJSON(): IAddressPayload {\n let addressFields = Object.keys(new Address());\n addressFields = addressFields.filter(\n (i) => ![\"country\", \"addressType\", \"addressId\"].includes(i)\n );\n\n // this might not be relevant anymore\n const isAddressHasCountryOnly = addressFields.every((field) => !this[field as keyof Address]);\n //if address only has country, other field is empty, don't send longForm\n if (isAddressHasCountryOnly) return { ...this };\n // until here\n\n const { _streetName, ...thisRest } = this;\n return {\n ...thisRest,\n streetName: this.streetName,\n longForm: this.longForm,\n };\n }\n static fromJSON(payload: IAddressPayload): Address {\n const newAddress = new Address();\n newAddress.buildingName = payload.buildingName;\n newAddress.unitNumber = payload.unitNumber;\n newAddress.streetNumber = payload.streetNumber;\n newAddress.streetName = payload.streetName;\n newAddress.streetType = payload.streetType;\n newAddress.suburb = payload.suburb;\n newAddress.state = payload.state;\n newAddress.postalCode = payload.postalCode;\n newAddress.country = payload.country;\n newAddress.town = payload.town;\n newAddress.addressId = payload.addressId;\n newAddress.addressType = payload.addressType;\n newAddress.data = payload.data ?? {};\n newAddress.isAddedByCustomer = payload.isAddedByCustomer ?? null;\n return newAddress;\n }\n static default(): Address {\n const newAddress = new Address();\n newAddress.buildingName = null;\n newAddress.unitNumber = null;\n newAddress.streetNumber = null;\n newAddress.streetName = null;\n newAddress.streetType = null;\n newAddress.suburb = null;\n newAddress.state = null;\n newAddress.postalCode = null;\n newAddress.country = null;\n newAddress.town = null;\n newAddress.addressId = null;\n newAddress.addressType = null;\n newAddress.isAddedByCustomer = null;\n return newAddress;\n }\n}\n\nexport function addressTypeSorter(a: Address[\"addressType\"], b: Address[\"addressType\"]) {\n const getPoints = (t: Address[\"addressType\"]) => {\n const type = t?.toLowerCase() || null;\n if (type === \"residential1\") return 0;\n if (type === \"residential\") return 1;\n const match = type?.match(/residential([0-9]+)/);\n if (match) return parseInt(match[1]);\n return Infinity;\n };\n return getPoints(a) - getPoints(b);\n}\n\ninterface IAddressConstructor {\n buildingName: string | null;\n postalCode: string | null;\n state: string | null;\n streetName: string | null;\n streetNumber: string | null;\n streetType: string | null;\n suburb: string | null;\n town: string | null;\n unitNumber: string | null;\n addressType: Core[\"AddressObject\"][\"addressType\"] | null;\n country: string | null;\n addressId: string | null;\n isAddedByCustomer: boolean;\n}\n","import { Address } from \"../Address\";\n\nexport const isEmptyAddress = (address: Address): boolean => {\n const { country, suburb, town, streetName } = address;\n const isEmpty = (requireList) => requireList.some((field) => !address[field]);\n\n switch (country) {\n case \"AUS\": {\n const suburbOrTown = Boolean(suburb || town);\n return (\n !suburbOrTown ||\n ![\"streetName\", \"state\", \"country\", \"postalCode\"].every((f) => Boolean(address[f]))\n );\n }\n case \"NZL\":\n return isEmpty([\"streetName\", \"postalCode\"]);\n case \"THA\":\n return isEmpty([\"streetName\", \"town\"]);\n case \"IDN\":\n return isEmpty([\"streetName\", \"town\"]);\n case \"SGP\":\n return isEmpty([\"streetName\", \"postalCode\", \"streetNumber\"]);\n default:\n return !((suburb || town || streetName) && country);\n }\n};\n","import allCountries from \"../data/country.json\";\nimport allAustralianStates from \"../data/aus_states.json\";\n\ntype TCountryObject = { label: string };\nexport default function getCountryDetails(code3: string): TCountryObject {\n const country = allCountries.find((c) => c.alpha3Code === code3);\n const countryObject = { label: country?.name ?? code3 };\n return countryObject;\n}\ntype TStateObject = { label: string };\nexport function getAustralianStateDetails(code3: string): TStateObject | null {\n const state = allAustralianStates.find((s) => s.alpha3Code === code3);\n const stateObject = { label: state?.name ?? code3 };\n return stateObject;\n}\n","import moment from \"moment\";\n\nexport interface IProfilePayload {\n profileType: string | null;\n kycMethod: string;\n countryAlpha3: string | null;\n dob: string | null;\n checkTypes: string[];\n}\n\nexport class Profile {\n private kycMethod: string;\n private country = \"AUS\";\n private profileType: string;\n private config: any;\n private dob: string | null = null;\n private _hadcodedCheckTypes: string[] | null = null;\n\n constructor(profileType: string | null, kycMethod: string);\n constructor(\n profileType: string | null,\n kycMethod: string,\n countryAlpha3: string | null,\n dob: string | null,\n configOrCheckType: { checkTypes: string[] } | any\n );\n constructor(\n profileType: string | null,\n kycMethod = \"electronic\",\n countryAlpha3?: string | null,\n dob?: string | null,\n configOrCheckType?: { checkTypes: string[] } | any\n ) {\n this.kycMethod = kycMethod;\n this.profileType = this.initialiseConfigOrCheckType(profileType, configOrCheckType);\n if (countryAlpha3) this.country = countryAlpha3?.toLowerCase();\n if (dob) this.dob = dob;\n }\n initialiseConfigOrCheckType(profileType: string | null, configOrCheckType: any): string {\n let theProfileType = profileType?.toLowerCase();\n if (!configOrCheckType) {\n this._hadcodedCheckTypes = null;\n } else if (Array.isArray(configOrCheckType?.checkTypes)) {\n this._hadcodedCheckTypes = configOrCheckType.checkTypes;\n } else {\n this.config = configOrCheckType;\n const defaultProfileType = this.config.get(\"default_profile\").value() as string;\n theProfileType = theProfileType ?? defaultProfileType?.toLowerCase();\n }\n return theProfileType ?? \"none\";\n }\n setConfiguration(config: any) {\n this.config = config;\n }\n getConfiguration(): string[] {\n const config = this.config;\n // if there's no configuration for current country, fallback to default.\n // current country may already be default as well\n const isUnder18 = this.dob && moment().diff(this.dob!, \"year\") < 18;\n // 1 check first for specific country and then for default\n // a first check if there's configuration for profileType\n // b if not, decide based on age\n const typeKey = this.profileType;\n const ageKey = isUnder18 ? \"under18\" : \"above18\";\n\n const mkPossibilitiesForCountry = (country: string) => [\n config.get(country).get(typeKey).value() as string,\n config.get(country).get(ageKey).value() as string,\n ];\n\n const countryAndFallback = [this.country, \"default\"];\n const allFourPossibilities = countryAndFallback.map(mkPossibilitiesForCountry).flat();\n\n // out of four possibilities (country type, country age, default type, default age), find the first configuration that exists\n const foundTypesAsString = allFourPossibilities.find(Boolean);\n // to prevent breaking when configuration is not present\n const foundTypesAsArray = foundTypesAsString?.split?.(\",\") || [];\n return foundTypesAsArray;\n }\n getProfileType(): string {\n return this.profileType;\n }\n get checkTypes(): string[] {\n if (!this.config && !this._hadcodedCheckTypes) return [];\n if (!this.config && !!this._hadcodedCheckTypes) return this._hadcodedCheckTypes;\n // if is manual kyc, replace configured kyc check types with 'manual'\n const isManualKyc = this.kycMethod === \"manual\";\n const kycTypes = [\"id\", \"id2\", \"one_plus\", \"two_plus\"];\n\n let finalTypes: string[] = this.getConfiguration();\n //If finalTypes is profile, we just need to return profile, core will know what need to be run.\n if (finalTypes.includes(\"profile\")) return [\"profile\"];\n if (isManualKyc) {\n const isNotKyc = (type: string) => !kycTypes.includes(type);\n const nonKycConfiguration = finalTypes.filter(isNotKyc);\n finalTypes = [\"manual\", ...nonKycConfiguration];\n }\n\n return finalTypes;\n }\n\n toJSON(): IProfilePayload {\n return {\n profileType: this.profileType,\n kycMethod: this.kycMethod,\n countryAlpha3: this.country,\n dob: this.dob,\n checkTypes: this.checkTypes, // because we can't guarantee configuration serialization, we just output a hardcoded list of chectypes\n };\n }\n\n static fromJSON(payload: IProfilePayload): Profile {\n const { profileType, kycMethod, countryAlpha3, dob, checkTypes } = payload;\n\n return new Profile(profileType, kycMethod, countryAlpha3, dob, {\n checkTypes,\n });\n }\n static default() {\n return new Profile(null, \"electronic\");\n }\n}\n","import { Address, IAddressPayload, addressTypeSorter } from \"./Address\";\nimport { Profile, IProfilePayload } from \"./Profile\";\nimport { Core } from \"./Core\";\nimport { Nullable, ICloneable, ExtraData } from \"./General\";\n\ntype AddressType = Address[\"addressType\"];\n\ntype ApplicantExtraData = ExtraData &\n Partial<{\n home_country_givenname: string;\n home_country_familyname: string;\n marital_status: Core[\"enumMaritalStatus\"];\n }>;\n\nexport type TOriginalUboDetails = {\n name: {\n givenName: Nullable<string>;\n middleName: Nullable<string>;\n familyName: Nullable<string>;\n displayName: Nullable<string>;\n };\n dateOfBirth: Nullable<string>;\n addresses: Address[];\n};\n\nexport interface IApplicantPayload {\n entityId: Nullable<string>;\n customerReference: Nullable<string>;\n name: {\n givenName: Nullable<string>;\n middleName: Nullable<string>;\n familyName: Nullable<string>;\n displayName: Nullable<string>;\n };\n extraData?: ApplicantExtraData;\n dateOfBirth: Nullable<string>;\n gender: Nullable<Core[\"enumGender\"]>;\n phoneNumber: {\n documentId: Nullable<string>;\n idNumber: Nullable<string>;\n };\n addresses: IAddressPayload[];\n email: {\n documentId: Nullable<string>;\n idNumber: Nullable<string>;\n };\n profile: IProfilePayload | null;\n assignee: Nullable<string>;\n consents: string[];\n blocklistAttributes: Nullable<\"ATTR\" | \"FULL\">;\n originalUboDetails?: Nullable<TOriginalUboDetails>;\n}\n\ninterface IApplicantConstructor {\n entityId: Nullable<string>;\n customerReference?: Nullable<string>;\n name?: {\n givenName?: Nullable<string>;\n middleName?: Nullable<string>;\n familyName?: Nullable<string>;\n displayName?: Nullable<string>;\n };\n extraData?: ApplicantExtraData;\n dateOfBirth?: Nullable<string>;\n gender?: Nullable<Core[\"enumGender\"]>;\n\n phoneNumber?: {\n documentId?: Nullable<string>;\n idNumber?: Nullable<string>;\n };\n addresses?: Address[];\n email?: {\n documentId?: Nullable<string>;\n idNumber?: Nullable<string>;\n };\n profile?: Nullable<Profile>;\n assignee?: Nullable<string>;\n consents?: string[];\n blocklistAttributes?: Nullable<\"ATTR\" | \"FULL\">;\n originalUboDetails?: Nullable<TOriginalUboDetails>;\n}\n\nexport type FullNameFields = {\n givenName: Nullable<string>;\n middleName: Nullable<string>;\n familyName: Nullable<string>;\n displayName: Nullable<string>;\n};\n\nexport type SpecialDocument = {\n documentId: Nullable<string>;\n idNumber: Nullable<string>;\n};\n\nexport class Applicant implements ICloneable<Applicant> {\n entityId: Nullable<string> = null;\n customerReference: Nullable<string> = null;\n name: FullNameFields = {\n givenName: null,\n middleName: null,\n familyName: null,\n displayName: null,\n };\n\n dateOfBirth: Nullable<string> = null;\n gender: Nullable<Core[\"enumGender\"]> = null;\n\n extraData: ApplicantExtraData = {};\n phoneNumber: SpecialDocument = {\n documentId: null,\n idNumber: null,\n };\n addresses: Address[] = [];\n email: SpecialDocument = {\n documentId: null,\n idNumber: null,\n };\n profile: Nullable<Profile> = null;\n assignee: Nullable<string> = null;\n consents: string[] = [];\n blocklistAttributes: Nullable<\"ATTR\" | \"FULL\"> = null;\n originalUboDetails: Nullable<TOriginalUboDetails> = null;\n\n constructor();\n\n constructor(a: IApplicantConstructor);\n\n constructor(a?: IApplicantConstructor) {\n if (!a) return;\n this.entityId = a?.entityId?.toLowerCase() || null;\n this.customerReference = a.customerReference || null;\n this.name = {\n givenName: a.name?.givenName || null,\n middleName: a.name?.middleName || null,\n familyName: a.name?.familyName ?? null,\n displayName: a.name?.displayName || null,\n };\n this.dateOfBirth = a.dateOfBirth || null;\n this.gender = a.gender || null;\n this.phoneNumber = {\n documentId: a.phoneNumber?.documentId || null,\n idNumber: a.phoneNumber?.idNumber || null,\n };\n this.email = {\n documentId: a.email?.documentId || null,\n idNumber: a.email?.idNumber || null,\n };\n this.addresses = sortAddressArray(a.addresses || []);\n this.profile = a.profile ?? null;\n this.assignee = a.assignee || null;\n this.consents = a.consents || [];\n this.extraData = a.extraData ?? {};\n this.blocklistAttributes = a.blocklistAttributes ?? null;\n this.originalUboDetails = !a.originalUboDetails\n ? null\n : {\n name: {\n givenName: a.originalUboDetails?.name?.givenName || null,\n middleName: a.originalUboDetails?.name?.middleName || null,\n familyName: a.originalUboDetails?.name?.familyName ?? null,\n displayName: a.originalUboDetails?.name?.displayName || null,\n },\n dateOfBirth: a.originalUboDetails?.dateOfBirth || null,\n addresses: sortAddressArray(a.originalUboDetails.addresses || []),\n };\n }\n\n get currentPreviousAddress() {\n return {\n current: this.addresses[0],\n previous: this.addresses[1],\n };\n }\n\n set fullName(value: string) {\n const split = value.split(\" \");\n const given = split[0];\n const family = split[1];\n const middle = split.slice(1, split.length - 1).join(\" \");\n this.name.givenName = given;\n this.name.middleName = middle;\n this.name.familyName = family;\n }\n\n get displayName() {\n const fullName = [this.name.givenName, this.name.middleName, this.name.familyName]\n .filter((i) => !!i)\n .join(\" \");\n return this.name.displayName || fullName;\n }\n\n get nativeName(): string {\n const givenName = this.extraData.home_country_givenname;\n const familyName = this.extraData.home_country_familyname;\n return [givenName, familyName].filter(Boolean).join(\" \");\n }\n\n getAddress(addressType: AddressType): Address | null {\n const addresses = this.addresses;\n const address = addresses.find((a) => addressTypeFinder(a.addressType, addressType)) ?? null;\n return address;\n }\n\n clone(): Applicant {\n const payload = JSON.parse(JSON.stringify(this));\n const applicant = Applicant.fromJSON(payload);\n return applicant;\n }\n\n toJSON(): IApplicantPayload {\n const { profile, addresses } = this;\n const addressMap = addresses.map((a) => a.toJSON());\n const profilePayload = profile?.toJSON() || null;\n return { ...this, profile: profilePayload, addresses: addressMap };\n }\n\n static fromJSON(payload: IApplicantPayload): Applicant {\n const profile = payload.profile ? Profile.fromJSON(payload.profile) : null;\n const addresses = payload.addresses.map((m) => Address.fromJSON(m));\n const consents = payload.consents ?? [];\n\n return new Applicant({\n ...payload,\n addresses,\n profile,\n consents,\n });\n }\n\n static default(): Applicant {\n return new Applicant({\n addresses: [],\n profile: Profile.default(),\n consents: [],\n entityId: null,\n customerReference: null,\n name: {\n givenName: null,\n middleName: null,\n familyName: null,\n displayName: null,\n },\n\n dateOfBirth: null,\n gender: null,\n phoneNumber: {\n documentId: null,\n idNumber: null,\n },\n email: {\n documentId: null,\n idNumber: null,\n },\n assignee: null,\n blocklistAttributes: null,\n originalUboDetails: null,\n });\n }\n}\n\nfunction sortAddressArray(list: Address[]) {\n return list?.sort((a, b) => addressTypeSorter(a.addressType, b.addressType));\n}\n\nfunction addressTypeFinder(compare: AddressType, needle: AddressType) {\n // if needle is residential1 and compare is any of the different values\n // for residential 1 (residential, residential1 and falsy), return true\n // otherwise, simply compare both\n const residential1Variants = [\"RESIDENTIAL\", \"RESIDENTIAL1\"] as Address[\"addressType\"][];\n const isCompareAVariant = residential1Variants.includes(compare);\n const isCompareFalsy = !compare;\n const isCompareResidential1 = isCompareAVariant || isCompareFalsy;\n if (needle === \"RESIDENTIAL1\" && isCompareResidential1) return true;\n else return compare === needle;\n}\n","import { TValidation, Nullable, ICloneable } from \"./General\";\nimport { Core } from \"./Core\";\nimport moment from \"moment\";\ntype TFileUploadUuid = string;\nexport type TScan = {\n scanId: Nullable<TFileUploadUuid>;\n fileUploadUuid?: Nullable<string>;\n file?: Nullable<string>;\n mimeType?: Nullable<string>;\n side?: Nullable<string>;\n scanCreated?: Nullable<string>;\n scanName?: Nullable<string>;\n};\ntype TDocumentValidation = {\n manual: {\n isValid: Nullable<boolean>;\n };\n electronic: {\n // this comes from onfito\n validationReport: Nullable<Scan>;\n isValid: Nullable<boolean>;\n };\n};\ntype TDocumentVerification = {\n electronic: Nullable<boolean>;\n manual: Nullable<boolean>;\n};\nexport interface IDocumentPayload {\n documentId: Nullable<string>;\n verified: TDocumentVerification;\n dateOfBirth: Nullable<string>;\n idType: Nullable<Core[\"enumIdType\"]>;\n idSubType: Nullable<string>;\n country: Nullable<string>;\n region: Nullable<string>;\n idNumber: Nullable<string>;\n idExpiry: Nullable<string>;\n gender: Nullable<Core[\"enumGender\"]>;\n extraData: { [field: string]: Nullable<string | boolean | number> };\n docScan: TScan[];\n scans: TScan[];\n validation: TDocumentValidation;\n}\nconst normalizeIdType = (idType: Nullable<string>): Nullable<Core[\"enumIdType\"]> => {\n const mapper: { [k: string]: Core[\"enumIdType\"] } = {\n MOBILE_PHONE: \"MSISDN\",\n };\n if (!idType) return null;\n type MappedDocType = keyof typeof mapper & string;\n return mapper[idType as MappedDocType] ?? idType;\n};\nexport class Document implements IDocumentPayload, ICloneable<Document> {\n documentId: Nullable<string> = null;\n verified: TDocumentVerification = {\n electronic: null,\n manual: null,\n };\n dateOfBirth: Nullable<string> = null;\n idType: Nullable<Core[\"enumIdType\"]> = null;\n idSubType: Nullable<string> = null;\n country: Nullable<string> = null;\n region: Nullable<string> = null;\n idNumber: Nullable<string> = null;\n idExpiry: Nullable<string> = null;\n extraData: { [field: string]: Nullable<string | boolean | number> } = {};\n gender: Nullable<Core[\"enumGender\"]> = null;\n scans: Scan[] = [];\n validation: TDocumentValidation = {\n manual: {\n isValid: null,\n },\n electronic: {\n // this comes from onfito\n validationReport: null, // pdf from onfito for document report\n isValid: null, // onfito decision if document is valid\n },\n };\n constructor();\n constructor(d: IDocumentConstructor);\n constructor(d?: IDocumentConstructor) {\n if (!d) return;\n this.documentId = d.documentId?.toLowerCase() || null;\n this.verified = {\n electronic: null,\n manual: null,\n ...d.verified,\n };\n this.dateOfBirth = d.dateOfBirth;\n this.idType = normalizeIdType(d.idType);\n this.idSubType = d.idSubType;\n this.country = d.country || \"AUS\";\n this.region = d.region;\n this.idNumber = d.idNumber;\n this.idExpiry = d.idExpiry ? moment(d.idExpiry).format(\"YYYY-MM-DD\") : null;\n this.gender = d.gender;\n this.extraData = d.extraData || {};\n this.scans = d.scans || [];\n this.validation = {\n manual: {\n isValid: d.validation?.manual?.isValid || null,\n },\n electronic: {\n validationReport: d.validation?.electronic?.validationReport || null,\n isValid: d.validation?.electronic?.isValid || null,\n },\n };\n }\n\n // keeping docScan for backwards compatibility\n get docScan(): Scan[] {\n return this.scans;\n }\n\n set docScan(v: Scan[]) {\n this.scans = v;\n }\n\n isNewDocument(): boolean {\n return !!this.documentId;\n }\n\n getUploadedScanUuids(): string[] {\n const uploadedScansFinder = (sc: Scan) => typeof sc.fileUploadUuid === \"string\";\n const extractUploadUuid = (sc: Scan) => sc.fileUploadUuid;\n const uploadedUuid = this.scans.filter(uploadedScansFinder).map(extractUploadUuid) as string[];\n return uploadedUuid;\n }\n includeUploadFile(uploadUuid: string, s: Scan) {\n const i = this.scans.findIndex((d) => d.fileUploadUuid === uploadUuid);\n this.scans[i] = s;\n }\n clone(): Document {\n const payload = JSON.parse(JSON.stringify(this));\n const instance = Document.fromJSON(payload);\n return instance;\n }\n toJSON(): IDocumentPayload {\n const {\n scans,\n dateOfBirth,\n idSubType,\n documentId,\n idType,\n verified,\n region,\n country,\n idExpiry,\n idNumber,\n gender,\n extraData,\n validation,\n } = this;\n\n return {\n dateOfBirth: dateOfBirth || null,\n idSubType: idSubType || null,\n docScan: scans,\n scans,\n documentId,\n verified,\n region: region || null,\n country,\n idNumber: idNumber || null,\n gender: gender,\n extraData,\n validation,\n idType: idType || null,\n idExpiry,\n };\n }\n\n static fromJSON(payload: IDocumentPayload): Document {\n const document = new Document();\n const keys = Object.keys(payload) as (keyof IDocumentPayload)[];\n keys.forEach((key) => {\n //idExpiry need to has the format YYYY-MM-DD\n if (key === \"idExpiry\" && payload[key])\n return (document[key] = moment(payload[key] as string).format(\"YYYY-MM-DD\"));\n Object.assign(document, { key: payload[key] });\n });\n return document;\n }\n static default(): Document {\n return new Document();\n }\n}\nexport class Scan {\n scanId: Nullable<string>;\n fileUploadUuid: Nullable<string>;\n file: Nullable<string>;\n mimeType: Nullable<string>;\n side: Nullable<string>;\n scanCreated: Nullable<string>;\n scanName: Nullable<string>;\n constructor(scan: TScan) {\n this.scanId = scan.scanId;\n this.fileUploadUuid = scan.fileUploadUuid || null;\n this.file = scan.file || null;\n this.mimeType = scan.mimeType || null;\n this.side = scan.side || \"F\";\n this.scanCreated = scan.scanCreated || null;\n this.scanName = scan.scanName || null;\n }\n toJSON(): TScan {\n return { ...this };\n }\n static fromJSON(payload: TScan): Scan {\n return new Scan(payload);\n }\n}\n\nexport interface IDocumentConstructor {\n documentId: string | null;\n verified?: {\n electronic: TValidation;\n manual: TValidation;\n };\n dateOfBirth: string | null;\n idType: Core[\"enumIdType\"];\n idSubType: string | null;\n country: string | null;\n region: string | null;\n idNumber: string | null;\n idExpiry: string | null;\n gender: Core[\"enumGender\"] | null;\n extraData?: { [field: string]: Nullable<string | boolean | number> };\n scans?: Scan[]; // [{ file: \"\", mimeType: \"image/jpeg\", side:\"F | B\" } OR string with file upload uuid ]\n validation?: {\n manual: {\n isValid: TValidation;\n };\n electronic: {\n // this comes from onfito\n validationReport: Scan | null;\n isValid: TValidation;\n };\n };\n}\n","import { TApplicantStatus } from \"../General\";\nexport const STATE_FAILED = \"failed\";\nexport const STATE_PASSED = \"passed\";\nexport const STATE_FAIL = \"fail\";\nexport const STATE_PASS = \"pass\";\nexport const STATE_MANUAL_FAILED = \"fail_manual\";\nexport const STATE_MANUAL_PASSED = \"pass_manual\";\nexport const STATE_NEEDS_ATTENTION = \"refer\";\nexport const STATE_WAITING_ON_CUSTOMER = \"wait\";\nexport const STATE_UNCHECKED = \"unchecked\";\n\nexport enum STATE_TYPES {\n FAILED = \"failed\",\n PASSED = \"passed\",\n MANUAL_FAILED = \"fail_manual\",\n MANUAL_PASSED = \"pass_manual\",\n NEEDS_ATTENTION = \"refer\",\n WAITING_ON_CUSTOMER = \"wait\",\n UNCHECKED = \"unchecked\",\n ARCHIVED = \"archived\",\n INACTIVE = \"inactive\",\n}\n\nexport default function stateBackend(state: string): TApplicantStatus {\n const frontend: TApplicantStatus = { type: null, label: \"\", key: state };\n\n if (state) {\n state = state.toLowerCase();\n switch (state) {\n case \"pass\":\n case \"passed\":\n case \"checked_success\":\n case \"checked_success_clear\":\n frontend.type = STATE_TYPES.PASSED;\n frontend.label = \"Passed\";\n break;\n case \"review\":\n case \"refer\":\n case \"checked_partial_success\":\n case \"checked_success_with_notes\":\n frontend.type = STATE_TYPES.NEEDS_ATTENTION;\n frontend.label = \"Refer\";\n break;\n case \"no_match\":\n case \"fail\":\n case \"failed\":\n case \"check_stopped\":\n case \"checked_failed\":\n case \"not_supported\":\n case \"unprocessable\":\n case \"checking\":\n frontend.type = STATE_TYPES.FAILED;\n frontend.label = \"Failed\";\n break;\n case \"wait\":\n case \"waiting\":\n frontend.type = STATE_TYPES.WAITING_ON_CUSTOMER;\n frontend.label = \"Waiting\";\n break;\n case \"fail_manual\":\n case \"manual_fail\":\n frontend.type = STATE_TYPES.MANUAL_FAILED;\n frontend.label = \"Manually Failed\";\n break;\n case \"pass_manual\":\n case \"manual_pass\":\n frontend.type = STATE_TYPES.MANUAL_PASSED;\n frontend.label = \"Manually Failed\";\n break;\n case \"archived\":\n frontend.type = STATE_TYPES.ARCHIVED;\n frontend.label = \"Archived\";\n break;\n case \"inactive\":\n frontend.type = STATE_TYPES.INACTIVE;\n frontend.label = \"Inactive\";\n break;\n case \"unchecked\":\n frontend.type = STATE_TYPES.UNCHECKED;\n frontend.label = \"Unchecked\";\n }\n }\n\n return frontend;\n}\n\nexport const sortStatus = (a: TApplicantStatus, b: TApplicantStatus): number => {\n const STATUS_SORT = {\n [STATE_TYPES.PASSED]: 1,\n [STATE_TYPES.MANUAL_PASSED]: 2,\n [STATE_TYPES.NEEDS_ATTENTION]: 3,\n [STATE_TYPES.FAILED]: 4,\n [STATE_TYPES.MANUAL_FAILED]: 5,\n [STATE_TYPES.WAITING_ON_CUSTOMER]: 6,\n [STATE_TYPES.UNCHECKED]: 7,\n [STATE_TYPES.ARCHIVED]: 8,\n [STATE_TYPES.INACTIVE]: 9,\n };\n\n const aType = a.type;\n const bType = b.type;\n const aPoints = aType ? STATUS_SORT[aType] : 0;\n const bPoints = bType ? STATUS_SORT[bType] : 0;\n\n return aPoints - bPoints;\n};\n","import { Scan, TScan } from \"./Document\";\nimport { Nullable, ICloneable, IChangeStamp } from \"./General\";\n\n// TODO Values to be decided\nexport enum DocumentType {\n DRIVERS_LICENCE = \"DRIVERS_LICENCE\",\n PASSPORT = \"PASSPORT\",\n VISA = \"VISA\",\n IMMIGRATION = \"IMMIGRATION\",\n NATIONAL_ID = \"NATIONAL_ID\",\n NATIONAL_HEALTH_ID = \"NATIONAL_HEALTH_ID\",\n CONCESSION = \"CONCESSION\",\n HEALTH_CONCESSION = \"HEALTH_CONCESSION\",\n PENSION = \"PENSION\",\n MILITARY_ID = \"MILITARY_ID\",\n BIRTH_CERT = \"BIRTH_CERT\",\n CITIZENSHIP = \"CITIZENSHIP\",\n MARRIAGE_CERT = \"MARRIAGE_CERT\",\n DEATH_CERT = \"DEATH_CERT\",\n NAME_CHANGE = \"NAME_CHANGE\",\n UTILITY_BILL = \"UTILITY_BILL\",\n BANK_STATEMENT = \"BANK_STATEMENT\",\n BANK_ACCOUNT = \"BANK_ACCOUNT\",\n INTENT_PROOF = \"INTENT_PROOF\",\n SELF_IMAGE = \"SELF_IMAGE\",\n EMAIL_ADDRESS = \"EMAIL_ADDRESS\",\n MSISDN = \"MSISDN\",\n DEVICE = \"DEVICE\",\n VEHICLE_REGISTRATION = \"VEHICLE_REGISTRATION\",\n PROOF_OF_ADDRESS = \"PROOF_OF_ADDRESS\",\n EXTERNAL_ADMIN = \"EXTERNAL_ADMIN\",\n CHARGES = \"CHARGES\",\n PRE_ASIC = \"PRE_ASIC\",\n ANNUAL_RETURN = \"ANNUAL_RETURN\",\n REPORT = \"REPORT\",\n TRUST_DEED = \"TRUST_DEED\",\n PARTNERSHIP_AGREEMENT = \"PARTNERSHIP_AGREEMENT\",\n ADMIN_CHANGE = \"ADMIN_CHANGE\",\n COMPANY_REPORT = \"COMPANY_REPORT\",\n CHECK_RESULTS = \"CHECK_RESULTS\",\n OTHER = \"OTHER\",\n RENTAL_AGREEMENT = \"RENTAL_AGREEMENT\",\n TAX_STATEMENT = \"TAX_STATEMENT\",\n HOUSE_REGISTRATION = \"HOUSE_REGISTRATION\",\n YELLOW_HOUSE_REGISTRATION = \"YELLOW_HOUSE_REGISTRATION\",\n WORK_PERMIT = \"WORK_PERMIT\",\n EMPLOYMENT_CERTIFICATE = \"EMPLOYMENT_CERTIFICATE\",\n NOTARY_PUBLIC_ID = \"NOTARY_PUBLIC_ID\",\n}\n\nexport enum DocumentStatus {\n APPROVED = \"APPROVED\",\n DECLINED = \"DECLINED\",\n NEEDS_REVIEW = \"NEEDS_REVIEW\",\n}\n\nexport type SupportingDocumentReference = {\n uuid: string;\n type: string;\n};\n\nexport const ALLOWED_MIME_TYPES = [\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n \"image/tiff\",\n \"image/bmp\",\n \"application/pdf\",\n];\n\nexport const ALLOWED_MIME_TYPES_STRING = ALLOWED_MIME_TYPES.join(\", \");\n\nexport interface ISupportingDocument {\n id?: Nullable<string>;\n type: DocumentType;\n label: string;\n file: Nullable<Scan>;\n status?: Nullable<DocumentStatus>;\n modified?: Nullable<IChangeStamp>;\n reviewed?: Nullable<IChangeStamp>;\n refer?: Nullable<SupportingDocumentReference>;\n smartUiDocOrder?: Nullable<number>;\n}\nexport interface ISupportingDocumentPayload {\n id?: Nullable<string>;\n type: DocumentType;\n label: string;\n file: Nullable<TScan>;\n status?: Nullable<DocumentStatus>;\n modified?: Nullable<IChangeStamp>;\n reviewed?: Nullable<IChangeStamp>;\n refer?: Nullable<SupportingDocumentReference>;\n smartUiDocOrder?: Nullable<number>;\n}\n\nexport class SupportingDocument implements ISupportingDocument, ICloneable<SupportingDocument> {\n id: Nullable<string>;\n type: DocumentType = DocumentType.OTHER;\n label: string;\n file: Nullable<Scan>;\n status: Nullable<DocumentStatus>;\n modified: Nullable<IChangeStamp>;\n reviewed: Nullable<IChangeStamp>;\n refer: Nullable<SupportingDocumentReference>;\n smartUiDocOrder: Nullable<number>;\n\n constructor(payload: ISupportingDocument) {\n this.id = payload.id ?? null;\n this.type = payload.type;\n this.label = payload.label;\n this.file = payload.file ?? null;\n this.status = payload.status ?? null;\n this.modified = payload.modified ?? null;\n this.reviewed = payload.reviewed ?? null;\n this.refer = payload.refer ?? null;\n this.smartUiDocOrder = payload.smartUiDocOrder ?? null;\n }\n clone(): SupportingDocument {\n return SupportingDocument.fromJSON(this.toJSON());\n }\n\n toJSON(): ISupportingDocument {\n const file = this.file ? this.file.toJSON() : null;\n return {\n ...this,\n file,\n };\n }\n\n static fromJSON(payload: ISupportingDocumentPayload): SupportingDocument {\n const file = payload.file ? Scan.fromJSON(payload.file) : null;\n return new SupportingDocument({\n ...payload,\n file,\n });\n }\n}\n","import {\n TValidation,\n IIssueAction,\n IIssue,\n TApplicantStatus,\n TKycMethod,\n Nullable,\n} from \"./General\";\nimport mapBackendStatus from \"./transformers/apiState\";\nimport { DuplicateResults } from \"./Duplicate\";\n\ntype issue = {\n code: string | null;\n description: string | null;\n};\n\ntype TMatchsetCount = {\n required: number | null;\n actual: number | null;\n};\n\nexport type TRulesetMatchFields = {\n name: TMatchsetCount;\n dob: TMatchsetCount;\n address: TMatchsetCount;\n govId: TMatchsetCount;\n};\ninterface IConstructorCheckResult {\n type: string | null;\n result: TApplicantStatus;\n issues: issue[];\n}\n\ninterface IConstructorRulesetsCount {\n name: string | null;\n order: number | null;\n result: string | null;\n rulesetMatchFields: TRulesetMatchFields;\n}\ntype CheckSource = string[] | null;\n\nexport class CheckResult {\n type: string | null;\n result = {\n key: \"\",\n type: null,\n label: \"\",\n } as TApplicantStatus;\n issues: issue[];\n constructor(payload: IConstructorCheckResult) {\n this.type = payload.type || null;\n this.result.type = payload?.result?.type || null;\n this.result.label = payload.result.label || \"\";\n this.result.action = payload.result.action;\n this.issues = payload.issues || [];\n }\n}\nexport interface ICheckSummaryPayload {\n checkTypes: string[];\n checkDate: string;\n personalChecks: {\n name: TValidation;\n dateOfBirth: TValidation;\n phoneNumber: TValidation;\n email: TValidation;\n chineseName: Nullable<string>;\n addresses: {\n [k: string]: TValidation;\n };\n };\n status: TApplicantStatus;\n blocklistPotentialMatches: DuplicateResults[];\n duplicatePotentialMatches: DuplicateResults[];\n duplicateBlocklistMatches: DuplicateResults[];\n risk: {\n level: number | null;\n class: string | null;\n };\n alertList: (IIssue | IIssueAction)[];\n checkCounts: {\n name: CheckSource;\n address: {\n [k: string]: CheckSource;\n };\n document: {\n [k: string]: CheckSource;\n };\n dob: CheckSource;\n };\n kycMethod: TKycMethod;\n issues: { [issue: string]: any };\n checkResults?: CheckResult[];\n rulesetsMatches: RulesetsMatch[];\n}\n\nexport interface ICheckSummaryConstructor {\n checkTypes: string[];\n checkDate: string;\n personalChecks: {\n name: TValidation;\n dateOfBirth: TValidation;\n phoneNumber: TValidation;\n email: TValidation;\n chineseName: Nullable<string>;\n addresses: {\n [k: string]: TValidation;\n };\n };\n status: string;\n blocklistPotentialMatches: DuplicateResults[];\n duplicatePotentialMatches: DuplicateResults[];\n duplicateBlocklistMatches: DuplicateResults[];\n risk: {\n level: number | null;\n class: string | null;\n };\n alertList: (IIssue | IIssueAction)[];\n checkCounts: {\n name: CheckSource;\n address: {\n [k: string]: CheckSource;\n };\n document: {\n [k: string]: CheckSource;\n };\n dob: CheckSource;\n };\n kycMethod: TKycMethod;\n issues: { [issue: string]: any };\n checkResults?: CheckResult[];\n rulesetsMatches?: RulesetsMatch[];\n}\n\nconst numericOrNull = (v: any): number | null => (!isNaN(v) ? v : null);\nconst booleanOrNull = (v: any): boolean | null => (typeof v === \"boolean\" ? v : null);\nconst stringOrNull = (v: any): string | null => (typeof v === \"string\" ? v : null);\nconst buildArrayWith =\n (visit: (props: any) => void) =>\n (carry: any, [key, value]: [string, unknown]) => {\n carry[key] = visit(value);\n return carry;\n };\nconst visitObjectWith = (addrs: any) => (visitor: (props: any) => void) => {\n const entries = Object.entries(addrs);\n const rebuilt = entries.reduce(buildArrayWith(visitor), {});\n return rebuilt;\n};\nconst buildAddressValidationObject = (addrs: any) => visitObjectWith(addrs)(booleanOrNull);\n\nexport class RulesetsMatch {\n name: string | null;\n order: number | null;\n result: string | null;\n rulesetMatchFields: TRulesetMatchFields;\n constructor(payload: IConstructorRulesetsCount) {\n this.name = payload.name || null;\n this.order = payload.order || null;\n this.result = payload?.result || null;\n this.rulesetMatchFields = payload.rulesetMatchFields || null;\n }\n}\n\nexport class CheckSummary implements ICheckSummaryPayload {\n checkDate: string;\n checkTypes: string[];\n personalChecks: {\n name: TValidation;\n dateOfBirth: TValidation;\n phoneNumber: TValidation;\n email: TValidation;\n chineseName: Nullable<string>;\n addresses: {\n [k: string]: TValidation;\n };\n };\n status: TApplicantStatus;\n risk: {\n level: number | null;\n class: string | null;\n };\n alertList: (IIssue | IIssueAction)[];\n blocklistPotentialMatches: DuplicateResults[];\n duplicatePotentialMatches: DuplicateResults[];\n duplicateBlocklistMatches: DuplicateResults[];\n checkCounts: {\n name: CheckSource;\n address: {\n [k: string]: CheckSource;\n };\n document: {\n [k: string]: CheckSource;\n };\n dob: CheckSource;\n };\n kycMethod: TKycMethod;\n issues: { [issue: string]: any };\n checkResults: CheckResult[];\n rulesetsMatches: RulesetsMatch[];\n\n constructor(c: ICheckSummaryConstructor) {\n this.checkTypes = c.checkTypes || [];\n this.checkDate = c.checkDate || \"\";\n this.personalChecks = {\n name: booleanOrNull(c.personalChecks.name),\n dateOfBirth: booleanOrNull(c.personalChecks.dateOfBirth),\n phoneNumber: booleanOrNull(c.personalChecks.phoneNumber),\n email: booleanOrNull(c.personalChecks.email),\n chineseName: stringOrNull(c.personalChecks.chineseName),\n addresses: buildAddressValidationObject(c.personalChecks.addresses),\n };\n this.status = mapBackendStatus(c.status || \"UNCHECKED\");\n this.blocklistPotentialMatches = c.blocklistPotentialMatches ?? [];\n this.duplicatePotentialMatches = c.duplicatePotentialMatches ?? [];\n this.duplicateBlocklistMatches = c.duplicateBlocklistMatches ?? [];\n this.risk = {\n level: numericOrNull(c.risk.level), // using fallback assignment doesnt work for 0\n class: c.risk.class || null,\n };\n this.alertList = c.alertList || [];\n this.checkCounts = {\n name: c.checkCounts.name,\n address: c.checkCounts.address,\n document: c.checkCounts.document,\n dob: c.checkCounts.dob,\n };\n this.kycMethod = c.kycMethod;\n this.issues = c.issues || {};\n this.checkResults = c.checkResults || [];\n this.rulesetsMatches = c.rulesetsMatches || [];\n }\n\n toJSON(): ICheckSummaryPayload {\n return { ...this };\n }\n\n clone(): CheckSummary {\n const payload = JSON.parse(JSON.stringify(this));\n const checkSummary = CheckSummary.fromJSON(payload);\n return checkSummary;\n }\n\n static fromJSON(payload: ICheckSummaryPayload): CheckSummary {\n return new CheckSummary({\n checkDate: payload.checkDate,\n checkTypes: payload.checkTypes,\n personalChecks: payload.personalChecks,\n status: payload.status.key,\n alertList: payload.alertList,\n blocklistPotentialMatches: payload.blocklistPotentialMatches,\n duplicatePotentialMatches: payload.duplicatePotentialMatches,\n duplicateBlocklistMatches: payload.duplicateBlocklistMatches,\n kycMethod: payload.kycMethod,\n issues: payload.issues,\n risk: payload.risk,\n checkCounts: payload.checkCounts,\n checkResults: payload.checkResults,\n rulesetsMatches: payload.rulesetsMatches,\n });\n }\n static default(): CheckSummary {\n return CheckSummary.fromJSON({\n checkDate: \"\",\n checkTypes: [],\n personalChecks: {\n name: null,\n dateOfBirth: null,\n phoneNumber: null,\n email: null,\n chineseName: \"\",\n addresses: {},\n },\n status: {\n type: null,\n label: \"\",\n key: \"\",\n },\n alertList: [],\n blocklistPotentialMatches: [],\n duplicatePotentialMatches: [],\n duplicateBlocklistMatches: [],\n kycMethod: \"electronic\",\n issues: {},\n risk: {\n level: null,\n class: null,\n },\n checkCounts: {\n address: {},\n dob: null,\n document: {},\n name: null,\n },\n rulesetsMatches: [],\n });\n }\n}\n","import { Applicant, IApplicantPayload } from \"./Applicant\";\nimport { IDocumentPayload, Document } from \"./Document\";\nimport { SupportingDocument, ISupportingDocumentPayload } from \"./SupportingDocument\";\nimport { ICheckSummaryPayload, CheckSummary } from \"./CheckSummary\";\nimport { OrganisationPayload } from \"./Organisation\";\n\nimport { Admin } from \"./Admin\";\nimport { Core } from \"./Core\";\nimport { PartialDeep } from \"type-fest\";\nexport declare type Nullable<T> = T | null;\nexport declare type IStringOrNull = string | null;\nexport declare type Dictionary<T = any> = {\n [key: string]: T;\n};\nexport declare type Kvp = (AdminKvpWithoutValue | CoreKvpWithoutValue) & {\n kvpValue: any;\n};\nexport declare type DictionaryReturnTypes<D extends Dictionary<(...args: any) => any>> = {\n [P in keyof D]: ReturnType<D[P]>;\n};\nexport declare type DeepPartial<T> = PartialDeep<T>;\nexport declare interface ICloneable<T> {\n clone(): T;\n}\ntype AdminKvpWithoutValue = Omit<Admin[\"KeyValuePairObject\"], \"kvpValue\">;\ntype CoreKvpWithoutValue = Omit<Core[\"KeyValuePairObject\"], \"kvpValue\">;\nexport declare type TDOBTypeSupport = \"gregorian\" | \"buddhist\";\nexport declare type DateObject = {\n dd: IStringOrNull;\n mm: IStringOrNull;\n yyyy: IStringOrNull;\n};\nexport declare type ExtraData = {\n [field: string]: Nullable<string | boolean | number>;\n};\nexport type TValidation = boolean | null;\nexport type TValidationFieldIssues = string[];\nexport type TValidationResult = { [field: string]: TValidationFieldIssues };\nexport type TFieldIssuesTuple = [string, TValidationFieldIssues];\nexport type TApplicantStatus = {\n type: TStatusType | null;\n label: string;\n key: string;\n action?: string;\n};\n\nexport type TStatusType =\n | \"failed\"\n | \"passed\"\n | \"fail_manual\"\n | \"pass_manual\"\n | \"refer\"\n | \"wait\"\n | \"unchecked\"\n | \"archived\"\n | \"inactive\";\nexport declare interface IMachineCredential {\n customerId: string;\n customerChildId?: string | null;\n apiKey: string;\n}\nexport declare interface IUserCredential {\n username: string;\n password: string;\n}\nexport declare type IFrankieClientCredentials = IMachineCredential | IUserCredential;\nexport declare interface IApplicantInformation {\n applicant: Applicant;\n documents?: Document[];\n supportingDocuments?: SupportingDocument[];\n}\nexport declare interface ICreateApplicantResponse {\n entityId: string;\n requestId: string;\n}\n\nexport type SearchOptions = {\n reference: string;\n entityId: string;\n};\n\nexport declare interface IUserRole {\n id: number;\n role: string;\n isHidden: boolean;\n permissions: [];\n createdAt: {\n date: Date;\n };\n}\n\nexport declare interface ICreateUser {\n userData: ICreateUserData;\n}\n\nexport declare interface ICreateUserData {\n realname: string;\n username: string;\n email: string;\n roleIds: number[];\n}\n\nexport declare interface ITriggerChecksResponse {\n hasCreditHeaderIssue: boolean;\n detailLevel: TDetailLevel;\n}\n\nexport declare interface IGetExternalIdvToken {\n token: string;\n}\n\nexport declare type TDetailLevel = \"full\";\n\nexport declare interface IGetApplicantDetailsResponse {\n applicant: IApplicantPayload;\n documents: IDocumentPayload[];\n checkSummary: ICheckSummaryPayload;\n}\n\nexport declare interface IGetApplicantInformationResponse {\n applicant: IApplicantPayload;\n documents: IDocumentPayload[];\n supportingDocuments: ISupportingDocumentPayload[];\n}\nexport interface ICreateIDVTokenResponse {\n token: string;\n applicant: IApplicantPayload;\n documents: IDocumentPayload[];\n checkSummary: ICheckSummaryPayload;\n docTypesRequiredToCheck: IDocumentPayload[\"idType\"][];\n idvTwoDocuments: boolean;\n}\nexport interface IApplicantDetails {\n applicant: Applicant;\n documents: Document[];\n checkSummary: CheckSummary;\n}\nexport interface IGetCommits {\n coreApiCommitId: string;\n adminApiCommitId: boolean;\n}\nexport interface IAnalyticsData {\n [organizationId: string]: IOrganizationAnalytics;\n}\nexport type IOrganizationAnalytics = {\n pass_rate: TPassRateAnalytics;\n risk_level: TRiskLevelAnalytics;\n issues: TIssueCount[];\n};\n\nexport type TPassRateAnalytics = {\n passed: number;\n manually_passed: number;\n failed: number;\n manually_failed: number;\n needs_attention: number;\n unchecked: number;\n pending: number;\n duplicate: number;\n archived: number;\n inactive: number;\n};\nexport type TRiskLevelAnalytics = {\n high: number;\n low: number;\n medium: number;\n unacceptable: number;\n unknown: number;\n};\nexport type TIssueCount = {\n type: string;\n count: number;\n};\n\nexport type TEventPayload = {\n customerId: string;\n sessionId: string;\n data: { [field: string]: Nullable<string | boolean | number> };\n channel: Nullable<string>;\n version: Nullable<string>;\n deviceType: Nullable<string>;\n browser: Nullable<string>;\n};\nexport type TIssueType = \"warning\" | \"action\" | \"alert\" | \"success\";\nexport interface IIssue {\n term: string;\n type: TIssueType;\n}\nexport interface IIssueAction extends IIssue {\n type: \"action\";\n extra: {\n action: string;\n label?: string;\n };\n}\nexport type TKycMethod = \"electronic\" | \"manual\";\nexport interface IChangeStamp {\n channel: ChannelString;\n userId: string;\n by: string;\n timestamp: string;\n}\n\nexport enum ChannelString {\n PORTAL = \"PORTAL\",\n SMART_UI = \"SMART_UI\",\n API = \"API\",\n}\n\nexport function isMachineCredential(cred: any): cred is IMachineCredential {\n if (!cred) return false;\n const { apiKey, customerId, customerChildId, ...rest } = cred as IMachineCredential;\n return !!apiKey && !!customerId && Object.keys(rest).length === 0;\n}\nexport function isUserCredential(cred: any): cred is IUserCredential {\n if (!cred) return false;\n const { password, username, ...rest } = cred as IUserCredential;\n return !!password && !!username && Object.keys(rest).length === 0;\n}\nexport interface ICreateMachineSessionResponse {\n organisation: OrganisationPayload;\n [configurations: string]: any;\n}\n","import { User } from \"./User\";\nimport { Nullable } from \"./General\";\n// missing field users in organisationpayload\nexport type OrganisationPayload = {\n id: Nullable<number>;\n parentId: Nullable<number>;\n customerId: Nullable<string>;\n customerChildId: Nullable<string>;\n name: Nullable<string>;\n nickName: Nullable<string>;\n authType: Nullable<string>;\n isRoot: Nullable<boolean>;\n denyOldPasswordCount: Nullable<number>;\n timezone: Nullable<string>;\n parent: Nullable<OrganisationPayload>;\n children: OrganisationPayload[];\n organisations: OrganisationPayload[];\n users: User[];\n};\nexport class Organisation {\n id: Nullable<number> = null;\n parentId: Nullable<number> = null;\n customerId: Nullable<string> = null;\n customerChildId: Nullable<string> = null;\n name: Nullable<string> = null;\n nickName: Nullable<string> = null;\n authType: Nullable<string> = null;\n isRoot: Nullable<boolean> = null;\n denyOldPasswordCount: Nullable<number> = null;\n timezone: Nullable<string> = null;\n parent: Nullable<Organisation> = null;\n children: Organisation[] = [];\n users: User[] = [];\n organisations: Organisation[] = [];\n toJSON(): OrganisationPayload {\n const { parent, children, users, organisations, ...primitives } = this;\n return {\n ...primitives,\n users,\n parent: parent && parent.toJSON(),\n children: children.map((c) => c.toJSON()),\n organisations: organisations.map((o) => o.toJSON()),\n };\n }\n static fromJSON(payload: OrganisationPayload): Organisation {\n const instance = new Organisation();\n instance.id = payload.id;\n instance.isRoot = payload.isRoot;\n instance.name = payload.name;\n instance.nickName = payload.nickName;\n instance.organisations = payload.organisations?.map((p) => Organisation.fromJSON(p)) ?? [];\n instance.parent = payload.parent && Organisation.fromJSON(payload.parent);\n instance.children = payload.children?.map((p) => Organisation.fromJSON(p)) ?? [];\n instance.parentId = payload.parentId;\n instance.timezone = payload.timezone;\n instance.customerChildId = payload.customerChildId;\n instance.customerId = payload.customerId;\n instance.users = payload.users;\n\n return instance;\n }\n}\n","import {\n Applicant,\n Document,\n CheckSummary,\n IGetApplicantDetailsResponse,\n IApplicantDetails,\n ICreateIDVTokenResponse,\n} from \"../models\";\nimport { AxiosInstance, AxiosRequestConfig, AxiosResponse } from \"axios\";\n\nexport class ExternalIdvClient {\n private instance: AxiosInstance;\n\n constructor(instance: AxiosInstance) {\n this.instance = instance;\n }\n\n async getIdvToken(\n entityId: string,\n config: {\n smsContent?: string;\n smsPhoneNumber?: string;\n referrer?: string;\n noService?: boolean;\n } = {}\n ): Promise<ICreateIDVTokenResponse> {\n const { smsContent, smsPhoneNumber, referrer, noService = false } = config;\n\n const { data } = await this.post<ICreateIDVTokenResponse>(\n `/data/v1/external-idv/applicant/${entityId}`,\n { smsContent, smsPhoneNumber, referrer },\n { params: { \"no-service\": noService || undefined } }\n );\n\n return data;\n }\n\n async initiateIdvProcess(entityId: string) {\n await this.post(`/data/v1/external-idv/applicant/${entityId}/initiate`, {});\n }\n\n async getApplicantDetails(token: string): Promise<IApplicantDetails> {\n const { data } = await this.get<IGetApplicantDetailsResponse>(`/data/v1/external-idv/${token}`);\n const applicant = Applicant.fromJSON(data.applicant);\n const documents = data.documents.map((d) => Document.fromJSON(d));\n const checkSummary = CheckSummary.fromJSON(data.checkSummary);\n return { applicant, documents, checkSummary };\n }\n\n get<T = any, R = AxiosResponse<T>>(...params: GetParameters): Promise<R> {\n return this.instance.get(...params);\n }\n post<T = any, R = AxiosResponse<T>>(...params: PostParameters): Promise<R> {\n return this.instance.post(...params);\n }\n}\ntype PostParameters = [string, any?, AxiosRequestConfig?];\ntype GetParameters = [string, AxiosRequestConfig?];\n","import { ExternalIdvClient } from \"./ExternalIdvClient\";\nimport Axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from \"axios\";\nimport {\n Applicant,\n CheckSummary,\n Document,\n SupportingDocument,\n ConfigurationReader,\n Organisation,\n OrganisationPayload,\n isMachineCredential,\n Admin,\n DeepPartial,\n IApplicantDetails,\n IApplicantInformation,\n ICreateApplicantResponse,\n IFrankieClientCredentials,\n IGetApplicantDetailsResponse,\n IGetApplicantInformationResponse,\n IStringOrNull,\n ITriggerChecksResponse,\n SearchOptions,\n ICreateMachineSessionResponse,\n User,\n} from \"../models\";\n\nimport { stringToBase64 } from \"../utils/base64\";\n\ntype AxiosComponentsInFrankieApiClient =\n | \"interceptors\"\n | \"get\"\n | \"delete\"\n | \"post\"\n | \"put\"\n | \"defaults\";\nexport type LoginResponse<Config> = {\n organisation: Organisation;\n configuration: ConfigurationReader<Config>;\n user?: User;\n permissions?: string[];\n};\ntype PermissionPresetName = \"smart-ui\";\ntype PermissionPresetObject = { preset: PermissionPresetName } & {\n preset: \"smart-ui\";\n reference?: string;\n};\ntype TLoginOptions = {\n referrer?: string | null;\n permissions?: string[] | PermissionPresetName | PermissionPresetObject;\n};\ntype UpdateApplicantQueryParameters = {\n noAddress: boolean;\n dataConsent: boolean;\n};\nexport type IChannel = \"portal\" | \"smart-ui\" | \"support-portal\" | \"unknown\" | Admin[\"enumChannel\"];\nexport class FrankieApiClient implements Pick<AxiosInstance, AxiosComponentsInFrankieApiClient> {\n private instance: AxiosInstance;\n private credentials: IFrankieClientCredentials | null = null;\n constructor(baseUrl: string, channel: IChannel = \"unknown\") {\n const resolvedConfig: AxiosRequestConfig = {\n baseURL: baseUrl,\n headers: {\n \"X-Frankie-Channel\": channel,\n },\n };\n this.instance = Axios.create(resolvedConfig);\n this.instance.interceptors.response.use((response: AxiosResponse) => {\n const token = response.headers.token;\n if (token) this.setToken(token);\n return response;\n });\n }\n get isMachine(): boolean {\n return isMachineCredential(this.credentials);\n }\n get interceptors(): AxiosInstance[\"interceptors\"] {\n return this.instance.interceptors;\n }\n get defaults(): AxiosInstance[\"defaults\"] {\n return this.instance.defaults;\n }\n\n async login<Config>(\n credentials: IFrankieClientCredentials,\n options: TLoginOptions = {}\n ): Promise<LoginResponse<Config>> {\n const { referrer = null, permissions = null } = options;\n this.credentials = credentials;\n const isMachine = isMachineCredential(credentials);\n const endpoint = \"/auth/v2/sessions\";\n const agent = isMachine ? \"machine\" : \"user\";\n const response = await this.post<ICreateMachineSessionResponse>(\n endpoint,\n { referrer, permissions },\n {\n headers: {\n authorization: `${agent} ${this.serialiseCredentials(credentials)}`,\n },\n }\n );\n if (!response.headers.token) throw \"Missing token\";\n this.setToken(response.headers.token);\n\n const { organisation: organisationData, ...configurationData } = response.data;\n const organisation = Organisation.fromJSON(organisationData);\n const configuration = new ConfigurationReader(configurationData as Config);\n\n return { organisation, configuration };\n }\n async createApplicant(\n { applicant, documents = [], supportingDocuments = [] }: IApplicantInformation,\n queryParameters: DeepPartial<UpdateApplicantQueryParameters> = {}\n ): Promise<ICreateApplicantResponse> {\n const { noAddress = false, dataConsent = false } = queryParameters;\n const { data } = await this.post<ICreateApplicantResponse>(\n \"/data/v2/applicants\",\n {\n applicant,\n documents,\n supportingDocuments,\n kycMethod: \"electronic\",\n consent: dataConsent,\n },\n {\n params: {\n no_address: noAddress,\n },\n }\n );\n return data;\n }\n async updateApplicant(\n entityId: string,\n { applicant, documents = [], supportingDocuments = [] }: IApplicantInformation,\n queryParameters: DeepPartial<UpdateApplicantQueryParameters> = {}\n ): Promise<ICreateApplicantResponse> {\n const { noAddress = false, dataConsent = false } = queryParameters;\n const { data } = await this.put<ICreateApplicantResponse>(\n `/data/v2/applicants/${entityId}`,\n {\n applicant,\n documents,\n supportingDocuments,\n kycMethod: \"electronic\",\n consent: dataConsent,\n },\n {\n params: {\n no_address: noAddress,\n },\n }\n );\n return data;\n }\n async triggerChecks(\n entityId: string,\n config: { fetchDetails?: boolean; manualKyc?: boolean } = {}\n ): Promise<ITriggerChecksResponse | IApplicantDetails> {\n const { fetchDetails = false } = config;\n const { data } = await this.post<ITriggerChecksResponse>(\n `/data/v1/applicants/${entityId}/checks`\n );\n if (fetchDetails) {\n return this.getApplicantDetails(entityId);\n } else {\n return data;\n }\n }\n async getApplicantDetails(entityId: string): Promise<IApplicantDetails> {\n const { data } = await this.get<IGetApplicantDetailsResponse>(\n `/data/v2/applicants/${entityId}`\n );\n\n const applicant = Applicant.fromJSON(data.applicant);\n const documents = data.documents.map((d) => Document.fromJSON(d));\n const checkSummary = CheckSummary.fromJSON(data.checkSummary);\n return { applicant, documents, checkSummary };\n }\n async search(details: Partial<SearchOptions>): Promise<IApplicantInformation> {\n const { data } = await this.get<IGetApplicantInformationResponse>(`/data/v2/applicant/`, {\n params: details,\n });\n\n const applicant = Applicant.fromJSON(data.applicant);\n const documents = data.documents.map((d) => Document.fromJSON(d));\n const supportingDocuments = data.supportingDocuments.map((d) => SupportingDocument.fromJSON(d));\n return { applicant, documents, supportingDocuments };\n }\n serialiseCredentials(credentials: IFrankieClientCredentials): string {\n let elements: [IStringOrNull?, IStringOrNull?, IStringOrNull?];\n\n if (isMachineCredential(credentials)) {\n elements = [credentials.customerId, credentials.customerChildId, credentials.apiKey];\n } else {\n elements = [credentials.username, credentials.password];\n }\n return stringToBase64(elements.filter(Boolean).join(\":\"));\n }\n get frankieToken(): string | null {\n const headers = this.instance.defaults.headers;\n const headerOrNull = (which: string) => headers[which] ?? null;\n const headersOrNull = (headers: string[]) => {\n return headers.reduce((found: string | null, header: string) => {\n if (found) return found;\n return headerOrNull(header);\n }, null);\n };\n const token = headersOrNull([\"authorisation\", \"authorization\", \"auth\"]);\n return token;\n }\n async setToken<Config>(\n token: string,\n options: { checkValidity?: boolean } = {}\n ): Promise<LoginResponse<Config> | null> {\n const { checkValidity = false } = options;\n this.instance.defaults.headers[\"authorization\"] = token;\n if (checkValidity) {\n const {\n data: { organisation: organisationPayload, ...configuration },\n } = await this.get<{ organisation: OrganisationPayload }>(\"data/v2/token-validity\");\n const organisation = Organisation.fromJSON(organisationPayload);\n\n return {\n organisation,\n configuration: new ConfigurationReader(configuration as Config),\n };\n }\n return null;\n }\n getClient(w: \"externalIdv\"): ExternalIdvClient;\n getClient(which: \"externalIdv\") {\n if (which === \"externalIdv\") return new ExternalIdvClient(this.instance);\n }\n\n get<T = any, R = AxiosResponse<T>>(\n url: string,\n config?: AxiosRequestConfig | undefined\n ): Promise<R> {\n return this.instance.get(url, config);\n }\n delete<T = any, R = AxiosResponse<T>>(\n url: string,\n config?: AxiosRequestConfig | undefined\n ): Promise<R> {\n return this.instance.delete(url, config);\n }\n post<T = any, R = AxiosResponse<T>>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig | undefined\n ): Promise<R> {\n return this.instance.post(url, data, config);\n }\n put<T = any, R = AxiosResponse<T>>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig | undefined\n ): Promise<R> {\n return this.instance.put(url, data, config);\n }\n}\n","import { Buffer } from \"buffer\";\nexport function stringToBase64(s: string): string {\n return bufferToBase64(Buffer.from(s, \"utf8\"));\n}\nexport function bufferToBase64(b: Buffer): string {\n return b.toString(\"base64\");\n}\nexport function base64ToString(bs: string): string {\n return Buffer.from(bs, \"base64\").toString(\"utf8\");\n}\nexport function bufferToString(b: Buffer): string {\n return b.toString(\"utf8\");\n}\nexport function hexToByteString(hex: string) {\n const bytes: number[] = hexToBytes(hex);\n const buffer: Buffer = Buffer.from(bytes);\n return bufferToString(buffer);\n}\nexport function hexToBytes(hex: string): number[] {\n const bytes: number[] = bufferToByteString(Buffer.from(hex, \"hex\"));\n return bytes;\n}\nexport function bytesToBase64(byt: number[]): string {\n const buffer: Buffer = Buffer.from(byt);\n return bufferToBase64(buffer);\n}\nexport function bufferToByteString(buff: Buffer) {\n const bytes = Array.from(buff);\n return bytes;\n}\nexport function stringToByteString(str: string): number[] {\n const buffer = Buffer.from(str);\n const bytes = bufferToByteString(buffer);\n return bytes;\n}\n","import { Context, RouteObject, Store, StrObject } from \"../../../interfaces\";\n\nexport type RouteDictionary<RouteName extends string, RouteComponent> = Record<\n RouteName,\n RouteObject<RouteComponent>\n>;\nexport type RouteHistory<RouteName> = (RouteName | null)[];\n\nexport type RouteNameResolution<RouteName extends string, Config> = (o: {\n context: Context<Config>;\n checkOrder: RouteName[];\n routeHistory: (RouteName | null)[]; // where null indicates context was submitted, which indicates a loop start\n}) => RouteName | null;\n\nexport type RouteComponentResolution<\n RouteName extends string,\n RouteComponent,\n Config extends StrObject,\n ResultingRouteComponent = RouteComponent\n> = (o: {\n routeName: RouteName;\n routeDictionary: RouteDictionary<RouteName, RouteComponent>;\n context: Context<Config>;\n}) => ResultingRouteComponent;\nexport type RouterContext<\n Config,\n RouteName extends string,\n RouteComponent,\n ResultingRouteComponent\n> = {\n resolveRouteName: RouteNameResolution<RouteName, Config>;\n resolveRouteComponent: RouteComponentResolution<\n RouteName,\n RouteComponent,\n Config,\n ResultingRouteComponent\n >;\n getStore(): Store<Config>;\n getRouteOrder(): RouteName[];\n getRouteHistory(): RouteHistory<RouteName>;\n pushRouteToHistory(nxtName: RouteHistory<RouteName>[0]): void;\n getRouteDictionary(): RouteDictionary<RouteName, RouteComponent>;\n};\nexport default async function getNextRoute<\n Config,\n RouteName extends string,\n RouteComponent,\n ResultingRouteComponent\n>(\n router: RouterContext<Config, RouteName, RouteComponent, ResultingRouteComponent>\n): Promise<ResultingRouteComponent | null> {\n const context = router.getStore().getContext();\n // discover next route name based on context\n const routeHistory = router.getRouteHistory();\n const routeDictionary = router.getRouteDictionary();\n const currentRouteName = routeHistory[routeHistory.length - 1];\n const nextRouteName = router.resolveRouteName({\n context,\n checkOrder: router.getRouteOrder(),\n routeHistory: router.getRouteHistory(),\n });\n // include next route name in history, even if \"null\"\n router.pushRouteToHistory(nextRouteName);\n\n console.log(\"next route: \", nextRouteName);\n\n if (nextRouteName === null) {\n // when it is \"null\", it means there's nothing for widget to do next, so:\n // 0 if previous was already null, we reached an unsolvable loop, which should be ended by returning null\n if (currentRouteName === null) return null;\n // 1 submit and update local context with new backend information (check results)\n // 2 attempt to get next route again\n await router.getStore().submitContext();\n return getNextRoute(router);\n } else {\n // if there is a next route,\n // 1 Store it as currentRouteName\n // 2 current route object will be derived and updated from it\n return router.resolveRouteComponent({\n context,\n routeDictionary,\n routeName: nextRouteName,\n });\n }\n}\n// assigning generics to any as this is the default value that needs to be compatible with \"any\" concrete specification. Unknown won't work here\nexport const defaultRouteComponentResolution: RouteComponentResolution<any, any, any, any> = ({\n routeName,\n routeDictionary,\n}) => (routeName ? routeDictionary[routeName] : null);\n// by default next route is simply the next in checkOrder, based on existing route history. This means that after checkOrder is completed it will signal with \"null\"\nexport const defaultRouteNameResolution: RouteNameResolution<any, any> = ({\n checkOrder,\n routeHistory,\n}) => checkOrder[routeHistory.length] ?? null;\n","import { RefObject, useRef, useState } from \"react\";\nimport { Router, Store, StrObject } from \"../../interfaces\";\nimport findNextRoute, {\n defaultRouteComponentResolution,\n defaultRouteNameResolution,\n RouteComponentResolution,\n RouteDictionary,\n RouteHistory,\n RouteNameResolution,\n} from \"./common/routing\";\nimport { RouterOptions } from \"./DictionaryRouter\";\nexport default class ReactDictionaryRouter<\n Config extends StrObject,\n RouteComponent,\n RouteName extends string,\n WrappedRouteComponent\n> implements Router<WrappedRouteComponent>\n{\n private currentComponent: WrappedRouteComponent | null;\n private routeComponentSetter;\n\n private routeDictionary: RouteDictionary<RouteName, RouteComponent>;\n private routeOrder: RouteName[];\n private routeHistoryRef: RefObject<RouteHistory<RouteName>>;\n private storeRef: RefObject<Store<Config>>;\n private routeNameResolution: RouteNameResolution<RouteName, Config>;\n private routeComponentResolution: RouteComponentResolution<\n RouteName,\n RouteComponent,\n Config,\n WrappedRouteComponent\n >;\n\n constructor({\n store,\n routeDictionary,\n routeOrder,\n routeComponentResolution,\n routeNameResolution,\n }: RouterOptions<Config, RouteComponent, RouteName, WrappedRouteComponent>) {\n // this constructor will be called on every render\n // constructor functions are just syntatic sugar for regular functions, so there's no performance hit for doing this\n // initialise routeComponent as reactive state and save its setter\n // to avoid storing a function component, store it wrapped in an object. Not required, just nicer.\n const [wrappedComponent, wrappedComponentSetter] = useState<{\n c: WrappedRouteComponent | null;\n }>({ c: null });\n // unwrap into a variable\n this.currentComponent = wrappedComponent.c;\n // when calling the setter, wrap back into the state\n this.routeComponentSetter = (c: WrappedRouteComponent | null) => wrappedComponentSetter({ c });\n // keep history as a mutable reference across renders\n this.routeHistoryRef = useRef([]);\n // keep store as a mutable reference across renders\n this.storeRef = useRef(store);\n this.routeDictionary = routeDictionary;\n this.routeOrder = routeOrder;\n this.routeNameResolution = routeNameResolution ?? defaultRouteNameResolution;\n this.routeComponentResolution =\n routeComponentResolution ??\n (defaultRouteComponentResolution as RouteComponentResolution<\n RouteName,\n RouteComponent,\n Config,\n WrappedRouteComponent\n >);\n }\n\n getCurrentRoute(): WrappedRouteComponent | null {\n return this.currentComponent ?? null;\n }\n\n async getNextRoute(): Promise<WrappedRouteComponent | null> {\n const routeComponent = await findNextRoute({\n getRouteOrder: () => this.routeOrder,\n getRouteHistory: () => this.routeHistoryRef.current!,\n getRouteDictionary: () => this.routeDictionary,\n pushRouteToHistory: (n) => this.routeHistoryRef.current!.push(n),\n getStore: () => this.storeRef.current!,\n resolveRouteComponent: this.routeComponentResolution,\n resolveRouteName: this.routeNameResolution,\n });\n\n this.routeComponentSetter(routeComponent);\n return routeComponent;\n }\n}\n","import { Applicant, ICreateApplicantResponse } from \"../../models\";\nimport { FrankieApiClient } from \"../../api\";\nimport { useRef, useState } from \"react\";\nimport { Context, Store, StrObject } from \"../../interfaces\";\nimport { ConfigurationReader } from \"../../models\";\n\n/**\n * lot of repeated code from InMemoryStore, but this will make the purpose of the code a bit clearer\n * notice how this is simply a \"class syntax\" version of a custom hook\n */\nexport default class ReactInMemoryStore<Config extends StrObject> implements Store<Config> {\n private frankieClientRef;\n private contextSetter;\n private context: Context<Config>;\n constructor(config: Config, frankieClient: FrankieApiClient) {\n // this constructor will be called on every render\n // constructor functions are just syntatic sugar for regular functions, so there's no performance hit for doing this\n // initialise context as reactive state and save its setter for later use\n const [context, contextSetter] = useState<Context<Config>>({\n frankieClient,\n applicant: new Applicant(),\n checkResults: [],\n configuration: new ConfigurationReader(config),\n documents: [],\n supportingDocuments: [],\n });\n\n this.context = context;\n this.contextSetter = contextSetter;\n // keep frankie client as a mutable reference across different renders\n this.frankieClientRef = useRef(frankieClient);\n }\n getContext(): Readonly<Context<Config>> {\n return Object.freeze(this.context);\n }\n updateContext(newContext: Context<Config>): void {\n this.contextSetter(Object.assign({}, this.context, newContext));\n }\n getFrankieClient(): FrankieApiClient {\n return this.frankieClientRef.current;\n }\n\n initialise(o: { applicant: Partial<Applicant> }) {\n const context = this.getContext();\n const applicant = Object.assign(context.applicant, o.applicant);\n this.updateContext({ ...context, applicant });\n }\n\n private isPersisted(): boolean {\n return Boolean(this.getContext().applicant.entityId);\n }\n\n private async load() {\n if (this.isPersisted()) {\n const entityId = this.getContext().applicant.entityId!;\n const { checkSummary, applicant, documents } =\n await this.getFrankieClient().getApplicantDetails(entityId);\n const newContext = Object.assign({}, this.getContext(), {\n applicant,\n documents,\n checkResults: [...this.getContext().checkResults, checkSummary],\n });\n this.updateContext(newContext);\n } else console.log(\"Attempted to load an unpersisted entity\");\n }\n\n private update(): Promise<ICreateApplicantResponse> {\n const { applicant, documents } = this.getContext();\n return this.getFrankieClient().updateApplicant(applicant.entityId!, {\n applicant,\n documents,\n });\n }\n private create(): Promise<ICreateApplicantResponse> {\n const { applicant, documents } = this.getContext();\n return this.getFrankieClient().createApplicant({\n applicant,\n documents,\n });\n }\n\n async submitContext() {\n if (this.isPersisted()) await this.update();\n else {\n const { entityId } = await this.create();\n const context = this.getContext();\n context.applicant.entityId = entityId;\n this.updateContext(context);\n await this.load();\n }\n }\n}\n","import { Address, Applicant, countryData } from \"../models\";\nimport date from \"date-and-time\";\nimport React, { useEffect, useState } from \"react\";\nimport * as OnfidoSDK from \"onfido-sdk-ui\";\nimport { RouteObject } from \"../interfaces\";\nimport { RawComponent } from \"~/facades/POC/typeDefinitions\";\n\nexport const NameForm: RouteObject<RawComponent> = {\n component: function (props) {\n const { context, onContextUpdate, onReadyStateChange } = props;\n const { configuration: c } = context;\n\n const name = context.applicant.name;\n const nameConfig = (c as any).read(\"name\", {});\n const requiredFields = Object.entries(nameConfig)\n .filter((e: any) => Boolean(e[1]?.required))\n .map((e) => e[0]);\n\n const fields = [\"givenName\", \"middleName\", \"familyName\"] as const;\n const isReady = () => fields.every((f) => (has(f) ? Boolean(name[f]?.length) : true));\n const onNameUpdated = (f: keyof Applicant[\"name\"], v: string) => {\n Object.assign(context.applicant.name, {\n [f]: v,\n });\n onContextUpdate(context);\n onReadyStateChange(isReady());\n };\n type NameField = keyof Applicant[\"name\"];\n const has = (f: NameField) => requiredFields.includes(f);\n\n return (\n <div>\n <h2>What&apos;s your name?</h2>\n {has(\"givenName\") && (\n <TextInput\n label=\"First Name\"\n value={name.givenName ?? \"\"}\n onChange={(value) => onNameUpdated(\"givenName\", value)}\n />\n )}\n {has(\"middleName\") && (\n <TextInput\n label=\"Middle Name\"\n value={name.middleName ?? \"\"}\n onChange={(value) => onNameUpdated(\"middleName\", value)}\n />\n )}\n {has(\"familyName\") && (\n <TextInput\n label=\"Family Name\"\n value={name.familyName ?? \"\"}\n onChange={(value) => onNameUpdated(\"familyName\", value)}\n />\n )}\n <div>Your name is: {Object.values(name).filter(Boolean).join(\" \")}</div>\n </div>\n );\n },\n};\nexport const DOBForm: RouteObject<RawComponent> = {\n component: function (props) {\n const { context, onContextUpdate, onReadyStateChange } = props;\n\n const value = context.applicant.dateOfBirth;\n const contextValidFormat = dateIsValid(value);\n const parsed = dateParse(value, contextValidFormat);\n const [dd, setDay] = useState(parsed.dd);\n const [mm, setMonth] = useState(parsed.mm);\n const [yyyy, setYear] = useState(parsed.yyyy);\n\n const dobString = `${yyyy}-${mm}-${dd}`;\n const localStateValidFormat = dateIsValid(dobString);\n const age = localStateValidFormat\n ? Math.floor(\n date.subtract(new Date(Date.now()), date.parse(dobString, localStateValidFormat)).toDays()\n )\n : null;\n\n const emitValue = (v: string) => {\n context.applicant.dateOfBirth = v;\n onContextUpdate(context);\n };\n\n useEffect(() => {\n if (localStateValidFormat) {\n emitValue(dateFormat(dobString, localStateValidFormat));\n onReadyStateChange(true);\n } else {\n onReadyStateChange(false);\n }\n }, [dd, mm, yyyy]);\n return (\n <div>\n <h2>What&apos;s your date of birth?</h2>\n <TextInput label=\"Day\" onChange={setDay} value={dd} />\n <TextInput label=\"Month\" onChange={setMonth} value={mm} />\n <TextInput label=\"Year\" onChange={setYear} value={yyyy} />\n {age && <div>You are {age} days old</div>}\n </div>\n );\n },\n};\nexport const AddressForm: RouteObject<RawComponent> = {\n component: function (props) {\n const { context, onContextUpdate } = props;\n const { configuration: c } = context;\n\n // Only handles residential 1 for now\n const addressType = \"RESIDENTIAL1\";\n const findAddress = (a: Address) => a.addressType === addressType;\n\n const resolveAddressAndIndex = () => {\n const index = context.applicant.addresses.findIndex(findAddress);\n if (index === -1) {\n const address = new Address();\n address.addressType = addressType;\n return { index: 0, address };\n } else {\n return {\n index,\n address: context.applicant.addresses[index],\n };\n }\n };\n\n // it really starts here <---\n\n const { index, address } = resolveAddressAndIndex();\n\n const acceptedCountries = (c.read(\"addresses\", {}) as any).acceptedCountries ?? \"ALL\";\n const countryItems = resolveAcceptedCountries(acceptedCountries);\n\n const [country, setCountry] = useState<string | null>(address.country);\n const [streetNumber, setStreetNumber] = useState<string | null>(address.streetNumber);\n const [streetName, setStreetName] = useState<string | null>(address.streetName);\n const [postalCode, setPostalCode] = useState<string | null>(address.postalCode);\n const [state, setState] = useState<string | null>(address.state);\n const [suburb, setSuburb] = useState<string | null>(address.suburb);\n\n const emitValue = () => {\n Object.assign(address, {\n country,\n streetNumber,\n streetName,\n postalCode,\n state,\n suburb,\n });\n context.applicant.addresses.splice(index, 1, address);\n onContextUpdate(context);\n if (address.isIncomplete) props.onReadyStateChange(false);\n else props.onReadyStateChange(true);\n };\n useEffect(emitValue, [country, streetNumber, streetName, postalCode, state, suburb]);\n return (\n <div>\n <h2>What&apos;s your address?</h2>\n <Dropdown\n label=\"Country\"\n options={countryItems}\n value={country ?? \"\"}\n onChange={setCountry}\n />\n <TextInput label=\"State (Abbr.)\" onChange={setState} value={state ?? \"\"} />\n <TextInput label=\"Suburb\" onChange={setSuburb} value={suburb ?? \"\"} />\n <TextInput label=\"Street Number\" onChange={setStreetNumber} value={streetNumber ?? \"\"} />\n <TextInput label=\"Street Name\" onChange={setStreetName} value={streetName ?? \"\"} />\n <TextInput label=\"Postal code\" onChange={setPostalCode} value={postalCode ?? \"\"} />\n </div>\n );\n },\n};\n\nexport const ReviewPage: RouteObject<RawComponent> = {\n component: function (props) {\n const { context } = props;\n useEffect(() => void props.onReadyStateChange(true));\n\n return (\n <div style={{ textAlign: \"left\" }}>\n <h2>Confirm your data</h2>\n <h3>Personal</h3>\n <div\n dangerouslySetInnerHTML={{\n __html: nl2br(JSON.stringify(context.applicant, null, 4)),\n }}\n />\n <h3>Id Documents</h3>\n <div\n dangerouslySetInnerHTML={{\n __html: nl2br(JSON.stringify(context.documents, null, 4)),\n }}\n />\n </div>\n );\n },\n};\nexport const SuccessScreen: RouteObject<RawComponent> = {\n component: function (props) {\n const { context } = props;\n const [checkResult] = context.checkResults.slice(-1);\n const result = checkResult.status.label;\n return (\n <div\n style={{\n background: \"lightgreen\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <h1>Congrats, {context.applicant.name.givenName}, you&apos;re done!</h1>\n <h2>&lt;{result}&gt;</h2>\n </div>\n );\n },\n};\n\nconst onfidoToken = \"onfido-jwt\";\nconst onfidoContainerId = \"onfido-sdk-wrapper\";\n\nexport const IDVScreen: RouteObject<RawComponent> = {\n component: function (props) {\n const [isLoading, setIsLoading] = useState(true);\n useEffect(() => {\n void (async function () {\n const { entityId } = props.context.applicant;\n if (!entityId)\n console.error(\n \"No entity id was found. Was applicant already persisted? Initialising Onfido in sandbox mode.\"\n );\n const idvClient = props.context.frankieClient.getClient(\"externalIdv\");\n const idvServiceOptions: [string, object?] = entityId\n ? [entityId]\n : [\"\", { noService: true }];\n const { token } = await idvClient.getIdvToken(...idvServiceOptions);\n if (onfidoToken)\n OnfidoSDK.init({\n token,\n containerId: onfidoContainerId,\n });\n setIsLoading(false);\n })();\n }, []);\n\n return (\n <div id={onfidoContainerId}>\n {isLoading && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n margin: \"0 auto\",\n border: \"1px solid black\",\n width: \"512px\",\n height: \"600px\",\n textAlign: \"center\",\n borderRadius: \"5px\",\n }}\n >\n Loading...\n </div>\n )}\n </div>\n );\n },\n hideNextButton: true,\n};\n\nfunction Dropdown<T extends string>(\n props: Omit<React.HTMLProps<HTMLSelectElement>, \"onChange\"> & {\n onChange(v: T): void;\n label?: string;\n options: Item<T>[];\n }\n) {\n return (\n <div\n style={{\n position: \"relative\",\n margin: \"20px 0\",\n paddingTop: \"10px\",\n border: \"1px solid black\",\n borderTopLeftRadius: \"5px\",\n }}\n >\n <label\n style={{\n fontSize: \"12px\",\n position: \"absolute\",\n display: \"block\",\n padding: \"2px 5px\",\n top: \"-.6em\",\n left: \"5px\",\n backgroundColor: \"white\",\n }}\n >\n {props.label}\n </label>\n <select\n style={{\n outline: \"none\",\n border: \"none\",\n height: \"30px\",\n width: \"100%\",\n padding: \"5px\",\n }}\n {...props}\n onChange={(e) => props.onChange((e.target as HTMLSelectElement).value as T)}\n >\n <option disabled value=\"\">\n Select\n </option>\n {props.options.map(({ label, value }) => (\n <option key={value} value={value}>\n {label}\n </option>\n ))}\n </select>\n </div>\n );\n}\nfunction TextInput(\n props: Omit<React.HTMLProps<HTMLInputElement>, \"onChange\"> & {\n onChange(v: string): void;\n label?: string;\n }\n) {\n return (\n <div\n style={{\n position: \"relative\",\n margin: \"20px 0\",\n paddingTop: \"10px\",\n border: \"1px solid black\",\n borderTopLeftRadius: \"5px\",\n }}\n >\n <label\n style={{\n fontSize: \"12px\",\n position: \"absolute\",\n display: \"block\",\n padding: \"2px 5px\",\n top: \"-.6em\",\n left: \"5px\",\n backgroundColor: \"white\",\n }}\n >\n {props.label}\n </label>\n <input\n style={{\n outline: \"none\",\n border: \"none\",\n height: \"30px\",\n width: \"100%\",\n padding: \"5px\",\n }}\n {...props}\n value={props.value}\n onChange={(e) => props.onChange((e.target as HTMLInputElement).value)}\n />\n </div>\n );\n}\n\nfunction nl2br(str: string) {\n if (typeof str === \"undefined\" || str === null) {\n return \"\";\n }\n const breakTag = \"<br>\";\n const htmlSpc = \"&emsp;\";\n const addSpaces = (str: string) => (str + \"\").replace(/\\s/g, htmlSpc);\n const wrapDiv = (line: string, i: number, { length: l }: Array<any>) => `\n <div style=\"padding: 2px; background: ${i % 2 === 0 ? \"#f7f7f7\" : \"#efefef\"}\">\n <span style='font-size: 10px'>${i === 0 || i === l - 1 ? htmlSpc : i}</span>\n <span>${line}</span>\n </div>`;\n str = (str + \"\").replace(/([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g, \"$1\" + breakTag + \"$2\");\n str = str.split(breakTag).map(addSpaces).map(wrapDiv).join(\"\");\n return str;\n}\n\ntype Item<T> = { label: string; value: T };\nfunction resolveAcceptedCountries(config?: \"ALL\" | string[]): Item<string>[] {\n const mappedAllChar3Countries: Item<string>[] = countryData.map((data: any) => ({\n label: data.name,\n value: data.alpha3Code,\n }));\n if (!config || config === \"ALL\") return mappedAllChar3Countries;\n else return mappedAllChar3Countries.filter((data) => config.includes(data.value));\n}\nconst dateFormats = [\"YYYY-MM-DD\", \"YYYY-MM-D\", \"YYYY-M-DD\", \"YYYY-M-D\"];\nconst dateIsValid = (v?: string | null) => {\n if (!v) return null;\n return dateFormats.find((f) => date.isValid(v, f)) ?? null;\n};\nconst dateParse = (\n v: string | null,\n format: string | null\n): { dd: string; mm: string; yyyy: string } => {\n const empty = { dd: \"\", mm: \"\", yyyy: \"\" };\n if (!v || !format) return empty;\n const validFormat = dateIsValid(v);\n if (!validFormat) return empty;\n const parsed = date.parse(v, validFormat);\n return {\n yyyy: parsed.getFullYear() + \"\",\n mm: parsed.getMonth() + \"\",\n dd: parsed.getDate() + \"\",\n };\n};\nconst dateFormat = (v: string, inFormat: string) => {\n const obj = date.parse(v, inFormat);\n return date.format(obj, dateFormats[0]);\n};\n","import React, { useEffect, useState } from \"react\";\nimport { RouteComponentResolution } from \"../../modules/router/common/routing\";\nimport { RawComponent, RouteName, WrappedComponent } from \"./typeDefinitions\";\nimport { Config } from \"./typeDefinitions\";\n\nexport const wrapReactComponent: RouteComponentResolution<\n RouteName,\n RawComponent,\n Config,\n WrappedComponent\n> = ({ routeDictionary, routeName }) => {\n /**\n * This function will\n * 1) take a route object, which in this POC is a react component,\n * 2) will wrap it with the widget's \"frame\"\n */\n const routeObjectWrapper = routeDictionary[routeName];\n\n return function Component({\n onNextRequested,\n onContextUpdate,\n context,\n }: {\n onNextRequested: () => void;\n onContextUpdate: any;\n context: any;\n }) {\n const [isReady, setIsReady] = useState(false);\n const { isIdle, setNextRequested } = useNextRequested(onNextRequested);\n\n const routeComponentProps = {\n onContextUpdate,\n onNextRequested: setNextRequested,\n onReadyStateChange: setIsReady,\n context,\n };\n const nextComponentProps = {\n disabled: !isReady || isIdle,\n onClick: setNextRequested,\n };\n\n const ViewComponent = routeObjectWrapper?.component ?? null;\n\n const components: ReturnType<typeof React.createElement>[] = [\n React.createElement(ViewComponent, routeComponentProps, null),\n ];\n if (!routeObjectWrapper.hideNextButton) components.push(NextButton(nextComponentProps));\n\n return React.createElement(\n \"div\",\n {\n className: `view-root' view-${routeName}`,\n },\n ...components\n );\n };\n};\nfunction NextButton(props: { disabled: boolean; onClick: () => void }) {\n return React.createElement(\n \"button\",\n { ...props, style: { width: \"100%\", height: \"60px\", marginTop: \"20px\" } },\n \"NEXT\"\n );\n}\nfunction useNextRequested(onNextRequested: () => void) {\n const [isIdle, _setIsIdle] = useState(false);\n const [nextRequested, _setNextRequested] = useState(false);\n\n const setNextRequested = () => {\n _setIsIdle(true);\n _setNextRequested(true);\n };\n\n useEffect(() => {\n if (nextRequested) onNextRequested();\n }, [nextRequested]);\n return {\n setNextRequested,\n isIdle,\n };\n}\n","export const env2url = (env: \"development\" | \"local\" | \"production\" | \"uat\" | \"demo\" | \"qa\") => {\n switch (env.toLowerCase()) {\n case \"latest\":\n case \"development\":\n case \"dev\":\n return \"https://backend.latest.frankiefinancial.io\";\n case \"qa\":\n case \"staging3\":\n return \"https://backend.staging3.latest.frankiefinancial.io\";\n case \"demo\":\n return \"https://backend.demo.frankiefinancial.io\";\n case \"uat\":\n return \"https://backend.kycaml.uat.frankiefinancial.io\";\n case \"prod\":\n case \"production\":\n return `https://backend.kycaml.frankiefinancial.io`;\n default:\n return `https://backend.${env}.latest.frankiefinancial.io`;\n }\n};\n","import { Context } from \"../../interfaces\";\nimport { Address, DeepPartial } from \"../../models\";\nimport { RouteNameResolution } from \"../../modules/router/common/routing\";\nimport { Config, RouteName } from \"./typeDefinitions\";\n\nexport const proceduralDictionaryRouting: RouteNameResolution<RouteName, Config> = (\n o\n): RouteName | null => {\n const { checkOrder, context, routeHistory } = o;\n /**\n * THIS COULD BE REPLACED WITH A STATE MACHINE\n * getNextRouteName takes context and returns the next route to be displayed out of a dictionary of routes\n * it may use holistics such as \"which fields are extracted by each specific route object\" to decide which route to display\n * here each route maps directly to a single field, so this function simply checks if fields are missing (criteria defiend in \"checkers\" below)\n * the order of checks is defined in the \"checkOrder\" array, which defines the order of screens\n * the review page is displayed if no data is missing\n */\n const [lastRoute] = routeHistory.slice(-1);\n // if last route was \"review\", indicate start of \"loop\", which will trigger a context update\n if (lastRoute === \"review\") return null;\n // if last rouet is null (start of loop), it means context was already updated and last check result is new\n if (lastRoute === null) {\n // get lst check result\n // const [lastCheckSummary] = context.checkResults.slice(-1);\n // do stuff with check result\n // return next screen for that check result\n return \"idv\";\n }\n if (lastRoute === \"idv\") {\n return \"success\";\n }\n\n // if nothing is missing, go to review\n // if checker is missing for a route, always display that route\n\n return checkOrder.find((name) => shouldDisplayRoute(name, context)) ?? \"review\";\n};\n\nfunction shouldDisplayRoute(\n routeName: RouteName,\n { applicant, configuration: c }: Context<Config>\n): boolean {\n // returns true if route should be displayed\n const checkers: Partial<Record<RouteName, () => boolean>> = {\n // idDocument: () => {\n // // if none of id_docs.idType is present in documents, then idDocument isnt complete\n // const idDocTypes = c.read<DocumentType[]>(\"id_docs.acceptedIdTypes\", []);\n // const hasAnyOfTheDocTypes = documents.some(d => idDocTypes.includes(d.idType as DocumentType));\n // return hasAnyOfTheDocTypes;\n // },\n name: () => {\n // if a field is true in name.{field}, then it's required\n // if a field is not mentioned, it doesn't matter if it's present or not\n const allNameFields = [\"givenName\", \"middleName\", \"familyName\"] as const;\n const requiredFields = allNameFields.filter((f) =>\n c.read<boolean>(`name.${f}.required` as any, false)\n );\n // if any of the required fields is missing, display name screen\n return requiredFields.some((f) => !applicant.name[f]);\n },\n dateOfBirth: () => {\n // if dateOfBirth is present, then it's required\n const isDateOfBirthRequired = c.read<boolean>(\"dateOfBirth.required\" as any, false);\n return isDateOfBirthRequired && !applicant.dateOfBirth;\n },\n address: () => {\n // if addresses is not present, then it's not required\n // otherwise, address is missing if no address in the list is both from required countries and required types\n type AddressTypesDictionary = DeepPartial<{\n addressType: {\n [k in Exclude<Address[\"addressType\"], null | undefined>]: {\n required: boolean;\n };\n };\n }>;\n const addressConfig = c.read<AddressTypesDictionary>(\"addresses\", {});\n const requiredAddressTypes = Object.entries(addressConfig.addressType ?? [])\n .filter((e) => Boolean(e[1]?.required))\n .map((e) => e[0]) as Address[\"addressType\"][];\n const requiredAddressCountries = c.read<Address[\"country\"][]>(\n \"addresses.acceptedCountries\" as any,\n []\n ) as Address[\"country\"][];\n\n return !applicant.addresses.some(\n (a) =>\n requiredAddressTypes.includes(a.addressType) &&\n requiredAddressCountries.includes(a.country)\n );\n },\n };\n\n const checker = checkers[routeName] ?? (() => true);\n return checker();\n}\n","import { FrankieApiClient } from \"../../api\";\nimport { Profile } from \"../../models\";\nimport React, { useEffect } from \"react\";\nimport ReactDictionaryRouter from \"../../modules/router/ReactDictionaryRouter\";\nimport ReactInMemoryStore from \"../../modules/store/ReactInMemoryStore\";\nimport { Context } from \"../../interfaces\";\nimport { Config, RawComponent, RouteName, WrappedComponent } from \"./typeDefinitions\";\nimport {\n AddressForm,\n DOBForm,\n IDVScreen,\n NameForm,\n ReviewPage,\n SuccessScreen,\n} from \"../../uiComponents/reactWeb\";\nimport { wrapReactComponent } from \"./viewWrapper\";\nimport { env2url } from \"~/utils/env2Url\";\nimport { RouteDictionary } from \"~/modules/router/common/routing\";\nimport { proceduralDictionaryRouting } from \"./routing\";\n\nexport type Props = {\n token: string;\n recipe: string;\n environment?: \"development\" | \"local\" | \"production\" | \"uat\" | \"demo\" | \"qa\";\n};\nexport default function Component({ token, recipe, environment = \"production\" }: Props) {\n // initialise frankie client with the provided token\n const BFF_URL = env2url(environment);\n const frankieClient = new FrankieApiClient(BFF_URL);\n frankieClient.setToken(token);\n // This configuration would be generated as a combination of recipe configuration and manual configuration (aka \"widget configuration\")\n // the \"widget configuration\" will be created in some admin page\n const configuration: Config = {\n \"name.givenName\": { required: true },\n \"name.familyName\": { required: true },\n dateOfBirth: { required: true },\n addresses: { acceptedCountries: [\"AUS\", \"NZL\"] },\n \"addresses.addressType.RESIDENTIAL1\": { required: true },\n };\n // The store will be initialised with that configuration\n // The store implements how/where data is stored and provides context to the rest of the widget\n const store = new ReactInMemoryStore(configuration, frankieClient);\n // The \"Dictionary Router\" here is initialised with a dictionary of routes that match the type that Mounter expects\n // It takes as parameters\n // - Store, so it can make route decisions based on context\n // - A dictionary of routes, mapping \"route names\" to UI Components. The route names are pre defined within the Router itself.\n // - A \"route resolution\" function, which takes context and decides what the next route name is\n // - An optional \"UI Component resolution\" function, which will wrap components with a \"frame\" containing the \"next\" button and potentially a progress bar, etc\n // - - this last one would also allow us to intercept changes to Context based on factors external to the ui component itself, such as \"is in a loop\" or \"is currently busy making http requests\" (making the whole screen idle, for example)\n // The route dictionary, the route resolution function and the ui component resolution function can all be extracted to server side\n const routeDictionary: RouteDictionary<RouteName, RawComponent> = {\n name: NameForm,\n dateOfBirth: DOBForm,\n address: AddressForm,\n review: ReviewPage,\n success: SuccessScreen,\n idv: IDVScreen,\n };\n const router = new ReactDictionaryRouter({\n store,\n routeDictionary,\n routeOrder: [\"name\", \"dateOfBirth\", \"address\", \"review\", \"idv\"],\n routeNameResolution: proceduralDictionaryRouting,\n routeComponentResolution: wrapReactComponent,\n });\n\n ////\n\n const RouteComponent: WrappedComponent | null = router.getCurrentRoute();\n const context = store.getContext();\n\n const nextRoute = () => void router.getNextRoute();\n const updateContext = (c: Context<Config>) => store.updateContext(c);\n const initialise = () => {\n // initialise can preload existing applicant details\n store.initialise({\n applicant: {\n profile: new Profile(recipe, \"electronic\"),\n consents: [\"general\", \"docs\", \"creditheader\"], // since I haven't implemented consent capture in the ui, I'm hard coding it here\n },\n });\n nextRoute();\n };\n useEffect(initialise, []);\n\n if (!RouteComponent) return null;\n return React.createElement(RouteComponent, {\n context,\n onContextUpdate: updateContext,\n onNextRequested: nextRoute,\n });\n}\n","console.log(\"test only\");\n\n/**\n * WEB SDK Entrypoint\n */\nimport webWidgetPOC1 from \"./facades/POC/webEntry\";\nimport reactComponentPOC2 from \"./facades/POC/reactComponent\";\n\nconst reactComponent = reactComponentPOC2;\n\nconst initialiseWebWidget = webWidgetPOC1;\n\n// or export as modules\nexport { reactComponent, initialiseWebWidget };\nexport * from \"./api\";\nexport * from \"./models\";\nexport { env2url } from \"./utils/env2Url\";\n\n// all the different \"exposure\" methods (two of which were done above) will be done automatically by webpack once it's configured appropriately\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport ReactComponent, { Props } from \"./reactComponent\";\n\ntype PublicOptions = {\n mountElement: HTMLDivElement;\n} & Props;\nexport default function ({ mountElement, ...props }: PublicOptions) {\n ReactDOM.render(React.createElement(ReactComponent, props, null), mountElement);\n}\n"],"names":["ConfigurationReader","original","parsedConfiguration","this","dot","object","read","path","fallback","pick","Object","assign","options","defaultOptions","disallowedTagsMode","dirty","sanitizeHtml","defaults","Address","a","buildingName","postalCode","state","streetNumber","streetType","suburb","town","unitNumber","addressType","_streetName","country","addressId","data","isAddedByCustomer","streetName","toLowerCase","hasExplicitLongForm","Boolean","longForm","clone","payload","toJSON","fromJSON","addressFields","keys","filter","i","includes","every","field","_this","newAddress","name","address","isEmpty","requireList","some","f","isEmptyAddress","isIncomplete","stateName","code3","allAustralianStates","find","s","alpha3Code","label","getAustralianStateDetails","_getAustralianStateDe2","countryName","allCountries","c","getCountryDetails","_getCountryDetails","join","value","addressTypeSorter","b","getPoints","t","type","match","parseInt","Infinity","Profile","profileType","kycMethod","countryAlpha3","dob","configOrCheckType","config","_hadcodedCheckTypes","initialiseConfigOrCheckType","theProfileType","Array","isArray","checkTypes","defaultProfileType","get","setConfiguration","getConfiguration","isUnder18","moment","diff","typeKey","ageKey","foundTypesAsString","map","flat","split","getProfileType","isManualKyc","kycTypes","finalTypes","nonKycConfiguration","Applicant","entityId","customerReference","givenName","middleName","familyName","displayName","dateOfBirth","gender","extraData","phoneNumber","documentId","idNumber","addresses","email","profile","assignee","consents","blocklistAttributes","originalUboDetails","_a$name3","sortAddressArray","_a$originalUboDetails6","_a$originalUboDetails7","getAddress","needle","isCompareAVariant","compare","JSON","parse","stringify","addressMap","m","current","previous","given","family","middle","slice","length","fullName","home_country_givenname","home_country_familyname","list","sort","STATE_TYPES","Document","d","idType","verified","electronic","manual","idSubType","region","idExpiry","scans","validation","isValid","validationReport","MOBILE_PHONE","format","isNewDocument","getUploadedScanUuids","sc","fileUploadUuid","includeUploadFile","uploadUuid","findIndex","docScan","document","forEach","key","v","Scan","scan","scanId","file","mimeType","side","scanCreated","scanName","DocumentType","DocumentStatus","numericOrNull","isNaN","booleanOrNull","CheckSummary","addrs","checkDate","personalChecks","status","risk","alertList","blocklistPotentialMatches","duplicatePotentialMatches","duplicateBlocklistMatches","checkCounts","issues","checkResults","rulesetsMatches","chineseName","visitor","visit","entries","reduce","carry","visitObjectWith","frontend","PASSED","NEEDS_ATTENTION","FAILED","WAITING_ON_CUSTOMER","MANUAL_FAILED","MANUAL_PASSED","ARCHIVED","INACTIVE","UNCHECKED","mapBackendStatus","level","class","ALLOWED_MIME_TYPES","ChannelString","ALLOWED_MIME_TYPES_STRING","SupportingDocument","id","OTHER","modified","reviewed","refer","smartUiDocOrder","Organisation","parentId","customerId","customerChildId","nickName","authType","isRoot","denyOldPasswordCount","timezone","parent","children","users","organisations","o","instance","_payload$organisation2","p","_payload$children","isMachineCredential","cred","apiKey","rest","ExternalIdvClient","getIdvToken","noService","post","smsContent","smsPhoneNumber","referrer","params","undefined","initiateIdvProcess","getApplicantDetails","token","applicant","documents","checkSummary","FrankieApiClient","baseUrl","channel","credentials","Axios","create","baseURL","headers","interceptors","response","use","setToken","login","permissions","_this3","isMachine","authorization","serialiseCredentials","organisationData","organisation","configurationData","configuration","createApplicant","queryParameters","supportingDocuments","noAddress","dataConsent","consent","no_address","updateApplicant","put","triggerChecks","fetchDetails","_this9","search","details","username","password","Buffer","from","toString","checkValidity","_this15","organisationPayload","getClient","which","url","found","header","getNextRoute","router","context","getStore","getContext","routeHistory","getRouteHistory","routeDictionary","getRouteDictionary","currentRouteName","nextRouteName","resolveRouteName","checkOrder","getRouteOrder","pushRouteToHistory","console","log","submitContext","resolveRouteComponent","routeName","defaultRouteComponentResolution","defaultRouteNameResolution","ReactDictionaryRouter","store","routeOrder","routeComponentResolution","routeNameResolution","currentComponent","routeComponentSetter","routeHistoryRef","storeRef","useState","wrappedComponentSetter","useRef","getCurrentRoute","findNextRoute","n","push","_this2","routeComponent","ReactInMemoryStore","frankieClient","frankieClientRef","contextSetter","freeze","updateContext","newContext","getFrankieClient","initialise","isPersisted","load","update","_this4","NameForm","component","props","onContextUpdate","onReadyStateChange","nameConfig","requiredFields","e","_e$","required","fields","onNameUpdated","has","_name$f","React","TextInput","onChange","values","DOBForm","contextValidFormat","dateIsValid","parsed","dateParse","dd","setDay","mm","setMonth","yyyy","setYear","dobString","localStateValidFormat","age","Math","floor","date","subtract","Date","now","toDays","useEffect","dateFormat","AddressForm","mappedAllChar3Countries","findAddress","index","resolveAddressAndIndex","acceptedCountries","countryItems","countryData","setCountry","setStreetNumber","setStreetName","setPostalCode","setState","setSuburb","splice","Dropdown","ReviewPage","style","textAlign","dangerouslySetInnerHTML","__html","nl2br","SuccessScreen","result","background","display","flexDirection","justifyContent","alignItems","onfidoContainerId","IDVScreen","isLoading","setIsLoading","error","idvClient","OnfidoSDK","init","containerId","margin","border","width","height","borderRadius","hideNextButton","position","paddingTop","borderTopLeftRadius","fontSize","padding","top","left","backgroundColor","outline","target","disabled","str","htmlSpc","replace","line","dateFormats","empty","validFormat","getFullYear","getMonth","getDate","inFormat","obj","wrapReactComponent","routeObjectWrapper","onNextRequested","isReady","setIsReady","isIdle","_setIsIdle","nextRequested","_setNextRequested","setNextRequested","useNextRequested","nextComponentProps","onClick","ViewComponent","components","createElement","marginTop","className","env2url","env","proceduralDictionaryRouting","lastRoute","addressConfig","requiredAddressTypes","requiredAddressCountries","Component","recipe","environment","BFF_URL","review","success","idv","RouteComponent","nextRoute","reactComponent","reactComponentPOC2","action","order","rulesetMatchFields","mountElement","ReactDOM","render","ReactComponent"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { IApplicantDetails, ICreateIDVTokenResponse } from "../models";
2
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
3
+ export declare class ExternalIdvClient {
4
+ private instance;
5
+ constructor(instance: AxiosInstance);
6
+ getIdvToken(entityId: string, config?: {
7
+ smsContent?: string;
8
+ smsPhoneNumber?: string;
9
+ referrer?: string;
10
+ noService?: boolean;
11
+ }): Promise<ICreateIDVTokenResponse>;
12
+ initiateIdvProcess(entityId: string): Promise<void>;
13
+ getApplicantDetails(token: string): Promise<IApplicantDetails>;
14
+ get<T = any, R = AxiosResponse<T>>(...params: GetParameters): Promise<R>;
15
+ post<T = any, R = AxiosResponse<T>>(...params: PostParameters): Promise<R>;
16
+ }
17
+ declare type PostParameters = [string, any?, AxiosRequestConfig?];
18
+ declare type GetParameters = [string, AxiosRequestConfig?];
19
+ export {};
@@ -0,0 +1,54 @@
1
+ import { ExternalIdvClient } from "./ExternalIdvClient";
2
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
3
+ import { ConfigurationReader, Organisation, Admin, DeepPartial, IApplicantDetails, IApplicantInformation, ICreateApplicantResponse, IFrankieClientCredentials, ITriggerChecksResponse, SearchOptions, User } from "../models";
4
+ declare type AxiosComponentsInFrankieApiClient = "interceptors" | "get" | "delete" | "post" | "put" | "defaults";
5
+ export declare type LoginResponse<Config> = {
6
+ organisation: Organisation;
7
+ configuration: ConfigurationReader<Config>;
8
+ user?: User;
9
+ permissions?: string[];
10
+ };
11
+ declare type PermissionPresetName = "smart-ui";
12
+ declare type PermissionPresetObject = {
13
+ preset: PermissionPresetName;
14
+ } & {
15
+ preset: "smart-ui";
16
+ reference?: string;
17
+ };
18
+ declare type TLoginOptions = {
19
+ referrer?: string | null;
20
+ permissions?: string[] | PermissionPresetName | PermissionPresetObject;
21
+ };
22
+ declare type UpdateApplicantQueryParameters = {
23
+ noAddress: boolean;
24
+ dataConsent: boolean;
25
+ };
26
+ export declare type IChannel = "portal" | "smart-ui" | "support-portal" | "unknown" | Admin["enumChannel"];
27
+ export declare class FrankieApiClient implements Pick<AxiosInstance, AxiosComponentsInFrankieApiClient> {
28
+ private instance;
29
+ private credentials;
30
+ constructor(baseUrl: string, channel?: IChannel);
31
+ get isMachine(): boolean;
32
+ get interceptors(): AxiosInstance["interceptors"];
33
+ get defaults(): AxiosInstance["defaults"];
34
+ login<Config>(credentials: IFrankieClientCredentials, options?: TLoginOptions): Promise<LoginResponse<Config>>;
35
+ createApplicant({ applicant, documents, supportingDocuments }: IApplicantInformation, queryParameters?: DeepPartial<UpdateApplicantQueryParameters>): Promise<ICreateApplicantResponse>;
36
+ updateApplicant(entityId: string, { applicant, documents, supportingDocuments }: IApplicantInformation, queryParameters?: DeepPartial<UpdateApplicantQueryParameters>): Promise<ICreateApplicantResponse>;
37
+ triggerChecks(entityId: string, config?: {
38
+ fetchDetails?: boolean;
39
+ manualKyc?: boolean;
40
+ }): Promise<ITriggerChecksResponse | IApplicantDetails>;
41
+ getApplicantDetails(entityId: string): Promise<IApplicantDetails>;
42
+ search(details: Partial<SearchOptions>): Promise<IApplicantInformation>;
43
+ serialiseCredentials(credentials: IFrankieClientCredentials): string;
44
+ get frankieToken(): string | null;
45
+ setToken<Config>(token: string, options?: {
46
+ checkValidity?: boolean;
47
+ }): Promise<LoginResponse<Config> | null>;
48
+ getClient(w: "externalIdv"): ExternalIdvClient;
49
+ get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig | undefined): Promise<R>;
50
+ delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig | undefined): Promise<R>;
51
+ post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig | undefined): Promise<R>;
52
+ put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig | undefined): Promise<R>;
53
+ }
54
+ export {};
@@ -0,0 +1 @@
1
+ export * from "./FrankieApiClient";