@@ -74,6 +74,86 @@ class ApiClient {
7474 enabledSites : app . extensionSupportedSites ,
7575 } ) ) ;
7676 }
77+
78+ async getSignedUploadUrl ( ) : Promise < {
79+ fields : { [ index : string ] : string } ;
80+ url : string ;
81+ path : string ;
82+ } > {
83+ const organizationId = await storage . get ( 'SELECTED_ORGANIZATION' ) ;
84+ if ( ! organizationId ) {
85+ throw new Error ( ) ;
86+ }
87+
88+ const url = `${ ApiUrl } /v1/cdn/upload-private` ;
89+ const headers = await this . getHeaders ( ) ;
90+
91+ const request = await fetch ( url , {
92+ method : 'POST' ,
93+ headers : {
94+ ...Object . fromEntries ( headers . entries ( ) ) ,
95+ 'X-Organization-Id' : organizationId ,
96+ } ,
97+ body : JSON . stringify ( {
98+ extension : 'pdf' ,
99+ appId : '_extensionTemp' ,
100+ } ) ,
101+ } ) ;
102+
103+ if ( ! request . ok ) {
104+ throw new Error ( `API request failed: ${ request . statusText } ` ) ;
105+ }
106+
107+ const response = await request . json ( ) ;
108+
109+ return response ;
110+ }
111+
112+ uploadFile (
113+ route : string ,
114+ file : FormData ,
115+ onProgress ?: ( progress : number ) => void ,
116+ ) {
117+ return new Promise ( ( resolve , reject ) => {
118+ const req = new XMLHttpRequest ( ) ;
119+ req . open ( 'post' , route ) ;
120+
121+ req . addEventListener (
122+ 'load' ,
123+ ( ) => {
124+ if ( req . status >= 200 && req . status <= 299 ) {
125+ resolve ( req . response ) ;
126+ } else {
127+ reject ( ) ;
128+ }
129+ } ,
130+ false ,
131+ ) ;
132+
133+ req . addEventListener (
134+ 'error' ,
135+ ( ) => {
136+ reject ( ) ;
137+ } ,
138+ false ,
139+ ) ;
140+
141+ req . upload . addEventListener (
142+ 'progress' ,
143+ ( e ) => {
144+ try {
145+ const { loaded, total } = e ;
146+ const progress = Math . floor ( ( loaded / total ) * 100 ) / 100 ;
147+ onProgress ?.( progress ) ;
148+ } catch { }
149+ } ,
150+ false ,
151+ ) ;
152+
153+ // Send file
154+ req . send ( file ) ;
155+ } ) ;
156+ }
77157}
78158
79159export const api = ApiClient . getInstance ( ) ;
0 commit comments