@redseat/api 0.0.1

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 ADDED
@@ -0,0 +1,132 @@
1
+ # @redseat/api
2
+
3
+ TypeScript API client library for interacting with Redseat servers. This package provides a comprehensive set of APIs for managing libraries, media, tags, people, series, movies, and more.
4
+
5
+ ## Overview
6
+
7
+ The `@redseat/api` package is organized into three main API classes:
8
+
9
+ - **RedseatClient**: Low-level HTTP client with automatic token management and local server detection
10
+ - **ServerApi**: Server-level operations (libraries, settings, plugins, credentials)
11
+ - **LibraryApi**: Library-specific operations (media, tags, people, series, movies, encryption)
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { RedseatClient, ServerApi, LibraryApi } from '@redseat/api';
17
+ import { IServer, ILibrary } from '@redseat/api';
18
+
19
+ // Initialize the client
20
+ const client = new RedseatClient({
21
+ server: {
22
+ id: 'server-id',
23
+ url: 'example.com',
24
+ port: 443
25
+ },
26
+ getIdToken: async () => {
27
+ // Return your ID token from your auth provider
28
+ return 'your-id-token';
29
+ }
30
+ });
31
+
32
+ // Get server API
33
+ const serverApi = new ServerApi(client);
34
+
35
+ // Get libraries
36
+ const libraries = await serverApi.getLibraries();
37
+
38
+ // Get library API for a specific library
39
+ const library = libraries[0];
40
+ const libraryApi = new LibraryApi(client, library.id!, library);
41
+
42
+ // For encrypted libraries, set the encryption key
43
+ if (library.crypt) {
44
+ await libraryApi.setKey('your-passphrase');
45
+ }
46
+
47
+ // Get media
48
+ const medias = await libraryApi.getMedias();
49
+ ```
50
+
51
+ ## Documentation
52
+
53
+ - **[client.md](client.md)** - RedseatClient documentation
54
+ - HTTP client configuration
55
+ - Automatic token refresh
56
+ - Local server detection
57
+ - Request/response interceptors
58
+
59
+ - **[server.md](server.md)** - ServerApi documentation
60
+ - Server-level operations
61
+ - Library management
62
+ - Settings and plugins
63
+ - Credentials management
64
+
65
+ - **[libraries.md](libraries.md)** - LibraryApi documentation
66
+ - Media operations (upload, download, update)
67
+ - Tags, people, series, movies management
68
+ - Face recognition operations
69
+ - Encryption support for encrypted libraries
70
+
71
+ - **[encryption.md](encryption.md)** - Encryption module documentation
72
+ - Key derivation (PBKDF2)
73
+ - Text and binary encryption/decryption
74
+ - File encryption with thumbnails
75
+ - Cross-platform compatibility
76
+
77
+ - **[test.md](test.md)** - Testing guide
78
+ - How to run tests
79
+ - Test file descriptions
80
+ - Test coverage information
81
+
82
+ - **[agents.md](agents.md)** - AI agent instructions
83
+ - Documentation maintenance guidelines
84
+ - Code change workflow
85
+ - Best practices for keeping docs updated
86
+
87
+ ## Package Exports
88
+
89
+ ### Classes
90
+ - `RedseatClient` - HTTP client with authentication
91
+ - `ServerApi` - Server-level API operations
92
+ - `LibraryApi` - Library-level API operations
93
+
94
+ ### Interfaces
95
+ - `IFile` - Media file interface
96
+ - `ILibrary` - Library interface
97
+ - `ITag` - Tag interface
98
+ - `IPerson` - Person interface
99
+ - `ISerie` - Series interface
100
+ - `IMovie` - Movie interface
101
+ - `IServer` - Server interface
102
+ - `MediaRequest` - Media query filter
103
+ - And more (see `src/interfaces.ts`)
104
+
105
+ ### Encryption Functions
106
+ - `deriveKey()` - Derive encryption key from passphrase
107
+ - `encryptText()` / `decryptText()` - Text encryption
108
+ - `encryptBuffer()` / `decryptBuffer()` - Binary encryption
109
+ - `encryptFile()` / `decryptFile()` - File encryption with metadata
110
+ - `getRandomIV()` - Generate random IV
111
+
112
+ ### Utilities
113
+ - `fetchServerToken()` - Fetch server authentication token
114
+ - Base64 encoding/decoding utilities
115
+ - Crypto utilities for cross-platform support
116
+
117
+ ## Installation
118
+
119
+ ```bash
120
+ npm install @redseat/api
121
+ ```
122
+
123
+ ## Requirements
124
+
125
+ - Node.js 15+ (for Web Crypto API support)
126
+ - TypeScript 5.0+
127
+ - Axios 1.11.0+
128
+
129
+ ## License
130
+
131
+ See the main project LICENSE file.
132
+
package/agents.md ADDED
@@ -0,0 +1,275 @@
1
+ # AI Agent Instructions
2
+
3
+ This document provides guidelines for AI agents working with the `@redseat/api` package. Follow these instructions to maintain code quality and keep documentation up to date.
4
+
5
+ ## Getting Started
6
+
7
+ ### Always Read First
8
+
9
+ 1. **Start with [README.md](README.md)**
10
+ - Understand the package structure
11
+ - Identify which API classes are relevant to your task
12
+ - Find links to specialized documentation
13
+
14
+ 2. **Read Relevant Documentation**
15
+ - [client.md](client.md) - For HTTP client changes
16
+ - [server.md](server.md) - For server API changes
17
+ - [libraries.md](libraries.md) - For library API changes
18
+ - [encryption.md](encryption.md) - For encryption module changes
19
+ - [test.md](test.md) - For testing changes
20
+
21
+ 3. **Examine Source Code**
22
+ - Read the actual implementation files in `src/`
23
+ - Understand the current architecture
24
+ - Check existing patterns and conventions
25
+
26
+ ## Documentation Maintenance
27
+
28
+ ### When Modifying Existing Functionality
29
+
30
+ **Required Actions:**
31
+
32
+ 1. **Update the Relevant Documentation File**
33
+ - If changing `RedseatClient`: Update [client.md](client.md)
34
+ - If changing `ServerApi`: Update [server.md](server.md)
35
+ - If changing `LibraryApi`: Update [libraries.md](libraries.md)
36
+ - If changing encryption: Update [encryption.md](encryption.md)
37
+
38
+ 2. **Update Method Signatures**
39
+ - Document new parameters
40
+ - Document changed return types
41
+ - Document new error cases
42
+ - Update examples if behavior changed
43
+
44
+ 3. **Update README.md if Needed**
45
+ - If API signatures changed significantly
46
+ - If new major features were added
47
+ - If package exports changed
48
+
49
+ 4. **Keep Examples Current**
50
+ - Update code examples to reflect new behavior
51
+ - Ensure examples are runnable
52
+ - Fix broken examples
53
+
54
+ **Example Workflow:**
55
+ ```
56
+ 1. User requests: "Add timeout parameter to getMedia()"
57
+ 2. Read libraries.md to see current getMedia() documentation
58
+ 3. Modify src/library.ts to add timeout parameter
59
+ 4. Update libraries.md with new parameter documentation
60
+ 5. Update example code in libraries.md
61
+ 6. Check if README.md needs updates (probably not for this change)
62
+ ```
63
+
64
+ ### When Adding New Functionality
65
+
66
+ **Required Actions:**
67
+
68
+ 1. **Document in Appropriate File**
69
+ - Add new methods to the relevant documentation file
70
+ - Follow existing formatting and structure
71
+ - Include parameters, return types, and examples
72
+
73
+ 2. **Update README.md**
74
+ - Add to package exports list if it's a new public export
75
+ - Update overview if it's a major feature
76
+ - Add to quick start if it's commonly used
77
+
78
+ 3. **Include Usage Examples**
79
+ - Provide at least one example per new method
80
+ - Show common use cases
81
+ - Include error handling examples
82
+
83
+ 4. **Update Related Documentation**
84
+ - If adding new encryption function: Update [encryption.md](encryption.md)
85
+ - If adding new test: Update [test.md](test.md)
86
+ - Cross-reference related functionality
87
+
88
+ **Example Workflow:**
89
+ ```
90
+ 1. User requests: "Add getMediaStats() method to LibraryApi"
91
+ 2. Implement method in src/library.ts
92
+ 3. Add documentation to libraries.md in "Media" section
93
+ 4. Add example showing usage
94
+ 5. Update README.md exports if needed
95
+ 6. Add test and update test.md if applicable
96
+ ```
97
+
98
+ ## Code Change Workflow
99
+
100
+ ### Before Making Changes
101
+
102
+ 1. **Understand the Request**
103
+ - What functionality is being added/modified?
104
+ - Which files are affected?
105
+ - Are there breaking changes?
106
+
107
+ 2. **Plan the Changes**
108
+ - Identify all files that need modification
109
+ - Identify all documentation that needs updates
110
+ - Consider backward compatibility
111
+
112
+ 3. **Check Dependencies**
113
+ - Will this change affect other parts of the codebase?
114
+ - Are there tests that need updating?
115
+ - Are there examples that need updating?
116
+
117
+ ### During Implementation
118
+
119
+ 1. **Follow Existing Patterns**
120
+ - Match code style and conventions
121
+ - Use similar error handling
122
+ - Follow naming conventions
123
+
124
+ 2. **Write Tests**
125
+ - Add tests for new functionality
126
+ - Update tests for modified functionality
127
+ - Ensure tests pass
128
+
129
+ 3. **Update Documentation As You Go**
130
+ - Don't wait until the end
131
+ - Update docs as you implement
132
+ - This helps catch documentation issues early
133
+
134
+ ### After Implementation
135
+
136
+ 1. **Verify Documentation**
137
+ - Read through your documentation changes
138
+ - Ensure examples are correct
139
+ - Check for typos and formatting
140
+
141
+ 2. **Check Cross-References**
142
+ - Update links if files moved
143
+ - Update related documentation
144
+ - Ensure consistency across files
145
+
146
+ 3. **Test Examples**
147
+ - Verify code examples are syntactically correct
148
+ - Ensure examples demonstrate the feature correctly
149
+ - Check that examples use current API
150
+
151
+ ## Documentation Standards
152
+
153
+ ### Formatting
154
+
155
+ - Use consistent markdown formatting
156
+ - Use code blocks with language tags for code examples
157
+ - Use proper heading hierarchy (## for sections, ### for subsections)
158
+ - Include parameter tables for complex methods
159
+
160
+ ### Code Examples
161
+
162
+ - Always include TypeScript type annotations
163
+ - Show both success and error cases when relevant
164
+ - Include imports when showing complete examples
165
+ - Use realistic variable names
166
+
167
+ ### Method Documentation Template
168
+
169
+ ```markdown
170
+ ### `methodName(param1: Type1, param2: Type2): Promise<ReturnType>`
171
+
172
+ Brief description of what the method does.
173
+
174
+ **Parameters:**
175
+ - `param1`: Description of parameter
176
+ - `param2`: Description of parameter
177
+
178
+ **Returns:** Promise resolving to description
179
+
180
+ **Example:**
181
+ \`\`\`typescript
182
+ const result = await libraryApi.methodName('value1', 'value2');
183
+ \`\`\`
184
+ ```
185
+
186
+ ## Common Scenarios
187
+
188
+ ### Scenario 1: Adding a New Method to LibraryApi
189
+
190
+ 1. Implement method in `src/library.ts`
191
+ 2. Add documentation to [libraries.md](libraries.md) in appropriate section
192
+ 3. Add example code
193
+ 4. Add test to appropriate test file
194
+ 5. Update [test.md](test.md) if new test file created
195
+ 6. Check if [README.md](README.md) needs updates
196
+
197
+ ### Scenario 2: Modifying Encryption Function
198
+
199
+ 1. Modify function in `src/encryption.ts`
200
+ 2. Update [encryption.md](encryption.md) with changes
201
+ 3. Update examples if behavior changed
202
+ 4. Update tests in `src/encryption.test.ts`
203
+ 5. Check if [libraries.md](libraries.md) needs updates (if LibraryApi uses it)
204
+
205
+ ### Scenario 3: Adding New Export
206
+
207
+ 1. Add export to `src/index.ts`
208
+ 2. Update [README.md](README.md) package exports section
209
+ 3. Add documentation to appropriate file
210
+ 4. Add example in README or relevant doc file
211
+
212
+ ### Scenario 4: Breaking Change
213
+
214
+ 1. Document breaking change clearly
215
+ 2. Update all affected documentation
216
+ 3. Update examples to show new usage
217
+ 4. Consider migration guide if significant
218
+
219
+ ## Quality Checklist
220
+
221
+ Before completing a task, verify:
222
+
223
+ - [ ] All code changes are implemented
224
+ - [ ] All relevant documentation is updated
225
+ - [ ] Examples are current and correct
226
+ - [ ] Tests are added/updated
227
+ - [ ] README.md is updated if needed
228
+ - [ ] Cross-references are correct
229
+ - [ ] No broken links
230
+ - [ ] Code follows existing patterns
231
+ - [ ] Documentation is clear and complete
232
+
233
+ ## Error Prevention
234
+
235
+ ### Common Mistakes to Avoid
236
+
237
+ 1. **Forgetting to Update Documentation**
238
+ - Always update docs when code changes
239
+ - Don't assume someone else will do it
240
+
241
+ 2. **Outdated Examples**
242
+ - Verify examples still work
243
+ - Update examples when API changes
244
+
245
+ 3. **Inconsistent Formatting**
246
+ - Follow existing documentation style
247
+ - Use consistent code formatting
248
+
249
+ 4. **Missing Error Cases**
250
+ - Document when methods throw errors
251
+ - Show error handling in examples
252
+
253
+ 5. **Incomplete Documentation**
254
+ - Document all parameters
255
+ - Document return types
256
+ - Include usage examples
257
+
258
+ ## Questions?
259
+
260
+ If you're unsure about:
261
+ - Which documentation file to update
262
+ - How to format documentation
263
+ - Whether a change needs documentation
264
+
265
+ **Default Action:** Update the documentation. It's better to have slightly redundant documentation than missing documentation.
266
+
267
+ ## Related Documentation
268
+
269
+ - [README.md](README.md) - Start here for package overview
270
+ - [client.md](client.md) - RedseatClient documentation
271
+ - [server.md](server.md) - ServerApi documentation
272
+ - [libraries.md](libraries.md) - LibraryApi documentation
273
+ - [encryption.md](encryption.md) - Encryption module documentation
274
+ - [test.md](test.md) - Testing guide
275
+
package/client.md ADDED
@@ -0,0 +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
+
package/dist/auth.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export interface IToken {
2
+ token: string;
3
+ expires: number;
4
+ }
5
+ export declare function fetchServerToken(serverId: string, idToken: string): Promise<IToken>;
package/dist/auth.js ADDED
@@ -0,0 +1,10 @@
1
+ import axios from 'axios';
2
+ export async function fetchServerToken(serverId, idToken) {
3
+ const headers = {
4
+ headers: {
5
+ Authorization: `Bearer ${idToken}`
6
+ }
7
+ };
8
+ const req = await axios.get(`/servers/${serverId}/token`, headers);
9
+ return req.data;
10
+ }