@redseat/api 0.0.6 → 0.0.8
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/README.md +132 -132
- package/agents.md +275 -275
- package/client.md +288 -288
- package/dist/library.d.ts +0 -1
- package/dist/library.js +8 -12
- package/encryption.md +533 -533
- package/firebase.md +602 -602
- package/libraries.md +1652 -1652
- package/package.json +49 -49
- package/server.md +196 -196
- package/test.md +291 -291
package/client.md
CHANGED
|
@@ -1,288 +1,288 @@
|
|
|
1
|
-
# RedseatClient
|
|
2
|
-
|
|
3
|
-
The `RedseatClient` class is the low-level HTTP client that handles all communication with Redseat servers. It provides automatic token management, local server detection, and request/response interceptors.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
`RedseatClient` wraps Axios and adds:
|
|
8
|
-
- Automatic token refresh before expiration
|
|
9
|
-
- Local server detection (for development)
|
|
10
|
-
- 401 error handling with automatic retry
|
|
11
|
-
- Request/response interceptors for authentication
|
|
12
|
-
|
|
13
|
-
## Constructor
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
new RedseatClient(options: ClientOptions)
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### ClientOptions Interface
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
interface ClientOptions {
|
|
23
|
-
server: IServer;
|
|
24
|
-
getIdToken: () => Promise<string>;
|
|
25
|
-
refreshThreshold?: number; // milliseconds before expiration to refresh (default: 5 minutes)
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Parameters:**
|
|
30
|
-
- `server`: Server configuration object with `id`, `url`, and optional `port`
|
|
31
|
-
- `getIdToken`: Async function that returns the current ID token from your auth provider
|
|
32
|
-
- `refreshThreshold`: Optional. Milliseconds before token expiration to trigger refresh (default: 300000 = 5 minutes)
|
|
33
|
-
|
|
34
|
-
**Example:**
|
|
35
|
-
```typescript
|
|
36
|
-
const client = new RedseatClient({
|
|
37
|
-
server: {
|
|
38
|
-
id: 'server-123',
|
|
39
|
-
url: 'example.com',
|
|
40
|
-
port: 443
|
|
41
|
-
},
|
|
42
|
-
getIdToken: async () => {
|
|
43
|
-
// Get ID token from your auth provider (Firebase, Auth0, etc.)
|
|
44
|
-
return await getCurrentUserToken();
|
|
45
|
-
},
|
|
46
|
-
refreshThreshold: 5 * 60 * 1000 // 5 minutes
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Features
|
|
51
|
-
|
|
52
|
-
### Automatic Token Refresh
|
|
53
|
-
|
|
54
|
-
The client automatically refreshes tokens before they expire. The refresh happens:
|
|
55
|
-
- Before each request if the token is expired or expiring soon
|
|
56
|
-
- When a 401 error is received (with automatic retry)
|
|
57
|
-
|
|
58
|
-
### Local Server Detection
|
|
59
|
-
|
|
60
|
-
The client automatically detects if a local development server is available by checking `local.{server.url}`. If detected, it uses the local URL instead of the production URL.
|
|
61
|
-
|
|
62
|
-
### Request Interceptor
|
|
63
|
-
|
|
64
|
-
All requests are intercepted to:
|
|
65
|
-
1. Check if token needs refresh
|
|
66
|
-
2. Add `Authorization: Bearer {token}` header
|
|
67
|
-
|
|
68
|
-
### Response Interceptor
|
|
69
|
-
|
|
70
|
-
All responses are intercepted to:
|
|
71
|
-
1. Handle 401 errors by refreshing token and retrying the request
|
|
72
|
-
2. Prevent infinite retry loops with `_retry` flag
|
|
73
|
-
|
|
74
|
-
## Methods
|
|
75
|
-
|
|
76
|
-
### `get<T>(url: string, config?: AxiosRequestConfig)`
|
|
77
|
-
|
|
78
|
-
Performs a GET request.
|
|
79
|
-
|
|
80
|
-
**Parameters:**
|
|
81
|
-
- `url`: The endpoint URL (relative to base URL)
|
|
82
|
-
- `config`: Optional Axios request configuration
|
|
83
|
-
|
|
84
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
85
|
-
|
|
86
|
-
**Example:**
|
|
87
|
-
```typescript
|
|
88
|
-
const response = await client.get<IFile[]>('/libraries/123/medias');
|
|
89
|
-
const medias = response.data;
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### `post<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
93
|
-
|
|
94
|
-
Performs a POST request.
|
|
95
|
-
|
|
96
|
-
**Parameters:**
|
|
97
|
-
- `url`: The endpoint URL
|
|
98
|
-
- `data`: Request body data
|
|
99
|
-
- `config`: Optional Axios request configuration
|
|
100
|
-
|
|
101
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
102
|
-
|
|
103
|
-
**Example:**
|
|
104
|
-
```typescript
|
|
105
|
-
const response = await client.post<ITag>('/libraries/123/tags', {
|
|
106
|
-
name: 'Vacation'
|
|
107
|
-
});
|
|
108
|
-
const tag = response.data;
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### `put<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
112
|
-
|
|
113
|
-
Performs a PUT request.
|
|
114
|
-
|
|
115
|
-
**Parameters:**
|
|
116
|
-
- `url`: The endpoint URL
|
|
117
|
-
- `data`: Request body data
|
|
118
|
-
- `config`: Optional Axios request configuration
|
|
119
|
-
|
|
120
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
121
|
-
|
|
122
|
-
**Example:**
|
|
123
|
-
```typescript
|
|
124
|
-
const formData = new FormData();
|
|
125
|
-
formData.append('file', fileBlob);
|
|
126
|
-
const response = await client.put('/libraries/123/medias/transfert', formData);
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### `patch<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
130
|
-
|
|
131
|
-
Performs a PATCH request.
|
|
132
|
-
|
|
133
|
-
**Parameters:**
|
|
134
|
-
- `url`: The endpoint URL
|
|
135
|
-
- `data`: Request body data
|
|
136
|
-
- `config`: Optional Axios request configuration
|
|
137
|
-
|
|
138
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
139
|
-
|
|
140
|
-
**Example:**
|
|
141
|
-
```typescript
|
|
142
|
-
const response = await client.patch<ITag>('/libraries/123/tags/tag-id', {
|
|
143
|
-
rename: 'New Tag Name'
|
|
144
|
-
});
|
|
145
|
-
const updatedTag = response.data;
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### `delete<T>(url: string, config?: AxiosRequestConfig)`
|
|
149
|
-
|
|
150
|
-
Performs a DELETE request.
|
|
151
|
-
|
|
152
|
-
**Parameters:**
|
|
153
|
-
- `url`: The endpoint URL
|
|
154
|
-
- `config`: Optional Axios request configuration (can include `data` for request body)
|
|
155
|
-
|
|
156
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
157
|
-
|
|
158
|
-
**Example:**
|
|
159
|
-
```typescript
|
|
160
|
-
// Simple delete
|
|
161
|
-
await client.delete('/libraries/123/tags/tag-id');
|
|
162
|
-
|
|
163
|
-
// Delete with body
|
|
164
|
-
await client.delete('/libraries/123/medias', {
|
|
165
|
-
data: { ids: ['media-1', 'media-2'] }
|
|
166
|
-
});
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### `request<T>(method: Method, url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
170
|
-
|
|
171
|
-
Performs a custom HTTP request.
|
|
172
|
-
|
|
173
|
-
**Parameters:**
|
|
174
|
-
- `method`: HTTP method ('GET', 'POST', 'PUT', 'PATCH', 'DELETE', etc.)
|
|
175
|
-
- `url`: The endpoint URL
|
|
176
|
-
- `data`: Request body data
|
|
177
|
-
- `config`: Optional Axios request configuration
|
|
178
|
-
|
|
179
|
-
**Returns:** `Promise<AxiosResponse<T>>`
|
|
180
|
-
|
|
181
|
-
**Example:**
|
|
182
|
-
```typescript
|
|
183
|
-
const response = await client.request<IFile>(
|
|
184
|
-
'GET',
|
|
185
|
-
'/libraries/123/medias/media-id',
|
|
186
|
-
undefined,
|
|
187
|
-
{ responseType: 'blob' }
|
|
188
|
-
);
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### `setToken(token: string | IToken)`
|
|
192
|
-
|
|
193
|
-
Manually set the authentication token. Useful when you already have a valid token.
|
|
194
|
-
|
|
195
|
-
**Parameters:**
|
|
196
|
-
- `token`: Either a token string or an `IToken` object with `token` and `expires` properties
|
|
197
|
-
|
|
198
|
-
**Example:**
|
|
199
|
-
```typescript
|
|
200
|
-
// Set as string (will be treated as expiring soon)
|
|
201
|
-
client.setToken('your-token-string');
|
|
202
|
-
|
|
203
|
-
// Set as IToken object with expiration
|
|
204
|
-
client.setToken({
|
|
205
|
-
token: 'your-token-string',
|
|
206
|
-
expires: Date.now() + 3600000 // 1 hour from now
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## Error Handling
|
|
211
|
-
|
|
212
|
-
The client automatically handles:
|
|
213
|
-
- **401 Unauthorized**: Refreshes token and retries the request once
|
|
214
|
-
- **Token expiration**: Refreshes token before making requests
|
|
215
|
-
- **Network errors**: Passes through to caller
|
|
216
|
-
|
|
217
|
-
**Example error handling:**
|
|
218
|
-
```typescript
|
|
219
|
-
try {
|
|
220
|
-
const response = await client.get('/libraries/123/medias');
|
|
221
|
-
} catch (error) {
|
|
222
|
-
if (error.response?.status === 401) {
|
|
223
|
-
// Token refresh failed or invalid credentials
|
|
224
|
-
console.error('Authentication failed');
|
|
225
|
-
} else if (error.response?.status === 404) {
|
|
226
|
-
// Resource not found
|
|
227
|
-
console.error('Resource not found');
|
|
228
|
-
} else {
|
|
229
|
-
// Other error
|
|
230
|
-
console.error('Request failed:', error.message);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Usage with Response Types
|
|
236
|
-
|
|
237
|
-
The client supports specifying response types for binary data:
|
|
238
|
-
|
|
239
|
-
```typescript
|
|
240
|
-
// Get as stream
|
|
241
|
-
const stream = await client.get('/libraries/123/medias/media-id', {
|
|
242
|
-
responseType: 'stream'
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// Get as ArrayBuffer
|
|
246
|
-
const buffer = await client.get('/libraries/123/medias/media-id', {
|
|
247
|
-
responseType: 'arraybuffer'
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Get as Blob
|
|
251
|
-
const blob = await client.get('/libraries/123/medias/media-id', {
|
|
252
|
-
responseType: 'blob'
|
|
253
|
-
});
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Progress Tracking
|
|
257
|
-
|
|
258
|
-
For file uploads, you can track progress:
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
const formData = new FormData();
|
|
262
|
-
formData.append('file', fileBlob);
|
|
263
|
-
|
|
264
|
-
await client.post('/libraries/123/medias', formData, {
|
|
265
|
-
onUploadProgress: (progressEvent) => {
|
|
266
|
-
if (progressEvent.total) {
|
|
267
|
-
const percent = (progressEvent.loaded / progressEvent.total) * 100;
|
|
268
|
-
console.log(`Upload progress: ${percent}%`);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## Internal Methods (Private)
|
|
275
|
-
|
|
276
|
-
The following methods are used internally and should not be called directly:
|
|
277
|
-
- `refreshToken()` - Refreshes the authentication token
|
|
278
|
-
- `ensureValidToken()` - Ensures token is valid before requests
|
|
279
|
-
- `isTokenExpiredOrExpiringSoon()` - Checks if token needs refresh
|
|
280
|
-
- `detectLocalUrl()` - Detects local development server
|
|
281
|
-
- `getRegularServerUrl()` - Gets production server URL
|
|
282
|
-
|
|
283
|
-
## See Also
|
|
284
|
-
|
|
285
|
-
- [ServerApi Documentation](server.md) - Uses RedseatClient for server operations
|
|
286
|
-
- [LibraryApi Documentation](libraries.md) - Uses RedseatClient for library operations
|
|
287
|
-
- [README](README.md) - Package overview
|
|
288
|
-
|
|
1
|
+
# RedseatClient
|
|
2
|
+
|
|
3
|
+
The `RedseatClient` class is the low-level HTTP client that handles all communication with Redseat servers. It provides automatic token management, local server detection, and request/response interceptors.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`RedseatClient` wraps Axios and adds:
|
|
8
|
+
- Automatic token refresh before expiration
|
|
9
|
+
- Local server detection (for development)
|
|
10
|
+
- 401 error handling with automatic retry
|
|
11
|
+
- Request/response interceptors for authentication
|
|
12
|
+
|
|
13
|
+
## Constructor
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
new RedseatClient(options: ClientOptions)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### ClientOptions Interface
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface ClientOptions {
|
|
23
|
+
server: IServer;
|
|
24
|
+
getIdToken: () => Promise<string>;
|
|
25
|
+
refreshThreshold?: number; // milliseconds before expiration to refresh (default: 5 minutes)
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Parameters:**
|
|
30
|
+
- `server`: Server configuration object with `id`, `url`, and optional `port`
|
|
31
|
+
- `getIdToken`: Async function that returns the current ID token from your auth provider
|
|
32
|
+
- `refreshThreshold`: Optional. Milliseconds before token expiration to trigger refresh (default: 300000 = 5 minutes)
|
|
33
|
+
|
|
34
|
+
**Example:**
|
|
35
|
+
```typescript
|
|
36
|
+
const client = new RedseatClient({
|
|
37
|
+
server: {
|
|
38
|
+
id: 'server-123',
|
|
39
|
+
url: 'example.com',
|
|
40
|
+
port: 443
|
|
41
|
+
},
|
|
42
|
+
getIdToken: async () => {
|
|
43
|
+
// Get ID token from your auth provider (Firebase, Auth0, etc.)
|
|
44
|
+
return await getCurrentUserToken();
|
|
45
|
+
},
|
|
46
|
+
refreshThreshold: 5 * 60 * 1000 // 5 minutes
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
### Automatic Token Refresh
|
|
53
|
+
|
|
54
|
+
The client automatically refreshes tokens before they expire. The refresh happens:
|
|
55
|
+
- Before each request if the token is expired or expiring soon
|
|
56
|
+
- When a 401 error is received (with automatic retry)
|
|
57
|
+
|
|
58
|
+
### Local Server Detection
|
|
59
|
+
|
|
60
|
+
The client automatically detects if a local development server is available by checking `local.{server.url}`. If detected, it uses the local URL instead of the production URL.
|
|
61
|
+
|
|
62
|
+
### Request Interceptor
|
|
63
|
+
|
|
64
|
+
All requests are intercepted to:
|
|
65
|
+
1. Check if token needs refresh
|
|
66
|
+
2. Add `Authorization: Bearer {token}` header
|
|
67
|
+
|
|
68
|
+
### Response Interceptor
|
|
69
|
+
|
|
70
|
+
All responses are intercepted to:
|
|
71
|
+
1. Handle 401 errors by refreshing token and retrying the request
|
|
72
|
+
2. Prevent infinite retry loops with `_retry` flag
|
|
73
|
+
|
|
74
|
+
## Methods
|
|
75
|
+
|
|
76
|
+
### `get<T>(url: string, config?: AxiosRequestConfig)`
|
|
77
|
+
|
|
78
|
+
Performs a GET request.
|
|
79
|
+
|
|
80
|
+
**Parameters:**
|
|
81
|
+
- `url`: The endpoint URL (relative to base URL)
|
|
82
|
+
- `config`: Optional Axios request configuration
|
|
83
|
+
|
|
84
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
85
|
+
|
|
86
|
+
**Example:**
|
|
87
|
+
```typescript
|
|
88
|
+
const response = await client.get<IFile[]>('/libraries/123/medias');
|
|
89
|
+
const medias = response.data;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `post<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
93
|
+
|
|
94
|
+
Performs a POST request.
|
|
95
|
+
|
|
96
|
+
**Parameters:**
|
|
97
|
+
- `url`: The endpoint URL
|
|
98
|
+
- `data`: Request body data
|
|
99
|
+
- `config`: Optional Axios request configuration
|
|
100
|
+
|
|
101
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
102
|
+
|
|
103
|
+
**Example:**
|
|
104
|
+
```typescript
|
|
105
|
+
const response = await client.post<ITag>('/libraries/123/tags', {
|
|
106
|
+
name: 'Vacation'
|
|
107
|
+
});
|
|
108
|
+
const tag = response.data;
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `put<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
112
|
+
|
|
113
|
+
Performs a PUT request.
|
|
114
|
+
|
|
115
|
+
**Parameters:**
|
|
116
|
+
- `url`: The endpoint URL
|
|
117
|
+
- `data`: Request body data
|
|
118
|
+
- `config`: Optional Axios request configuration
|
|
119
|
+
|
|
120
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
121
|
+
|
|
122
|
+
**Example:**
|
|
123
|
+
```typescript
|
|
124
|
+
const formData = new FormData();
|
|
125
|
+
formData.append('file', fileBlob);
|
|
126
|
+
const response = await client.put('/libraries/123/medias/transfert', formData);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `patch<T>(url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
130
|
+
|
|
131
|
+
Performs a PATCH request.
|
|
132
|
+
|
|
133
|
+
**Parameters:**
|
|
134
|
+
- `url`: The endpoint URL
|
|
135
|
+
- `data`: Request body data
|
|
136
|
+
- `config`: Optional Axios request configuration
|
|
137
|
+
|
|
138
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
139
|
+
|
|
140
|
+
**Example:**
|
|
141
|
+
```typescript
|
|
142
|
+
const response = await client.patch<ITag>('/libraries/123/tags/tag-id', {
|
|
143
|
+
rename: 'New Tag Name'
|
|
144
|
+
});
|
|
145
|
+
const updatedTag = response.data;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `delete<T>(url: string, config?: AxiosRequestConfig)`
|
|
149
|
+
|
|
150
|
+
Performs a DELETE request.
|
|
151
|
+
|
|
152
|
+
**Parameters:**
|
|
153
|
+
- `url`: The endpoint URL
|
|
154
|
+
- `config`: Optional Axios request configuration (can include `data` for request body)
|
|
155
|
+
|
|
156
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
157
|
+
|
|
158
|
+
**Example:**
|
|
159
|
+
```typescript
|
|
160
|
+
// Simple delete
|
|
161
|
+
await client.delete('/libraries/123/tags/tag-id');
|
|
162
|
+
|
|
163
|
+
// Delete with body
|
|
164
|
+
await client.delete('/libraries/123/medias', {
|
|
165
|
+
data: { ids: ['media-1', 'media-2'] }
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `request<T>(method: Method, url: string, data?: unknown, config?: AxiosRequestConfig)`
|
|
170
|
+
|
|
171
|
+
Performs a custom HTTP request.
|
|
172
|
+
|
|
173
|
+
**Parameters:**
|
|
174
|
+
- `method`: HTTP method ('GET', 'POST', 'PUT', 'PATCH', 'DELETE', etc.)
|
|
175
|
+
- `url`: The endpoint URL
|
|
176
|
+
- `data`: Request body data
|
|
177
|
+
- `config`: Optional Axios request configuration
|
|
178
|
+
|
|
179
|
+
**Returns:** `Promise<AxiosResponse<T>>`
|
|
180
|
+
|
|
181
|
+
**Example:**
|
|
182
|
+
```typescript
|
|
183
|
+
const response = await client.request<IFile>(
|
|
184
|
+
'GET',
|
|
185
|
+
'/libraries/123/medias/media-id',
|
|
186
|
+
undefined,
|
|
187
|
+
{ responseType: 'blob' }
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `setToken(token: string | IToken)`
|
|
192
|
+
|
|
193
|
+
Manually set the authentication token. Useful when you already have a valid token.
|
|
194
|
+
|
|
195
|
+
**Parameters:**
|
|
196
|
+
- `token`: Either a token string or an `IToken` object with `token` and `expires` properties
|
|
197
|
+
|
|
198
|
+
**Example:**
|
|
199
|
+
```typescript
|
|
200
|
+
// Set as string (will be treated as expiring soon)
|
|
201
|
+
client.setToken('your-token-string');
|
|
202
|
+
|
|
203
|
+
// Set as IToken object with expiration
|
|
204
|
+
client.setToken({
|
|
205
|
+
token: 'your-token-string',
|
|
206
|
+
expires: Date.now() + 3600000 // 1 hour from now
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Error Handling
|
|
211
|
+
|
|
212
|
+
The client automatically handles:
|
|
213
|
+
- **401 Unauthorized**: Refreshes token and retries the request once
|
|
214
|
+
- **Token expiration**: Refreshes token before making requests
|
|
215
|
+
- **Network errors**: Passes through to caller
|
|
216
|
+
|
|
217
|
+
**Example error handling:**
|
|
218
|
+
```typescript
|
|
219
|
+
try {
|
|
220
|
+
const response = await client.get('/libraries/123/medias');
|
|
221
|
+
} catch (error) {
|
|
222
|
+
if (error.response?.status === 401) {
|
|
223
|
+
// Token refresh failed or invalid credentials
|
|
224
|
+
console.error('Authentication failed');
|
|
225
|
+
} else if (error.response?.status === 404) {
|
|
226
|
+
// Resource not found
|
|
227
|
+
console.error('Resource not found');
|
|
228
|
+
} else {
|
|
229
|
+
// Other error
|
|
230
|
+
console.error('Request failed:', error.message);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Usage with Response Types
|
|
236
|
+
|
|
237
|
+
The client supports specifying response types for binary data:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// Get as stream
|
|
241
|
+
const stream = await client.get('/libraries/123/medias/media-id', {
|
|
242
|
+
responseType: 'stream'
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Get as ArrayBuffer
|
|
246
|
+
const buffer = await client.get('/libraries/123/medias/media-id', {
|
|
247
|
+
responseType: 'arraybuffer'
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Get as Blob
|
|
251
|
+
const blob = await client.get('/libraries/123/medias/media-id', {
|
|
252
|
+
responseType: 'blob'
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Progress Tracking
|
|
257
|
+
|
|
258
|
+
For file uploads, you can track progress:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const formData = new FormData();
|
|
262
|
+
formData.append('file', fileBlob);
|
|
263
|
+
|
|
264
|
+
await client.post('/libraries/123/medias', formData, {
|
|
265
|
+
onUploadProgress: (progressEvent) => {
|
|
266
|
+
if (progressEvent.total) {
|
|
267
|
+
const percent = (progressEvent.loaded / progressEvent.total) * 100;
|
|
268
|
+
console.log(`Upload progress: ${percent}%`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Internal Methods (Private)
|
|
275
|
+
|
|
276
|
+
The following methods are used internally and should not be called directly:
|
|
277
|
+
- `refreshToken()` - Refreshes the authentication token
|
|
278
|
+
- `ensureValidToken()` - Ensures token is valid before requests
|
|
279
|
+
- `isTokenExpiredOrExpiringSoon()` - Checks if token needs refresh
|
|
280
|
+
- `detectLocalUrl()` - Detects local development server
|
|
281
|
+
- `getRegularServerUrl()` - Gets production server URL
|
|
282
|
+
|
|
283
|
+
## See Also
|
|
284
|
+
|
|
285
|
+
- [ServerApi Documentation](server.md) - Uses RedseatClient for server operations
|
|
286
|
+
- [LibraryApi Documentation](libraries.md) - Uses RedseatClient for library operations
|
|
287
|
+
- [README](README.md) - Package overview
|
|
288
|
+
|
package/dist/library.d.ts
CHANGED
|
@@ -151,7 +151,6 @@ export declare class LibraryApi {
|
|
|
151
151
|
faceClusterPerson(personId: string): Promise<void>;
|
|
152
152
|
mergePeople(request: any): Promise<any>;
|
|
153
153
|
clusterFaces(personId: string): Promise<any>;
|
|
154
|
-
getMediaPureMetadata(mediaId: string): Promise<IFile>;
|
|
155
154
|
mergeMedias(request: any): Promise<IFile>;
|
|
156
155
|
mediaUpdateMany(update: any, ids: string[]): Promise<IFile[]>;
|
|
157
156
|
mediaUpdateProgress(mediaId: string, progress: number): Promise<{
|
package/dist/library.js
CHANGED
|
@@ -143,7 +143,7 @@ export class LibraryApi {
|
|
|
143
143
|
await this.client.delete(this.getUrl('/medias'), { data: { ids: mediaIds } });
|
|
144
144
|
}
|
|
145
145
|
async getMediaMetadata(mediaId) {
|
|
146
|
-
const res = await this.client.get(this.getUrl(`/medias/${mediaId}`));
|
|
146
|
+
const res = await this.client.get(this.getUrl(`/medias/${mediaId}/metadata`));
|
|
147
147
|
return res.data;
|
|
148
148
|
}
|
|
149
149
|
async getMediaBackupMetadatas(mediaId) {
|
|
@@ -303,31 +303,31 @@ export class LibraryApi {
|
|
|
303
303
|
queryParams[key] = value;
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
|
-
const res = await this.client.get(this.getUrl('/faces/unassigned'), { params: queryParams });
|
|
306
|
+
const res = await this.client.get(this.getUrl('/people/faces/unassigned'), { params: queryParams });
|
|
307
307
|
return res.data;
|
|
308
308
|
}
|
|
309
309
|
async getClusters() {
|
|
310
|
-
const res = await this.client.get(this.getUrl('/faces/clusters'));
|
|
310
|
+
const res = await this.client.get(this.getUrl('/people/faces/clusters'));
|
|
311
311
|
return res.data;
|
|
312
312
|
}
|
|
313
313
|
async assignFaces(request) {
|
|
314
|
-
const res = await this.client.post(this.getUrl('/faces/assign'), request);
|
|
314
|
+
const res = await this.client.post(this.getUrl('/people/faces/assign'), request);
|
|
315
315
|
return res.data;
|
|
316
316
|
}
|
|
317
317
|
async createPersonFromCluster(request) {
|
|
318
|
-
const res = await this.client.post(this.getUrl('/faces/cluster/person'), request);
|
|
318
|
+
const res = await this.client.post(this.getUrl('/people/faces/cluster/person'), request);
|
|
319
319
|
return res.data;
|
|
320
320
|
}
|
|
321
321
|
async splitCluster(request) {
|
|
322
|
-
const res = await this.client.post(this.getUrl('/faces/cluster/split'), request);
|
|
322
|
+
const res = await this.client.post(this.getUrl('/people/faces/cluster/split'), request);
|
|
323
323
|
return res.data;
|
|
324
324
|
}
|
|
325
325
|
async unassignFace(request) {
|
|
326
|
-
const res = await this.client.post(this.getUrl('/faces/unassign'), request);
|
|
326
|
+
const res = await this.client.post(this.getUrl('/people/faces/unassign'), request);
|
|
327
327
|
return res.data;
|
|
328
328
|
}
|
|
329
329
|
async deleteFace(faceId) {
|
|
330
|
-
const res = await this.client.delete(this.getUrl(`/faces/${faceId}`));
|
|
330
|
+
const res = await this.client.delete(this.getUrl(`/people/faces/${faceId}`));
|
|
331
331
|
return res.data;
|
|
332
332
|
}
|
|
333
333
|
async getAssignedFaces(personId) {
|
|
@@ -345,10 +345,6 @@ export class LibraryApi {
|
|
|
345
345
|
const res = await this.client.post(this.getUrl(`/people/${personId}/faces/cluster`), {});
|
|
346
346
|
return res.data;
|
|
347
347
|
}
|
|
348
|
-
async getMediaPureMetadata(mediaId) {
|
|
349
|
-
const res = await this.client.get(this.getUrl(`/medias/${mediaId}`));
|
|
350
|
-
return res.data;
|
|
351
|
-
}
|
|
352
348
|
async mergeMedias(request) {
|
|
353
349
|
const res = await this.client.post(this.getUrl('/medias/merge'), request);
|
|
354
350
|
return res.data;
|