@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.
@@ -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, fetchSharePatch, Input, currentUsername, Button } from './../imports';
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, fetchSharePatch } from './../imports';
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 { fetchSharePatch, requireToken, alertit, fetchIt, stripPrefixes, make_path, secureFetchIt } from "./../imports";
1
+ export { requireToken, alertit, fetchIt, stripPrefixes, make_path } from "./../imports";
2
2
  export type { FileItem, ApiRow } from "./../types";
@@ -1 +1 @@
1
- export { secureFetchIt, requireToken, alertit } from "./../imports";
1
+ export { requireToken, alertit } from "./../imports";
@@ -1,2 +1,2 @@
1
- export { secureFetchIt, requireToken } from './../imports';
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, secureFetchIt, fetchSharePatch } from './../imports';
2
+ export { alertit, requireToken } from './../imports';
@@ -1,2 +1 @@
1
- export { secureFetchIt, fetchSharePatch } from './../imports';
2
1
  export type { FileItem, ApiRow } from './../imports';
@@ -1,2 +1 @@
1
1
  export type { FileItem } from './../../../types/src/types';
2
- export { fetchSharePatch } from './../imports';
@@ -1,3 +1,3 @@
1
1
  export type { FileItem, ApiRow } from './../imports';
2
- export { secureFetchIt, fetchSharePatch, alertit, useCallback, isLoggedIn } from './../imports';
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 { secureFetchIt, fetchSharePatch, alertit, toggleShare, removeFile, listFiles, useCallback, downloadFile, isLoggedIn } from './../imports';
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) {