@codedartdev/coinsentry-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -0
- package/dist/brand/config.d.ts +78 -0
- package/dist/brand/config.d.ts.map +1 -0
- package/dist/brand/config.js +274 -0
- package/dist/brand/config.js.map +1 -0
- package/dist/brand/index.d.ts +4 -0
- package/dist/brand/index.d.ts.map +1 -0
- package/dist/brand/index.js +2 -0
- package/dist/brand/index.js.map +1 -0
- package/dist/brand/types.d.ts +122 -0
- package/dist/brand/types.d.ts.map +1 -0
- package/dist/brand/types.js +2 -0
- package/dist/brand/types.js.map +1 -0
- package/dist/client.d.ts +169 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +239 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +143 -0
- package/dist/errors.js.map +1 -0
- package/dist/guards.d.ts +12 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +76 -0
- package/dist/guards.js.map +1 -0
- package/dist/http.d.ts +38 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +175 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/kyc/config.d.ts +20 -0
- package/dist/kyc/config.d.ts.map +1 -0
- package/dist/kyc/config.js +224 -0
- package/dist/kyc/config.js.map +1 -0
- package/dist/kyc/flow.d.ts +37 -0
- package/dist/kyc/flow.d.ts.map +1 -0
- package/dist/kyc/flow.js +329 -0
- package/dist/kyc/flow.js.map +1 -0
- package/dist/kyc/index.d.ts +6 -0
- package/dist/kyc/index.d.ts.map +1 -0
- package/dist/kyc/index.js +4 -0
- package/dist/kyc/index.js.map +1 -0
- package/dist/kyc/locale.d.ts +17 -0
- package/dist/kyc/locale.d.ts.map +1 -0
- package/dist/kyc/locale.js +40 -0
- package/dist/kyc/locale.js.map +1 -0
- package/dist/kyc/types.d.ts +289 -0
- package/dist/kyc/types.d.ts.map +1 -0
- package/dist/kyc/types.js +2 -0
- package/dist/kyc/types.js.map +1 -0
- package/dist/products.d.ts +280 -0
- package/dist/products.d.ts.map +1 -0
- package/dist/products.js +302 -0
- package/dist/products.js.map +1 -0
- package/dist/realtime.d.ts +33 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +28 -0
- package/dist/realtime.js.map +1 -0
- package/dist/types.d.ts +145 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
export function normalizeStringList(value) {
|
|
2
|
+
if (Array.isArray(value)) {
|
|
3
|
+
return value.flatMap((item) => normalizeStringList(item));
|
|
4
|
+
}
|
|
5
|
+
if (typeof value === 'string') {
|
|
6
|
+
return value
|
|
7
|
+
.split(',')
|
|
8
|
+
.map((item) => item.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
}
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
export function normalizeClientFlowStep(step) {
|
|
14
|
+
return {
|
|
15
|
+
...step,
|
|
16
|
+
required_fields: normalizeStringList(step.required_fields),
|
|
17
|
+
required_documents: normalizeStringList(step.required_documents),
|
|
18
|
+
entity_types: normalizeStringList(step.entity_types),
|
|
19
|
+
document_type_options: normalizeStringList(step.document_type_options),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function normalizeClientFlow(value) {
|
|
23
|
+
if (!Array.isArray(value))
|
|
24
|
+
return [];
|
|
25
|
+
return value
|
|
26
|
+
.filter((step) => Boolean(step && typeof step === 'object'))
|
|
27
|
+
.map(normalizeClientFlowStep);
|
|
28
|
+
}
|
|
29
|
+
export function normalizeDocumentTypeChoices(value) {
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
return value.flatMap((item) => {
|
|
32
|
+
if (item && typeof item === 'object') {
|
|
33
|
+
const record = item;
|
|
34
|
+
const optionValue = String(record.value ?? '').trim();
|
|
35
|
+
if (!optionValue)
|
|
36
|
+
return [];
|
|
37
|
+
return [{
|
|
38
|
+
value: optionValue,
|
|
39
|
+
label: String(record.label ?? optionValue).trim() || optionValue,
|
|
40
|
+
}];
|
|
41
|
+
}
|
|
42
|
+
if (typeof item === 'string') {
|
|
43
|
+
const optionValue = item.trim();
|
|
44
|
+
return optionValue ? [{ value: optionValue, label: optionValue }] : [];
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return normalizeStringList(value).map((optionValue) => ({
|
|
50
|
+
value: optionValue,
|
|
51
|
+
label: optionValue,
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
export function uniqueDocumentChoices(choices) {
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
return choices.filter((choice) => {
|
|
57
|
+
const value = choice.value.trim();
|
|
58
|
+
if (!value || seen.has(value))
|
|
59
|
+
return false;
|
|
60
|
+
seen.add(value);
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function getKycPrefill(requirements) {
|
|
65
|
+
if (!requirements)
|
|
66
|
+
return {};
|
|
67
|
+
const kycForm = requirements.kyc_form;
|
|
68
|
+
if (kycForm?.prefill && typeof kycForm.prefill === 'object')
|
|
69
|
+
return kycForm.prefill;
|
|
70
|
+
if (requirements.form_prefill && typeof requirements.form_prefill === 'object')
|
|
71
|
+
return requirements.form_prefill;
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
function uniqueStrings(values) {
|
|
75
|
+
return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
|
|
76
|
+
}
|
|
77
|
+
function normalizeFieldName(value) {
|
|
78
|
+
return value.trim().toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
function recordValue(value) {
|
|
81
|
+
return value && typeof value === 'object' ? value : {};
|
|
82
|
+
}
|
|
83
|
+
const PREFILL_FIELD_ALIASES = {
|
|
84
|
+
birth_date: ['birth_date', 'date_of_birth'],
|
|
85
|
+
date_of_birth: ['date_of_birth', 'birth_date'],
|
|
86
|
+
document_number: ['document_number', 'tax_id'],
|
|
87
|
+
tax_id: ['tax_id', 'document_number'],
|
|
88
|
+
};
|
|
89
|
+
const STRONG_READ_ONLY_LIST_KEYS = [
|
|
90
|
+
'locked_fields',
|
|
91
|
+
'strong_read_only_fields',
|
|
92
|
+
'force_read_only_fields',
|
|
93
|
+
'forced_read_only_fields',
|
|
94
|
+
'hard_read_only_fields',
|
|
95
|
+
];
|
|
96
|
+
const STRONG_READ_ONLY_MAP_KEYS = [
|
|
97
|
+
'field_locks',
|
|
98
|
+
'read_only_locks',
|
|
99
|
+
];
|
|
100
|
+
function prefillAliasesForField(field) {
|
|
101
|
+
const normalized = normalizeFieldName(field);
|
|
102
|
+
return PREFILL_FIELD_ALIASES[normalized] ?? [normalized];
|
|
103
|
+
}
|
|
104
|
+
export function hasRealKycPrefillValue(value) {
|
|
105
|
+
if (value === null || value === undefined)
|
|
106
|
+
return false;
|
|
107
|
+
if (typeof value === 'string') {
|
|
108
|
+
const trimmed = value.trim();
|
|
109
|
+
if (!trimmed || trimmed.includes('*'))
|
|
110
|
+
return false;
|
|
111
|
+
return /[A-Za-z0-9]/.test(trimmed);
|
|
112
|
+
}
|
|
113
|
+
if (typeof value === 'number')
|
|
114
|
+
return Number.isFinite(value);
|
|
115
|
+
if (typeof value === 'boolean')
|
|
116
|
+
return true;
|
|
117
|
+
if (Array.isArray(value))
|
|
118
|
+
return value.length > 0;
|
|
119
|
+
if (typeof value === 'object')
|
|
120
|
+
return Object.keys(value).length > 0;
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
function hasRealKycPrefillForField(requirements, field) {
|
|
124
|
+
const prefill = getKycPrefill(requirements);
|
|
125
|
+
return prefillAliasesForField(field).some((alias) => hasRealKycPrefillValue(prefill[alias]));
|
|
126
|
+
}
|
|
127
|
+
export function getKycReadOnlyFields(requirements) {
|
|
128
|
+
if (!requirements)
|
|
129
|
+
return [];
|
|
130
|
+
const kycFormFields = normalizeStringList(requirements.kyc_form?.read_only_fields);
|
|
131
|
+
return uniqueStrings([
|
|
132
|
+
...kycFormFields,
|
|
133
|
+
...normalizeStringList(requirements.read_only_fields),
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
136
|
+
function getKycStrongReadOnlyFields(requirements) {
|
|
137
|
+
if (!requirements)
|
|
138
|
+
return [];
|
|
139
|
+
const kycForm = recordValue(requirements.kyc_form);
|
|
140
|
+
const topLevel = recordValue(requirements);
|
|
141
|
+
const listFields = STRONG_READ_ONLY_LIST_KEYS.flatMap((key) => [
|
|
142
|
+
...normalizeStringList(kycForm[key]),
|
|
143
|
+
...normalizeStringList(topLevel[key]),
|
|
144
|
+
]);
|
|
145
|
+
const mapFields = STRONG_READ_ONLY_MAP_KEYS.flatMap((key) => [
|
|
146
|
+
...strongReadOnlyFieldsFromMap(kycForm[key]),
|
|
147
|
+
...strongReadOnlyFieldsFromMap(topLevel[key]),
|
|
148
|
+
]);
|
|
149
|
+
return uniqueStrings([...listFields, ...mapFields]);
|
|
150
|
+
}
|
|
151
|
+
function strongReadOnlyFieldsFromMap(value) {
|
|
152
|
+
const locks = recordValue(value);
|
|
153
|
+
return Object.entries(locks).flatMap(([field, lock]) => {
|
|
154
|
+
if (lock === true)
|
|
155
|
+
return [field];
|
|
156
|
+
if (typeof lock !== 'string')
|
|
157
|
+
return [];
|
|
158
|
+
const normalized = lock.trim().toLowerCase();
|
|
159
|
+
return ['strong', 'hard', 'locked', 'force', 'forced', 'read_only'].includes(normalized)
|
|
160
|
+
? [field]
|
|
161
|
+
: [];
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
export function isKycFieldReadOnly(requirements, field) {
|
|
165
|
+
const normalizedField = normalizeFieldName(field);
|
|
166
|
+
const strongReadOnlyFields = getKycStrongReadOnlyFields(requirements).map(normalizeFieldName);
|
|
167
|
+
if (strongReadOnlyFields.includes(normalizedField))
|
|
168
|
+
return true;
|
|
169
|
+
const readOnlyFields = getKycReadOnlyFields(requirements).map(normalizeFieldName);
|
|
170
|
+
return readOnlyFields.includes(normalizedField)
|
|
171
|
+
&& hasRealKycPrefillForField(requirements, normalizedField);
|
|
172
|
+
}
|
|
173
|
+
export function shouldLockKycFiscalDocumentField(options) {
|
|
174
|
+
return options.configuredReadOnly
|
|
175
|
+
&& options.normalized.length > 0
|
|
176
|
+
&& options.isValid;
|
|
177
|
+
}
|
|
178
|
+
function getConfigClientFlow(config) {
|
|
179
|
+
const record = config && typeof config === 'object' ? config : {};
|
|
180
|
+
return [
|
|
181
|
+
...normalizeClientFlow(record.client_flow),
|
|
182
|
+
...normalizeClientFlow(record.compliance_config?.client_flow),
|
|
183
|
+
...normalizeClientFlow(record.flow_config?.compliance_config?.client_flow),
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
export function getRegistrationDocumentConfig(config) {
|
|
187
|
+
const record = config && typeof config === 'object' ? config : {};
|
|
188
|
+
const direct = record.registration_document;
|
|
189
|
+
if (direct && typeof direct === 'object') {
|
|
190
|
+
return direct;
|
|
191
|
+
}
|
|
192
|
+
const flowConfig = record.flow_config && typeof record.flow_config === 'object'
|
|
193
|
+
? record.flow_config
|
|
194
|
+
: {};
|
|
195
|
+
const nested = flowConfig.registration_document;
|
|
196
|
+
if (nested && typeof nested === 'object') {
|
|
197
|
+
return nested;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
export function getRegistrationTaxIdField(config) {
|
|
202
|
+
const field = String(getRegistrationDocumentConfig(config)?.field ?? 'tax_id').trim();
|
|
203
|
+
return field || 'tax_id';
|
|
204
|
+
}
|
|
205
|
+
export function shouldCollectRegistrationTaxId(config) {
|
|
206
|
+
const registrationDocument = getRegistrationDocumentConfig(config);
|
|
207
|
+
if (registrationDocument?.collect_tax_id === true)
|
|
208
|
+
return true;
|
|
209
|
+
return getConfigClientFlow(config).some((step) => step.screen === 'account' && step.collect_tax_id === true);
|
|
210
|
+
}
|
|
211
|
+
export function isRegistrationTaxIdRequired(config) {
|
|
212
|
+
const registrationDocument = getRegistrationDocumentConfig(config);
|
|
213
|
+
const taxIdField = getRegistrationTaxIdField(config);
|
|
214
|
+
if (registrationDocument?.collect_tax_id === true && registrationDocument.required === true) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
return getConfigClientFlow(config).some((step) => {
|
|
218
|
+
if (step.screen !== 'account')
|
|
219
|
+
return false;
|
|
220
|
+
const requiredFields = normalizeStringList(step.required_fields);
|
|
221
|
+
return requiredFields.includes(taxIdField) || requiredFields.includes('tax_id');
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/kyc/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ClientFlowStep,\n DocumentTypeChoice,\n KycRequirements,\n KycFormPrefill,\n RegistrationDocumentConfig,\n} from './types.js';\n\nexport function normalizeStringList(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.flatMap((item) => normalizeStringList(item));\n }\n\n if (typeof value === 'string') {\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n }\n\n return [];\n}\n\nexport function normalizeClientFlowStep(step: ClientFlowStep): ClientFlowStep {\n return {\n ...step,\n required_fields: normalizeStringList(step.required_fields),\n required_documents: normalizeStringList(step.required_documents),\n entity_types: normalizeStringList(step.entity_types) as ClientFlowStep['entity_types'],\n document_type_options: normalizeStringList(step.document_type_options),\n };\n}\n\nexport function normalizeClientFlow(value: unknown): ClientFlowStep[] {\n if (!Array.isArray(value)) return [];\n return value\n .filter((step): step is ClientFlowStep => Boolean(step && typeof step === 'object'))\n .map(normalizeClientFlowStep);\n}\n\nexport function normalizeDocumentTypeChoices(value: unknown): DocumentTypeChoice[] {\n if (Array.isArray(value)) {\n return value.flatMap((item) => {\n if (item && typeof item === 'object') {\n const record = item as Record<string, unknown>;\n const optionValue = String(record.value ?? '').trim();\n if (!optionValue) return [];\n return [{\n value: optionValue,\n label: String(record.label ?? optionValue).trim() || optionValue,\n }];\n }\n\n if (typeof item === 'string') {\n const optionValue = item.trim();\n return optionValue ? [{ value: optionValue, label: optionValue }] : [];\n }\n\n return [];\n });\n }\n\n return normalizeStringList(value).map((optionValue) => ({\n value: optionValue,\n label: optionValue,\n }));\n}\n\nexport function uniqueDocumentChoices(choices: DocumentTypeChoice[]): DocumentTypeChoice[] {\n const seen = new Set<string>();\n return choices.filter((choice) => {\n const value = choice.value.trim();\n if (!value || seen.has(value)) return false;\n seen.add(value);\n return true;\n });\n}\n\nexport function getKycPrefill(requirements: KycRequirements | null): KycFormPrefill {\n if (!requirements) return {};\n const kycForm = requirements.kyc_form;\n if (kycForm?.prefill && typeof kycForm.prefill === 'object') return kycForm.prefill;\n if (requirements.form_prefill && typeof requirements.form_prefill === 'object') return requirements.form_prefill;\n return {};\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));\n}\n\nfunction normalizeFieldName(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' ? value as Record<string, unknown> : {};\n}\n\nconst PREFILL_FIELD_ALIASES: Record<string, string[]> = {\n birth_date: ['birth_date', 'date_of_birth'],\n date_of_birth: ['date_of_birth', 'birth_date'],\n document_number: ['document_number', 'tax_id'],\n tax_id: ['tax_id', 'document_number'],\n};\n\nconst STRONG_READ_ONLY_LIST_KEYS = [\n 'locked_fields',\n 'strong_read_only_fields',\n 'force_read_only_fields',\n 'forced_read_only_fields',\n 'hard_read_only_fields',\n];\n\nconst STRONG_READ_ONLY_MAP_KEYS = [\n 'field_locks',\n 'read_only_locks',\n];\n\nfunction prefillAliasesForField(field: string): string[] {\n const normalized = normalizeFieldName(field);\n return PREFILL_FIELD_ALIASES[normalized] ?? [normalized];\n}\n\nexport function hasRealKycPrefillValue(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed || trimmed.includes('*')) return false;\n return /[A-Za-z0-9]/.test(trimmed);\n }\n\n if (typeof value === 'number') return Number.isFinite(value);\n if (typeof value === 'boolean') return true;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n\n return false;\n}\n\nfunction hasRealKycPrefillForField(requirements: KycRequirements | null, field: string): boolean {\n const prefill = getKycPrefill(requirements);\n return prefillAliasesForField(field).some((alias) => hasRealKycPrefillValue(prefill[alias]));\n}\n\nexport function getKycReadOnlyFields(requirements: KycRequirements | null): string[] {\n if (!requirements) return [];\n const kycFormFields = normalizeStringList(requirements.kyc_form?.read_only_fields);\n return uniqueStrings([\n ...kycFormFields,\n ...normalizeStringList(requirements.read_only_fields),\n ]);\n}\n\nfunction getKycStrongReadOnlyFields(requirements: KycRequirements | null): string[] {\n if (!requirements) return [];\n\n const kycForm = recordValue(requirements.kyc_form);\n const topLevel = recordValue(requirements);\n const listFields = STRONG_READ_ONLY_LIST_KEYS.flatMap((key) => [\n ...normalizeStringList(kycForm[key]),\n ...normalizeStringList(topLevel[key]),\n ]);\n const mapFields = STRONG_READ_ONLY_MAP_KEYS.flatMap((key) => [\n ...strongReadOnlyFieldsFromMap(kycForm[key]),\n ...strongReadOnlyFieldsFromMap(topLevel[key]),\n ]);\n\n return uniqueStrings([...listFields, ...mapFields]);\n}\n\nfunction strongReadOnlyFieldsFromMap(value: unknown): string[] {\n const locks = recordValue(value);\n\n return Object.entries(locks).flatMap(([field, lock]) => {\n if (lock === true) return [field];\n if (typeof lock !== 'string') return [];\n\n const normalized = lock.trim().toLowerCase();\n return ['strong', 'hard', 'locked', 'force', 'forced', 'read_only'].includes(normalized)\n ? [field]\n : [];\n });\n}\n\nexport function isKycFieldReadOnly(requirements: KycRequirements | null, field: string): boolean {\n const normalizedField = normalizeFieldName(field);\n const strongReadOnlyFields = getKycStrongReadOnlyFields(requirements).map(normalizeFieldName);\n if (strongReadOnlyFields.includes(normalizedField)) return true;\n\n const readOnlyFields = getKycReadOnlyFields(requirements).map(normalizeFieldName);\n return readOnlyFields.includes(normalizedField)\n && hasRealKycPrefillForField(requirements, normalizedField);\n}\n\nexport function shouldLockKycFiscalDocumentField(options: {\n configuredReadOnly: boolean;\n normalized: string;\n isValid: boolean;\n}): boolean {\n return options.configuredReadOnly\n && options.normalized.length > 0\n && options.isValid;\n}\n\nfunction getConfigClientFlow(config: unknown): ClientFlowStep[] {\n const record = config && typeof config === 'object' ? config as Record<string, unknown> : {};\n return [\n ...normalizeClientFlow(record.client_flow),\n ...normalizeClientFlow((record.compliance_config as Record<string, unknown> | undefined)?.client_flow),\n ...normalizeClientFlow(\n ((record.flow_config as Record<string, unknown> | undefined)?.compliance_config as Record<string, unknown> | undefined)?.client_flow\n ),\n ];\n}\n\nexport function getRegistrationDocumentConfig(config: unknown): RegistrationDocumentConfig | null {\n const record = config && typeof config === 'object' ? config as Record<string, unknown> : {};\n const direct = record.registration_document;\n if (direct && typeof direct === 'object') {\n return direct as RegistrationDocumentConfig;\n }\n\n const flowConfig = record.flow_config && typeof record.flow_config === 'object'\n ? record.flow_config as Record<string, unknown>\n : {};\n const nested = flowConfig.registration_document;\n if (nested && typeof nested === 'object') {\n return nested as RegistrationDocumentConfig;\n }\n\n return null;\n}\n\nexport function getRegistrationTaxIdField(config: unknown): string {\n const field = String(getRegistrationDocumentConfig(config)?.field ?? 'tax_id').trim();\n return field || 'tax_id';\n}\n\nexport function shouldCollectRegistrationTaxId(config: unknown): boolean {\n const registrationDocument = getRegistrationDocumentConfig(config);\n if (registrationDocument?.collect_tax_id === true) return true;\n\n return getConfigClientFlow(config).some((step) =>\n step.screen === 'account' && step.collect_tax_id === true\n );\n}\n\nexport function isRegistrationTaxIdRequired(config: unknown): boolean {\n const registrationDocument = getRegistrationDocumentConfig(config);\n const taxIdField = getRegistrationTaxIdField(config);\n\n if (registrationDocument?.collect_tax_id === true && registrationDocument.required === true) {\n return true;\n }\n\n return getConfigClientFlow(config).some((step) => {\n if (step.screen !== 'account') return false;\n const requiredFields = normalizeStringList(step.required_fields);\n return requiredFields.includes(taxIdField) || requiredFields.includes('tax_id');\n });\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ClientFlowStep, KycCustomerType, KycFlowEntityType, KycFlowSnapshot, KycOverviewData, KycRequirements, KycVerificationData } from './types.js';
|
|
2
|
+
export declare const VIRTUAL_REVIEW_STEP: ClientFlowStep;
|
|
3
|
+
export declare function normalizeCustomerType(value: unknown): KycCustomerType;
|
|
4
|
+
export declare function flowEntityTypeForCustomerType(customerType: KycCustomerType): KycFlowEntityType;
|
|
5
|
+
export declare function getRequirementsClientFlow(requirements: KycRequirements | null | undefined): ClientFlowStep[];
|
|
6
|
+
export declare function hasKycClientFlow(requirements: KycRequirements | null | undefined): boolean;
|
|
7
|
+
export declare function hasResolvedKycRequirements(requirements: KycRequirements | null | undefined): requirements is KycRequirements;
|
|
8
|
+
export declare function getComplianceSteps(requirements: KycRequirements | null | undefined, customerType: KycCustomerType): ClientFlowStep[];
|
|
9
|
+
export declare function ensureReviewStep(steps: ClientFlowStep[], customerType: KycCustomerType): ClientFlowStep[];
|
|
10
|
+
export declare function isUniversalStepCompleted(step: ClientFlowStep, status: KycVerificationData | null | undefined): boolean;
|
|
11
|
+
export declare function resolveActiveKycStep(params: {
|
|
12
|
+
requirements: KycRequirements | null | undefined;
|
|
13
|
+
status: KycVerificationData | null | undefined;
|
|
14
|
+
customerType: KycCustomerType;
|
|
15
|
+
}): ClientFlowStep | null;
|
|
16
|
+
export declare function canOpenUniversalStep(params: {
|
|
17
|
+
step: ClientFlowStep;
|
|
18
|
+
steps: ClientFlowStep[];
|
|
19
|
+
activeStep: ClientFlowStep | null;
|
|
20
|
+
status: KycVerificationData | null | undefined;
|
|
21
|
+
}): boolean;
|
|
22
|
+
export declare function findStepByMissing(steps: ClientFlowStep[], missingStep?: string, missingScreen?: string): ClientFlowStep | null;
|
|
23
|
+
export declare function getKycProgress(params: {
|
|
24
|
+
steps: ClientFlowStep[];
|
|
25
|
+
status: KycVerificationData | null | undefined;
|
|
26
|
+
}): number;
|
|
27
|
+
export declare function requirementsFromOverview(overview: KycOverviewData | null | undefined): KycRequirements | null;
|
|
28
|
+
export declare function preserveSsrKycRequirementsAnchor(anchor: KycRequirements, overviewRequirements: KycRequirements | null): KycRequirements;
|
|
29
|
+
export declare function mergeKycRequirementsWithAnchor(nextRequirements: KycRequirements, anchor: KycRequirements | null): KycRequirements;
|
|
30
|
+
export declare function statusFromOverview(overview: KycOverviewData | null | undefined): KycVerificationData | null;
|
|
31
|
+
export declare function resolveKycFlowSnapshot(input: {
|
|
32
|
+
overview?: KycOverviewData | null;
|
|
33
|
+
anchorRequirements?: KycRequirements | null;
|
|
34
|
+
}): KycFlowSnapshot;
|
|
35
|
+
export declare function isKycFlowSnapshotConfigured(snapshot: KycFlowSnapshot | null | undefined): boolean;
|
|
36
|
+
export declare function isKycOverviewFlowConfigured(overview: KycOverviewData | null | undefined): boolean;
|
|
37
|
+
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/kyc/flow.ts"],"names":[],"mappings":"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"}
|
package/dist/kyc/flow.js
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
export const VIRTUAL_REVIEW_STEP = {
|
|
2
|
+
key: 'review',
|
|
3
|
+
title: 'Review',
|
|
4
|
+
phase: 'compliance',
|
|
5
|
+
screen: 'review',
|
|
6
|
+
description: 'Review and submit verification.',
|
|
7
|
+
endpoint: '/api/v1/kyc/submit',
|
|
8
|
+
required_fields: [],
|
|
9
|
+
required_documents: [],
|
|
10
|
+
entity_types: ['PF', 'PJ'],
|
|
11
|
+
blocking: true,
|
|
12
|
+
};
|
|
13
|
+
function asRecord(value) {
|
|
14
|
+
return value && typeof value === 'object' ? value : {};
|
|
15
|
+
}
|
|
16
|
+
function normalizeClientFlow(value) {
|
|
17
|
+
if (!Array.isArray(value))
|
|
18
|
+
return [];
|
|
19
|
+
return value
|
|
20
|
+
.filter((step) => Boolean(step && typeof step === 'object'))
|
|
21
|
+
.flatMap((step) => {
|
|
22
|
+
const key = typeof step.key === 'string' ? step.key.trim() : '';
|
|
23
|
+
const screen = typeof step.screen === 'string' ? step.screen.trim() : '';
|
|
24
|
+
const phase = step.phase === 'registration' || step.phase === 'compliance'
|
|
25
|
+
? step.phase
|
|
26
|
+
: 'compliance';
|
|
27
|
+
if (!key || !screen)
|
|
28
|
+
return [];
|
|
29
|
+
return [{
|
|
30
|
+
...step,
|
|
31
|
+
key,
|
|
32
|
+
title: typeof step.title === 'string' && step.title.trim() ? step.title : key,
|
|
33
|
+
phase,
|
|
34
|
+
screen: screen,
|
|
35
|
+
endpoint: typeof step.endpoint === 'string' ? step.endpoint : undefined,
|
|
36
|
+
required_fields: Array.isArray(step.required_fields) ? step.required_fields.map(String) : [],
|
|
37
|
+
required_documents: Array.isArray(step.required_documents) ? step.required_documents.map(String) : [],
|
|
38
|
+
entity_types: normalizeEntityTypes(step.entity_types),
|
|
39
|
+
blocking: step.blocking !== false,
|
|
40
|
+
}];
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function normalizeEntityTypes(value) {
|
|
44
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
45
|
+
return ['PF', 'PJ'];
|
|
46
|
+
const entityTypes = value
|
|
47
|
+
.map((item) => String(item).trim().toUpperCase())
|
|
48
|
+
.filter((item) => item === 'PF' || item === 'PJ');
|
|
49
|
+
return entityTypes.length > 0 ? entityTypes : ['PF', 'PJ'];
|
|
50
|
+
}
|
|
51
|
+
function normalizeJurisdictionCode(value) {
|
|
52
|
+
const normalized = String(value ?? '').trim().toUpperCase();
|
|
53
|
+
return /^[A-Z]{2}$/.test(normalized) ? normalized : undefined;
|
|
54
|
+
}
|
|
55
|
+
function normalizeDocumentTypes(requirements) {
|
|
56
|
+
const value = requirements?.document_types;
|
|
57
|
+
const list = Array.isArray(value)
|
|
58
|
+
? value
|
|
59
|
+
: typeof value === 'string'
|
|
60
|
+
? value.split(',')
|
|
61
|
+
: [];
|
|
62
|
+
return Array.from(new Set(list
|
|
63
|
+
.map((type) => String(type).trim().toLowerCase())
|
|
64
|
+
.filter(Boolean))).sort();
|
|
65
|
+
}
|
|
66
|
+
function sameDocumentTypes(nextRequirements, anchor) {
|
|
67
|
+
const nextTypes = normalizeDocumentTypes(nextRequirements);
|
|
68
|
+
const anchorTypes = normalizeDocumentTypes(anchor);
|
|
69
|
+
if (nextTypes.length === 0 || anchorTypes.length === 0)
|
|
70
|
+
return true;
|
|
71
|
+
if (nextTypes.length !== anchorTypes.length)
|
|
72
|
+
return false;
|
|
73
|
+
return nextTypes.every((type, index) => type === anchorTypes[index]);
|
|
74
|
+
}
|
|
75
|
+
function anchorMatchesRequirements(nextRequirements, anchor) {
|
|
76
|
+
const nextJurisdiction = normalizeJurisdictionCode(nextRequirements.jurisdiction_code ?? nextRequirements.code);
|
|
77
|
+
const anchorJurisdiction = normalizeJurisdictionCode(anchor.jurisdiction_code ?? anchor.code);
|
|
78
|
+
if (nextJurisdiction && anchorJurisdiction && nextJurisdiction !== anchorJurisdiction)
|
|
79
|
+
return false;
|
|
80
|
+
if (nextRequirements.customer_type
|
|
81
|
+
&& anchor.customer_type
|
|
82
|
+
&& nextRequirements.customer_type !== anchor.customer_type) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return sameDocumentTypes(nextRequirements, anchor);
|
|
86
|
+
}
|
|
87
|
+
export function normalizeCustomerType(value) {
|
|
88
|
+
const normalized = String(value ?? '').trim().toLowerCase();
|
|
89
|
+
return ['company', 'pj', 'business', 'legal_entity'].includes(normalized)
|
|
90
|
+
? 'company'
|
|
91
|
+
: 'individual';
|
|
92
|
+
}
|
|
93
|
+
export function flowEntityTypeForCustomerType(customerType) {
|
|
94
|
+
return customerType === 'company' ? 'PJ' : 'PF';
|
|
95
|
+
}
|
|
96
|
+
export function getRequirementsClientFlow(requirements) {
|
|
97
|
+
if (!requirements)
|
|
98
|
+
return [];
|
|
99
|
+
const direct = normalizeClientFlow(requirements.client_flow);
|
|
100
|
+
if (direct.length > 0)
|
|
101
|
+
return direct;
|
|
102
|
+
const nested = normalizeClientFlow(requirements.compliance_config?.client_flow);
|
|
103
|
+
if (nested.length > 0)
|
|
104
|
+
return nested;
|
|
105
|
+
return normalizeClientFlow(requirements.flow_config?.compliance_config?.client_flow);
|
|
106
|
+
}
|
|
107
|
+
export function hasKycClientFlow(requirements) {
|
|
108
|
+
return getRequirementsClientFlow(requirements).length > 0;
|
|
109
|
+
}
|
|
110
|
+
export function hasResolvedKycRequirements(requirements) {
|
|
111
|
+
return Boolean(requirements && hasKycClientFlow(requirements));
|
|
112
|
+
}
|
|
113
|
+
export function getComplianceSteps(requirements, customerType) {
|
|
114
|
+
const entityType = flowEntityTypeForCustomerType(customerType);
|
|
115
|
+
return getRequirementsClientFlow(requirements)
|
|
116
|
+
.filter((step) => step.phase === 'compliance')
|
|
117
|
+
.filter((step) => (step.entity_types?.length ? step.entity_types : ['PF', 'PJ']).includes(entityType));
|
|
118
|
+
}
|
|
119
|
+
export function ensureReviewStep(steps, customerType) {
|
|
120
|
+
if (steps.length === 0 || steps.some((step) => step.screen === 'review'))
|
|
121
|
+
return steps;
|
|
122
|
+
return [
|
|
123
|
+
...steps,
|
|
124
|
+
{
|
|
125
|
+
...VIRTUAL_REVIEW_STEP,
|
|
126
|
+
entity_types: [flowEntityTypeForCustomerType(customerType)],
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
export function isUniversalStepCompleted(step, status) {
|
|
131
|
+
if (!status)
|
|
132
|
+
return false;
|
|
133
|
+
return status.completed_flow_steps?.includes(step.key) ?? false;
|
|
134
|
+
}
|
|
135
|
+
function flowStateStepKey(status) {
|
|
136
|
+
return status?.flow_state?.required_action?.step_key
|
|
137
|
+
?? status?.flow_state?.target_flow_step
|
|
138
|
+
?? status?.flow_state?.current_step?.key
|
|
139
|
+
?? status?.flow_state?.target_step
|
|
140
|
+
?? null;
|
|
141
|
+
}
|
|
142
|
+
export function resolveActiveKycStep(params) {
|
|
143
|
+
if (getRequirementsClientFlow(params.requirements).length === 0)
|
|
144
|
+
return null;
|
|
145
|
+
const steps = ensureReviewStep(getComplianceSteps(params.requirements, params.customerType), params.customerType);
|
|
146
|
+
if (steps.length === 0)
|
|
147
|
+
return null;
|
|
148
|
+
if (params.status?.status === 'pending_review' || params.status?.status === 'under_review')
|
|
149
|
+
return null;
|
|
150
|
+
if (params.status?.status === 'approved')
|
|
151
|
+
return null;
|
|
152
|
+
const flowStateKey = flowStateStepKey(params.status);
|
|
153
|
+
if (flowStateKey) {
|
|
154
|
+
const configuredStep = steps.find((step) => step.key === flowStateKey);
|
|
155
|
+
if (configuredStep)
|
|
156
|
+
return configuredStep;
|
|
157
|
+
}
|
|
158
|
+
if (params.status?.status === 'rejected' || params.status?.status === 'requires_resubmission') {
|
|
159
|
+
return steps.find((step) => step.screen !== 'review' && !isUniversalStepCompleted(step, params.status))
|
|
160
|
+
?? steps.find((step) => step.screen === 'review')
|
|
161
|
+
?? steps[0];
|
|
162
|
+
}
|
|
163
|
+
for (const step of steps) {
|
|
164
|
+
if (step.screen === 'review')
|
|
165
|
+
continue;
|
|
166
|
+
if (isUniversalStepCompleted(step, params.status))
|
|
167
|
+
continue;
|
|
168
|
+
if (step.blocking !== false)
|
|
169
|
+
return step;
|
|
170
|
+
}
|
|
171
|
+
return steps.find((step) => step.screen === 'review') ?? steps[steps.length - 1];
|
|
172
|
+
}
|
|
173
|
+
export function canOpenUniversalStep(params) {
|
|
174
|
+
const index = params.steps.findIndex((step) => step.key === params.step.key);
|
|
175
|
+
if (index < 0)
|
|
176
|
+
return false;
|
|
177
|
+
if (params.activeStep?.key === params.step.key)
|
|
178
|
+
return true;
|
|
179
|
+
if (isUniversalStepCompleted(params.step, params.status))
|
|
180
|
+
return true;
|
|
181
|
+
const firstIncompleteIndex = params.steps.findIndex((step) => step.screen !== 'review' && !isUniversalStepCompleted(step, params.status));
|
|
182
|
+
if (params.step.screen === 'review')
|
|
183
|
+
return firstIncompleteIndex === -1;
|
|
184
|
+
if (firstIncompleteIndex === -1)
|
|
185
|
+
return true;
|
|
186
|
+
return index <= firstIncompleteIndex;
|
|
187
|
+
}
|
|
188
|
+
export function findStepByMissing(steps, missingStep, missingScreen) {
|
|
189
|
+
if (!missingStep && !missingScreen)
|
|
190
|
+
return null;
|
|
191
|
+
return steps.find((step) => (missingStep && step.key === missingStep)
|
|
192
|
+
|| (missingScreen && step.screen === missingScreen)) ?? null;
|
|
193
|
+
}
|
|
194
|
+
export function getKycProgress(params) {
|
|
195
|
+
if (params.steps.length === 0)
|
|
196
|
+
return 0;
|
|
197
|
+
const completed = params.steps.filter((step) => step.screen === 'review'
|
|
198
|
+
? params.status?.status === 'pending_review'
|
|
199
|
+
|| params.status?.status === 'under_review'
|
|
200
|
+
|| params.status?.status === 'approved'
|
|
201
|
+
: isUniversalStepCompleted(step, params.status)).length;
|
|
202
|
+
return Math.min(100, Math.round((completed / params.steps.length) * 100));
|
|
203
|
+
}
|
|
204
|
+
export function requirementsFromOverview(overview) {
|
|
205
|
+
if (!overview)
|
|
206
|
+
return null;
|
|
207
|
+
const overviewRequirements = asRecord(overview.requirements);
|
|
208
|
+
const overviewFlowConfig = asRecord(overview.flow_config);
|
|
209
|
+
const requirementFlowConfig = asRecord(overviewRequirements.flow_config);
|
|
210
|
+
const flowConfig = {
|
|
211
|
+
...overviewFlowConfig,
|
|
212
|
+
...requirementFlowConfig,
|
|
213
|
+
};
|
|
214
|
+
const requirementsSource = Object.keys(overviewRequirements).length > 0
|
|
215
|
+
? overviewRequirements
|
|
216
|
+
: flowConfig;
|
|
217
|
+
if (Object.keys(requirementsSource).length === 0)
|
|
218
|
+
return null;
|
|
219
|
+
const flowComplianceConfig = asRecord(asRecord(flowConfig).compliance_config);
|
|
220
|
+
const requirementsComplianceConfig = asRecord(requirementsSource.compliance_config);
|
|
221
|
+
const directClientFlow = normalizeClientFlow(overview.client_flow);
|
|
222
|
+
const clientFlow = directClientFlow.length > 0
|
|
223
|
+
? directClientFlow
|
|
224
|
+
: [
|
|
225
|
+
...normalizeClientFlow(requirementsSource.client_flow),
|
|
226
|
+
...normalizeClientFlow(requirementsComplianceConfig.client_flow),
|
|
227
|
+
...normalizeClientFlow(flowComplianceConfig.client_flow),
|
|
228
|
+
];
|
|
229
|
+
const flowState = overview.flow_state ?? overview.status?.flow_state ?? null;
|
|
230
|
+
const jurisdiction = asRecord(requirementsSource.jurisdiction ?? flowConfig.jurisdiction);
|
|
231
|
+
const resolvedLocale = String(requirementsSource.locale
|
|
232
|
+
?? asRecord(overview).locale
|
|
233
|
+
?? flowConfig.locale
|
|
234
|
+
?? jurisdiction.locale
|
|
235
|
+
?? '').trim() || undefined;
|
|
236
|
+
return {
|
|
237
|
+
...flowConfig,
|
|
238
|
+
...requirementsSource,
|
|
239
|
+
jurisdiction_code: normalizeJurisdictionCode(requirementsSource.jurisdiction_code
|
|
240
|
+
?? requirementsSource.code
|
|
241
|
+
?? flowState?.jurisdiction_code),
|
|
242
|
+
customer_type: requirementsSource.customer_type
|
|
243
|
+
?? normalizeCustomerType(flowState?.entity_type),
|
|
244
|
+
locale: resolvedLocale,
|
|
245
|
+
flow_config: {
|
|
246
|
+
...flowConfig,
|
|
247
|
+
compliance_config: {
|
|
248
|
+
...flowComplianceConfig,
|
|
249
|
+
client_flow: clientFlow,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
compliance_config: {
|
|
253
|
+
...flowComplianceConfig,
|
|
254
|
+
...requirementsComplianceConfig,
|
|
255
|
+
client_flow: clientFlow,
|
|
256
|
+
},
|
|
257
|
+
client_flow: clientFlow,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
export function preserveSsrKycRequirementsAnchor(anchor, overviewRequirements) {
|
|
261
|
+
const anchorClientFlow = getRequirementsClientFlow(anchor);
|
|
262
|
+
return {
|
|
263
|
+
...anchor,
|
|
264
|
+
kyc_form: overviewRequirements?.kyc_form ?? anchor.kyc_form,
|
|
265
|
+
form_prefill: overviewRequirements?.form_prefill ?? anchor.form_prefill,
|
|
266
|
+
read_only_fields: overviewRequirements?.read_only_fields ?? anchor.read_only_fields,
|
|
267
|
+
client_flow: anchorClientFlow,
|
|
268
|
+
flow_config: {
|
|
269
|
+
...(anchor.flow_config ?? {}),
|
|
270
|
+
compliance_config: {
|
|
271
|
+
...(anchor.flow_config?.compliance_config ?? {}),
|
|
272
|
+
client_flow: anchorClientFlow,
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
compliance_config: {
|
|
276
|
+
...(anchor.compliance_config ?? {}),
|
|
277
|
+
client_flow: anchorClientFlow,
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
export function mergeKycRequirementsWithAnchor(nextRequirements, anchor) {
|
|
282
|
+
if (!anchor)
|
|
283
|
+
return nextRequirements;
|
|
284
|
+
const anchorClientFlow = getRequirementsClientFlow(anchor);
|
|
285
|
+
const nextClientFlow = getRequirementsClientFlow(nextRequirements);
|
|
286
|
+
const canUseAnchor = anchorClientFlow.length > 0
|
|
287
|
+
&& nextClientFlow.length === 0
|
|
288
|
+
&& anchorMatchesRequirements(nextRequirements, anchor);
|
|
289
|
+
if (!canUseAnchor)
|
|
290
|
+
return nextRequirements;
|
|
291
|
+
return preserveSsrKycRequirementsAnchor(anchor, nextRequirements);
|
|
292
|
+
}
|
|
293
|
+
export function statusFromOverview(overview) {
|
|
294
|
+
return overview?.status ?? null;
|
|
295
|
+
}
|
|
296
|
+
export function resolveKycFlowSnapshot(input) {
|
|
297
|
+
const overviewRequirements = requirementsFromOverview(input.overview);
|
|
298
|
+
const requirements = overviewRequirements
|
|
299
|
+
? mergeKycRequirementsWithAnchor(overviewRequirements, input.anchorRequirements ?? null)
|
|
300
|
+
: input.anchorRequirements ?? null;
|
|
301
|
+
const status = statusFromOverview(input.overview);
|
|
302
|
+
const customerType = normalizeCustomerType(requirements?.customer_type
|
|
303
|
+
?? status?.flow_state?.entity_type);
|
|
304
|
+
const jurisdictionCode = normalizeJurisdictionCode(requirements?.jurisdiction_code
|
|
305
|
+
?? requirements?.code
|
|
306
|
+
?? status?.flow_state?.jurisdiction_code);
|
|
307
|
+
const hasConfiguredClientFlow = getRequirementsClientFlow(requirements).length > 0;
|
|
308
|
+
const steps = hasConfiguredClientFlow
|
|
309
|
+
? ensureReviewStep(getComplianceSteps(requirements, customerType), customerType)
|
|
310
|
+
: [];
|
|
311
|
+
const activeStep = resolveActiveKycStep({ requirements, status, customerType });
|
|
312
|
+
return {
|
|
313
|
+
activeStep,
|
|
314
|
+
steps,
|
|
315
|
+
requirements,
|
|
316
|
+
status,
|
|
317
|
+
customerType,
|
|
318
|
+
jurisdictionCode,
|
|
319
|
+
progress: getKycProgress({ steps, status }),
|
|
320
|
+
configMissing: Boolean(requirements && !hasConfiguredClientFlow),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
export function isKycFlowSnapshotConfigured(snapshot) {
|
|
324
|
+
return Boolean(snapshot && !snapshot.configMissing && snapshot.steps.length > 0);
|
|
325
|
+
}
|
|
326
|
+
export function isKycOverviewFlowConfigured(overview) {
|
|
327
|
+
return isKycFlowSnapshotConfigured(resolveKycFlowSnapshot({ overview }));
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=flow.js.map
|