@fintekkers/ledger-models 0.4.9 → 0.4.11

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 (75) hide show
  1. package/node/wrappers/models/hydrate.test.d.ts +1 -0
  2. package/node/wrappers/models/hydrate.test.js +204 -0
  3. package/node/wrappers/models/hydrate.test.js.map +1 -0
  4. package/node/wrappers/models/hydrate.test.ts +214 -0
  5. package/node/wrappers/models/lazy-hydrate-race.test.d.ts +1 -0
  6. package/node/wrappers/models/lazy-hydrate-race.test.js +153 -0
  7. package/node/wrappers/models/lazy-hydrate-race.test.js.map +1 -0
  8. package/node/wrappers/models/lazy-hydrate-race.test.ts +144 -0
  9. package/node/wrappers/models/lazy-hydrate.bench.test.d.ts +1 -0
  10. package/node/wrappers/models/lazy-hydrate.bench.test.js +121 -0
  11. package/node/wrappers/models/lazy-hydrate.bench.test.js.map +1 -0
  12. package/node/wrappers/models/lazy-hydrate.bench.test.ts +103 -0
  13. package/node/wrappers/models/portfolio/portfolio.d.ts +18 -0
  14. package/node/wrappers/models/portfolio/portfolio.js +93 -1
  15. package/node/wrappers/models/portfolio/portfolio.js.map +1 -1
  16. package/node/wrappers/models/portfolio/portfolio.ts +58 -1
  17. package/node/wrappers/models/portfolio-price-transaction.lazy-hydrate.test.d.ts +1 -0
  18. package/node/wrappers/models/portfolio-price-transaction.lazy-hydrate.test.js +158 -0
  19. package/node/wrappers/models/portfolio-price-transaction.lazy-hydrate.test.js.map +1 -0
  20. package/node/wrappers/models/portfolio-price-transaction.lazy-hydrate.test.ts +153 -0
  21. package/node/wrappers/models/price/Price.d.ts +5 -0
  22. package/node/wrappers/models/price/Price.js +48 -0
  23. package/node/wrappers/models/price/Price.js.map +1 -1
  24. package/node/wrappers/models/price/Price.ts +26 -0
  25. package/node/wrappers/models/security/identifier-validation.test.d.ts +1 -0
  26. package/node/wrappers/models/security/identifier-validation.test.js +104 -0
  27. package/node/wrappers/models/security/identifier-validation.test.js.map +1 -0
  28. package/node/wrappers/models/security/identifier-validation.test.ts +133 -0
  29. package/node/wrappers/models/security/identifier.d.ts +26 -0
  30. package/node/wrappers/models/security/identifier.js +54 -1
  31. package/node/wrappers/models/security/identifier.js.map +1 -1
  32. package/node/wrappers/models/security/identifier.test.js +6 -9
  33. package/node/wrappers/models/security/identifier.test.js.map +1 -1
  34. package/node/wrappers/models/security/identifier.test.ts +6 -9
  35. package/node/wrappers/models/security/identifier.ts +58 -0
  36. package/node/wrappers/models/security/security.d.ts +23 -5
  37. package/node/wrappers/models/security/security.js +53 -6
  38. package/node/wrappers/models/security/security.js.map +1 -1
  39. package/node/wrappers/models/security/security.ts +38 -6
  40. package/node/wrappers/models/transaction/transaction.d.ts +18 -0
  41. package/node/wrappers/models/transaction/transaction.js +98 -0
  42. package/node/wrappers/models/transaction/transaction.js.map +1 -1
  43. package/node/wrappers/models/transaction/transaction.ts +65 -0
  44. package/node/wrappers/services/portfolio-service/PortfolioService.js +35 -0
  45. package/node/wrappers/services/portfolio-service/PortfolioService.js.map +1 -1
  46. package/node/wrappers/services/portfolio-service/PortfolioService.ts +14 -2
  47. package/node/wrappers/services/price-service/PriceService.js +10 -0
  48. package/node/wrappers/services/price-service/PriceService.js.map +1 -1
  49. package/node/wrappers/services/price-service/PriceService.ts +12 -2
  50. package/node/wrappers/services/security-service/SecurityService.js +23 -0
  51. package/node/wrappers/services/security-service/SecurityService.js.map +1 -1
  52. package/node/wrappers/services/security-service/SecurityService.ts +27 -2
  53. package/node/wrappers/services/security.identifier-guard.test.d.ts +1 -0
  54. package/node/wrappers/services/security.identifier-guard.test.js +63 -0
  55. package/node/wrappers/services/security.identifier-guard.test.js.map +1 -0
  56. package/node/wrappers/services/security.identifier-guard.test.ts +70 -0
  57. package/node/wrappers/services/service-client-writethrough.test.d.ts +1 -0
  58. package/node/wrappers/services/service-client-writethrough.test.js +147 -0
  59. package/node/wrappers/services/service-client-writethrough.test.js.map +1 -0
  60. package/node/wrappers/services/service-client-writethrough.test.ts +141 -0
  61. package/node/wrappers/services/transaction-service/TransactionService.js +36 -0
  62. package/node/wrappers/services/transaction-service/TransactionService.js.map +1 -1
  63. package/node/wrappers/services/transaction-service/TransactionService.ts +13 -0
  64. package/node/wrappers/util/link-cache.d.ts +13 -6
  65. package/node/wrappers/util/link-cache.js +51 -15
  66. package/node/wrappers/util/link-cache.js.map +1 -1
  67. package/node/wrappers/util/link-cache.ts +51 -17
  68. package/node/wrappers/util/link-resolver.d.ts +39 -31
  69. package/node/wrappers/util/link-resolver.js +157 -97
  70. package/node/wrappers/util/link-resolver.js.map +1 -1
  71. package/node/wrappers/util/link-resolver.test.js +88 -2
  72. package/node/wrappers/util/link-resolver.test.js.map +1 -1
  73. package/node/wrappers/util/link-resolver.test.ts +76 -2
  74. package/node/wrappers/util/link-resolver.ts +143 -124
  75. package/package.json +1 -1
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ // Lazy-hydrate tests for Portfolio / Price / Transaction wrappers.
3
+ // Mirror of security.lazy-hydrate.test.ts — cache-only design, throws on miss.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || function (mod) {
21
+ if (mod && mod.__esModule) return mod;
22
+ var result = {};
23
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24
+ __setModuleDefault(result, mod);
25
+ return result;
26
+ };
27
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28
+ return (mod && mod.__esModule) ? mod : { "default": mod };
29
+ };
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ const portfolio_1 = __importDefault(require("./portfolio/portfolio"));
32
+ const Price_1 = __importDefault(require("./price/Price"));
33
+ const transaction_1 = __importDefault(require("./transaction/transaction"));
34
+ const uuid_1 = require("./utils/uuid");
35
+ const datetime_1 = require("./utils/datetime");
36
+ const portfolio_pb_1 = require("../../fintekkers/models/portfolio/portfolio_pb");
37
+ const price_pb_1 = require("../../fintekkers/models/price/price_pb");
38
+ const transaction_pb_1 = require("../../fintekkers/models/transaction/transaction_pb");
39
+ const decimal_value_pb_1 = require("../../fintekkers/models/util/decimal_value_pb");
40
+ const local_timestamp_pb_1 = require("../../fintekkers/models/util/local_timestamp_pb");
41
+ const timestamp_pb_1 = require("google-protobuf/google/protobuf/timestamp_pb");
42
+ const LinkCache = __importStar(require("../util/link-cache"));
43
+ function makeAsOf(epochSeconds = 1700000000) {
44
+ const ts = new timestamp_pb_1.Timestamp();
45
+ ts.setSeconds(epochSeconds);
46
+ ts.setNanos(0);
47
+ const proto = new local_timestamp_pb_1.LocalTimestampProto();
48
+ proto.setTimestamp(ts);
49
+ proto.setTimeZone('UTC');
50
+ return new datetime_1.ZonedDateTime(proto);
51
+ }
52
+ function linkPortfolio(uuid, asOf) {
53
+ const p = new portfolio_pb_1.PortfolioProto();
54
+ p.setUuid(uuid.toUUIDProto());
55
+ p.setAsOf(asOf.toProto());
56
+ p.setIsLink(true);
57
+ return p;
58
+ }
59
+ function fullPortfolio(uuid, asOf, name) {
60
+ const p = new portfolio_pb_1.PortfolioProto();
61
+ p.setUuid(uuid.toUUIDProto());
62
+ p.setAsOf(asOf.toProto());
63
+ p.setIsLink(false);
64
+ p.setPortfolioName(name);
65
+ return p;
66
+ }
67
+ function linkPriceProto(uuid, asOf) {
68
+ const p = new price_pb_1.PriceProto();
69
+ p.setUuid(uuid.toUUIDProto());
70
+ p.setAsOf(asOf.toProto());
71
+ p.setIsLink(true);
72
+ return p;
73
+ }
74
+ function fullPriceProto(uuid, asOf, value) {
75
+ const p = new price_pb_1.PriceProto();
76
+ p.setUuid(uuid.toUUIDProto());
77
+ p.setAsOf(asOf.toProto());
78
+ p.setIsLink(false);
79
+ const dv = new decimal_value_pb_1.DecimalValueProto();
80
+ dv.setArbitraryPrecisionValue(value);
81
+ p.setPrice(dv);
82
+ return p;
83
+ }
84
+ function linkTxnProto(uuid, asOf) {
85
+ const p = new transaction_pb_1.TransactionProto();
86
+ p.setUuid(uuid.toUUIDProto());
87
+ p.setAsOf(asOf.toProto());
88
+ p.setIsLink(true);
89
+ return p;
90
+ }
91
+ function fullTxnProto(uuid, asOf) {
92
+ const p = new transaction_pb_1.TransactionProto();
93
+ p.setUuid(uuid.toUUIDProto());
94
+ p.setAsOf(asOf.toProto());
95
+ p.setIsLink(false);
96
+ p.setTradeName('TXN');
97
+ return p;
98
+ }
99
+ beforeEach(() => {
100
+ LinkCache.PORTFOLIO.clear();
101
+ LinkCache.PRICE.clear();
102
+ LinkCache.TRANSACTION.clear();
103
+ });
104
+ // ---- Portfolio ----
105
+ test('Portfolio getPortfolioName on link wrapper hydrates from cache', () => {
106
+ const uuid = uuid_1.UUID.random();
107
+ const asOf = makeAsOf(1);
108
+ LinkCache.PORTFOLIO.put(uuid.toString(), fullPortfolio(uuid, asOf, 'Strategy Z'), asOf);
109
+ const p = new portfolio_1.default(linkPortfolio(uuid, asOf));
110
+ expect(p.isLink()).toBe(true);
111
+ expect(p.getPortfolioName()).toBe('Strategy Z');
112
+ expect(p.proto.getIsLink()).toBe(false);
113
+ });
114
+ test('Portfolio cache miss throws with uuid in message', () => {
115
+ const uuid = uuid_1.UUID.random();
116
+ const asOf = makeAsOf(2);
117
+ const p = new portfolio_1.default(linkPortfolio(uuid, asOf));
118
+ expect(() => p.getPortfolioName()).toThrow(new RegExp(uuid.toString()));
119
+ });
120
+ // ---- Price ----
121
+ test('Price getPrice on link wrapper hydrates from cache', () => {
122
+ const uuid = uuid_1.UUID.random();
123
+ const asOf = makeAsOf(3);
124
+ LinkCache.PRICE.put(uuid.toString(), fullPriceProto(uuid, asOf, '123.45'), asOf);
125
+ const pr = new Price_1.default(linkPriceProto(uuid, asOf));
126
+ expect(pr.isLink()).toBe(true);
127
+ expect(pr.getPrice().toString()).toBe('123.45');
128
+ });
129
+ test('Price cache miss throws with uuid in message', () => {
130
+ const uuid = uuid_1.UUID.random();
131
+ const asOf = makeAsOf(4);
132
+ const pr = new Price_1.default(linkPriceProto(uuid, asOf));
133
+ expect(() => pr.getPrice()).toThrow(new RegExp(uuid.toString()));
134
+ });
135
+ // ---- Transaction ----
136
+ test('Transaction getTradeName on link wrapper hydrates from cache', () => {
137
+ const uuid = uuid_1.UUID.random();
138
+ const asOf = makeAsOf(5);
139
+ LinkCache.TRANSACTION.put(uuid.toString(), fullTxnProto(uuid, asOf), asOf);
140
+ const t = new transaction_1.default(linkTxnProto(uuid, asOf));
141
+ expect(t.isLink()).toBe(true);
142
+ expect(t.getTradeName()).toBe('TXN');
143
+ });
144
+ test('Transaction cache miss throws with uuid in message', () => {
145
+ const uuid = uuid_1.UUID.random();
146
+ const asOf = makeAsOf(6);
147
+ const t = new transaction_1.default(linkTxnProto(uuid, asOf));
148
+ expect(() => t.getTradeName()).toThrow(new RegExp(uuid.toString()));
149
+ });
150
+ test('Transaction link-safe accessors do not hydrate', () => {
151
+ const uuid = uuid_1.UUID.random();
152
+ const asOf = makeAsOf(7);
153
+ // No cache entry, no fetcher — link-safe accessors must still work.
154
+ const t = new transaction_1.default(linkTxnProto(uuid, asOf));
155
+ expect(t.isLink()).toBe(true);
156
+ expect(t.getID().toString()).toBe(uuid.toString());
157
+ });
158
+ //# sourceMappingURL=portfolio-price-transaction.lazy-hydrate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio-price-transaction.lazy-hydrate.test.js","sourceRoot":"","sources":["portfolio-price-transaction.lazy-hydrate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ // Lazy-hydrate tests for Portfolio / Price / Transaction wrappers.
2
+ // Mirror of security.lazy-hydrate.test.ts — cache-only design, throws on miss.
3
+
4
+ import Portfolio from './portfolio/portfolio';
5
+ import Price from './price/Price';
6
+ import Transaction from './transaction/transaction';
7
+ import { UUID } from './utils/uuid';
8
+ import { ZonedDateTime } from './utils/datetime';
9
+
10
+ import { PortfolioProto } from '../../fintekkers/models/portfolio/portfolio_pb';
11
+ import { PriceProto } from '../../fintekkers/models/price/price_pb';
12
+ import { TransactionProto } from '../../fintekkers/models/transaction/transaction_pb';
13
+ import { DecimalValueProto } from '../../fintekkers/models/util/decimal_value_pb';
14
+ import { LocalTimestampProto } from '../../fintekkers/models/util/local_timestamp_pb';
15
+ import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
16
+
17
+ import * as LinkCache from '../util/link-cache';
18
+
19
+ function makeAsOf(epochSeconds = 1_700_000_000): ZonedDateTime {
20
+ const ts = new Timestamp();
21
+ ts.setSeconds(epochSeconds);
22
+ ts.setNanos(0);
23
+ const proto = new LocalTimestampProto();
24
+ proto.setTimestamp(ts);
25
+ proto.setTimeZone('UTC');
26
+ return new ZonedDateTime(proto);
27
+ }
28
+
29
+ function linkPortfolio(uuid: UUID, asOf: ZonedDateTime): PortfolioProto {
30
+ const p = new PortfolioProto();
31
+ p.setUuid(uuid.toUUIDProto());
32
+ p.setAsOf(asOf.toProto());
33
+ p.setIsLink(true);
34
+ return p;
35
+ }
36
+
37
+ function fullPortfolio(uuid: UUID, asOf: ZonedDateTime, name: string): PortfolioProto {
38
+ const p = new PortfolioProto();
39
+ p.setUuid(uuid.toUUIDProto());
40
+ p.setAsOf(asOf.toProto());
41
+ p.setIsLink(false);
42
+ p.setPortfolioName(name);
43
+ return p;
44
+ }
45
+
46
+ function linkPriceProto(uuid: UUID, asOf: ZonedDateTime): PriceProto {
47
+ const p = new PriceProto();
48
+ p.setUuid(uuid.toUUIDProto());
49
+ p.setAsOf(asOf.toProto());
50
+ p.setIsLink(true);
51
+ return p;
52
+ }
53
+
54
+ function fullPriceProto(uuid: UUID, asOf: ZonedDateTime, value: string): PriceProto {
55
+ const p = new PriceProto();
56
+ p.setUuid(uuid.toUUIDProto());
57
+ p.setAsOf(asOf.toProto());
58
+ p.setIsLink(false);
59
+ const dv = new DecimalValueProto();
60
+ dv.setArbitraryPrecisionValue(value);
61
+ p.setPrice(dv);
62
+ return p;
63
+ }
64
+
65
+ function linkTxnProto(uuid: UUID, asOf: ZonedDateTime): TransactionProto {
66
+ const p = new TransactionProto();
67
+ p.setUuid(uuid.toUUIDProto());
68
+ p.setAsOf(asOf.toProto());
69
+ p.setIsLink(true);
70
+ return p;
71
+ }
72
+
73
+ function fullTxnProto(uuid: UUID, asOf: ZonedDateTime): TransactionProto {
74
+ const p = new TransactionProto();
75
+ p.setUuid(uuid.toUUIDProto());
76
+ p.setAsOf(asOf.toProto());
77
+ p.setIsLink(false);
78
+ p.setTradeName('TXN');
79
+ return p;
80
+ }
81
+
82
+ beforeEach(() => {
83
+ LinkCache.PORTFOLIO.clear();
84
+ LinkCache.PRICE.clear();
85
+ LinkCache.TRANSACTION.clear();
86
+ });
87
+
88
+ // ---- Portfolio ----
89
+
90
+ test('Portfolio getPortfolioName on link wrapper hydrates from cache', () => {
91
+ const uuid = UUID.random();
92
+ const asOf = makeAsOf(1);
93
+ LinkCache.PORTFOLIO.put(uuid.toString(), fullPortfolio(uuid, asOf, 'Strategy Z'), asOf);
94
+
95
+ const p = new Portfolio(linkPortfolio(uuid, asOf));
96
+ expect(p.isLink()).toBe(true);
97
+ expect(p.getPortfolioName()).toBe('Strategy Z');
98
+ expect(p.proto.getIsLink()).toBe(false);
99
+ });
100
+
101
+ test('Portfolio cache miss throws with uuid in message', () => {
102
+ const uuid = UUID.random();
103
+ const asOf = makeAsOf(2);
104
+ const p = new Portfolio(linkPortfolio(uuid, asOf));
105
+ expect(() => p.getPortfolioName()).toThrow(new RegExp(uuid.toString()));
106
+ });
107
+
108
+ // ---- Price ----
109
+
110
+ test('Price getPrice on link wrapper hydrates from cache', () => {
111
+ const uuid = UUID.random();
112
+ const asOf = makeAsOf(3);
113
+ LinkCache.PRICE.put(uuid.toString(), fullPriceProto(uuid, asOf, '123.45'), asOf);
114
+
115
+ const pr = new Price(linkPriceProto(uuid, asOf));
116
+ expect(pr.isLink()).toBe(true);
117
+ expect(pr.getPrice().toString()).toBe('123.45');
118
+ });
119
+
120
+ test('Price cache miss throws with uuid in message', () => {
121
+ const uuid = UUID.random();
122
+ const asOf = makeAsOf(4);
123
+ const pr = new Price(linkPriceProto(uuid, asOf));
124
+ expect(() => pr.getPrice()).toThrow(new RegExp(uuid.toString()));
125
+ });
126
+
127
+ // ---- Transaction ----
128
+
129
+ test('Transaction getTradeName on link wrapper hydrates from cache', () => {
130
+ const uuid = UUID.random();
131
+ const asOf = makeAsOf(5);
132
+ LinkCache.TRANSACTION.put(uuid.toString(), fullTxnProto(uuid, asOf), asOf);
133
+
134
+ const t = new Transaction(linkTxnProto(uuid, asOf));
135
+ expect(t.isLink()).toBe(true);
136
+ expect(t.getTradeName()).toBe('TXN');
137
+ });
138
+
139
+ test('Transaction cache miss throws with uuid in message', () => {
140
+ const uuid = UUID.random();
141
+ const asOf = makeAsOf(6);
142
+ const t = new Transaction(linkTxnProto(uuid, asOf));
143
+ expect(() => t.getTradeName()).toThrow(new RegExp(uuid.toString()));
144
+ });
145
+
146
+ test('Transaction link-safe accessors do not hydrate', () => {
147
+ const uuid = UUID.random();
148
+ const asOf = makeAsOf(7);
149
+ // No cache entry, no fetcher — link-safe accessors must still work.
150
+ const t = new Transaction(linkTxnProto(uuid, asOf));
151
+ expect(t.isLink()).toBe(true);
152
+ expect(t.getID().toString()).toBe(uuid.toString());
153
+ });
@@ -32,6 +32,11 @@ declare class Price {
32
32
  * See docs/adr/is_link_pattern.md. Pair with LinkResolver to hydrate.
33
33
  */
34
34
  isLink(): boolean;
35
+ /**
36
+ * Lazy hydration. Cache-only — caller must pre-warm via LinkResolver.
37
+ * See docs/adr/lazy-link-hydration.md.
38
+ */
39
+ private ensureHydrated;
35
40
  getPrice(): Decimal;
36
41
  getPriceType(): PriceTypeProto;
37
42
  getSecurity(): Security;
@@ -1,4 +1,27 @@
1
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
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -11,6 +34,7 @@ const security_1 = __importDefault(require("../security/security"));
11
34
  const datetime_1 = require("../utils/datetime");
12
35
  const uuid_1 = require("../utils/uuid");
13
36
  const decimal_js_1 = require("decimal.js");
37
+ const LinkCacheModule = __importStar(require("../../util/link-cache"));
14
38
  class Price {
15
39
  constructor(proto) {
16
40
  this.proto = proto;
@@ -75,13 +99,37 @@ class Price {
75
99
  isLink() {
76
100
  return this.proto.getIsLink();
77
101
  }
102
+ /**
103
+ * Lazy hydration. Cache-only — caller must pre-warm via LinkResolver.
104
+ * See docs/adr/lazy-link-hydration.md.
105
+ */
106
+ ensureHydrated() {
107
+ if (!this.proto.getIsLink())
108
+ return;
109
+ const uuidProto = this.proto.getUuid();
110
+ if (!uuidProto)
111
+ throw new Error("Cannot read fields on link-mode Price with no UUID set.");
112
+ const uuidKey = uuid_1.UUID.fromU8Array(uuidProto.getRawUuid_asU8()).toString();
113
+ const asOfProto = this.proto.getAsOf();
114
+ const asOf = asOfProto ? new datetime_1.ZonedDateTime(asOfProto) : null;
115
+ const cached = LinkCacheModule.PRICE.get(uuidKey, asOf);
116
+ if (cached) {
117
+ this.proto = cached;
118
+ return;
119
+ }
120
+ throw new Error(`Cannot read fields on link-mode Price uuid=${uuidKey} `
121
+ + `— LinkCache miss. Pre-warm via LinkResolver. `
122
+ + `See docs/adr/lazy-link-hydration.md.`);
123
+ }
78
124
  getPrice() {
125
+ this.ensureHydrated();
79
126
  const priceValue = this.proto.getPrice();
80
127
  if (!priceValue)
81
128
  throw new Error("Price value is required");
82
129
  return new decimal_js_1.Decimal(priceValue.getArbitraryPrecisionValue());
83
130
  }
84
131
  getPriceType() {
132
+ this.ensureHydrated();
85
133
  return this.proto.getPriceType();
86
134
  }
87
135
  getSecurity() {
@@ -1 +1 @@
1
- {"version":3,"file":"Price.js","sourceRoot":"","sources":["Price.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Price.js","sourceRoot":"","sources":["Price.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import Security from "../security/security";
6
6
  import { ZonedDateTime } from "../utils/datetime";
7
7
  import { UUID } from "../utils/uuid";
8
8
  import { Decimal } from "decimal.js";
9
+ import * as LinkCacheModule from "../../util/link-cache";
9
10
 
10
11
  class Price {
11
12
  proto: PriceProto;
@@ -88,13 +89,38 @@ class Price {
88
89
  return this.proto.getIsLink();
89
90
  }
90
91
 
92
+ /**
93
+ * Lazy hydration. Cache-only — caller must pre-warm via LinkResolver.
94
+ * See docs/adr/lazy-link-hydration.md.
95
+ */
96
+ private ensureHydrated(): void {
97
+ if (!this.proto.getIsLink()) return;
98
+ const uuidProto = this.proto.getUuid();
99
+ if (!uuidProto) throw new Error("Cannot read fields on link-mode Price with no UUID set.");
100
+ const uuidKey = UUID.fromU8Array(uuidProto.getRawUuid_asU8()).toString();
101
+ const asOfProto = this.proto.getAsOf();
102
+ const asOf = asOfProto ? new ZonedDateTime(asOfProto) : null;
103
+ const cached = LinkCacheModule.PRICE.get(uuidKey, asOf);
104
+ if (cached) {
105
+ this.proto = cached;
106
+ return;
107
+ }
108
+ throw new Error(
109
+ `Cannot read fields on link-mode Price uuid=${uuidKey} `
110
+ + `— LinkCache miss. Pre-warm via LinkResolver. `
111
+ + `See docs/adr/lazy-link-hydration.md.`
112
+ );
113
+ }
114
+
91
115
  getPrice(): Decimal {
116
+ this.ensureHydrated();
92
117
  const priceValue = this.proto.getPrice();
93
118
  if (!priceValue) throw new Error("Price value is required");
94
119
  return new Decimal(priceValue.getArbitraryPrecisionValue());
95
120
  }
96
121
 
97
122
  getPriceType(): PriceTypeProto {
123
+ this.ensureHydrated();
98
124
  return this.proto.getPriceType();
99
125
  }
100
126
 
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ // Client-side identifier guard tests (FinTekkers/second-brain#347).
3
+ // Pins behaviour of the consumer-side reject so callers fail fast on the
4
+ // client before the gRPC round-trip, mirroring the server's
5
+ // SecurityAPIGRPCImpl.validateCreateRequest UNKNOWN_IDENTIFIER_TYPE check.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const identifier_pb_1 = require("../../../fintekkers/models/security/identifier/identifier_pb");
8
+ const identifier_type_pb_1 = require("../../../fintekkers/models/security/identifier/identifier_type_pb");
9
+ const security_pb_1 = require("../../../fintekkers/models/security/security_pb");
10
+ const identifier_1 = require("./identifier");
11
+ function makeIdentifier(type, value) {
12
+ const p = new identifier_pb_1.IdentifierProto();
13
+ p.setIdentifierType(type);
14
+ p.setIdentifierValue(value);
15
+ return p;
16
+ }
17
+ // ---------- validateIdentifierProto ----------
18
+ describe('validateIdentifierProto', () => {
19
+ test('rejects UNKNOWN_IDENTIFIER_TYPE with a helpful message', () => {
20
+ const bad = makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.UNKNOWN_IDENTIFIER_TYPE, 'some-uuid-hex');
21
+ let err;
22
+ try {
23
+ (0, identifier_1.validateIdentifierProto)(bad);
24
+ }
25
+ catch (e) {
26
+ err = e;
27
+ }
28
+ expect(err).toBeInstanceOf(identifier_1.IdentifierValidationError);
29
+ expect(err.message).toMatch(/UNKNOWN_IDENTIFIER_TYPE/);
30
+ // Surfaces the valid alternatives so the caller can fix the typo
31
+ expect(err.message).toMatch(/EXCH_TICKER/);
32
+ expect(err.message).toMatch(/#347/);
33
+ });
34
+ test('rejects a default-constructed identifier (type=0, empty value)', () => {
35
+ const bad = new identifier_pb_1.IdentifierProto();
36
+ expect(() => (0, identifier_1.validateIdentifierProto)(bad)).toThrow(identifier_1.IdentifierValidationError);
37
+ });
38
+ test('rejects empty identifier_value with the type name in the message', () => {
39
+ const bad = makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.EXCH_TICKER, '');
40
+ let err;
41
+ try {
42
+ (0, identifier_1.validateIdentifierProto)(bad);
43
+ }
44
+ catch (e) {
45
+ err = e;
46
+ }
47
+ expect(err).toBeInstanceOf(identifier_1.IdentifierValidationError);
48
+ expect(err.message).toMatch(/empty/);
49
+ expect(err.message).toMatch(/EXCH_TICKER/);
50
+ });
51
+ test('rejects whitespace-only identifier_value', () => {
52
+ const bad = makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.CUSIP, ' ');
53
+ expect(() => (0, identifier_1.validateIdentifierProto)(bad)).toThrow(identifier_1.IdentifierValidationError);
54
+ });
55
+ test.each([
56
+ ['EXCH_TICKER', identifier_type_pb_1.IdentifierTypeProto.EXCH_TICKER, 'AAPL'],
57
+ ['ISIN', identifier_type_pb_1.IdentifierTypeProto.ISIN, 'US0378331005'],
58
+ ['CUSIP', identifier_type_pb_1.IdentifierTypeProto.CUSIP, '037833100'],
59
+ ['FIGI', identifier_type_pb_1.IdentifierTypeProto.FIGI, 'BBG000B9XRY4'],
60
+ ['OSI', identifier_type_pb_1.IdentifierTypeProto.OSI, 'AAPL 250620C00150000'],
61
+ ['SERIES_ID', identifier_type_pb_1.IdentifierTypeProto.SERIES_ID, 'GS10'],
62
+ ['INDEX_NAME', identifier_type_pb_1.IdentifierTypeProto.INDEX_NAME, 'SPX'],
63
+ ['CASH', identifier_type_pb_1.IdentifierTypeProto.CASH, 'USD'],
64
+ ])('accepts every real identifier type (%s)', (_name, type, value) => {
65
+ const good = makeIdentifier(type, value);
66
+ expect(() => (0, identifier_1.validateIdentifierProto)(good)).not.toThrow();
67
+ });
68
+ test('IdentifierValidationError is an Error', () => {
69
+ // Catch-by-Error still works for callers that don't import the
70
+ // specific subclass.
71
+ const err = new identifier_1.IdentifierValidationError('x');
72
+ expect(err).toBeInstanceOf(Error);
73
+ expect(err.name).toBe('IdentifierValidationError');
74
+ });
75
+ });
76
+ // ---------- validateIdentifiersForCreate ----------
77
+ describe('validateIdentifiersForCreate', () => {
78
+ test('passes when every identifier on the SecurityProto is well-typed', () => {
79
+ const security = new security_pb_1.SecurityProto();
80
+ security.addIdentifiers(makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.EXCH_TICKER, 'AAPL'));
81
+ security.addIdentifiers(makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.ISIN, 'US0378331005'));
82
+ expect(() => (0, identifier_1.validateIdentifiersForCreate)(security)).not.toThrow();
83
+ });
84
+ test('rejects when any identifier in the list is UNKNOWN_IDENTIFIER_TYPE', () => {
85
+ const security = new security_pb_1.SecurityProto();
86
+ security.addIdentifiers(makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.EXCH_TICKER, 'AAPL'));
87
+ security.addIdentifiers(makeIdentifier(identifier_type_pb_1.IdentifierTypeProto.UNKNOWN_IDENTIFIER_TYPE, 'stale-uuid'));
88
+ expect(() => (0, identifier_1.validateIdentifiersForCreate)(security)).toThrow(identifier_1.IdentifierValidationError);
89
+ });
90
+ test('skips link-mode securities (is_link=true)', () => {
91
+ // Link-mode = reference handle (uuid + as_of only); no identifiers
92
+ // attached. The guard must skip rather than over-trigger.
93
+ const link = new security_pb_1.SecurityProto();
94
+ link.setIsLink(true);
95
+ expect(() => (0, identifier_1.validateIdentifiersForCreate)(link)).not.toThrow();
96
+ });
97
+ test('passes on empty identifiers list (server enforces "at least one")', () => {
98
+ // Our consumer-side check polices the *type* of every attached
99
+ // identifier; the "must have ≥1 identifier" rule lives server-side.
100
+ const security = new security_pb_1.SecurityProto();
101
+ expect(() => (0, identifier_1.validateIdentifiersForCreate)(security)).not.toThrow();
102
+ });
103
+ });
104
+ //# sourceMappingURL=identifier-validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifier-validation.test.js","sourceRoot":"","sources":["identifier-validation.test.ts"],"names":[],"mappings":"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"}