@contello/uploader 8.21.4 → 8.21.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.cjs +149 -205
- package/dist/index.d.cts +92 -91
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +92 -91
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +149 -177
- package/dist/index.js.map +1 -0
- package/package.json +8 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2026 entwico GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -1,211 +1,155 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
ContelloUploader: () => ContelloUploader,
|
|
24
|
-
UploadAssetRetentionPolicy: () => UploadAssetRetentionPolicy
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(index_exports);
|
|
27
|
-
|
|
28
|
-
// src/upload-metadata.ts
|
|
29
|
-
var UploadAssetRetentionPolicy = /* @__PURE__ */ ((UploadAssetRetentionPolicy2) => {
|
|
30
|
-
UploadAssetRetentionPolicy2["retain"] = "retain";
|
|
31
|
-
UploadAssetRetentionPolicy2["deleteIfNotUsed"] = "deleteIfNotUsed";
|
|
32
|
-
return UploadAssetRetentionPolicy2;
|
|
33
|
-
})(UploadAssetRetentionPolicy || {});
|
|
34
|
-
|
|
35
|
-
// src/uploader.ts
|
|
36
|
-
var import_rxjs3 = require("rxjs");
|
|
37
|
-
|
|
38
|
-
// src/implementations/ws.ts
|
|
39
|
-
var import_rxjs = require("rxjs");
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let rxjs = require("rxjs");
|
|
3
|
+
//#region src/upload-metadata.ts
|
|
4
|
+
let UploadAssetRetentionPolicy = /* @__PURE__ */ function(UploadAssetRetentionPolicy) {
|
|
5
|
+
UploadAssetRetentionPolicy["retain"] = "retain";
|
|
6
|
+
UploadAssetRetentionPolicy["deleteIfNotUsed"] = "deleteIfNotUsed";
|
|
7
|
+
return UploadAssetRetentionPolicy;
|
|
8
|
+
}({});
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/implementations/ws.ts
|
|
11
|
+
/** Uploads a file via WebSocket using chunked binary transfer. Emits progress events and the asset ID on completion. */
|
|
40
12
|
function uploadViaWebSocket({ url, project, token, chunkSize }, file, meta, options) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
obs.complete();
|
|
123
|
-
} else {
|
|
124
|
-
obs.error(new Error("No asset id received"));
|
|
125
|
-
}
|
|
126
|
-
return ws.close();
|
|
127
|
-
}
|
|
128
|
-
obs.error(new Error(`WebSocket message with unknown type ${JSON.stringify(message)}`));
|
|
129
|
-
ws.close();
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
|
-
ws.onerror = (error) => obs.error(error);
|
|
133
|
-
ws.onclose = () => {
|
|
134
|
-
if (!done) {
|
|
135
|
-
obs.error(new Error("Connection closed"));
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
const abortHandler = () => {
|
|
139
|
-
if (!done) {
|
|
140
|
-
reader?.abort();
|
|
141
|
-
ws.close();
|
|
142
|
-
obs.error(new Error("Upload aborted"));
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
options?.abort?.addEventListener("abort", abortHandler);
|
|
146
|
-
return () => {
|
|
147
|
-
options?.abort?.removeEventListener("abort", abortHandler);
|
|
148
|
-
ws.close();
|
|
149
|
-
};
|
|
150
|
-
});
|
|
13
|
+
const metadata = {
|
|
14
|
+
...meta,
|
|
15
|
+
projectRef: project
|
|
16
|
+
};
|
|
17
|
+
return new rxjs.Observable((obs) => {
|
|
18
|
+
const parsedUrl = new URL(url);
|
|
19
|
+
const ws = new WebSocket(`${parsedUrl.protocol === "https:" ? "wss" : "ws"}://${parsedUrl.host}/api/v1/assets/ws`, "contello-file-upload-v1");
|
|
20
|
+
let offset = 0;
|
|
21
|
+
let done = false;
|
|
22
|
+
let ackReceived = false;
|
|
23
|
+
ws.addEventListener("open", () => {
|
|
24
|
+
const initFrame = {
|
|
25
|
+
type: "init",
|
|
26
|
+
metadata: {
|
|
27
|
+
...metadata,
|
|
28
|
+
name: file.name,
|
|
29
|
+
mimeType: file.type,
|
|
30
|
+
size: file.size
|
|
31
|
+
},
|
|
32
|
+
token
|
|
33
|
+
};
|
|
34
|
+
ws.send(JSON.stringify(initFrame));
|
|
35
|
+
function readSlice() {
|
|
36
|
+
(async () => {
|
|
37
|
+
try {
|
|
38
|
+
handleArrayBuffer(await file.slice(offset, offset + chunkSize).arrayBuffer());
|
|
39
|
+
} catch (error) {
|
|
40
|
+
obs.error(error);
|
|
41
|
+
}
|
|
42
|
+
})();
|
|
43
|
+
}
|
|
44
|
+
function markAsDone() {
|
|
45
|
+
ws.send(JSON.stringify({ type: "done" }));
|
|
46
|
+
}
|
|
47
|
+
function startUpload() {
|
|
48
|
+
if (ackReceived) readSlice();
|
|
49
|
+
}
|
|
50
|
+
function handleArrayBuffer(buffer) {
|
|
51
|
+
if (options?.abort?.aborted) return;
|
|
52
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
53
|
+
ws.send(buffer);
|
|
54
|
+
offset += buffer.byteLength;
|
|
55
|
+
if (offset < file.size) readSlice();
|
|
56
|
+
else markAsDone();
|
|
57
|
+
} else obs.error(/* @__PURE__ */ new Error("WebSocket is closed"));
|
|
58
|
+
}
|
|
59
|
+
ws.addEventListener("message", (event) => {
|
|
60
|
+
const message = JSON.parse(event.data);
|
|
61
|
+
if (message.type === "ack") {
|
|
62
|
+
ackReceived = true;
|
|
63
|
+
startUpload();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (message.type === "progress") return obs.next({ progress: message.bytesReceived / file.size * 100 });
|
|
67
|
+
if (message.type === "done") {
|
|
68
|
+
if (message.id) {
|
|
69
|
+
done = true;
|
|
70
|
+
obs.next({ id: message.id });
|
|
71
|
+
obs.complete();
|
|
72
|
+
} else obs.error(/* @__PURE__ */ new Error("No asset id received"));
|
|
73
|
+
return ws.close();
|
|
74
|
+
}
|
|
75
|
+
obs.error(/* @__PURE__ */ new Error(`WebSocket message with unknown type ${JSON.stringify(message)}`));
|
|
76
|
+
ws.close();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
ws.addEventListener("error", (error) => obs.error(error));
|
|
80
|
+
ws.addEventListener("close", () => {
|
|
81
|
+
if (!done) obs.error(/* @__PURE__ */ new Error("Connection closed"));
|
|
82
|
+
});
|
|
83
|
+
const abortHandler = () => {
|
|
84
|
+
if (done) return;
|
|
85
|
+
ws.close();
|
|
86
|
+
obs.error(/* @__PURE__ */ new Error("Upload aborted"));
|
|
87
|
+
};
|
|
88
|
+
options?.abort?.addEventListener("abort", abortHandler);
|
|
89
|
+
return () => {
|
|
90
|
+
options?.abort?.removeEventListener("abort", abortHandler);
|
|
91
|
+
ws.close();
|
|
92
|
+
};
|
|
93
|
+
});
|
|
151
94
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/implementations/xhr.ts
|
|
97
|
+
/** Uploads a file via XMLHttpRequest with multipart form data. Emits progress events and the asset ID on completion. */
|
|
155
98
|
function uploadViaXhr({ url, project, token }, file, meta, options) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
99
|
+
return new rxjs.Observable((obs) => {
|
|
100
|
+
const data = new FormData();
|
|
101
|
+
data.append("metadata", JSON.stringify({
|
|
102
|
+
...meta,
|
|
103
|
+
projectRef: project
|
|
104
|
+
}));
|
|
105
|
+
data.append("file", file);
|
|
106
|
+
const xhr = new XMLHttpRequest();
|
|
107
|
+
xhr.open("POST", `${url}/api/v1/assets`, true);
|
|
108
|
+
xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
|
109
|
+
xhr.upload.addEventListener("progress", (event) => {
|
|
110
|
+
if (event.lengthComputable) obs.next({ progress: event.loaded / event.total * 100 });
|
|
111
|
+
});
|
|
112
|
+
xhr.addEventListener("load", () => {
|
|
113
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
114
|
+
const { id } = JSON.parse(xhr.responseText);
|
|
115
|
+
obs.next({ id });
|
|
116
|
+
return obs.complete();
|
|
117
|
+
}
|
|
118
|
+
obs.error(/* @__PURE__ */ new Error(`${xhr.status}: ${xhr.statusText}`));
|
|
119
|
+
});
|
|
120
|
+
xhr.addEventListener("error", (error) => obs.error(error));
|
|
121
|
+
xhr.send(data);
|
|
122
|
+
options?.abort?.addEventListener("abort", () => xhr.abort());
|
|
123
|
+
return () => xhr.abort();
|
|
124
|
+
});
|
|
181
125
|
}
|
|
182
|
-
|
|
183
|
-
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/uploader.ts
|
|
128
|
+
/**
|
|
129
|
+
* ContelloUploader is a class for uploading files to a Contello server.
|
|
130
|
+
* It supports both WebSocket and HTTP transports.
|
|
131
|
+
*/
|
|
184
132
|
var ContelloUploader = class {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return uploadViaWebSocket(this.params, file, meta, options);
|
|
205
|
-
}
|
|
133
|
+
params;
|
|
134
|
+
constructor(params) {
|
|
135
|
+
this.params = {
|
|
136
|
+
url: params.url,
|
|
137
|
+
project: params.project,
|
|
138
|
+
token: params.token,
|
|
139
|
+
transport: params.transport || "ws",
|
|
140
|
+
chunkSize: params.chunkSize || 4 * 1024 * 1024
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** Uploads a file and resolves with the asset ID once complete. */
|
|
144
|
+
async upload(file, meta, options) {
|
|
145
|
+
return (0, rxjs.firstValueFrom)(this.uploadWithEvents(file, meta, options).pipe((0, rxjs.filter)((r) => "id" in r)));
|
|
146
|
+
}
|
|
147
|
+
/** Uploads a file and returns an Observable emitting progress events and the final asset ID. */
|
|
148
|
+
uploadWithEvents(file, meta, options) {
|
|
149
|
+
if (this.params.transport === "http") return uploadViaXhr(this.params, file, meta, options);
|
|
150
|
+
return uploadViaWebSocket(this.params, file, meta, options);
|
|
151
|
+
}
|
|
206
152
|
};
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
UploadAssetRetentionPolicy
|
|
211
|
-
});
|
|
153
|
+
//#endregion
|
|
154
|
+
exports.ContelloUploader = ContelloUploader;
|
|
155
|
+
exports.UploadAssetRetentionPolicy = UploadAssetRetentionPolicy;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,122 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/upload-metadata.d.ts
|
|
3
2
|
type UploadAssetMetadata = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
name?: string | undefined;
|
|
4
|
+
mimeType?: string | undefined;
|
|
5
|
+
size?: number | undefined;
|
|
6
|
+
annotations?: UploadAssetAnnotation[] | undefined;
|
|
7
|
+
collectionRefs?: string[] | undefined;
|
|
8
|
+
image?: UploadAssetImageMetadata | undefined;
|
|
9
|
+
retentionPolicy?: UploadAssetRetentionPolicy | undefined;
|
|
10
|
+
generatePreview?: boolean | undefined;
|
|
11
|
+
createdAt?: string | undefined;
|
|
12
|
+
updatedAt?: string | undefined;
|
|
14
13
|
};
|
|
15
14
|
type UploadAssetAnnotation = {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
key: string;
|
|
16
|
+
value: string;
|
|
18
17
|
};
|
|
19
18
|
type UploadAssetProgress = {
|
|
20
|
-
|
|
19
|
+
progress: number;
|
|
21
20
|
};
|
|
22
21
|
declare enum UploadAssetRetentionPolicy {
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
retain = "retain",
|
|
23
|
+
deleteIfNotUsed = "deleteIfNotUsed"
|
|
25
24
|
}
|
|
26
25
|
type UploadAssetImageMetadata = {
|
|
27
|
-
|
|
26
|
+
transformations: UploadAssetImageTransformation[];
|
|
28
27
|
};
|
|
29
28
|
type UploadAssetImageTransformation = UploadAssetExtractTransformation | UploadAssetFitTransformation | UploadAssetConvertTransformation;
|
|
30
29
|
type UploadAssetExtractTransformation = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
name: 'extract';
|
|
31
|
+
options: {
|
|
32
|
+
top: number;
|
|
33
|
+
left: number;
|
|
34
|
+
areaWidth: number;
|
|
35
|
+
areaHeight: number;
|
|
36
|
+
rotate?: 0 | 90 | 180 | 270 | undefined;
|
|
37
|
+
};
|
|
39
38
|
};
|
|
40
39
|
type UploadAssetFitTransformation = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
name: 'fit';
|
|
41
|
+
options: {
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
};
|
|
46
45
|
};
|
|
47
46
|
type UploadAssetConvertTransformation = {
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
name: 'convert';
|
|
48
|
+
options: UploadAssetConvertTransformationJpegOptions | UploadAssetConvertTransformationPngOptions | UploadAssetConvertTransformationAvifOptions;
|
|
50
49
|
};
|
|
51
50
|
type UploadAssetConvertTransformationJpegOptions = {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
format: 'jpeg';
|
|
52
|
+
options: {
|
|
53
|
+
quality: number;
|
|
54
|
+
interlace: boolean;
|
|
55
|
+
};
|
|
57
56
|
};
|
|
58
57
|
type UploadAssetConvertTransformationPngOptions = {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
format: 'png';
|
|
59
|
+
options: {
|
|
60
|
+
compressionLevel: number;
|
|
61
|
+
};
|
|
63
62
|
};
|
|
64
63
|
type UploadAssetConvertTransformationAvifOptions = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
format: 'avif';
|
|
65
|
+
options: {
|
|
66
|
+
quality: number;
|
|
67
|
+
lossless: boolean;
|
|
68
|
+
};
|
|
70
69
|
};
|
|
71
|
-
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/uploader.d.ts
|
|
72
72
|
type ContelloUploaderParams = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Base URL of the Contello server.
|
|
75
|
+
* Example: 'https://example.com'
|
|
76
|
+
*/
|
|
77
|
+
url: string;
|
|
78
|
+
/**
|
|
79
|
+
* Project identifier for the Contello project.
|
|
80
|
+
* Example: 'myProjectId'
|
|
81
|
+
*/
|
|
82
|
+
project: string;
|
|
83
|
+
/**
|
|
84
|
+
* Authentication token for the Contello API.
|
|
85
|
+
* Example: 'app-a123b456c7890d123456789'
|
|
86
|
+
*/
|
|
87
|
+
token: string;
|
|
88
|
+
/**
|
|
89
|
+
* Transport protocol to use for uploading files.
|
|
90
|
+
* 'http' uses XMLHttpRequest, 'ws' uses WebSocket.
|
|
91
|
+
* @default 'ws'
|
|
92
|
+
*/
|
|
93
|
+
transport?: 'http' | 'ws';
|
|
94
|
+
/**
|
|
95
|
+
* Size of each chunk in bytes when uploading files.
|
|
96
|
+
* Default is 4MB.
|
|
97
|
+
* @default 4_194_304
|
|
98
|
+
*/
|
|
99
|
+
chunkSize?: number;
|
|
100
100
|
};
|
|
101
101
|
/**
|
|
102
102
|
* ContelloUploader is a class for uploading files to a Contello server.
|
|
103
103
|
* It supports both WebSocket and HTTP transports.
|
|
104
104
|
*/
|
|
105
105
|
declare class ContelloUploader {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
106
|
+
private params;
|
|
107
|
+
constructor(params: ContelloUploaderParams);
|
|
108
|
+
/** Uploads a file and resolves with the asset ID once complete. */
|
|
109
|
+
upload(file: File, meta?: UploadAssetMetadata | undefined, options?: {
|
|
110
|
+
abort?: AbortSignal;
|
|
111
|
+
} | undefined): Promise<{
|
|
112
|
+
id: string;
|
|
113
|
+
}>;
|
|
114
|
+
/** Uploads a file and returns an Observable emitting progress events and the final asset ID. */
|
|
115
|
+
uploadWithEvents(file: File, meta?: UploadAssetMetadata | undefined, options?: {
|
|
116
|
+
abort?: AbortSignal;
|
|
117
|
+
} | undefined): import("rxjs").Observable<UploadAssetProgress | {
|
|
118
|
+
id: string;
|
|
119
|
+
}>;
|
|
120
120
|
}
|
|
121
|
-
|
|
122
|
-
export { ContelloUploader,
|
|
121
|
+
//#endregion
|
|
122
|
+
export { ContelloUploader, ContelloUploaderParams, UploadAssetAnnotation, UploadAssetConvertTransformation, UploadAssetConvertTransformationAvifOptions, UploadAssetConvertTransformationJpegOptions, UploadAssetConvertTransformationPngOptions, UploadAssetExtractTransformation, UploadAssetFitTransformation, UploadAssetImageMetadata, UploadAssetImageTransformation, UploadAssetMetadata, UploadAssetProgress, UploadAssetRetentionPolicy };
|
|
123
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/upload-metadata.ts","../src/uploader.ts"],"mappings":";KAAY,mBAAA;EACV,IAAA;EACA,QAAA;EACA,IAAA;EACA,WAAA,GAAc,qBAAA;EACd,cAAA;EACA,KAAA,GAAQ,wBAAA;EACR,eAAA,GAAkB,0BAAA;EAClB,eAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,KAGU,qBAAA;EACV,GAAA;EACA,KAAK;AAAA;AAAA,KAGK,mBAAA;EACV,QAAQ;AAAA;AAAA,aAGE,0BAAA;EACV,MAAA;EACA,eAAe;AAAA;AAAA,KAGL,wBAAA;EACV,eAAA,EAAiB,8BAA8B;AAAA;AAAA,KAGrC,8BAAA,GACR,gCAAA,GACA,4BAAA,GACA,gCAAA;AAAA,KAEQ,gCAAA;EACV,IAAA;EACA,OAAA;IACE,GAAA;IACA,IAAA;IACA,SAAA;IACA,UAAA;IACA,MAAA;EAAA;AAAA;AAAA,KAIQ,4BAAA;EACV,IAAA;EACA,OAAA;IACE,KAAA;IACA,MAAA;EAAA;AAAA;AAAA,KAIQ,gCAAA;EACV,IAAA;EACA,OAAA,EACI,2CAAA,GACA,0CAAA,GACA,2CAAA;AAAA;AAAA,KAGM,2CAAA;EACV,MAAA;EACA,OAAA;IACE,OAAA;IACA,SAAA;EAAA;AAAA;AAAA,KAIQ,0CAAA;EACV,MAAA;EACA,OAAA;IACE,gBAAA;EAAA;AAAA;AAAA,KAIQ,2CAAA;EACV,MAAA;EACA,OAAA;IACE,OAAA;IACA,QAAA;EAAA;AAAA;;;KC7EQ,sBAAA;EDLmB;;;;ECU7B,GAAA;EDH4C;;;;ECQ5C,OAAA;EDXA;;;;ECgBA,KAAA;EDbA;;;;;ECmBA,SAAA;EDhBS;AAGX;;;;ECmBE,SAAA;AAAA;;;;ADbQ;cCoBG,gBAAA;EAAA,QACH,MAAA;cAEI,MAAA,EAAQ,sBAAA;EDnBpB;EC8BM,MAAA,CACJ,IAAA,EAAM,IAAA,EACN,IAAA,GAAO,mBAAA,cACP,OAAA;IAAY,KAAA,GAAQ,WAAA;EAAA,gBACnB,OAAA;IAAU,EAAA;EAAA;ED7BkC;ECkC/C,gBAAA,CAAiB,IAAA,EAAM,IAAA,EAAM,IAAA,GAAO,mBAAA,cAAiC,OAAA;IAAY,KAAA,GAAQ,WAAA;EAAA,+BAAyB,UAAA,CAAd,mBAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,122 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/upload-metadata.d.ts
|
|
3
2
|
type UploadAssetMetadata = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
name?: string | undefined;
|
|
4
|
+
mimeType?: string | undefined;
|
|
5
|
+
size?: number | undefined;
|
|
6
|
+
annotations?: UploadAssetAnnotation[] | undefined;
|
|
7
|
+
collectionRefs?: string[] | undefined;
|
|
8
|
+
image?: UploadAssetImageMetadata | undefined;
|
|
9
|
+
retentionPolicy?: UploadAssetRetentionPolicy | undefined;
|
|
10
|
+
generatePreview?: boolean | undefined;
|
|
11
|
+
createdAt?: string | undefined;
|
|
12
|
+
updatedAt?: string | undefined;
|
|
14
13
|
};
|
|
15
14
|
type UploadAssetAnnotation = {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
key: string;
|
|
16
|
+
value: string;
|
|
18
17
|
};
|
|
19
18
|
type UploadAssetProgress = {
|
|
20
|
-
|
|
19
|
+
progress: number;
|
|
21
20
|
};
|
|
22
21
|
declare enum UploadAssetRetentionPolicy {
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
retain = "retain",
|
|
23
|
+
deleteIfNotUsed = "deleteIfNotUsed"
|
|
25
24
|
}
|
|
26
25
|
type UploadAssetImageMetadata = {
|
|
27
|
-
|
|
26
|
+
transformations: UploadAssetImageTransformation[];
|
|
28
27
|
};
|
|
29
28
|
type UploadAssetImageTransformation = UploadAssetExtractTransformation | UploadAssetFitTransformation | UploadAssetConvertTransformation;
|
|
30
29
|
type UploadAssetExtractTransformation = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
name: 'extract';
|
|
31
|
+
options: {
|
|
32
|
+
top: number;
|
|
33
|
+
left: number;
|
|
34
|
+
areaWidth: number;
|
|
35
|
+
areaHeight: number;
|
|
36
|
+
rotate?: 0 | 90 | 180 | 270 | undefined;
|
|
37
|
+
};
|
|
39
38
|
};
|
|
40
39
|
type UploadAssetFitTransformation = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
name: 'fit';
|
|
41
|
+
options: {
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
};
|
|
46
45
|
};
|
|
47
46
|
type UploadAssetConvertTransformation = {
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
name: 'convert';
|
|
48
|
+
options: UploadAssetConvertTransformationJpegOptions | UploadAssetConvertTransformationPngOptions | UploadAssetConvertTransformationAvifOptions;
|
|
50
49
|
};
|
|
51
50
|
type UploadAssetConvertTransformationJpegOptions = {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
format: 'jpeg';
|
|
52
|
+
options: {
|
|
53
|
+
quality: number;
|
|
54
|
+
interlace: boolean;
|
|
55
|
+
};
|
|
57
56
|
};
|
|
58
57
|
type UploadAssetConvertTransformationPngOptions = {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
format: 'png';
|
|
59
|
+
options: {
|
|
60
|
+
compressionLevel: number;
|
|
61
|
+
};
|
|
63
62
|
};
|
|
64
63
|
type UploadAssetConvertTransformationAvifOptions = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
format: 'avif';
|
|
65
|
+
options: {
|
|
66
|
+
quality: number;
|
|
67
|
+
lossless: boolean;
|
|
68
|
+
};
|
|
70
69
|
};
|
|
71
|
-
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/uploader.d.ts
|
|
72
72
|
type ContelloUploaderParams = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Base URL of the Contello server.
|
|
75
|
+
* Example: 'https://example.com'
|
|
76
|
+
*/
|
|
77
|
+
url: string;
|
|
78
|
+
/**
|
|
79
|
+
* Project identifier for the Contello project.
|
|
80
|
+
* Example: 'myProjectId'
|
|
81
|
+
*/
|
|
82
|
+
project: string;
|
|
83
|
+
/**
|
|
84
|
+
* Authentication token for the Contello API.
|
|
85
|
+
* Example: 'app-a123b456c7890d123456789'
|
|
86
|
+
*/
|
|
87
|
+
token: string;
|
|
88
|
+
/**
|
|
89
|
+
* Transport protocol to use for uploading files.
|
|
90
|
+
* 'http' uses XMLHttpRequest, 'ws' uses WebSocket.
|
|
91
|
+
* @default 'ws'
|
|
92
|
+
*/
|
|
93
|
+
transport?: 'http' | 'ws';
|
|
94
|
+
/**
|
|
95
|
+
* Size of each chunk in bytes when uploading files.
|
|
96
|
+
* Default is 4MB.
|
|
97
|
+
* @default 4_194_304
|
|
98
|
+
*/
|
|
99
|
+
chunkSize?: number;
|
|
100
100
|
};
|
|
101
101
|
/**
|
|
102
102
|
* ContelloUploader is a class for uploading files to a Contello server.
|
|
103
103
|
* It supports both WebSocket and HTTP transports.
|
|
104
104
|
*/
|
|
105
105
|
declare class ContelloUploader {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
106
|
+
private params;
|
|
107
|
+
constructor(params: ContelloUploaderParams);
|
|
108
|
+
/** Uploads a file and resolves with the asset ID once complete. */
|
|
109
|
+
upload(file: File, meta?: UploadAssetMetadata | undefined, options?: {
|
|
110
|
+
abort?: AbortSignal;
|
|
111
|
+
} | undefined): Promise<{
|
|
112
|
+
id: string;
|
|
113
|
+
}>;
|
|
114
|
+
/** Uploads a file and returns an Observable emitting progress events and the final asset ID. */
|
|
115
|
+
uploadWithEvents(file: File, meta?: UploadAssetMetadata | undefined, options?: {
|
|
116
|
+
abort?: AbortSignal;
|
|
117
|
+
} | undefined): import("rxjs").Observable<UploadAssetProgress | {
|
|
118
|
+
id: string;
|
|
119
|
+
}>;
|
|
120
120
|
}
|
|
121
|
-
|
|
122
|
-
export { ContelloUploader,
|
|
121
|
+
//#endregion
|
|
122
|
+
export { ContelloUploader, ContelloUploaderParams, UploadAssetAnnotation, UploadAssetConvertTransformation, UploadAssetConvertTransformationAvifOptions, UploadAssetConvertTransformationJpegOptions, UploadAssetConvertTransformationPngOptions, UploadAssetExtractTransformation, UploadAssetFitTransformation, UploadAssetImageMetadata, UploadAssetImageTransformation, UploadAssetMetadata, UploadAssetProgress, UploadAssetRetentionPolicy };
|
|
123
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/upload-metadata.ts","../src/uploader.ts"],"mappings":";KAAY,mBAAA;EACV,IAAA;EACA,QAAA;EACA,IAAA;EACA,WAAA,GAAc,qBAAA;EACd,cAAA;EACA,KAAA,GAAQ,wBAAA;EACR,eAAA,GAAkB,0BAAA;EAClB,eAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,KAGU,qBAAA;EACV,GAAA;EACA,KAAK;AAAA;AAAA,KAGK,mBAAA;EACV,QAAQ;AAAA;AAAA,aAGE,0BAAA;EACV,MAAA;EACA,eAAe;AAAA;AAAA,KAGL,wBAAA;EACV,eAAA,EAAiB,8BAA8B;AAAA;AAAA,KAGrC,8BAAA,GACR,gCAAA,GACA,4BAAA,GACA,gCAAA;AAAA,KAEQ,gCAAA;EACV,IAAA;EACA,OAAA;IACE,GAAA;IACA,IAAA;IACA,SAAA;IACA,UAAA;IACA,MAAA;EAAA;AAAA;AAAA,KAIQ,4BAAA;EACV,IAAA;EACA,OAAA;IACE,KAAA;IACA,MAAA;EAAA;AAAA;AAAA,KAIQ,gCAAA;EACV,IAAA;EACA,OAAA,EACI,2CAAA,GACA,0CAAA,GACA,2CAAA;AAAA;AAAA,KAGM,2CAAA;EACV,MAAA;EACA,OAAA;IACE,OAAA;IACA,SAAA;EAAA;AAAA;AAAA,KAIQ,0CAAA;EACV,MAAA;EACA,OAAA;IACE,gBAAA;EAAA;AAAA;AAAA,KAIQ,2CAAA;EACV,MAAA;EACA,OAAA;IACE,OAAA;IACA,QAAA;EAAA;AAAA;;;KC7EQ,sBAAA;EDLmB;;;;ECU7B,GAAA;EDH4C;;;;ECQ5C,OAAA;EDXA;;;;ECgBA,KAAA;EDbA;;;;;ECmBA,SAAA;EDhBS;AAGX;;;;ECmBE,SAAA;AAAA;;;;ADbQ;cCoBG,gBAAA;EAAA,QACH,MAAA;cAEI,MAAA,EAAQ,sBAAA;EDnBpB;EC8BM,MAAA,CACJ,IAAA,EAAM,IAAA,EACN,IAAA,GAAO,mBAAA,cACP,OAAA;IAAY,KAAA,GAAQ,WAAA;EAAA,gBACnB,OAAA;IAAU,EAAA;EAAA;ED7BkC;ECkC/C,gBAAA,CAAiB,IAAA,EAAM,IAAA,EAAM,IAAA,GAAO,mBAAA,cAAiC,OAAA;IAAY,KAAA,GAAQ,WAAA;EAAA,+BAAyB,UAAA,CAAd,mBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,183 +1,155 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// src/implementations/ws.ts
|
|
12
|
-
import { Observable } from "rxjs";
|
|
1
|
+
import { Observable, filter, firstValueFrom } from "rxjs";
|
|
2
|
+
//#region src/upload-metadata.ts
|
|
3
|
+
let UploadAssetRetentionPolicy = /* @__PURE__ */ function(UploadAssetRetentionPolicy) {
|
|
4
|
+
UploadAssetRetentionPolicy["retain"] = "retain";
|
|
5
|
+
UploadAssetRetentionPolicy["deleteIfNotUsed"] = "deleteIfNotUsed";
|
|
6
|
+
return UploadAssetRetentionPolicy;
|
|
7
|
+
}({});
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/implementations/ws.ts
|
|
10
|
+
/** Uploads a file via WebSocket using chunked binary transfer. Emits progress events and the asset ID on completion. */
|
|
13
11
|
function uploadViaWebSocket({ url, project, token, chunkSize }, file, meta, options) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
obs.complete();
|
|
96
|
-
} else {
|
|
97
|
-
obs.error(new Error("No asset id received"));
|
|
98
|
-
}
|
|
99
|
-
return ws.close();
|
|
100
|
-
}
|
|
101
|
-
obs.error(new Error(`WebSocket message with unknown type ${JSON.stringify(message)}`));
|
|
102
|
-
ws.close();
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
ws.onerror = (error) => obs.error(error);
|
|
106
|
-
ws.onclose = () => {
|
|
107
|
-
if (!done) {
|
|
108
|
-
obs.error(new Error("Connection closed"));
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const abortHandler = () => {
|
|
112
|
-
if (!done) {
|
|
113
|
-
reader?.abort();
|
|
114
|
-
ws.close();
|
|
115
|
-
obs.error(new Error("Upload aborted"));
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
options?.abort?.addEventListener("abort", abortHandler);
|
|
119
|
-
return () => {
|
|
120
|
-
options?.abort?.removeEventListener("abort", abortHandler);
|
|
121
|
-
ws.close();
|
|
122
|
-
};
|
|
123
|
-
});
|
|
12
|
+
const metadata = {
|
|
13
|
+
...meta,
|
|
14
|
+
projectRef: project
|
|
15
|
+
};
|
|
16
|
+
return new Observable((obs) => {
|
|
17
|
+
const parsedUrl = new URL(url);
|
|
18
|
+
const ws = new WebSocket(`${parsedUrl.protocol === "https:" ? "wss" : "ws"}://${parsedUrl.host}/api/v1/assets/ws`, "contello-file-upload-v1");
|
|
19
|
+
let offset = 0;
|
|
20
|
+
let done = false;
|
|
21
|
+
let ackReceived = false;
|
|
22
|
+
ws.addEventListener("open", () => {
|
|
23
|
+
const initFrame = {
|
|
24
|
+
type: "init",
|
|
25
|
+
metadata: {
|
|
26
|
+
...metadata,
|
|
27
|
+
name: file.name,
|
|
28
|
+
mimeType: file.type,
|
|
29
|
+
size: file.size
|
|
30
|
+
},
|
|
31
|
+
token
|
|
32
|
+
};
|
|
33
|
+
ws.send(JSON.stringify(initFrame));
|
|
34
|
+
function readSlice() {
|
|
35
|
+
(async () => {
|
|
36
|
+
try {
|
|
37
|
+
handleArrayBuffer(await file.slice(offset, offset + chunkSize).arrayBuffer());
|
|
38
|
+
} catch (error) {
|
|
39
|
+
obs.error(error);
|
|
40
|
+
}
|
|
41
|
+
})();
|
|
42
|
+
}
|
|
43
|
+
function markAsDone() {
|
|
44
|
+
ws.send(JSON.stringify({ type: "done" }));
|
|
45
|
+
}
|
|
46
|
+
function startUpload() {
|
|
47
|
+
if (ackReceived) readSlice();
|
|
48
|
+
}
|
|
49
|
+
function handleArrayBuffer(buffer) {
|
|
50
|
+
if (options?.abort?.aborted) return;
|
|
51
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
52
|
+
ws.send(buffer);
|
|
53
|
+
offset += buffer.byteLength;
|
|
54
|
+
if (offset < file.size) readSlice();
|
|
55
|
+
else markAsDone();
|
|
56
|
+
} else obs.error(/* @__PURE__ */ new Error("WebSocket is closed"));
|
|
57
|
+
}
|
|
58
|
+
ws.addEventListener("message", (event) => {
|
|
59
|
+
const message = JSON.parse(event.data);
|
|
60
|
+
if (message.type === "ack") {
|
|
61
|
+
ackReceived = true;
|
|
62
|
+
startUpload();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (message.type === "progress") return obs.next({ progress: message.bytesReceived / file.size * 100 });
|
|
66
|
+
if (message.type === "done") {
|
|
67
|
+
if (message.id) {
|
|
68
|
+
done = true;
|
|
69
|
+
obs.next({ id: message.id });
|
|
70
|
+
obs.complete();
|
|
71
|
+
} else obs.error(/* @__PURE__ */ new Error("No asset id received"));
|
|
72
|
+
return ws.close();
|
|
73
|
+
}
|
|
74
|
+
obs.error(/* @__PURE__ */ new Error(`WebSocket message with unknown type ${JSON.stringify(message)}`));
|
|
75
|
+
ws.close();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
ws.addEventListener("error", (error) => obs.error(error));
|
|
79
|
+
ws.addEventListener("close", () => {
|
|
80
|
+
if (!done) obs.error(/* @__PURE__ */ new Error("Connection closed"));
|
|
81
|
+
});
|
|
82
|
+
const abortHandler = () => {
|
|
83
|
+
if (done) return;
|
|
84
|
+
ws.close();
|
|
85
|
+
obs.error(/* @__PURE__ */ new Error("Upload aborted"));
|
|
86
|
+
};
|
|
87
|
+
options?.abort?.addEventListener("abort", abortHandler);
|
|
88
|
+
return () => {
|
|
89
|
+
options?.abort?.removeEventListener("abort", abortHandler);
|
|
90
|
+
ws.close();
|
|
91
|
+
};
|
|
92
|
+
});
|
|
124
93
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/implementations/xhr.ts
|
|
96
|
+
/** Uploads a file via XMLHttpRequest with multipart form data. Emits progress events and the asset ID on completion. */
|
|
128
97
|
function uploadViaXhr({ url, project, token }, file, meta, options) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
98
|
+
return new Observable((obs) => {
|
|
99
|
+
const data = new FormData();
|
|
100
|
+
data.append("metadata", JSON.stringify({
|
|
101
|
+
...meta,
|
|
102
|
+
projectRef: project
|
|
103
|
+
}));
|
|
104
|
+
data.append("file", file);
|
|
105
|
+
const xhr = new XMLHttpRequest();
|
|
106
|
+
xhr.open("POST", `${url}/api/v1/assets`, true);
|
|
107
|
+
xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
|
108
|
+
xhr.upload.addEventListener("progress", (event) => {
|
|
109
|
+
if (event.lengthComputable) obs.next({ progress: event.loaded / event.total * 100 });
|
|
110
|
+
});
|
|
111
|
+
xhr.addEventListener("load", () => {
|
|
112
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
113
|
+
const { id } = JSON.parse(xhr.responseText);
|
|
114
|
+
obs.next({ id });
|
|
115
|
+
return obs.complete();
|
|
116
|
+
}
|
|
117
|
+
obs.error(/* @__PURE__ */ new Error(`${xhr.status}: ${xhr.statusText}`));
|
|
118
|
+
});
|
|
119
|
+
xhr.addEventListener("error", (error) => obs.error(error));
|
|
120
|
+
xhr.send(data);
|
|
121
|
+
options?.abort?.addEventListener("abort", () => xhr.abort());
|
|
122
|
+
return () => xhr.abort();
|
|
123
|
+
});
|
|
154
124
|
}
|
|
155
|
-
|
|
156
|
-
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/uploader.ts
|
|
127
|
+
/**
|
|
128
|
+
* ContelloUploader is a class for uploading files to a Contello server.
|
|
129
|
+
* It supports both WebSocket and HTTP transports.
|
|
130
|
+
*/
|
|
157
131
|
var ContelloUploader = class {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return uploadViaWebSocket(this.params, file, meta, options);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
export {
|
|
181
|
-
ContelloUploader,
|
|
182
|
-
UploadAssetRetentionPolicy
|
|
132
|
+
params;
|
|
133
|
+
constructor(params) {
|
|
134
|
+
this.params = {
|
|
135
|
+
url: params.url,
|
|
136
|
+
project: params.project,
|
|
137
|
+
token: params.token,
|
|
138
|
+
transport: params.transport || "ws",
|
|
139
|
+
chunkSize: params.chunkSize || 4 * 1024 * 1024
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** Uploads a file and resolves with the asset ID once complete. */
|
|
143
|
+
async upload(file, meta, options) {
|
|
144
|
+
return firstValueFrom(this.uploadWithEvents(file, meta, options).pipe(filter((r) => "id" in r)));
|
|
145
|
+
}
|
|
146
|
+
/** Uploads a file and returns an Observable emitting progress events and the final asset ID. */
|
|
147
|
+
uploadWithEvents(file, meta, options) {
|
|
148
|
+
if (this.params.transport === "http") return uploadViaXhr(this.params, file, meta, options);
|
|
149
|
+
return uploadViaWebSocket(this.params, file, meta, options);
|
|
150
|
+
}
|
|
183
151
|
};
|
|
152
|
+
//#endregion
|
|
153
|
+
export { ContelloUploader, UploadAssetRetentionPolicy };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/upload-metadata.ts","../src/implementations/ws.ts","../src/implementations/xhr.ts","../src/uploader.ts"],"sourcesContent":["export type UploadAssetMetadata = {\n name?: string | undefined;\n mimeType?: string | undefined;\n size?: number | undefined;\n annotations?: UploadAssetAnnotation[] | undefined;\n collectionRefs?: string[] | undefined;\n image?: UploadAssetImageMetadata | undefined;\n retentionPolicy?: UploadAssetRetentionPolicy | undefined;\n generatePreview?: boolean | undefined;\n createdAt?: string | undefined;\n updatedAt?: string | undefined;\n};\n\nexport type UploadAssetAnnotation = {\n key: string;\n value: string;\n};\n\nexport type UploadAssetProgress = {\n progress: number;\n};\n\nexport enum UploadAssetRetentionPolicy {\n retain = 'retain',\n deleteIfNotUsed = 'deleteIfNotUsed',\n}\n\nexport type UploadAssetImageMetadata = {\n transformations: UploadAssetImageTransformation[];\n};\n\nexport type UploadAssetImageTransformation =\n | UploadAssetExtractTransformation\n | UploadAssetFitTransformation\n | UploadAssetConvertTransformation;\n\nexport type UploadAssetExtractTransformation = {\n name: 'extract';\n options: {\n top: number;\n left: number;\n areaWidth: number;\n areaHeight: number;\n rotate?: 0 | 90 | 180 | 270 | undefined;\n };\n};\n\nexport type UploadAssetFitTransformation = {\n name: 'fit';\n options: {\n width: number;\n height: number;\n };\n};\n\nexport type UploadAssetConvertTransformation = {\n name: 'convert';\n options:\n | UploadAssetConvertTransformationJpegOptions\n | UploadAssetConvertTransformationPngOptions\n | UploadAssetConvertTransformationAvifOptions;\n};\n\nexport type UploadAssetConvertTransformationJpegOptions = {\n format: 'jpeg';\n options: {\n quality: number; // 0-100\n interlace: boolean;\n };\n};\n\nexport type UploadAssetConvertTransformationPngOptions = {\n format: 'png';\n options: {\n compressionLevel: number; // 0-9\n };\n};\n\nexport type UploadAssetConvertTransformationAvifOptions = {\n format: 'avif';\n options: {\n quality: number; // 0-100\n lossless: boolean;\n };\n};\n","import { Observable } from 'rxjs';\nimport type { UploadAssetMetadata, UploadAssetProgress } from '../upload-metadata';\nimport type { ContelloUploaderParams } from '../uploader';\n\ntype InitFrame = {\n type: 'init';\n metadata: UploadAssetMetadata & { projectRef: string };\n token: string;\n};\n\ntype AckMessage = { type: 'ack' };\n\ntype ProgressMessage = { type: 'progress'; bytesReceived: number };\n\ntype DoneMessage = { type: 'done'; id: string };\n\n/** Uploads a file via WebSocket using chunked binary transfer. Emits progress events and the asset ID on completion. */\nexport function uploadViaWebSocket(\n { url, project, token, chunkSize }: Required<ContelloUploaderParams>,\n file: File,\n meta: UploadAssetMetadata | undefined,\n options: { abort?: AbortSignal } | undefined,\n) {\n const metadata = { ...meta, projectRef: project };\n\n return new Observable<UploadAssetProgress | { id: string }>((obs) => {\n const parsedUrl = new URL(url);\n\n const ws = new WebSocket(\n `${parsedUrl.protocol === 'https:' ? 'wss' : 'ws'}://${parsedUrl.host}/api/v1/assets/ws`,\n 'contello-file-upload-v1',\n );\n\n let offset = 0;\n\n let done = false;\n let ackReceived = false;\n\n ws.addEventListener('open', () => {\n const initFrame: InitFrame = {\n type: 'init',\n metadata: {\n ...metadata,\n name: file.name,\n mimeType: file.type,\n size: file.size,\n },\n token,\n };\n\n ws.send(JSON.stringify(initFrame));\n\n function readSlice() {\n void (async () => {\n try {\n const buffer = await file.slice(offset, offset + chunkSize).arrayBuffer();\n\n handleArrayBuffer(buffer);\n } catch (error) {\n obs.error(error);\n }\n })();\n }\n\n function markAsDone() {\n ws.send(JSON.stringify({ type: 'done' }));\n }\n\n function startUpload() {\n if (ackReceived) {\n readSlice();\n }\n }\n\n function handleArrayBuffer(buffer: ArrayBuffer) {\n // bail between chunks if the upload was aborted — abortHandler already closed the socket and errored\n if (options?.abort?.aborted) {\n return;\n }\n\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(buffer);\n offset += buffer.byteLength;\n\n if (offset < file.size) {\n readSlice();\n } else {\n markAsDone();\n }\n } else {\n obs.error(new Error('WebSocket is closed'));\n }\n }\n\n ws.addEventListener('message', (event) => {\n const message: AckMessage | ProgressMessage | DoneMessage = JSON.parse(event.data);\n\n if (message.type === 'ack') {\n ackReceived = true;\n startUpload();\n return;\n }\n\n if (message.type === 'progress') {\n return obs.next({ progress: (message.bytesReceived / file.size) * 100 });\n }\n\n if (message.type === 'done') {\n if (message.id) {\n done = true;\n\n obs.next({ id: message.id });\n obs.complete();\n } else {\n obs.error(new Error('No asset id received'));\n }\n\n return ws.close();\n }\n\n obs.error(new Error(`WebSocket message with unknown type ${JSON.stringify(message)}`));\n ws.close();\n });\n });\n\n ws.addEventListener('error', (error) => obs.error(error));\n\n ws.addEventListener('close', () => {\n if (!done) {\n obs.error(new Error('Connection closed'));\n }\n });\n\n const abortHandler = () => {\n if (done) {\n return;\n }\n\n ws.close();\n obs.error(new Error('Upload aborted'));\n };\n\n options?.abort?.addEventListener('abort', abortHandler);\n\n return () => {\n options?.abort?.removeEventListener('abort', abortHandler);\n ws.close();\n };\n });\n}\n","import { Observable } from 'rxjs';\nimport type { UploadAssetMetadata, UploadAssetProgress } from '../upload-metadata';\nimport type { ContelloUploaderParams } from '../uploader';\n\n/** Uploads a file via XMLHttpRequest with multipart form data. Emits progress events and the asset ID on completion. */\nexport function uploadViaXhr(\n { url, project, token }: Required<ContelloUploaderParams>,\n file: File,\n meta: UploadAssetMetadata | undefined,\n options: { abort?: AbortSignal } | undefined,\n) {\n return new Observable<UploadAssetProgress | { id: string }>((obs) => {\n const data = new FormData();\n\n data.append('metadata', JSON.stringify({ ...meta, projectRef: project }));\n data.append('file', file);\n\n const xhr = new XMLHttpRequest();\n\n xhr.open('POST', `${url}/api/v1/assets`, true);\n\n xhr.setRequestHeader('Authorization', `Bearer ${token}`);\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable) {\n obs.next({ progress: (event.loaded / event.total) * 100 });\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n const { id }: { id: string } = JSON.parse(xhr.responseText);\n\n obs.next({ id });\n\n return obs.complete();\n }\n\n obs.error(new Error(`${xhr.status}: ${xhr.statusText}`));\n });\n\n xhr.addEventListener('error', (error) => obs.error(error));\n xhr.send(data);\n\n options?.abort?.addEventListener('abort', () => xhr.abort());\n\n return () => xhr.abort();\n });\n}\n","import { filter, firstValueFrom } from 'rxjs';\nimport { uploadViaWebSocket } from './implementations/ws';\nimport { uploadViaXhr } from './implementations/xhr';\nimport type { UploadAssetMetadata } from './upload-metadata';\n\nexport type ContelloUploaderParams = {\n /**\n * Base URL of the Contello server.\n * Example: 'https://example.com'\n */\n url: string;\n /**\n * Project identifier for the Contello project.\n * Example: 'myProjectId'\n */\n project: string;\n /**\n * Authentication token for the Contello API.\n * Example: 'app-a123b456c7890d123456789'\n */\n token: string;\n /**\n * Transport protocol to use for uploading files.\n * 'http' uses XMLHttpRequest, 'ws' uses WebSocket.\n * @default 'ws'\n */\n transport?: 'http' | 'ws';\n /**\n * Size of each chunk in bytes when uploading files.\n * Default is 4MB.\n * @default 4_194_304\n */\n chunkSize?: number;\n};\n\n/**\n * ContelloUploader is a class for uploading files to a Contello server.\n * It supports both WebSocket and HTTP transports.\n */\nexport class ContelloUploader {\n private params: Required<ContelloUploaderParams>;\n\n constructor(params: ContelloUploaderParams) {\n this.params = {\n url: params.url,\n project: params.project,\n token: params.token,\n transport: params.transport || 'ws',\n chunkSize: params.chunkSize || 4 * 1024 * 1024,\n };\n }\n\n /** Uploads a file and resolves with the asset ID once complete. */\n async upload(\n file: File,\n meta?: UploadAssetMetadata | undefined,\n options?: { abort?: AbortSignal } | undefined,\n ): Promise<{ id: string }> {\n return firstValueFrom(this.uploadWithEvents(file, meta, options).pipe(filter((r) => 'id' in r)));\n }\n\n /** Uploads a file and returns an Observable emitting progress events and the final asset ID. */\n uploadWithEvents(file: File, meta?: UploadAssetMetadata | undefined, options?: { abort?: AbortSignal } | undefined) {\n if (this.params.transport === 'http') {\n return uploadViaXhr(this.params, file, meta, options);\n }\n\n return uploadViaWebSocket(this.params, file, meta, options);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contello/uploader",
|
|
3
|
-
"version": "8.21.
|
|
3
|
+
"version": "8.21.6",
|
|
4
4
|
"description": "File uploader for Contello CMS with WebSocket and HTTP transports",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,12 +10,6 @@
|
|
|
10
10
|
"url": "https://github.com/entwico/contello-js",
|
|
11
11
|
"directory": "packages/uploader"
|
|
12
12
|
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsup",
|
|
15
|
-
"lint": "eslint .",
|
|
16
|
-
"lint:fix": "eslint . --fix",
|
|
17
|
-
"typecheck": "tsc --noEmit"
|
|
18
|
-
},
|
|
19
13
|
"peerDependencies": {
|
|
20
14
|
"rxjs": "^7.0.0"
|
|
21
15
|
},
|
|
@@ -35,5 +29,11 @@
|
|
|
35
29
|
"publishConfig": {
|
|
36
30
|
"access": "public",
|
|
37
31
|
"registry": "https://registry.npmjs.org"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsdown",
|
|
35
|
+
"lint": "eslint . --cache",
|
|
36
|
+
"lint:fix": "eslint . --fix",
|
|
37
|
+
"typecheck": "tsc --noEmit"
|
|
38
38
|
}
|
|
39
|
-
}
|
|
39
|
+
}
|