@fintekkers/ledger-models 0.4.24 → 0.4.25

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/hierarchy.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "schema_version": "1.0",
3
- "_doc": "Single source of truth for the FinTekkers product hierarchy. See ../docs/product-hierarchy.md for narrative description, hierarchy-examples.md for worked examples, and registry-versioning.md for compatibility rules. Each leaf product_type carries (asset_class, instrument_type). Abstract nodes carry only hierarchy. status=active entries must have a matching ProductTypeProto enum value (CI-enforced). status=planned entries are aspirational and not yet wired into the proto enum. NOTE: M1 ships a 3-dimensional registry (productType + asset_class + instrument_type). The 4th dimension (index_type — single_name vs index) is intentionally deferred and will be added in a future milestone. Option strategy leaves (butterfly, vertical spread, calendar spread, condor, straddle, ...) are also intentionally absent — strategies are derived from the legs field on SecurityProto, not from a productType enum value.",
2
+ "schema_version": "1.1",
3
+ "_doc": "Single source of truth for the FinTekkers product hierarchy. See ../docs/product-hierarchy.md for narrative description, hierarchy-examples.md for worked examples, and registry-versioning.md for compatibility rules. Each leaf product_type carries (asset_class, instrument_type). Abstract nodes carry only hierarchy. status=active entries must have a matching ProductTypeProto enum value (CI-enforced). status=planned entries are aspirational and not yet wired into the proto enum. NOTE: M1 ships a 3-dimensional registry (productType + asset_class + instrument_type). The 4th dimension (index_type — single_name vs index) is intentionally deferred and will be added in a future milestone. Option strategy leaves (butterfly, vertical spread, calendar spread, condor, straddle, ...) are also intentionally absent — strategies are derived from the legs field on SecurityProto, not from a productType enum value. asset_classes is the one canonical asset-class vocabulary (codes and tree); an entry's optional aliases list names legacy values that resolve to it. enum_labels holds display labels (and identifier-type input placeholders) for proto enum values with no entry elsewhere, keyed by proto enum name then value name. See ../docs/adr/asset_class_vocabulary.md.",
4
4
 
5
5
  "product_types": {
6
6
  "BOND": { "parent": null, "abstract": true, "label": "Bond" },
@@ -116,7 +116,7 @@
116
116
  "CREDIT": { "parent": "FIXED_INCOME", "label": "Credit" },
117
117
  "EQUITY": { "parent": null, "label": "Equity" },
118
118
  "VOLATILITY": { "parent": null, "label": "Volatility" },
119
- "CASH": { "parent": null, "label": "Cash" },
119
+ "CASH": { "parent": null, "label": "Cash", "aliases": ["CASH_ASSET_CLASS"] },
120
120
  "FX": { "parent": null, "label": "Foreign Exchange" },
121
121
  "CRYPTO": { "parent": null, "label": "Crypto" },
122
122
  "COMMODITY": { "parent": null, "label": "Commodity" },
@@ -127,5 +127,32 @@
127
127
  "ALTERNATIVE": { "parent": null, "label": "Alternative" }
128
128
  },
129
129
 
130
- "instrument_types": ["CASH", "DERIVATIVE", "REFERENCE_INDEX"]
130
+ "instrument_types": ["CASH", "DERIVATIVE", "REFERENCE_INDEX"],
131
+
132
+ "enum_labels": {
133
+ "IdentifierTypeProto": {
134
+ "UNKNOWN_IDENTIFIER_TYPE": { "label": "Unknown", "placeholder": "Identifier" },
135
+ "EXCH_TICKER": { "label": "Exchange Ticker", "placeholder": "e.g. AAPL" },
136
+ "ISIN": { "label": "ISIN", "placeholder": "e.g. US0378331005" },
137
+ "CUSIP": { "label": "CUSIP", "placeholder": "e.g. 037833100" },
138
+ "OSI": { "label": "OSI Option Symbol", "placeholder": "e.g. AAPL 250117C00150000" },
139
+ "FIGI": { "label": "FIGI", "placeholder": "e.g. BBG000B9XRY4" },
140
+ "SERIES_ID": { "label": "Series ID", "placeholder": "e.g. CPIAUCSL" },
141
+ "INDEX_NAME": { "label": "Index Name", "placeholder": "e.g. SPX" },
142
+ "CASH": { "label": "Currency Code", "placeholder": "e.g. USD" }
143
+ },
144
+ "InstrumentTypeProto": {
145
+ "INSTRUMENT_TYPE_UNKNOWN": { "label": "Unknown" },
146
+ "INSTRUMENT_TYPE_CASH": { "label": "Cash" },
147
+ "INSTRUMENT_TYPE_DERIVATIVE": { "label": "Derivative" },
148
+ "INSTRUMENT_TYPE_REFERENCE_INDEX": { "label": "Reference Index" }
149
+ },
150
+ "ProductTypeProto": {
151
+ "PRODUCT_TYPE_UNKNOWN": { "label": "Unknown" }
152
+ },
153
+ "AssetClassProto": {
154
+ "UNKNOWN_ASSET_CLASS": { "label": "Unknown" },
155
+ "INDEX": { "label": "Index" }
156
+ }
157
+ }
131
158
  }
