@putkoff/abstract-securefiles 0.0.43 → 0.0.47
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/dist/FileHandlers/FileTable/imports.d.ts +1 -1
- package/dist/FileHandlers/imports.d.ts +1 -1
- package/dist/file_utils/imports.d.ts +1 -1
- package/dist/file_utils/src/delete_utils/imports.d.ts +1 -1
- package/dist/file_utils/src/download_utils/imports.d.ts +1 -1
- package/dist/file_utils/src/download_utils/src/download_select.d.ts +1 -1
- package/dist/file_utils/src/imports.d.ts +1 -1
- package/dist/file_utils/src/list_utils/imports.d.ts +0 -1
- package/dist/file_utils/src/share_utils/imports.d.ts +0 -1
- package/dist/hooks/imports.d.ts +1 -1
- package/dist/hooks/useFiles/imports.d.ts +1 -1
- package/dist/imports.d.ts +0 -1
- package/dist/index.cjs +114 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +115 -108
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/FileHandlers/FileTable/imports.ts +0 -1
- package/src/FileHandlers/imports.ts +0 -1
- package/src/file_utils/imports.ts +1 -1
- package/src/file_utils/src/delete_utils/imports.ts +1 -1
- package/src/file_utils/src/download_utils/imports.ts +1 -1
- package/src/file_utils/src/download_utils/src/download_select.ts +18 -13
- package/src/file_utils/src/imports.ts +1 -1
- package/src/file_utils/src/list_utils/imports.ts +1 -1
- package/src/file_utils/src/share_utils/imports.ts +0 -1
- package/src/hooks/imports.ts +1 -1
- package/src/hooks/useFiles/imports.ts +1 -1
- package/src/imports.ts +2 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { FileRow } from './../FileRow';
|
|
2
2
|
export { ShareModal } from './../ShareModal';
|
|
3
3
|
export type { FileItem, FileTableProps } from './../imports';
|
|
4
|
-
export { useState, useFiles, downloadFile, Spinner,
|
|
4
|
+
export { useState, useFiles, downloadFile, Spinner, Input, currentUsername, Button } from './../imports';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps } from './../imports';
|
|
2
|
-
export { CloudArrowUpIcon, currentUsername, Button, Checkbox, Input, Spinner, useEffect, useRef, useState, useCallback, ClipboardIcon, createPortal,
|
|
2
|
+
export { CloudArrowUpIcon, currentUsername, Button, Checkbox, Input, Spinner, useEffect, useRef, useState, useCallback, ClipboardIcon, createPortal, } from './../imports';
|
|
3
3
|
export { useFiles } from './../hooks';
|
|
4
4
|
export { downloadFile, uploadFiles } from './../file_utils';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { requireToken, alertit, fetchIt, stripPrefixes, make_path } from "./../imports";
|
|
2
2
|
export type { FileItem, ApiRow } from "./../types";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { requireToken, alertit } from "./../imports";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { requireToken } from './../imports';
|
|
2
2
|
export type { FileItem } from './../imports';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { FileItem } from './../imports';
|
|
1
|
+
import type { FileItem } from './../imports';
|
|
2
2
|
export declare function downloadSelect(item: FileItem): Promise<void>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type { FileItem, ApiRow } from './../../types/src/types';
|
|
2
|
-
export { alertit, requireToken
|
|
2
|
+
export { alertit, requireToken } from './../imports';
|
package/dist/hooks/imports.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type { FileItem, ApiRow } from './../imports';
|
|
2
|
-
export {
|
|
2
|
+
export { alertit, useCallback, isLoggedIn } from './../imports';
|
|
3
3
|
export { toggleShare, removeFile, listFiles, downloadFile } from './../file_utils';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type { FileItem, ApiRow } from './../imports';
|
|
2
|
-
export {
|
|
2
|
+
export { alertit, toggleShare, removeFile, listFiles, useCallback, downloadFile, isLoggedIn } from './../imports';
|
package/dist/imports.d.ts
CHANGED
|
@@ -4,4 +4,3 @@ export { useEffect, useRef, useState, useCallback } from 'react';
|
|
|
4
4
|
export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps, ApiRow, EnhancedInputProps } from './types';
|
|
5
5
|
export { currentUsername, alertit, requireToken, isLoggedIn, fetchIt, stripPrefixes, make_path } from "@putkoff/abstract-utilities";
|
|
6
6
|
export { Button, Checkbox, Input, Spinner } from './UI';
|
|
7
|
-
export { secureFetchIt, fetchSharePatch } from "@putkoff/abstract-apis";
|
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,6 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
4
4
|
var reactDom = require('react-dom');
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var abstractUtilities = require('@putkoff/abstract-utilities');
|
|
7
|
-
var abstractApis = require('@putkoff/abstract-apis');
|
|
8
7
|
|
|
9
8
|
function _interopNamespaceDefault(e) {
|
|
10
9
|
var n = Object.create(null);
|
|
@@ -184,110 +183,6 @@ async function downloadFile(item) {
|
|
|
184
183
|
triggerDownload(blob, item.filename || "download");
|
|
185
184
|
}
|
|
186
185
|
|
|
187
|
-
async function downloadSelect(item) {
|
|
188
|
-
const token = abstractUtilities.requireToken();
|
|
189
|
-
const body = item;
|
|
190
|
-
const headers = {
|
|
191
|
-
Authorization: `Bearer ${token}`,
|
|
192
|
-
Accept: "application/octet-stream",
|
|
193
|
-
"Content-Type": "application/json"
|
|
194
|
-
};
|
|
195
|
-
const blob = await abstractApis.secureFetchIt("download", body, "POST", headers, true, true);
|
|
196
|
-
if (!blob || blob.size === 0) {
|
|
197
|
-
throw new Error(`Received empty file data for “${item.filename}”`);
|
|
198
|
-
}
|
|
199
|
-
triggerDownload(blob, item.filename);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** Given a checkbox inside a table-row → download that row’s file. */
|
|
203
|
-
async function downloadRow(cb) {
|
|
204
|
-
const row = cb.closest("tr");
|
|
205
|
-
const filepath = cb.value;
|
|
206
|
-
const filename = row?.children[1]?.textContent?.trim() || "downloaded_file";
|
|
207
|
-
if (filepath)
|
|
208
|
-
await downloadSelect({ filepath, filename });
|
|
209
|
-
}
|
|
210
|
-
/** Bulk download: pass a NodeList or array of checkboxes. */
|
|
211
|
-
async function downloadSelected(checkboxes) {
|
|
212
|
-
const list = Array.from(checkboxes);
|
|
213
|
-
if (!list.length) {
|
|
214
|
-
alert("No files selected.");
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
for (const cb of list) {
|
|
218
|
-
await downloadRow(cb);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Classic “select all rows” logic (still handy in non-React views
|
|
224
|
-
* such as the admin dashboard).
|
|
225
|
-
*/
|
|
226
|
-
function syncHeaderCheckbox() {
|
|
227
|
-
const all = document.querySelectorAll(".file-checkbox");
|
|
228
|
-
const checked = document.querySelectorAll(".file-checkbox:checked");
|
|
229
|
-
const header = document.getElementById("select-all-checkbox");
|
|
230
|
-
header.indeterminate =
|
|
231
|
-
checked.length > 0 && checked.length < all.length;
|
|
232
|
-
header.checked = checked.length === all.length;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Wire up header + row checkboxes once the table is in the DOM. */
|
|
236
|
-
function initSelectAll() {
|
|
237
|
-
const header = document.getElementById("select-all-checkbox");
|
|
238
|
-
const btn = document.getElementById("select-all");
|
|
239
|
-
// 1) header → toggle all
|
|
240
|
-
header.addEventListener("change", (e) => {
|
|
241
|
-
const on = e.target.checked;
|
|
242
|
-
document
|
|
243
|
-
.querySelectorAll(".file-checkbox")
|
|
244
|
-
.forEach((cb) => (cb.checked = on));
|
|
245
|
-
});
|
|
246
|
-
// 2) button → toggle all
|
|
247
|
-
btn.addEventListener("click", () => {
|
|
248
|
-
const cbs = Array.from(document.querySelectorAll(".file-checkbox"));
|
|
249
|
-
if (!cbs.length) {
|
|
250
|
-
alert("No files to select.");
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
254
|
-
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
255
|
-
syncHeaderCheckbox();
|
|
256
|
-
});
|
|
257
|
-
// 3) row boxes → keep header state
|
|
258
|
-
document
|
|
259
|
-
.querySelectorAll(".file-checkbox")
|
|
260
|
-
.forEach((cb) => cb.addEventListener("change", syncHeaderCheckbox));
|
|
261
|
-
syncHeaderCheckbox();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/** Utility for other screens: toggle a list of checkboxes on/off. */
|
|
265
|
-
function toggleCheckboxes(cbs) {
|
|
266
|
-
if (!cbs.length) {
|
|
267
|
-
alert("No files to select.");
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
271
|
-
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
272
|
-
syncHeaderCheckbox();
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const API_BASE$1 = '/api/secure-files';
|
|
276
|
-
/** Generic PATCH helper for file-level admin settings. */
|
|
277
|
-
async function patchFileSetting(fileId, field, value) {
|
|
278
|
-
const res = await fetch(`${API_BASE$1}/files/${fileId}/settings/${field}`, {
|
|
279
|
-
method: 'PATCH',
|
|
280
|
-
credentials: 'include',
|
|
281
|
-
headers: { 'Content-Type': 'application/json' },
|
|
282
|
-
body: JSON.stringify({ value }),
|
|
283
|
-
});
|
|
284
|
-
if (!res.ok) {
|
|
285
|
-
const err = await res.json().catch(() => ({}));
|
|
286
|
-
throw new Error(err.error || res.statusText);
|
|
287
|
-
}
|
|
288
|
-
return (await res.json());
|
|
289
|
-
}
|
|
290
|
-
|
|
291
186
|
/**
|
|
292
187
|
* Cookie-authenticated API helpers.
|
|
293
188
|
* All requests include credentials: 'include' so the browser sends the
|
|
@@ -324,10 +219,10 @@ function resolveApiBase() {
|
|
|
324
219
|
// 4. Same-origin default
|
|
325
220
|
return "/api/secure-files";
|
|
326
221
|
}
|
|
327
|
-
const API_BASE = resolveApiBase();
|
|
222
|
+
const API_BASE$1 = resolveApiBase();
|
|
328
223
|
function apiUrl(path) {
|
|
329
224
|
const p = path.startsWith("/") ? path : `/${path}`;
|
|
330
|
-
return `${API_BASE}${p}`;
|
|
225
|
+
return `${API_BASE$1}${p}`;
|
|
331
226
|
}
|
|
332
227
|
/**
|
|
333
228
|
* Generic JSON fetch with session-cookie auth.
|
|
@@ -388,6 +283,118 @@ async function cookieUpload(file, relPath = "") {
|
|
|
388
283
|
throw new Error(`Upload failed: HTTP ${res.status}`);
|
|
389
284
|
return res.json();
|
|
390
285
|
}
|
|
286
|
+
/** The resolved API base URL, exported for debugging / display purposes. */
|
|
287
|
+
const SECURE_FILES_API_BASE = API_BASE$1;
|
|
288
|
+
|
|
289
|
+
async function downloadSelect(item) {
|
|
290
|
+
const res = await fetch(`${SECURE_FILES_API_BASE}/download`, {
|
|
291
|
+
method: "POST",
|
|
292
|
+
credentials: "include",
|
|
293
|
+
headers: {
|
|
294
|
+
"Content-Type": "application/json",
|
|
295
|
+
Accept: "application/octet-stream",
|
|
296
|
+
},
|
|
297
|
+
body: JSON.stringify(item),
|
|
298
|
+
});
|
|
299
|
+
if (res.status === 401)
|
|
300
|
+
throw new Error("Not authenticated – please log in.");
|
|
301
|
+
if (!res.ok)
|
|
302
|
+
throw new Error(`Download failed: HTTP ${res.status}`);
|
|
303
|
+
const blob = await res.blob();
|
|
304
|
+
if (!blob || blob.size === 0) {
|
|
305
|
+
throw new Error(`Received empty file data for "${item.filename}"`);
|
|
306
|
+
}
|
|
307
|
+
triggerDownload(blob, item.filename);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Given a checkbox inside a table-row → download that row’s file. */
|
|
311
|
+
async function downloadRow(cb) {
|
|
312
|
+
const row = cb.closest("tr");
|
|
313
|
+
const filepath = cb.value;
|
|
314
|
+
const filename = row?.children[1]?.textContent?.trim() || "downloaded_file";
|
|
315
|
+
if (filepath)
|
|
316
|
+
await downloadSelect({ filepath, filename });
|
|
317
|
+
}
|
|
318
|
+
/** Bulk download: pass a NodeList or array of checkboxes. */
|
|
319
|
+
async function downloadSelected(checkboxes) {
|
|
320
|
+
const list = Array.from(checkboxes);
|
|
321
|
+
if (!list.length) {
|
|
322
|
+
alert("No files selected.");
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
for (const cb of list) {
|
|
326
|
+
await downloadRow(cb);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Classic “select all rows” logic (still handy in non-React views
|
|
332
|
+
* such as the admin dashboard).
|
|
333
|
+
*/
|
|
334
|
+
function syncHeaderCheckbox() {
|
|
335
|
+
const all = document.querySelectorAll(".file-checkbox");
|
|
336
|
+
const checked = document.querySelectorAll(".file-checkbox:checked");
|
|
337
|
+
const header = document.getElementById("select-all-checkbox");
|
|
338
|
+
header.indeterminate =
|
|
339
|
+
checked.length > 0 && checked.length < all.length;
|
|
340
|
+
header.checked = checked.length === all.length;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Wire up header + row checkboxes once the table is in the DOM. */
|
|
344
|
+
function initSelectAll() {
|
|
345
|
+
const header = document.getElementById("select-all-checkbox");
|
|
346
|
+
const btn = document.getElementById("select-all");
|
|
347
|
+
// 1) header → toggle all
|
|
348
|
+
header.addEventListener("change", (e) => {
|
|
349
|
+
const on = e.target.checked;
|
|
350
|
+
document
|
|
351
|
+
.querySelectorAll(".file-checkbox")
|
|
352
|
+
.forEach((cb) => (cb.checked = on));
|
|
353
|
+
});
|
|
354
|
+
// 2) button → toggle all
|
|
355
|
+
btn.addEventListener("click", () => {
|
|
356
|
+
const cbs = Array.from(document.querySelectorAll(".file-checkbox"));
|
|
357
|
+
if (!cbs.length) {
|
|
358
|
+
alert("No files to select.");
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
362
|
+
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
363
|
+
syncHeaderCheckbox();
|
|
364
|
+
});
|
|
365
|
+
// 3) row boxes → keep header state
|
|
366
|
+
document
|
|
367
|
+
.querySelectorAll(".file-checkbox")
|
|
368
|
+
.forEach((cb) => cb.addEventListener("change", syncHeaderCheckbox));
|
|
369
|
+
syncHeaderCheckbox();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Utility for other screens: toggle a list of checkboxes on/off. */
|
|
373
|
+
function toggleCheckboxes(cbs) {
|
|
374
|
+
if (!cbs.length) {
|
|
375
|
+
alert("No files to select.");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
379
|
+
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
380
|
+
syncHeaderCheckbox();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const API_BASE = '/api/secure-files';
|
|
384
|
+
/** Generic PATCH helper for file-level admin settings. */
|
|
385
|
+
async function patchFileSetting(fileId, field, value) {
|
|
386
|
+
const res = await fetch(`${API_BASE}/files/${fileId}/settings/${field}`, {
|
|
387
|
+
method: 'PATCH',
|
|
388
|
+
credentials: 'include',
|
|
389
|
+
headers: { 'Content-Type': 'application/json' },
|
|
390
|
+
body: JSON.stringify({ value }),
|
|
391
|
+
});
|
|
392
|
+
if (!res.ok) {
|
|
393
|
+
const err = await res.json().catch(() => ({}));
|
|
394
|
+
throw new Error(err.error || res.statusText);
|
|
395
|
+
}
|
|
396
|
+
return (await res.json());
|
|
397
|
+
}
|
|
391
398
|
|
|
392
399
|
/** File-upload helper (used by non-React fallback pages). */
|
|
393
400
|
async function uploadFile(file, subdir) {
|