@fintekkers/ledger-models 0.4.30 → 0.4.31
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/node/wrappers/models/utils/requestcontext.auth.test.js +21 -6
- package/node/wrappers/models/utils/requestcontext.auth.test.js.map +1 -1
- package/node/wrappers/models/utils/requestcontext.auth.test.ts +24 -6
- package/node/wrappers/models/utils/requestcontext.d.ts +18 -12
- package/node/wrappers/models/utils/requestcontext.js +28 -28
- package/node/wrappers/models/utils/requestcontext.js.map +1 -1
- package/node/wrappers/models/utils/requestcontext.test.js +15 -3
- package/node/wrappers/models/utils/requestcontext.test.js.map +1 -1
- package/node/wrappers/models/utils/requestcontext.test.ts +17 -3
- package/node/wrappers/models/utils/requestcontext.ts +31 -29
- package/node/wrappers/services/apikey.credentials.test.d.ts +1 -1
- package/node/wrappers/services/apikey.credentials.test.js +14 -12
- package/node/wrappers/services/apikey.credentials.test.js.map +1 -1
- package/node/wrappers/services/apikey.credentials.test.ts +15 -13
- package/node/wrappers/services/apikey.test.js +1 -1
- package/node/wrappers/services/apikey.test.js.map +1 -1
- package/node/wrappers/services/apikey.test.ts +1 -1
- package/node/wrappers/services/portfolio-service/PortfolioService.d.ts +2 -1
- package/node/wrappers/services/portfolio-service/PortfolioService.js +8 -4
- package/node/wrappers/services/portfolio-service/PortfolioService.js.map +1 -1
- package/node/wrappers/services/portfolio-service/PortfolioService.ts +8 -4
- package/node/wrappers/services/position-service/PositionService.js +4 -3
- package/node/wrappers/services/position-service/PositionService.js.map +1 -1
- package/node/wrappers/services/position-service/PositionService.ts +4 -3
- package/node/wrappers/services/price-service/PriceService.js +4 -3
- package/node/wrappers/services/price-service/PriceService.js.map +1 -1
- package/node/wrappers/services/price-service/PriceService.ts +4 -3
- package/node/wrappers/services/security-service/SecurityService.js +4 -3
- package/node/wrappers/services/security-service/SecurityService.js.map +1 -1
- package/node/wrappers/services/security-service/SecurityService.ts +4 -3
- package/node/wrappers/services/serviceaddress.clients.test.d.ts +9 -0
- package/node/wrappers/services/serviceaddress.clients.test.js +181 -0
- package/node/wrappers/services/serviceaddress.clients.test.js.map +1 -0
- package/node/wrappers/services/serviceaddress.clients.test.ts +176 -0
- package/node/wrappers/services/transaction-service/TransactionService.js +4 -3
- package/node/wrappers/services/transaction-service/TransactionService.js.map +1 -1
- package/node/wrappers/services/transaction-service/TransactionService.ts +4 -3
- package/node/wrappers/util/link-resolver.d.ts +1 -1
- package/node/wrappers/util/link-resolver.js +10 -9
- package/node/wrappers/util/link-resolver.js.map +1 -1
- package/node/wrappers/util/link-resolver.ts +11 -10
- package/node/wrappers/util/serviceaddress.d.ts +47 -0
- package/node/wrappers/util/serviceaddress.js +132 -0
- package/node/wrappers/util/serviceaddress.js.map +1 -0
- package/node/wrappers/util/serviceaddress.test.d.ts +6 -0
- package/node/wrappers/util/serviceaddress.test.js +76 -0
- package/node/wrappers/util/serviceaddress.test.js.map +1 -0
- package/node/wrappers/util/serviceaddress.test.ts +83 -0
- package/node/wrappers/util/serviceaddress.ts +141 -0
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the address of a FinTekkers service from the environment, the same
|
|
3
|
+
* way as Java `ServiceAddress` and Rust `service_address.rs` (LM-278). Every
|
|
4
|
+
* default client resolves through here, in this order:
|
|
5
|
+
*
|
|
6
|
+
* 1. `BROKER_HOST` (`host[:port]`, port defaults to {@link BROKER_PORT}):
|
|
7
|
+
* all calls go through the broker.
|
|
8
|
+
* 2. Only if that is unset, `<SERVICE>_SERVICE_HOST` with
|
|
9
|
+
* `<SERVICE>_SERVICE_PORT` (or the service's standard port). `_PORT`
|
|
10
|
+
* without `_HOST` is ignored.
|
|
11
|
+
* 3. `API_URL`, with the service's standard port unless it carries one.
|
|
12
|
+
* 4. `localhost` on the service's standard port.
|
|
13
|
+
*
|
|
14
|
+
* An empty value counts as unset. A leading `http://` or `https://` is
|
|
15
|
+
* ignored. Loopback hosts (`localhost`, `127.0.0.1`) are plaintext; any other
|
|
16
|
+
* host uses TLS. A port that is not a number throws an Error naming the
|
|
17
|
+
* variable.
|
|
18
|
+
*
|
|
19
|
+
* The same cases are checked in every language against
|
|
20
|
+
* `test-fixtures/service-address-cases.json`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const BROKER_PORT = 8085;
|
|
23
|
+
export declare const LEDGER_PORT = 8082;
|
|
24
|
+
export declare const VALUATION_PORT = 8080;
|
|
25
|
+
export declare const PRICE_PORT = 8083;
|
|
26
|
+
export declare enum Service {
|
|
27
|
+
BROKER = "BROKER",
|
|
28
|
+
SECURITY = "SECURITY",
|
|
29
|
+
TRANSACTION = "TRANSACTION",
|
|
30
|
+
PORTFOLIO = "PORTFOLIO",
|
|
31
|
+
VALUATION = "VALUATION",
|
|
32
|
+
PRICE = "PRICE",
|
|
33
|
+
/** JS only: the position client talks to ledger-service. */
|
|
34
|
+
POSITION = "POSITION"
|
|
35
|
+
}
|
|
36
|
+
export interface Endpoint {
|
|
37
|
+
host: string;
|
|
38
|
+
port: number;
|
|
39
|
+
plaintext: boolean;
|
|
40
|
+
}
|
|
41
|
+
export type Env = Record<string, string | undefined>;
|
|
42
|
+
export declare function envPrefix(service: Service): string;
|
|
43
|
+
export declare function standardPort(service: Service): number;
|
|
44
|
+
/** Resolves `service` against `env` (defaults to `process.env`). */
|
|
45
|
+
export declare function resolve(service: Service, env?: Env): Endpoint;
|
|
46
|
+
/** The `host:port` string a gRPC client connects to. */
|
|
47
|
+
export declare function target(endpoint: Endpoint): string;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Finds the address of a FinTekkers service from the environment, the same
|
|
4
|
+
* way as Java `ServiceAddress` and Rust `service_address.rs` (LM-278). Every
|
|
5
|
+
* default client resolves through here, in this order:
|
|
6
|
+
*
|
|
7
|
+
* 1. `BROKER_HOST` (`host[:port]`, port defaults to {@link BROKER_PORT}):
|
|
8
|
+
* all calls go through the broker.
|
|
9
|
+
* 2. Only if that is unset, `<SERVICE>_SERVICE_HOST` with
|
|
10
|
+
* `<SERVICE>_SERVICE_PORT` (or the service's standard port). `_PORT`
|
|
11
|
+
* without `_HOST` is ignored.
|
|
12
|
+
* 3. `API_URL`, with the service's standard port unless it carries one.
|
|
13
|
+
* 4. `localhost` on the service's standard port.
|
|
14
|
+
*
|
|
15
|
+
* An empty value counts as unset. A leading `http://` or `https://` is
|
|
16
|
+
* ignored. Loopback hosts (`localhost`, `127.0.0.1`) are plaintext; any other
|
|
17
|
+
* host uses TLS. A port that is not a number throws an Error naming the
|
|
18
|
+
* variable.
|
|
19
|
+
*
|
|
20
|
+
* The same cases are checked in every language against
|
|
21
|
+
* `test-fixtures/service-address-cases.json`.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.target = exports.resolve = exports.standardPort = exports.envPrefix = exports.Service = exports.PRICE_PORT = exports.VALUATION_PORT = exports.LEDGER_PORT = exports.BROKER_PORT = void 0;
|
|
25
|
+
exports.BROKER_PORT = 8085;
|
|
26
|
+
exports.LEDGER_PORT = 8082;
|
|
27
|
+
exports.VALUATION_PORT = 8080;
|
|
28
|
+
exports.PRICE_PORT = 8083;
|
|
29
|
+
var Service;
|
|
30
|
+
(function (Service) {
|
|
31
|
+
Service["BROKER"] = "BROKER";
|
|
32
|
+
Service["SECURITY"] = "SECURITY";
|
|
33
|
+
Service["TRANSACTION"] = "TRANSACTION";
|
|
34
|
+
Service["PORTFOLIO"] = "PORTFOLIO";
|
|
35
|
+
Service["VALUATION"] = "VALUATION";
|
|
36
|
+
Service["PRICE"] = "PRICE";
|
|
37
|
+
/** JS only: the position client talks to ledger-service. */
|
|
38
|
+
Service["POSITION"] = "POSITION";
|
|
39
|
+
})(Service || (exports.Service = Service = {}));
|
|
40
|
+
/** Prefix of each service's `<SERVICE>_SERVICE_HOST/_PORT` variables, and its standard port. */
|
|
41
|
+
const SERVICE_ENV = {
|
|
42
|
+
[Service.BROKER]: { envPrefix: 'BROKER', standardPort: exports.BROKER_PORT },
|
|
43
|
+
[Service.SECURITY]: { envPrefix: 'LEDGER', standardPort: exports.LEDGER_PORT },
|
|
44
|
+
[Service.TRANSACTION]: { envPrefix: 'LEDGER', standardPort: exports.LEDGER_PORT },
|
|
45
|
+
[Service.PORTFOLIO]: { envPrefix: 'LEDGER', standardPort: exports.LEDGER_PORT },
|
|
46
|
+
[Service.VALUATION]: { envPrefix: 'VALUATION', standardPort: exports.VALUATION_PORT },
|
|
47
|
+
[Service.PRICE]: { envPrefix: 'PRICE', standardPort: exports.PRICE_PORT },
|
|
48
|
+
[Service.POSITION]: { envPrefix: 'LEDGER', standardPort: exports.LEDGER_PORT },
|
|
49
|
+
};
|
|
50
|
+
function envPrefix(service) {
|
|
51
|
+
return SERVICE_ENV[service].envPrefix;
|
|
52
|
+
}
|
|
53
|
+
exports.envPrefix = envPrefix;
|
|
54
|
+
function standardPort(service) {
|
|
55
|
+
return SERVICE_ENV[service].standardPort;
|
|
56
|
+
}
|
|
57
|
+
exports.standardPort = standardPort;
|
|
58
|
+
/** Resolves `service` against `env` (defaults to `process.env`). */
|
|
59
|
+
function resolve(service, env = process.env) {
|
|
60
|
+
const broker = read(env, 'BROKER_HOST');
|
|
61
|
+
if (broker !== undefined) {
|
|
62
|
+
return parse(broker, 'BROKER_HOST', exports.BROKER_PORT);
|
|
63
|
+
}
|
|
64
|
+
const { envPrefix, standardPort } = SERVICE_ENV[service];
|
|
65
|
+
const hostVar = envPrefix + '_SERVICE_HOST';
|
|
66
|
+
const host = read(env, hostVar);
|
|
67
|
+
if (host !== undefined) {
|
|
68
|
+
const portVar = envPrefix + '_SERVICE_PORT';
|
|
69
|
+
const port = read(env, portVar);
|
|
70
|
+
const endpoint = parse(host, hostVar, standardPort);
|
|
71
|
+
return port === undefined
|
|
72
|
+
? endpoint
|
|
73
|
+
: makeEndpoint(endpoint.host, parsePort(port, portVar));
|
|
74
|
+
}
|
|
75
|
+
const apiUrl = read(env, 'API_URL');
|
|
76
|
+
if (apiUrl !== undefined) {
|
|
77
|
+
return parse(apiUrl, 'API_URL', standardPort);
|
|
78
|
+
}
|
|
79
|
+
return makeEndpoint('localhost', standardPort);
|
|
80
|
+
}
|
|
81
|
+
exports.resolve = resolve;
|
|
82
|
+
/** The `host:port` string a gRPC client connects to. */
|
|
83
|
+
function target(endpoint) {
|
|
84
|
+
return `${endpoint.host}:${endpoint.port}`;
|
|
85
|
+
}
|
|
86
|
+
exports.target = target;
|
|
87
|
+
function read(env, name) {
|
|
88
|
+
if (!Object.prototype.hasOwnProperty.call(env, name))
|
|
89
|
+
return undefined;
|
|
90
|
+
const value = env[name];
|
|
91
|
+
if (value === undefined || value === null)
|
|
92
|
+
return undefined;
|
|
93
|
+
const trimmed = value.trim();
|
|
94
|
+
return trimmed === '' ? undefined : trimmed;
|
|
95
|
+
}
|
|
96
|
+
function parse(value, variable, defaultPort) {
|
|
97
|
+
let address = value;
|
|
98
|
+
const scheme = address.indexOf('://');
|
|
99
|
+
if (scheme >= 0)
|
|
100
|
+
address = address.substring(scheme + 3);
|
|
101
|
+
while (address.endsWith('/'))
|
|
102
|
+
address = address.substring(0, address.length - 1);
|
|
103
|
+
let host = address;
|
|
104
|
+
let port = defaultPort;
|
|
105
|
+
const colon = address.lastIndexOf(':');
|
|
106
|
+
if (colon >= 0) {
|
|
107
|
+
host = address.substring(0, colon);
|
|
108
|
+
port = parsePort(address.substring(colon + 1), variable);
|
|
109
|
+
}
|
|
110
|
+
if (host === '') {
|
|
111
|
+
throw new Error(`${variable} has no host: '${value}'`);
|
|
112
|
+
}
|
|
113
|
+
return makeEndpoint(host, port);
|
|
114
|
+
}
|
|
115
|
+
function parsePort(value, variable) {
|
|
116
|
+
const trimmed = value.trim();
|
|
117
|
+
// Java's Integer.parseInt accepts an optional sign; the range check below rejects negatives.
|
|
118
|
+
if (!/^[+-]?\d+$/.test(trimmed))
|
|
119
|
+
throw invalidPort(value, variable);
|
|
120
|
+
const port = Number(trimmed);
|
|
121
|
+
if (port < 1 || port > 65535)
|
|
122
|
+
throw invalidPort(value, variable);
|
|
123
|
+
return port;
|
|
124
|
+
}
|
|
125
|
+
function invalidPort(value, variable) {
|
|
126
|
+
return new Error(`${variable} has an invalid port: '${value}'`);
|
|
127
|
+
}
|
|
128
|
+
function makeEndpoint(host, port) {
|
|
129
|
+
const plaintext = host === 'localhost' || host === '127.0.0.1';
|
|
130
|
+
return { host, port, plaintext };
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=serviceaddress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceaddress.js","sourceRoot":"","sources":["serviceaddress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LM-287: the JS service-address lookup resolves every case in the shared
|
|
4
|
+
* fixture exactly as Java `ServiceAddress` and Rust `service_address.rs` do.
|
|
5
|
+
* No cases are written here; they all come from the fixture.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
24
|
+
if (mod && mod.__esModule) return mod;
|
|
25
|
+
var result = {};
|
|
26
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
27
|
+
__setModuleDefault(result, mod);
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
|
+
const path = __importStar(require("path"));
|
|
33
|
+
const serviceaddress_1 = require("./serviceaddress");
|
|
34
|
+
const fixturePath = path.resolve(__dirname, '../../../../test-fixtures/service-address-cases.json');
|
|
35
|
+
const fixture = JSON.parse(fs.readFileSync(fixturePath, 'utf8'));
|
|
36
|
+
const rows = fixture.cases.flatMap((c) => c.services.map((s) => [c.name, s, c]));
|
|
37
|
+
function serviceNamed(name) {
|
|
38
|
+
if (!Object.prototype.hasOwnProperty.call(serviceaddress_1.Service, name)) {
|
|
39
|
+
throw new Error(`fixture names an unknown service: ${name}`);
|
|
40
|
+
}
|
|
41
|
+
return serviceaddress_1.Service[name];
|
|
42
|
+
}
|
|
43
|
+
describe('service-address-cases.json', () => {
|
|
44
|
+
test('has cases covering every step, so an emptied fixture cannot pass', () => {
|
|
45
|
+
// 30 cases expanding to 55 (case, service) checks.
|
|
46
|
+
expect(fixture.cases.length).toBeGreaterThanOrEqual(30);
|
|
47
|
+
expect(rows.length).toBeGreaterThanOrEqual(55);
|
|
48
|
+
expect(new Set(fixture.cases.map((c) => c.step))).toEqual(new Set(['a', 'b', 'c', 'd']));
|
|
49
|
+
for (const c of fixture.cases) {
|
|
50
|
+
expect(c.services.length).toBeGreaterThan(0);
|
|
51
|
+
expect((c.expected === undefined) !== (c.error === undefined)).toBe(true);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
test('standard_ports match the resolver', () => {
|
|
55
|
+
expect(fixture.standard_ports).toEqual({
|
|
56
|
+
BROKER: serviceaddress_1.BROKER_PORT,
|
|
57
|
+
LEDGER: serviceaddress_1.LEDGER_PORT,
|
|
58
|
+
VALUATION: serviceaddress_1.VALUATION_PORT,
|
|
59
|
+
PRICE: serviceaddress_1.PRICE_PORT,
|
|
60
|
+
});
|
|
61
|
+
for (const s of Object.values(serviceaddress_1.Service)) {
|
|
62
|
+
expect((0, serviceaddress_1.standardPort)(s)).toBe(fixture.standard_ports[(0, serviceaddress_1.envPrefix)(s)]);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
test.each(rows)('%s [%s]', (_name, serviceName, c) => {
|
|
66
|
+
const service = serviceNamed(serviceName);
|
|
67
|
+
if (c.error !== undefined) {
|
|
68
|
+
expect(() => (0, serviceaddress_1.resolve)(service, c.env)).toThrow(c.error);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const endpoint = (0, serviceaddress_1.resolve)(service, c.env);
|
|
72
|
+
expect(endpoint).toEqual(c.expected);
|
|
73
|
+
expect((0, serviceaddress_1.target)(endpoint)).toBe(`${c.expected.host}:${c.expected.port}`);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=serviceaddress.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceaddress.test.js","sourceRoot":"","sources":["serviceaddress.test.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAC7B,qDAU0B;AAgB1B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,sDAAsD,CAAC,CAAC;AACpG,MAAM,OAAO,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAE1E,MAAM,IAAI,GAAyC,OAAO,CAAC,KAAK,CAAC,OAAO,CACtE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAiC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAC5E,CAAC;AAEF,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,wBAAO,EAAE,IAAI,CAAC,EAAE;QACxD,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;KAC9D;IACD,OAAO,wBAAO,CAAC,IAA4B,CAAC,CAAC;AAC/C,CAAC;AAED,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC5E,mDAAmD;QACnD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACzF,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE;YAC7B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAC3E;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC;YACrC,MAAM,EAAE,4BAAW;YACnB,MAAM,EAAE,4BAAW;YACnB,SAAS,EAAE,+BAAc;YACzB,KAAK,EAAE,2BAAU;SAClB,CAAC,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,wBAAO,CAAC,EAAE;YACtC,MAAM,CAAC,IAAA,6BAAY,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAA,0BAAS,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACpE;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE;QACnD,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE;YACzB,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,wBAAO,EAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvD,OAAO;SACR;QACD,MAAM,QAAQ,GAAG,IAAA,wBAAO,EAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,CAAC,IAAA,uBAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAS,CAAC,IAAI,IAAI,CAAC,CAAC,QAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LM-287: the JS service-address lookup resolves every case in the shared
|
|
3
|
+
* fixture exactly as Java `ServiceAddress` and Rust `service_address.rs` do.
|
|
4
|
+
* No cases are written here; they all come from the fixture.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import {
|
|
10
|
+
Service,
|
|
11
|
+
resolve,
|
|
12
|
+
target,
|
|
13
|
+
envPrefix,
|
|
14
|
+
standardPort,
|
|
15
|
+
BROKER_PORT,
|
|
16
|
+
LEDGER_PORT,
|
|
17
|
+
VALUATION_PORT,
|
|
18
|
+
PRICE_PORT,
|
|
19
|
+
} from './serviceaddress';
|
|
20
|
+
|
|
21
|
+
interface FixtureCase {
|
|
22
|
+
name: string;
|
|
23
|
+
step: string;
|
|
24
|
+
env: Record<string, string>;
|
|
25
|
+
services: string[];
|
|
26
|
+
expected?: { host: string; port: number; plaintext: boolean };
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface Fixture {
|
|
31
|
+
standard_ports: Record<string, number>;
|
|
32
|
+
cases: FixtureCase[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const fixturePath = path.resolve(__dirname, '../../../../test-fixtures/service-address-cases.json');
|
|
36
|
+
const fixture: Fixture = JSON.parse(fs.readFileSync(fixturePath, 'utf8'));
|
|
37
|
+
|
|
38
|
+
const rows: Array<[string, string, FixtureCase]> = fixture.cases.flatMap(
|
|
39
|
+
(c) => c.services.map((s): [string, string, FixtureCase] => [c.name, s, c])
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
function serviceNamed(name: string): Service {
|
|
43
|
+
if (!Object.prototype.hasOwnProperty.call(Service, name)) {
|
|
44
|
+
throw new Error(`fixture names an unknown service: ${name}`);
|
|
45
|
+
}
|
|
46
|
+
return Service[name as keyof typeof Service];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe('service-address-cases.json', () => {
|
|
50
|
+
test('has cases covering every step, so an emptied fixture cannot pass', () => {
|
|
51
|
+
// 30 cases expanding to 55 (case, service) checks.
|
|
52
|
+
expect(fixture.cases.length).toBeGreaterThanOrEqual(30);
|
|
53
|
+
expect(rows.length).toBeGreaterThanOrEqual(55);
|
|
54
|
+
expect(new Set(fixture.cases.map((c) => c.step))).toEqual(new Set(['a', 'b', 'c', 'd']));
|
|
55
|
+
for (const c of fixture.cases) {
|
|
56
|
+
expect(c.services.length).toBeGreaterThan(0);
|
|
57
|
+
expect((c.expected === undefined) !== (c.error === undefined)).toBe(true);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('standard_ports match the resolver', () => {
|
|
62
|
+
expect(fixture.standard_ports).toEqual({
|
|
63
|
+
BROKER: BROKER_PORT,
|
|
64
|
+
LEDGER: LEDGER_PORT,
|
|
65
|
+
VALUATION: VALUATION_PORT,
|
|
66
|
+
PRICE: PRICE_PORT,
|
|
67
|
+
});
|
|
68
|
+
for (const s of Object.values(Service)) {
|
|
69
|
+
expect(standardPort(s)).toBe(fixture.standard_ports[envPrefix(s)]);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test.each(rows)('%s [%s]', (_name, serviceName, c) => {
|
|
74
|
+
const service = serviceNamed(serviceName);
|
|
75
|
+
if (c.error !== undefined) {
|
|
76
|
+
expect(() => resolve(service, c.env)).toThrow(c.error);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const endpoint = resolve(service, c.env);
|
|
80
|
+
expect(endpoint).toEqual(c.expected);
|
|
81
|
+
expect(target(endpoint)).toBe(`${c.expected!.host}:${c.expected!.port}`);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the address of a FinTekkers service from the environment, the same
|
|
3
|
+
* way as Java `ServiceAddress` and Rust `service_address.rs` (LM-278). Every
|
|
4
|
+
* default client resolves through here, in this order:
|
|
5
|
+
*
|
|
6
|
+
* 1. `BROKER_HOST` (`host[:port]`, port defaults to {@link BROKER_PORT}):
|
|
7
|
+
* all calls go through the broker.
|
|
8
|
+
* 2. Only if that is unset, `<SERVICE>_SERVICE_HOST` with
|
|
9
|
+
* `<SERVICE>_SERVICE_PORT` (or the service's standard port). `_PORT`
|
|
10
|
+
* without `_HOST` is ignored.
|
|
11
|
+
* 3. `API_URL`, with the service's standard port unless it carries one.
|
|
12
|
+
* 4. `localhost` on the service's standard port.
|
|
13
|
+
*
|
|
14
|
+
* An empty value counts as unset. A leading `http://` or `https://` is
|
|
15
|
+
* ignored. Loopback hosts (`localhost`, `127.0.0.1`) are plaintext; any other
|
|
16
|
+
* host uses TLS. A port that is not a number throws an Error naming the
|
|
17
|
+
* variable.
|
|
18
|
+
*
|
|
19
|
+
* The same cases are checked in every language against
|
|
20
|
+
* `test-fixtures/service-address-cases.json`.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const BROKER_PORT = 8085;
|
|
24
|
+
export const LEDGER_PORT = 8082;
|
|
25
|
+
export const VALUATION_PORT = 8080;
|
|
26
|
+
export const PRICE_PORT = 8083;
|
|
27
|
+
|
|
28
|
+
export enum Service {
|
|
29
|
+
BROKER = 'BROKER',
|
|
30
|
+
SECURITY = 'SECURITY',
|
|
31
|
+
TRANSACTION = 'TRANSACTION',
|
|
32
|
+
PORTFOLIO = 'PORTFOLIO',
|
|
33
|
+
VALUATION = 'VALUATION',
|
|
34
|
+
PRICE = 'PRICE',
|
|
35
|
+
/** JS only: the position client talks to ledger-service. */
|
|
36
|
+
POSITION = 'POSITION',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Prefix of each service's `<SERVICE>_SERVICE_HOST/_PORT` variables, and its standard port. */
|
|
40
|
+
const SERVICE_ENV: Record<Service, { envPrefix: string; standardPort: number }> = {
|
|
41
|
+
[Service.BROKER]: { envPrefix: 'BROKER', standardPort: BROKER_PORT },
|
|
42
|
+
[Service.SECURITY]: { envPrefix: 'LEDGER', standardPort: LEDGER_PORT },
|
|
43
|
+
[Service.TRANSACTION]: { envPrefix: 'LEDGER', standardPort: LEDGER_PORT },
|
|
44
|
+
[Service.PORTFOLIO]: { envPrefix: 'LEDGER', standardPort: LEDGER_PORT },
|
|
45
|
+
[Service.VALUATION]: { envPrefix: 'VALUATION', standardPort: VALUATION_PORT },
|
|
46
|
+
[Service.PRICE]: { envPrefix: 'PRICE', standardPort: PRICE_PORT },
|
|
47
|
+
[Service.POSITION]: { envPrefix: 'LEDGER', standardPort: LEDGER_PORT },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export interface Endpoint {
|
|
51
|
+
host: string;
|
|
52
|
+
port: number;
|
|
53
|
+
plaintext: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type Env = Record<string, string | undefined>;
|
|
57
|
+
|
|
58
|
+
export function envPrefix(service: Service): string {
|
|
59
|
+
return SERVICE_ENV[service].envPrefix;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function standardPort(service: Service): number {
|
|
63
|
+
return SERVICE_ENV[service].standardPort;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Resolves `service` against `env` (defaults to `process.env`). */
|
|
67
|
+
export function resolve(service: Service, env: Env = process.env): Endpoint {
|
|
68
|
+
const broker = read(env, 'BROKER_HOST');
|
|
69
|
+
if (broker !== undefined) {
|
|
70
|
+
return parse(broker, 'BROKER_HOST', BROKER_PORT);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const { envPrefix, standardPort } = SERVICE_ENV[service];
|
|
74
|
+
const hostVar = envPrefix + '_SERVICE_HOST';
|
|
75
|
+
const host = read(env, hostVar);
|
|
76
|
+
if (host !== undefined) {
|
|
77
|
+
const portVar = envPrefix + '_SERVICE_PORT';
|
|
78
|
+
const port = read(env, portVar);
|
|
79
|
+
const endpoint = parse(host, hostVar, standardPort);
|
|
80
|
+
return port === undefined
|
|
81
|
+
? endpoint
|
|
82
|
+
: makeEndpoint(endpoint.host, parsePort(port, portVar));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const apiUrl = read(env, 'API_URL');
|
|
86
|
+
if (apiUrl !== undefined) {
|
|
87
|
+
return parse(apiUrl, 'API_URL', standardPort);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return makeEndpoint('localhost', standardPort);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The `host:port` string a gRPC client connects to. */
|
|
94
|
+
export function target(endpoint: Endpoint): string {
|
|
95
|
+
return `${endpoint.host}:${endpoint.port}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function read(env: Env, name: string): string | undefined {
|
|
99
|
+
if (!Object.prototype.hasOwnProperty.call(env, name)) return undefined;
|
|
100
|
+
const value = env[name];
|
|
101
|
+
if (value === undefined || value === null) return undefined;
|
|
102
|
+
const trimmed = value.trim();
|
|
103
|
+
return trimmed === '' ? undefined : trimmed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function parse(value: string, variable: string, defaultPort: number): Endpoint {
|
|
107
|
+
let address = value;
|
|
108
|
+
const scheme = address.indexOf('://');
|
|
109
|
+
if (scheme >= 0) address = address.substring(scheme + 3);
|
|
110
|
+
while (address.endsWith('/')) address = address.substring(0, address.length - 1);
|
|
111
|
+
|
|
112
|
+
let host = address;
|
|
113
|
+
let port = defaultPort;
|
|
114
|
+
const colon = address.lastIndexOf(':');
|
|
115
|
+
if (colon >= 0) {
|
|
116
|
+
host = address.substring(0, colon);
|
|
117
|
+
port = parsePort(address.substring(colon + 1), variable);
|
|
118
|
+
}
|
|
119
|
+
if (host === '') {
|
|
120
|
+
throw new Error(`${variable} has no host: '${value}'`);
|
|
121
|
+
}
|
|
122
|
+
return makeEndpoint(host, port);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function parsePort(value: string, variable: string): number {
|
|
126
|
+
const trimmed = value.trim();
|
|
127
|
+
// Java's Integer.parseInt accepts an optional sign; the range check below rejects negatives.
|
|
128
|
+
if (!/^[+-]?\d+$/.test(trimmed)) throw invalidPort(value, variable);
|
|
129
|
+
const port = Number(trimmed);
|
|
130
|
+
if (port < 1 || port > 65535) throw invalidPort(value, variable);
|
|
131
|
+
return port;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function invalidPort(value: string, variable: string): Error {
|
|
135
|
+
return new Error(`${variable} has an invalid port: '${value}'`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function makeEndpoint(host: string, port: number): Endpoint {
|
|
139
|
+
const plaintext = host === 'localhost' || host === '127.0.0.1';
|
|
140
|
+
return { host, port, plaintext };
|
|
141
|
+
}
|