@finsys/core 4.0.0 → 4.2.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 CHANGED
@@ -23,6 +23,10 @@ Partner-facing integration documentation lives in [`docs/`](./docs/):
23
23
  - **Visibility-Aware Validation** — Conditional fields are only validated when visible (`visibleIf` expressions)
24
24
  - **TypeScript-First** — Full type exports for all config types and generator outputs
25
25
 
26
+ ## Prerequisites
27
+
28
+ This project targets Node 24.16.0 (see [`.nvmrc`](./.nvmrc)) and npm ≥ 12.0.1. After `nvm use`, upgrade npm with `npm install -g npm@12.0.1`.
29
+
26
30
  ## Installation
27
31
 
28
32
  ```bash
package/dist/index.cjs CHANGED
@@ -47,6 +47,7 @@ __export(index_exports, {
47
47
  FormFieldValidator: () => FormFieldValidator,
48
48
  FormSpec: () => FormSpec,
49
49
  IHS_FAILURE_STATUSES: () => IHS_FAILURE_STATUSES,
50
+ IHS_FIELD_ORIGINS: () => IHS_FIELD_ORIGINS,
50
51
  IHS_TERMINAL_STATUSES: () => IHS_TERMINAL_STATUSES,
51
52
  IHS_VALID_STATUSES: () => IHS_VALID_STATUSES,
52
53
  IhsStatus: () => IhsStatus,
@@ -59,6 +60,7 @@ __export(index_exports, {
59
60
  assertDocumentType: () => assertDocumentType,
60
61
  buildDocumentRows: () => buildDocumentRows,
61
62
  buildFileFieldTables: () => buildFileFieldTables,
63
+ buildFileFieldTablesFromInstances: () => buildFileFieldTablesFromInstances,
62
64
  categoryFieldsOf: () => categoryFieldsOf,
63
65
  categoryForField: () => categoryForField,
64
66
  categorySchemaOf: () => categorySchemaOf,
@@ -85,6 +87,7 @@ __export(index_exports, {
85
87
  getReuploadableDocTypes: () => getReuploadableDocTypes,
86
88
  getStepDefaultValues: () => getStepDefaultValues,
87
89
  getStepSchema: () => getStepSchema,
90
+ groupColumnsByInstance: () => groupColumnsByInstance,
88
91
  groupColumnsByTimePeriod: () => groupColumnsByTimePeriod,
89
92
  groupDetailsByCategory: () => groupDetailsByCategory,
90
93
  groupFieldsByCategory: () => groupFieldsByCategory,
@@ -93,6 +96,7 @@ __export(index_exports, {
93
96
  isDocumentType: () => isDocumentType,
94
97
  isFailureIhsStatus: () => isFailureIhsStatus,
95
98
  isTerminalIhsStatus: () => isTerminalIhsStatus,
99
+ isValidIhsFieldOrigin: () => isValidIhsFieldOrigin,
96
100
  isValidIhsStatus: () => isValidIhsStatus,
97
101
  parseFileField: () => parseFileField,
98
102
  processIhsDetails: () => processIhsDetails,
@@ -9306,6 +9310,10 @@ var FileFieldTableType = /* @__PURE__ */ ((FileFieldTableType2) => {
9306
9310
  FileFieldTableType2["KEY_VALUE"] = "keyValue";
9307
9311
  return FileFieldTableType2;
9308
9312
  })(FileFieldTableType || {});
9313
+ var IHS_FIELD_ORIGINS = ["extracted", "derived", "manual"];
9314
+ function isValidIhsFieldOrigin(origin) {
9315
+ return typeof origin === "string" && IHS_FIELD_ORIGINS.includes(origin);
9316
+ }
9309
9317
 
9310
9318
  // src/document-types.ts
9311
9319
  var cached = null;
@@ -9703,6 +9711,124 @@ function buildFileFieldTables(ihsData, fieldProvenance) {
9703
9711
  }
9704
9712
  return tables;
9705
9713
  }
9714
+ function instanceColumnLabel(row) {
9715
+ const period = row.timePeriod || row.instanceKey;
9716
+ return row.sourceLabel ? `${period} \xB7 ${row.sourceLabel}` : period;
9717
+ }
9718
+ function instanceColumnLabels(rows) {
9719
+ const seenCounts = /* @__PURE__ */ new Map();
9720
+ return rows.map((row) => {
9721
+ const raw = instanceColumnLabel(row);
9722
+ const occurrence = (seenCounts.get(raw) ?? 0) + 1;
9723
+ seenCounts.set(raw, occurrence);
9724
+ return occurrence === 1 ? raw : `${raw} (${occurrence})`;
9725
+ });
9726
+ }
9727
+ function groupColumnsByInstance(baseColumnNames, instanceRows) {
9728
+ const groups = {};
9729
+ for (const baseName of baseColumnNames) {
9730
+ groups[baseName] = {};
9731
+ }
9732
+ if (!instanceRows?.length) return groups;
9733
+ const labels = instanceColumnLabels(instanceRows);
9734
+ instanceRows.forEach((row, i) => {
9735
+ const label = labels[i];
9736
+ for (const baseName of baseColumnNames) {
9737
+ if (Object.prototype.hasOwnProperty.call(row, baseName)) {
9738
+ groups[baseName][label] = row[baseName];
9739
+ }
9740
+ }
9741
+ });
9742
+ return groups;
9743
+ }
9744
+ function buildInstanceTable(groupName, baseNames, groupDisplayName, instanceRows, fieldProvenance) {
9745
+ const columnGroups = groupColumnsByInstance(baseNames, instanceRows);
9746
+ const instanceLabels = instanceColumnLabels(instanceRows);
9747
+ const items = [];
9748
+ for (const [baseName, labelMap] of Object.entries(columnGroups)) {
9749
+ const hasAny = Object.values(labelMap).some((v) => v !== null && v !== void 0 && v !== "");
9750
+ if (!hasAny) continue;
9751
+ const numeric = isNumericField(baseName);
9752
+ const data = {};
9753
+ const formattedData = {};
9754
+ const confidence = {};
9755
+ const provenance = {};
9756
+ for (const [i, row] of instanceRows.entries()) {
9757
+ const label = instanceLabels[i];
9758
+ const value = labelMap[label] ?? null;
9759
+ data[label] = value;
9760
+ formattedData[label] = formatValue(value, numeric);
9761
+ const legacyKey = row.timePeriod ? `${baseName}${row.timePeriod}` : void 0;
9762
+ const prov = legacyKey ? fieldProvenance?.[legacyKey] : void 0;
9763
+ if (prov) {
9764
+ provenance[label] = prov;
9765
+ if (prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence)) {
9766
+ confidence[label] = prov.confidence;
9767
+ }
9768
+ }
9769
+ }
9770
+ items.push({
9771
+ displayName: getDisplayName(baseName),
9772
+ timePeriods: instanceLabels,
9773
+ data,
9774
+ formattedData,
9775
+ type: "timeSeries" /* TIME_SERIES */,
9776
+ isNumeric: numeric,
9777
+ ...Object.keys(confidence).length ? { confidence } : {},
9778
+ ...Object.keys(provenance).length ? { provenance } : {}
9779
+ });
9780
+ }
9781
+ const hasData = items.some(
9782
+ (item) => Object.values(item.data).some((v) => v !== null && v !== void 0 && v !== "")
9783
+ );
9784
+ if (!items.length || !hasData) return null;
9785
+ return {
9786
+ name: groupName,
9787
+ displayName: groupDisplayName,
9788
+ type: "timeSeries" /* TIME_SERIES */,
9789
+ items,
9790
+ hasData
9791
+ };
9792
+ }
9793
+ function buildFileFieldTablesFromInstances(instancesByCategory = {}, fieldProvenance, categoryOverrides) {
9794
+ const specs = getBaseFieldSpecs();
9795
+ const fileFields = specs.filter((f) => f.type === "file" && f.ihs_column_names?.length);
9796
+ const grouped = groupFieldsByPattern(fileFields);
9797
+ const tables = {};
9798
+ for (const [groupName, fields] of Object.entries(grouped)) {
9799
+ const instanceRows = instancesByCategory[groupName];
9800
+ if (!instanceRows?.length) continue;
9801
+ const baseNames = /* @__PURE__ */ new Set();
9802
+ for (const field of fields) {
9803
+ for (const col of field.ihs_column_names ?? []) {
9804
+ baseNames.add(col.replace(TIME_PERIOD_REGEX, ""));
9805
+ }
9806
+ }
9807
+ const groupDisplayName = getGroupDisplayNames()[groupName] || fields[0]?.displayName || getDisplayName(groupName);
9808
+ const table = buildInstanceTable(
9809
+ groupName,
9810
+ [...baseNames],
9811
+ groupDisplayName,
9812
+ instanceRows,
9813
+ fieldProvenance
9814
+ );
9815
+ if (table) tables[groupName] = table;
9816
+ }
9817
+ for (const [groupName, spec] of Object.entries(categoryOverrides ?? {})) {
9818
+ if (Object.prototype.hasOwnProperty.call(tables, groupName)) continue;
9819
+ const instanceRows = instancesByCategory[groupName];
9820
+ if (!instanceRows?.length) continue;
9821
+ const table = buildInstanceTable(
9822
+ groupName,
9823
+ spec.baseColumnNames,
9824
+ spec.displayName,
9825
+ instanceRows,
9826
+ fieldProvenance
9827
+ );
9828
+ if (table) tables[groupName] = table;
9829
+ }
9830
+ return tables;
9831
+ }
9706
9832
  var DOC_DISPLAY_NAMES = {
9707
9833
  bankStatements: "Bank Statements",
9708
9834
  financialStatements: "Financial Statements",
@@ -9955,6 +10081,7 @@ var IhsStatus = /* @__PURE__ */ ((IhsStatus2) => {
9955
10081
  IhsStatus2["CreatingApplication"] = "CREATING_APPLICATION";
9956
10082
  IhsStatus2["ApplicationFinalized"] = "APPLICATION_FINALIZED";
9957
10083
  IhsStatus2["LenderEvaluation"] = "LENDER_EVALUATION";
10084
+ IhsStatus2["EditingApplication"] = "EDITING_APPLICATION";
9958
10085
  IhsStatus2["Approved"] = "APPROVED";
9959
10086
  IhsStatus2["LouDelivered"] = "LOU_DELIVERED";
9960
10087
  IhsStatus2["AwaitingDisbursement"] = "AWAITING_DISBURSEMENT";
@@ -9968,6 +10095,7 @@ var IHS_VALID_STATUSES = [
9968
10095
  "CREATING_APPLICATION" /* CreatingApplication */,
9969
10096
  "APPLICATION_FINALIZED" /* ApplicationFinalized */,
9970
10097
  "LENDER_EVALUATION" /* LenderEvaluation */,
10098
+ "EDITING_APPLICATION" /* EditingApplication */,
9971
10099
  "APPROVED" /* Approved */,
9972
10100
  "LOU_DELIVERED" /* LouDelivered */,
9973
10101
  "AWAITING_DISBURSEMENT" /* AwaitingDisbursement */,
@@ -10734,6 +10862,7 @@ function assertAdapterCategory(id) {
10734
10862
  FormFieldValidator,
10735
10863
  FormSpec,
10736
10864
  IHS_FAILURE_STATUSES,
10865
+ IHS_FIELD_ORIGINS,
10737
10866
  IHS_TERMINAL_STATUSES,
10738
10867
  IHS_VALID_STATUSES,
10739
10868
  IhsStatus,
@@ -10746,6 +10875,7 @@ function assertAdapterCategory(id) {
10746
10875
  assertDocumentType,
10747
10876
  buildDocumentRows,
10748
10877
  buildFileFieldTables,
10878
+ buildFileFieldTablesFromInstances,
10749
10879
  categoryFieldsOf,
10750
10880
  categoryForField,
10751
10881
  categorySchemaOf,
@@ -10772,6 +10902,7 @@ function assertAdapterCategory(id) {
10772
10902
  getReuploadableDocTypes,
10773
10903
  getStepDefaultValues,
10774
10904
  getStepSchema,
10905
+ groupColumnsByInstance,
10775
10906
  groupColumnsByTimePeriod,
10776
10907
  groupDetailsByCategory,
10777
10908
  groupFieldsByCategory,
@@ -10780,6 +10911,7 @@ function assertAdapterCategory(id) {
10780
10911
  isDocumentType,
10781
10912
  isFailureIhsStatus,
10782
10913
  isTerminalIhsStatus,
10914
+ isValidIhsFieldOrigin,
10783
10915
  isValidIhsStatus,
10784
10916
  parseFileField,
10785
10917
  processIhsDetails,