refs #14857-new-workbench-affects-files-content
[arvados-workbench2.git] / src / common / webdav.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 export class WebDAV {
6
7     defaults: WebDAVDefaults = {
8         baseURL: '',
9         headers: {},
10     };
11
12     constructor(config?: Partial<WebDAVDefaults>, private createRequest = () => new XMLHttpRequest()) {
13         if (config) {
14             this.defaults = { ...this.defaults, ...config };
15         }
16     }
17
18     propfind = (url: string, config: WebDAVRequestConfig = {}) =>
19         this.request({
20             ...config, url,
21             method: 'PROPFIND'
22         })
23
24     put = (url: string, data?: any, config: WebDAVRequestConfig = {}) =>
25         this.request({
26             ...config, url,
27             method: 'PUT',
28             data
29         })
30
31     upload = (url: string, path: string, files: File[], config: WebDAVRequestConfig = {}) => {
32         return files.map(file => this.request({
33             ...config, url,
34             method: 'PUT',
35             data: file
36         }));
37     }
38
39     copy = (url: string, destination: string, config: WebDAVRequestConfig = {}) =>
40         this.request({
41             ...config, url,
42             method: 'COPY',
43             headers: { ...config.headers, Destination: this.defaults.baseURL + destination }
44         })
45
46     move = (url: string, destination: string, config: WebDAVRequestConfig = {}) =>
47         this.request({
48             ...config, url,
49             method: 'MOVE',
50             headers: { ...config.headers, Destination: this.defaults.baseURL + destination }
51         })
52
53     delete = (url: string, config: WebDAVRequestConfig = {}) =>
54         this.request({
55             ...config, url,
56             method: 'DELETE'
57         })
58
59     private request = (config: RequestConfig) => {
60         return new Promise<XMLHttpRequest>((resolve, reject) => {
61             const r = this.createRequest();
62             r.open(config.method, this.defaults.baseURL + config.url);
63             const headers = { ...this.defaults.headers, ...config.headers };
64             Object
65                 .keys(headers)
66                 .forEach(key => r.setRequestHeader(key, headers[key]));
67
68             if (config.onUploadProgress) {
69                 r.upload.addEventListener('progress', config.onUploadProgress);
70             }
71
72             r.addEventListener('load', () => {
73                 if (r.status === 404) {
74                     return reject(r);
75                 } else {
76                     return resolve(r);
77                 }
78             });
79
80             r.addEventListener('error', () => {
81                 return reject(r);
82             });
83
84             r.upload.addEventListener('error', () => {
85                 return reject(r);
86             });
87
88             r.send(config.data);
89         });
90     }
91 }
92
93 export interface WebDAVRequestConfig {
94     headers?: {
95         [key: string]: string;
96     };
97     onUploadProgress?: (event: ProgressEvent) => void;
98 }
99
100 interface WebDAVDefaults {
101     baseURL: string;
102     headers: { [key: string]: string };
103 }
104
105 interface RequestConfig {
106     method: string;
107     url: string;
108     headers?: { [key: string]: string };
109     data?: any;
110     onUploadProgress?: (event: ProgressEvent) => void;
111 }