@@ -0,0 +1,146 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ /**
27
+ * LM-275: one asset-class vocabulary (hierarchy.json), a shared match helper
28
+ * and labels for every enum the UI shows.
29
+ *
30
+ * The match cases live in ledger-models-protos/fixtures/asset_class_matches.json,
31
+ * shared with the Java and Python tests.
32
+ */
33
+ const fs = __importStar(require("fs"));
34
+ const path = __importStar(require("path"));
35
+ const product_hierarchy_1 = require("./product_hierarchy");
36
+ const asset_class_pb_1 = require("../../../fintekkers/models/security/asset_class_pb");
37
+ const identifier_type_pb_1 = require("../../../fintekkers/models/security/identifier/identifier_type_pb");
38
+ const instrument_type_pb_1 = require("../../../fintekkers/models/security/instrument_type_pb");
39
+ const product_type_pb_1 = require("../../../fintekkers/models/security/product_type_pb");
40
+ const PROTOS = path.resolve(__dirname, '../../../../../ledger-models-protos');
41
+ const rows = JSON.parse(fs.readFileSync(path.join(PROTOS, 'fixtures/asset_class_matches.json'), 'utf-8')).cases;
42
+ const hierarchy = JSON.parse(fs.readFileSync(path.join(PROTOS, 'hierarchy.json'), 'utf-8'));
43
+ describe('assetClassMatches shared fixture', () => {
44
+ test.each(rows)('assetClassMatches($filter, $stored) === $expected', ({ filter, stored, expected }) => {
45
+ expect((0, product_hierarchy_1.assetClassMatches)(filter, stored)).toBe(expected);
46
+ });
47
+ test('fixture has the required rows', () => {
48
+ expect(rows.length).toBeGreaterThanOrEqual(7);
49
+ const found = new Map(rows.map((r) => [`${r.filter}|${r.stored}`, r.expected]));
50
+ const required = [
51
+ ['FIXED_INCOME|RATES', true],
52
+ ['FIXED_INCOME|CREDIT', true],
53
+ ['FIXED_INCOME|Fixed Income', true],
54
+ ['EQUITY|Equity', true],
55
+ ['CASH|Cash', true],
56
+ ['EQUITY|RATES', false],
57
+ ['EQUITY|NOT_AN_ASSET_CLASS', false],
58
+ ];
59
+ for (const [key, expected] of required) {
60
+ expect([key, found.get(key)]).toEqual([key, expected]);
61
+ }
62
+ });
63
+ });
64
+ describe('the tree comes from hierarchy.json', () => {
65
+ test('every asset_classes entry matches its parent, label and aliases', () => {
66
+ var _a;
67
+ const entries = Object.entries(hierarchy.asset_classes);
68
+ expect(entries.length).toBeGreaterThan(0);
69
+ for (const [code, entry] of entries) {
70
+ if (entry.parent)
71
+ expect([entry.parent, code, (0, product_hierarchy_1.assetClassMatches)(entry.parent, code)]).toEqual([entry.parent, code, true]);
72
+ expect([code, entry.label, (0, product_hierarchy_1.assetClassMatches)(code, entry.label)]).toEqual([code, entry.label, true]);
73
+ for (const alias of (_a = entry.aliases) !== null && _a !== void 0 ? _a : []) {
74
+ expect([code, alias, (0, product_hierarchy_1.assetClassMatches)(code, alias)]).toEqual([code, alias, true]);
75
+ }
76
+ }
77
+ });
78
+ test('an ambiguous label fails at load', () => {
79
+ expect(() => (0, product_hierarchy_1.buildAssetClassLookup)({ A: { parent: null, label: 'Shared' }, B: { parent: null, label: 'shared' } })).toThrow();
80
+ });
81
+ });
82
+ describe('labels for every enum value', () => {
83
+ const enums = [
84
+ ['IdentifierTypeProto', identifier_type_pb_1.IdentifierTypeProto, product_hierarchy_1.identifierTypeLabelOf],
85
+ ['InstrumentTypeProto', instrument_type_pb_1.InstrumentTypeProto, product_hierarchy_1.instrumentTypeLabelOf],
86
+ ['ProductTypeProto', product_type_pb_1.ProductTypeProto, product_hierarchy_1.productTypeLabelOf],
87
+ ['AssetClassProto', asset_class_pb_1.AssetClassProto, product_hierarchy_1.assetClassProtoLabelOf],
88
+ ];
89
+ test.each(enums)('every %s value has a non-empty label', (name, enumObj, labelOf) => {
90
+ var _a;
91
+ const values = Object.entries(enumObj);
92
+ expect(values.length).toBeGreaterThan(0);
93
+ let checked = 0;
94
+ for (const [valueName, v] of values) {
95
+ expect([`${name}.${valueName}`, ((_a = labelOf(v)) !== null && _a !== void 0 ? _a : '').trim() !== '']).toEqual([`${name}.${valueName}`, true]);
96
+ checked++;
97
+ }
98
+ expect(checked).toBe(values.length);
99
+ });
100
+ test('every IdentifierTypeProto value has a non-empty placeholder', () => {
101
+ var _a;
102
+ const values = Object.entries(identifier_type_pb_1.IdentifierTypeProto);
103
+ for (const [valueName, v] of values) {
104
+ expect([valueName, ((_a = (0, product_hierarchy_1.identifierTypePlaceholderOf)(v)) !== null && _a !== void 0 ? _a : '').trim() !== '']).toEqual([valueName, true]);
105
+ }
106
+ expect(values.length).toBeGreaterThan(0);
107
+ });
108
+ test('CASH_ASSET_CLASS is labelled Cash', () => {
109
+ expect((0, product_hierarchy_1.assetClassProtoLabelOf)(asset_class_pb_1.AssetClassProto.CASH_ASSET_CLASS)).toBe('Cash');
110
+ });
111
+ test('out-of-range numbers return null', () => {
112
+ expect((0, product_hierarchy_1.identifierTypeLabelOf)(9999)).toBeNull();
113
+ expect((0, product_hierarchy_1.identifierTypePlaceholderOf)(9999)).toBeNull();
114
+ expect((0, product_hierarchy_1.instrumentTypeLabelOf)(9999)).toBeNull();
115
+ expect((0, product_hierarchy_1.productTypeLabelOf)(9999)).toBeNull();
116
+ expect((0, product_hierarchy_1.assetClassProtoLabelOf)(9999)).toBeNull();
117
+ });
118
+ });
119
+ describe('the published (compiled) product_hierarchy.js', () => {
120
+ // npm publish runs no tsc: the tracked .js is what consumers get.
121
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
122
+ const compiled = require('./product_hierarchy.js');
123
+ test('exports the asset-class match helper', () => {
124
+ expect(typeof compiled.assetClassMatches).toBe('function');
125
+ expect(typeof compiled.resolveAssetClass).toBe('function');
126
+ expect(compiled.assetClassMatches('FIXED_INCOME', 'RATES')).toBe(true);
127
+ expect(compiled.assetClassMatches('EQUITY', 'RATES')).toBe(false);
128
+ });
129
+ test('exports the label and placeholder helpers', () => {
130
+ for (const fn of [
131
+ 'identifierTypeLabelOf',
132
+ 'identifierTypePlaceholderOf',
133
+ 'instrumentTypeLabelOf',
134
+ 'productTypeLabelOf',
135
+ 'assetClassProtoLabelOf',
136
+ ]) {
137
+ expect([fn, typeof compiled[fn]]).toEqual([fn, 'function']);
138
+ }
139
+ expect(compiled.identifierTypeLabelOf(identifier_type_pb_1.IdentifierTypeProto.ISIN)).toBe('ISIN');
140
+ expect(compiled.identifierTypePlaceholderOf(identifier_type_pb_1.IdentifierTypeProto.ISIN)).toBeTruthy();
141
+ expect(compiled.instrumentTypeLabelOf(instrument_type_pb_1.InstrumentTypeProto.INSTRUMENT_TYPE_CASH)).toBeTruthy();
142
+ expect(compiled.productTypeLabelOf(product_type_pb_1.ProductTypeProto.TBILL)).toBe('Treasury Bill');
143
+ expect(compiled.assetClassProtoLabelOf(asset_class_pb_1.AssetClassProto.CASH_ASSET_CLASS)).toBe('Cash');
144
+ });
145
+ });
146
+ //# sourceMappingURL=asset_class_vocabulary.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset_class_vocabulary.test.js","sourceRoot":"","sources":["asset_class_vocabulary.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * LM-275: one asset-class vocabulary (hierarchy.json), a shared match helper
3
+ * and labels for every enum the UI shows.
4
+ *
5
+ * The match cases live in ledger-models-protos/fixtures/asset_class_matches.json,
6
+ * shared with the Java and Python tests.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+
11
+ import {
12
+ assetClassMatches,
13
+ assetClassProtoLabelOf,
14
+ buildAssetClassLookup,
15
+ identifierTypeLabelOf,
16
+ identifierTypePlaceholderOf,
17
+ instrumentTypeLabelOf,
18
+ productTypeLabelOf,
19
+ } from './product_hierarchy';
20
+ import { AssetClassProto } from '../../../fintekkers/models/security/asset_class_pb';
21
+ import { IdentifierTypeProto } from '../../../fintekkers/models/security/identifier/identifier_type_pb';
22
+ import { InstrumentTypeProto } from '../../../fintekkers/models/security/instrument_type_pb';
23
+ import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
24
+
25
+ const PROTOS = path.resolve(__dirname, '../../../../../ledger-models-protos');
26
+
27
+ interface FixtureRow {
28
+ filter: string | null;
29
+ stored: string | null;
30
+ expected: boolean;
31
+ }
32
+
33
+ const rows: FixtureRow[] = JSON.parse(
34
+ fs.readFileSync(path.join(PROTOS, 'fixtures/asset_class_matches.json'), 'utf-8'),
35
+ ).cases;
36
+
37
+ const hierarchy = JSON.parse(fs.readFileSync(path.join(PROTOS, 'hierarchy.json'), 'utf-8'));
38
+
39
+ describe('assetClassMatches shared fixture', () => {
40
+ test.each(rows)('assetClassMatches($filter, $stored) === $expected', ({ filter, stored, expected }) => {
41
+ expect(assetClassMatches(filter, stored)).toBe(expected);
42
+ });
43
+
44
+ test('fixture has the required rows', () => {
45
+ expect(rows.length).toBeGreaterThanOrEqual(7);
46
+ const found = new Map(rows.map((r) => [`${r.filter}|${r.stored}`, r.expected]));
47
+ const required: Array<[string, boolean]> = [
48
+ ['FIXED_INCOME|RATES', true],
49
+ ['FIXED_INCOME|CREDIT', true],
50
+ ['FIXED_INCOME|Fixed Income', true],
51
+ ['EQUITY|Equity', true],
52
+ ['CASH|Cash', true],
53
+ ['EQUITY|RATES', false],
54
+ ['EQUITY|NOT_AN_ASSET_CLASS', false],
55
+ ];
56
+ for (const [key, expected] of required) {
57
+ expect([key, found.get(key)]).toEqual([key, expected]);
58
+ }
59
+ });
60
+ });
61
+
62
+ describe('the tree comes from hierarchy.json', () => {
63
+ test('every asset_classes entry matches its parent, label and aliases', () => {
64
+ const entries = Object.entries<{ parent: string | null; label: string; aliases?: string[] }>(
65
+ hierarchy.asset_classes,
66
+ );
67
+ expect(entries.length).toBeGreaterThan(0);
68
+ for (const [code, entry] of entries) {
69
+ if (entry.parent) expect([entry.parent, code, assetClassMatches(entry.parent, code)]).toEqual([entry.parent, code, true]);
70
+ expect([code, entry.label, assetClassMatches(code, entry.label)]).toEqual([code, entry.label, true]);
71
+ for (const alias of entry.aliases ?? []) {
72
+ expect([code, alias, assetClassMatches(code, alias)]).toEqual([code, alias, true]);
73
+ }
74
+ }
75
+ });
76
+
77
+ test('an ambiguous label fails at load', () => {
78
+ expect(() =>
79
+ buildAssetClassLookup({ A: { parent: null, label: 'Shared' }, B: { parent: null, label: 'shared' } }),
80
+ ).toThrow();
81
+ });
82
+ });
83
+
84
+ describe('labels for every enum value', () => {
85
+ const enums: Array<[string, object, (v: number) => string | null]> = [
86
+ ['IdentifierTypeProto', IdentifierTypeProto, identifierTypeLabelOf],
87
+ ['InstrumentTypeProto', InstrumentTypeProto, instrumentTypeLabelOf],
88
+ ['ProductTypeProto', ProductTypeProto, productTypeLabelOf],
89
+ ['AssetClassProto', AssetClassProto, assetClassProtoLabelOf],
90
+ ];
91
+
92
+ test.each(enums)('every %s value has a non-empty label', (name, enumObj, labelOf) => {
93
+ const values = Object.entries(enumObj);
94
+ expect(values.length).toBeGreaterThan(0);
95
+ let checked = 0;
96
+ for (const [valueName, v] of values) {
97
+ expect([`${name}.${valueName}`, (labelOf(v) ?? '').trim() !== '']).toEqual([`${name}.${valueName}`, true]);
98
+ checked++;
99
+ }
100
+ expect(checked).toBe(values.length);
101
+ });
102
+
103
+ test('every IdentifierTypeProto value has a non-empty placeholder', () => {
104
+ const values = Object.entries(IdentifierTypeProto);
105
+ for (const [valueName, v] of values) {
106
+ expect([valueName, (identifierTypePlaceholderOf(v as IdentifierTypeProto) ?? '').trim() !== '']).toEqual([valueName, true]);
107
+ }
108
+ expect(values.length).toBeGreaterThan(0);
109
+ });
110
+
111
+ test('CASH_ASSET_CLASS is labelled Cash', () => {
112
+ expect(assetClassProtoLabelOf(AssetClassProto.CASH_ASSET_CLASS)).toBe('Cash');
113
+ });
114
+
115
+ test('out-of-range numbers return null', () => {
116
+ expect(identifierTypeLabelOf(9999 as IdentifierTypeProto)).toBeNull();
117
+ expect(identifierTypePlaceholderOf(9999 as IdentifierTypeProto)).toBeNull();
118
+ expect(instrumentTypeLabelOf(9999 as InstrumentTypeProto)).toBeNull();
119
+ expect(productTypeLabelOf(9999 as ProductTypeProto)).toBeNull();
120
+ expect(assetClassProtoLabelOf(9999 as AssetClassProto)).toBeNull();
121
+ });
122
+ });
123
+
124
+ describe('the published (compiled) product_hierarchy.js', () => {
125
+ // npm publish runs no tsc: the tracked .js is what consumers get.
126
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
127
+ const compiled = require('./product_hierarchy.js');
128
+
129
+ test('exports the asset-class match helper', () => {
130
+ expect(typeof compiled.assetClassMatches).toBe('function');
131
+ expect(typeof compiled.resolveAssetClass).toBe('function');
132
+ expect(compiled.assetClassMatches('FIXED_INCOME', 'RATES')).toBe(true);
133
+ expect(compiled.assetClassMatches('EQUITY', 'RATES')).toBe(false);
134
+ });
135
+
136
+ test('exports the label and placeholder helpers', () => {
137
+ for (const fn of [
138
+ 'identifierTypeLabelOf',
139
+ 'identifierTypePlaceholderOf',
140
+ 'instrumentTypeLabelOf',
141
+ 'productTypeLabelOf',
142
+ 'assetClassProtoLabelOf',
143
+ ]) {
144
+ expect([fn, typeof compiled[fn]]).toEqual([fn, 'function']);
145
+ }
146
+ expect(compiled.identifierTypeLabelOf(IdentifierTypeProto.ISIN)).toBe('ISIN');
147
+ expect(compiled.identifierTypePlaceholderOf(IdentifierTypeProto.ISIN)).toBeTruthy();
148
+ expect(compiled.instrumentTypeLabelOf(InstrumentTypeProto.INSTRUMENT_TYPE_CASH)).toBeTruthy();
149
+ expect(compiled.productTypeLabelOf(ProductTypeProto.TBILL)).toBe('Treasury Bill');
150
+ expect(compiled.assetClassProtoLabelOf(AssetClassProto.CASH_ASSET_CLASS)).toBe('Cash');
151
+ });
152
+ });
@@ -13,9 +13,25 @@
13
13
  * Plus per-leaf classification lookups: assetClassOf, instrumentTypeOf,
