@cobre-npm/library-portal-core 0.55.0 → 0.57.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.
Files changed (61) hide show
  1. package/README.md +117 -23
  2. package/dist/cjs/businessLines/catalog.d.ts +19 -0
  3. package/dist/cjs/businessLines/catalog.js +10 -0
  4. package/dist/cjs/businessLines/index.d.ts +2 -0
  5. package/dist/cjs/businessLines/index.js +17 -0
  6. package/dist/cjs/businessLines/utils/business-line.utils.d.ts +2 -0
  7. package/dist/cjs/businessLines/utils/business-line.utils.js +6 -0
  8. package/dist/cjs/filterClassification/categoryFamilies/catalog.d.ts +33 -0
  9. package/dist/cjs/filterClassification/categoryFamilies/catalog.js +12 -0
  10. package/dist/cjs/filterClassification/categoryFamilies/locales/en.json +11 -0
  11. package/dist/cjs/filterClassification/categoryFamilies/locales/es-mex.json +11 -0
  12. package/dist/cjs/filterClassification/categoryFamilies/utils/filter-classification-category-family.utils.d.ts +8 -0
  13. package/dist/cjs/filterClassification/categoryFamilies/utils/filter-classification-category-family.utils.js +19 -0
  14. package/dist/cjs/filterClassification/index.d.ts +7 -0
  15. package/dist/cjs/filterClassification/index.js +20 -0
  16. package/dist/cjs/filterClassification/interfaces/filter-classification.interface.d.ts +14 -0
  17. package/dist/cjs/filterClassification/interfaces/filter-classification.interface.js +2 -0
  18. package/dist/cjs/filterClassification/sections/catalog.d.ts +28 -0
  19. package/dist/cjs/filterClassification/sections/catalog.js +13 -0
  20. package/dist/cjs/filterClassification/sections/locales/en.json +12 -0
  21. package/dist/cjs/filterClassification/sections/locales/es-mex.json +12 -0
  22. package/dist/cjs/filterClassification/sections/utils/filter-classification-section.utils.d.ts +7 -0
  23. package/dist/cjs/filterClassification/sections/utils/filter-classification-section.utils.js +20 -0
  24. package/dist/cjs/filterClassification/utils/type-group.utils.d.ts +13 -0
  25. package/dist/cjs/filterClassification/utils/type-group.utils.js +24 -0
  26. package/dist/cjs/filterClassification/utils/type-label.utils.d.ts +9 -0
  27. package/dist/cjs/filterClassification/utils/type-label.utils.js +17 -0
  28. package/dist/cjs/movements/index.d.ts +1 -1
  29. package/dist/cjs/movements/types/catalog.d.ts +27 -16
  30. package/dist/cjs/movements/types/catalog.js +26 -26
  31. package/dist/cjs/movements/types/utils/movement-type.utils.d.ts +1 -8
  32. package/dist/cjs/movements/types/utils/movement-type.utils.js +1 -8
  33. package/dist/cjs/transactions/index.d.ts +1 -2
  34. package/dist/cjs/transactions/types/catalog.d.ts +108 -0
  35. package/dist/cjs/transactions/types/catalog.js +101 -0
  36. package/dist/cjs/transactions/types/locales/en.json +9 -0
  37. package/dist/cjs/transactions/types/locales/es-mex.json +9 -0
  38. package/dist/cjs/transactions/types/utils/transaction-type.utils.d.ts +12 -1
  39. package/dist/cjs/transactions/types/utils/transaction-type.utils.js +30 -1
  40. package/dist/esm/businessLines/catalog.js +7 -0
  41. package/dist/esm/businessLines/index.js +1 -0
  42. package/dist/esm/businessLines/utils/business-line.utils.js +2 -0
  43. package/dist/esm/filterClassification/categoryFamilies/catalog.js +9 -0
  44. package/dist/esm/filterClassification/categoryFamilies/locales/en.json +11 -0
  45. package/dist/esm/filterClassification/categoryFamilies/locales/es-mex.json +11 -0
  46. package/dist/esm/filterClassification/categoryFamilies/utils/filter-classification-category-family.utils.js +12 -0
  47. package/dist/esm/filterClassification/index.js +4 -0
  48. package/dist/esm/filterClassification/interfaces/filter-classification.interface.js +1 -0
  49. package/dist/esm/filterClassification/sections/catalog.js +10 -0
  50. package/dist/esm/filterClassification/sections/locales/en.json +12 -0
  51. package/dist/esm/filterClassification/sections/locales/es-mex.json +12 -0
  52. package/dist/esm/filterClassification/sections/utils/filter-classification-section.utils.js +13 -0
  53. package/dist/esm/filterClassification/utils/type-group.utils.js +18 -0
  54. package/dist/esm/filterClassification/utils/type-label.utils.js +13 -0
  55. package/dist/esm/movements/types/catalog.js +26 -26
  56. package/dist/esm/movements/types/utils/movement-type.utils.js +1 -8
  57. package/dist/esm/transactions/types/catalog.js +101 -0
  58. package/dist/esm/transactions/types/locales/en.json +9 -0
  59. package/dist/esm/transactions/types/locales/es-mex.json +9 -0
  60. package/dist/esm/transactions/types/utils/transaction-type.utils.js +28 -0
  61. package/package.json +11 -1
