@abyss-project/tools 1.0.1 → 1.0.3

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.
@@ -1,98 +1,98 @@
1
- export enum PdfOperationType {
2
- ANNOTATE_TEXT = 'ANNOTATE_TEXT',
3
- ANNOTATE_DRAW = 'ANNOTATE_DRAW',
4
- ANNOTATE_IMAGE = 'ANNOTATE_IMAGE',
5
- FILL_FIELD = 'FILL_FIELD',
6
- PAGE_REORDER = 'PAGE_REORDER',
7
- PAGE_DELETE = 'PAGE_DELETE',
8
- PAGE_ROTATE = 'PAGE_ROTATE',
9
- PAGE_INSERT_FROM_UPLOAD = 'PAGE_INSERT_FROM_UPLOAD',
10
- FLATTEN = 'FLATTEN',
11
- }
12
-
13
- export interface IPdfOpAnnotateText {
14
- opId: string;
15
- type: PdfOperationType.ANNOTATE_TEXT;
16
- pageIndex: number;
17
- x: number;
18
- y: number;
19
- text: string;
20
- fontSize: number;
21
- color: string;
22
- }
23
-
24
- export interface IPdfOpAnnotateDraw {
25
- opId: string;
26
- type: PdfOperationType.ANNOTATE_DRAW;
27
- pageIndex: number;
28
- pathSvg: string;
29
- color: string;
30
- strokeWidth: number;
31
- }
32
-
33
- export type PdfImageSource =
34
- | { kind: 'USER_ASSET'; assetId: string }
35
- | { kind: 'INLINE'; storageKey: string };
36
-
37
- export interface IPdfOpAnnotateImage {
38
- opId: string;
39
- type: PdfOperationType.ANNOTATE_IMAGE;
40
- pageIndex: number;
41
- x: number;
42
- y: number;
43
- /** Width in PDF points (1/72 inch). Aligned with front-core PdfOperation. */
44
- widthPt: number;
45
- /** Height in PDF points (1/72 inch). Aligned with front-core PdfOperation. */
46
- heightPt: number;
47
- source: PdfImageSource;
48
- }
49
-
50
- export interface IPdfOpFillField {
51
- opId: string;
52
- type: PdfOperationType.FILL_FIELD;
53
- fieldName: string;
54
- value: string | boolean;
55
- }
56
-
57
- export interface IPdfOpPageReorder {
58
- opId: string;
59
- type: PdfOperationType.PAGE_REORDER;
60
- order: number[];
61
- }
62
-
63
- export interface IPdfOpPageDelete {
64
- opId: string;
65
- type: PdfOperationType.PAGE_DELETE;
66
- pageIndex: number;
67
- }
68
-
69
- export interface IPdfOpPageRotate {
70
- opId: string;
71
- type: PdfOperationType.PAGE_ROTATE;
72
- pageIndex: number;
73
- deg: 90 | 180 | 270;
74
- }
75
-
76
- export interface IPdfOpPageInsertFromUpload {
77
- opId: string;
78
- type: PdfOperationType.PAGE_INSERT_FROM_UPLOAD;
79
- afterPageIndex: number;
80
- uploadKey: string;
81
- uploadPages: number[];
82
- }
83
-
84
- export interface IPdfOpFlatten {
85
- opId: string;
86
- type: PdfOperationType.FLATTEN;
87
- }
88
-
89
- export type PdfOperation =
90
- | IPdfOpAnnotateText
91
- | IPdfOpAnnotateDraw
92
- | IPdfOpAnnotateImage
93
- | IPdfOpFillField
94
- | IPdfOpPageReorder
95
- | IPdfOpPageDelete
96
- | IPdfOpPageRotate
97
- | IPdfOpPageInsertFromUpload
98
- | IPdfOpFlatten;
1
+ export enum PdfOperationType {
2
+ ANNOTATE_TEXT = 'ANNOTATE_TEXT',
3
+ ANNOTATE_DRAW = 'ANNOTATE_DRAW',
4
+ ANNOTATE_IMAGE = 'ANNOTATE_IMAGE',
5
+ FILL_FIELD = 'FILL_FIELD',
6
+ PAGE_REORDER = 'PAGE_REORDER',
7
+ PAGE_DELETE = 'PAGE_DELETE',
8
+ PAGE_ROTATE = 'PAGE_ROTATE',
9
+ PAGE_INSERT_FROM_UPLOAD = 'PAGE_INSERT_FROM_UPLOAD',
10
+ FLATTEN = 'FLATTEN',
11
+ }
12
+
13
+ export interface IPdfOpAnnotateText {
14
+ opId: string;
15
+ type: PdfOperationType.ANNOTATE_TEXT;
16
+ pageIndex: number;
17
+ x: number;
18
+ y: number;
19
+ text: string;
20
+ fontSize: number;
21
+ color: string;
22
+ }
23
+
24
+ export interface IPdfOpAnnotateDraw {
25
+ opId: string;
26
+ type: PdfOperationType.ANNOTATE_DRAW;
27
+ pageIndex: number;
28
+ pathSvg: string;
29
+ color: string;
30
+ strokeWidth: number;
31
+ }
32
+
33
+ export type PdfImageSource =
34
+ | { kind: 'USER_ASSET'; assetId: string }
35
+ | { kind: 'INLINE'; storageKey: string };
36
+
37
+ export interface IPdfOpAnnotateImage {
38
+ opId: string;
39
+ type: PdfOperationType.ANNOTATE_IMAGE;
40
+ pageIndex: number;
41
+ x: number;
42
+ y: number;
43
+ /** Width in PDF points (1/72 inch). Aligned with front-core PdfOperation. */
44
+ widthPt: number;
45
+ /** Height in PDF points (1/72 inch). Aligned with front-core PdfOperation. */
46
+ heightPt: number;
47
+ source: PdfImageSource;
48
+ }
49
+
50
+ export interface IPdfOpFillField {
51
+ opId: string;
52
+ type: PdfOperationType.FILL_FIELD;
53
+ fieldName: string;
54
+ value: string | boolean;
55
+ }
56
+
57
+ export interface IPdfOpPageReorder {
58
+ opId: string;
59
+ type: PdfOperationType.PAGE_REORDER;
60
+ order: number[];
61
+ }
62
+
63
+ export interface IPdfOpPageDelete {
64
+ opId: string;
65
+ type: PdfOperationType.PAGE_DELETE;
66
+ pageIndex: number;
67
+ }
68
+
69
+ export interface IPdfOpPageRotate {
70
+ opId: string;
71
+ type: PdfOperationType.PAGE_ROTATE;
72
+ pageIndex: number;
73
+ deg: 90 | 180 | 270;
74
+ }
75
+
76
+ export interface IPdfOpPageInsertFromUpload {
77
+ opId: string;
78
+ type: PdfOperationType.PAGE_INSERT_FROM_UPLOAD;
79
+ afterPageIndex: number;
80
+ uploadKey: string;
81
+ uploadPages: number[];
82
+ }
83
+
84
+ export interface IPdfOpFlatten {
85
+ opId: string;
86
+ type: PdfOperationType.FLATTEN;
87
+ }
88
+
89
+ export type PdfOperation =
90
+ | IPdfOpAnnotateText
91
+ | IPdfOpAnnotateDraw
92
+ | IPdfOpAnnotateImage
93
+ | IPdfOpFillField
94
+ | IPdfOpPageReorder
95
+ | IPdfOpPageDelete
96
+ | IPdfOpPageRotate
97
+ | IPdfOpPageInsertFromUpload
98
+ | IPdfOpFlatten;
@@ -1,137 +1,137 @@
1
- // ──────────────────────────────────────────────
2
- // RCB — Formal catalogue of supported banks and versions.
3
- //
4
- // Mirrors the server-side registry (BANK_VERSIONS in abyss-tools/apps/api).
5
- // Use these enums whenever you reference a bank or version in hint mode,
6
- // UI dropdowns, or per-bank metrics. Adding a bank?
7
- // 1. Add the entry to BANK_VERSIONS in apps/api.
8
- // 2. Add the matching id here. CI will catch any mismatch.
9
- // ──────────────────────────────────────────────
10
-
11
- /**
12
- * Stable id of a bank+version profile. The wire-format string used in
13
- * `hint.bank` (POST /rcb/extract mode=hint) and returned in
14
- * extraction.strategy_used.
15
- */
16
- export enum RcbBankVersionId {
17
- BNP_CONNEXIS_DEFAULT = 'bnp-connexis-default',
18
- BNP_PARIBAS_DEFAULT = 'bnp-paribas-default',
19
- SOCIETE_GENERALE_DEFAULT = 'societe-generale-default',
20
- CREDIT_AGRICOLE_DEFAULT = 'credit-agricole-default',
21
- LCL_DEFAULT = 'lcl-default',
22
- BOURSORAMA_DEFAULT = 'boursorama-default',
23
- SPENDESK_DEFAULT = 'spendesk-default',
24
- LA_BANQUE_POSTALE_DEFAULT = 'la-banque-postale-default',
25
- CAISSE_EPARGNE_DEFAULT = 'caisse-epargne-default',
26
- THEMIS_DEFAULT = 'themis-default',
27
- CIC_EBICS_DEFAULT = 'cic-ebics-default',
28
- CIC_DEFAULT = 'cic-default',
29
- CREDIT_MUTUEL_DEFAULT = 'credit-mutuel-default',
30
- N26_DEFAULT = 'n26-default',
31
- REVOLUT_DEFAULT = 'revolut-default',
32
- HSBC_DEFAULT = 'hsbc-default',
33
- HSBC_UK_DEFAULT = 'hsbc-uk-default',
34
- WISE_DEFAULT = 'wise-default',
35
- CREDIT_DU_NORD_DEFAULT = 'cdn-default',
36
- BRED_DEFAULT = 'bred-default',
37
- QONTO_DEFAULT = 'qonto-default',
38
- SHINE_DEFAULT = 'shine-default',
39
- SWAN_DEFAULT = 'swan-default',
40
- ROTHSCHILD_DEFAULT = 'rothschild-default',
41
- FINOM_DEFAULT = 'finom-default',
42
- TIIME_DEFAULT = 'tiime-default',
43
- UBS_DEFAULT = 'ubs-default',
44
- CAIXA_DEFAULT = 'caixa-default',
45
- CDE_NET_DEFAULT = 'cde-net-default',
46
- DELUBAC_DEFAULT = 'delubac-default',
47
- AIRWALLEX_DEFAULT = 'airwallex-default',
48
- PAYPAL_DEFAULT = 'paypal-default',
49
- VIVA_WALLET_DEFAULT = 'viva-wallet-default',
50
- PALATINE_DEFAULT = 'palatine-default',
51
- NATIXIS_DEFAULT = 'natixis-default',
52
- JPMORGAN_DEFAULT = 'jpmorgan-default',
53
- LA_NEF_V1 = 'la-nef-v1',
54
- LA_NEF_V2 = 'la-nef-v2',
55
- }
56
-
57
- /**
58
- * Display catalogue — one entry per supported (bank, version) pair.
59
- * Drives dropdowns, "supported banks" pages, and customer docs.
60
- */
61
- export interface RcbBankCatalogueEntry {
62
- id: RcbBankVersionId;
63
- bank: string;
64
- version: string;
65
- country: 'FR' | 'UK' | 'CH' | 'US' | 'PT' | 'EU' | 'INTL';
66
- type: 'retail' | 'business' | 'neobank' | 'fintech' | 'corporate';
67
- }
68
-
69
- export const RCB_BANK_CATALOGUE: ReadonlyArray<RcbBankCatalogueEntry> = [
70
- // ─── French retail / business ─────────────
71
- { id: RcbBankVersionId.BNP_CONNEXIS_DEFAULT, bank: 'BNP Connexis', version: 'default', country: 'FR', type: 'business' },
72
- { id: RcbBankVersionId.BNP_PARIBAS_DEFAULT, bank: 'BNP Paribas', version: 'default', country: 'FR', type: 'retail' },
73
- { id: RcbBankVersionId.SOCIETE_GENERALE_DEFAULT, bank: 'Société Générale', version: 'default', country: 'FR', type: 'retail' },
74
- { id: RcbBankVersionId.CREDIT_AGRICOLE_DEFAULT, bank: 'Crédit Agricole', version: 'default', country: 'FR', type: 'retail' },
75
- { id: RcbBankVersionId.LCL_DEFAULT, bank: 'LCL', version: 'default', country: 'FR', type: 'retail' },
76
- { id: RcbBankVersionId.BOURSORAMA_DEFAULT, bank: 'Boursorama', version: 'default', country: 'FR', type: 'retail' },
77
- { id: RcbBankVersionId.LA_BANQUE_POSTALE_DEFAULT, bank: 'La Banque Postale', version: 'default', country: 'FR', type: 'retail' },
78
- { id: RcbBankVersionId.CAISSE_EPARGNE_DEFAULT, bank: "Caisse d'Épargne", version: 'default', country: 'FR', type: 'retail' },
79
- { id: RcbBankVersionId.CIC_EBICS_DEFAULT, bank: 'CIC', version: 'ebics', country: 'FR', type: 'business' },
80
- { id: RcbBankVersionId.CIC_DEFAULT, bank: 'CIC', version: 'default', country: 'FR', type: 'retail' },
81
- { id: RcbBankVersionId.CREDIT_MUTUEL_DEFAULT, bank: 'Crédit Mutuel', version: 'default', country: 'FR', type: 'retail' },
82
- { id: RcbBankVersionId.BRED_DEFAULT, bank: 'BRED', version: 'default', country: 'FR', type: 'retail' },
83
- { id: RcbBankVersionId.CREDIT_DU_NORD_DEFAULT, bank: 'Crédit du Nord', version: 'default', country: 'FR', type: 'retail' },
84
- { id: RcbBankVersionId.CDE_NET_DEFAULT, bank: 'CDE Net', version: 'default', country: 'FR', type: 'business' },
85
- { id: RcbBankVersionId.DELUBAC_DEFAULT, bank: 'Delubac', version: 'default', country: 'FR', type: 'business' },
86
- { id: RcbBankVersionId.PALATINE_DEFAULT, bank: 'Palatine', version: 'default', country: 'FR', type: 'business' },
87
- { id: RcbBankVersionId.NATIXIS_DEFAULT, bank: 'Natixis', version: 'default', country: 'FR', type: 'corporate' },
88
- { id: RcbBankVersionId.THEMIS_DEFAULT, bank: 'Themis Banque', version: 'default', country: 'FR', type: 'business' },
89
- { id: RcbBankVersionId.ROTHSCHILD_DEFAULT, bank: 'Rothschild Martin Maurel', version: 'default', country: 'FR', type: 'corporate' },
90
- { id: RcbBankVersionId.LA_NEF_V1, bank: 'La Nef', version: 'v1', country: 'FR', type: 'retail' },
91
- { id: RcbBankVersionId.LA_NEF_V2, bank: 'La Nef', version: 'v2', country: 'FR', type: 'retail' },
92
-
93
- // ─── Neobanks / fintech ───────────────────
94
- { id: RcbBankVersionId.QONTO_DEFAULT, bank: 'Qonto', version: 'default', country: 'FR', type: 'neobank' },
95
- { id: RcbBankVersionId.SHINE_DEFAULT, bank: 'Shine', version: 'default', country: 'FR', type: 'neobank' },
96
- { id: RcbBankVersionId.FINOM_DEFAULT, bank: 'Finom', version: 'default', country: 'EU', type: 'neobank' },
97
- { id: RcbBankVersionId.TIIME_DEFAULT, bank: 'Tiime', version: 'default', country: 'FR', type: 'neobank' },
98
- { id: RcbBankVersionId.SPENDESK_DEFAULT, bank: 'Spendesk', version: 'default', country: 'FR', type: 'fintech' },
99
- { id: RcbBankVersionId.SWAN_DEFAULT, bank: 'Swan', version: 'default', country: 'FR', type: 'fintech' },
100
- { id: RcbBankVersionId.N26_DEFAULT, bank: 'N26', version: 'default', country: 'EU', type: 'neobank' },
101
- { id: RcbBankVersionId.REVOLUT_DEFAULT, bank: 'Revolut', version: 'default', country: 'EU', type: 'neobank' },
102
- { id: RcbBankVersionId.WISE_DEFAULT, bank: 'Wise', version: 'default', country: 'INTL', type: 'fintech' },
103
- { id: RcbBankVersionId.PAYPAL_DEFAULT, bank: 'PayPal', version: 'default', country: 'INTL', type: 'fintech' },
104
- { id: RcbBankVersionId.AIRWALLEX_DEFAULT, bank: 'Airwallex', version: 'default', country: 'INTL', type: 'fintech' },
105
- { id: RcbBankVersionId.VIVA_WALLET_DEFAULT, bank: 'Viva Wallet', version: 'default', country: 'EU', type: 'fintech' },
106
-
107
- // ─── International retail / corporate ─────
108
- { id: RcbBankVersionId.HSBC_DEFAULT, bank: 'HSBC', version: 'default', country: 'FR', type: 'retail' },
109
- { id: RcbBankVersionId.HSBC_UK_DEFAULT, bank: 'HSBC UK', version: 'default', country: 'UK', type: 'retail' },
110
- { id: RcbBankVersionId.UBS_DEFAULT, bank: 'UBS', version: 'default', country: 'CH', type: 'corporate' },
111
- { id: RcbBankVersionId.CAIXA_DEFAULT, bank: 'Caixa', version: 'default', country: 'PT', type: 'retail' },
112
- { id: RcbBankVersionId.JPMORGAN_DEFAULT, bank: 'JPMorgan', version: 'default', country: 'US', type: 'corporate' },
113
- ];
114
-
115
- /**
116
- * Lookup by id (typed). Returns undefined for unknown ids — callers should
117
- * treat that as "use auto mode" rather than crash.
118
- */
119
- export function getRcbBankCatalogueEntry(
120
- id: string,
121
- ): RcbBankCatalogueEntry | undefined {
122
- return RCB_BANK_CATALOGUE.find((e) => e.id === id);
123
- }
124
-
125
- /**
126
- * Group catalogue entries by the bank display name. Useful for UIs that
127
- * show "BNP Paribas" once with a sub-menu listing all supported versions.
128
- */
129
- export function groupRcbCatalogueByBank(): Map<string, RcbBankCatalogueEntry[]> {
130
- const out = new Map<string, RcbBankCatalogueEntry[]>();
131
- for (const entry of RCB_BANK_CATALOGUE) {
132
- const list = out.get(entry.bank) ?? [];
133
- list.push(entry);
134
- out.set(entry.bank, list);
135
- }
136
- return out;
137
- }
1
+ // ──────────────────────────────────────────────
2
+ // RCB — Formal catalogue of supported banks and versions.
3
+ //
4
+ // Mirrors the server-side registry (BANK_VERSIONS in abyss-tools/apps/api).
5
+ // Use these enums whenever you reference a bank or version in hint mode,
6
+ // UI dropdowns, or per-bank metrics. Adding a bank?
7
+ // 1. Add the entry to BANK_VERSIONS in apps/api.
8
+ // 2. Add the matching id here. CI will catch any mismatch.
9
+ // ──────────────────────────────────────────────
10
+
11
+ /**
12
+ * Stable id of a bank+version profile. The wire-format string used in
13
+ * `hint.bank` (POST /rcb/extract mode=hint) and returned in
14
+ * extraction.strategy_used.
15
+ */
16
+ export enum RcbBankVersionId {
17
+ BNP_CONNEXIS_DEFAULT = 'bnp-connexis-default',
18
+ BNP_PARIBAS_DEFAULT = 'bnp-paribas-default',
19
+ SOCIETE_GENERALE_DEFAULT = 'societe-generale-default',
20
+ CREDIT_AGRICOLE_DEFAULT = 'credit-agricole-default',
21
+ LCL_DEFAULT = 'lcl-default',
22
+ BOURSORAMA_DEFAULT = 'boursorama-default',
23
+ SPENDESK_DEFAULT = 'spendesk-default',
24
+ LA_BANQUE_POSTALE_DEFAULT = 'la-banque-postale-default',
25
+ CAISSE_EPARGNE_DEFAULT = 'caisse-epargne-default',
26
+ THEMIS_DEFAULT = 'themis-default',
27
+ CIC_EBICS_DEFAULT = 'cic-ebics-default',
28
+ CIC_DEFAULT = 'cic-default',
29
+ CREDIT_MUTUEL_DEFAULT = 'credit-mutuel-default',
30
+ N26_DEFAULT = 'n26-default',
31
+ REVOLUT_DEFAULT = 'revolut-default',
32
+ HSBC_DEFAULT = 'hsbc-default',
33
+ HSBC_UK_DEFAULT = 'hsbc-uk-default',
34
+ WISE_DEFAULT = 'wise-default',
35
+ CREDIT_DU_NORD_DEFAULT = 'cdn-default',
36
+ BRED_DEFAULT = 'bred-default',
37
+ QONTO_DEFAULT = 'qonto-default',
38
+ SHINE_DEFAULT = 'shine-default',
39
+ SWAN_DEFAULT = 'swan-default',
40
+ ROTHSCHILD_DEFAULT = 'rothschild-default',
41
+ FINOM_DEFAULT = 'finom-default',
42
+ TIIME_DEFAULT = 'tiime-default',
43
+ UBS_DEFAULT = 'ubs-default',
44
+ CAIXA_DEFAULT = 'caixa-default',
45
+ CDE_NET_DEFAULT = 'cde-net-default',
46
+ DELUBAC_DEFAULT = 'delubac-default',
47
+ AIRWALLEX_DEFAULT = 'airwallex-default',
48
+ PAYPAL_DEFAULT = 'paypal-default',
49
+ VIVA_WALLET_DEFAULT = 'viva-wallet-default',
50
+ PALATINE_DEFAULT = 'palatine-default',
51
+ NATIXIS_DEFAULT = 'natixis-default',
52
+ JPMORGAN_DEFAULT = 'jpmorgan-default',
53
+ LA_NEF_V1 = 'la-nef-v1',
54
+ LA_NEF_V2 = 'la-nef-v2',
55
+ }
56
+
57
+ /**
58
+ * Display catalogue — one entry per supported (bank, version) pair.
59
+ * Drives dropdowns, "supported banks" pages, and customer docs.
60
+ */
61
+ export interface RcbBankCatalogueEntry {
62
+ id: RcbBankVersionId;
63
+ bank: string;
64
+ version: string;
65
+ country: 'FR' | 'UK' | 'CH' | 'US' | 'PT' | 'EU' | 'INTL';
66
+ type: 'retail' | 'business' | 'neobank' | 'fintech' | 'corporate';
67
+ }
68
+
69
+ export const RCB_BANK_CATALOGUE: ReadonlyArray<RcbBankCatalogueEntry> = [
70
+ // ─── French retail / business ─────────────
71
+ { id: RcbBankVersionId.BNP_CONNEXIS_DEFAULT, bank: 'BNP Connexis', version: 'default', country: 'FR', type: 'business' },
72
+ { id: RcbBankVersionId.BNP_PARIBAS_DEFAULT, bank: 'BNP Paribas', version: 'default', country: 'FR', type: 'retail' },
73
+ { id: RcbBankVersionId.SOCIETE_GENERALE_DEFAULT, bank: 'Société Générale', version: 'default', country: 'FR', type: 'retail' },
74
+ { id: RcbBankVersionId.CREDIT_AGRICOLE_DEFAULT, bank: 'Crédit Agricole', version: 'default', country: 'FR', type: 'retail' },
75
+ { id: RcbBankVersionId.LCL_DEFAULT, bank: 'LCL', version: 'default', country: 'FR', type: 'retail' },
76
+ { id: RcbBankVersionId.BOURSORAMA_DEFAULT, bank: 'Boursorama', version: 'default', country: 'FR', type: 'retail' },
77
+ { id: RcbBankVersionId.LA_BANQUE_POSTALE_DEFAULT, bank: 'La Banque Postale', version: 'default', country: 'FR', type: 'retail' },
78
+ { id: RcbBankVersionId.CAISSE_EPARGNE_DEFAULT, bank: "Caisse d'Épargne", version: 'default', country: 'FR', type: 'retail' },
79
+ { id: RcbBankVersionId.CIC_EBICS_DEFAULT, bank: 'CIC', version: 'ebics', country: 'FR', type: 'business' },
80
+ { id: RcbBankVersionId.CIC_DEFAULT, bank: 'CIC', version: 'default', country: 'FR', type: 'retail' },
81
+ { id: RcbBankVersionId.CREDIT_MUTUEL_DEFAULT, bank: 'Crédit Mutuel', version: 'default', country: 'FR', type: 'retail' },
82
+ { id: RcbBankVersionId.BRED_DEFAULT, bank: 'BRED', version: 'default', country: 'FR', type: 'retail' },
83
+ { id: RcbBankVersionId.CREDIT_DU_NORD_DEFAULT, bank: 'Crédit du Nord', version: 'default', country: 'FR', type: 'retail' },
84
+ { id: RcbBankVersionId.CDE_NET_DEFAULT, bank: 'CDE Net', version: 'default', country: 'FR', type: 'business' },
85
+ { id: RcbBankVersionId.DELUBAC_DEFAULT, bank: 'Delubac', version: 'default', country: 'FR', type: 'business' },
86
+ { id: RcbBankVersionId.PALATINE_DEFAULT, bank: 'Palatine', version: 'default', country: 'FR', type: 'business' },
87
+ { id: RcbBankVersionId.NATIXIS_DEFAULT, bank: 'Natixis', version: 'default', country: 'FR', type: 'corporate' },
88
+ { id: RcbBankVersionId.THEMIS_DEFAULT, bank: 'Themis Banque', version: 'default', country: 'FR', type: 'business' },
89
+ { id: RcbBankVersionId.ROTHSCHILD_DEFAULT, bank: 'Rothschild Martin Maurel', version: 'default', country: 'FR', type: 'corporate' },
90
+ { id: RcbBankVersionId.LA_NEF_V1, bank: 'La Nef', version: 'v1', country: 'FR', type: 'retail' },
91
+ { id: RcbBankVersionId.LA_NEF_V2, bank: 'La Nef', version: 'v2', country: 'FR', type: 'retail' },
92
+
93
+ // ─── Neobanks / fintech ───────────────────
94
+ { id: RcbBankVersionId.QONTO_DEFAULT, bank: 'Qonto', version: 'default', country: 'FR', type: 'neobank' },
95
+ { id: RcbBankVersionId.SHINE_DEFAULT, bank: 'Shine', version: 'default', country: 'FR', type: 'neobank' },
96
+ { id: RcbBankVersionId.FINOM_DEFAULT, bank: 'Finom', version: 'default', country: 'EU', type: 'neobank' },
97
+ { id: RcbBankVersionId.TIIME_DEFAULT, bank: 'Tiime', version: 'default', country: 'FR', type: 'neobank' },
98
+ { id: RcbBankVersionId.SPENDESK_DEFAULT, bank: 'Spendesk', version: 'default', country: 'FR', type: 'fintech' },
99
+ { id: RcbBankVersionId.SWAN_DEFAULT, bank: 'Swan', version: 'default', country: 'FR', type: 'fintech' },
100
+ { id: RcbBankVersionId.N26_DEFAULT, bank: 'N26', version: 'default', country: 'EU', type: 'neobank' },
101
+ { id: RcbBankVersionId.REVOLUT_DEFAULT, bank: 'Revolut', version: 'default', country: 'EU', type: 'neobank' },
102
+ { id: RcbBankVersionId.WISE_DEFAULT, bank: 'Wise', version: 'default', country: 'INTL', type: 'fintech' },
103
+ { id: RcbBankVersionId.PAYPAL_DEFAULT, bank: 'PayPal', version: 'default', country: 'INTL', type: 'fintech' },
104
+ { id: RcbBankVersionId.AIRWALLEX_DEFAULT, bank: 'Airwallex', version: 'default', country: 'INTL', type: 'fintech' },
105
+ { id: RcbBankVersionId.VIVA_WALLET_DEFAULT, bank: 'Viva Wallet', version: 'default', country: 'EU', type: 'fintech' },
106
+
107
+ // ─── International retail / corporate ─────
108
+ { id: RcbBankVersionId.HSBC_DEFAULT, bank: 'HSBC', version: 'default', country: 'FR', type: 'retail' },
109
+ { id: RcbBankVersionId.HSBC_UK_DEFAULT, bank: 'HSBC UK', version: 'default', country: 'UK', type: 'retail' },
110
+ { id: RcbBankVersionId.UBS_DEFAULT, bank: 'UBS', version: 'default', country: 'CH', type: 'corporate' },
111
+ { id: RcbBankVersionId.CAIXA_DEFAULT, bank: 'Caixa', version: 'default', country: 'PT', type: 'retail' },
112
+ { id: RcbBankVersionId.JPMORGAN_DEFAULT, bank: 'JPMorgan', version: 'default', country: 'US', type: 'corporate' },
113
+ ];
114
+
115
+ /**
116
+ * Lookup by id (typed). Returns undefined for unknown ids — callers should
117
+ * treat that as "use auto mode" rather than crash.
118
+ */
119
+ export function getRcbBankCatalogueEntry(
120
+ id: string,
121
+ ): RcbBankCatalogueEntry | undefined {
122
+ return RCB_BANK_CATALOGUE.find((e) => e.id === id);
123
+ }
124
+
125
+ /**
126
+ * Group catalogue entries by the bank display name. Useful for UIs that
127
+ * show "BNP Paribas" once with a sub-menu listing all supported versions.
128
+ */
129
+ export function groupRcbCatalogueByBank(): Map<string, RcbBankCatalogueEntry[]> {
130
+ const out = new Map<string, RcbBankCatalogueEntry[]>();
131
+ for (const entry of RCB_BANK_CATALOGUE) {
132
+ const list = out.get(entry.bank) ?? [];
133
+ list.push(entry);
134
+ out.set(entry.bank, list);
135
+ }
136
+ return out;
137
+ }