14
14
  * labelOf.
15
15
  *
16
+ * asset_classes is the one canonical asset-class vocabulary.
17
+ * assetClassMatches filters stored asset-class values (codes, labels such as
18
+ * "Fixed Income", or aliases such as "CASH_ASSET_CLASS") against a code,
19
+ * walking the tree. The *LabelOf / identifierTypePlaceholderOf helpers give
20
+ * display strings for every value of the enums the UI shows. See
21
+ * docs/adr/asset_class_vocabulary.md.
22
+ *
16
23
  * `indexTypeOf` is intentionally absent — that dimension is deferred per
17
24
  * the M1 descope.
18
25
  */
26
+ import { AssetClassProto } from '../../../fintekkers/models/security/asset_class_pb';
27
+ import { IdentifierTypeProto } from '../../../fintekkers/models/security/identifier/identifier_type_pb';
28
+ import { InstrumentTypeProto } from '../../../fintekkers/models/security/instrument_type_pb';
29
+ import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
30
+ interface AssetClassEntry {
31
+ parent?: string | null;
32
+ label?: string;
33
+ aliases?: string[];
34
+ }
19
35
  /** Parent product_type node (abstract or leaf). null for top-level nodes;
20
36
  * null for unknown nodes. */
21
37
  export declare function parentOf(node: string): string | null;
