1
1
import { OAuth2Client , generateCodeVerifier } from '@badgateway/oauth2-client' ;
2
- import type { AxiosInstance , AxiosResponse } from 'axios' ;
3
- import defaultAxios from 'axios' ;
2
+ import ky , { KyInstance } from 'ky' ;
4
3
import { v4 as uuid } from 'uuid' ;
5
4
import { OAuthError , RequiredParameterMissingError } from './errors.js' ;
6
5
import type {
@@ -20,7 +19,7 @@ const authorizationURLTimeout = 60_000;
20
19
export class MermaidChart {
21
20
private clientID : string ;
22
21
#baseURL! : string ;
23
- private axios ! : AxiosInstance ;
22
+ private api ! : KyInstance ;
24
23
private oauth ! : OAuth2Client ;
25
24
private pendingStates : Record < string , AuthState > = { } ;
26
25
private redirectURI ! : string ;
@@ -54,17 +53,26 @@ export class MermaidChart {
54
53
tokenEndpoint : URLS . oauth . token ,
55
54
authorizationEndpoint : URLS . oauth . authorize ,
56
55
} ) ;
57
- this . axios = defaultAxios . create ( {
58
- baseURL : this . #baseURL,
59
- timeout : this . requestTimeout ,
60
- } ) ;
61
56
62
- this . axios . interceptors . response . use ( ( res : AxiosResponse ) => {
63
- // Reset token if a 401 is thrown
64
- if ( res . status === 401 ) {
65
- this . resetAccessToken ( ) ;
66
- }
67
- return res ;
57
+ this . api = ky . create ( {
58
+ prefixUrl : this . #baseURL + '/' ,
59
+ timeout : this . requestTimeout ,
60
+ hooks : {
61
+ beforeError : [
62
+ ( error ) => {
63
+ // Reset token if a 401 is thrown
64
+ if ( error . response . status === 401 ) {
65
+ this . resetAccessToken ( ) ;
66
+ }
67
+ return error ;
68
+ } ,
69
+ ] ,
70
+ beforeRequest : [
71
+ ( request ) => {
72
+ request . headers . set ( 'Authorization' , `Bearer ${ this . accessToken } ` ) ;
73
+ } ,
74
+ ] ,
75
+ } ,
68
76
} ) ;
69
77
}
70
78
@@ -151,15 +159,13 @@ export class MermaidChart {
151
159
* @param accessToken - access token to use for requests
152
160
*/
153
161
public async setAccessToken ( accessToken : string ) : Promise < void > {
154
- this . axios . defaults . headers . common [ 'Authorization' ] = `Bearer ${ accessToken } ` ;
162
+ this . accessToken = accessToken ;
155
163
// This is to verify that the token is valid
156
164
await this . getUser ( ) ;
157
- this . accessToken = accessToken ;
158
165
}
159
166
160
167
public resetAccessToken ( ) : void {
161
168
this . accessToken = undefined ;
162
- this . axios . defaults . headers . common [ 'Authorization' ] = `Bearer none` ;
163
169
}
164
170
165
171
/**
@@ -175,42 +181,40 @@ export class MermaidChart {
175
181
}
176
182
177
183
public async getUser ( ) : Promise < MCUser > {
178
- const user = await this . axios . get < MCUser > ( URLS . rest . users . self ) ;
179
- return user . data ;
184
+ const user = await this . api . get < MCUser > ( URLS . rest . users . self ) ;
185
+ return user . json ( ) ;
180
186
}
181
187
182
188
public async getProjects ( ) : Promise < MCProject [ ] > {
183
- const projects = await this . axios . get < MCProject [ ] > ( URLS . rest . projects . list ) ;
184
- return projects . data ;
189
+ const projects = await this . api . get < MCProject [ ] > ( URLS . rest . projects . list ) ;
190
+ return projects . json ( ) ;
185
191
}
186
192
187
193
public async getDocuments ( projectID : string ) : Promise < MCDocument [ ] > {
188
- const projects = await this . axios . get < MCDocument [ ] > (
189
- URLS . rest . projects . get ( projectID ) . documents ,
190
- ) ;
191
- return projects . data ;
194
+ const documents = await this . api . get < MCDocument [ ] > ( URLS . rest . projects . get ( projectID ) . documents ) ;
195
+ return documents . json ( ) ;
192
196
}
193
197
194
198
public async createDocument ( projectID : string ) {
195
- const newDocument = await this . axios . post < MCDocument > (
199
+ const newDocument = await this . api . post < MCDocument > (
196
200
URLS . rest . projects . get ( projectID ) . documents ,
197
- { } , // force sending empty JSON to avoid triggering CSRF check
201
+ { json : { } } , // force sending empty JSON to avoid triggering CSRF check
198
202
) ;
199
- return newDocument . data ;
203
+ return newDocument . json ( ) ;
200
204
}
201
205
202
206
public async getEditURL (
203
207
document : Pick < MCDocument , 'documentID' | 'major' | 'minor' | 'projectID' > ,
204
208
) {
205
- const url = `${ this . #baseURL} ${ URLS . diagram ( document ) . edit } ` ;
209
+ const url = `${ this . #baseURL} / ${ URLS . diagram ( document ) . edit } ` ;
206
210
return url ;
207
211
}
208
212
209
213
public async getDocument (
210
214
document : Pick < MCDocument , 'documentID' > | Pick < MCDocument , 'documentID' | 'major' | 'minor' > ,
211
215
) {
212
- const { data } = await this . axios . get < MCDocument > ( URLS . rest . documents . pick ( document ) . self ) ;
213
- return data ;
216
+ const res = await this . api . get < MCDocument > ( URLS . rest . documents . pick ( document ) . self ) ;
217
+ return res . json ( ) ;
214
218
}
215
219
216
220
/**
@@ -221,16 +225,16 @@ export class MermaidChart {
221
225
public async setDocument (
222
226
document : Pick < MCDocument , 'documentID' | 'projectID' > & Partial < MCDocument > ,
223
227
) {
224
- const { data } = await this . axios . put < { result : 'ok' } | { result : 'failed' ; error : unknown } > (
228
+ const res = await this . api . put < { result : 'ok' } | { result : 'failed' ; error : unknown } > (
225
229
URLS . rest . documents . pick ( document ) . self ,
226
- document ,
230
+ { json : document } ,
227
231
) ;
228
232
229
- if ( data . result === 'failed' ) {
233
+ if ( ! res . ok ) {
230
234
throw new Error (
231
235
`setDocument(${ JSON . stringify ( {
232
236
documentID : document . documentID ,
233
- } ) } failed due to ${ JSON . stringify ( data . error ) } `,
237
+ } ) } failed due to ${ JSON . stringify ( res . statusText ) } `,
234
238
) ;
235
239
}
236
240
}
@@ -241,18 +245,18 @@ export class MermaidChart {
241
245
* @returns Metadata about the deleted document.
242
246
*/
243
247
public async deleteDocument ( documentID : MCDocument [ 'documentID' ] ) {
244
- const deletedDocument = await this . axios . delete < Document > (
248
+ const deletedDocument = await this . api . delete < Document > (
245
249
URLS . rest . documents . pick ( { documentID } ) . self ,
246
- { } , // force sending empty JSON to avoid triggering CSRF check
250
+ { json : { } } , // force sending empty JSON to avoid triggering CSRF check
247
251
) ;
248
- return deletedDocument . data ;
252
+ return deletedDocument . json ( ) ;
249
253
}
250
254
251
255
public async getRawDocument (
252
256
document : Pick < MCDocument , 'documentID' | 'major' | 'minor' > ,
253
257
theme : 'light' | 'dark' ,
254
258
) {
255
- const raw = await this . axios . get < string > ( URLS . raw ( document , theme ) . svg ) ;
256
- return raw . data ;
259
+ const raw = await this . api . get < string > ( URLS . raw ( document , theme ) . svg ) ;
260
+ return raw . text ( ) ;
257
261
}
258
262
}
0 commit comments