@howells/stow-client
Advanced tools
+34
-33
@@ -41,4 +41,5 @@ "use strict"; | ||
| // src/index.ts | ||
| function uploadToR2(uploadUrl, file, onProgress) { | ||
| return new Promise((resolve, reject) => { | ||
| var uploadToR2 = (uploadUrl, file, onProgress) => ( | ||
| // eslint-disable-next-line eslint-plugin-promise/avoid-new | ||
| new Promise((resolve, reject) => { | ||
| const xhr = new XMLHttpRequest(); | ||
@@ -52,3 +53,3 @@ xhr.upload.addEventListener("progress", (event) => { | ||
| if (xhr.status >= 200 && xhr.status < 300) { | ||
| resolve(void 0); | ||
| resolve(); | ||
| return; | ||
@@ -67,4 +68,4 @@ } | ||
| xhr.send(file); | ||
| }); | ||
| } | ||
| }) | ||
| ); | ||
| var StowClient = class { | ||
@@ -82,3 +83,3 @@ endpoint; | ||
| constructor(config) { | ||
| this.endpoint = typeof config === "string" ? config.replace(/\/+$/, "") : config.endpoint.replace(/\/+$/, ""); | ||
| this.endpoint = typeof config === "string" ? config.replace(/\/+$/u, "") : config.endpoint.replace(/\/+$/u, ""); | ||
| } | ||
@@ -95,6 +96,6 @@ endpointUrl(path) { | ||
| } | ||
| if (confirmUrl.startsWith("/") || /^[a-z][a-z0-9+\-.]*:\/\//i.test(confirmUrl)) { | ||
| if (confirmUrl.startsWith("/") || /^[a-z][a-z0-9+\-.]*:\/\//iu.test(confirmUrl)) { | ||
| return confirmUrl; | ||
| } | ||
| return this.endpointUrl(`/${confirmUrl.replace(/^\/+/, "")}`); | ||
| return this.endpointUrl(`/${confirmUrl.replace(/^\/+/u, "")}`); | ||
| } | ||
@@ -118,16 +119,16 @@ /** | ||
| loaded: 0, | ||
| total: file.size, | ||
| percent: 0, | ||
| phase: "presigning" | ||
| phase: "presigning", | ||
| total: file.size | ||
| }); | ||
| const presignResponse = await fetch(this.endpointUrl("/presign"), { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ | ||
| contentType: file.type || "application/octet-stream", | ||
| filename: file.name, | ||
| contentType: file.type || "application/octet-stream", | ||
| route, | ||
| size: file.size, | ||
| route, | ||
| ...metadata ? { metadata } : {} | ||
| }) | ||
| }), | ||
| headers: { "Content-Type": "application/json" }, | ||
| method: "POST" | ||
| }); | ||
@@ -142,12 +143,12 @@ if (!presignResponse.ok) { | ||
| loaded: file.size, | ||
| total: file.size, | ||
| percent: 100, | ||
| phase: "confirming" | ||
| phase: "confirming", | ||
| total: file.size | ||
| }); | ||
| return { | ||
| contentType: presign.contentType, | ||
| deduped: true, | ||
| key: presign.key, | ||
| url: presign.url, | ||
| size: presign.size, | ||
| contentType: presign.contentType, | ||
| deduped: true | ||
| url: presign.url | ||
| }; | ||
@@ -157,5 +158,5 @@ } | ||
| loaded: 0, | ||
| total: file.size, | ||
| percent: 0, | ||
| phase: "uploading" | ||
| phase: "uploading", | ||
| total: file.size | ||
| }); | ||
@@ -165,5 +166,5 @@ await uploadToR2(presign.uploadUrl, file, (loaded) => { | ||
| loaded, | ||
| total: file.size, | ||
| percent: Math.round(loaded / file.size * 100), | ||
| phase: "uploading" | ||
| phase: "uploading", | ||
| total: file.size | ||
| }); | ||
@@ -173,15 +174,15 @@ }); | ||
| loaded: file.size, | ||
| total: file.size, | ||
| percent: 100, | ||
| phase: "confirming" | ||
| phase: "confirming", | ||
| total: file.size | ||
| }); | ||
| const confirmResponse = await fetch(this.resolveConfirmUrl(presign.confirmUrl), { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ | ||
| contentType: file.type || "application/octet-stream", | ||
| fileKey: presign.fileKey, | ||
| size: file.size, | ||
| contentType: file.type || "application/octet-stream", | ||
| ...metadata ? { metadata } : {} | ||
| }) | ||
| }), | ||
| headers: { "Content-Type": "application/json" }, | ||
| method: "POST" | ||
| }); | ||
@@ -194,6 +195,6 @@ if (!confirmResponse.ok) { | ||
| return { | ||
| contentType: result.contentType, | ||
| key: result.key, | ||
| url: result.url, | ||
| size: result.size, | ||
| contentType: result.contentType | ||
| url: result.url | ||
| }; | ||
@@ -221,3 +222,3 @@ } | ||
| async uploadFiles(files, options) { | ||
| const fileArray = Array.from(files); | ||
| const fileArray = [...files]; | ||
| const concurrency = Math.max(1, options?.concurrency ?? 3); | ||
@@ -224,0 +225,0 @@ if (concurrency === 1) { |
+34
-33
@@ -14,4 +14,5 @@ // src/stow-error.ts | ||
| // src/index.ts | ||
| function uploadToR2(uploadUrl, file, onProgress) { | ||
| return new Promise((resolve, reject) => { | ||
| var uploadToR2 = (uploadUrl, file, onProgress) => ( | ||
| // eslint-disable-next-line eslint-plugin-promise/avoid-new | ||
| new Promise((resolve, reject) => { | ||
| const xhr = new XMLHttpRequest(); | ||
@@ -25,3 +26,3 @@ xhr.upload.addEventListener("progress", (event) => { | ||
| if (xhr.status >= 200 && xhr.status < 300) { | ||
| resolve(void 0); | ||
| resolve(); | ||
| return; | ||
@@ -40,4 +41,4 @@ } | ||
| xhr.send(file); | ||
| }); | ||
| } | ||
| }) | ||
| ); | ||
| var StowClient = class { | ||
@@ -55,3 +56,3 @@ endpoint; | ||
| constructor(config) { | ||
| this.endpoint = typeof config === "string" ? config.replace(/\/+$/, "") : config.endpoint.replace(/\/+$/, ""); | ||
| this.endpoint = typeof config === "string" ? config.replace(/\/+$/u, "") : config.endpoint.replace(/\/+$/u, ""); | ||
| } | ||
@@ -68,6 +69,6 @@ endpointUrl(path) { | ||
| } | ||
| if (confirmUrl.startsWith("/") || /^[a-z][a-z0-9+\-.]*:\/\//i.test(confirmUrl)) { | ||
| if (confirmUrl.startsWith("/") || /^[a-z][a-z0-9+\-.]*:\/\//iu.test(confirmUrl)) { | ||
| return confirmUrl; | ||
| } | ||
| return this.endpointUrl(`/${confirmUrl.replace(/^\/+/, "")}`); | ||
| return this.endpointUrl(`/${confirmUrl.replace(/^\/+/u, "")}`); | ||
| } | ||
@@ -91,16 +92,16 @@ /** | ||
| loaded: 0, | ||
| total: file.size, | ||
| percent: 0, | ||
| phase: "presigning" | ||
| phase: "presigning", | ||
| total: file.size | ||
| }); | ||
| const presignResponse = await fetch(this.endpointUrl("/presign"), { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ | ||
| contentType: file.type || "application/octet-stream", | ||
| filename: file.name, | ||
| contentType: file.type || "application/octet-stream", | ||
| route, | ||
| size: file.size, | ||
| route, | ||
| ...metadata ? { metadata } : {} | ||
| }) | ||
| }), | ||
| headers: { "Content-Type": "application/json" }, | ||
| method: "POST" | ||
| }); | ||
@@ -115,12 +116,12 @@ if (!presignResponse.ok) { | ||
| loaded: file.size, | ||
| total: file.size, | ||
| percent: 100, | ||
| phase: "confirming" | ||
| phase: "confirming", | ||
| total: file.size | ||
| }); | ||
| return { | ||
| contentType: presign.contentType, | ||
| deduped: true, | ||
| key: presign.key, | ||
| url: presign.url, | ||
| size: presign.size, | ||
| contentType: presign.contentType, | ||
| deduped: true | ||
| url: presign.url | ||
| }; | ||
@@ -130,5 +131,5 @@ } | ||
| loaded: 0, | ||
| total: file.size, | ||
| percent: 0, | ||
| phase: "uploading" | ||
| phase: "uploading", | ||
| total: file.size | ||
| }); | ||
@@ -138,5 +139,5 @@ await uploadToR2(presign.uploadUrl, file, (loaded) => { | ||
| loaded, | ||
| total: file.size, | ||
| percent: Math.round(loaded / file.size * 100), | ||
| phase: "uploading" | ||
| phase: "uploading", | ||
| total: file.size | ||
| }); | ||
@@ -146,15 +147,15 @@ }); | ||
| loaded: file.size, | ||
| total: file.size, | ||
| percent: 100, | ||
| phase: "confirming" | ||
| phase: "confirming", | ||
| total: file.size | ||
| }); | ||
| const confirmResponse = await fetch(this.resolveConfirmUrl(presign.confirmUrl), { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ | ||
| contentType: file.type || "application/octet-stream", | ||
| fileKey: presign.fileKey, | ||
| size: file.size, | ||
| contentType: file.type || "application/octet-stream", | ||
| ...metadata ? { metadata } : {} | ||
| }) | ||
| }), | ||
| headers: { "Content-Type": "application/json" }, | ||
| method: "POST" | ||
| }); | ||
@@ -167,6 +168,6 @@ if (!confirmResponse.ok) { | ||
| return { | ||
| contentType: result.contentType, | ||
| key: result.key, | ||
| url: result.url, | ||
| size: result.size, | ||
| contentType: result.contentType | ||
| url: result.url | ||
| }; | ||
@@ -194,3 +195,3 @@ } | ||
| async uploadFiles(files, options) { | ||
| const fileArray = Array.from(files); | ||
| const fileArray = [...files]; | ||
| const concurrency = Math.max(1, options?.concurrency ?? 3); | ||
@@ -197,0 +198,0 @@ if (concurrency === 1) { |
+12
-8
| { | ||
| "name": "@howells/stow-client", | ||
| "version": "2.4.0", | ||
| "description": "Client-side SDK for Stow file storage", | ||
| "version": "2.6.0", | ||
| "description": "Client-side SDK for Stow visual media infrastructure", | ||
| "keywords": [ | ||
@@ -33,14 +33,18 @@ "file-storage", | ||
| "devDependencies": { | ||
| "jsdom": "^29.0.0", | ||
| "@howells/typescript-config": "^0.1.6", | ||
| "jsdom": "^29.0.1", | ||
| "tsup": "^8.5.1", | ||
| "typescript": "^5.9.3", | ||
| "vite-plus": "latest", | ||
| "@stow/typescript-config": "0.0.0" | ||
| "typescript": "^5.9.3" | ||
| }, | ||
| "engines": { | ||
| "node": ">=22.22.3" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsup src/index.ts --format cjs,esm --dts", | ||
| "dev": "tsup src/index.ts --format cjs,esm --dts --watch", | ||
| "test": "vp test run", | ||
| "test:watch": "vp test" | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "lint": "howells-check src", | ||
| "lint:fix": "howells-fix src" | ||
| } | ||
| } |
+1
-1
| # @howells/stow-client | ||
| Client-side SDK for [Stow](https://stow.sh) file storage. Upload files directly from the browser with progress tracking. | ||
| Client-side SDK for [Stow](https://stow.sh) visual media infrastructure. Upload files directly from the browser with progress tracking. | ||
@@ -5,0 +5,0 @@ ## Installation |
Unstable ownership
Supply chain riskA new collaborator has begun publishing package versions. Package stability and security risk may be elevated.
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
32914
0.65%4
-20%686
0.29%1
Infinity%5
25%