sockress-client 0.1.7 → 0.1.9
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/LICENSE +29 -0
- package/package.json +2 -2
- package/dist/index.d.ts +0 -111
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -517
- package/dist/index.js.map +0 -1
- package/src/index.ts +0 -700
- package/tsconfig.json +0 -14
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
PROPRIETARY LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Also Coder. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS:
|
|
6
|
+
|
|
7
|
+
1. USE PERMISSION:
|
|
8
|
+
You are granted permission to use this software ("sockress-client") in your projects,
|
|
9
|
+
applications, and commercial products.
|
|
10
|
+
|
|
11
|
+
2. RESTRICTIONS:
|
|
12
|
+
- You MAY NOT modify, adapt, alter, or create derivative works of this software.
|
|
13
|
+
- You MAY NOT sell, resell, sublicense, or redistribute this software as a standalone product.
|
|
14
|
+
- You MAY NOT create your own repository, fork, or distribution of this software.
|
|
15
|
+
- You MUST use the original repository maintained by Also Coder.
|
|
16
|
+
|
|
17
|
+
3. DISTRIBUTION:
|
|
18
|
+
You may include this software as a dependency in your projects, but you may not
|
|
19
|
+
redistribute the source code or compiled code separately from your project.
|
|
20
|
+
|
|
21
|
+
4. NO WARRANTY:
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
25
|
+
|
|
26
|
+
5. CONTACT:
|
|
27
|
+
For licensing inquiries or special permissions, contact: hello@alsocoder.com
|
|
28
|
+
|
|
29
|
+
By using this software, you agree to these terms and conditions.
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sockress-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Socket-first client SDK for Sockress servers with automatic HTTP fallback and FormData serialization.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
|
-
"type": "module",
|
|
8
7
|
"exports": {
|
|
9
8
|
".": {
|
|
10
9
|
"import": "./dist/index.js",
|
|
@@ -29,6 +28,7 @@
|
|
|
29
28
|
"bugs": {
|
|
30
29
|
"url": "https://github.com/alsocoders/sockress/issues"
|
|
31
30
|
},
|
|
31
|
+
"license": "PROPRIETARY",
|
|
32
32
|
"keywords": [
|
|
33
33
|
"sockress",
|
|
34
34
|
"websocket",
|
package/dist/index.d.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
2
|
-
export interface SockressClientOptions {
|
|
3
|
-
baseUrl: string;
|
|
4
|
-
socketPath?: string;
|
|
5
|
-
headers?: Record<string, string>;
|
|
6
|
-
timeout?: number;
|
|
7
|
-
reconnectInterval?: number;
|
|
8
|
-
maxReconnectInterval?: number;
|
|
9
|
-
autoConnect?: boolean;
|
|
10
|
-
preferSocket?: boolean;
|
|
11
|
-
fetchImpl?: typeof fetch;
|
|
12
|
-
wsFactory?: WebSocketFactory;
|
|
13
|
-
credentials?: RequestCredentials;
|
|
14
|
-
}
|
|
15
|
-
export interface SockressClientRequest {
|
|
16
|
-
path: string;
|
|
17
|
-
method?: HTTPMethod;
|
|
18
|
-
headers?: Record<string, string>;
|
|
19
|
-
query?: Record<string, string | number | boolean | Array<string | number | boolean>>;
|
|
20
|
-
body?: unknown;
|
|
21
|
-
timeout?: number;
|
|
22
|
-
signal?: AbortSignal;
|
|
23
|
-
disableHttpFallback?: boolean;
|
|
24
|
-
}
|
|
25
|
-
export interface SockressClientResponse<T = unknown> {
|
|
26
|
-
status: number;
|
|
27
|
-
ok: boolean;
|
|
28
|
-
headers: Record<string, string>;
|
|
29
|
-
body: T;
|
|
30
|
-
json: <R = T>() => R;
|
|
31
|
-
text: () => string;
|
|
32
|
-
raw: () => T;
|
|
33
|
-
}
|
|
34
|
-
export type EventMap = {
|
|
35
|
-
open: void;
|
|
36
|
-
close: {
|
|
37
|
-
code?: number;
|
|
38
|
-
reason?: string;
|
|
39
|
-
};
|
|
40
|
-
error: unknown;
|
|
41
|
-
reconnect: {
|
|
42
|
-
attempt: number;
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
type Listener<K extends keyof EventMap> = (payload: EventMap[K]) => void;
|
|
46
|
-
type WebSocketLike = {
|
|
47
|
-
readyState: number;
|
|
48
|
-
send(data: string): void;
|
|
49
|
-
close(code?: number, reason?: string): void;
|
|
50
|
-
onopen?: ((event: any) => void) | null;
|
|
51
|
-
onmessage?: ((event: any) => void) | null;
|
|
52
|
-
onclose?: ((event: any) => void) | null;
|
|
53
|
-
onerror?: ((event: any) => void) | null;
|
|
54
|
-
addEventListener?(type: string, listener: (event: any) => void): void;
|
|
55
|
-
removeEventListener?(type: string, listener: (event: any) => void): void;
|
|
56
|
-
on?(type: string, listener: (...args: unknown[]) => void): void;
|
|
57
|
-
off?(type: string, listener: (...args: unknown[]) => void): void;
|
|
58
|
-
};
|
|
59
|
-
export type WebSocketFactory = (url: string) => WebSocketLike;
|
|
60
|
-
interface NormalizedOptions {
|
|
61
|
-
baseUrl: string;
|
|
62
|
-
socketPath: string;
|
|
63
|
-
headers: Record<string, string>;
|
|
64
|
-
timeout: number;
|
|
65
|
-
reconnectInterval: number;
|
|
66
|
-
maxReconnectInterval: number;
|
|
67
|
-
autoConnect: boolean;
|
|
68
|
-
preferSocket: boolean;
|
|
69
|
-
fetchImpl: typeof fetch;
|
|
70
|
-
wsFactory?: WebSocketFactory;
|
|
71
|
-
credentials: RequestCredentials;
|
|
72
|
-
}
|
|
73
|
-
export declare class SockressClient {
|
|
74
|
-
private readonly options;
|
|
75
|
-
private ws?;
|
|
76
|
-
private reconnectAttempts;
|
|
77
|
-
private pending;
|
|
78
|
-
private queue;
|
|
79
|
-
private listeners;
|
|
80
|
-
private socketEnabled;
|
|
81
|
-
private lifecycleTeardown;
|
|
82
|
-
private closeRequested;
|
|
83
|
-
constructor(options: NormalizedOptions);
|
|
84
|
-
static create(options: SockressClientOptions): SockressClient;
|
|
85
|
-
on<K extends keyof EventMap>(event: K, listener: Listener<K>): () => void;
|
|
86
|
-
off<K extends keyof EventMap>(event: K, listener: Listener<K>): void;
|
|
87
|
-
emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void;
|
|
88
|
-
connect(): Promise<void>;
|
|
89
|
-
private attachSocketHandlers;
|
|
90
|
-
private flushQueue;
|
|
91
|
-
private scheduleReconnect;
|
|
92
|
-
private handleSocketMessage;
|
|
93
|
-
private applyCookies;
|
|
94
|
-
private clearPending;
|
|
95
|
-
private rejectAllPending;
|
|
96
|
-
private registerLifecycleHooks;
|
|
97
|
-
private canUseSocket;
|
|
98
|
-
request<T = unknown>(options: SockressClientRequest): Promise<SockressClientResponse<T>>;
|
|
99
|
-
get<T = unknown>(path: string, options?: Omit<SockressClientRequest, 'path' | 'method'>): Promise<SockressClientResponse<T>>;
|
|
100
|
-
post<T = unknown>(path: string, options?: Omit<SockressClientRequest, 'path' | 'method'>): Promise<SockressClientResponse<T>>;
|
|
101
|
-
put<T = unknown>(path: string, options?: Omit<SockressClientRequest, 'path' | 'method'>): Promise<SockressClientResponse<T>>;
|
|
102
|
-
patch<T = unknown>(path: string, options?: Omit<SockressClientRequest, 'path' | 'method'>): Promise<SockressClientResponse<T>>;
|
|
103
|
-
delete<T = unknown>(path: string, options?: Omit<SockressClientRequest, 'path' | 'method'>): Promise<SockressClientResponse<T>>;
|
|
104
|
-
private sendViaSocket;
|
|
105
|
-
private sendViaHttp;
|
|
106
|
-
close(): void;
|
|
107
|
-
}
|
|
108
|
-
export declare function sockressClient(options: SockressClientOptions): SockressClient;
|
|
109
|
-
export declare const createSockressClient: typeof sockressClient;
|
|
110
|
-
export {};
|
|
111
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
DELETED
|
@@ -1,517 +0,0 @@
|
|
|
1
|
-
import { nanoid } from 'nanoid';
|
|
2
|
-
export class SockressClient {
|
|
3
|
-
constructor(options) {
|
|
4
|
-
this.options = options;
|
|
5
|
-
this.reconnectAttempts = 0;
|
|
6
|
-
this.pending = new Map();
|
|
7
|
-
this.queue = [];
|
|
8
|
-
this.listeners = {
|
|
9
|
-
open: new Set(),
|
|
10
|
-
close: new Set(),
|
|
11
|
-
error: new Set(),
|
|
12
|
-
reconnect: new Set()
|
|
13
|
-
};
|
|
14
|
-
this.socketEnabled = true;
|
|
15
|
-
this.lifecycleTeardown = [];
|
|
16
|
-
this.closeRequested = false;
|
|
17
|
-
if (options.autoConnect) {
|
|
18
|
-
this.connect().catch(() => {
|
|
19
|
-
// Ignore initial connection failures, HTTP fallback will handle requests.
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
this.registerLifecycleHooks();
|
|
23
|
-
}
|
|
24
|
-
static create(options) {
|
|
25
|
-
return new SockressClient(normalizeOptions(options));
|
|
26
|
-
}
|
|
27
|
-
on(event, listener) {
|
|
28
|
-
this.listeners[event].add(listener);
|
|
29
|
-
return () => this.off(event, listener);
|
|
30
|
-
}
|
|
31
|
-
off(event, listener) {
|
|
32
|
-
this.listeners[event].delete(listener);
|
|
33
|
-
}
|
|
34
|
-
emit(event, payload) {
|
|
35
|
-
for (const listener of this.listeners[event]) {
|
|
36
|
-
listener(payload);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
async connect() {
|
|
40
|
-
if (!this.options.wsFactory) {
|
|
41
|
-
this.socketEnabled = false;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (this.ws && this.ws.readyState === 1) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const socketUrl = buildSocketUrl(this.options.baseUrl, this.options.socketPath);
|
|
48
|
-
this.ws = this.options.wsFactory(socketUrl);
|
|
49
|
-
this.attachSocketHandlers(this.ws);
|
|
50
|
-
}
|
|
51
|
-
attachSocketHandlers(socket) {
|
|
52
|
-
const handleOpen = () => {
|
|
53
|
-
this.reconnectAttempts = 0;
|
|
54
|
-
this.emit('open', undefined);
|
|
55
|
-
this.flushQueue();
|
|
56
|
-
};
|
|
57
|
-
const handleMessage = (event) => {
|
|
58
|
-
const data = resolveEventData(event);
|
|
59
|
-
if (data) {
|
|
60
|
-
this.handleSocketMessage(data);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const handleError = (event) => {
|
|
64
|
-
this.emit('error', event);
|
|
65
|
-
this.rejectAllPending(new Error('Socket error'));
|
|
66
|
-
};
|
|
67
|
-
const handleClose = (details) => {
|
|
68
|
-
this.emit('close', { code: details === null || details === void 0 ? void 0 : details.code, reason: details === null || details === void 0 ? void 0 : details.reason });
|
|
69
|
-
this.rejectAllPending(new Error('Socket closed'));
|
|
70
|
-
this.scheduleReconnect();
|
|
71
|
-
};
|
|
72
|
-
if (typeof socket.addEventListener === 'function') {
|
|
73
|
-
socket.addEventListener('open', () => handleOpen());
|
|
74
|
-
socket.addEventListener('message', (event) => handleMessage(event));
|
|
75
|
-
socket.addEventListener('error', (event) => handleError(event));
|
|
76
|
-
socket.addEventListener('close', (event) => handleClose(extractCloseDetails(event)));
|
|
77
|
-
}
|
|
78
|
-
else if (typeof socket.on === 'function') {
|
|
79
|
-
socket.on('open', handleOpen);
|
|
80
|
-
socket.on('message', (data) => handleMessage({ data }));
|
|
81
|
-
socket.on('error', handleError);
|
|
82
|
-
socket.on('close', (...args) => {
|
|
83
|
-
const [code, reason] = args;
|
|
84
|
-
handleClose({
|
|
85
|
-
code: typeof code === 'number' ? code : undefined,
|
|
86
|
-
reason: typeof reason === 'string' ? reason : typeof reason === 'object' && reason ? `${reason}` : undefined
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
socket.onopen = () => handleOpen();
|
|
92
|
-
socket.onmessage = (event) => handleMessage(event);
|
|
93
|
-
socket.onerror = (event) => handleError(event);
|
|
94
|
-
socket.onclose = (event) => handleClose(extractCloseDetails(event));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
flushQueue() {
|
|
98
|
-
if (!this.ws || this.ws.readyState !== 1)
|
|
99
|
-
return;
|
|
100
|
-
while (this.queue.length) {
|
|
101
|
-
const payload = this.queue.shift();
|
|
102
|
-
if (!payload)
|
|
103
|
-
continue;
|
|
104
|
-
this.ws.send(JSON.stringify(payload));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
scheduleReconnect() {
|
|
108
|
-
if (!this.socketEnabled || !this.options.wsFactory) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
this.reconnectAttempts += 1;
|
|
112
|
-
const delay = Math.min(this.options.reconnectInterval * this.reconnectAttempts, this.options.maxReconnectInterval);
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
this.emit('reconnect', { attempt: this.reconnectAttempts });
|
|
115
|
-
this.connect().catch(() => {
|
|
116
|
-
// keep trying silently
|
|
117
|
-
});
|
|
118
|
-
}, delay);
|
|
119
|
-
}
|
|
120
|
-
handleSocketMessage(raw) {
|
|
121
|
-
try {
|
|
122
|
-
const payload = JSON.parse(raw);
|
|
123
|
-
if (payload.type === 'error') {
|
|
124
|
-
const pending = payload.id ? this.pending.get(payload.id) : null;
|
|
125
|
-
const error = new Error(payload.message);
|
|
126
|
-
if (pending) {
|
|
127
|
-
this.clearPending(payload.id);
|
|
128
|
-
pending.reject(error);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
this.emit('error', error);
|
|
132
|
-
}
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const pending = this.pending.get(payload.id);
|
|
136
|
-
if (!pending) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
this.clearPending(payload.id);
|
|
140
|
-
const response = createClientResponse(payload);
|
|
141
|
-
this.applyCookies(payload.cookies);
|
|
142
|
-
pending.resolve(response);
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
this.emit('error', error);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
applyCookies(cookies) {
|
|
149
|
-
if (!cookies || typeof document === 'undefined')
|
|
150
|
-
return;
|
|
151
|
-
for (const cookie of cookies) {
|
|
152
|
-
document.cookie = cookie;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
clearPending(id) {
|
|
156
|
-
const pending = this.pending.get(id);
|
|
157
|
-
if (pending === null || pending === void 0 ? void 0 : pending.timeout) {
|
|
158
|
-
clearTimeout(pending.timeout);
|
|
159
|
-
}
|
|
160
|
-
this.pending.delete(id);
|
|
161
|
-
}
|
|
162
|
-
rejectAllPending(error) {
|
|
163
|
-
for (const [id, pending] of this.pending.entries()) {
|
|
164
|
-
this.clearPending(id);
|
|
165
|
-
pending.reject(error);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
registerLifecycleHooks() {
|
|
169
|
-
const boundClose = () => this.close();
|
|
170
|
-
if (typeof process !== 'undefined' && typeof process.on === 'function') {
|
|
171
|
-
const handleSignal = () => boundClose();
|
|
172
|
-
process.once('beforeExit', handleSignal);
|
|
173
|
-
process.once('SIGINT', handleSignal);
|
|
174
|
-
process.once('SIGTERM', handleSignal);
|
|
175
|
-
this.lifecycleTeardown.push(() => {
|
|
176
|
-
process.off('beforeExit', handleSignal);
|
|
177
|
-
process.off('SIGINT', handleSignal);
|
|
178
|
-
process.off('SIGTERM', handleSignal);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
|
|
182
|
-
const handleUnload = () => boundClose();
|
|
183
|
-
window.addEventListener('beforeunload', handleUnload);
|
|
184
|
-
this.lifecycleTeardown.push(() => window.removeEventListener('beforeunload', handleUnload));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
canUseSocket() {
|
|
188
|
-
return Boolean(this.options.wsFactory && this.socketEnabled && this.ws && this.ws.readyState === 1);
|
|
189
|
-
}
|
|
190
|
-
async request(options) {
|
|
191
|
-
var _a, _b;
|
|
192
|
-
const method = (options.method || 'GET').toUpperCase();
|
|
193
|
-
const path = normalizePath(options.path);
|
|
194
|
-
const headers = { ...this.options.headers, ...((_a = options.headers) !== null && _a !== void 0 ? _a : {}) };
|
|
195
|
-
const query = options.query ? normalizeQuery(options.query) : undefined;
|
|
196
|
-
const timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.options.timeout;
|
|
197
|
-
if (this.options.preferSocket && this.socketEnabled) {
|
|
198
|
-
try {
|
|
199
|
-
return await this.sendViaSocket({ method, path, headers, query, body: options.body, timeout });
|
|
200
|
-
}
|
|
201
|
-
catch (error) {
|
|
202
|
-
if (options.disableHttpFallback) {
|
|
203
|
-
throw error;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return this.sendViaHttp({ method, path, headers, query, body: options.body, signal: options.signal });
|
|
208
|
-
}
|
|
209
|
-
get(path, options) {
|
|
210
|
-
return this.request({ ...(options !== null && options !== void 0 ? options : {}), path, method: 'GET' });
|
|
211
|
-
}
|
|
212
|
-
post(path, options) {
|
|
213
|
-
return this.request({ ...(options !== null && options !== void 0 ? options : {}), path, method: 'POST' });
|
|
214
|
-
}
|
|
215
|
-
put(path, options) {
|
|
216
|
-
return this.request({ ...(options !== null && options !== void 0 ? options : {}), path, method: 'PUT' });
|
|
217
|
-
}
|
|
218
|
-
patch(path, options) {
|
|
219
|
-
return this.request({ ...(options !== null && options !== void 0 ? options : {}), path, method: 'PATCH' });
|
|
220
|
-
}
|
|
221
|
-
delete(path, options) {
|
|
222
|
-
return this.request({ ...(options !== null && options !== void 0 ? options : {}), path, method: 'DELETE' });
|
|
223
|
-
}
|
|
224
|
-
async sendViaSocket(input) {
|
|
225
|
-
if (!this.options.wsFactory) {
|
|
226
|
-
this.socketEnabled = false;
|
|
227
|
-
throw new Error('Socket transport is unavailable');
|
|
228
|
-
}
|
|
229
|
-
await this.connect();
|
|
230
|
-
const id = nanoid();
|
|
231
|
-
const serializedBody = await serializeBodyForSocket(input.body);
|
|
232
|
-
const payload = {
|
|
233
|
-
type: 'request',
|
|
234
|
-
id,
|
|
235
|
-
method: input.method,
|
|
236
|
-
path: input.path,
|
|
237
|
-
headers: input.headers,
|
|
238
|
-
query: input.query,
|
|
239
|
-
body: serializedBody
|
|
240
|
-
};
|
|
241
|
-
const responsePromise = new Promise((resolve, reject) => {
|
|
242
|
-
const timeout = setTimeout(() => {
|
|
243
|
-
this.clearPending(id);
|
|
244
|
-
reject(new Error('Socket request timed out'));
|
|
245
|
-
}, input.timeout);
|
|
246
|
-
this.pending.set(id, { resolve, reject, timeout });
|
|
247
|
-
});
|
|
248
|
-
const serialized = JSON.stringify(payload);
|
|
249
|
-
if (this.canUseSocket()) {
|
|
250
|
-
this.ws.send(serialized);
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
this.queue.push(payload);
|
|
254
|
-
}
|
|
255
|
-
return responsePromise;
|
|
256
|
-
}
|
|
257
|
-
async sendViaHttp(input) {
|
|
258
|
-
var _a;
|
|
259
|
-
const url = buildHttpUrl(this.options.baseUrl, input.path, input.query);
|
|
260
|
-
const headers = new Headers(input.headers);
|
|
261
|
-
const init = {
|
|
262
|
-
method: input.method,
|
|
263
|
-
headers,
|
|
264
|
-
credentials: this.options.credentials,
|
|
265
|
-
signal: input.signal
|
|
266
|
-
};
|
|
267
|
-
if (input.body !== undefined && input.method !== 'GET' && input.method !== 'HEAD') {
|
|
268
|
-
if (typeof input.body === 'string' ||
|
|
269
|
-
input.body instanceof URLSearchParams ||
|
|
270
|
-
isBlob(input.body) ||
|
|
271
|
-
isFormData(input.body)) {
|
|
272
|
-
init.body = input.body;
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
init.body = JSON.stringify(input.body);
|
|
276
|
-
if (!headers.has('content-type')) {
|
|
277
|
-
headers.set('content-type', 'application/json');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
const response = await this.options.fetchImpl(url, init);
|
|
282
|
-
const text = await response.text();
|
|
283
|
-
let parsed = text;
|
|
284
|
-
const contentType = (_a = response.headers.get('content-type')) !== null && _a !== void 0 ? _a : '';
|
|
285
|
-
if (contentType.includes('application/json') && text) {
|
|
286
|
-
try {
|
|
287
|
-
parsed = JSON.parse(text);
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
parsed = text;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const headersObj = {};
|
|
294
|
-
response.headers.forEach((value, key) => {
|
|
295
|
-
headersObj[key.toLowerCase()] = value;
|
|
296
|
-
});
|
|
297
|
-
return {
|
|
298
|
-
status: response.status,
|
|
299
|
-
ok: response.ok,
|
|
300
|
-
headers: headersObj,
|
|
301
|
-
body: parsed,
|
|
302
|
-
json: () => parsed,
|
|
303
|
-
text: () => text,
|
|
304
|
-
raw: () => parsed
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
close() {
|
|
308
|
-
if (this.closeRequested)
|
|
309
|
-
return;
|
|
310
|
-
this.closeRequested = true;
|
|
311
|
-
this.socketEnabled = false;
|
|
312
|
-
if (this.ws) {
|
|
313
|
-
this.ws.close();
|
|
314
|
-
this.ws = undefined;
|
|
315
|
-
}
|
|
316
|
-
this.queue = [];
|
|
317
|
-
this.rejectAllPending(new Error('Client closed'));
|
|
318
|
-
this.lifecycleTeardown.forEach((teardown) => teardown());
|
|
319
|
-
this.lifecycleTeardown = [];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
export function sockressClient(options) {
|
|
323
|
-
return SockressClient.create(options);
|
|
324
|
-
}
|
|
325
|
-
export const createSockressClient = sockressClient;
|
|
326
|
-
function normalizeOptions(options) {
|
|
327
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
328
|
-
if (!options.baseUrl) {
|
|
329
|
-
throw new Error('baseUrl is required');
|
|
330
|
-
}
|
|
331
|
-
const fetchImpl = (_a = options.fetchImpl) !== null && _a !== void 0 ? _a : globalThis.fetch;
|
|
332
|
-
if (!fetchImpl) {
|
|
333
|
-
throw new Error('Fetch implementation is not available in this environment');
|
|
334
|
-
}
|
|
335
|
-
const wsFactory = (_b = options.wsFactory) !== null && _b !== void 0 ? _b : (typeof WebSocket !== 'undefined' ? (url) => new WebSocket(url) : undefined);
|
|
336
|
-
return {
|
|
337
|
-
baseUrl: options.baseUrl.replace(/\/+$/, ''),
|
|
338
|
-
socketPath: (_c = options.socketPath) !== null && _c !== void 0 ? _c : '/sockress',
|
|
339
|
-
headers: { ...((_d = options.headers) !== null && _d !== void 0 ? _d : {}) },
|
|
340
|
-
timeout: (_e = options.timeout) !== null && _e !== void 0 ? _e : 15000,
|
|
341
|
-
reconnectInterval: (_f = options.reconnectInterval) !== null && _f !== void 0 ? _f : 1000,
|
|
342
|
-
maxReconnectInterval: (_g = options.maxReconnectInterval) !== null && _g !== void 0 ? _g : 15000,
|
|
343
|
-
autoConnect: (_h = options.autoConnect) !== null && _h !== void 0 ? _h : true,
|
|
344
|
-
preferSocket: (_j = options.preferSocket) !== null && _j !== void 0 ? _j : true,
|
|
345
|
-
fetchImpl,
|
|
346
|
-
wsFactory,
|
|
347
|
-
credentials: (_k = options.credentials) !== null && _k !== void 0 ? _k : 'include'
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
async function serializeBodyForSocket(body) {
|
|
351
|
-
if (isFormData(body)) {
|
|
352
|
-
return {
|
|
353
|
-
__formData: await serializeFormData(body)
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
return body;
|
|
357
|
-
}
|
|
358
|
-
async function serializeFormData(formData) {
|
|
359
|
-
var _a, _b;
|
|
360
|
-
const fields = {};
|
|
361
|
-
const files = {};
|
|
362
|
-
const entries = collectFormDataEntries(formData);
|
|
363
|
-
for (const [key, value] of entries) {
|
|
364
|
-
if (typeof value === 'string') {
|
|
365
|
-
if (fields[key]) {
|
|
366
|
-
const existing = fields[key];
|
|
367
|
-
fields[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
fields[key] = value;
|
|
371
|
-
}
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
const fileBuffer = await value.arrayBuffer();
|
|
375
|
-
const encoded = arrayBufferToBase64(fileBuffer);
|
|
376
|
-
if (!files[key]) {
|
|
377
|
-
files[key] = [];
|
|
378
|
-
}
|
|
379
|
-
files[key].push({
|
|
380
|
-
fieldName: key,
|
|
381
|
-
name: (_a = value.name) !== null && _a !== void 0 ? _a : 'file',
|
|
382
|
-
type: (_b = value.type) !== null && _b !== void 0 ? _b : 'application/octet-stream',
|
|
383
|
-
size: value.size,
|
|
384
|
-
lastModified: typeof value.lastModified === 'number' ? value.lastModified : undefined,
|
|
385
|
-
data: encoded
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
return { fields, files };
|
|
389
|
-
}
|
|
390
|
-
function buildSocketUrl(baseUrl, socketPath) {
|
|
391
|
-
const url = new URL(socketPath, baseUrl);
|
|
392
|
-
url.protocol = url.protocol.replace('http', 'ws');
|
|
393
|
-
return url.toString();
|
|
394
|
-
}
|
|
395
|
-
function buildHttpUrl(baseUrl, path, query) {
|
|
396
|
-
const url = new URL(path, baseUrl);
|
|
397
|
-
if (query) {
|
|
398
|
-
for (const [key, value] of Object.entries(query)) {
|
|
399
|
-
if (Array.isArray(value)) {
|
|
400
|
-
value.forEach((entry) => url.searchParams.append(key, entry));
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
url.searchParams.append(key, value);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
return url.toString();
|
|
408
|
-
}
|
|
409
|
-
function normalizePath(path) {
|
|
410
|
-
if (!path.startsWith('/')) {
|
|
411
|
-
return `/${path}`;
|
|
412
|
-
}
|
|
413
|
-
return path;
|
|
414
|
-
}
|
|
415
|
-
function normalizeQuery(query) {
|
|
416
|
-
const result = {};
|
|
417
|
-
for (const [key, value] of Object.entries(query)) {
|
|
418
|
-
if (Array.isArray(value)) {
|
|
419
|
-
result[key] = value.map((item) => String(item));
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
result[key] = String(value);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return result;
|
|
426
|
-
}
|
|
427
|
-
function createClientResponse(payload) {
|
|
428
|
-
var _a;
|
|
429
|
-
const headers = (_a = payload.headers) !== null && _a !== void 0 ? _a : {};
|
|
430
|
-
const status = payload.status;
|
|
431
|
-
const body = payload.body;
|
|
432
|
-
return {
|
|
433
|
-
status,
|
|
434
|
-
ok: status >= 200 && status < 300,
|
|
435
|
-
headers,
|
|
436
|
-
body,
|
|
437
|
-
json: () => body,
|
|
438
|
-
text: () => (typeof body === 'string' ? body : JSON.stringify(body)),
|
|
439
|
-
raw: () => body
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
function extractCloseDetails(event) {
|
|
443
|
-
if (!event || typeof event !== 'object')
|
|
444
|
-
return {};
|
|
445
|
-
const closeEvent = event;
|
|
446
|
-
return {
|
|
447
|
-
code: closeEvent.code,
|
|
448
|
-
reason: closeEvent.reason
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
function resolveEventData(event) {
|
|
452
|
-
if (!event)
|
|
453
|
-
return '';
|
|
454
|
-
if (typeof event === 'string')
|
|
455
|
-
return event;
|
|
456
|
-
if (typeof event === 'object' && 'data' in event) {
|
|
457
|
-
return toText(event.data);
|
|
458
|
-
}
|
|
459
|
-
return toText(event);
|
|
460
|
-
}
|
|
461
|
-
const textDecoder = typeof TextDecoder !== 'undefined' ? new TextDecoder() : null;
|
|
462
|
-
function toText(value) {
|
|
463
|
-
if (typeof value === 'string') {
|
|
464
|
-
return value;
|
|
465
|
-
}
|
|
466
|
-
if (value instanceof ArrayBuffer) {
|
|
467
|
-
return textDecoder ? textDecoder.decode(value) : '';
|
|
468
|
-
}
|
|
469
|
-
if (ArrayBuffer.isView(value)) {
|
|
470
|
-
const view = value;
|
|
471
|
-
if (textDecoder) {
|
|
472
|
-
return textDecoder.decode(view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength));
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
if (value && typeof value.toString === 'function') {
|
|
476
|
-
return value.toString();
|
|
477
|
-
}
|
|
478
|
-
return '';
|
|
479
|
-
}
|
|
480
|
-
function isBlob(value) {
|
|
481
|
-
return typeof Blob !== 'undefined' && value instanceof Blob;
|
|
482
|
-
}
|
|
483
|
-
function isFormData(value) {
|
|
484
|
-
return typeof FormData !== 'undefined' && value instanceof FormData;
|
|
485
|
-
}
|
|
486
|
-
function arrayBufferToBase64(buffer) {
|
|
487
|
-
if (typeof Buffer !== 'undefined') {
|
|
488
|
-
return Buffer.from(buffer).toString('base64');
|
|
489
|
-
}
|
|
490
|
-
let binary = '';
|
|
491
|
-
const bytes = new Uint8Array(buffer);
|
|
492
|
-
for (let i = 0; i < bytes.length; i += 1) {
|
|
493
|
-
binary += String.fromCharCode(bytes[i]);
|
|
494
|
-
}
|
|
495
|
-
if (typeof btoa === 'function') {
|
|
496
|
-
return btoa(binary);
|
|
497
|
-
}
|
|
498
|
-
throw new Error('Base64 encoding is not supported in this environment');
|
|
499
|
-
}
|
|
500
|
-
function collectFormDataEntries(formData) {
|
|
501
|
-
const anyForm = formData;
|
|
502
|
-
const entries = [];
|
|
503
|
-
if (typeof anyForm.entries === 'function') {
|
|
504
|
-
for (const pair of anyForm.entries()) {
|
|
505
|
-
entries.push(pair);
|
|
506
|
-
}
|
|
507
|
-
return entries;
|
|
508
|
-
}
|
|
509
|
-
if (typeof anyForm[Symbol.iterator] === 'function') {
|
|
510
|
-
for (const pair of anyForm) {
|
|
511
|
-
entries.push(pair);
|
|
512
|
-
}
|
|
513
|
-
return entries;
|
|
514
|
-
}
|
|
515
|
-
throw new Error('FormData implementation does not support iteration');
|
|
516
|
-
}
|
|
517
|
-
//# sourceMappingURL=index.js.map
|