@sogni-ai/sogni-client 3.4.0-alpha.1 → 4.0.0-alpha.2
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/CHANGELOG.md +27 -0
- package/dist/Account/CurrentAccount.d.ts +2 -4
- package/dist/Account/CurrentAccount.js +4 -9
- package/dist/Account/CurrentAccount.js.map +1 -1
- package/dist/Account/index.d.ts +2 -30
- package/dist/Account/index.js +36 -49
- package/dist/Account/index.js.map +1 -1
- package/dist/Account/types.d.ts +11 -0
- package/dist/ApiClient/WebSocketClient/index.d.ts +1 -1
- package/dist/ApiClient/WebSocketClient/index.js +1 -10
- package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/index.d.ts +12 -5
- package/dist/ApiClient/index.js +17 -31
- package/dist/ApiClient/index.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +48 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/AuthManager/AuthManagerBase.d.ts +25 -0
- package/dist/lib/AuthManager/AuthManagerBase.js +14 -0
- package/dist/lib/AuthManager/AuthManagerBase.js.map +1 -0
- package/dist/lib/AuthManager/CookieAuthManager.d.ts +15 -0
- package/dist/lib/AuthManager/CookieAuthManager.js +53 -0
- package/dist/lib/AuthManager/CookieAuthManager.js.map +1 -0
- package/dist/lib/AuthManager/TokenAuthManager.d.ts +41 -0
- package/dist/lib/{AuthManager.js → AuthManager/TokenAuthManager.js} +96 -60
- package/dist/lib/AuthManager/TokenAuthManager.js.map +1 -0
- package/dist/lib/AuthManager/index.d.ts +5 -0
- package/dist/lib/AuthManager/index.js +11 -0
- package/dist/lib/AuthManager/index.js.map +1 -0
- package/dist/lib/RestClient.d.ts +1 -1
- package/dist/lib/RestClient.js +6 -2
- package/dist/lib/RestClient.js.map +1 -1
- package/package.json +1 -1
- package/src/Account/CurrentAccount.ts +5 -12
- package/src/Account/index.ts +34 -48
- package/src/Account/types.ts +12 -0
- package/src/ApiClient/WebSocketClient/index.ts +2 -11
- package/src/ApiClient/index.ts +35 -31
- package/src/index.ts +63 -9
- package/src/lib/AuthManager/AuthManagerBase.ts +37 -0
- package/src/lib/AuthManager/CookieAuthManager.ts +40 -0
- package/src/lib/{AuthManager.ts → AuthManager/TokenAuthManager.ts} +97 -77
- package/src/lib/AuthManager/index.ts +8 -0
- package/src/lib/RestClient.ts +7 -10
- package/dist/lib/AuthManager.d.ts +0 -51
- package/dist/lib/AuthManager.js.map +0 -1
|
@@ -1,100 +1,117 @@
|
|
|
1
|
-
import { decodeToken, decodeRefreshToken } from '
|
|
2
|
-
import { ApiError, ApiErrorResponse } from '
|
|
3
|
-
import { Logger } from '
|
|
4
|
-
import isNodejs from '
|
|
1
|
+
import { decodeToken, decodeRefreshToken } from '../utils';
|
|
2
|
+
import { ApiError, ApiErrorResponse } from '../../ApiClient';
|
|
3
|
+
import { Logger } from '../DefaultLogger';
|
|
4
|
+
import isNodejs from '../isNodejs';
|
|
5
5
|
import Cookie from 'js-cookie';
|
|
6
|
-
import
|
|
6
|
+
import AuthManagerBase from './AuthManagerBase';
|
|
7
|
+
import { ClientOptions } from 'ws';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
* @
|
|
11
|
-
* @property {string} [token] - The JWT token. Optonal, if missing it will be retrieved from the server
|
|
10
|
+
* Token object, containing the token and refresh token
|
|
11
|
+
* @property {string} token - The JWT token
|
|
12
12
|
* @property {string} refreshToken - The refresh token
|
|
13
13
|
*/
|
|
14
|
-
export interface
|
|
15
|
-
token
|
|
14
|
+
export interface TokenAuthData {
|
|
15
|
+
token: string;
|
|
16
16
|
refreshToken: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
| { token: string; refreshToken: string; walletAddress: string }
|
|
21
|
-
| { token: null; refreshToken: null; walletAddress: null };
|
|
22
|
-
|
|
23
|
-
interface AuthManagerEvents {
|
|
24
|
-
updated: AuthUpdatedEvent;
|
|
25
|
-
refreshFailed: ApiErrorResponse;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
|
|
19
|
+
class TokenAuthManager extends AuthManagerBase<TokenAuthData | null> {
|
|
29
20
|
private _token?: string;
|
|
30
21
|
private _tokenExpiresAt: Date = new Date(0);
|
|
31
22
|
private _refreshToken?: string;
|
|
32
23
|
private _refreshTokenExpiresAt: Date = new Date(0);
|
|
33
|
-
private _logger: Logger;
|
|
34
24
|
private _baseUrl: string;
|
|
35
|
-
private _walletAddress?: string;
|
|
36
25
|
private _renewTokenPromise?: Promise<string>;
|
|
37
26
|
|
|
38
27
|
constructor(baseUrl: string, logger: Logger) {
|
|
39
|
-
super();
|
|
40
|
-
this._logger = logger;
|
|
28
|
+
super(logger);
|
|
41
29
|
this._baseUrl = baseUrl;
|
|
42
30
|
}
|
|
43
31
|
|
|
44
|
-
get refreshToken() {
|
|
45
|
-
return this._refreshToken;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get walletAddress() {
|
|
49
|
-
return this._walletAddress;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
32
|
get isAuthenticated() {
|
|
53
33
|
return !!this._refreshToken && this._refreshTokenExpiresAt > new Date();
|
|
54
34
|
}
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const token = this._token;
|
|
61
|
-
if (token) {
|
|
62
|
-
Cookie.set('authorization', token, {
|
|
63
|
-
domain: '.sogni.ai',
|
|
64
|
-
expires: 1
|
|
65
|
-
});
|
|
66
|
-
} else {
|
|
67
|
-
Cookie.remove('authorization', {
|
|
68
|
-
domain: '.sogni.ai'
|
|
69
|
-
});
|
|
36
|
+
async backup() {
|
|
37
|
+
if (this._token && this._refreshToken) {
|
|
38
|
+
return { token: this._token, refreshToken: this._refreshToken };
|
|
70
39
|
}
|
|
40
|
+
return null;
|
|
71
41
|
}
|
|
72
42
|
|
|
73
|
-
async
|
|
43
|
+
async authenticate({ refreshToken, token }: TokenAuthData) {
|
|
44
|
+
// If there is a token, and it is not expired, authenticate with it
|
|
74
45
|
if (token) {
|
|
75
|
-
|
|
76
|
-
|
|
46
|
+
const { expiresAt } = decodeToken(token);
|
|
47
|
+
if (expiresAt > new Date()) {
|
|
48
|
+
this._updateTokens({ token, refreshToken });
|
|
49
|
+
this.emit('updated', true);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
77
52
|
}
|
|
53
|
+
// If token is expired, try to renew it with the refresh token
|
|
78
54
|
this._refreshToken = refreshToken;
|
|
79
55
|
const { expiresAt: refreshExpiresAt } = decodeRefreshToken(refreshToken);
|
|
80
56
|
this._refreshTokenExpiresAt = refreshExpiresAt;
|
|
81
|
-
await this.
|
|
57
|
+
await this._renewTokenSafe();
|
|
58
|
+
this.emit('updated', true);
|
|
82
59
|
}
|
|
83
60
|
|
|
84
|
-
|
|
61
|
+
clear() {
|
|
62
|
+
// Prevent duplicate events
|
|
63
|
+
if (!this._token && !this._refreshToken) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this._refreshToken = undefined;
|
|
67
|
+
this._refreshTokenExpiresAt = new Date(0);
|
|
68
|
+
this._token = undefined;
|
|
69
|
+
this._tokenExpiresAt = new Date(0);
|
|
70
|
+
this.emit('updated', false);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async authenticateRequest(option: RequestInit): Promise<RequestInit> {
|
|
85
74
|
//If there is a token, and it is not expired, return it
|
|
75
|
+
if (this._token && this._tokenExpiresAt > new Date()) {
|
|
76
|
+
return { ...option, headers: { ...option.headers, Authorization: this._token } };
|
|
77
|
+
}
|
|
78
|
+
//If there is no refresh token, return undefined, to make unauthorized requests
|
|
79
|
+
if (!this._refreshToken) {
|
|
80
|
+
return option;
|
|
81
|
+
}
|
|
82
|
+
//If there is a refresh token, try to renew the token
|
|
83
|
+
const token = await this._renewTokenSafe();
|
|
84
|
+
return { ...option, headers: { ...option.headers, Authorization: token } };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async socketOptions(): Promise<ClientOptions | undefined> {
|
|
88
|
+
if (!isNodejs) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const token = await this._getToken();
|
|
92
|
+
if (!token) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
headers: {
|
|
97
|
+
Authorization: token
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private async _getToken() {
|
|
86
103
|
if (this._token && this._tokenExpiresAt > new Date()) {
|
|
87
104
|
return this._token;
|
|
88
105
|
}
|
|
89
106
|
//If there is no refresh token, return undefined, to make unauthorized requests
|
|
90
107
|
if (!this._refreshToken) {
|
|
91
|
-
return;
|
|
108
|
+
return undefined;
|
|
92
109
|
}
|
|
93
110
|
//If there is a refresh token, try to renew the token
|
|
94
|
-
return this.
|
|
111
|
+
return this._renewTokenSafe();
|
|
95
112
|
}
|
|
96
113
|
|
|
97
|
-
async
|
|
114
|
+
private async _renewTokenSafe(): Promise<string> {
|
|
98
115
|
if (this._renewTokenPromise) {
|
|
99
116
|
return this._renewTokenPromise;
|
|
100
117
|
}
|
|
@@ -105,33 +122,41 @@ class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
|
|
|
105
122
|
return this._renewTokenPromise;
|
|
106
123
|
}
|
|
107
124
|
|
|
108
|
-
clear() {
|
|
109
|
-
// Prevent duplicate events
|
|
110
|
-
if (!this._token && !this._refreshToken) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
this._refreshToken = undefined;
|
|
114
|
-
this._refreshTokenExpiresAt = new Date(0);
|
|
115
|
-
this._token = undefined;
|
|
116
|
-
this._tokenExpiresAt = new Date(0);
|
|
117
|
-
this._walletAddress = undefined;
|
|
118
|
-
this.emit('updated', { token: null, refreshToken: null, walletAddress: null });
|
|
119
|
-
}
|
|
120
|
-
|
|
121
125
|
private _updateTokens({ token, refreshToken }: { token: string; refreshToken: string }) {
|
|
122
126
|
// Prevent duplicate events
|
|
123
127
|
if (this._token === token && this._refreshToken === refreshToken) {
|
|
124
128
|
return;
|
|
125
129
|
}
|
|
126
130
|
this._token = token;
|
|
127
|
-
const { expiresAt
|
|
128
|
-
this._walletAddress = walletAddress;
|
|
131
|
+
const { expiresAt } = decodeToken(token);
|
|
129
132
|
this._tokenExpiresAt = expiresAt;
|
|
130
133
|
this._refreshToken = refreshToken;
|
|
131
134
|
const { expiresAt: refreshExpiresAt } = decodeRefreshToken(refreshToken);
|
|
132
135
|
this._refreshTokenExpiresAt = refreshExpiresAt;
|
|
133
136
|
this._updateCookies();
|
|
134
|
-
this.emit('updated',
|
|
137
|
+
this.emit('updated', true);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* This is a fallback for browsers, where we can't set headers on WebSocket requests.
|
|
142
|
+
* Normally a browser should use CookieAuthManager
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
private _updateCookies() {
|
|
146
|
+
if (isNodejs) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const token = this._token;
|
|
150
|
+
if (token) {
|
|
151
|
+
Cookie.set('authorization', token, {
|
|
152
|
+
domain: '.sogni.ai',
|
|
153
|
+
expires: 1
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
Cookie.remove('authorization', {
|
|
157
|
+
domain: '.sogni.ai'
|
|
158
|
+
});
|
|
159
|
+
}
|
|
135
160
|
}
|
|
136
161
|
|
|
137
162
|
private async _renewToken(): Promise<string> {
|
|
@@ -150,16 +175,11 @@ class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
|
|
|
150
175
|
try {
|
|
151
176
|
responseData = await response.json();
|
|
152
177
|
} catch (e) {
|
|
153
|
-
this.
|
|
154
|
-
status: 'error',
|
|
155
|
-
errorCode: 0,
|
|
156
|
-
message: 'Failed to parse response'
|
|
157
|
-
});
|
|
178
|
+
this.clear();
|
|
158
179
|
this._logger.error('Failed to parse response:', e);
|
|
159
180
|
throw new Error('Failed to parse response');
|
|
160
181
|
}
|
|
161
182
|
if (!response.ok) {
|
|
162
|
-
this.emit('refreshFailed', responseData);
|
|
163
183
|
this.clear();
|
|
164
184
|
throw new ApiError(response.status, responseData as ApiErrorResponse);
|
|
165
185
|
}
|
|
@@ -169,4 +189,4 @@ class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
|
|
|
169
189
|
}
|
|
170
190
|
}
|
|
171
191
|
|
|
172
|
-
export default
|
|
192
|
+
export default TokenAuthManager;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import CookieAuthManager from './CookieAuthManager';
|
|
2
|
+
import TokenAuthManager, { TokenAuthData } from './TokenAuthManager';
|
|
3
|
+
|
|
4
|
+
export type { TokenAuthData };
|
|
5
|
+
|
|
6
|
+
export { CookieAuthManager, TokenAuthManager };
|
|
7
|
+
|
|
8
|
+
export type AuthManager = CookieAuthManager | TokenAuthManager;
|
package/src/lib/RestClient.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ApiError, ApiErrorResponse } from '../ApiClient';
|
|
|
2
2
|
import TypedEventEmitter, { EventMap } from './TypedEventEmitter';
|
|
3
3
|
import { JSONValue } from '../types/json';
|
|
4
4
|
import { Logger } from './DefaultLogger';
|
|
5
|
-
import AuthManager from './AuthManager';
|
|
5
|
+
import { AuthManager } from './AuthManager';
|
|
6
6
|
|
|
7
7
|
class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
|
|
8
8
|
readonly baseUrl: string;
|
|
@@ -29,15 +29,8 @@ class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
private async request<T = JSONValue>(url: string, options: RequestInit = {}): Promise<T> {
|
|
32
|
-
const
|
|
33
|
-
return fetch(url,
|
|
34
|
-
...options,
|
|
35
|
-
credentials: 'include',
|
|
36
|
-
headers: {
|
|
37
|
-
...(options.headers || {}),
|
|
38
|
-
...(token ? { Authorization: token } : {})
|
|
39
|
-
}
|
|
40
|
-
}).then((r) => this.processResponse(r) as T);
|
|
32
|
+
const init = await this.auth.authenticateRequest(options);
|
|
33
|
+
return fetch(url, init).then((r) => this.processResponse(r) as T);
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
private async processResponse(response: Response): Promise<JSONValue> {
|
|
@@ -48,6 +41,10 @@ class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
|
|
|
48
41
|
this._logger.error('Failed to parse response:', e);
|
|
49
42
|
throw new Error('Failed to parse response');
|
|
50
43
|
}
|
|
44
|
+
// 401 means that the client instance is not authenticated, so we clear the authentication
|
|
45
|
+
if (response.status === 401 && this.auth.isAuthenticated) {
|
|
46
|
+
this.auth.clear();
|
|
47
|
+
}
|
|
51
48
|
if (!response.ok) {
|
|
52
49
|
throw new ApiError(response.status, responseData as ApiErrorResponse);
|
|
53
50
|
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { ApiErrorResponse } from '../ApiClient';
|
|
2
|
-
import { Logger } from './DefaultLogger';
|
|
3
|
-
import TypedEventEmitter from './TypedEventEmitter';
|
|
4
|
-
/**
|
|
5
|
-
* Tokens object, containing the token and refresh token
|
|
6
|
-
* @typedef {Object} Tokens
|
|
7
|
-
* @property {string} [token] - The JWT token. Optonal, if missing it will be retrieved from the server
|
|
8
|
-
* @property {string} refreshToken - The refresh token
|
|
9
|
-
*/
|
|
10
|
-
export interface Tokens {
|
|
11
|
-
token?: string;
|
|
12
|
-
refreshToken: string;
|
|
13
|
-
}
|
|
14
|
-
export type AuthUpdatedEvent = {
|
|
15
|
-
token: string;
|
|
16
|
-
refreshToken: string;
|
|
17
|
-
walletAddress: string;
|
|
18
|
-
} | {
|
|
19
|
-
token: null;
|
|
20
|
-
refreshToken: null;
|
|
21
|
-
walletAddress: null;
|
|
22
|
-
};
|
|
23
|
-
interface AuthManagerEvents {
|
|
24
|
-
updated: AuthUpdatedEvent;
|
|
25
|
-
refreshFailed: ApiErrorResponse;
|
|
26
|
-
}
|
|
27
|
-
declare class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
|
|
28
|
-
private _token?;
|
|
29
|
-
private _tokenExpiresAt;
|
|
30
|
-
private _refreshToken?;
|
|
31
|
-
private _refreshTokenExpiresAt;
|
|
32
|
-
private _logger;
|
|
33
|
-
private _baseUrl;
|
|
34
|
-
private _walletAddress?;
|
|
35
|
-
private _renewTokenPromise?;
|
|
36
|
-
constructor(baseUrl: string, logger: Logger);
|
|
37
|
-
get refreshToken(): string | undefined;
|
|
38
|
-
get walletAddress(): string | undefined;
|
|
39
|
-
get isAuthenticated(): boolean;
|
|
40
|
-
private _updateCookies;
|
|
41
|
-
setTokens({ refreshToken, token }: {
|
|
42
|
-
refreshToken: string;
|
|
43
|
-
token?: string;
|
|
44
|
-
}): Promise<void>;
|
|
45
|
-
getToken(): Promise<string | undefined>;
|
|
46
|
-
renewToken(): Promise<string>;
|
|
47
|
-
clear(): void;
|
|
48
|
-
private _updateTokens;
|
|
49
|
-
private _renewToken;
|
|
50
|
-
}
|
|
51
|
-
export default AuthManager;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthManager.js","sourceRoot":"","sources":["../../src/lib/AuthManager.ts"],"names":[],"mappings":"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"}
|