@interopio/bridge 0.0.1-alpha → 0.0.3-beta

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 (84) hide show
  1. package/bin/bridge.js +1 -1
  2. package/dist/main.js +2139 -0
  3. package/dist/main.js.map +7 -0
  4. package/package.json +9 -6
  5. package/gen/instance/GeneratedBuildInfo.ts +0 -4
  6. package/src/cluster/Address.ts +0 -57
  7. package/src/cluster/Cluster.ts +0 -13
  8. package/src/cluster/Endpoint.ts +0 -5
  9. package/src/cluster/Member.ts +0 -9
  10. package/src/cluster/MembershipListener.ts +0 -6
  11. package/src/config/Config.ts +0 -100
  12. package/src/config/DiscoveryConfig.ts +0 -21
  13. package/src/config/Duration.ts +0 -168
  14. package/src/config/KubernetesConfig.ts +0 -7
  15. package/src/config/NamedDiscoveryConfig.ts +0 -17
  16. package/src/config/Properties.ts +0 -49
  17. package/src/config/index.ts +0 -1
  18. package/src/discovery/SimpleDiscoveryNode.ts +0 -14
  19. package/src/discovery/index.ts +0 -207
  20. package/src/discovery/multicast/MulticastDiscoveryStrategy.ts +0 -141
  21. package/src/discovery/multicast/MulticastDiscoveryStrategyFactory.ts +0 -30
  22. package/src/discovery/multicast/MulticastProperties.ts +0 -4
  23. package/src/discovery/settings.ts +0 -37
  24. package/src/error/RequestFailure.ts +0 -48
  25. package/src/gossip/ApplicationState.ts +0 -48
  26. package/src/gossip/EndpointState.ts +0 -141
  27. package/src/gossip/FailureDetector.ts +0 -235
  28. package/src/gossip/Gossiper.ts +0 -1133
  29. package/src/gossip/HeartbeatState.ts +0 -66
  30. package/src/gossip/Messenger.ts +0 -130
  31. package/src/gossip/VersionedValue.ts +0 -59
  32. package/src/index.ts +0 -3
  33. package/src/instance/AddressPicker.ts +0 -245
  34. package/src/instance/BridgeNode.ts +0 -141
  35. package/src/instance/ClusterTopologyIntentTracker.ts +0 -4
  36. package/src/io/VersionedSerializer.ts +0 -230
  37. package/src/io/util.ts +0 -117
  38. package/src/kubernetes/DnsEndpointResolver.ts +0 -70
  39. package/src/kubernetes/KubernetesApiEndpointResolver.ts +0 -111
  40. package/src/kubernetes/KubernetesApiProvider.ts +0 -75
  41. package/src/kubernetes/KubernetesClient.ts +0 -264
  42. package/src/kubernetes/KubernetesConfig.ts +0 -130
  43. package/src/kubernetes/KubernetesDiscoveryStrategy.ts +0 -30
  44. package/src/kubernetes/KubernetesDiscoveryStrategyFactory.ts +0 -71
  45. package/src/kubernetes/KubernetesEndpointResolver.ts +0 -43
  46. package/src/kubernetes/KubernetesProperties.ts +0 -22
  47. package/src/license/BridgeLicenseValidator.ts +0 -19
  48. package/src/license/LicenseValidator.ts +0 -114
  49. package/src/license/types.ts +0 -40
  50. package/src/logging.ts +0 -22
  51. package/src/main.mts +0 -53
  52. package/src/net/Action.ts +0 -143
  53. package/src/net/AddressSerializer.ts +0 -44
  54. package/src/net/ByteBufferAllocator.ts +0 -27
  55. package/src/net/FrameDecoder.ts +0 -314
  56. package/src/net/FrameEncoder.ts +0 -138
  57. package/src/net/HandshakeProtocol.ts +0 -143
  58. package/src/net/InboundConnection.ts +0 -108
  59. package/src/net/InboundConnectionInitiator.ts +0 -150
  60. package/src/net/InboundMessageHandler.ts +0 -377
  61. package/src/net/InboundSink.ts +0 -38
  62. package/src/net/Message.ts +0 -428
  63. package/src/net/OutboundConnection.ts +0 -1141
  64. package/src/net/OutboundConnectionInitiator.ts +0 -76
  65. package/src/net/RequestCallbacks.ts +0 -148
  66. package/src/net/ResponseHandler.ts +0 -30
  67. package/src/net/ShareableBytes.ts +0 -125
  68. package/src/net/internal/AsyncResourceExecutor.ts +0 -464
  69. package/src/net/internal/AsyncSocketPromise.ts +0 -37
  70. package/src/net/internal/channel/ChannelHandlerAdapter.ts +0 -99
  71. package/src/net/internal/channel/types.ts +0 -188
  72. package/src/utils/bigint.ts +0 -23
  73. package/src/utils/buffer.ts +0 -434
  74. package/src/utils/clock.ts +0 -148
  75. package/src/utils/collections.ts +0 -283
  76. package/src/utils/crc.ts +0 -39
  77. package/src/utils/internal/IpAddressUtil.ts +0 -161
  78. package/src/utils/memory/BufferPools.ts +0 -40
  79. package/src/utils/network.ts +0 -130
  80. package/src/utils/promise.ts +0 -38
  81. package/src/utils/uuid.ts +0 -5
  82. package/src/utils/vint.ts +0 -238
  83. package/src/version/MemberVersion.ts +0 -42
  84. package/src/version/Version.ts +0 -12