@@ -36,7 +52,36 @@ export declare function assetClassParentOf(node: string): string | null;
36
52
  export declare function assetClassDescendantsOf(ancestor: string): string[];
37
53
  export declare function isAssetClassDescendantOf(node: string, ancestor: string): boolean;
38
54
  export declare function assetClassLabelOf(node: string): string | null;
55
+ /** Normalised code / label / alias -> code. Throws if two codes claim the
56
+ * same key, so an ambiguous label or alias fails at load time. Exported for
57
+ * tests only. */
58
+ export declare function buildAssetClassLookup(classes: Record<string, AssetClassEntry>): Map<string, string>;
59
+ /** Resolve a stored or user-supplied asset-class value to its hierarchy.json
60
+ * code. An exact code wins; otherwise the value is normalised (trimmed,
61
+ * upper-cased, runs of whitespace or hyphens turned into `_`) and matched
62
+ * against every code, label and alias. null for null, blank or unknown. */
63
+ export declare function resolveAssetClass(value: string | null | undefined): string | null;
64
+ /** True iff `storedValue` falls under `filterCode`: both resolve (see
65
+ * resolveAssetClass) and the stored code equals the filter code or descends
66
+ * from it. FIXED_INCOME matches RATES, CREDIT and "Fixed Income"; EQUITY
67
+ * does not match RATES; unknown values match nothing. */
68
+ export declare function assetClassMatches(filterCode: string | null | undefined, storedValue: string | null | undefined): boolean;
69
+ /** Display label for an IdentifierTypeProto value, or null if unknown. */
70
+ export declare function identifierTypeLabelOf(v: IdentifierTypeProto): string | null;
71
+ /** Input placeholder (e.g. "e.g. US0378331005") for an IdentifierTypeProto
72
+ * value, or null if unknown. */
73
+ export declare function identifierTypePlaceholderOf(v: IdentifierTypeProto): string | null;
74
+ /** Display label for an InstrumentTypeProto value, or null if unknown. */
75
+ export declare function instrumentTypeLabelOf(v: InstrumentTypeProto): string | null;
76
+ /** Display label for a ProductTypeProto value: the product_types label, else
77
+ * enum_labels (e.g. PRODUCT_TYPE_UNKNOWN). null if unknown. */
78
+ export declare function productTypeLabelOf(v: ProductTypeProto): string | null;
79
+ /** Display label for an AssetClassProto value: the label of the hierarchy.json
80
+ * code it resolves to (CASH_ASSET_CLASS -> "Cash"), else enum_labels
81
+ * (e.g. INDEX). null if unknown. */
82
+ export declare function assetClassProtoLabelOf(v: AssetClassProto): string | null;
39
83
  export declare function allProductTypes(): string[];
