@mytmpvpn/mytmpvpn-common 13.0.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/models/vpn.js
CHANGED
|
@@ -220,7 +220,7 @@ function vpnIdToWgFileName(vpn) {
|
|
|
220
220
|
const result = vpn.createdAt.toISOString() // This will create YYYY-MM-DDThh:mm:ss....
|
|
221
221
|
.replace(/[^\d]/g, '') // Remove meanless characters: YYYYMMDDhhmmss
|
|
222
222
|
.substring(4, 14); // Use only MMDDhhmmss
|
|
223
|
-
return result
|
|
223
|
+
return `${result}.conf`;
|
|
224
224
|
}
|
|
225
225
|
exports.vpnIdToWgFileName = vpnIdToWgFileName;
|
|
226
226
|
function vpnToClient(vpn) {
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { VpnState } from './vpn';
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket Message Protocol Types
|
|
4
|
+
*
|
|
5
|
+
* This module defines the complete message protocol for WebSocket communication
|
|
6
|
+
* between clients and the backend for real-time VPN state notifications.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Base interface for all client-to-server messages
|
|
10
|
+
*/
|
|
11
|
+
export interface BaseClientMessage {
|
|
12
|
+
action: string;
|
|
13
|
+
requestId: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Subscribe to VPN state change notifications
|
|
17
|
+
* - vpnId: specific VPN ID to subscribe to, or "all" for all user VPNs
|
|
18
|
+
*/
|
|
19
|
+
export interface SubscribeMessage extends BaseClientMessage {
|
|
20
|
+
action: 'subscribe';
|
|
21
|
+
vpnId: string | 'all';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Unsubscribe from VPN state change notifications
|
|
25
|
+
*/
|
|
26
|
+
export interface UnsubscribeMessage extends BaseClientMessage {
|
|
27
|
+
action: 'unsubscribe';
|
|
28
|
+
vpnId: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ping message to keep connection alive
|
|
32
|
+
*/
|
|
33
|
+
export interface PingMessage extends BaseClientMessage {
|
|
34
|
+
action: 'ping';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Union type of all possible client messages
|
|
38
|
+
*/
|
|
39
|
+
export type ClientMessage = SubscribeMessage | UnsubscribeMessage | PingMessage;
|
|
40
|
+
/**
|
|
41
|
+
* Base interface for all server-to-client messages
|
|
42
|
+
*/
|
|
43
|
+
export interface BaseServerMessage {
|
|
44
|
+
type: string;
|
|
45
|
+
timestamp: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* VPN state change notification sent to subscribed clients
|
|
49
|
+
*/
|
|
50
|
+
export interface StateChangeNotification extends BaseServerMessage {
|
|
51
|
+
type: 'state_change';
|
|
52
|
+
vpnId: string;
|
|
53
|
+
previousState: VpnState;
|
|
54
|
+
newState: VpnState;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Acknowledgment message for successful operations
|
|
58
|
+
*/
|
|
59
|
+
export interface AcknowledgmentMessage extends BaseServerMessage {
|
|
60
|
+
type: 'ack';
|
|
61
|
+
requestId: string;
|
|
62
|
+
action: string;
|
|
63
|
+
success: boolean;
|
|
64
|
+
message?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Error message for failed operations
|
|
68
|
+
*/
|
|
69
|
+
export interface ErrorMessage extends BaseServerMessage {
|
|
70
|
+
type: 'error';
|
|
71
|
+
code: WebSocketErrorCode;
|
|
72
|
+
message: string;
|
|
73
|
+
requestId?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pong response to ping message
|
|
77
|
+
*/
|
|
78
|
+
export interface PongMessage extends BaseServerMessage {
|
|
79
|
+
type: 'pong';
|
|
80
|
+
requestId: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Union type of all possible server messages
|
|
84
|
+
*/
|
|
85
|
+
export type ServerMessage = StateChangeNotification | AcknowledgmentMessage | ErrorMessage | PongMessage;
|
|
86
|
+
/**
|
|
87
|
+
* Standard error codes for WebSocket operations
|
|
88
|
+
*/
|
|
89
|
+
export declare enum WebSocketErrorCode {
|
|
90
|
+
AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
|
|
91
|
+
TOKEN_EXPIRED = "TOKEN_EXPIRED",
|
|
92
|
+
TOKEN_INVALID = "TOKEN_INVALID",
|
|
93
|
+
TOKEN_MISSING = "TOKEN_MISSING",
|
|
94
|
+
PERMISSION_DENIED = "PERMISSION_DENIED",
|
|
95
|
+
VPN_NOT_OWNED = "VPN_NOT_OWNED",
|
|
96
|
+
INVALID_MESSAGE_FORMAT = "INVALID_MESSAGE_FORMAT",
|
|
97
|
+
INVALID_VPN_ID = "INVALID_VPN_ID",
|
|
98
|
+
MISSING_REQUIRED_FIELD = "MISSING_REQUIRED_FIELD",
|
|
99
|
+
UNKNOWN_ACTION = "UNKNOWN_ACTION",
|
|
100
|
+
VPN_NOT_FOUND = "VPN_NOT_FOUND",
|
|
101
|
+
SUBSCRIPTION_NOT_FOUND = "SUBSCRIPTION_NOT_FOUND",
|
|
102
|
+
RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED",
|
|
103
|
+
TOO_MANY_MALFORMED_MESSAGES = "TOO_MANY_MALFORMED_MESSAGES",
|
|
104
|
+
CONNECTION_FAILED = "CONNECTION_FAILED",
|
|
105
|
+
CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT",
|
|
106
|
+
INTERNAL_ERROR = "INTERNAL_ERROR",
|
|
107
|
+
NOTIFICATION_DELIVERY_FAILED = "NOTIFICATION_DELIVERY_FAILED"
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* WebSocket connection record stored in DynamoDB
|
|
111
|
+
*/
|
|
112
|
+
export interface ConnectionRecord {
|
|
113
|
+
connectionId: string;
|
|
114
|
+
userId: string;
|
|
115
|
+
connectedAt: number;
|
|
116
|
+
lastPingAt?: number;
|
|
117
|
+
ttl: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* WebSocket subscription record stored in DynamoDB
|
|
121
|
+
*/
|
|
122
|
+
export interface SubscriptionRecord {
|
|
123
|
+
subscriptionId: string;
|
|
124
|
+
connectionId: string;
|
|
125
|
+
userId: string;
|
|
126
|
+
vpnId: string;
|
|
127
|
+
subscribedAt: number;
|
|
128
|
+
ttl: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* VPN state change event published to EventBridge
|
|
132
|
+
*/
|
|
133
|
+
export interface VpnStateChangeEvent {
|
|
134
|
+
version: '0';
|
|
135
|
+
id: string;
|
|
136
|
+
'detail-type': 'VPN State Change';
|
|
137
|
+
source: 'mytmpvpn.vpn';
|
|
138
|
+
account: string;
|
|
139
|
+
time: string;
|
|
140
|
+
region: string;
|
|
141
|
+
resources: string[];
|
|
142
|
+
detail: VpnStateChangeEventDetail;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Detail section of VPN state change event
|
|
146
|
+
*/
|
|
147
|
+
export interface VpnStateChangeEventDetail {
|
|
148
|
+
vpnId: string;
|
|
149
|
+
userId: string;
|
|
150
|
+
locationId?: string;
|
|
151
|
+
geonamesId?: number;
|
|
152
|
+
previousState: VpnState;
|
|
153
|
+
newState: VpnState;
|
|
154
|
+
timestamp: number;
|
|
155
|
+
metadata?: Record<string, any>;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Configuration for WebSocket client
|
|
159
|
+
*/
|
|
160
|
+
export interface WebSocketConfig {
|
|
161
|
+
websocketUrl: string;
|
|
162
|
+
getAuthToken: () => Promise<string>;
|
|
163
|
+
reconnect?: boolean;
|
|
164
|
+
reconnectDelay?: number;
|
|
165
|
+
maxReconnectAttempts?: number;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* WebSocket connection state
|
|
169
|
+
*/
|
|
170
|
+
export declare enum WebSocketConnectionState {
|
|
171
|
+
DISCONNECTED = "DISCONNECTED",
|
|
172
|
+
CONNECTING = "CONNECTING",
|
|
173
|
+
CONNECTED = "CONNECTED",
|
|
174
|
+
RECONNECTING = "RECONNECTING",
|
|
175
|
+
FAILED = "FAILED"
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Callback function for state change events
|
|
179
|
+
*/
|
|
180
|
+
export type StateChangeCallback = (event: StateChangeNotification) => void;
|
|
181
|
+
/**
|
|
182
|
+
* Callback function for error events
|
|
183
|
+
*/
|
|
184
|
+
export type ErrorCallback = (error: ErrorMessage) => void;
|
|
185
|
+
/**
|
|
186
|
+
* Callback function for connection state changes
|
|
187
|
+
*/
|
|
188
|
+
export type ConnectionStateCallback = (state: WebSocketConnectionState) => void;
|
|
189
|
+
/**
|
|
190
|
+
* Options for waiting for a specific VPN state
|
|
191
|
+
*/
|
|
192
|
+
export interface WaitForStateOptions {
|
|
193
|
+
vpnId: string;
|
|
194
|
+
targetState: VpnState;
|
|
195
|
+
timeoutMs?: number;
|
|
196
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketConnectionState = exports.WebSocketErrorCode = void 0;
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Error Codes
|
|
6
|
+
// ============================================================================
|
|
7
|
+
/**
|
|
8
|
+
* Standard error codes for WebSocket operations
|
|
9
|
+
*/
|
|
10
|
+
var WebSocketErrorCode;
|
|
11
|
+
(function (WebSocketErrorCode) {
|
|
12
|
+
// Authentication errors
|
|
13
|
+
WebSocketErrorCode["AUTHENTICATION_FAILED"] = "AUTHENTICATION_FAILED";
|
|
14
|
+
WebSocketErrorCode["TOKEN_EXPIRED"] = "TOKEN_EXPIRED";
|
|
15
|
+
WebSocketErrorCode["TOKEN_INVALID"] = "TOKEN_INVALID";
|
|
16
|
+
WebSocketErrorCode["TOKEN_MISSING"] = "TOKEN_MISSING";
|
|
17
|
+
// Authorization errors
|
|
18
|
+
WebSocketErrorCode["PERMISSION_DENIED"] = "PERMISSION_DENIED";
|
|
19
|
+
WebSocketErrorCode["VPN_NOT_OWNED"] = "VPN_NOT_OWNED";
|
|
20
|
+
// Validation errors
|
|
21
|
+
WebSocketErrorCode["INVALID_MESSAGE_FORMAT"] = "INVALID_MESSAGE_FORMAT";
|
|
22
|
+
WebSocketErrorCode["INVALID_VPN_ID"] = "INVALID_VPN_ID";
|
|
23
|
+
WebSocketErrorCode["MISSING_REQUIRED_FIELD"] = "MISSING_REQUIRED_FIELD";
|
|
24
|
+
WebSocketErrorCode["UNKNOWN_ACTION"] = "UNKNOWN_ACTION";
|
|
25
|
+
// Resource errors
|
|
26
|
+
WebSocketErrorCode["VPN_NOT_FOUND"] = "VPN_NOT_FOUND";
|
|
27
|
+
WebSocketErrorCode["SUBSCRIPTION_NOT_FOUND"] = "SUBSCRIPTION_NOT_FOUND";
|
|
28
|
+
// Rate limiting
|
|
29
|
+
WebSocketErrorCode["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED";
|
|
30
|
+
WebSocketErrorCode["TOO_MANY_MALFORMED_MESSAGES"] = "TOO_MANY_MALFORMED_MESSAGES";
|
|
31
|
+
// Connection errors
|
|
32
|
+
WebSocketErrorCode["CONNECTION_FAILED"] = "CONNECTION_FAILED";
|
|
33
|
+
WebSocketErrorCode["CONNECTION_TIMEOUT"] = "CONNECTION_TIMEOUT";
|
|
34
|
+
// Internal errors
|
|
35
|
+
WebSocketErrorCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
|
|
36
|
+
WebSocketErrorCode["NOTIFICATION_DELIVERY_FAILED"] = "NOTIFICATION_DELIVERY_FAILED";
|
|
37
|
+
})(WebSocketErrorCode = exports.WebSocketErrorCode || (exports.WebSocketErrorCode = {}));
|
|
38
|
+
/**
|
|
39
|
+
* WebSocket connection state
|
|
40
|
+
*/
|
|
41
|
+
var WebSocketConnectionState;
|
|
42
|
+
(function (WebSocketConnectionState) {
|
|
43
|
+
WebSocketConnectionState["DISCONNECTED"] = "DISCONNECTED";
|
|
44
|
+
WebSocketConnectionState["CONNECTING"] = "CONNECTING";
|
|
45
|
+
WebSocketConnectionState["CONNECTED"] = "CONNECTED";
|
|
46
|
+
WebSocketConnectionState["RECONNECTING"] = "RECONNECTING";
|
|
47
|
+
WebSocketConnectionState["FAILED"] = "FAILED";
|
|
48
|
+
})(WebSocketConnectionState = exports.WebSocketConnectionState || (exports.WebSocketConnectionState = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vpn_1 = require("../../src/models/vpn");
|
|
4
|
+
const websocket_1 = require("../../src/models/websocket");
|
|
5
|
+
describe('WebSocket Types', () => {
|
|
6
|
+
describe('Client Messages', () => {
|
|
7
|
+
it('should create a valid SubscribeMessage', () => {
|
|
8
|
+
const message = {
|
|
9
|
+
action: 'subscribe',
|
|
10
|
+
vpnId: 'test-vpn-id',
|
|
11
|
+
requestId: 'req-123',
|
|
12
|
+
};
|
|
13
|
+
expect(message.action).toBe('subscribe');
|
|
14
|
+
expect(message.vpnId).toBe('test-vpn-id');
|
|
15
|
+
});
|
|
16
|
+
it('should create a SubscribeMessage with "all"', () => {
|
|
17
|
+
const message = {
|
|
18
|
+
action: 'subscribe',
|
|
19
|
+
vpnId: 'all',
|
|
20
|
+
requestId: 'req-123',
|
|
21
|
+
};
|
|
22
|
+
expect(message.vpnId).toBe('all');
|
|
23
|
+
});
|
|
24
|
+
it('should create a valid UnsubscribeMessage', () => {
|
|
25
|
+
const message = {
|
|
26
|
+
action: 'unsubscribe',
|
|
27
|
+
vpnId: 'test-vpn-id',
|
|
28
|
+
requestId: 'req-456',
|
|
29
|
+
};
|
|
30
|
+
expect(message.action).toBe('unsubscribe');
|
|
31
|
+
});
|
|
32
|
+
it('should create a valid PingMessage', () => {
|
|
33
|
+
const message = {
|
|
34
|
+
action: 'ping',
|
|
35
|
+
requestId: 'req-789',
|
|
36
|
+
};
|
|
37
|
+
expect(message.action).toBe('ping');
|
|
38
|
+
});
|
|
39
|
+
it('should accept ClientMessage union type', () => {
|
|
40
|
+
const messages = [
|
|
41
|
+
{ action: 'subscribe', vpnId: 'vpn-1', requestId: 'req-1' },
|
|
42
|
+
{ action: 'unsubscribe', vpnId: 'vpn-2', requestId: 'req-2' },
|
|
43
|
+
{ action: 'ping', requestId: 'req-3' },
|
|
44
|
+
];
|
|
45
|
+
expect(messages).toHaveLength(3);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('Server Messages', () => {
|
|
49
|
+
it('should create a valid StateChangeNotification', () => {
|
|
50
|
+
const notification = {
|
|
51
|
+
type: 'state_change',
|
|
52
|
+
vpnId: 'test-vpn-id',
|
|
53
|
+
previousState: vpn_1.VpnState.Provisioning,
|
|
54
|
+
newState: vpn_1.VpnState.Running,
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
};
|
|
57
|
+
expect(notification.type).toBe('state_change');
|
|
58
|
+
expect(notification.newState).toBe(vpn_1.VpnState.Running);
|
|
59
|
+
});
|
|
60
|
+
it('should create a valid AcknowledgmentMessage', () => {
|
|
61
|
+
const ack = {
|
|
62
|
+
type: 'ack',
|
|
63
|
+
requestId: 'req-123',
|
|
64
|
+
action: 'subscribe',
|
|
65
|
+
success: true,
|
|
66
|
+
timestamp: Date.now(),
|
|
67
|
+
};
|
|
68
|
+
expect(ack.success).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
it('should create a valid ErrorMessage', () => {
|
|
71
|
+
const error = {
|
|
72
|
+
type: 'error',
|
|
73
|
+
code: websocket_1.WebSocketErrorCode.VPN_NOT_FOUND,
|
|
74
|
+
message: 'VPN not found',
|
|
75
|
+
requestId: 'req-456',
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
};
|
|
78
|
+
expect(error.code).toBe(websocket_1.WebSocketErrorCode.VPN_NOT_FOUND);
|
|
79
|
+
});
|
|
80
|
+
it('should create a valid PongMessage', () => {
|
|
81
|
+
const pong = {
|
|
82
|
+
type: 'pong',
|
|
83
|
+
requestId: 'req-789',
|
|
84
|
+
timestamp: Date.now(),
|
|
85
|
+
};
|
|
86
|
+
expect(pong.type).toBe('pong');
|
|
87
|
+
});
|
|
88
|
+
it('should accept ServerMessage union type', () => {
|
|
89
|
+
const messages = [
|
|
90
|
+
{
|
|
91
|
+
type: 'state_change',
|
|
92
|
+
vpnId: 'vpn-1',
|
|
93
|
+
previousState: vpn_1.VpnState.Creating,
|
|
94
|
+
newState: vpn_1.VpnState.Running,
|
|
95
|
+
timestamp: Date.now(),
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'ack',
|
|
99
|
+
requestId: 'req-1',
|
|
100
|
+
action: 'subscribe',
|
|
101
|
+
success: true,
|
|
102
|
+
timestamp: Date.now(),
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'error',
|
|
106
|
+
code: websocket_1.WebSocketErrorCode.INTERNAL_ERROR,
|
|
107
|
+
message: 'Error',
|
|
108
|
+
timestamp: Date.now(),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: 'pong',
|
|
112
|
+
requestId: 'req-2',
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
expect(messages).toHaveLength(4);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('Error Codes', () => {
|
|
120
|
+
it('should have authentication error codes', () => {
|
|
121
|
+
expect(websocket_1.WebSocketErrorCode.AUTHENTICATION_FAILED).toBe('AUTHENTICATION_FAILED');
|
|
122
|
+
expect(websocket_1.WebSocketErrorCode.TOKEN_EXPIRED).toBe('TOKEN_EXPIRED');
|
|
123
|
+
expect(websocket_1.WebSocketErrorCode.TOKEN_INVALID).toBe('TOKEN_INVALID');
|
|
124
|
+
expect(websocket_1.WebSocketErrorCode.TOKEN_MISSING).toBe('TOKEN_MISSING');
|
|
125
|
+
});
|
|
126
|
+
it('should have authorization error codes', () => {
|
|
127
|
+
expect(websocket_1.WebSocketErrorCode.PERMISSION_DENIED).toBe('PERMISSION_DENIED');
|
|
128
|
+
expect(websocket_1.WebSocketErrorCode.VPN_NOT_OWNED).toBe('VPN_NOT_OWNED');
|
|
129
|
+
});
|
|
130
|
+
it('should have validation error codes', () => {
|
|
131
|
+
expect(websocket_1.WebSocketErrorCode.INVALID_MESSAGE_FORMAT).toBe('INVALID_MESSAGE_FORMAT');
|
|
132
|
+
expect(websocket_1.WebSocketErrorCode.INVALID_VPN_ID).toBe('INVALID_VPN_ID');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('DynamoDB Records', () => {
|
|
136
|
+
it('should create a valid ConnectionRecord', () => {
|
|
137
|
+
const record = {
|
|
138
|
+
connectionId: 'conn-123',
|
|
139
|
+
userId: 'user-456',
|
|
140
|
+
connectedAt: Date.now(),
|
|
141
|
+
ttl: Date.now() + 7200000, // 2 hours
|
|
142
|
+
};
|
|
143
|
+
expect(record.connectionId).toBe('conn-123');
|
|
144
|
+
expect(record.userId).toBe('user-456');
|
|
145
|
+
});
|
|
146
|
+
it('should create a valid SubscriptionRecord', () => {
|
|
147
|
+
const record = {
|
|
148
|
+
subscriptionId: 'conn-123#vpn-456',
|
|
149
|
+
connectionId: 'conn-123',
|
|
150
|
+
userId: 'user-789',
|
|
151
|
+
vpnId: 'vpn-456',
|
|
152
|
+
subscribedAt: Date.now(),
|
|
153
|
+
ttl: Date.now() + 7200000,
|
|
154
|
+
};
|
|
155
|
+
expect(record.subscriptionId).toBe('conn-123#vpn-456');
|
|
156
|
+
expect(record.vpnId).toBe('vpn-456');
|
|
157
|
+
});
|
|
158
|
+
it('should support "all" subscription', () => {
|
|
159
|
+
const record = {
|
|
160
|
+
subscriptionId: 'conn-123#all',
|
|
161
|
+
connectionId: 'conn-123',
|
|
162
|
+
userId: 'user-789',
|
|
163
|
+
vpnId: 'all',
|
|
164
|
+
subscribedAt: Date.now(),
|
|
165
|
+
ttl: Date.now() + 7200000,
|
|
166
|
+
};
|
|
167
|
+
expect(record.vpnId).toBe('all');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('EventBridge Events', () => {
|
|
171
|
+
it('should create a valid VpnStateChangeEvent', () => {
|
|
172
|
+
const event = {
|
|
173
|
+
version: '0',
|
|
174
|
+
id: 'event-123',
|
|
175
|
+
'detail-type': 'VPN State Change',
|
|
176
|
+
source: 'mytmpvpn.vpn',
|
|
177
|
+
account: '123456789012',
|
|
178
|
+
time: new Date().toISOString(),
|
|
179
|
+
region: 'us-east-1',
|
|
180
|
+
resources: [],
|
|
181
|
+
detail: {
|
|
182
|
+
vpnId: 'vpn-123',
|
|
183
|
+
userId: 'user-456',
|
|
184
|
+
geonamesId: 5128581,
|
|
185
|
+
previousState: vpn_1.VpnState.Provisioning,
|
|
186
|
+
newState: vpn_1.VpnState.Running,
|
|
187
|
+
timestamp: Date.now(),
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
expect(event.source).toBe('mytmpvpn.vpn');
|
|
191
|
+
expect(event.detail.newState).toBe(vpn_1.VpnState.Running);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('Connection States', () => {
|
|
195
|
+
it('should have all connection states', () => {
|
|
196
|
+
expect(websocket_1.WebSocketConnectionState.DISCONNECTED).toBe('DISCONNECTED');
|
|
197
|
+
expect(websocket_1.WebSocketConnectionState.CONNECTING).toBe('CONNECTING');
|
|
198
|
+
expect(websocket_1.WebSocketConnectionState.CONNECTED).toBe('CONNECTED');
|
|
199
|
+
expect(websocket_1.WebSocketConnectionState.RECONNECTING).toBe('RECONNECTING');
|
|
200
|
+
expect(websocket_1.WebSocketConnectionState.FAILED).toBe('FAILED');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
package/dist/test/models.test.js
CHANGED
|
@@ -126,6 +126,7 @@ describe('Testing vpnId to Wireguard file name functions ', () => {
|
|
|
126
126
|
const fileName = (0, vpn_1.vpnIdToWgFileName)(vpn);
|
|
127
127
|
expect(fileName).toBeDefined();
|
|
128
128
|
expect(fileName.length).toBeLessThanOrEqual(15);
|
|
129
|
+
expect(fileName.endsWith('.conf')).toBe(true);
|
|
129
130
|
});
|
|
130
131
|
});
|
|
131
132
|
describe('Testing vpn config', () => {
|