@@ -1,114 +0,0 @@
1
- import getLogger, {type Logger} from "../logging.ts";
2
- import {
3
- type LicensePayload,
4
- type LicenseEvaluationResult,
5
- type LicenseValidatorOptions,
6
- licenseValidationResults, type LicenseValidationOptions
7
- } from "./types.ts";
8
- import {KJUR} from 'jsrsasign';
9
-
10
- export class LicenseError extends Error {
11
- public readonly licensePayload: LicensePayload | string;
12
-
13
- constructor(message: string, licensePayload: string | LicensePayload) {
14
- super(message);
15
- this.licensePayload = licensePayload;
16
- }
17
- }
18
-
19
- export class LicenseEvaluator {
20
- private readonly tokenResultMap = {
21
- 'trial-false': licenseValidationResults.TRIAL_LICENSE_VALID,
22
- 'trial-true': licenseValidationResults.TRIAL_LICENSE_EXPIRED,
23
- 'paid-false': licenseValidationResults.PAID_LICENSE_VALID,
24
- 'paid-true': licenseValidationResults.PAID_LICENSE_EXPIRED,
25
- };
26
-
27
- private readonly validationKey: string;
28
-
29
- constructor(validationKey: string) {
30
- if (!validationKey || typeof validationKey !== 'string') {
31
- throw new Error(`Validation key must be a non-empty string`);
32
- }
33
- this.validationKey = validationKey;
34
- }
35
-
36
- private decrypt(token: string): object {
37
- if (KJUR.jws.JWS.verifyJWT(token, this.validationKey, {alg: ['RS256']})) {
38
- return KJUR.jws.JWS.parse(token).payloadObj;
39
- } else {
40
- throw new LicenseError('invalid jwt token', token);
41
- }
42
- }
43
-
44
- private validateBasicTokenData(token: string): LicensePayload {
45
- const decoded = this.decrypt(token) as LicensePayload;
46
- if (['paid', 'trial'].indexOf(decoded.type) === -1) {
47
- throw new LicenseError('Invalid license type', token);
48
- }
49
- return decoded;
50
- }
51
-
52
- getLicenseStatus(token: string, now: Date = new Date()): LicenseEvaluationResult {
53
- try {
54
- const license = this.validateBasicTokenData(token);
55
- const isExpired = license.expiration < now.getTime();
56
- const licenseValidationResult = this.tokenResultMap[`${license.type}-${isExpired}`];
57
- return {
58
- ...licenseValidationResult,
59
- license
60
- };
61
- } catch (e) {
62
- return {
63
- ...licenseValidationResults.NO_LICENSE,
64
- error: e.message,
65
- };
66
- }
67
-
68
- }
69
- }
70
-
71
- export class LicenseValidator {
72
- private readonly licenseHelper: LicenseEvaluator;
73
- private readonly logger: Logger;
74
-
75
- constructor({validationKey, logger}: LicenseValidatorOptions) {
76
- this.licenseHelper = new LicenseEvaluator(validationKey);
77
- this.logger = logger ?? getLogger("LicenseValidator"); // Default to console if no logger provided
78
- }
79
-
80
- public validate(licenseKeyString: string, options?: LicenseValidationOptions): void {
81
- if (typeof licenseKeyString !== 'string') {
82
- throw new LicenseError('Invalid license key format', licenseKeyString);
83
- }
84
-
85
- const licenseStatus = this.licenseHelper.getLicenseStatus(licenseKeyString);
86
- this.printLicenseMessage(licenseStatus, options?.logSuccessMessages ?? true);
87
- if (licenseStatus.fatal) {
88
- throw new LicenseError('License validation failed', licenseStatus.license);
89
- }
90
- }
91
-
92
- private printLicenseMessage(licenseStatus: LicenseEvaluationResult, logSuccessMessages: boolean): void {
93
- if (!licenseStatus || licenseStatus.licenseType === 'none') {
94
- this.logger.error('This license is invalid. Please contact us at sales@interop.io to get a valid license');
95
- return;
96
- }
97
-
98
- const message = [
99
- licenseStatus.licenseType === 'paid' ? `This is a paid license that was issued for client ` : `This is a trial license that was issued for `,
100
- licenseStatus.license.organization.displayName,
101
- licenseStatus.expired ? `, but it has expired at ` : ` and is valid until `,
102
- new Date(licenseStatus.license.expiration).toString(),
103
- '.'
104
- ].join('');
105
-
106
- if (licenseStatus.fatal) {
107
- this.logger.error(message);
108
- } else if (licenseStatus.expired) {
109
- this.logger.warn(message);
110
- } else if(logSuccessMessages) {
111
- this.logger.info(message);
112
- }
113
- }
114
- }
@@ -1,40 +0,0 @@
1
- import type {Logger} from "../logging.ts";
2
-
3
- export type LicenseValidatorOptions = {
4
- validationKey: string;
5
- logger?: Logger
6
- }
7
-
8
- export type LicenseValidationOptions = {
9
- logSuccessMessages?: boolean
10
- };
11
-
12
- export type LicensePayload = {
13
- "type": "paid" | "trial";
14
- "expiration": number // in milliseconds
15
- "email": string,
16
- "issuedBy": string;
17
- "iat": number; // in seconds
18
- "licensee": string;
19
- "organization": {
20
- "displayName": string,
21
- "identifier": string
22
- }
23
- }
24
-
25
- export type LicenseEvaluationResult = {
26
- licenseType: 'paid' | 'trial' | 'none';
27
- expired: boolean;
28
- fatal: boolean;
29
- license?: LicensePayload;
30
- error?: string;
31
- }
32
-
33
-
34
- export const licenseValidationResults = {
35
- TRIAL_LICENSE_EXPIRED: {licenseType: 'trial', expired: true, fatal: true} as LicenseEvaluationResult,
36
- TRIAL_LICENSE_VALID: {licenseType: 'trial', expired: false, fatal: false} as LicenseEvaluationResult,
37
- PAID_LICENSE_EXPIRED: {licenseType: 'paid', expired: true, fatal: false} as LicenseEvaluationResult,
38
- PAID_LICENSE_VALID: {licenseType: 'paid', expired: false, fatal: false} as LicenseEvaluationResult,
39
- NO_LICENSE: {licenseType: 'none', expired: false, fatal: true} as LicenseEvaluationResult,
40
- };
package/src/logging.ts DELETED
@@ -1,22 +0,0 @@
1
- import {IOGateway} from '@interopio/gateway';
2
-
3
- export type Logger = ReturnType<typeof IOGateway.Logging.getLogger>;
4
- IOGateway.Logging.getLogger(`gateway.server.app`); // ensure the logger is created
5
- IOGateway.Logging.getLogger(`gateway.bridge`); // ensure the logger is created
6
- IOGateway.Logging.getLogger(`gateway.bridge.gossiper`); // ensure the logger is created
7
- IOGateway.Logging.getLogger(`gateway.bridge.net.callbacks`); // ensure the logger is created
8
- IOGateway.Logging.configure({
9
- level: {
10
- "gateway": 'info',
11
- "gateway.server": 'trace',
12
- "gateway.server.app": 'info',
13
- "gateway.bridge": 'trace',
14
- "gateway.bridge.gossiper": 'info',
15
- // "gateway.bridge.net.callbacks": 'debug'
16
- "gateway.bridge.net.internal.channel": 'debug'
17
- }
18
- });
19
-
20
- export default function getLogger(name: string): Logger {
21
- return IOGateway.Logging.getLogger(`gateway.bridge.${name}`);
22
- }
package/src/main.mts DELETED
@@ -1,53 +0,0 @@
1
- import {BridgeNode} from './instance/BridgeNode.ts';
2
- import {Config} from './config/Config.ts';
3
- import {BOOLEAN, NUMBER, type PropertyType, type PropertyTypeConverter, STRING} from './config/Properties.ts';
4
-
5
- import info from '@interopio/bridge/package.json' with {type: 'json'};
6
-
7
- let hadFatalError = false;
8
- const reportedErrors = new Set();
9
- function onFatalError(error) {
10
-
11
- process.exitCode = 2;
12
- hadFatalError = true;
13
-
14
- const errorMessage = `io.Bridge: ${info.version}`
15
-
16
- if (!reportedErrors.has(errorMessage)) {
17
- console.error(error);
18
- reportedErrors.add(errorMessage);
19
- }
20
- }
21
-
22
- function loadConfig<T extends PropertyType=string>(name: string, converter: PropertyTypeConverter<T>): T | undefined {
23
- const cmdArg = process.argv.find(arg => {return arg.startsWith(`--${name}=`);})?.split('=')[1];
24
- if (cmdArg) {
25
- return converter.convert(cmdArg);
26
- }
27
- const envKey = `IO_BRIDGE_${name.toUpperCase().replace('-', '_').replace('.', '_')}`;
28
- const envVar = process.env[envKey];
29
- if (envVar) {
30
- return converter.convert(envVar);
31
- }
32
- }
33
-
34
- try {
35
- process.on('uncaughtException', onFatalError);
36
- process.on('unhandledRejection', onFatalError);
37
-
38
- await import('dotenv/config');
39
- const config = new Config();
40
- config.license ??= loadConfig('license-key', STRING);
41
- config.server.port ??= loadConfig('server.port', NUMBER) ?? 8383;
42
- config.server.host ??= loadConfig('server.host', STRING);
43
- config.server.mesh.ping ??= loadConfig('mesh.ping-interval', NUMBER);
44
- config.server.gateway.enabled ??= loadConfig('gateway.enabled', BOOLEAN);
45
- config.server.gateway.contexts.lifetime ??= loadConfig('gateway.contexts.lifetime', STRING) as 'retained' | 'ref-counted' | 'ownership';
46
- const bridge = new BridgeNode(config);
47
-
48
- await bridge.start();
49
-
50
- }
51
- catch (error) {
52
- onFatalError(error);
53
- }
package/src/net/Action.ts DELETED
@@ -1,143 +0,0 @@
1
- import {type Message, type MessageFactory} from './Message.ts';
2
- import type {DataInput, DataOutput, VersionedSerializer} from '../io/VersionedSerializer.ts';
3
- import {convert, type Unit} from '../config/Duration.ts';
4
- import {
5
- type Gossiper,
6
- type GossipDigestSyn,
7
- type GossipDigestAck,
8
- type GossipDigestAck2,
9
- gossipDigestSynHandler,
10
- gossipDigestAckHandler,
11
- gossipDigestAck2Handler,
12
- echoHandler,
13
- GossipDigestSynSerializer,
14
- GossipDigestAckSerializer,
15
- GossipDigestAck2Serializer
16
- } from '../gossip/Gossiper.ts';
17
- import {type RequestFailureReason, RequestFailureReasonSerializer} from '../error/RequestFailure.ts';
18
- import type {MessageDelivery} from '../gossip/Messenger.ts';
19
- import {responseHandler} from './ResponseHandler.ts';
20
- import {maxn} from '../utils/bigint.ts';
21
-
22
- const timeouts: {[keys: string]: (unit: Unit) => bigint} = {
23
- rpcTimeout: (unit: Unit) => convert(unit, 10, 'seconds'),
24
- writeTimeout: (unit: Unit) => convert(unit, 2, 'seconds'),
25
- longTimeout: (unit: Unit) => maxn(timeouts.rpcTimeout(unit), convert(unit, 5, 'minutes')),
26
- noTimeout: (unit: Unit) => { throw new Error(''); }
27
- }
28
-
29
- export interface VerbHandler<T> {
30
- doVerb(message: Message<T>) : void
31
- }
32
-
33
- export type VerbHandlerContext = {
34
- messageFactory: () => MessageFactory;
35
- messaging: () => MessageDelivery
36
- gossiper: () => Gossiper
37
- }
38
-
39
- export interface Verb<T> {
40
- readonly id: number
41
- readonly expirationNs: () => bigint
42
- readonly serializer: VersionedSerializer<T>
43
- handler(context: VerbHandlerContext): VerbHandler<T>
44
- expiresAt(createdAt: bigint): bigint
45
-
46
- responseVerb?: Verb<unknown>
47
- }
48
-
49
-
50
- class NetVerb<T> implements Verb<T> {
51
- readonly id: number;
52
- readonly expiration: (unit: Unit) => bigint;
53
- private readonly _serializer: () => VersionedSerializer<T>;
54
- private readonly _handler: (context: VerbHandlerContext) => VerbHandler<T>;
55
- private readonly _responseVerb?: () => Verb<unknown>;
56
-
57
- constructor(id: number,
58
- expiration: (unit: Unit) => bigint,
59
- serializer: () => VersionedSerializer<T>,
60
- handler: (context: VerbHandlerContext) => VerbHandler<T>,
61
- responseVerb?: () => Verb<unknown>) {
62
- this.id = id;
63
- this.expiration = expiration;
64
- this._serializer = serializer;
65
- this._handler = handler;
66
- this._responseVerb = responseVerb;
67
- }
68
-
69
- get serializer(): VersionedSerializer<T> {
70
- return this._serializer();
71
- }
72
-
73
- handler(context: VerbHandlerContext): VerbHandler<T> {
74
- return this._handler(context);
75
- }
76
-
77
- expiresAt(nowNs: bigint): bigint {
78
- return nowNs + this.expiration('nanoseconds');
79
- }
80
-
81
- expirationNs(): bigint {
82
- return this.expiration('nanoseconds');
83
- }
84
-
85
- get responseVerb(): Verb<unknown> | undefined {
86
- return this._responseVerb ? this._responseVerb() : undefined;
87
- }
88
-
89
- /* testing */ unsafeSetHandler(handler: (context: VerbHandlerContext) => VerbHandler<T>) {
90
- const original = this._handler;
91
- (this as any)._handler = handler;
92
- return original;
93
- }
94
- }
95
-
96
- export class NoPayload {
97
- static readonly instance = new NoPayload();
98
- toString() {
99
- return '<NoPayload>';
100
- }
101
- }
102
- export const NoPayloadSerializer: VersionedSerializer<NoPayload> = new (class implements VersionedSerializer<NoPayload> {
103
- serialize(value: NoPayload, output: DataOutput, version?: number) {
104
- if (value !== NoPayload.instance) {
105
- throw new Error('NoPayload can only be serialized as NoPayload.instance');
106
- }
107
- }
108
-
109
- deserialize(input: DataInput, version?: number): NoPayload {
110
- return NoPayload.instance;
111
- }
112
-
113
- serializedSize(value: NoPayload, version?: number): number {
114
- return 0;
115
- }
116
- });
117
-
118
- export const Verbs = {
119
- GOSSIP_DIGEST_SYN: new NetVerb<GossipDigestSyn>(14, timeouts.longTimeout, () => GossipDigestSynSerializer, gossipDigestSynHandler),
120
- GOSSIP_DIGEST_ACK: new NetVerb<GossipDigestAck>(15, timeouts.longTimeout, () => GossipDigestAckSerializer, gossipDigestAckHandler),
121
- GOSSIP_DIGEST_ACK2: new NetVerb<GossipDigestAck2>(16, timeouts.longTimeout, () => GossipDigestAck2Serializer, gossipDigestAck2Handler),
122
- // GOSSIP_SHUTDOWN: new NetVerb<GossipShutdown>(29, timeouts.longTimeout, () => GossipShutdownSerializer, gossipShutdownHandler),
123
-
124
- ECHO_RSP: new NetVerb<NoPayload>(91, timeouts.rpcTimeout, () => NoPayloadSerializer, responseHandler),
125
- ECHO_REQ: new NetVerb<NoPayload>(31, timeouts.rpcTimeout, () => NoPayloadSerializer, echoHandler, () => Verbs.ECHO_RSP),
126
-
127
- // generic failure
128
- FAILURE_RESPONSE: new NetVerb<RequestFailureReason>(99, timeouts.noTimeout, () => RequestFailureReasonSerializer, responseHandler),
129
-
130
- // dummy verb for testing
131
- _TEST1: new NetVerb<NoPayload>(10, timeouts.writeTimeout, () => NoPayloadSerializer, () => undefined)
132
- };
133
-
134
- export type MessageType = keyof typeof Verbs;
135
-
136
- export function fromId(id: number): MessageType {
137
- for (const [key, value] of Object.entries<Verb<unknown>>(Verbs)) {
138
- if (value.id === id) {
139
- return key as MessageType;
140
- }
141
- }
142
- throw new Error(`Unknown verb id: ${id}`);
143
- }
@@ -1,44 +0,0 @@
1
- import type {DataInput, DataOutput, VersionedSerializer} from '../io/VersionedSerializer.ts';
2
- import {type Address, fromIpAddress} from '../cluster/Address.ts';
3
- import {getByAddress} from '../utils/network.ts';
4
-
5
- class AddressSerializer implements VersionedSerializer<Address> {
6
- readonly MAX_SIZE = 1 + 16 + 2; // 1 byte for length, 16 bytes for address, 2 bytes for port
7
- serialize(value: Address, output: DataOutput, version?: number) {
8
- this.serializeAddressAndPort(value.address.addressBytes, value.port, output, version);
9
- }
10
- deserialize(input: DataInput, version?: number): Address {
11
- const size = input.readInt8() & 0xFF;
12
- switch (size) {
13
- case 4:
14
- case 16:
15
- throw new Error(`unexpected address size: ${size}`);
16
- case 6:
17
- case 18: {
18
- const address = new Uint8Array(size - 2);
19
- input.readUint8Array(address);
20
- const port = input.readInt16() & 0xFFFF;
21
-
22
- const ipAddress = getByAddress(undefined, address);
23
- return fromIpAddress(ipAddress, port);
24
- }
25
- default:
26
- throw new Error(`unexpected address size: ${size}`);
27
- }
28
- }
29
-
30
- private serializeAddressAndPort(address: Uint8Array, port: number, output: DataOutput, version?: number) {
31
- output.writeUint8(address.length + 2);
32
- output.writeUint8Array(address);
33
- output.writeUint16(port);
34
- }
35
-
36
- serializedSize(value: Address, version?: number): number {
37
- if (value.type === 4) {
38
- return 1 + 4 + 2;
39
- }
40
- return 1 + 16 + 2;
41
- }
42
- }
43
-
44
- export const addressSerializer = new AddressSerializer();
@@ -1,27 +0,0 @@
1
- import type {ByteBuffer} from '../utils/buffer.ts';
2
- import {forNetworking} from '../utils/memory/BufferPools.ts';
3
-
4
- const bufferPool= forNetworking();
5
-
6
- abstract class ByteBufferAllocator {
7
-
8
- getAtLeast(size: number): ByteBuffer {
9
- return bufferPool.getAtLeast(size);
10
- }
11
-
12
- put(buffer: ByteBuffer) {
13
- return bufferPool.put(buffer);
14
- }
15
- }
16
-
17
- export type {ByteBufferAllocator};
18
-
19
- class GlobalByteBufferAllocator extends ByteBufferAllocator {
20
- public static readonly instance= new GlobalByteBufferAllocator();
21
-
22
- private constructor() {
23
- super();
24
- }
25
- }
26
-
27
- export const globalByteBufferAllocator: ByteBufferAllocator = GlobalByteBufferAllocator.instance;