@camstack/addon-remote-storage 1.2.76 → 1.2.77
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/s3.addon.js +1 -1
- package/dist/s3.addon.mjs +1 -1
- package/dist/sftp.addon.js +1 -1
- package/dist/sftp.addon.mjs +1 -1
- package/dist/{shared-DlUg7bET.js → shared-DW6PfRB-.js} +33 -14
- package/dist/{shared-Ch1dJcLf.mjs → shared-NUBj0w5N.mjs} +33 -14
- package/dist/smb.addon.js +31 -4
- package/dist/smb.addon.mjs +31 -4
- package/dist/webdav.addon.js +1 -1
- package/dist/webdav.addon.mjs +1 -1
- package/package.json +1 -1
package/dist/s3.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-DW6PfRB-.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
|
|
8
8
|
let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
|
package/dist/s3.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
4
4
|
import { Upload } from "@aws-sdk/lib-storage";
|
package/dist/sftp.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-DW6PfRB-.js");
|
|
6
6
|
let ssh2 = require("ssh2");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_shared.__toESM(node_path);
|
package/dist/sftp.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
|
|
2
2
|
import { Client } from "ssh2";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
//#region src/providers/sftp/sftp-config-schema.ts
|
|
@@ -10557,12 +10557,30 @@ var BackupDestinationInfoSchema = object({
|
|
|
10557
10557
|
lastSuccessAt: number().optional(),
|
|
10558
10558
|
/** Newest-archive size from `manifests.json`, or undefined. */
|
|
10559
10559
|
lastSuccessSizeBytes: number().optional(),
|
|
10560
|
-
/**
|
|
10560
|
+
/**
|
|
10561
|
+
* Cron cadence(s) of the ENABLED schedules that fan out to this
|
|
10562
|
+
* destination, comma-joined. Absent when no enabled schedule targets it
|
|
10563
|
+
* — a destination nothing is scheduled to write to must not advertise a
|
|
10564
|
+
* cadence (D384). This is never the `backup_destination_policies.cron`
|
|
10565
|
+
* column: that per-location cron has scheduled nothing since 2026-07-28
|
|
10566
|
+
* and reading it made a destination with a DISABLED schedule claim a
|
|
10567
|
+
* nightly run.
|
|
10568
|
+
*/
|
|
10561
10569
|
cron: string().optional(),
|
|
10562
|
-
/** ms-epoch of next
|
|
10570
|
+
/** ms-epoch of the next firing across those schedules (earliest), if any. */
|
|
10563
10571
|
nextRunAt: number().optional(),
|
|
10564
|
-
/**
|
|
10565
|
-
|
|
10572
|
+
/**
|
|
10573
|
+
* ms-epoch of the last time a run ATTEMPTED to write here — success or
|
|
10574
|
+
* failure. Never a success stamp: pair it with `lastSuccessAt` (the
|
|
10575
|
+
* newest archive that actually landed) and `lastError`.
|
|
10576
|
+
*/
|
|
10577
|
+
lastAttemptAt: number().optional(),
|
|
10578
|
+
/**
|
|
10579
|
+
* Why the last attempt failed, verbatim. Absent when the last attempt
|
|
10580
|
+
* landed the archive. A destination that has never been written to has
|
|
10581
|
+
* neither this nor `lastAttemptAt`.
|
|
10582
|
+
*/
|
|
10583
|
+
lastError: string().optional()
|
|
10566
10584
|
});
|
|
10567
10585
|
/**
|
|
10568
10586
|
* Per-archive entry returned by `backup.listArchives({ destinationId })`.
|
|
@@ -10725,8 +10743,16 @@ var BackupScheduleSchema = object({
|
|
|
10725
10743
|
retentionCount: number().int().min(1).max(1e3),
|
|
10726
10744
|
/** Optional subset of source locations to include; omitted = all. */
|
|
10727
10745
|
dataSources: array(string()).readonly().optional(),
|
|
10728
|
-
/**
|
|
10729
|
-
|
|
10746
|
+
/**
|
|
10747
|
+
* ms-epoch of the last tick that FIRED this schedule. Stamped before the
|
|
10748
|
+
* archive runs (it is the dedupe anchor), so it says "attempted", never
|
|
10749
|
+
* "succeeded" — a run refused by every destination stamps it too.
|
|
10750
|
+
*/
|
|
10751
|
+
lastAttemptAt: number().optional(),
|
|
10752
|
+
/** ms-epoch of the last run of this schedule that landed at ≥1 destination. */
|
|
10753
|
+
lastSuccessAt: number().optional(),
|
|
10754
|
+
/** Why the last fired run failed, verbatim. Absent when it succeeded. */
|
|
10755
|
+
lastError: string().optional(),
|
|
10730
10756
|
/** ms-epoch of next computed firing (read-only, filled on list). */
|
|
10731
10757
|
nextRunAt: number().optional()
|
|
10732
10758
|
});
|
|
@@ -10775,14 +10801,7 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
|
|
|
10775
10801
|
locationId: string(),
|
|
10776
10802
|
enabled: boolean(),
|
|
10777
10803
|
retentionCount: number().int().min(1).max(1e3),
|
|
10778
|
-
label: string().optional()
|
|
10779
|
-
/**
|
|
10780
|
-
* Per-destination cron expression. Empty string clears the
|
|
10781
|
-
* schedule (manual-only). Validated server-side via croner;
|
|
10782
|
-
* malformed expressions reject the upsert with an actionable
|
|
10783
|
-
* message.
|
|
10784
|
-
*/
|
|
10785
|
-
cron: string().optional()
|
|
10804
|
+
label: string().optional()
|
|
10786
10805
|
}), _void(), {
|
|
10787
10806
|
kind: "mutation",
|
|
10788
10807
|
auth: "admin"
|
|
@@ -10534,12 +10534,30 @@ var BackupDestinationInfoSchema = object({
|
|
|
10534
10534
|
lastSuccessAt: number().optional(),
|
|
10535
10535
|
/** Newest-archive size from `manifests.json`, or undefined. */
|
|
10536
10536
|
lastSuccessSizeBytes: number().optional(),
|
|
10537
|
-
/**
|
|
10537
|
+
/**
|
|
10538
|
+
* Cron cadence(s) of the ENABLED schedules that fan out to this
|
|
10539
|
+
* destination, comma-joined. Absent when no enabled schedule targets it
|
|
10540
|
+
* — a destination nothing is scheduled to write to must not advertise a
|
|
10541
|
+
* cadence (D384). This is never the `backup_destination_policies.cron`
|
|
10542
|
+
* column: that per-location cron has scheduled nothing since 2026-07-28
|
|
10543
|
+
* and reading it made a destination with a DISABLED schedule claim a
|
|
10544
|
+
* nightly run.
|
|
10545
|
+
*/
|
|
10538
10546
|
cron: string().optional(),
|
|
10539
|
-
/** ms-epoch of next
|
|
10547
|
+
/** ms-epoch of the next firing across those schedules (earliest), if any. */
|
|
10540
10548
|
nextRunAt: number().optional(),
|
|
10541
|
-
/**
|
|
10542
|
-
|
|
10549
|
+
/**
|
|
10550
|
+
* ms-epoch of the last time a run ATTEMPTED to write here — success or
|
|
10551
|
+
* failure. Never a success stamp: pair it with `lastSuccessAt` (the
|
|
10552
|
+
* newest archive that actually landed) and `lastError`.
|
|
10553
|
+
*/
|
|
10554
|
+
lastAttemptAt: number().optional(),
|
|
10555
|
+
/**
|
|
10556
|
+
* Why the last attempt failed, verbatim. Absent when the last attempt
|
|
10557
|
+
* landed the archive. A destination that has never been written to has
|
|
10558
|
+
* neither this nor `lastAttemptAt`.
|
|
10559
|
+
*/
|
|
10560
|
+
lastError: string().optional()
|
|
10543
10561
|
});
|
|
10544
10562
|
/**
|
|
10545
10563
|
* Per-archive entry returned by `backup.listArchives({ destinationId })`.
|
|
@@ -10702,8 +10720,16 @@ var BackupScheduleSchema = object({
|
|
|
10702
10720
|
retentionCount: number().int().min(1).max(1e3),
|
|
10703
10721
|
/** Optional subset of source locations to include; omitted = all. */
|
|
10704
10722
|
dataSources: array(string()).readonly().optional(),
|
|
10705
|
-
/**
|
|
10706
|
-
|
|
10723
|
+
/**
|
|
10724
|
+
* ms-epoch of the last tick that FIRED this schedule. Stamped before the
|
|
10725
|
+
* archive runs (it is the dedupe anchor), so it says "attempted", never
|
|
10726
|
+
* "succeeded" — a run refused by every destination stamps it too.
|
|
10727
|
+
*/
|
|
10728
|
+
lastAttemptAt: number().optional(),
|
|
10729
|
+
/** ms-epoch of the last run of this schedule that landed at ≥1 destination. */
|
|
10730
|
+
lastSuccessAt: number().optional(),
|
|
10731
|
+
/** Why the last fired run failed, verbatim. Absent when it succeeded. */
|
|
10732
|
+
lastError: string().optional(),
|
|
10707
10733
|
/** ms-epoch of next computed firing (read-only, filled on list). */
|
|
10708
10734
|
nextRunAt: number().optional()
|
|
10709
10735
|
});
|
|
@@ -10752,14 +10778,7 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
|
|
|
10752
10778
|
locationId: string(),
|
|
10753
10779
|
enabled: boolean(),
|
|
10754
10780
|
retentionCount: number().int().min(1).max(1e3),
|
|
10755
|
-
label: string().optional()
|
|
10756
|
-
/**
|
|
10757
|
-
* Per-destination cron expression. Empty string clears the
|
|
10758
|
-
* schedule (manual-only). Validated server-side via croner;
|
|
10759
|
-
* malformed expressions reject the upsert with an actionable
|
|
10760
|
-
* message.
|
|
10761
|
-
*/
|
|
10762
|
-
cron: string().optional()
|
|
10781
|
+
label: string().optional()
|
|
10763
10782
|
}), _void(), {
|
|
10764
10783
|
kind: "mutation",
|
|
10765
10784
|
auth: "admin"
|
package/dist/smb.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-DW6PfRB-.js");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_shared.__toESM(node_path);
|
|
@@ -225,6 +225,28 @@ function shareIdentity(input) {
|
|
|
225
225
|
function pathSegments(remotePath) {
|
|
226
226
|
return remotePath.split("/").filter((s) => s.length > 0);
|
|
227
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Turn a directory path into the MASK `smbclient dir` needs to enumerate it.
|
|
230
|
+
*
|
|
231
|
+
* `samba-client`'s `list(x)` runs `smbclient -c 'dir x'`, and smbclient's
|
|
232
|
+
* `dir` argument is a wildcard mask evaluated against the current directory —
|
|
233
|
+
* it does NOT descend into a directory named by it. A bare directory path
|
|
234
|
+
* therefore returns that directory's own entry, and an empty string returns
|
|
235
|
+
* nothing at all, because an empty mask matches nothing.
|
|
236
|
+
*
|
|
237
|
+
* Measured on the hub, 2026-09-07: `backups:smb` held a 387 MB archive and a
|
|
238
|
+
* `manifests.json`; `storage.list` answered `[]` and `storage.exists`
|
|
239
|
+
* answered `false`, so every SMB upload was refused by its own post-transfer
|
|
240
|
+
* "did it land?" check even though the bytes were intact on the share. The
|
|
241
|
+
* unit suite was green because its fake client treated the argument as a
|
|
242
|
+
* directory — the fake supplied the semantics production assumed and
|
|
243
|
+
* smbclient does not have.
|
|
244
|
+
*
|
|
245
|
+
* @param dir `''` for the connection's basePath, else a relative directory.
|
|
246
|
+
*/
|
|
247
|
+
function listMaskFor(dir) {
|
|
248
|
+
return dir === "" ? "*" : `${dir}/*`;
|
|
249
|
+
}
|
|
228
250
|
//#endregion
|
|
229
251
|
//#region src/providers/smb/smb-provider.ts
|
|
230
252
|
/**
|
|
@@ -484,7 +506,7 @@ var SmbStorageProvider = class {
|
|
|
484
506
|
const client = await this.clientForLocation(location);
|
|
485
507
|
const dir = safeSmbRelativePath(prefix ?? "");
|
|
486
508
|
try {
|
|
487
|
-
return (await client.list(dir)).filter((e) => e.name !== "." && e.name !== "..").map((e) => dir === "" ? e.name : `${dir}/${e.name}`);
|
|
509
|
+
return (await client.list(listMaskFor(dir))).filter((e) => e.name !== "." && e.name !== "..").map((e) => dir === "" ? e.name : `${dir}/${e.name}`);
|
|
488
510
|
} catch (err) {
|
|
489
511
|
if (isNotFound(err)) return [];
|
|
490
512
|
this.logger.warn("smb-storage: list failed", { meta: {
|
|
@@ -682,14 +704,19 @@ var SmbStorageProvider = class {
|
|
|
682
704
|
...cfg.basePath !== "" ? { directory: cfg.basePath } : {}
|
|
683
705
|
});
|
|
684
706
|
}
|
|
685
|
-
/**
|
|
707
|
+
/**
|
|
708
|
+
* One entry of a remote listing, or `null` when the path does not exist.
|
|
709
|
+
*
|
|
710
|
+
* Goes through {@link listMaskFor} — a bare directory path is NOT a
|
|
711
|
+
* listable argument for smbclient.
|
|
712
|
+
*/
|
|
686
713
|
async statRemote(location, relativePath) {
|
|
687
714
|
const client = await this.clientForLocation(location);
|
|
688
715
|
const target = safeSmbRelativePath(relativePath);
|
|
689
716
|
const dir = target.includes("/") ? target.slice(0, target.lastIndexOf("/")) : "";
|
|
690
717
|
const name = target.includes("/") ? target.slice(target.lastIndexOf("/") + 1) : target;
|
|
691
718
|
try {
|
|
692
|
-
return (await client.list(dir)).find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
719
|
+
return (await client.list(listMaskFor(dir))).find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
693
720
|
} catch (err) {
|
|
694
721
|
if (isNotFound(err)) return null;
|
|
695
722
|
throw err;
|
package/dist/smb.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-
|
|
1
|
+
import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-NUBj0w5N.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
|
@@ -218,6 +218,28 @@ function shareIdentity(input) {
|
|
|
218
218
|
function pathSegments(remotePath) {
|
|
219
219
|
return remotePath.split("/").filter((s) => s.length > 0);
|
|
220
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Turn a directory path into the MASK `smbclient dir` needs to enumerate it.
|
|
223
|
+
*
|
|
224
|
+
* `samba-client`'s `list(x)` runs `smbclient -c 'dir x'`, and smbclient's
|
|
225
|
+
* `dir` argument is a wildcard mask evaluated against the current directory —
|
|
226
|
+
* it does NOT descend into a directory named by it. A bare directory path
|
|
227
|
+
* therefore returns that directory's own entry, and an empty string returns
|
|
228
|
+
* nothing at all, because an empty mask matches nothing.
|
|
229
|
+
*
|
|
230
|
+
* Measured on the hub, 2026-09-07: `backups:smb` held a 387 MB archive and a
|
|
231
|
+
* `manifests.json`; `storage.list` answered `[]` and `storage.exists`
|
|
232
|
+
* answered `false`, so every SMB upload was refused by its own post-transfer
|
|
233
|
+
* "did it land?" check even though the bytes were intact on the share. The
|
|
234
|
+
* unit suite was green because its fake client treated the argument as a
|
|
235
|
+
* directory — the fake supplied the semantics production assumed and
|
|
236
|
+
* smbclient does not have.
|
|
237
|
+
*
|
|
238
|
+
* @param dir `''` for the connection's basePath, else a relative directory.
|
|
239
|
+
*/
|
|
240
|
+
function listMaskFor(dir) {
|
|
241
|
+
return dir === "" ? "*" : `${dir}/*`;
|
|
242
|
+
}
|
|
221
243
|
//#endregion
|
|
222
244
|
//#region src/providers/smb/smb-provider.ts
|
|
223
245
|
/**
|
|
@@ -477,7 +499,7 @@ var SmbStorageProvider = class {
|
|
|
477
499
|
const client = await this.clientForLocation(location);
|
|
478
500
|
const dir = safeSmbRelativePath(prefix ?? "");
|
|
479
501
|
try {
|
|
480
|
-
return (await client.list(dir)).filter((e) => e.name !== "." && e.name !== "..").map((e) => dir === "" ? e.name : `${dir}/${e.name}`);
|
|
502
|
+
return (await client.list(listMaskFor(dir))).filter((e) => e.name !== "." && e.name !== "..").map((e) => dir === "" ? e.name : `${dir}/${e.name}`);
|
|
481
503
|
} catch (err) {
|
|
482
504
|
if (isNotFound(err)) return [];
|
|
483
505
|
this.logger.warn("smb-storage: list failed", { meta: {
|
|
@@ -675,14 +697,19 @@ var SmbStorageProvider = class {
|
|
|
675
697
|
...cfg.basePath !== "" ? { directory: cfg.basePath } : {}
|
|
676
698
|
});
|
|
677
699
|
}
|
|
678
|
-
/**
|
|
700
|
+
/**
|
|
701
|
+
* One entry of a remote listing, or `null` when the path does not exist.
|
|
702
|
+
*
|
|
703
|
+
* Goes through {@link listMaskFor} — a bare directory path is NOT a
|
|
704
|
+
* listable argument for smbclient.
|
|
705
|
+
*/
|
|
679
706
|
async statRemote(location, relativePath) {
|
|
680
707
|
const client = await this.clientForLocation(location);
|
|
681
708
|
const target = safeSmbRelativePath(relativePath);
|
|
682
709
|
const dir = target.includes("/") ? target.slice(0, target.lastIndexOf("/")) : "";
|
|
683
710
|
const name = target.includes("/") ? target.slice(target.lastIndexOf("/") + 1) : target;
|
|
684
711
|
try {
|
|
685
|
-
return (await client.list(dir)).find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
712
|
+
return (await client.list(listMaskFor(dir))).find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
686
713
|
} catch (err) {
|
|
687
714
|
if (isNotFound(err)) return null;
|
|
688
715
|
throw err;
|
package/dist/webdav.addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_shared = require("./shared-
|
|
5
|
+
const require_shared = require("./shared-DW6PfRB-.js");
|
|
6
6
|
let node_stream = require("node:stream");
|
|
7
7
|
let webdav = require("webdav");
|
|
8
8
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/dist/webdav.addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-
|
|
1
|
+
import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { AuthType, createClient } from "webdav";
|
|
4
4
|
//#region src/providers/webdav/webdav-config-schema.ts
|
package/package.json
CHANGED