dolphin-client 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 +15 -0
- package/README.md +100 -0
- package/dist/a11y.d.ts +1 -0
- package/dist/animation.d.ts +1 -0
- package/dist/api.d.ts +30 -0
- package/dist/api.js +112 -0
- package/dist/auth.d.ts +56 -0
- package/dist/auth.js +120 -0
- package/dist/collab.d.ts +1 -0
- package/dist/core.d.ts +119 -0
- package/dist/core.js +345 -0
- package/dist/dolphin-client.js +2042 -0
- package/dist/dom.d.ts +1 -0
- package/dist/dom.js +316 -0
- package/dist/dragdrop.d.ts +1 -0
- package/dist/i18n.d.ts +1 -0
- package/dist/index.cjs +2040 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +2018 -0
- package/dist/offline.d.ts +24 -0
- package/dist/pwa.d.ts +1 -0
- package/dist/store.d.ts +22 -0
- package/dist/store.js +131 -0
- package/dist/testing.d.ts +20 -0
- package/dist/validation.d.ts +2 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shankar Phuyal
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARDARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# dolphin-client π¬ β HTML is back!
|
|
2
|
+
|
|
3
|
+
**Hookless, framework-agnostic, zero-dependency real-time reactive DOM-binding engine.**
|
|
4
|
+
|
|
5
|
+
Unleash the full power of modern native browser APIs and DolphinCSS without the heavy framework tax of React or Vue!
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
### π Returning Home: A Love Letter to HTML
|
|
10
|
+
|
|
11
|
+
Remember the early days of your coding journey? Writing a simple `index.html` in a plain text editor, double-clicking it, and watching it open instantly in the browser. No complex build pipelines, no `node_modules` weighing hundreds of megabytes, no state hooks, and no framework fatigue. Just a direct, pure, and magical relationship between your markup and the browser.
|
|
12
|
+
|
|
13
|
+
Over the last decade, we treated HTML as a dead, passive mounting point (`<div id="root"></div>`) while building virtual universes in JavaScript. We spent 80% of our time debugging configurations and boilerplate, and only 20% building beautiful user experiences.
|
|
14
|
+
|
|
15
|
+
**Dolphin Client is our way of coming home.**
|
|
16
|
+
|
|
17
|
+
By breathing life back into standard HTML, we have resurrected the simplicity of standard markup and empowered it with the modern superpowers of WebSockets, IndexedDB, WebRTC, and hardware-accelerated CSS variables. It is the renaissance of the native web standards we all fell in love with.
|
|
18
|
+
|
|
19
|
+
*Because the best JavaScript is actually the code you never had to write.*
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Hookless Reactivity**: Bind topics to DOM elements via HTML data attributesβno React, Vue, or Angular state management required.
|
|
26
|
+
- **Unified Event Binding**: Loop-based browser event handling for values (`data-rt-push`) and actions (`data-rt-[event]` / `data-api-[event]`).
|
|
27
|
+
- **Context API/Prop drilling in Pure DOM**: Crawls up the DOM tree (`getClosestContext`) to fetch parent contexts and inject parameters.
|
|
28
|
+
- **REST API + Realtime Hybrid Support**: Evaluates templates (`data-rt-template`) on initial HTTP fetches (`data-api-get`) and transitions seamlessly to real-time WebSockets on connection.
|
|
29
|
+
- **WebRTC Intercom Signaling**: Built-in methods to handle peer connections, track negotiation, ICE candidates, and signaling.
|
|
30
|
+
- **Ultralight weight**: Zero external dependencies, pure browser-native runtime APIs.
|
|
31
|
+
|
|
32
|
+
### Method 1: NPM (For Modern Bundlers)
|
|
33
|
+
```bash
|
|
34
|
+
npm install dolphin-client
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Method 2: Direct Local Download (For No-Install / Plain HTML)
|
|
38
|
+
Tired of the command line and `node_modules` clutter? We've got you covered!
|
|
39
|
+
|
|
40
|
+
[](https://unpkg.com/dolphin-client/dist/dolphin-client.js) [](https://github.com/Phuyalshankar/dolphin-server-modules/releases/latest/download/dolphin-bundle.zip)
|
|
41
|
+
|
|
42
|
+
*(Right-click on **dolphin-client.js** and select "Save Link As..." to save it directly to your project)*
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Extract the zip directly inside your project folder to get a clean local directory structure with pre-bundled assets:
|
|
46
|
+
```
|
|
47
|
+
my-project/
|
|
48
|
+
βββ css/
|
|
49
|
+
β βββ dolphin-css.css (DolphinCSS Premium Visuals Layer)
|
|
50
|
+
βββ js/
|
|
51
|
+
β βββ dolphin-client.js (Dolphin Reactivity Engine)
|
|
52
|
+
βββ index.html (A ready-to-run skeleton template!)
|
|
53
|
+
```
|
|
54
|
+
Inside your HTML, simply link them locally:
|
|
55
|
+
```html
|
|
56
|
+
<link rel="stylesheet" href="css/dolphin-css.css">
|
|
57
|
+
<script src="js/dolphin-client.js"></script>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Basic Usage
|
|
61
|
+
|
|
62
|
+
### 1. In Modern Bundlers (Next.js, Vite, React)
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
import { DolphinClient } from 'dolphin-client';
|
|
66
|
+
|
|
67
|
+
const dolphin = new DolphinClient('http://localhost:3000', 'ROOM_101');
|
|
68
|
+
await dolphin.connect();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 2. In Plain HTML (Static / Script Tag)
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<script src="node_modules/dolphin-client/dist/dolphin-client.js"></script>
|
|
75
|
+
<script>
|
|
76
|
+
const dolphin = new DolphinModule.DolphinClient('http://localhost:3000', 'ROOM_101');
|
|
77
|
+
dolphin.connect();
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## HTML Directives
|
|
82
|
+
|
|
83
|
+
### Pushing value changes
|
|
84
|
+
```html
|
|
85
|
+
<input name="chat" data-rt-push="chat/messages/ROOM_101" placeholder="Type..." />
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Directives & Templates
|
|
89
|
+
```html
|
|
90
|
+
<div data-api-get="/api/devices" data-rt-bind="devices/online" data-rt-template='
|
|
91
|
+
<div data-rt-type="context">
|
|
92
|
+
<h3>{{id}}</h3>
|
|
93
|
+
<button onclick="dialPeer('{{id}}')">Dial</button>
|
|
94
|
+
</div>
|
|
95
|
+
'></div>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
ISC License
|
package/dist/a11y.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function attachA11y(clientProto: any): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function attachAnimations(clientProto: any): void;
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare class APIHandler {
|
|
2
|
+
client: any;
|
|
3
|
+
/** @param {DolphinClient} client */
|
|
4
|
+
constructor(client: any);
|
|
5
|
+
/** @private */
|
|
6
|
+
_createProxy(pathParts: any): {
|
|
7
|
+
(options: any): any;
|
|
8
|
+
get(pathOrOptions: any, options: any): any;
|
|
9
|
+
post(pathOrBody: any, bodyOrOptions: any, options: any): any;
|
|
10
|
+
put(pathOrBody: any, bodyOrOptions: any, options: any): any;
|
|
11
|
+
patch(pathOrBody: any, bodyOrOptions: any, options: any): any;
|
|
12
|
+
del(pathOrOptions: any, options: any): any;
|
|
13
|
+
request(method: any, subPath: any, body: any, options: any): any;
|
|
14
|
+
requestDirect(method: any, path: any, body: any, options: any): any;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Intercept request for offline-first caching and queuing.
|
|
18
|
+
*/
|
|
19
|
+
request(method: string, path: string, body?: any, options?: any): any;
|
|
20
|
+
/**
|
|
21
|
+
* Make an HTTP request with timeout + auto token refresh.
|
|
22
|
+
* @param {string} method
|
|
23
|
+
* @param {string} path
|
|
24
|
+
* @param {any} [body]
|
|
25
|
+
* @param {RequestInit} [options]
|
|
26
|
+
* @param {boolean} [_isRetry=false] β internal: prevent infinite refresh loop
|
|
27
|
+
* @returns {Promise<any>}
|
|
28
|
+
*/
|
|
29
|
+
requestDirect(method: any, path: any, body?: any, options?: any): any;
|
|
30
|
+
}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export class APIHandler {
|
|
2
|
+
/** @param {DolphinClient} client */
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
return this._createProxy([]);
|
|
6
|
+
}
|
|
7
|
+
/** @private */
|
|
8
|
+
_createProxy(pathParts) {
|
|
9
|
+
const joined = pathParts.join('/');
|
|
10
|
+
const target = (options) => this.request('GET', joined, null, options);
|
|
11
|
+
target.get = (pathOrOptions, options) => typeof pathOrOptions === 'string'
|
|
12
|
+
? this.request('GET', pathOrOptions, null, options)
|
|
13
|
+
: this.request('GET', joined, null, pathOrOptions);
|
|
14
|
+
target.post = (pathOrBody, bodyOrOptions, options) => typeof pathOrBody === 'string'
|
|
15
|
+
? this.request('POST', pathOrBody, bodyOrOptions, options)
|
|
16
|
+
: this.request('POST', joined, pathOrBody, bodyOrOptions);
|
|
17
|
+
target.put = (pathOrBody, bodyOrOptions, options) => typeof pathOrBody === 'string'
|
|
18
|
+
? this.request('PUT', pathOrBody, bodyOrOptions, options)
|
|
19
|
+
: this.request('PUT', joined, pathOrBody, bodyOrOptions);
|
|
20
|
+
target.patch = (pathOrBody, bodyOrOptions, options) => typeof pathOrBody === 'string'
|
|
21
|
+
? this.request('PATCH', pathOrBody, bodyOrOptions, options)
|
|
22
|
+
: this.request('PATCH', joined, pathOrBody, bodyOrOptions);
|
|
23
|
+
target.del = (pathOrOptions, options) => typeof pathOrOptions === 'string'
|
|
24
|
+
? this.request('DELETE', pathOrOptions, null, options)
|
|
25
|
+
: this.request('DELETE', joined, null, pathOrOptions);
|
|
26
|
+
target.request = (method, subPath, body, options) => {
|
|
27
|
+
const finalPath = subPath
|
|
28
|
+
? `${joined}/${subPath.startsWith('/') ? subPath.slice(1) : subPath}`
|
|
29
|
+
: joined;
|
|
30
|
+
return this.request(method, finalPath, body, options);
|
|
31
|
+
};
|
|
32
|
+
const methods = ['get', 'post', 'put', 'patch', 'del', 'request'];
|
|
33
|
+
return new Proxy(target, {
|
|
34
|
+
get: (t, prop) => {
|
|
35
|
+
if (typeof prop === 'string' && !methods.includes(prop)) {
|
|
36
|
+
return this._createProxy([...pathParts, prop]);
|
|
37
|
+
}
|
|
38
|
+
return t[prop];
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Make an HTTP request with timeout + auto token refresh.
|
|
44
|
+
* @param {string} method
|
|
45
|
+
* @param {string} path
|
|
46
|
+
* @param {any} [body]
|
|
47
|
+
* @param {RequestInit} [options]
|
|
48
|
+
* @param {boolean} [_isRetry=false] β internal: prevent infinite refresh loop
|
|
49
|
+
* @returns {Promise<any>}
|
|
50
|
+
*/
|
|
51
|
+
async request(method, path, body = null, options = {}) {
|
|
52
|
+
const _isRetry = options._isRetry === true;
|
|
53
|
+
const url = `${this.client.httpUrl}${path.startsWith('/') ? path : '/' + path}`;
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
const timeoutId = setTimeout(() => controller.abort(), this.client.options.timeout);
|
|
56
|
+
const headers = {
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
...(options.headers || {}),
|
|
59
|
+
};
|
|
60
|
+
if (this.client.accessToken) {
|
|
61
|
+
headers['Authorization'] = `Bearer ${this.client.accessToken}`;
|
|
62
|
+
}
|
|
63
|
+
const fetchOptions = { ...options };
|
|
64
|
+
delete fetchOptions._isRetry;
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(url, {
|
|
67
|
+
method,
|
|
68
|
+
headers,
|
|
69
|
+
signal: controller.signal,
|
|
70
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
71
|
+
...fetchOptions,
|
|
72
|
+
});
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
// Auto-refresh: 401 + not a retry + autoRefreshToken enabled
|
|
75
|
+
if (response.status === 401 &&
|
|
76
|
+
!_isRetry &&
|
|
77
|
+
this.client.options.autoRefreshToken) {
|
|
78
|
+
const refreshed = await this.client.auth._silentRefresh();
|
|
79
|
+
if (refreshed) {
|
|
80
|
+
return this.request(method, path, body, { ...options, _isRetry: true });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const contentType = response.headers.get('content-type') || '';
|
|
84
|
+
const data = contentType.includes('application/json')
|
|
85
|
+
? await response.json()
|
|
86
|
+
: await response.text();
|
|
87
|
+
if (!response.ok)
|
|
88
|
+
throw { status: response.status, data };
|
|
89
|
+
// Hookless auth token auto-save
|
|
90
|
+
if (data && typeof data === 'object') {
|
|
91
|
+
if (data.accessToken) {
|
|
92
|
+
this.client.setToken(data.accessToken);
|
|
93
|
+
if (data.user)
|
|
94
|
+
this.client.auth.user = data.user;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Auto-broadcast data changes
|
|
98
|
+
if (this.client.options.autoBroadcast && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method.toUpperCase())) {
|
|
99
|
+
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
|
100
|
+
this.client.publish(cleanPath, { method: method.toUpperCase(), payload: body, result: data });
|
|
101
|
+
}
|
|
102
|
+
return data;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
clearTimeout(timeoutId);
|
|
106
|
+
if (err.name === 'AbortError') {
|
|
107
|
+
throw { status: 408, data: { error: 'Request timed out' } };
|
|
108
|
+
}
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare class AuthHandler {
|
|
2
|
+
client: any;
|
|
3
|
+
user: any;
|
|
4
|
+
_refreshing: boolean;
|
|
5
|
+
/** @param {DolphinClient} client */
|
|
6
|
+
constructor(client: any);
|
|
7
|
+
/**
|
|
8
|
+
* Login with email + password.
|
|
9
|
+
* @param {string} email
|
|
10
|
+
* @param {string} password
|
|
11
|
+
*/
|
|
12
|
+
login(email: any, password: any): Promise<any>;
|
|
13
|
+
/**
|
|
14
|
+
* Register a new account.
|
|
15
|
+
* @param {{ email: string, password: string, [key: string]: any }} data
|
|
16
|
+
*/
|
|
17
|
+
register(data: any): Promise<any>;
|
|
18
|
+
/** Get current user profile. */
|
|
19
|
+
me(): Promise<any>;
|
|
20
|
+
/** Logout and clear token. */
|
|
21
|
+
logout(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Manually refresh the access token using the httpOnly refresh-token cookie.
|
|
24
|
+
* Called automatically on 401 if autoRefreshToken is enabled.
|
|
25
|
+
* @returns {Promise<boolean>} β true if refresh succeeded
|
|
26
|
+
*/
|
|
27
|
+
refresh(): Promise<boolean>;
|
|
28
|
+
/** @private */
|
|
29
|
+
_silentRefresh(): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Verify a 2FA TOTP code after login.
|
|
32
|
+
* @param {string} code β 6-digit TOTP code
|
|
33
|
+
* @param {string} [email] β email (if not already in user)
|
|
34
|
+
*/
|
|
35
|
+
verify2FA(code: any, email: any): Promise<any>;
|
|
36
|
+
/**
|
|
37
|
+
* Enable 2FA β returns QR code URL and secret.
|
|
38
|
+
*/
|
|
39
|
+
enable2FA(): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Disable 2FA.
|
|
42
|
+
* @param {string} code β current TOTP code to confirm
|
|
43
|
+
*/
|
|
44
|
+
disable2FA(code: any): Promise<any>;
|
|
45
|
+
/**
|
|
46
|
+
* Request a password reset email.
|
|
47
|
+
* @param {string} email
|
|
48
|
+
*/
|
|
49
|
+
forgotPassword(email: any): Promise<any>;
|
|
50
|
+
/**
|
|
51
|
+
* Reset password using the token from email.
|
|
52
|
+
* @param {string} token
|
|
53
|
+
* @param {string} newPassword
|
|
54
|
+
*/
|
|
55
|
+
resetPassword(token: any, newPassword: any): Promise<any>;
|
|
56
|
+
}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export class AuthHandler {
|
|
2
|
+
/** @param {DolphinClient} client */
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
/** @type {any|null} */
|
|
6
|
+
this.user = null;
|
|
7
|
+
this._refreshing = false;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Login with email + password.
|
|
11
|
+
* @param {string} email
|
|
12
|
+
* @param {string} password
|
|
13
|
+
*/
|
|
14
|
+
async login(email, password) {
|
|
15
|
+
const res = await this.client.api.post('/api/auth/login', { email, password });
|
|
16
|
+
if (res.accessToken) {
|
|
17
|
+
this.client.setToken(res.accessToken);
|
|
18
|
+
this.user = res.user || null;
|
|
19
|
+
}
|
|
20
|
+
return res;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Register a new account.
|
|
24
|
+
* @param {{ email: string, password: string, [key: string]: any }} data
|
|
25
|
+
*/
|
|
26
|
+
async register(data) {
|
|
27
|
+
return this.client.api.post('/api/auth/register', data);
|
|
28
|
+
}
|
|
29
|
+
/** Get current user profile. */
|
|
30
|
+
async me() {
|
|
31
|
+
const res = await this.client.api.get('/api/auth/me');
|
|
32
|
+
if (res.success)
|
|
33
|
+
this.user = res.data;
|
|
34
|
+
return res;
|
|
35
|
+
}
|
|
36
|
+
/** Logout and clear token. */
|
|
37
|
+
async logout() {
|
|
38
|
+
try {
|
|
39
|
+
await this.client.api.post('/api/auth/logout');
|
|
40
|
+
}
|
|
41
|
+
catch { }
|
|
42
|
+
this.client.setToken(null);
|
|
43
|
+
this.user = null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Manually refresh the access token using the httpOnly refresh-token cookie.
|
|
47
|
+
* Called automatically on 401 if autoRefreshToken is enabled.
|
|
48
|
+
* @returns {Promise<boolean>} β true if refresh succeeded
|
|
49
|
+
*/
|
|
50
|
+
async refresh() {
|
|
51
|
+
return this._silentRefresh();
|
|
52
|
+
}
|
|
53
|
+
/** @private */
|
|
54
|
+
async _silentRefresh() {
|
|
55
|
+
if (this._refreshing)
|
|
56
|
+
return false;
|
|
57
|
+
this._refreshing = true;
|
|
58
|
+
try {
|
|
59
|
+
const res = await this.client.api.post('/api/auth/refresh', null, { _isRetry: true });
|
|
60
|
+
if (res.accessToken) {
|
|
61
|
+
this.client.setToken(res.accessToken);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
this.client.setToken(null);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
this._refreshing = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Verify a 2FA TOTP code after login.
|
|
76
|
+
* @param {string} code β 6-digit TOTP code
|
|
77
|
+
* @param {string} [email] β email (if not already in user)
|
|
78
|
+
*/
|
|
79
|
+
async verify2FA(code, email) {
|
|
80
|
+
const payload = {
|
|
81
|
+
code,
|
|
82
|
+
email: email || this.user?.email,
|
|
83
|
+
};
|
|
84
|
+
const res = await this.client.api.post('/api/auth/2fa/verify', payload);
|
|
85
|
+
if (res.accessToken) {
|
|
86
|
+
this.client.setToken(res.accessToken);
|
|
87
|
+
if (res.user)
|
|
88
|
+
this.user = res.user;
|
|
89
|
+
}
|
|
90
|
+
return res;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Enable 2FA β returns QR code URL and secret.
|
|
94
|
+
*/
|
|
95
|
+
async enable2FA() {
|
|
96
|
+
return this.client.api.post('/api/auth/2fa/enable');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Disable 2FA.
|
|
100
|
+
* @param {string} code β current TOTP code to confirm
|
|
101
|
+
*/
|
|
102
|
+
async disable2FA(code) {
|
|
103
|
+
return this.client.api.post('/api/auth/2fa/disable', { code });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Request a password reset email.
|
|
107
|
+
* @param {string} email
|
|
108
|
+
*/
|
|
109
|
+
async forgotPassword(email) {
|
|
110
|
+
return this.client.api.post('/api/auth/forgot-password', { email });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Reset password using the token from email.
|
|
114
|
+
* @param {string} token
|
|
115
|
+
* @param {string} newPassword
|
|
116
|
+
*/
|
|
117
|
+
async resetPassword(token, newPassword) {
|
|
118
|
+
return this.client.api.post('/api/auth/reset-password', { token, newPassword });
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/collab.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function attachCollab(clientProto: any): void;
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export declare class DolphinClient {
|
|
2
|
+
host: string;
|
|
3
|
+
httpUrl: string;
|
|
4
|
+
deviceId: string;
|
|
5
|
+
options: any;
|
|
6
|
+
socket: any;
|
|
7
|
+
storage: any;
|
|
8
|
+
accessToken: string | null;
|
|
9
|
+
api: any;
|
|
10
|
+
auth: any;
|
|
11
|
+
store: any;
|
|
12
|
+
handlers: Map<string, Set<any>>;
|
|
13
|
+
signalHandlers: Set<any>;
|
|
14
|
+
fileHandlers: Set<any>;
|
|
15
|
+
_offlineQueue: string[];
|
|
16
|
+
reconnectAttempts: number;
|
|
17
|
+
_attachedListeners: {
|
|
18
|
+
target: any;
|
|
19
|
+
event: string;
|
|
20
|
+
cb: any;
|
|
21
|
+
}[];
|
|
22
|
+
constructor(url?: string, deviceId?: string, options?: {});
|
|
23
|
+
/** Save or clear the access token */
|
|
24
|
+
setToken(token: any): void;
|
|
25
|
+
/** Connect to the Dolphin realtime server */
|
|
26
|
+
connect(): Promise<void>;
|
|
27
|
+
/** Disconnect cleanly */
|
|
28
|
+
disconnect(): void;
|
|
29
|
+
/** @private */
|
|
30
|
+
_handleMessage(data: any): void;
|
|
31
|
+
/** @private */
|
|
32
|
+
_dispatch(pattern: any, payload: any, topic?: any): void;
|
|
33
|
+
/** @private */
|
|
34
|
+
_sendRaw(msg: any): void;
|
|
35
|
+
/** Flush buffered messages after reconnect @private */
|
|
36
|
+
_flushOfflineQueue(): void;
|
|
37
|
+
/** @private */
|
|
38
|
+
_sendAck(to: any, msgId: any): void;
|
|
39
|
+
/** MQTT wildcard topic matching @private */
|
|
40
|
+
_matchTopic(pattern: any, topic: any): boolean;
|
|
41
|
+
/** @private */
|
|
42
|
+
_maybeReconnect(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Subscribe to a topic (MQTT wildcards supported: + and #).
|
|
45
|
+
* @param {string} topic
|
|
46
|
+
* @param {TopicCallback} callback
|
|
47
|
+
*/
|
|
48
|
+
subscribe(topic: any, callback: any): void;
|
|
49
|
+
/**
|
|
50
|
+
* Unsubscribe from a topic.
|
|
51
|
+
* @param {string} topic
|
|
52
|
+
* @param {TopicCallback} callback
|
|
53
|
+
*/
|
|
54
|
+
unsubscribe(topic: any, callback: any): void;
|
|
55
|
+
/**
|
|
56
|
+
* Publish a message to a topic. Queued if offline.
|
|
57
|
+
* @param {string} topic
|
|
58
|
+
* @param {any} payload
|
|
59
|
+
*/
|
|
60
|
+
publish(topic: any, payload: any): void;
|
|
61
|
+
/**
|
|
62
|
+
* High-frequency data push (IoT sensors).
|
|
63
|
+
* @param {string} topic
|
|
64
|
+
* @param {any} payload
|
|
65
|
+
*/
|
|
66
|
+
pubPush(topic: any, payload: any): void;
|
|
67
|
+
/**
|
|
68
|
+
* Request historical data from a topic.
|
|
69
|
+
* @param {string} topic
|
|
70
|
+
* @param {number} [count=10]
|
|
71
|
+
*/
|
|
72
|
+
subPull(topic: any, count?: number): void;
|
|
73
|
+
/**
|
|
74
|
+
* Upload a file to the server in chunks.
|
|
75
|
+
* @param {string} fileId
|
|
76
|
+
* @param {Blob|ArrayBuffer|Uint8Array} fileData
|
|
77
|
+
* @param {string} [filename]
|
|
78
|
+
* @param {function(number): void} [onProgress] β progress callback (0-100)
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
pubFile(fileId: any, fileData: any, filename: string, onProgress: any): Promise<void>;
|
|
82
|
+
/** @private */
|
|
83
|
+
_uint8ToBase64(uint8: any): string;
|
|
84
|
+
/**
|
|
85
|
+
* Download a file from the server by chunks.
|
|
86
|
+
* @param {string} fileId
|
|
87
|
+
* @param {number} [startChunk=0]
|
|
88
|
+
*/
|
|
89
|
+
subFile(fileId: any, startChunk?: number): void;
|
|
90
|
+
/**
|
|
91
|
+
* Resume a file download from saved progress.
|
|
92
|
+
* @param {string} fileId
|
|
93
|
+
*/
|
|
94
|
+
resumeFile(fileId: any): void;
|
|
95
|
+
/**
|
|
96
|
+
* Save download chunk progress.
|
|
97
|
+
* @param {string} fileId
|
|
98
|
+
* @param {number} chunkIndex
|
|
99
|
+
*/
|
|
100
|
+
saveFileProgress(fileId: any, chunkIndex: any): void;
|
|
101
|
+
/**
|
|
102
|
+
* @param {function(SignalMessage): void} handler
|
|
103
|
+
*/
|
|
104
|
+
onSignal(handler: any): void;
|
|
105
|
+
/**
|
|
106
|
+
* @param {function(SignalMessage): void} handler
|
|
107
|
+
*/
|
|
108
|
+
offSignal(handler: any): void;
|
|
109
|
+
/**
|
|
110
|
+
* @param {function(FileMetadata): void} handler
|
|
111
|
+
*/
|
|
112
|
+
onFileAvailable(handler: any): void;
|
|
113
|
+
/**
|
|
114
|
+
* @param {function(FileMetadata): void} handler
|
|
115
|
+
*/
|
|
116
|
+
offFileAvailable(handler: any): void;
|
|
117
|
+
addDomListener(target: any, event: string, cb: any): void;
|
|
118
|
+
cleanupDomListeners(): void;
|
|
119
|
+
}
|