@nextcloud/files 3.9.1 → 3.10.0

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.
Files changed (39) hide show
  1. package/README.md +63 -26
  2. package/dist/chunks/dav-BBwoJ8WE.cjs +703 -0
  3. package/dist/chunks/dav-BBwoJ8WE.cjs.map +1 -0
  4. package/dist/chunks/dav-DxfiR0wZ.mjs +704 -0
  5. package/dist/chunks/dav-DxfiR0wZ.mjs.map +1 -0
  6. package/dist/dav.cjs +19 -0
  7. package/dist/dav.cjs.map +1 -0
  8. package/dist/dav.d.ts +370 -0
  9. package/dist/dav.mjs +19 -0
  10. package/dist/dav.mjs.map +1 -0
  11. package/dist/index.cjs +99 -709
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.ts +1099 -40
  14. package/dist/index.mjs +403 -1012
  15. package/dist/index.mjs.map +1 -1
  16. package/package.json +13 -8
  17. package/dist/dav/dav.d.ts +0 -56
  18. package/dist/dav/davPermissions.d.ts +0 -6
  19. package/dist/dav/davProperties.d.ts +0 -57
  20. package/dist/fileAction.d.ts +0 -84
  21. package/dist/fileListFilters.d.ts +0 -90
  22. package/dist/fileListHeaders.d.ts +0 -27
  23. package/dist/files/file.d.ts +0 -16
  24. package/dist/files/fileType.d.ts +0 -8
  25. package/dist/files/folder.d.ts +0 -22
  26. package/dist/files/node.d.ts +0 -174
  27. package/dist/files/nodeData.d.ts +0 -54
  28. package/dist/navigation/column.d.ts +0 -28
  29. package/dist/navigation/index.d.ts +0 -7
  30. package/dist/navigation/navigation.d.ts +0 -74
  31. package/dist/navigation/view.d.ts +0 -92
  32. package/dist/newFileMenu.d.ts +0 -66
  33. package/dist/permissions.d.ts +0 -16
  34. package/dist/utils/fileSize.d.ts +0 -25
  35. package/dist/utils/fileSorting.d.ts +0 -35
  36. package/dist/utils/filename-validation.d.ts +0 -51
  37. package/dist/utils/filename.d.ts +0 -24
  38. package/dist/utils/logger.d.ts +0 -2
  39. package/dist/utils/sorting.d.ts +0 -12
package/dist/index.cjs CHANGED
@@ -1,17 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const logger$1 = require("@nextcloud/logger");
4
- const auth = require("@nextcloud/auth");
5
- const path = require("path");
6
- const paths = require("@nextcloud/paths");
7
- const router = require("@nextcloud/router");
8
- const cancelablePromise = require("cancelable-promise");
9
- const webdav = require("webdav");
10
- const _public = require("@nextcloud/sharing/public");
3
+ const dav = require("./chunks/dav-BBwoJ8WE.cjs");
11
4
  const capabilities = require("@nextcloud/capabilities");
5
+ const path = require("path");
12
6
  const l10n = require("@nextcloud/l10n");
13
7
  const typescriptEventTarget = require("typescript-event-target");