40
84
  export declare function activeProductTypes(): string[];
41
85
  export declare function allAssetClasses(): string[];
42
86
  export declare function allInstrumentTypes(): string[];
87
+ export {};
@@ -14,6 +14,13 @@
14
14
  * Plus per-leaf classification lookups: assetClassOf, instrumentTypeOf,
15
15
  * labelOf.
16
16
  *
17
+ * asset_classes is the one canonical asset-class vocabulary.
18
+ * assetClassMatches filters stored asset-class values (codes, labels such as
19
+ * "Fixed Income", or aliases such as "CASH_ASSET_CLASS") against a code,
20
+ * walking the tree. The *LabelOf / identifierTypePlaceholderOf helpers give
21
+ * display strings for every value of the enums the UI shows. See
22
+ * docs/adr/asset_class_vocabulary.md.
23
+ *
17
24
  * `indexTypeOf` is intentionally absent — that dimension is deferred per
18
25
  * the M1 descope.
19
26
  */
@@ -21,12 +28,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
21
28
  return (mod && mod.__esModule) ? mod : { "default": mod };
22
29
  };
23
30
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.allInstrumentTypes = exports.allAssetClasses = exports.activeProductTypes = exports.allProductTypes = exports.assetClassLabelOf = exports.isAssetClassDescendantOf = exports.assetClassDescendantsOf = exports.assetClassParentOf = exports.instrumentTypeOf = exports.assetClassOf = exports.labelOf = exports.isDescendantOf = exports.descendantsOf = exports.parentOf = void 0;
31
+ exports.allInstrumentTypes = exports.allAssetClasses = exports.activeProductTypes = exports.allProductTypes = exports.assetClassProtoLabelOf = exports.productTypeLabelOf = exports.instrumentTypeLabelOf = exports.identifierTypePlaceholderOf = exports.identifierTypeLabelOf = exports.assetClassMatches = exports.resolveAssetClass = exports.buildAssetClassLookup = exports.assetClassLabelOf = exports.isAssetClassDescendantOf = exports.assetClassDescendantsOf = exports.assetClassParentOf = exports.instrumentTypeOf = exports.assetClassOf = exports.labelOf = exports.isDescendantOf = exports.descendantsOf = exports.parentOf = void 0;
25
32
  // hierarchy.json is bundled into the npm package via the package's `files`
