@@ -17,17 +17,6 @@ function looksLikeJwt(token: string): boolean {
1717 return / ^ [ A - Z a - z 0 - 9 _ - ] + \. [ A - Z a - z 0 - 9 _ - ] + \. [ A - Z a - z 0 - 9 _ - ] + $ / . test ( token ) ;
1818}
1919
20- /**
21- * Some /api/v1 list endpoints wrap each item as `{comment: {…}}` while /api/v3
22- * returns the comment fields flat. Normalise so callers always see flat shape.
23- */
24- function unwrapV1Item ( item : unknown ) : JobResponse {
25- if ( item && typeof item === 'object' && 'comment' in item && ( item as Record < string , unknown > ) [ 'comment' ] && typeof ( item as Record < string , unknown > ) [ 'comment' ] === 'object' ) {
26- return ( item as { comment : JobResponse } ) . comment ;
27- }
28- return item as JobResponse ;
29- }
30-
3120export class ExportCommentsClient {
3221 private token : string ;
3322 private baseUrl : string ;
@@ -135,57 +124,13 @@ export class ExportCommentsClient {
135124 }
136125 }
137126
138- /**
139- * Returns true when the configured token is an OAuth-issued JWT. OAuth users
140- * are routed through the same `/api/v1/*` endpoints the web dashboard uses
141- * (per-user rate-limits, no `X-AUTH-TOKEN` required). Legacy API tokens stay
142- * on `/api/v3/*` (developer API, per-token rate-limits).
143- */
144- private get useUserApi ( ) : boolean {
145- return looksLikeJwt ( this . token ) ;
146- }
147-
148127 /** Create a new export job */
149128 async createJob ( req : CreateJobRequest ) : Promise < CLIOutput < JobResponse > > {
150- if ( this . useUserApi ) {
151- // The user-API returns HTTP 400 with `{error: "export.unfinished", guid}`
152- // when a new export is accepted and queued (it's not an actual error — the
153- // guid is the handle to poll with). Read the body ourselves so we can
154- // unwrap that case into an `ok: true` response with the guid.
155- const v1BaseUrl = this . baseUrl . replace ( '/v3' , '/v1' ) ;
156- try {
157- const res = await fetch ( `${ v1BaseUrl } /job` , {
158- method : 'POST' ,
159- headers : this . headers ,
160- body : JSON . stringify ( req ) ,
161- } ) ;
162- const text = await res . text ( ) ;
163- let data : Record < string , unknown > | null = null ;
164- try { data = JSON . parse ( text ) ; } catch { /* non-JSON */ }
165- if ( data && typeof data === 'object' && data [ 'error' ] === 'export.unfinished' && typeof data [ 'guid' ] === 'string' ) {
166- return { ok : true , data : { guid : data [ 'guid' ] as string , status : 'queueing' } as JobResponse } ;
167- }
168- if ( res . ok && data ) {
169- return { ok : true , data : data as unknown as JobResponse } ;
170- }
171- return {
172- ok : false ,
173- error : ( data ?. [ 'error' ] as string | undefined ) ?? `HTTP ${ res . status } ` ,
174- error_code : data ?. [ 'error_code' ] as string | undefined ,
175- detail : data ?. [ 'detail' ] as string | undefined ,
176- } ;
177- } catch ( err ) {
178- return { ok : false , error : err instanceof Error ? err . message : String ( err ) } ;
179- }
180- }
181129 return this . request < JobResponse > ( 'POST' , '/job' , req ) ;
182130 }
183131
184132 /** Check the status of an export job */
185133 async getJob ( guid : string ) : Promise < CLIOutput < JobResponse > > {
186- if ( this . useUserApi ) {
187- return this . v1Request < JobResponse > ( 'GET' , `/job/${ guid } ` ) ;
188- }
189134 return this . request < JobResponse > ( 'GET' , `/job/${ guid } ` ) ;
190135 }
191136
@@ -194,30 +139,12 @@ export class ExportCommentsClient {
194139 page = 1 ,
195140 limit = 20
196141 ) : Promise < CLIOutput < JobResponse [ ] > > {
197- if ( this . useUserApi ) {
198- // /api/v1/jobs returns {metadata, items:[{comment:{…}}] } — unwrap.
199- const res = await this . v1Request < { items ?: unknown [ ] } > (
200- 'GET' ,
201- `/jobs?page=${ page } &limit=${ limit } `
202- ) ;
203- if ( ! res . ok ) return { ok : false , error : res . error , error_code : res . error_code , detail : res . detail } ;
204- const items = ( res . data ?. items ?? [ ] ) . map ( unwrapV1Item ) ;
205- return { ok : true , data : items } ;
206- }
207142 return this . request < JobResponse [ ] > (
208143 'GET' ,
209144 `/jobs?page=${ page } &limit=${ limit } `
210145 ) ;
211146 }
212147
213- /** Stop a queued or in-progress export */
214- async stopJob ( guid : string ) : Promise < CLIOutput < unknown > > {
215- if ( this . useUserApi ) {
216- return this . v1Request ( 'POST' , `/jobs/${ guid } /stop` ) ;
217- }
218- return this . request ( 'PATCH' , `/job/${ guid } /stop` ) ;
219- }
220-
221148 /** Download a file from a direct URL, saving it to disk */
222149 private async downloadFile (
223150 fileUrl : string ,
0 commit comments