Add onProgress callback to PutConfig
[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     static create(config?: Partial<WebDAVDefaults>, createRequest?: () => XMLHttpRequest) {
7         return new WebDAV(config, createRequest);
8     }
9
10     defaults: WebDAVDefaults = {
11         baseUrl: '',
12         headers: {},
13     };
14
15     propfind = (url: string, config: PropfindConfig = {}) =>
16         this.request({
17             ...config, url,
18             method: 'PROPFIND'
19         })
20
21     put = (url: string, config: PutConfig = {}) =>
22         this.request({
23             ...config, url,
24             method: 'PUT'
25         })
26
27     copy = (url: string, { destination, ...config }: CopyConfig) =>
28         this.request({
29             ...config, url,
30             method: 'COPY',
31             headers: { ...config.headers, Destination: this.defaults.baseUrl + destination }
32         })
33
34     move = (url: string, { destination, ...config }: MoveConfig) =>
35         this.request({
36             ...config, url,
37             method: 'MOVE',
38             headers: { ...config.headers, Destination: this.defaults.baseUrl + destination }
39         })
40
41     delete = (url: string, config: DeleteConfig = {}) =>
42         this.request({
43             ...config, url,
44             method: 'DELETE'
45         })
46
47     private constructor(config?: Partial<WebDAVDefaults>, private createRequest = () => new XMLHttpRequest()) {
48         if (config) {
49             this.defaults = { ...this.defaults, ...config };
50         }
51     }
52
53     private request = (config: RequestConfig) => {
54         return new Promise<XMLHttpRequest>((resolve, reject) => {
55             const r = this.createRequest();
56             r.open(config.method, this.defaults.baseUrl + config.url);
57
58             const headers = { ...this.defaults.headers, ...config.headers };
59             Object
60                 .keys(headers)
61                 .forEach(key => r.setRequestHeader(key, headers[key]));
62
63             if (config.onProgress) {
64                 r.addEventListener('progress', config.onProgress);
65             }
66
67             r.addEventListener('load', () => resolve(r));
68             r.addEventListener('error', () => reject(r));
69
70             r.send(config.data);
71         });
72
73     }
74 }
75
76 export interface PropfindConfig extends BaseConfig { }
77
78 export interface PutConfig extends BaseConfig {
79     data?: any;
80     onProgress?: (event: ProgressEvent) => void;
81 }
82
83 export interface CopyConfig extends BaseConfig {
84     destination: string;
85 }
86
87 export interface MoveConfig extends BaseConfig {
88     destination: string;
89 }
90
91 export interface DeleteConfig extends BaseConfig { }
92
93 interface BaseConfig {
94     headers?: {
95         [key: string]: string;
96     };
97 }
98
99 interface WebDAVDefaults {
100     baseUrl: string;
101     headers: { [key: string]: string };
102 }
103
104 interface RequestConfig {
105     method: string;
106     url: string;
107     headers?: { [key: string]: string };
108     data?: any;
109     onProgress?: (event: ProgressEvent) => void;
110 }