26
33
  // list (see package.json). Bundlers handle this `import` at build time
27
34
  // (TypeScript's resolveJsonModule is enabled).
28
35
  const hierarchy_json_1 = __importDefault(require("../../../../hierarchy.json"));
36
+ const asset_class_pb_1 = require("../../../fintekkers/models/security/asset_class_pb");
37
+ const identifier_type_pb_1 = require("../../../fintekkers/models/security/identifier/identifier_type_pb");
38
+ const instrument_type_pb_1 = require("../../../fintekkers/models/security/instrument_type_pb");
39
+ const product_type_pb_1 = require("../../../fintekkers/models/security/product_type_pb");
29
40
  const registry = hierarchy_json_1.default;
41
+ function hasOwn(o, key) {
42
+ return o !== undefined && Object.prototype.hasOwnProperty.call(o, key);
43
+ }
30
44
  // ---------- product_type tree ----------
31
45
  /** Parent product_type node (abstract or leaf). null for top-level nodes;
32
46
  * null for unknown nodes. */
@@ -134,6 +148,117 @@ function assetClassLabelOf(node) {
134
148
  return (_b = (_a = registry.asset_classes[node]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : null;
135
149
  }
136
150
  exports.assetClassLabelOf = assetClassLabelOf;
151
+ function normaliseAssetClass(value) {
152
+ return value.trim().toUpperCase().replace(/[\s-]+/g, '_');
153
+ }
154
+ /** Normalised code / label / alias -> code. Throws if two codes claim the
155
+ * same key, so an ambiguous label or alias fails at load time. Exported for
156
+ * tests only. */
157
+ function buildAssetClassLookup(classes) {
158
+ var _a;
159
+ const lookup = new Map();
160
+ for (const [code, entry] of Object.entries(classes)) {
161
+ const keys = [code, ...(entry.label ? [entry.label] : []), ...((_a = entry.aliases) !== null && _a !== void 0 ? _a : [])];
162
+ for (const key of keys) {
163
+ const n = normaliseAssetClass(key);
164
+ if (!n)
165
+ continue;
166
+ const prev = lookup.get(n);
167
+ if (prev !== undefined && prev !== code) {
168
+ throw new Error(`hierarchy.json asset_classes: '${key}' resolves to both ${prev} and ${code}`);
169
+ }
170
+ lookup.set(n, code);
171
+ }
172
+ }
173
+ return lookup;
174
+ }
175
+ exports.buildAssetClassLookup = buildAssetClassLookup;
176
+ const assetClassLookup = buildAssetClassLookup(registry.asset_classes);
177
+ /** Resolve a stored or user-supplied asset-class value to its hierarchy.json
178
+ * code. An exact code wins; otherwise the value is normalised (trimmed,
179
+ * upper-cased, runs of whitespace or hyphens turned into `_`) and matched
180
+ * against every code, label and alias. null for null, blank or unknown. */
181
+ function resolveAssetClass(value) {
182
+ var _a;
183
+ if (value === null || value === undefined)
184
+ return null;
185
+ if (hasOwn(registry.asset_classes, value))
186
+ return value;
187
+ return (_a = assetClassLookup.get(normaliseAssetClass(value))) !== null && _a !== void 0 ? _a : null;
188
+ }
189
+ exports.resolveAssetClass = resolveAssetClass;
190
+ /** True iff `storedValue` falls under `filterCode`: both resolve (see
191
+ * resolveAssetClass) and the stored code equals the filter code or descends
192
+ * from it. FIXED_INCOME matches RATES, CREDIT and "Fixed Income"; EQUITY
193
+ * does not match RATES; unknown values match nothing. */
194
+ function assetClassMatches(filterCode, storedValue) {
195
+ const f = resolveAssetClass(filterCode);
196
+ const s = resolveAssetClass(storedValue);
197
+ if (f === null || s === null)
198
+ return false;
199
+ return f === s || isAssetClassDescendantOf(s, f);
200
+ }
201
+ exports.assetClassMatches = assetClassMatches;
202
+ // ---------- enum labels ----------
203
+ /** Name of numeric enum value `v` in a generated *_pb enum object, or null. */
204
+ function enumValueName(enumObj, v) {
205
+ for (const [name, n] of Object.entries(enumObj)) {
206
+ if (n === v)
207
+ return name;
208
+ }
209
+ return null;
210
+ }
211
+ function enumEntry(enumName, valueName) {
212
+ var _a;
213
+ if (valueName === null)
214
+ return null;
215
+ const values = (_a = registry.enum_labels) === null || _a === void 0 ? void 0 : _a[enumName];
216
+ return values && hasOwn(values, valueName) ? values[valueName] : null;
217
+ }
218
+ /** Display label for an IdentifierTypeProto value, or null if unknown. */
219
+ function identifierTypeLabelOf(v) {
220
+ var _a, _b;
221
+ return (_b = (_a = enumEntry('IdentifierTypeProto', enumValueName(identifier_type_pb_1.IdentifierTypeProto, v))) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : null;
222
+ }
223
+ exports.identifierTypeLabelOf = identifierTypeLabelOf;
224
+ /** Input placeholder (e.g. "e.g. US0378331005") for an IdentifierTypeProto
225
+ * value, or null if unknown. */
226
+ function identifierTypePlaceholderOf(v) {
227
+ var _a, _b;
228
+ return (_b = (_a = enumEntry('IdentifierTypeProto', enumValueName(identifier_type_pb_1.IdentifierTypeProto, v))) === null || _a === void 0 ? void 0 : _a.placeholder) !== null && _b !== void 0 ? _b : null;
229
+ }
230
+ exports.identifierTypePlaceholderOf = identifierTypePlaceholderOf;
231
+ /** Display label for an InstrumentTypeProto value, or null if unknown. */
232
+ function instrumentTypeLabelOf(v) {
233
+ var _a, _b;
234
+ return (_b = (_a = enumEntry('InstrumentTypeProto', enumValueName(instrument_type_pb_1.InstrumentTypeProto, v))) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : null;
235
+ }
236
+ exports.instrumentTypeLabelOf = instrumentTypeLabelOf;
237
+ /** Display label for a ProductTypeProto value: the product_types label, else
238
+ * enum_labels (e.g. PRODUCT_TYPE_UNKNOWN). null if unknown. */
239
+ function productTypeLabelOf(v) {
240
+ var _a, _b, _c;
241
+ const name = enumValueName(product_type_pb_1.ProductTypeProto, v);
242
+ if (name === null)
243
+ return null;
244
+ const entry = hasOwn(registry.product_types, name) ? registry.product_types[name] : undefined;
245
+ return (_c = (_a = entry === null || entry === void 0 ? void 0 : entry.label) !== null && _a !== void 0 ? _a : (_b = enumEntry('ProductTypeProto', name)) === null || _b === void 0 ? void 0 : _b.label) !== null && _c !== void 0 ? _c : null;
246
+ }
247
+ exports.productTypeLabelOf = productTypeLabelOf;
248
+ /** Display label for an AssetClassProto value: the label of the hierarchy.json
249
+ * code it resolves to (CASH_ASSET_CLASS -> "Cash"), else enum_labels
250
+ * (e.g. INDEX). null if unknown. */
251
+ function assetClassProtoLabelOf(v) {
252
+ var _a, _b;
253
+ const name = enumValueName(asset_class_pb_1.AssetClassProto, v);
254
+ if (name === null)
255
+ return null;
256
+ const code = resolveAssetClass(name);
257
+ if (code !== null)
258
+ return assetClassLabelOf(code);
259
+ return (_b = (_a = enumEntry('AssetClassProto', name)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : null;
260
+ }
261
+ exports.assetClassProtoLabelOf = assetClassProtoLabelOf;
137
262
  // ---------- introspection ----------
138
263
  function allProductTypes() {
139
264
  return Object.keys(registry.product_types).sort();
@@ -1 +1 @@
1
- {"version":3,"file":"product_hierarchy.js","sourceRoot":"","sources":["product_hierarchy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"product_hierarchy.js","sourceRoot":"","sources":["product_hierarchy.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,13 @@
13
13
  * Plus per-leaf classification lookups: assetClassOf, instrumentTypeOf,
14
14
  * labelOf.
15
15
  *
16
+ * asset_classes is the one canonical asset-class vocabulary.
17
+ * assetClassMatches filters stored asset-class values (codes, labels such as
18
+ * "Fixed Income", or aliases such as "CASH_ASSET_CLASS") against a code,
19
+ * walking the tree. The *LabelOf / identifierTypePlaceholderOf helpers give
20
+ * display strings for every value of the enums the UI shows. See
21
+ * docs/adr/asset_class_vocabulary.md.
22
+ *
16
23
  * `indexTypeOf` is intentionally absent — that dimension is deferred per
17
24
  * the M1 descope.
18
25
  */
@@ -21,6 +28,10 @@
21
28
  // list (see package.json). Bundlers handle this `import` at build time
22
29
  // (TypeScript's resolveJsonModule is enabled).
23
30
  import hierarchy from '../../../../hierarchy.json';
31
+ import { AssetClassProto } from '../../../fintekkers/models/security/asset_class_pb';
32
+ import { IdentifierTypeProto } from '../../../fintekkers/models/security/identifier/identifier_type_pb';
33
+ import { InstrumentTypeProto } from '../../../fintekkers/models/security/instrument_type_pb';
34
+ import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
24
35
 
25
36
  interface ProductTypeEntry {
26
37
  parent?: string | null;
@@ -34,16 +45,27 @@ interface ProductTypeEntry {
34
45
  interface AssetClassEntry {
35
46
  parent?: string | null;
36
47
  label?: string;
48
+ aliases?: string[];
49
+ }
50
+
51
+ interface EnumLabelEntry {
52
+ label?: string;
53
+ placeholder?: string;
37
54
  }
38
55
 
39
56
  interface Registry {
40
57
  product_types: Record<string, ProductTypeEntry>;
41
58
  asset_classes: Record<string, AssetClassEntry>;
42
59
  instrument_types: string[];
60
+ enum_labels?: Record<string, Record<string, EnumLabelEntry>>;
43
61
  }
44
62
 
45
63
  const registry: Registry = hierarchy as Registry;
46
64
 
65
+ function hasOwn(o: object | undefined, key: string): boolean {
66
+ return o !== undefined && Object.prototype.hasOwnProperty.call(o, key);
67
+ }
68
+
47
69
  // ---------- product_type tree ----------
48
70
 
49
71
  /** Parent product_type node (abstract or leaf). null for top-level nodes;
@@ -137,6 +159,112 @@ export function assetClassLabelOf(node: string): string | null {
137
159
  return registry.asset_classes[node]?.label ?? null;
138
160
  }
139
161
 
162
+ function normaliseAssetClass(value: string): string {
163
+ return value.trim().toUpperCase().replace(/[\s-]+/g, '_');
164
+ }
165
+
166
+ /** Normalised code / label / alias -> code. Throws if two codes claim the
167
+ * same key, so an ambiguous label or alias fails at load time. Exported for
168
+ * tests only. */
169
+ export function buildAssetClassLookup(
170
+ classes: Record<string, AssetClassEntry>,
171
+ ): Map<string, string> {
172
+ const lookup = new Map<string, string>();
173
+ for (const [code, entry] of Object.entries(classes)) {
174
+ const keys = [code, ...(entry.label ? [entry.label] : []), ...(entry.aliases ?? [])];
175
+ for (const key of keys) {
176
+ const n = normaliseAssetClass(key);
177
+ if (!n) continue;
178
+ const prev = lookup.get(n);
179
+ if (prev !== undefined && prev !== code) {
180
+ throw new Error(
181
+ `hierarchy.json asset_classes: '${key}' resolves to both ${prev} and ${code}`,
182
+ );
183
+ }
184
+ lookup.set(n, code);
185
+ }
186
+ }
187
+ return lookup;
188
+ }
189
+
190
+ const assetClassLookup = buildAssetClassLookup(registry.asset_classes);
191
+
192
+ /** Resolve a stored or user-supplied asset-class value to its hierarchy.json
193
+ * code. An exact code wins; otherwise the value is normalised (trimmed,
194
+ * upper-cased, runs of whitespace or hyphens turned into `_`) and matched
195
+ * against every code, label and alias. null for null, blank or unknown. */
196
+ export function resolveAssetClass(value: string | null | undefined): string | null {
197
+ if (value === null || value === undefined) return null;
198
+ if (hasOwn(registry.asset_classes, value)) return value;
199
+ return assetClassLookup.get(normaliseAssetClass(value)) ?? null;
200
+ }
201
+
202
+ /** True iff `storedValue` falls under `filterCode`: both resolve (see
203
+ * resolveAssetClass) and the stored code equals the filter code or descends
204
+ * from it. FIXED_INCOME matches RATES, CREDIT and "Fixed Income"; EQUITY
205
+ * does not match RATES; unknown values match nothing. */
206
+ export function assetClassMatches(
207
+ filterCode: string | null | undefined,
208
+ storedValue: string | null | undefined,
209
+ ): boolean {
210
+ const f = resolveAssetClass(filterCode);
211
+ const s = resolveAssetClass(storedValue);
212
+ if (f === null || s === null) return false;
213
+ return f === s || isAssetClassDescendantOf(s, f);
214
+ }
215
+
216
+ // ---------- enum labels ----------
217
+
218
+ /** Name of numeric enum value `v` in a generated *_pb enum object, or null. */
219
+ function enumValueName(enumObj: object, v: number): string | null {
220
+ for (const [name, n] of Object.entries(enumObj)) {
221
+ if (n === v) return name;
222
+ }
223
+ return null;
224
+ }
225
+
226
+ function enumEntry(enumName: string, valueName: string | null): EnumLabelEntry | null {
227
+ if (valueName === null) return null;
228
+ const values = registry.enum_labels?.[enumName];
229
+ return values && hasOwn(values, valueName) ? values[valueName] : null;
230
+ }
231
+
232
+ /** Display label for an IdentifierTypeProto value, or null if unknown. */
233
+ export function identifierTypeLabelOf(v: IdentifierTypeProto): string | null {
234
+ return enumEntry('IdentifierTypeProto', enumValueName(IdentifierTypeProto, v))?.label ?? null;
235
+ }
236
+
237
+ /** Input placeholder (e.g. "e.g. US0378331005") for an IdentifierTypeProto
238
+ * value, or null if unknown. */
239
+ export function identifierTypePlaceholderOf(v: IdentifierTypeProto): string | null {
240
+ return enumEntry('IdentifierTypeProto', enumValueName(IdentifierTypeProto, v))?.placeholder ?? null;
241
+ }
242
+
243
+ /** Display label for an InstrumentTypeProto value, or null if unknown. */
244
+ export function instrumentTypeLabelOf(v: InstrumentTypeProto): string | null {
245
+ return enumEntry('InstrumentTypeProto', enumValueName(InstrumentTypeProto, v))?.label ?? null;
246
+ }
247
+
248
+ /** Display label for a ProductTypeProto value: the product_types label, else
249
+ * enum_labels (e.g. PRODUCT_TYPE_UNKNOWN). null if unknown. */
250
+ export function productTypeLabelOf(v: ProductTypeProto): string | null {
251
+ const name = enumValueName(ProductTypeProto, v);
252
+ if (name === null) return null;
253
+ const entry = hasOwn(registry.product_types, name) ? registry.product_types[name] : undefined;
254
+ return entry?.label ?? enumEntry('ProductTypeProto', name)?.label ?? null;
255
+ }
256
+
257
+ /** Display label for an AssetClassProto value: the label of the hierarchy.json
258
+ * code it resolves to (CASH_ASSET_CLASS -> "Cash"), else enum_labels
259
+ * (e.g. INDEX). null if unknown. */
260
+ export function assetClassProtoLabelOf(v: AssetClassProto): string | null {
261
+ const name = enumValueName(AssetClassProto, v);
262
+ if (name === null) return null;
263
+ const code = resolveAssetClass(name);
264
+ if (code !== null) return assetClassLabelOf(code);
265
+ return enumEntry('AssetClassProto', name)?.label ?? null;
266
+ }
267
+
140
268
  // ---------- introspection ----------
141
269
 
142
270
  export function allProductTypes(): string[] {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fintekkers/ledger-models",
3
3
  "todo": "Replace the version with build script version number",
4
- "version": "0.4.24",
4
+ "version": "0.4.25",
5
5
  "description": "ledger model protos ",
6
6
  "authors": [
7
7
  "David Doherty",