14
- const logger = logger$1.getLoggerBuilder().setApp("@nextcloud/files").detectUser().build();
15
8
  var NewMenuEntryCategory = /* @__PURE__ */ ((NewMenuEntryCategory2) => {
16
9
  NewMenuEntryCategory2[NewMenuEntryCategory2["UploadFromDevice"] = 0] = "UploadFromDevice";
17
10
  NewMenuEntryCategory2[NewMenuEntryCategory2["CreateNew"] = 1] = "CreateNew";
@@ -28,7 +21,7 @@ class NewFileMenu {
28
21
  unregisterEntry(entry) {
29
22
  const entryIndex = typeof entry === "string" ? this.getEntryIndex(entry) : this.getEntryIndex(entry.id);
30
23
  if (entryIndex === -1) {
31
- logger.warn("Entry not found, nothing removed", { entry, entries: this.getEntries() });
24
+ dav.logger.warn("Entry not found, nothing removed", { entry, entries: this.getEntries() });
32
25
  return;
33
26
  }
34
27
  this._entries.splice(entryIndex, 1);
@@ -74,7 +67,7 @@ class NewFileMenu {
74
67
  const getNewFileMenu = function() {
75
68
  if (typeof window._nc_newfilemenu === "undefined") {
76
69
  window._nc_newfilemenu = new NewFileMenu();
77
- logger.debug("NewFileMenu initialized");
70
+ dav.logger.debug("NewFileMenu initialized");
78
71
  }
79
72
  return window._nc_newfilemenu;
80
73
  };
@@ -173,10 +166,10 @@ class FileAction {
173
166
  const registerFileAction = function(action) {
174
167
  if (typeof window._nc_fileactions === "undefined") {
175
168
  window._nc_fileactions = [];
176
- logger.debug("FileActions initialized");
169
+ dav.logger.debug("FileActions initialized");
177
170
  }
178
171
  if (window._nc_fileactions.find((search) => search.id === action.id)) {
179
- logger.error(`FileAction ${action.id} already registered`, { action });
172
+ dav.logger.error(`FileAction ${action.id} already registered`, { action });
180
173
  return;
181
174
  }
182
175
  window._nc_fileactions.push(action);
@@ -184,10 +177,71 @@ const registerFileAction = function(action) {
184
177
  const getFileActions = function() {
185
178
  if (typeof window._nc_fileactions === "undefined") {
186
179
  window._nc_fileactions = [];
187
- logger.debug("FileActions initialized");
180
+ dav.logger.debug("FileActions initialized");
188
181
  }
189
182
  return window._nc_fileactions;
190
183
  };
184
+ class FileListAction {
185
+ _action;
186
+ constructor(action) {
187
+ this.validateAction(action);
188
+ this._action = action;
189
+ }
190
+ get id() {
191
+ return this._action.id;
192
+ }
193
+ get displayName() {
194
+ return this._action.displayName;
195
+ }
196
+ get iconSvgInline() {
197
+ return this._action.iconSvgInline;
198
+ }
199
+ get order() {
200
+ return this._action.order;
201
+ }
202
+ get enabled() {
203
+ return this._action.enabled;
204
+ }
205
+ get exec() {
206
+ return this._action.exec;
207
+ }
208
+ validateAction(action) {
209
+ if (!action.id || typeof action.id !== "string") {
210
+ throw new Error("Invalid id");
211
+ }
212
+ if (!action.displayName || typeof action.displayName !== "function") {
213
+ throw new Error("Invalid displayName function");
214
+ }
215
+ if (!action.iconSvgInline || typeof action.iconSvgInline !== "function") {
216
+ throw new Error("Invalid iconSvgInline function");
217
+ }
218
+ if ("order" in action && typeof action.order !== "number") {
219
+ throw new Error("Invalid order");
220
+ }
221
+ if ("enabled" in action && typeof action.enabled !== "function") {
222
+ throw new Error("Invalid enabled function");
223
+ }
224
+ if (!action.exec || typeof action.exec !== "function") {
225
+ throw new Error("Invalid exec function");
226
+ }
227
+ }
228
+ }
229
+ const registerFileListAction = (action) => {
230
+ if (typeof window._nc_filelistactions === "undefined") {
231
+ window._nc_filelistactions = [];
232
+ }
233
+ if (window._nc_filelistactions.find((listAction) => listAction.id === action.id)) {
234
+ dav.logger.error(`FileListAction with id "${action.id}" is already registered`, { action });
235
+ return;
236
+ }
237
+ window._nc_filelistactions.push(action);
238
+ };
239
+ const getFileListActions = () => {
240
+ if (typeof window._nc_filelistactions === "undefined") {
241
+ window._nc_filelistactions = [];
242
+ }
243
+ return window._nc_filelistactions;
244
+ };
191
245
  class Header {
192
246
  _header;
193
247
  constructor(header) {
@@ -230,10 +284,10 @@ class Header {
230
284
  const registerFileListHeaders = function(header) {
231
285
  if (typeof window._nc_filelistheader === "undefined") {
232
286
  window._nc_filelistheader = [];
233
- logger.debug("FileListHeaders initialized");
287
+ dav.logger.debug("FileListHeaders initialized");
234
288
  }
235
289
  if (window._nc_filelistheader.find((search) => search.id === header.id)) {
236
- logger.error(`Header ${header.id} already registered`, { header });
290
+ dav.logger.error(`Header ${header.id} already registered`, { header });
237
291
  return;
238
292
  }
239
293
  window._nc_filelistheader.push(header);
@@ -241,677 +295,10 @@ const registerFileListHeaders = function(header) {
241
295
  const getFileListHeaders = function() {
242
296
  if (typeof window._nc_filelistheader === "undefined") {
243
297
  window._nc_filelistheader = [];
244
- logger.debug("FileListHeaders initialized");
298
+ dav.logger.debug("FileListHeaders initialized");
245
299
  }
246
300
  return window._nc_filelistheader;
247
301
  };
248
- var Permission = /* @__PURE__ */ ((Permission2) => {
249
- Permission2[Permission2["NONE"] = 0] = "NONE";
250
- Permission2[Permission2["CREATE"] = 4] = "CREATE";
251
- Permission2[Permission2["READ"] = 1] = "READ";
252
- Permission2[Permission2["UPDATE"] = 2] = "UPDATE";
253
- Permission2[Permission2["DELETE"] = 8] = "DELETE";
254
- Permission2[Permission2["SHARE"] = 16] = "SHARE";
255
- Permission2[Permission2["ALL"] = 31] = "ALL";
256
- return Permission2;
257
- })(Permission || {});
258
- const defaultDavProperties = [
259
- "d:getcontentlength",
260
- "d:getcontenttype",
261
- "d:getetag",
262
- "d:getlastmodified",
263
- "d:creationdate",
264
- "d:displayname",
265
- "d:quota-available-bytes",
266
- "d:resourcetype",
267
- "nc:has-preview",
268
- "nc:is-encrypted",
269
- "nc:mount-type",
270
- "oc:comments-unread",
271
- "oc:favorite",
272
- "oc:fileid",
273
- "oc:owner-display-name",
274
- "oc:owner-id",
275
- "oc:permissions",
276
- "oc:size"
277
- ];
278
- const defaultDavNamespaces = {
279
- d: "DAV:",
280
- nc: "http://nextcloud.org/ns",
281
- oc: "http://owncloud.org/ns",
282
- ocs: "http://open-collaboration-services.org/ns"
283
- };
284
- const registerDavProperty = function(prop, namespace = { nc: "http://nextcloud.org/ns" }) {
285
- if (typeof window._nc_dav_properties === "undefined") {
286
- window._nc_dav_properties = [...defaultDavProperties];
287
- window._nc_dav_namespaces = { ...defaultDavNamespaces };
288
- }
289
- const namespaces = { ...window._nc_dav_namespaces, ...namespace };
290
- if (window._nc_dav_properties.find((search) => search === prop)) {
291
- logger.warn(`${prop} already registered`, { prop });
292
- return false;
293
- }
294
- if (prop.startsWith("<") || prop.split(":").length !== 2) {
295
- logger.error(`${prop} is not valid. See example: 'oc:fileid'`, { prop });
296
- return false;
297
- }
298
- const ns = prop.split(":")[0];
299
- if (!namespaces[ns]) {
300
- logger.error(`${prop} namespace unknown`, { prop, namespaces });
301
- return false;
302
- }
303
- window._nc_dav_properties.push(prop);
304
- window._nc_dav_namespaces = namespaces;
305
- return true;
306
- };
307
- const getDavProperties = function() {
308
- if (typeof window._nc_dav_properties === "undefined") {
309
- window._nc_dav_properties = [...defaultDavProperties];
310
- }
311
- return window._nc_dav_properties.map((prop) => `<${prop} />`).join(" ");
312
- };
313
- const getDavNameSpaces = function() {
314
- if (typeof window._nc_dav_namespaces === "undefined") {
315
- window._nc_dav_namespaces = { ...defaultDavNamespaces };
316
- }
317
- return Object.keys(window._nc_dav_namespaces).map((ns) => `xmlns:${ns}="${window._nc_dav_namespaces?.[ns]}"`).join(" ");
318
- };
319
- const davGetDefaultPropfind = function() {
320
- return `<?xml version="1.0"?>
321
- <d:propfind ${getDavNameSpaces()}>
322
- <d:prop>
323
- ${getDavProperties()}
324
- </d:prop>
325
- </d:propfind>`;
326
- };
327
- const davGetFavoritesReport = function() {
328
- return `<?xml version="1.0"?>
329
- <oc:filter-files ${getDavNameSpaces()}>
330
- <d:prop>
331
- ${getDavProperties()}
332
- </d:prop>
333
- <oc:filter-rules>
334
- <oc:favorite>1</oc:favorite>
335
- </oc:filter-rules>
336
- </oc:filter-files>`;
337
- };
338
- const davGetRecentSearch = function(lastModified) {
339
- return `<?xml version="1.0" encoding="UTF-8"?>
340
- <d:searchrequest ${getDavNameSpaces()}
341
- xmlns:ns="https://github.com/icewind1991/SearchDAV/ns">
342
- <d:basicsearch>
343
- <d:select>
344
- <d:prop>
345
- ${getDavProperties()}
346
- </d:prop>
347
- </d:select>
348
- <d:from>
349
- <d:scope>
350
- <d:href>/files/${auth.getCurrentUser()?.uid}/</d:href>
351
- <d:depth>infinity</d:depth>
352
- </d:scope>
353
- </d:from>
354
- <d:where>
355
- <d:and>
356
- <d:or>
357
- <d:not>
358
- <d:eq>
359
- <d:prop>
360
- <d:getcontenttype/>
361
- </d:prop>
362
- <d:literal>httpd/unix-directory</d:literal>
363
- </d:eq>
364
- </d:not>
365
- <d:eq>
366
- <d:prop>
367
- <oc:size/>
368
- </d:prop>
369
- <d:literal>0</d:literal>
370
- </d:eq>
371
- </d:or>
372
- <d:gt>
373
- <d:prop>
374
- <d:getlastmodified/>
375
- </d:prop>
376
- <d:literal>${lastModified}</d:literal>
377
- </d:gt>
378
- </d:and>
379
- </d:where>
380
- <d:orderby>
381
- <d:order>
382
- <d:prop>
383
- <d:getlastmodified/>
384
- </d:prop>
385
- <d:descending/>
386
- </d:order>
387
- </d:orderby>
388
- <d:limit>
389
- <d:nresults>100</d:nresults>
390
- <ns:firstresult>0</ns:firstresult>
391
- </d:limit>
392
- </d:basicsearch>
393
- </d:searchrequest>`;
394
- };
395
- const davParsePermissions = function(permString = "") {
396
- let permissions = Permission.NONE;
397
- if (!permString) {
398
- return permissions;
399
- }
400
- if (permString.includes("C") || permString.includes("K")) {
401
- permissions |= Permission.CREATE;
402
- }
403
- if (permString.includes("G")) {
404
- permissions |= Permission.READ;
405
- }
406
- if (permString.includes("W") || permString.includes("N") || permString.includes("V")) {
407
- permissions |= Permission.UPDATE;
408
- }
409
- if (permString.includes("D")) {
410
- permissions |= Permission.DELETE;
411
- }
412
- if (permString.includes("R")) {
413
- permissions |= Permission.SHARE;
414
- }
415
- return permissions;
416
- };
417
- var FileType = /* @__PURE__ */ ((FileType2) => {
418
- FileType2["Folder"] = "folder";
419
- FileType2["File"] = "file";
420
- return FileType2;
421
- })(FileType || {});
422
- const isDavRessource = function(source, davService) {
423
- return source.match(davService) !== null;
424
- };
425
- const validateData = (data, davService) => {
426
- if (data.id && typeof data.id !== "number") {
427
- throw new Error("Invalid id type of value");
428
- }
429
- if (!data.source) {
430
- throw new Error("Missing mandatory source");
431
- }
432
- try {
433
- new URL(data.source);
434
- } catch (e) {
435
- throw new Error("Invalid source format, source must be a valid URL");
436
- }
437
- if (!data.source.startsWith("http")) {
438
- throw new Error("Invalid source format, only http(s) is supported");
439
- }
440
- if (data.displayname && typeof data.displayname !== "string") {
441
- throw new Error("Invalid displayname type");
442
- }
443
- if (data.mtime && !(data.mtime instanceof Date)) {
444
- throw new Error("Invalid mtime type");
445
- }
446
- if (data.crtime && !(data.crtime instanceof Date)) {
447
- throw new Error("Invalid crtime type");
448
- }
449
- if (!data.mime || typeof data.mime !== "string" || !data.mime.match(/^[-\w.]+\/[-+\w.]+$/gi)) {
450
- throw new Error("Missing or invalid mandatory mime");
451
- }
452
- if ("size" in data && typeof data.size !== "number" && data.size !== void 0) {
453
- throw new Error("Invalid size type");
454
- }
455
- if ("permissions" in data && data.permissions !== void 0 && !(typeof data.permissions === "number" && data.permissions >= Permission.NONE && data.permissions <= Permission.ALL)) {
456
- throw new Error("Invalid permissions");
457
- }
458
- if (data.owner && data.owner !== null && typeof data.owner !== "string") {
459
- throw new Error("Invalid owner type");
460
- }
461
- if (data.attributes && typeof data.attributes !== "object") {
462
- throw new Error("Invalid attributes type");
463
- }
464
- if (data.root && typeof data.root !== "string") {
465
- throw new Error("Invalid root type");
466
- }
467
- if (data.root && !data.root.startsWith("/")) {
468
- throw new Error("Root must start with a leading slash");
469
- }
470
- if (data.root && !data.source.includes(data.root)) {
471
- throw new Error("Root must be part of the source");
472
- }
473
- if (data.root && isDavRessource(data.source, davService)) {
474
- const service = data.source.match(davService)[0];
475
- if (!data.source.includes(path.join(service, data.root))) {
476
- throw new Error("The root must be relative to the service. e.g /files/emma");
477
- }
478
- }
479
- if (data.status && !Object.values(NodeStatus).includes(data.status)) {
480
- throw new Error("Status must be a valid NodeStatus");
481
- }
482
- };
483
- var NodeStatus = /* @__PURE__ */ ((NodeStatus2) => {
484
- NodeStatus2["NEW"] = "new";
485
- NodeStatus2["FAILED"] = "failed";
486
- NodeStatus2["LOADING"] = "loading";
487
- NodeStatus2["LOCKED"] = "locked";
488
- return NodeStatus2;
489
- })(NodeStatus || {});
490
- class Node {
491
- _data;
492
- _attributes;
493
- _knownDavService = /(remote|public)\.php\/(web)?dav/i;
494
- readonlyAttributes = Object.entries(Object.getOwnPropertyDescriptors(Node.prototype)).filter((e) => typeof e[1].get === "function" && e[0] !== "__proto__").map((e) => e[0]);
495
- handler = {
496
- set: (target, prop, value) => {
497
- if (this.readonlyAttributes.includes(prop)) {
498
- return false;
499
- }
500
- return Reflect.set(target, prop, value);
501
- },
502
- deleteProperty: (target, prop) => {
503
- if (this.readonlyAttributes.includes(prop)) {
504
- return false;
505
- }
506
- return Reflect.deleteProperty(target, prop);
507
- },
508
- // TODO: This is deprecated and only needed for files v3
509
- get: (target, prop, receiver) => {
510
- if (this.readonlyAttributes.includes(prop)) {
511
- logger.warn(`Accessing "Node.attributes.${prop}" is deprecated, access it directly on the Node instance.`);
512
- return Reflect.get(this, prop);
513
- }
514
- return Reflect.get(target, prop, receiver);
515
- }
516
- };
517
- constructor(data, davService) {
518
- validateData(data, davService || this._knownDavService);
519
- this._data = {
520
- // TODO: Remove with next major release, this is just for compatibility
521
- displayname: data.attributes?.displayname,
522
- ...data,
523
- attributes: {}
524
- };
525
- this._attributes = new Proxy(this._data.attributes, this.handler);
526
- this.update(data.attributes ?? {});
527
- if (davService) {
528
- this._knownDavService = davService;
529
- }
530
- }
531
- /**
532
- * Get the source url to this object
533
- * There is no setter as the source is not meant to be changed manually.
534
- * You can use the rename or move method to change the source.
535
- */
536
- get source() {
537
- return this._data.source.replace(/\/$/i, "");
538
- }
539
- /**
540
- * Get the encoded source url to this object for requests purposes
541
- */
542
- get encodedSource() {
543
- const { origin } = new URL(this.source);
544
- return origin + paths.encodePath(this.source.slice(origin.length));
545
- }
546
- /**
547
- * Get this object name
548
- * There is no setter as the source is not meant to be changed manually.
549
- * You can use the rename or move method to change the source.
550
- */
551
- get basename() {
552
- return path.basename(this.source);
553
- }
554
- /**
555
- * The nodes displayname
556
- * By default the display name and the `basename` are identical,
557
- * but it is possible to have a different name. This happens
558
- * on the files app for example for shared folders.
559
- */
560
- get displayname() {
561
- return this._data.displayname || this.basename;
562
- }
563
- /**
564
- * Set the displayname
565
- */
566
- set displayname(displayname) {
567
- this._data.displayname = displayname;
568
- }
569
- /**
570
- * Get this object's extension
571
- * There is no setter as the source is not meant to be changed manually.
572
- * You can use the rename or move method to change the source.
573
- */
574
- get extension() {
575
- return path.extname(this.source);
576
- }
577
- /**
578
- * Get the directory path leading to this object
579
- * Will use the relative path to root if available
580
- *
581
- * There is no setter as the source is not meant to be changed manually.
582
- * You can use the rename or move method to change the source.
583
- */
584
- get dirname() {
585
- if (this.root) {
586
- let source = this.source;
587
- if (this.isDavRessource) {
588
- source = source.split(this._knownDavService).pop();
589
- }
590
- const firstMatch = source.indexOf(this.root);
591
- const root = this.root.replace(/\/$/, "");
592
- return path.dirname(source.slice(firstMatch + root.length) || "/");
593
- }
594
- const url = new URL(this.source);
595
- return path.dirname(url.pathname);
596
- }
597
- /**
598
- * Get the file mime
599
- * There is no setter as the mime is not meant to be changed
600
- */
601
- get mime() {
602
- return this._data.mime;
603
- }
604
- /**
605
- * Get the file modification time
606
- */
607
- get mtime() {
608
- return this._data.mtime;
609
- }
610
- /**
611
- * Set the file modification time
612
- */
613
- set mtime(mtime) {
614
- this._data.mtime = mtime;
615
- }
616
- /**
617
- * Get the file creation time
618
- * There is no setter as the creation time is not meant to be changed
619
- */
620
- get crtime() {
621
- return this._data.crtime;
622
- }
623
- /**
624
- * Get the file size
625
- */
626
- get size() {
627
- return this._data.size;
628
- }
629
- /**
630
- * Set the file size
631
- */
632
- set size(size) {
633
- this.updateMtime();
634
- this._data.size = size;
635
- }
636
- /**
637
- * Get the file attribute
638
- * This contains all additional attributes not provided by the Node class
639
- */
640
- get attributes() {
641
- return this._attributes;
642
- }
643
- /**
644
- * Get the file permissions
645
- */
646
- get permissions() {
647
- if (this.owner === null && !this.isDavRessource) {
648
- return Permission.READ;
649
- }
650
- return this._data.permissions !== void 0 ? this._data.permissions : Permission.NONE;
651
- }
652
- /**
653
- * Set the file permissions
654
- */
655
- set permissions(permissions) {
656
- this.updateMtime();
657
- this._data.permissions = permissions;
658
- }
659
- /**
660
- * Get the file owner
661
- * There is no setter as the owner is not meant to be changed
662
- */
663
- get owner() {
664
- if (!this.isDavRessource) {
665
- return null;
666
- }
667
- return this._data.owner;
668
- }
669
- /**
670
- * Is this a dav-related ressource ?
671
- */
672
- get isDavRessource() {
673
- return isDavRessource(this.source, this._knownDavService);
674
- }
675
- /**
676
- * Get the dav root of this object
677
- * There is no setter as the root is not meant to be changed
678
- */
679
- get root() {
680
- if (this._data.root) {
681
- return this._data.root.replace(/^(.+)\/$/, "$1");
682
- }
683
- if (this.isDavRessource) {
684
- const root = path.dirname(this.source);
685
- return root.split(this._knownDavService).pop() || null;
686
- }
687
- return null;
688
- }
689
- /**
690
- * Get the absolute path of this object relative to the root
691
- */
692
- get path() {
693
- if (this.root) {
694
- let source = this.source;
695
- if (this.isDavRessource) {
696
- source = source.split(this._knownDavService).pop();
697
- }
698
- const firstMatch = source.indexOf(this.root);
699
- const root = this.root.replace(/\/$/, "");
700
- return source.slice(firstMatch + root.length) || "/";
701
- }
702
- return (this.dirname + "/" + this.basename).replace(/\/\//g, "/");
703
- }
704
- /**
705
- * Get the node id if defined.
706
- * There is no setter as the fileid is not meant to be changed
707
- */
708
- get fileid() {
709
- return this._data?.id;
710
- }
711
- /**
712
- * Get the node status.
713
- */
714
- get status() {
715
- return this._data?.status;
716
- }
717
- /**
718
- * Set the node status.
719
- */
720
- set status(status) {
721
- this._data.status = status;
722
- }
723
- /**
724
- * Get the node data
725
- */
726
- get data() {
727
- return structuredClone(this._data);
728
- }
729
- /**
730
- * Move the node to a new destination
731
- *
732
- * @param {string} destination the new source.
733
- * e.g. https://cloud.domain.com/remote.php/dav/files/emma/Photos/picture.jpg
734
- */
735
- move(destination) {
736
- validateData({ ...this._data, source: destination }, this._knownDavService);
737
- const oldBasename = this.basename;
738
- this._data.source = destination;
739
- if (this.displayname === oldBasename && this.basename !== oldBasename) {
740
- this.displayname = this.basename;
741
- }
742
- this.updateMtime();
743
- }
744
- /**
745
- * Rename the node
746
- * This aliases the move method for easier usage
747
- *
748
- * @param basename The new name of the node
749
- */
750
- rename(basename2) {
751
- if (basename2.includes("/")) {
752
- throw new Error("Invalid basename");
753
- }
754
- this.move(path.dirname(this.source) + "/" + basename2);
755
- }
756
- /**
757
- * Update the mtime if exists
758
- */
759
- updateMtime() {
760
- if (this._data.mtime) {
761
- this._data.mtime = /* @__PURE__ */ new Date();
762
- }
763
- }
764
- /**
765
- * Update the attributes of the node
766
- * Warning, updating attributes will NOT automatically update the mtime.
767
- *
768
- * @param attributes The new attributes to update on the Node attributes
769
- */
770
- update(attributes) {
771
- for (const [name, value] of Object.entries(attributes)) {
772
- try {
773
- if (value === void 0) {
774
- delete this.attributes[name];
775
- } else {
776
- this.attributes[name] = value;
777
- }
778
- } catch (e) {
779
- if (e instanceof TypeError) {
780
- continue;
781
- }
782
- throw e;
783
- }
784
- }
785
- }
786
- }
787
- class File extends Node {
788
- get type() {
789
- return FileType.File;
790
- }
791
- /**
792
- * Returns a clone of the file
793
- */
794
- clone() {
795
- return new File(this.data);
796
- }
797
- }
798
- class Folder extends Node {
799
- constructor(data) {
800
- super({
801
- ...data,
802
- mime: "httpd/unix-directory"
803
- });
804
- }
805
- get type() {
806
- return FileType.Folder;
807
- }
808
- get extension() {
809
- return null;
810
- }
811
- get mime() {
812
- return "httpd/unix-directory";
813
- }
814
- /**
815
- * Returns a clone of the folder
816
- */
817
- clone() {
818
- return new Folder(this.data);
819
- }
820
- }
821
- function davGetRootPath() {
822
- if (_public.isPublicShare()) {
823
- return `/files/${_public.getSharingToken()}`;
824
- }
825
- return `/files/${auth.getCurrentUser()?.uid}`;
826
- }
827
- const davRootPath = davGetRootPath();
828
- function davGetRemoteURL() {
829
- const url = router.generateRemoteUrl("dav");
830
- if (_public.isPublicShare()) {
831
- return url.replace("remote.php", "public.php");
832
- }
833
- return url;
834
- }
835
- const davRemoteURL = davGetRemoteURL();
836
- const davGetClient = function(remoteURL = davRemoteURL, headers = {}) {
837
- const client = webdav.createClient(remoteURL, { headers });
838
- function setHeaders(token) {
839
- client.setHeaders({
840
- ...headers,
841
- // Add this so the server knows it is an request from the browser
842
- "X-Requested-With": "XMLHttpRequest",
843
- // Inject user auth
844
- requesttoken: token ?? ""
845
- });
846
- }
847
- auth.onRequestTokenUpdate(setHeaders);
848
- setHeaders(auth.getRequestToken());
849
- const patcher = webdav.getPatcher();
850
- patcher.patch("fetch", (url, options) => {
851
- const headers2 = options.headers;
852
- if (headers2?.method) {
853
- options.method = headers2.method;
854
- delete headers2.method;
855
- }
856
- return fetch(url, options);
857
- });
858
- return client;
859
- };
860
- const getFavoriteNodes = (davClient, path2 = "/", davRoot = davRootPath) => {
861
- const controller = new AbortController();
862
- return new cancelablePromise.CancelablePromise(async (resolve, reject, onCancel) => {
863
- onCancel(() => controller.abort());
864
- try {
865
- const contentsResponse = await davClient.getDirectoryContents(`${davRoot}${path2}`, {
866
- signal: controller.signal,
867
- details: true,
868
- data: davGetFavoritesReport(),
869
- headers: {
870
- // see davGetClient for patched webdav client
871
- method: "REPORT"
872
- },
873
- includeSelf: true
874
- });
875
- const nodes = contentsResponse.data.filter((node) => node.filename !== path2).map((result) => davResultToNode(result, davRoot));
876
- resolve(nodes);
877
- } catch (error) {
878
- reject(error);
879
- }
880
- });
881
- };
882
- const davResultToNode = function(node, filesRoot = davRootPath, remoteURL = davRemoteURL) {
883
- let userId = auth.getCurrentUser()?.uid;
884
- if (_public.isPublicShare()) {
885
- userId = userId ?? "anonymous";
886
- } else if (!userId) {
887
- throw new Error("No user id found");
888
- }
889
- const props = node.props;
890
- const permissions = davParsePermissions(props?.permissions);
891
- const owner = String(props?.["owner-id"] || userId);
892
- const id = props.fileid || 0;
893
- const nodeData = {
894
- id,
895
- source: `${remoteURL}${node.filename}`,
896
- mtime: new Date(Date.parse(node.lastmod)),
897
- mime: node.mime || "application/octet-stream",
898
- // Manually cast to work around for https://github.com/perry-mitchell/webdav-client/pull/380
899
- displayname: props.displayname !== void 0 ? String(props.displayname) : void 0,
900
- size: props?.size || Number.parseInt(props.getcontentlength || "0"),
901
- // The fileid is set to -1 for failed requests
902
- status: id < 0 ? NodeStatus.FAILED : void 0,
903
- permissions,
904
- owner,
905
- root: filesRoot,
906
- attributes: {
907
- ...node,
908
- ...props,
909
- hasPreview: props?.["has-preview"]
910
- }
911
- };
912
- delete nodeData.attributes?.props;
913
- return node.type === "file" ? new File(nodeData) : new Folder(nodeData);
914
- };
915
302
  var InvalidFilenameErrorReason = /* @__PURE__ */ ((InvalidFilenameErrorReason2) => {
916
303
  InvalidFilenameErrorReason2["ReservedName"] = "reserved name";
917
304
  InvalidFilenameErrorReason2["Character"] = "character";
@@ -1170,7 +557,7 @@ class Navigation extends typescriptEventTarget.TypedEventTarget {
1170
557
  const getNavigation = function() {
1171
558
  if (typeof window._nc_navigation === "undefined") {
1172
559
  window._nc_navigation = new Navigation();
1173
- logger.debug("Navigation service initialized");
560
+ dav.logger.debug("Navigation service initialized");
1174
561
  }
1175
562
  return window._nc_navigation;
1176
563
  };
@@ -2915,8 +2302,8 @@ const isValidView = function(view) {
2915
2302
  if (!view.name || typeof view.name !== "string") {
2916
2303
  throw new Error("View name is required and must be a string");
2917
2304
  }
2918
- if (view.columns && view.columns.length > 0 && (!view.caption || typeof view.caption !== "string")) {
2919
- throw new Error("View caption is required for top-level views and must be a string");
2305
+ if ("caption" in view && typeof view.caption !== "string") {
2306
+ throw new Error("View caption must be a string");
2920
2307
  }
2921
2308
  if (!view.getContents || typeof view.getContents !== "function") {
2922
2309
  throw new Error("View getContents is required and must be a function");
@@ -3499,41 +2886,44 @@ const getNewFileMenuEntries = function(context) {
3499
2886
  return a.displayName.localeCompare(b.displayName, void 0, { numeric: true, sensitivity: "base" });
3500
2887
  });
3501
2888
  };
2889
+ exports.File = dav.File;
2890
+ exports.FileType = dav.FileType;
2891
+ exports.Folder = dav.Folder;
2892
+ exports.Node = dav.Node;
2893
+ exports.NodeStatus = dav.NodeStatus;
2894
+ exports.Permission = dav.Permission;
2895
+ exports.davGetClient = dav.getClient;
2896
+ exports.davGetDefaultPropfind = dav.getDefaultPropfind;
2897
+ exports.davGetFavoritesReport = dav.getFavoritesReport;
2898
+ exports.davGetRecentSearch = dav.getRecentSearch;
2899
+ exports.davGetRemoteURL = dav.getRemoteURL;
2900
+ exports.davGetRootPath = dav.getRootPath;
2901
+ exports.davParsePermissions = dav.parsePermissions;
2902
+ exports.davRemoteURL = dav.defaultRemoteURL;
2903
+ exports.davResultToNode = dav.resultToNode;
2904
+ exports.davRootPath = dav.defaultRootPath;
2905
+ exports.defaultDavNamespaces = dav.defaultDavNamespaces;
2906
+ exports.defaultDavProperties = dav.defaultDavProperties;
2907
+ exports.getDavNameSpaces = dav.getDavNameSpaces;
2908
+ exports.getDavProperties = dav.getDavProperties;
2909
+ exports.getFavoriteNodes = dav.getFavoriteNodes;
2910
+ exports.registerDavProperty = dav.registerDavProperty;
3502
2911
  exports.Column = Column;
3503
2912
  exports.DefaultType = DefaultType;
3504
- exports.File = File;
3505
2913
  exports.FileAction = FileAction;
2914
+ exports.FileListAction = FileListAction;
3506
2915
  exports.FileListFilter = FileListFilter;
3507
- exports.FileType = FileType;
3508
2916
  exports.FilesSortingMode = FilesSortingMode;
3509
- exports.Folder = Folder;
3510
2917
  exports.Header = Header;
3511
2918
  exports.InvalidFilenameError = InvalidFilenameError;
3512
2919
  exports.InvalidFilenameErrorReason = InvalidFilenameErrorReason;
3513
2920
  exports.Navigation = Navigation;
3514
2921
  exports.NewMenuEntryCategory = NewMenuEntryCategory;
3515
- exports.Node = Node;
3516
- exports.NodeStatus = NodeStatus;
3517
- exports.Permission = Permission;
3518
2922
  exports.View = View;
3519
2923
  exports.addNewFileMenuEntry = addNewFileMenuEntry;
3520
- exports.davGetClient = davGetClient;
3521
- exports.davGetDefaultPropfind = davGetDefaultPropfind;
3522
- exports.davGetFavoritesReport = davGetFavoritesReport;
3523
- exports.davGetRecentSearch = davGetRecentSearch;
3524
- exports.davGetRemoteURL = davGetRemoteURL;
3525
- exports.davGetRootPath = davGetRootPath;
3526
- exports.davParsePermissions = davParsePermissions;
3527
- exports.davRemoteURL = davRemoteURL;
3528
- exports.davResultToNode = davResultToNode;
3529
- exports.davRootPath = davRootPath;
3530
- exports.defaultDavNamespaces = defaultDavNamespaces;
3531
- exports.defaultDavProperties = defaultDavProperties;
3532
2924
  exports.formatFileSize = formatFileSize;
3533
- exports.getDavNameSpaces = getDavNameSpaces;
3534
- exports.getDavProperties = getDavProperties;
3535
- exports.getFavoriteNodes = getFavoriteNodes;
3536
2925
  exports.getFileActions = getFileActions;
2926
+ exports.getFileListActions = getFileListActions;
3537
2927
  exports.getFileListFilters = getFileListFilters;
3538
2928
  exports.getFileListHeaders = getFileListHeaders;
3539
2929
  exports.getNavigation = getNavigation;
@@ -3542,8 +2932,8 @@ exports.getUniqueName = getUniqueName;
3542
2932
  exports.isFilenameValid = isFilenameValid;
3543
2933
  exports.orderBy = orderBy;
3544
2934
  exports.parseFileSize = parseFileSize;
3545
- exports.registerDavProperty = registerDavProperty;
3546
2935
  exports.registerFileAction = registerFileAction;
2936
+ exports.registerFileListAction = registerFileListAction;
3547
2937
  exports.registerFileListFilter = registerFileListFilter;
3548
2938
  exports.registerFileListHeaders = registerFileListHeaders;
3549
2939
  exports.removeNewFileMenuEntry = removeNewFileMenuEntry;