package/README.md CHANGED
@@ -39,12 +39,14 @@ import { getCountries } from "@cobre-npm/library-portal-core/countries"
39
39
  | `@cobre-npm/library-portal-core/counterparties` | Counterparty types + `Counterparty` interfaces |
40
40
  | `@cobre-npm/library-portal-core/countries` | Countries (base) and ISO countries (dialing codes, etc.) |
41
41
  | `@cobre-npm/library-portal-core/movements` | Movement types and statuses |
42
+ | `@cobre-npm/library-portal-core/businessLines` | Cobre's lines of business (LoB) |
42
43
  | `@cobre-npm/library-portal-core/subclients` | Subclient statuses + `Subclient`/`SubclientPerson` interfaces |
43
44
  | `@cobre-npm/library-portal-core/documentTypes` | Document types (definition + per-country applicability) |
44
45
  | `@cobre-npm/library-portal-core/currencies` | Currencies |
45
46
  | `@cobre-npm/library-portal-core/transactions` | Transaction types + interfaces |
46
47
  | `@cobre-npm/library-portal-core/canonicalTransactions` | Canonical transaction/money-movement detail interfaces |
47
48
  | `@cobre-npm/library-portal-core/search` | Search / aggregation interfaces |
49
+ | `@cobre-npm/library-portal-core/filterClassification` | Grouped type-filter vocabulary (families, sections, categories), `splitTypeLabel`, group-selection helpers |
48
50
  | `@cobre-npm/library-portal-core/trustedSessions` | Trusted session (OTP elevation window) interfaces + constants |
49
51
  | `@cobre-npm/library-portal-core/exports` | Export request/response entity + the engine's format/operator allow-lists |
50
52
  | `@cobre-npm/library-portal-core/financialInstitutions` | Financial institutions (banks) by country, with labels |
@@ -254,44 +256,37 @@ queryCountries({ lang, ...(codes ? { code: codes } : {}) })
254
256
 
255
257
  ```ts
256
258
  import {
257
- getMovementTypes, queryMovementTypes, type MovementType, type MovementTypeGroupLabel,
259
+ getMovementTypes, queryMovementTypes, type MovementType,
258
260
  type MovementTypeOption, type MovementTypeQuery,
259
- type ClassificationLine, type ClassificationCategory,
260
261
  getMovementStatuses, queryMovementStatuses, type MovementStatus, type MovementStatusType,
261
262
  type MovementStatusOption, type MovementStatusQuery,
262
263
  } from "@cobre-npm/library-portal-core/movements"
263
264
 
264
265
  getMovementTypes("en").ach.label // "Transfer · ACH"
265
- getMovementTypes("en").on_ramp.groupLabel // "Stablecoin"
266
+ getMovementTypes("en").on_ramp.section // "stablecoin"
266
267
  getMovementTypes("en").on_ramp.label // "Conversion to stablecoin" (individual label)
267
268
  getMovementTypes("en").spei.category // "payments"
268
269
  queryMovementTypes({ lang: "en", category: "top_up" }) // r2p_top_up_bancolombia, r2p_top_up_pse
269
- queryMovementTypes({ lang: "en", groupLabel: "Stablecoin" }) // global, off_ramp, on_ramp, stable_payout
270
+ queryMovementTypes({ lang: "en", section: "stablecoin" }) // global, off_ramp, on_ramp, stable_payout
270
271
  getMovementStatuses("en").completed // { code: "completed", label: "Completed", type: "success", icon: "icon-check" }
271
272
  queryMovementStatuses({ lang: "en", type: "error" }) // error, failed, rejected — localized
272
273
  ```
273
274
 
274
275
  - **types** (i18n): movement types, usually labelled as "what you did · rail" (`Transfer · SPEI`,
275
276
  `Collection · Bre-B`). Movement and transaction types share one classification, carried on each record as
