@araminix/lib 0.0.0-stage → 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amin Abbasi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,194 @@
1
- # Temporary Holding Version
1
+ # @araminix/lib
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Universal, type-safe multiplexed WebSocket streaming and functional communication protocol.**
4
+
5
+ [![npm version](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://www.npmjs.com/package/@araminix/lib)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.4-blue.svg)](https://www.typescriptlang.org/)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20.0.0-green.svg)](https://nodejs.org/)
9
+
10
+ **Araminix Lib** (`@araminix/lib`) provides the foundational communication layer for modern real-time applications. Designed to be completely **isomorphic**, it runs seamlessly across **Node.js**, **Web Browsers**, **Web Workers**, and modern frontend frameworks (React, Vue, Svelte, Angular).
11
+
12
+ Instead of maintaining multiple raw WebSocket connections or writing complex manual event dispatchers, `@araminix/lib` introduces **typed, multiplexed bidirectional streams** over a single persistent WebSocket connection, backed by a robust **`Result<T, E>` monad** for compile-time error resilience.
13
+
14
+ ---
15
+
16
+ ## 🌟 Key Features
17
+
18
+ - ⚡ **Multiplexed Bidirectional Streams**: Run hundreds of independent data streams over a single physical WebSocket connection with isolated lifecycles, flow control, and arguments.
19
+ - 🛡️ **Zero-Exception Result Monad**: Functional `Result<T, E>`, `Ok`, `Err`, `deal()`, and `wrap()` abstractions prevent unhandled promise rejections and force explicit error handling.
20
+ - 🌐 **Truly Isomorphic / Universal**: Single codebase operating identically in the browser (native `WebSocket`) and Node.js (`ws` / `websocket`).
21
+ - 📦 **Typed Protocol Envelopes**: Built-in runtime-validated message types (`NewStream`, `AcceptStream`, `DataStream`, `CloseStream`, `PingStream`, `PongStream`) validated via `io-ts`.
22
+ - 🔍 **Structured Logger**: Configurable, timestamped, colored logging utility supporting dynamic levels (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`).
23
+ - 🚀 **Zero Overhead**: Minimal dependencies, pure ESM, fully tree-shakeable, and bundled with complete TypeScript `.d.ts` declaration maps.
24
+
25
+ ---
26
+
27
+ ## 📦 Installation
28
+
29
+ ```bash
30
+ # npm
31
+ npm install @araminix/lib
32
+
33
+ # pnpm
34
+ pnpm add @araminix/lib
35
+
36
+ # yarn
37
+ yarn add @araminix/lib
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 🚀 Quick Start
43
+
44
+ ### 1. Connecting and Opening a Multiplexed Stream
45
+
46
+ ```typescript
47
+ import { Client, Socket, Stream } from '@araminix/lib';
48
+
49
+ // Connect client to a WebSocket endpoint
50
+ const client = new Client({
51
+ url: 'wss://api.example.com/ws/session',
52
+ });
53
+
54
+ const connectResult = await client.connect();
55
+
56
+ if (connectResult.isOk()) {
57
+ const socket: Socket = connectResult.unwrap();
58
+
59
+ // Open an outgoing typed stream over the single WebSocket connection
60
+ const streamResult = await socket.outgoingStream<{ channelId: string }, string, string>('chatRoom', { channelId: 'room-42' });
61
+
62
+ if (streamResult.isOk()) {
63
+ const stream = streamResult.unwrap();
64
+
65
+ // Send data through the stream
66
+ await stream.write('Hello from client!');
67
+
68
+ // Read incoming messages
69
+ const incoming = await stream.read();
70
+ if (incoming.isOk()) {
71
+ console.log('Received:', incoming.unwrap());
72
+ }
73
+
74
+ // Gracefully close stream
75
+ stream.closeOk();
76
+ }
77
+ }
78
+ ```
79
+
80
+ ---
81
+
82
+ ### 2. Handling Incoming Streams
83
+
84
+ ```typescript
85
+ import { loop, LoopResult, Socket } from '@araminix/lib';
86
+
87
+ export function handleSocket(socket: Socket) {
88
+ loop(async () => {
89
+ // Wait for an incoming stream named 'sensorData'
90
+ const streamResult = await socket.incomingStream('sensorData');
91
+ if (streamResult.isErr()) return LoopResult.Stop;
92
+
93
+ const stream = streamResult.unwrap();
94
+ console.log(`Stream initialized with arguments:`, stream.args);
95
+
96
+ // Process stream data
97
+ const readResult = await stream.read();
98
+ if (readResult.isOk()) {
99
+ console.log('Sensor payload:', readResult.unwrap());
100
+ await stream.write({ status: 'ACK' });
101
+ }
102
+
103
+ stream.closeOk();
104
+ return LoopResult.Cont;
105
+ });
106
+ }
107
+ ```
108
+
109
+ ---
110
+
111
+ ### 3. Safe Functional Programming with `Result<T, E>`
112
+
113
+ Eliminate `try/catch` boilerplate and unhandled promise crashes:
114
+
115
+ ```typescript
116
+ import { deal, Err, Ok, Result, wrap } from '@araminix/lib';
117
+
118
+ // 1. Creating typed Results
119
+ function parseNumber(input: string): Result<number, string> {
120
+ const val = Number(input);
121
+ return isNaN(val) ? new Err('Invalid number') : new Ok(val);
122
+ }
123
+
124
+ // 2. Safely wrapping third-party promises
125
+ const fetchResult = await wrap(fetch('https://api.example.com/data'));
126
+ if (fetchResult.isOk()) {
127
+ console.log('HTTP Status:', fetchResult.unwrap().status);
128
+ } else {
129
+ console.error('Network failure:', fetchResult.e);
130
+ }
131
+
132
+ // 3. Deferred execution with deal()
133
+ const [promise, resolve] = deal<string>();
134
+ setTimeout(() => resolve(new Ok('Completed!')), 100);
135
+ const result = await promise;
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 📐 Architecture Overview
141
+
142
+ ```
143
+ Single WebSocket Connection
144
+ Client (Browser / Node) <=====================> Server (@araminix/platform)
145
+ | |
146
+ +----------------+ +----------------+
147
+ | |
148
+ Stream "chat" Stream "telemetry"
149
+ [DataStream -> "hello"] [DataStream -> { cpu: 45 }]
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 🛠️ API Reference
155
+
156
+ ### Core Classes & Exports
157
+
158
+ | Export | Type | Description |
159
+ | -------------------------- | -------- | ---------------------------------------------------------------------------------------- |
160
+ | `Socket` | Class | High-level wrapper over a connection providing stream multiplexing and state inspection. |
161
+ | `Connection` | Class | Manages low-level WebSocket frames, keepalives, and stream controllers. |
162
+ | `Stream<TArgs, TIn, TOut>` | Class | Represents an independent, bidirectional typed channel over a `Socket`. |
163
+ | `Client` | Class | Isomorphic WebSocket connector supporting headers, tokens, and reconnects. |
164
+ | `Result<T, E>` | Class | Monadic result container (`Ok<T>` or `Err<E>`). |
165
+ | `Logger` | Class | Leveled structured logger (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`). |
166
+ | `wrap` / `wrapSync` | Function | Converts throwing functions/promises into `Result` instances. |
167
+ | `deal` | Function | Creates an inverted deferred promise tuple `[promise, resolve]`. |
168
+
169
+ ---
170
+
171
+ ## 🧪 Testing
172
+
173
+ ```bash
174
+ # Run unit tests
175
+ npm test
176
+
177
+ # Run tests with built-in code coverage report
178
+ npm run test:coverage
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 👤 Author
184
+
185
+ **Amin Abbasi**
186
+
187
+ - Organization: [araminix](https://github.com/araminix)
188
+ - GitHub: [@abbasi](https://github.com)
189
+
190
+ ---
191
+
192
+ ## 📄 License
193
+
194
+ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,8 @@
1
+ import * as messages from './src/messages.js';
2
+ import { InitStreamErr, Stream, StreamCloseCodes, StreamErr } from './src/stream.js';
3
+ export * from './src/Socket.js';
4
+ export * from './src/connection.js';
5
+ export * from './src/utils/index.js';
6
+ export * from './src/client.js';
7
+ export { Stream, StreamErr, InitStreamErr, messages as Message, StreamCloseCodes };
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErF,cAAc,iBAAiB,CAAC;AAEhC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,IAAI,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import * as messages from './src/messages.js';
2
+ import { InitStreamErr, Stream, StreamCloseCodes, StreamErr } from './src/stream.js';
3
+ export * from './src/Socket.js';
4
+ export * from './src/connection.js';
5
+ export * from './src/utils/index.js';
6
+ export * from './src/client.js';
7
+ export { Stream, StreamErr, InitStreamErr, messages as Message, StreamCloseCodes };
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErF,cAAc,iBAAiB,CAAC;AAEhC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,IAAI,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { CloseCodes, Connection } from './connection.js';
2
+ import { InitStreamErr, Stream } from './stream.js';
3
+ import { Result } from './utils/result.js';
4
+ export declare enum SocketErr {
5
+ Closed = 0,
6
+ Concurrent = 1
7
+ }
8
+ export declare enum ConnectionStatus {
9
+ Connecting = "connecting",
10
+ Open = "open",
11
+ Closing = "closing",
12
+ Closed = "closed",
13
+ Unknown = "unknown"
14
+ }
15
+ export declare class Socket {
16
+ connection: Connection;
17
+ constructor(connection: Connection);
18
+ incomingStream<TArgs = unknown, TDataIn = unknown, TDataOut = unknown>(name: string): Promise<Result<Stream<TArgs, TDataIn, TDataOut>, SocketErr>>;
19
+ get arg(): string;
20
+ waitClose(): Promise<CloseCodes>;
21
+ isDead(): boolean;
22
+ destroy(): void;
23
+ outgoingStream<TArgs = unknown, TDataIn = unknown, TDataOut = unknown>(name: string, args?: TArgs): Promise<Result<Stream<TArgs, TDataIn, TDataOut>, InitStreamErr>>;
24
+ getConnectionStatus(): ConnectionStatus;
25
+ }
26
+ //# sourceMappingURL=Socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Socket.d.ts","sourceRoot":"","sources":["../../src/Socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,oBAAY,SAAS;IACjB,MAAM,IAAI;IACV,UAAU,IAAI;CACjB;AAED,oBAAY,gBAAgB;IACxB,UAAU,eAAe;IACzB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;CACtB;AAED,qBAAa,MAAM;IACf,UAAU,EAAE,UAAU,CAAC;IAEvB,YAAY,UAAU,EAAE,UAAU,EAEjC;IAEK,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,CAEvJ;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAEK,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CAErC;IAED,MAAM,IAAI,OAAO,CAEhB;IAED,OAAO,IAAI,IAAI,CAEd;IAED,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC,CAEnK;IAED,mBAAmB,IAAI,gBAAgB,CAmBtC;CACJ"}
@@ -0,0 +1,61 @@
1
+ import { CloseCodes } from './connection.js';
2
+ export var SocketErr;
3
+ (function (SocketErr) {
4
+ SocketErr[SocketErr["Closed"] = 0] = "Closed";
5
+ SocketErr[SocketErr["Concurrent"] = 1] = "Concurrent";
6
+ })(SocketErr || (SocketErr = {}));
7
+ export var ConnectionStatus;
8
+ (function (ConnectionStatus) {
9
+ ConnectionStatus["Connecting"] = "connecting";
10
+ ConnectionStatus["Open"] = "open";
11
+ ConnectionStatus["Closing"] = "closing";
12
+ ConnectionStatus["Closed"] = "closed";
13
+ ConnectionStatus["Unknown"] = "unknown";
14
+ })(ConnectionStatus || (ConnectionStatus = {}));
15
+ export class Socket {
16
+ connection;
17
+ constructor(connection) {
18
+ this.connection = connection;
19
+ }
20
+ async incomingStream(name) {
21
+ return await this.connection.acquireStream(name);
22
+ }
23
+ get arg() {
24
+ return this.connection.arg;
25
+ }
26
+ async waitClose() {
27
+ return this.connection.closePromise;
28
+ }
29
+ isDead() {
30
+ return this.connection?.dead === true;
31
+ }
32
+ destroy() {
33
+ this.connection.destroy(CloseCodes.Intentional);
34
+ }
35
+ outgoingStream(name, args) {
36
+ return this.connection.newOutgoingStream(name, args);
37
+ }
38
+ getConnectionStatus() {
39
+ try {
40
+ const ws = this.connection?.ws;
41
+ if (!ws)
42
+ return ConnectionStatus.Unknown;
43
+ switch (ws.readyState) {
44
+ case 0:
45
+ return ConnectionStatus.Connecting;
46
+ case 1:
47
+ return ConnectionStatus.Open;
48
+ case 2:
49
+ return ConnectionStatus.Closing;
50
+ case 3:
51
+ return ConnectionStatus.Closed;
52
+ default:
53
+ return ConnectionStatus.Unknown;
54
+ }
55
+ }
56
+ catch {
57
+ return ConnectionStatus.Unknown;
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=Socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Socket.js","sourceRoot":"","sources":["../../src/Socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AAIzD,MAAM,CAAN,IAAY,SAGX;AAHD,WAAY,SAAS;IACjB,6CAAU,CAAA;IACV,qDAAc,CAAA;AAClB,CAAC,EAHW,SAAS,KAAT,SAAS,QAGpB;AAED,MAAM,CAAN,IAAY,gBAMX;AAND,WAAY,gBAAgB;IACxB,6CAAyB,CAAA;IACzB,iCAAa,CAAA;IACb,uCAAmB,CAAA;IACnB,qCAAiB,CAAA;IACjB,uCAAmB,CAAA;AACvB,CAAC,EANW,gBAAgB,KAAhB,gBAAgB,QAM3B;AAED,MAAM,OAAO,MAAM;IACf,UAAU,CAAa;IAEvB,YAAY,UAAsB;QAC9B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,cAAc,CAAyD,IAAY;QACrF,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAA2B,IAAI,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,GAAG;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;IACxC,CAAC;IAED,MAAM;QACF,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,CAAC;IAC1C,CAAC;IAED,OAAO;QACH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,cAAc,CAAyD,IAAY,EAAE,IAAY;QAC7F,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAA2B,IAAI,EAAE,IAAa,CAAC,CAAC;IAC5F,CAAC;IAED,mBAAmB;QACf,IAAI,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,EAAE;gBAAE,OAAO,gBAAgB,CAAC,OAAO,CAAC;YACzC,QAAQ,EAAE,CAAC,UAAU,EAAE,CAAC;gBACpB,KAAK,CAAC;oBACF,OAAO,gBAAgB,CAAC,UAAU,CAAC;gBACvC,KAAK,CAAC;oBACF,OAAO,gBAAgB,CAAC,IAAI,CAAC;gBACjC,KAAK,CAAC;oBACF,OAAO,gBAAgB,CAAC,OAAO,CAAC;gBACpC,KAAK,CAAC;oBACF,OAAO,gBAAgB,CAAC,MAAM,CAAC;gBACnC;oBACI,OAAO,gBAAgB,CAAC,OAAO,CAAC;YACxC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,gBAAgB,CAAC,OAAO,CAAC;QACpC,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,74 @@
1
+ import { AxiosResponse } from 'axios';
2
+ import { CloseCodes } from './connection.js';
3
+ import { Socket, SocketErr } from './Socket.js';
4
+ import { R } from './utils/index.js';
5
+ import { Err, Ok, Result } from './utils/result.js';
6
+ export declare const axiosService: import("axios").AxiosStatic;
7
+ export interface FileInfo {
8
+ name: string;
9
+ size: number;
10
+ mimetype: string;
11
+ id?: string;
12
+ userId: string;
13
+ }
14
+ export interface ClientOptions {
15
+ hp?: number;
16
+ host: string;
17
+ wsHost: string;
18
+ mount?: string;
19
+ token?: string;
20
+ }
21
+ export declare enum ConnectFail {
22
+ Unexpected = "Unexpected",
23
+ Unauthorized = "Unauthorized",
24
+ NotFound = "NotFound",
25
+ Denied = "Denied"
26
+ }
27
+ export declare enum AgentClientErrorType {
28
+ Communication = "Communication",
29
+ Execution = "Execution"
30
+ }
31
+ export declare abstract class AgentClientError {
32
+ abstract type: AgentClientErrorType;
33
+ }
34
+ export declare class CommunicationClientAgentError<E = unknown> implements AgentClientError {
35
+ readonly e: E;
36
+ readonly type = AgentClientErrorType.Communication;
37
+ constructor(e: E);
38
+ }
39
+ export declare class ExecutionClientAgentError<E = unknown> implements AgentClientError {
40
+ readonly e: E;
41
+ readonly type = AgentClientErrorType.Execution;
42
+ constructor(e: E);
43
+ }
44
+ export declare class AgentClient {
45
+ private socket;
46
+ constructor(socket: Socket);
47
+ onTask<TTask = unknown, TResult = unknown, TError = unknown>(name: string): Promise<Result<[TTask, (value: Result<TResult, TError>) => R], SocketErr>>;
48
+ destroy(): void;
49
+ post<TData = unknown, TResult = unknown, E = unknown>(name: string, data: TData, hp?: number): Promise<Result<TResult, AgentClientError>>;
50
+ waitClose(): Promise<CloseCodes>;
51
+ }
52
+ export declare class Client {
53
+ private readonly mount;
54
+ private readonly token;
55
+ private readonly host;
56
+ private readonly wsHost;
57
+ private readonly hp?;
58
+ constructor({ host, wsHost, mount, token, hp }: ClientOptions);
59
+ auth<TAuthData = unknown, TAuthResponse = unknown, TErr = unknown>(data: TAuthData): Promise<Result<AxiosResponse<TAuthResponse>, TErr>>;
60
+ gauth<TResponse = unknown, TErr = unknown>(access_token: string): Promise<Result<AxiosResponse<TResponse>, TErr | void>>;
61
+ deauth(): Promise<Ok<void> | Err<void, void>>;
62
+ request2FA<T = unknown, E = unknown>(): Promise<Result<AxiosResponse<T>, E>>;
63
+ enable2FA<T = unknown, E = unknown>(secret: string, code: string): Promise<Result<AxiosResponse<T>, E>>;
64
+ verify2FA<T = unknown, E = unknown>(accountName: string, code: string, uuid: string): Promise<Result<AxiosResponse<T>, E>>;
65
+ disable2FA<T = unknown, E = unknown>(): Promise<Result<AxiosResponse<T>, E>>;
66
+ upload(file: string | Blob): Promise<Result<FileInfo, void>>;
67
+ getFileLink(file: string | FileInfo): string;
68
+ getPresignedUploadUrl<T = unknown, E = unknown>(): Promise<Result<AxiosResponse<T>, E>>;
69
+ getPresignedDownloadUrl<T = unknown, E = unknown>(fileId: string): Promise<Result<AxiosResponse<T>, E>>;
70
+ private reconnect;
71
+ connectAgent(): Promise<Result<AgentClient, ConnectFail>>;
72
+ connect(name: string, arg?: string): Promise<Result<Socket, ConnectFail>>;
73
+ }
74
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,226 @@
1
+ import axios from 'axios';
2
+ import WS from 'websocket';
3
+ import { CloseCodes, Connection, WsCloseCodes } from './connection.js';
4
+ import { Socket } from './Socket.js';
5
+ import { err, ok, once, trimSlash, wrap } from './utils/index.js';
6
+ import { deal, Err, Ok } from './utils/result.js';
7
+ export const axiosService = axios;
8
+ export var ConnectFail;
9
+ (function (ConnectFail) {
10
+ ConnectFail["Unexpected"] = "Unexpected";
11
+ ConnectFail["Unauthorized"] = "Unauthorized";
12
+ ConnectFail["NotFound"] = "NotFound";
13
+ ConnectFail["Denied"] = "Denied";
14
+ })(ConnectFail || (ConnectFail = {}));
15
+ export var AgentClientErrorType;
16
+ (function (AgentClientErrorType) {
17
+ AgentClientErrorType["Communication"] = "Communication";
18
+ AgentClientErrorType["Execution"] = "Execution";
19
+ })(AgentClientErrorType || (AgentClientErrorType = {}));
20
+ export class AgentClientError {
21
+ }
22
+ export class CommunicationClientAgentError {
23
+ e;
24
+ type = AgentClientErrorType.Communication;
25
+ constructor(e) {
26
+ this.e = e;
27
+ }
28
+ }
29
+ export class ExecutionClientAgentError {
30
+ e;
31
+ type = AgentClientErrorType.Execution;
32
+ constructor(e) {
33
+ this.e = e;
34
+ }
35
+ }
36
+ export class AgentClient {
37
+ socket;
38
+ constructor(socket) {
39
+ this.socket = socket;
40
+ }
41
+ async onTask(name) {
42
+ const streamResult = await this.socket.incomingStream(name);
43
+ if (streamResult.isErr()) {
44
+ return new Err(streamResult.e);
45
+ }
46
+ const stream = streamResult.unwrap();
47
+ const [promise, resolve] = deal();
48
+ once(async () => {
49
+ const result = await promise;
50
+ await stream.write(result.serialize());
51
+ });
52
+ return new Ok([stream.args, resolve]);
53
+ }
54
+ destroy() {
55
+ this.socket.destroy();
56
+ }
57
+ async post(name, data, hp = 10) {
58
+ const stream = await this.socket.outgoingStream('post', { name, data });
59
+ if (stream.isErr()) {
60
+ return new Err(new CommunicationClientAgentError(stream.e));
61
+ }
62
+ const readResult = await stream.unwrap().read(hp);
63
+ if (readResult.isErr()) {
64
+ return new Err(new CommunicationClientAgentError(readResult.e));
65
+ }
66
+ const read = readResult.unwrap();
67
+ if (typeof read !== 'object' || read === null || !('ok' in read)) {
68
+ return new Err(new CommunicationClientAgentError('Format'));
69
+ }
70
+ if (read.ok === true) {
71
+ return new Ok(read.v);
72
+ }
73
+ return new Err(new ExecutionClientAgentError(read.e));
74
+ }
75
+ async waitClose() {
76
+ return await this.socket.waitClose();
77
+ }
78
+ }
79
+ export class Client {
80
+ mount;
81
+ token;
82
+ host;
83
+ wsHost;
84
+ hp;
85
+ constructor({ host, wsHost, mount, token, hp }) {
86
+ this.mount = mount ? `/${trimSlash(mount)}` : '';
87
+ this.token = token ? `ws-token/${token}` : 'ws';
88
+ this.host = host;
89
+ this.wsHost = wsHost;
90
+ this.hp = hp;
91
+ }
92
+ async auth(data) {
93
+ const res = await wrap(axios.post(`${this.host}${this.mount}/auth`, data));
94
+ if (res.isOk())
95
+ return new Ok(res.v);
96
+ return new Err(res.e);
97
+ }
98
+ async gauth(access_token) {
99
+ if (!this.token)
100
+ return new Err(undefined);
101
+ const res = await wrap(axios.post(`${this.host}${this.mount}/gauth`, { access_token }));
102
+ if (res.isOk())
103
+ return new Ok(res.v);
104
+ return new Err(res.e);
105
+ }
106
+ async deauth() {
107
+ const res = await wrap(axios.delete(`${this.host}${this.mount}/auth`));
108
+ if (res.isOk())
109
+ return ok();
110
+ return err();
111
+ }
112
+ async request2FA() {
113
+ const res = await wrap(axios.post(`${this.host}${this.mount}/2fa/request`));
114
+ if (res.isOk())
115
+ return new Ok(res.v);
116
+ return new Err(res.e);
117
+ }
118
+ async enable2FA(secret, code) {
119
+ const res = await wrap(axios.post(`${this.host}${this.mount}/2fa/enable`, { secret, code }));
120
+ if (res.isOk())
121
+ return new Ok(res.v);
122
+ return new Err(res.e);
123
+ }
124
+ async verify2FA(accountName, code, uuid) {
125
+ const res = await wrap(axios.post(`${this.host}${this.mount}/2fa/verify`, { accountName, code, uuid }));
126
+ if (res.isOk())
127
+ return new Ok(res.v);
128
+ return new Err(res.e);
129
+ }
130
+ async disable2FA() {
131
+ const res = await wrap(axios.delete(`${this.host}${this.mount}/2fa/disable`));
132
+ if (res.isOk())
133
+ return new Ok(res.v);
134
+ return new Err(res.e);
135
+ }
136
+ async upload(file) {
137
+ const form = new FormData();
138
+ form.append('file', file);
139
+ const options = this.token ? { headers: { 'x-token': this.token } } : undefined;
140
+ const res = await wrap(axios.post(`${this.host}${this.mount}/file`, form, options));
141
+ if (res.isOk())
142
+ return new Ok(res.v.data);
143
+ return new Err(undefined);
144
+ }
145
+ getFileLink(file) {
146
+ if (typeof file === 'string') {
147
+ return `${this.host}${this.mount}/file/${file}`;
148
+ }
149
+ return `${this.host}${this.mount}/file/${file.id}/${file.name}`;
150
+ }
151
+ async getPresignedUploadUrl() {
152
+ const res = await wrap(axios.post(`${this.host}${this.mount}/storage/upload`));
153
+ if (res.isOk())
154
+ return new Ok(res.v);
155
+ return new Err(res.e);
156
+ }
157
+ async getPresignedDownloadUrl(fileId) {
158
+ const res = await wrap(axios.get(`${this.host}${this.mount}/storage/${fileId}`));
159
+ if (res.isOk())
160
+ return new Ok(res.v);
161
+ return new Err(res.e);
162
+ }
163
+ reconnect(url, connection) {
164
+ const ws = new WS.w3cwebsocket(url);
165
+ connection.connect(ws, false);
166
+ }
167
+ async connectAgent() {
168
+ const socket = await this.connect('agent');
169
+ if (socket.isErr()) {
170
+ return new Err(socket.e);
171
+ }
172
+ return new Ok(new AgentClient(socket.unwrap()));
173
+ }
174
+ connect(name, arg) {
175
+ const pathArg = arg ? `/${arg}` : '';
176
+ const url = `${this.wsHost}${this.mount}/${this.token}/${name}${pathArg}`;
177
+ let connection;
178
+ const [promise, resolve] = deal();
179
+ const inter = {
180
+ hp: this.hp,
181
+ onDestroy: function () { },
182
+ onDisconnect: (code) => {
183
+ switch (code) {
184
+ case WsCloseCodes.ConcurrentConnection: {
185
+ resolve(new Err(ConnectFail.Unexpected));
186
+ connection.destroy(CloseCodes.Concurrent);
187
+ break;
188
+ }
189
+ case WsCloseCodes.Denied: {
190
+ resolve(new Err(ConnectFail.Denied));
191
+ connection.destroy(CloseCodes.Unauthorized);
192
+ break;
193
+ }
194
+ case WsCloseCodes.Normal: {
195
+ resolve(new Err(ConnectFail.Unexpected));
196
+ connection.destroy(CloseCodes.Intentional);
197
+ break;
198
+ }
199
+ case WsCloseCodes.Unauthorized: {
200
+ resolve(new Err(ConnectFail.Unauthorized));
201
+ connection.destroy(CloseCodes.Unauthorized);
202
+ break;
203
+ }
204
+ case WsCloseCodes.NotFound: {
205
+ resolve(new Err(ConnectFail.NotFound));
206
+ connection.destroy(CloseCodes.Unexpected);
207
+ break;
208
+ }
209
+ default: {
210
+ setTimeout(() => {
211
+ this.reconnect(url, connection);
212
+ }, 500);
213
+ break;
214
+ }
215
+ }
216
+ },
217
+ onAccept: () => {
218
+ resolve(new Ok(new Socket(connection)));
219
+ },
220
+ };
221
+ connection = new Connection(inter, arg ?? '');
222
+ this.reconnect(url, connection);
223
+ return promise;
224
+ }
225
+ }
226
+ //# sourceMappingURL=client.js.map