276
- codes, not translated text (nothing displays them yet): `line: ClassificationLine`
277
- (`payin | payout | cbmm | stable | unclassified`) and `category: ClassificationCategory`
278
- (`payments | collections | conversions | international | between_accounts | top_up | adjustment |
279
- reward | unclassified`). Both types are exported from `/movements` and `/transactions` (the same types on
280
- both subpaths). `on_ramp`/`off_ramp`/`stable_payout`/`global`
281
- additionally carry `groupLabel: "Stablecoin"` — a display grouping for views that need to show them
282
- under one label. `getMovementTypes()` keeps returning each rail's own individual `label` unchanged; a
283
- consumer that wants the grouped label picks `groupLabel ?? label`. There's no separate `getXLabel`
284
- for this — the value already comes back inside `getMovementTypes()`, same as everything else in this
285
- catalog.
277
+ codes, not translated text (nothing displays them yet): `line: BusinessLine`
278
+ (`payin | payout | cbmm | stable | unclassified`, defined in [`businessLines`](#businesslines)) and
279
+ `category: FilterClassificationCategory` (`payments | collections | conversions | international | between_accounts | top_up |
280
+ adjustment | reward | unclassified`, defined in [`filterClassification`](#filterclassification)). Each movement type also carries a
281
+ `section: FilterClassificationSection` (`cop | mxn | usd_global | eur | corridors | stablecoin | …`), the heading it
282
+ is listed under in grouped filters. `getMovementTypes()` returns each rail's own `label` unchanged.
286
283
  - **types query** (i18n `queryX()`): `queryMovementTypes({ lang, ...filters })` — same rules as
287
- `queryTransactionTypes`/`queryDocumentTypes`, no default field. `code`, `line`, `category`, `group` and
288
- `groupLabel` are filterable (equality only; a list matches any of its values). Filter by `group`, not
289
- `groupLabel` — the label is display text. Both are optional on the record: **a key that is present always filters**, so
290
- `groupLabel: undefined` matches the rails that don't carry a group, not "no filter". An optional UI
284
+ `queryTransactionTypes`/`queryDocumentTypes`, no default field. `code`, `line`, `category` and `section` are
285
+ filterable (equality only; a list matches any of its values). A present key always filters, so an optional UI
291
286
  filter has to be spread in conditionally:
292
287
 
293
288
  ```ts
294
- queryMovementTypes({ lang, ...(group.value ? { groupLabel: group.value } : {}) })
289
+ queryMovementTypes({ lang, ...(section.value ? { section: section.value } : {}) })
295
290
  ```
296
291
  - **status** (i18n): movement statuses (`initiated`, `processing`, `completed`, …). Each record also
297
292
  carries `type: MovementStatusType` (`success | warning | error | info | neutral | pending`) — a
@@ -306,6 +301,21 @@ queryMovementStatuses({ lang: "en", type: "error" }) // error, failed, rejected
306
301
  the real use case: `queryMovementStatuses({ lang, type: "error" })` returns `error`, `failed`,
307
302
  `rejected`, replacing a hand-maintained list of codes with a query.
308
303
 
304
+ ### `businessLines`
305
+
306
+ Cobre's lines of business (LoB). No i18n (no labels exist yet), so `getBusinessLines()` takes no arguments.
307
+
308
+ ```ts
309
+ import { getBusinessLines, type BusinessLine } from "@cobre-npm/library-portal-core/businessLines"
310
+
311
+ getBusinessLines().cbmm // { code: "cbmm" }
312
+ ```
313
+
314
+ - **lines**: `payin`, `payout`, `cbmm`, `stable`, `unclassified`. `BusinessLine` is the type of the `line` field of
315
+ movement and transaction types.
316
+ - `/movements` and `/transactions` no longer re-export the line/category types (formerly `ClassificationLine` /
317
+ `ClassificationCategory`): use `BusinessLine` from `/businessLines` and `FilterClassificationCategory` from [`/filterClassification`](#filterclassification).
318
+
309
319
  ### `subclients`
310
320
 
311
321
  ```ts
@@ -430,9 +440,10 @@ And two on rule 1: `{ minAmount: 1 }` is equality, not `>=`, which is rarely wha
430
440
  ```ts
431
441
  import {
432
442
  getTransactionTypes, queryTransactionTypes, type TransactionType, type TransactionTypeQuery,
433
- type ClassificationLine, type ClassificationCategory,
443
+ collapseTransactionTypes, type TransactionTypeGroup, type TransactionTypeGroupOption,
434
444
  type Transaction, type EnrichedTransaction, /* ...interfaces */
435
445
  } from "@cobre-npm/library-portal-core/transactions"
446
+ import { isGroupOption, expandGroupSelection } from "@cobre-npm/library-portal-core/filterClassification"
436
447
 
437
448
  getTransactionTypes("en").spei_debit.label // "Outgoing transfer · SPEI"
438
449
  getTransactionTypes("es-mex").spei_debit.label // "Transferencia enviada · SPEI"
@@ -442,13 +453,40 @@ queryTransactionTypes({ lang: "en", category: "top_up" }) // col_top_up_credit
442
453
 
443
454
  - **types** (i18n): `getTransactionTypes(lang)`; each record carries `code`, `creditDebitType`
444
455
  (`"credit" | "debit"` — the same `CreditDebitType` used by the `Transaction` interface), `label`, and the same
445
- `line: ClassificationLine` / `category: ClassificationCategory` codes as movement types (value sets
456
+ `line: BusinessLine` / `category: FilterClassificationCategory` codes as movement types (value sets
446
457
  listed under [`movements`](#movements)). Labels are usually "what you did · rail" (`Outgoing transfer ·
447
458
  SPEI`). Types that stand for a collapsed matrix row (`cbmm_*`, `internal_*`, `mex_*`, `col_debit`/`col_credit`, `misc_*`,
448
459
  `adjustment_*`, `col_cb_*`, the corridors, ramps and `stable_payout_*`, plus `transfer_credit`) add a
449
460
  "· débito" / "· crédito" (en "· debit" / "· credit") suffix, except `offramp_treasury_credit`, whose label has none; elsewhere the direction is in the verb
450
461
  ("Outgoing transfer", "Incoming transfer"). `col_cb_*` keeps "Cobre Balance" in its label. `misc_*`,
451
462
  `internal_*` and `adjustment_*` have `line: "unclassified"`, and `misc_*` also `category: "unclassified"`.
463
+ Each type also carries a required `section: FilterClassificationSection`, the heading it is listed under in the
464
+ grouped filter (group members take their group's section; `internal_spei_*`, `col_cb_debit` → `internal`,
465
+ `misc_*` → `connected_account`).
466
+ - **conditional marker**: five rarely used types (`misc_debit`, `misc_credit`, `col_cb_debit`, `internal_spei_debit`,
467
+ `internal_spei_credit`) carry `filterDisplay: "when_present"`: the grouped filter should list them only when the
468
+ data has them. It is descriptive, not a visibility switch: there is no default, `queryTransactionTypes()` still
469
+ returns them and their labels are unchanged, so flat filters see no difference. The field is absent on every
470
+ other type, so read it with `"filterDisplay" in type`.
471
+ - **group**: every type carries a required `group: TransactionTypeGroup | null`. The 14 debit/credit legs name
472
+ one of 7 UI-only groups (`cbmm`, `global_pay_to_usa`, `usa_pay_to_global`, `on_ramp`, `off_ramp`,
473
+ `stable_payout`, `internal`); every other type is `null`. A group code is **never** a transaction type and is
474
+ never sent to the API: selecting a group means selecting its member codes (`expandGroupSelection`). There is no
475
+ separate groups catalog; group labels come out of `collapseTransactionTypes`.
476
+ - **collapse** (i18n): `collapseTransactionTypes({ lang, ...filters })` takes the same query as
477
+ `queryTransactionTypes`, filters first, then folds each group into one `TransactionTypeGroupOption`
478
+ `{ code, members, line, category, section, label }`, placed at its first member's position. A group collapses
479
+ only if **all** its legs survive the filter; otherwise the surviving legs come out as plain options. Tell the
480
+ two apart with `isGroupOption` (from [`filterClassification`](#filterclassification)), which also feeds
481
+ `expandGroupSelection` / `getGroupSelectionState`:
482
+
483
+ ```ts
484
+ collapseTransactionTypes({ lang: "en", category: "conversions" }).map(option => option.code)
485
+ // 7 conversion types → 4 options: ["on_ramp", "off_ramp", "stable_payout", "offramp_treasury_credit"]
486
+ collapseTransactionTypes({ lang: "en", creditDebitType: "debit" }) // no group survives: plain legs only
487
+ const groups = collapseTransactionTypes({ lang: "en" }).filter(isGroupOption)
488
+ expandGroupSelection(["cbmm", "spei_debit"], groups) // ["cbmm_debit", "cbmm_credit", "spei_debit"]
489
+ ```
452
490
  - **types query** (i18n `queryX()`): `queryTransactionTypes({ lang, ...filters })` — `lang` is **required inside
453
491
  the query object**, not a separate argument, so the result is already localized. There is no default field
454
492
  (unlike `currencies`' `scope`): every transaction type comes back when only `lang` is given.
@@ -457,12 +495,68 @@ queryTransactionTypes({ lang: "en", category: "top_up" }) // col_top_up_credit
457
495
  `queryTransactionTypes({ lang: "en", line: "payin", category: "collections" })`.
458
496
  - **interfaces**: `Transaction`, `EnrichedTransaction`, `TransactionMetadata`, `CreditDebitType`.
459
497
 
460
- ### `search` / `trustedSessions`
498
+ ### `search`
461
499
 
462
- Interfaces only (pure types):
500
+ Interfaces only (pure types): the Cobre Search request/response contract.
463
501
 
464
502
  ```ts
465
503
  import type { SearchRequest, SearchResponse, SearchFilter } from "@cobre-npm/library-portal-core/search"
504
+ ```
505
+
506
+ ### `filterClassification`
507
+
508
+ The vocabulary of the grouped type filter, shared by movement and transaction types and owned by neither (some
509
+ transactions, like adjustments and rewards, have no money movement): **families** are the chips, **sections** are
510
+ the headings inside a chip, and **types** (movement / transaction types) are the options.
511
+
512
+ ```ts
513
+ import {
514
+ getFilterClassificationCategoryFamilies, getFilterClassificationSections, splitTypeLabel,
515
+ expandGroupSelection, getGroupSelectionState, isGroupOption,
516
+ type FilterClassificationCategoryFamily, type FilterClassificationSection,
517
+ type FilterClassificationCategory, type FilterClassificationRecord,
518
+ } from "@cobre-npm/library-portal-core/filterClassification"
519
+
520
+ declare const types: { category: FilterClassificationCategory }[] // e.g. Object.values(getMovementTypes("en"))
521
+ declare const record: { section: FilterClassificationSection } // one of those types
522
+ declare const groups: FilterClassificationRecord<string>[] // the UI's group records
523
+ declare const group: FilterClassificationRecord<string> // one of them
524
+ declare const selectedCodes: string[] // what the user has ticked
525
+ declare const options: ({ code: string } | FilterClassificationRecord<string>)[] // a mixed list: plain and group options
526
+
527
+ const families = getFilterClassificationCategoryFamilies("en")
528
+ families.between_accounts.label // "Between accounts"
529
+ families.between_accounts.categories // ["between_accounts", "adjustment", "reward"]
530
+ types.filter(type => families.between_accounts.categories.includes(type.category)) // group types by family
531
+ getFilterClassificationSections("es-mex")[record.section].label // "Corredores"
532
+ splitTypeLabel("Transfer · ACH") // { title: "Transfer", rail: "ACH" }
533
+ splitTypeLabel("International") // { title: "International" } — no empty rail
534
+ expandGroupSelection(["stablecoin_group", "ach"], groups) // member codes + "ach"; the group code is never returned
535
+ getGroupSelectionState(group, selectedCodes) // "checked" | "indeterminate" | "unchecked"
536
+ options.filter(isGroupOption) // only the group options, typed as such
537
+ ```
538
+
539
+ - **Family** (`FilterClassificationCategoryFamily`): the chips of the grouped type filter, in chip order: `payments`, `collections`,
540
+ `international`, `conversions`, `top_up`, `between_accounts` and `unclassified`. Each family lists the
541
+ `categories` it groups, and a category belongs to exactly one family (`adjustment` and `reward` fold into
542
+ `between_accounts`). `getFilterClassificationCategoryFamilies(lang)` returns each family with its label and categories; `lang` is required.
543
+ - **Category** (`FilterClassificationCategory`): derived from the families' lists: `payments`, `collections`, `conversions`,
544
+ `international`, `between_accounts`, `top_up`, `adjustment`, `reward`, `unclassified`. The family is never stored
545
+ per record: group types by family with `getFilterClassificationCategoryFamilies(lang)[family].categories.includes(type.category)`.
546
+ - **Section** (`FilterClassificationSection`): groups types by currency, rail or corridor (`cop`, `mxn`, `usd_global`, `eur`,
547
+ `corridors`, `stablecoin`). It is stored per type, used as a heading in the grouped filter, never selectable and
548
+ never sent to an API. `getFilterClassificationSections(lang)`. `internal` and `connected_account` exist but no movement type uses
549
+ them yet.
550
+ - **`splitTypeLabel(label)`**: splits at the first `" · "` into `{ title, rail? }` for two-line options.
551
+ - **group helpers**: `FilterClassificationRecord<Code, Member = Code>` (`code`, `members`, `line`, `category`, `section`). A group code is a UI
552
+ identifier: `expandGroupSelection` swaps it for its members before calling an API, `getGroupSelectionState`
553
+ gives the checkbox state from the selected member codes, and `isGroupOption` tells group options from plain ones in a mixed list.
554
+
555
+ ### `trustedSessions`
556
+
557
+ Interfaces only (pure types):
558
+
559
+ ```ts
466
560
  import type { TrustedSessionStatus } from "@cobre-npm/library-portal-core/trustedSessions"
467
561
  ```
468
562
 
@@ -0,0 +1,19 @@
1
+ export declare const BUSINESS_LINES: {
2
+ readonly payin: {
3
+ readonly code: "payin";
4
+ };
5
+ readonly payout: {
6
+ readonly code: "payout";
7
+ };
8
+ readonly cbmm: {
9
+ readonly code: "cbmm";
10
+ };
11
+ readonly stable: {
12
+ readonly code: "stable";
13
+ };
14
+ readonly unclassified: {
15
+ readonly code: "unclassified";
16
+ };
17
+ };
18
+ export type BusinessLine = keyof typeof BUSINESS_LINES;
19
+ export type BusinessLineRecord = (typeof BUSINESS_LINES)[BusinessLine];
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BUSINESS_LINES = void 0;
4
+ exports.BUSINESS_LINES = {
5
+ payin: { code: "payin" },
6
+ payout: { code: "payout" },
7
+ cbmm: { code: "cbmm" },
8
+ stable: { code: "stable" },
9
+ unclassified: { code: "unclassified" },
10
+ };
@@ -0,0 +1,2 @@
1
+ export type { BusinessLine, BusinessLineRecord } from "./catalog";
2
+ export * from "./utils/business-line.utils";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./utils/business-line.utils"), exports);
@@ -0,0 +1,2 @@
1
+ import type { BusinessLine, BusinessLineRecord } from "../catalog";
2
+ export declare const getBusinessLines: () => Record<BusinessLine, BusinessLineRecord>;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBusinessLines = void 0;
4
+ const catalog_1 = require("../catalog");
5
+ const getBusinessLines = () => catalog_1.BUSINESS_LINES;
6
+ exports.getBusinessLines = getBusinessLines;
@@ -0,0 +1,33 @@
1
+ export declare const FILTER_CLASSIFICATION_CATEGORY_FAMILIES: {
2
+ readonly payments: {
3
+ readonly code: "payments";
4
+ readonly categories: readonly ["payments"];
5
+ };
6
+ readonly collections: {
7
+ readonly code: "collections";
8
+ readonly categories: readonly ["collections"];
9
+ };
10
+ readonly international: {
11
+ readonly code: "international";
12
+ readonly categories: readonly ["international"];
13
+ };
14
+ readonly conversions: {
15
+ readonly code: "conversions";
16
+ readonly categories: readonly ["conversions"];
17
+ };
18
+ readonly top_up: {
19
+ readonly code: "top_up";
20
+ readonly categories: readonly ["top_up"];
21
+ };
22
+ readonly between_accounts: {
23
+ readonly code: "between_accounts";
24
+ readonly categories: readonly ["between_accounts", "adjustment", "reward"];
25
+ };
26
+ readonly unclassified: {
27
+ readonly code: "unclassified";
28
+ readonly categories: readonly ["unclassified"];
29
+ };
30
+ };
31
+ export type FilterClassificationCategoryFamily = keyof typeof FILTER_CLASSIFICATION_CATEGORY_FAMILIES;
32
+ export type FilterClassificationCategoryFamilyRecord = (typeof FILTER_CLASSIFICATION_CATEGORY_FAMILIES)[FilterClassificationCategoryFamily];
33
+ export type FilterClassificationCategory = FilterClassificationCategoryFamilyRecord["categories"][number];
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FILTER_CLASSIFICATION_CATEGORY_FAMILIES = void 0;
4
+ exports.FILTER_CLASSIFICATION_CATEGORY_FAMILIES = {
5
+ payments: { code: "payments", categories: ["payments"] },
6
+ collections: { code: "collections", categories: ["collections"] },
7
+ international: { code: "international", categories: ["international"] },
8
+ conversions: { code: "conversions", categories: ["conversions"] },
9
+ top_up: { code: "top_up", categories: ["top_up"] },
10
+ between_accounts: { code: "between_accounts", categories: ["between_accounts", "adjustment", "reward"] },
11
+ unclassified: { code: "unclassified", categories: ["unclassified"] },
12
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ "categoryFamilies": {
3
+ "payments": "Payments",
4
+ "collections": "Collections",
5
+ "international": "International",
6
+ "conversions": "Conversions",
7
+ "top_up": "Top-up",
8
+ "between_accounts": "Between accounts",
9
+ "unclassified": "Unclassified"
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "categoryFamilies": {
3
+ "payments": "Pagos",
4
+ "collections": "Recaudos",
5
+ "international": "Internacional",
6
+ "conversions": "Conversiones",
7
+ "top_up": "Recarga",
8
+ "between_accounts": "Entre cuentas",
9
+ "unclassified": "Sin clasificar"
10
+ }
11
+ }
@@ -0,0 +1,8 @@
1
+ import type { FilterClassificationCategory, FilterClassificationCategoryFamily } from "../catalog";
2
+ import type { Locale } from "../../../lang";
3
+ export type FilterClassificationCategoryFamilyOption = {
4
+ code: FilterClassificationCategoryFamily;
5
+ categories: readonly FilterClassificationCategory[];
6
+ label: string;
7
+ };
8
+ export declare const getFilterClassificationCategoryFamilies: (lang: Locale) => Record<FilterClassificationCategoryFamily, FilterClassificationCategoryFamilyOption>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getFilterClassificationCategoryFamilies = void 0;
7
+ const catalog_1 = require("../catalog");
8
+ const en_json_1 = __importDefault(require("../locales/en.json"));
9
+ const es_mex_json_1 = __importDefault(require("../locales/es-mex.json"));
10
+ const locales = { en: en_json_1.default, "es-mex": es_mex_json_1.default };
11
+ const getFilterClassificationCategoryFamilies = (lang) => {
12
+ const locale = locales[lang];
13
+ const result = {};
14
+ for (const record of Object.values(catalog_1.FILTER_CLASSIFICATION_CATEGORY_FAMILIES)) {
15
+ result[record.code] = { ...record, label: locale.categoryFamilies[record.code] };
16
+ }
17
+ return result;
18
+ };
19
+ exports.getFilterClassificationCategoryFamilies = getFilterClassificationCategoryFamilies;
@@ -0,0 +1,7 @@
1
+ export type { FilterClassificationRecord } from "./interfaces/filter-classification.interface";
2
+ export type { FilterClassificationCategory, FilterClassificationCategoryFamily } from "./categoryFamilies/catalog";
3
+ export * from "./categoryFamilies/utils/filter-classification-category-family.utils";
4
+ export type { FilterClassificationSection } from "./sections/catalog";
5
+ export * from "./sections/utils/filter-classification-section.utils";
6
+ export * from "./utils/type-label.utils";
7
+ export * from "./utils/type-group.utils";
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./categoryFamilies/utils/filter-classification-category-family.utils"), exports);
18
+ __exportStar(require("./sections/utils/filter-classification-section.utils"), exports);
19
+ __exportStar(require("./utils/type-label.utils"), exports);
20
+ __exportStar(require("./utils/type-group.utils"), exports);
@@ -0,0 +1,14 @@
1
+ import type { BusinessLine } from "../../businessLines/catalog";
2
+ import type { FilterClassificationCategory } from "../categoryFamilies/catalog";
3
+ import type { FilterClassificationSection } from "../sections/catalog";
4
+ /**
5
+ * A selectable group of type codes (one checkbox that stands for several types). The group `code` is a UI
6
+ * identifier: it is never sent to an API, only its `members` are — see `expandGroupSelection`.
7
+ */
8
+ export type FilterClassificationRecord<Code extends string, Member extends string = Code> = {
9
+ readonly code: Code;
10
+ readonly members: readonly Member[];
11
+ readonly line: BusinessLine;
12
+ readonly category: FilterClassificationCategory;
13
+ readonly section: FilterClassificationSection;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,28 @@
1
+ export declare const FILTER_CLASSIFICATION_SECTIONS: {
2
+ readonly cop: {
3
+ readonly code: "cop";
4
+ };
5
+ readonly mxn: {
6
+ readonly code: "mxn";
7
+ };
8
+ readonly usd_global: {
9
+ readonly code: "usd_global";
10
+ };
11
+ readonly eur: {
12
+ readonly code: "eur";
13
+ };
14
+ readonly corridors: {
15
+ readonly code: "corridors";
16
+ };
17
+ readonly stablecoin: {
18
+ readonly code: "stablecoin";
19
+ };
20
+ readonly internal: {
21
+ readonly code: "internal";
22
+ };
23
+ readonly connected_account: {
24
+ readonly code: "connected_account";
25
+ };
26
+ };
27
+ export type FilterClassificationSection = keyof typeof FILTER_CLASSIFICATION_SECTIONS;
28
+ export type FilterClassificationSectionRecord = (typeof FILTER_CLASSIFICATION_SECTIONS)[FilterClassificationSection];
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FILTER_CLASSIFICATION_SECTIONS = void 0;
4
+ exports.FILTER_CLASSIFICATION_SECTIONS = {
5
+ cop: { code: "cop" },
6
+ mxn: { code: "mxn" },
7
+ usd_global: { code: "usd_global" },
8
+ eur: { code: "eur" },
9
+ corridors: { code: "corridors" },
10
+ stablecoin: { code: "stablecoin" },
11
+ internal: { code: "internal" },
12
+ connected_account: { code: "connected_account" },
13
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "sections": {
3
+ "cop": "COP",
4
+ "mxn": "MXN",
5
+ "usd_global": "USD / Global",
6
+ "eur": "EUR",
7
+ "corridors": "Corridors",
8
+ "stablecoin": "Stablecoin",
9
+ "internal": "Internal",
10
+ "connected_account": "Connected account"
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "sections": {
3
+ "cop": "COP",
4
+ "mxn": "MXN",
5
+ "usd_global": "USD / Global",
6
+ "eur": "EUR",
7
+ "corridors": "Corredores",
8
+ "stablecoin": "Stablecoin",
9
+ "internal": "Internas",
10
+ "connected_account": "Cuenta conectada"
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ import type { FilterClassificationSection, FilterClassificationSectionRecord } from "../catalog";
2
+ import type { Locale } from "../../../lang";
3
+ export type FilterClassificationSectionOption = FilterClassificationSectionRecord & {
4
+ label: string;
5
+ };
6
+ /** The section headings indexed by code, each with its label. A section is a heading: never selectable, never sent to an API. */
7
+ export declare const getFilterClassificationSections: (lang: Locale) => Record<FilterClassificationSection, FilterClassificationSectionOption>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getFilterClassificationSections = void 0;
7
+ const catalog_1 = require("../catalog");
8
+ const en_json_1 = __importDefault(require("../locales/en.json"));
9
+ const es_mex_json_1 = __importDefault(require("../locales/es-mex.json"));
10
+ const locales = { en: en_json_1.default, "es-mex": es_mex_json_1.default };
11
+ /** The section headings indexed by code, each with its label. A section is a heading: never selectable, never sent to an API. */
12
+ const getFilterClassificationSections = (lang) => {
13
+ const locale = locales[lang];
14
+ const result = {};
15
+ for (const record of Object.values(catalog_1.FILTER_CLASSIFICATION_SECTIONS)) {
16
+ result[record.code] = { ...record, label: locale.sections[record.code] };
17
+ }
18
+ return result;
19
+ };
20
+ exports.getFilterClassificationSections = getFilterClassificationSections;
@@ -0,0 +1,13 @@
1
+ import type { FilterClassificationRecord } from "../interfaces/filter-classification.interface";
2
+ export type GroupSelectionState = "checked" | "indeterminate" | "unchecked";
3
+ /** Tells a group option (it has `members`) from a plain option, narrowing a mixed list of both. */
4
+ export declare const isGroupOption: <Option extends object>(option: Option) => option is Extract<Option, {
5
+ readonly members: readonly string[];
6
+ }>;
7
+ /**
8
+ * The codes to send to an API: each selected group code is replaced by its members, anything else passes
9
+ * through. The group code itself never appears in the output, and repeated codes are dropped.
10
+ */
11
+ export declare const expandGroupSelection: <Code extends string, Member extends string = Code>(selected: readonly (Code | Member)[], groups: readonly FilterClassificationRecord<Code, Member>[]) => Member[];
12
+ /** checked = every member selected, indeterminate = some, unchecked = none (or a group without members). */
13
+ export declare const getGroupSelectionState: <Code extends string, Member extends string = Code>(group: FilterClassificationRecord<Code, Member>, selected: readonly Member[]) => GroupSelectionState;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getGroupSelectionState = exports.expandGroupSelection = exports.isGroupOption = void 0;
4
+ /** Tells a group option (it has `members`) from a plain option, narrowing a mixed list of both. */
5
+ const isGroupOption = (option) => "members" in option;
6
+ exports.isGroupOption = isGroupOption;
7
+ /**
8
+ * The codes to send to an API: each selected group code is replaced by its members, anything else passes
9
+ * through. The group code itself never appears in the output, and repeated codes are dropped.
10
+ */
11
+ const expandGroupSelection = (selected, groups) => {
12
+ const membersByGroup = new Map(groups.map(group => [group.code, group.members]));
13
+ const expanded = selected.flatMap(code => membersByGroup.get(code) ?? [code]);
14
+ return [...new Set(expanded)];
15
+ };
16
+ exports.expandGroupSelection = expandGroupSelection;
17
+ /** checked = every member selected, indeterminate = some, unchecked = none (or a group without members). */
18
+ const getGroupSelectionState = (group, selected) => {
19
+ const count = group.members.filter(member => selected.includes(member)).length;
20
+ if (count === 0)
21
+ return "unchecked";
22
+ return count === group.members.length ? "checked" : "indeterminate";
23
+ };
24
+ exports.getGroupSelectionState = getGroupSelectionState;
@@ -0,0 +1,9 @@
1
+ export type SplitTypeLabel = {
2
+ title: string;
3
+ rail?: string;
4
+ };
5
+ /**
6
+ * Splits a type label ("Transfer · ACH") at its FIRST " · " into a title and a rail, for two-line options.
7
+ * A label without the separator, or with nothing after it, comes back as `{ title }` alone — never an empty `rail`.
8
+ */
9
+ export declare const splitTypeLabel: (label: string) => SplitTypeLabel;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitTypeLabel = void 0;
4
+ const SEPARATOR = " · ";
5
+ /**
6
+ * Splits a type label ("Transfer · ACH") at its FIRST " · " into a title and a rail, for two-line options.
7
+ * A label without the separator, or with nothing after it, comes back as `{ title }` alone — never an empty `rail`.
8
+ */
9
+ const splitTypeLabel = (label) => {
10
+ const index = label.indexOf(SEPARATOR);
11
+ if (index === -1)
12
+ return { title: label };
13
+ const title = label.slice(0, index);
14
+ const rail = label.slice(index + SEPARATOR.length);
15
+ return rail === "" ? { title } : { title, rail };
16
+ };
17
+ exports.splitTypeLabel = splitTypeLabel;
@@ -1,4 +1,4 @@
1
- export type { ClassificationCategory, ClassificationLine, MovementType, MovementTypeGroup, MovementTypeGroupLabel } from "./types/catalog";
1
+ export type { MovementType } from "./types/catalog";
2
2
  export * from "./types/utils/movement-type.utils";
3
3
  export type { MovementStatus, MovementStatusType } from "./status/catalog";
4
4
  export * from "./status/utils/movement-status.utils";