@homeflare/distilled-proxmox-backup 0.2.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.
- package/LICENSE +201 -0
- package/README.md +102 -0
- package/dist/credentials.d.ts +50 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +105 -0
- package/dist/credentials.js.map +1 -0
- package/dist/errors.d.ts +100 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +73 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +19 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +158 -0
- package/dist/protocol.js.map +1 -0
- package/dist/protocol.test.d.ts +2 -0
- package/dist/protocol.test.d.ts.map +1 -0
- package/dist/protocol.test.js +75 -0
- package/dist/protocol.test.js.map +1 -0
- package/dist/retry.d.ts +53 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +46 -0
- package/dist/retry.js.map +1 -0
- package/dist/services/access.d.ts +587 -0
- package/dist/services/access.d.ts.map +1 -0
- package/dist/services/access.js +787 -0
- package/dist/services/access.js.map +1 -0
- package/dist/services/admin.d.ts +1110 -0
- package/dist/services/admin.d.ts.map +1 -0
- package/dist/services/admin.js +1428 -0
- package/dist/services/admin.js.map +1 -0
- package/dist/services/backup.d.ts +224 -0
- package/dist/services/backup.d.ts.map +1 -0
- package/dist/services/backup.js +325 -0
- package/dist/services/backup.js.map +1 -0
- package/dist/services/config.d.ts +3662 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/config.js +4445 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/index.d.ts +14 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +15 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/nodes.d.ts +1441 -0
- package/dist/services/nodes.d.ts.map +1 -0
- package/dist/services/nodes.js +1829 -0
- package/dist/services/nodes.js.map +1 -0
- package/dist/services/ping.d.ts +15 -0
- package/dist/services/ping.d.ts.map +1 -0
- package/dist/services/ping.js +21 -0
- package/dist/services/ping.js.map +1 -0
- package/dist/services/pull.d.ts +54 -0
- package/dist/services/pull.d.ts.map +1 -0
- package/dist/services/pull.js +47 -0
- package/dist/services/pull.js.map +1 -0
- package/dist/services/push.d.ts +50 -0
- package/dist/services/push.d.ts.map +1 -0
- package/dist/services/push.js +45 -0
- package/dist/services/push.js.map +1 -0
- package/dist/services/reader.d.ts +68 -0
- package/dist/services/reader.d.ts.map +1 -0
- package/dist/services/reader.js +89 -0
- package/dist/services/reader.js.map +1 -0
- package/dist/services/root.d.ts +14 -0
- package/dist/services/root.d.ts.map +1 -0
- package/dist/services/root.js +19 -0
- package/dist/services/root.js.map +1 -0
- package/dist/services/status.d.ts +78 -0
- package/dist/services/status.d.ts.map +1 -0
- package/dist/services/status.js +97 -0
- package/dist/services/status.js.map +1 -0
- package/dist/services/tape.d.ts +711 -0
- package/dist/services/tape.d.ts.map +1 -0
- package/dist/services/tape.js +986 -0
- package/dist/services/tape.js.map +1 -0
- package/dist/services/version.d.ts +17 -0
- package/dist/services/version.d.ts.map +1 -0
- package/dist/services/version.js +25 -0
- package/dist/services/version.js.map +1 -0
- package/dist/task.d.ts +48 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +57 -0
- package/dist/task.js.map +1 -0
- package/dist/traits.d.ts +13 -0
- package/dist/traits.d.ts.map +1 -0
- package/dist/traits.js +15 -0
- package/dist/traits.js.map +1 -0
- package/package.json +81 -0
- package/src/credentials.ts +139 -0
- package/src/errors.ts +126 -0
- package/src/index.ts +36 -0
- package/src/protocol.test.ts +128 -0
- package/src/protocol.ts +196 -0
- package/src/retry.ts +79 -0
- package/src/services/access.ts +1787 -0
- package/src/services/admin.ts +3258 -0
- package/src/services/backup.ts +698 -0
- package/src/services/config.ts +10561 -0
- package/src/services/index.ts +14 -0
- package/src/services/nodes.ts +4313 -0
- package/src/services/ping.ts +43 -0
- package/src/services/pull.ts +118 -0
- package/src/services/push.ts +108 -0
- package/src/services/reader.ts +196 -0
- package/src/services/root.ts +39 -0
- package/src/services/status.ts +233 -0
- package/src/services/tape.ts +2257 -0
- package/src/services/version.ts +49 -0
- package/src/task.ts +84 -0
- package/src/traits.ts +46 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @distilled.cloud/proxmox-backup — Proxmox Backup Server API SDK for
|
|
3
|
+
* Effect.
|
|
4
|
+
*
|
|
5
|
+
* `./services` is generated by `scripts/generate.ts` from the Smithy
|
|
6
|
+
* models in `.generated-specs` (written by `scripts/convert.ts` from PBS's
|
|
7
|
+
* own `apidoc.js`, mirrored under `specs/`). Everything else in this
|
|
8
|
+
* folder is hand-written.
|
|
9
|
+
*
|
|
10
|
+
* One module per PBS top-level path segment — `access`, `admin`, `backup`,
|
|
11
|
+
* `config`, `nodes`, `ping`, `pull`, `push`, `reader`, `root`, `status`,
|
|
12
|
+
* `tape`, `version` — the same split the vendor's own api-viewer uses
|
|
13
|
+
* (measured on the pinned schema; see `scripts/convert.ts`'s header for
|
|
14
|
+
* per-bucket endpoint counts).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import * as ProxmoxBackup from "@distilled.cloud/proxmox-backup";
|
|
19
|
+
*
|
|
20
|
+
* const status = yield* ProxmoxBackup.Services.nodes.getNodeTaskStatus({
|
|
21
|
+
* node: "pbs1",
|
|
22
|
+
* upid: "UPID:pbs1:00001234:...",
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export * from "./credentials.ts";
|
|
27
|
+
export * from "./errors.ts";
|
|
28
|
+
export * as T from "./traits.ts";
|
|
29
|
+
export { ProxmoxBackupProtocol, type ProxmoxBackupOpError, type ProxmoxBackupOpContext, } from "./protocol.ts";
|
|
30
|
+
export * as Retry from "./retry.ts";
|
|
31
|
+
export * as Services from "./services/index.ts";
|
|
32
|
+
export { awaitTask, type TaskRef, type AwaitTaskOptions } from "./task.ts";
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @distilled.cloud/proxmox-backup — Proxmox Backup Server API SDK for
|
|
3
|
+
* Effect.
|
|
4
|
+
*
|
|
5
|
+
* `./services` is generated by `scripts/generate.ts` from the Smithy
|
|
6
|
+
* models in `.generated-specs` (written by `scripts/convert.ts` from PBS's
|
|
7
|
+
* own `apidoc.js`, mirrored under `specs/`). Everything else in this
|
|
8
|
+
* folder is hand-written.
|
|
9
|
+
*
|
|
10
|
+
* One module per PBS top-level path segment — `access`, `admin`, `backup`,
|
|
11
|
+
* `config`, `nodes`, `ping`, `pull`, `push`, `reader`, `root`, `status`,
|
|
12
|
+
* `tape`, `version` — the same split the vendor's own api-viewer uses
|
|
13
|
+
* (measured on the pinned schema; see `scripts/convert.ts`'s header for
|
|
14
|
+
* per-bucket endpoint counts).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import * as ProxmoxBackup from "@distilled.cloud/proxmox-backup";
|
|
19
|
+
*
|
|
20
|
+
* const status = yield* ProxmoxBackup.Services.nodes.getNodeTaskStatus({
|
|
21
|
+
* node: "pbs1",
|
|
22
|
+
* upid: "UPID:pbs1:00001234:...",
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export * from "./credentials.js";
|
|
27
|
+
export * from "./errors.js";
|
|
28
|
+
export * as T from "./traits.js";
|
|
29
|
+
export { ProxmoxBackupProtocol, } from "./protocol.js";
|
|
30
|
+
export * as Retry from "./retry.js";
|
|
31
|
+
export * as Services from "./services/index.js";
|
|
32
|
+
export { awaitTask } from "./task.js";
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,qBAAqB,GAGtB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAuC,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type * as Layer from "effect/Layer";
|
|
2
|
+
import type * as HttpClient from "effect/unstable/http/HttpClient";
|
|
3
|
+
import type * as HttpClientError from "effect/unstable/http/HttpClientError";
|
|
4
|
+
import type * as API from "@distilled.cloud/core/api";
|
|
5
|
+
import { type ConfigError } from "@distilled.cloud/core/errors";
|
|
6
|
+
import { Credentials } from "./credentials.ts";
|
|
7
|
+
import { type DefaultErrors } from "./errors.ts";
|
|
8
|
+
/**
|
|
9
|
+
* Error channel shared by every generated Proxmox Backup Server operation.
|
|
10
|
+
* Generated service files annotate operations with
|
|
11
|
+
* `API.OperationMethod<I, O, ProxmoxBackupOpError, ProxmoxBackupOpContext>`
|
|
12
|
+
* explicitly so the compiler never infers these back out of the schema
|
|
13
|
+
* generics.
|
|
14
|
+
*/
|
|
15
|
+
export type ProxmoxBackupOpError = DefaultErrors | ConfigError | HttpClientError.HttpClientError;
|
|
16
|
+
/** Context (requirements) shared by every generated Proxmox Backup Server operation. */
|
|
17
|
+
export type ProxmoxBackupOpContext = Credentials | HttpClient.HttpClient;
|
|
18
|
+
export declare const ProxmoxBackupProtocol: Layer.Layer<API.Protocol>;
|
|
19
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AA4EA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,KAAK,eAAe,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,KAAK,GAAG,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC5B,aAAa,GACb,WAAW,GACX,eAAe,CAAC,eAAe,CAAC;AAEpC,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC;AAwBzE,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CA6DxD,CAAC"}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProxmoxBackupProtocol — the shared bearer-REST protocol instantiated for
|
|
3
|
+
* Proxmox Backup Server. Hand-written; `@distilled.cloud/core` is never
|
|
4
|
+
* changed for a provider's own quirks — they all live here.
|
|
5
|
+
*
|
|
6
|
+
* Ported from `packages/proxmox/src/protocol.ts` in this same distilled
|
|
7
|
+
* clone. Three of PVE's "THREE 200-TRAPS" carry forward; the fourth
|
|
8
|
+
* (cluster-forwarding 595) does not exist for PBS — see `src/errors.ts`'s
|
|
9
|
+
* header. Each trap below cites what was actually checked against the
|
|
10
|
+
* pinned schema (`~/.cache/homeflare/schemas/proxmox/
|
|
11
|
+
* pbs_4.2.6-1_apidoc.js`), versus what is carried by same-vendor
|
|
12
|
+
* architecture and NOT independently measured (this build makes no live
|
|
13
|
+
* PBS calls).
|
|
14
|
+
*
|
|
15
|
+
* ## The envelope
|
|
16
|
+
*
|
|
17
|
+
* Every PBS response is wrapped `{"data": …}`, the same as PVE.
|
|
18
|
+
* ⚠️ NOT independently measured live (no PBS credential exists to call
|
|
19
|
+
* with). Asserted, not just assumed: `taslabs-net/homeflare-kit`'s
|
|
20
|
+
* `packages/alchemy/src/proxmox/credentials.ts` documents PVE and PBS
|
|
21
|
+
* sharing ONE http client specifically BECAUSE "Proxmox Backup Server
|
|
22
|
+
* speaks the same `/api2/json` paths, wraps every answer in the same
|
|
23
|
+
* `{"data": …}` envelope" — also written before that repo had a live PBS
|
|
24
|
+
* credential, so this is the same vendor-architecture inference stated
|
|
25
|
+
* independently in two places, not two confirmations of one live check.
|
|
26
|
+
* `transformResponse` below unwraps it before `core/protocol-rest`'s
|
|
27
|
+
* schema-driven decode ever sees a payload, exactly as PVE's does.
|
|
28
|
+
*
|
|
29
|
+
* ## Authentication
|
|
30
|
+
*
|
|
31
|
+
* The API-token scheme: `Authorization: PBSAPIToken=<user>@<realm>!
|
|
32
|
+
* <tokenid>:<secret>` — MEASURED DIFFERENT FROM PVE: a colon separator,
|
|
33
|
+
* not `=`, and a `PBSAPIToken` prefix, not `PVEAPIToken`. See
|
|
34
|
+
* `src/credentials.ts`'s header for the two independent citations (kit
|
|
35
|
+
* `credentials.ts` and `pbs-prune-job.ts`) and their shared caveat
|
|
36
|
+
* (reasoned from PBS's documented scheme, not a live call either).
|
|
37
|
+
*
|
|
38
|
+
* ## THE TRAPS CARRIED FROM PVE (measured against the pinned schema)
|
|
39
|
+
*
|
|
40
|
+
* (a) **Async POST/PUT/DELETE answer 200 with a UPID and can fail later.**
|
|
41
|
+
* CONFIRMED IN SCHEMA: the pinned file's `pattern` for UPID-shaped
|
|
42
|
+
* strings appears 44 times, and `GET /nodes/{node}/tasks/{upid}/status`
|
|
43
|
+
* exists (measured: `grep -n 'tasks/{upid}/status'` finds it at line
|
|
44
|
+
* 25814) — the identical path shape PVE's own `awaitTask` polls.
|
|
45
|
+
* Handled with real code: `src/task.ts`'s `awaitTask`, unchanged in
|
|
46
|
+
* its `"OK"` exact-equality logic from PVE's (see that file's header
|
|
47
|
+
* for why `"OK (warnings)"` must not match a prefix/substring check).
|
|
48
|
+
*
|
|
49
|
+
* (b) **Some PUTs answer 200 `{"data":null}` even when nothing changed.**
|
|
50
|
+
* CONFIRMED IN SCHEMA: e.g. `PUT /access/acl` and `PUT /access/
|
|
51
|
+
* password` both declare `"returns": {"type": "null"}` (measured,
|
|
52
|
+
* among 53 total PUT endpoints in the pinned schema) — the same
|
|
53
|
+
* declared-null-return signature PVE's update endpoints carry. THIS IS
|
|
54
|
+
* NOT SOMETHING A PROTOCOL LAYER CAN DETECT OR FIX; documented here so
|
|
55
|
+
* it travels with the protocol.
|
|
56
|
+
*
|
|
57
|
+
* (c) **Permission-filtered lists return 200 + `[]` instead of 403.**
|
|
58
|
+
* CONFIRMED IN SCHEMA: `GET /access/acl`'s own `permissions.description`
|
|
59
|
+
* reads "Returns all ACLs if user has Sys.Audit on '/access/acl', or
|
|
60
|
+
* just the ACLs containing the user's API tokens" (measured, line 32
|
|
61
|
+
* of the pinned file) — the identical conditional-visibility-by-token
|
|
62
|
+
* phrasing the PVE package's header cites for this trap, not a guess
|
|
63
|
+
* by analogy. Also undetectable here for the same reason as (b).
|
|
64
|
+
*
|
|
65
|
+
* ## NOT carried: cluster-forwarding 595
|
|
66
|
+
*
|
|
67
|
+
* See `src/errors.ts`'s header — the pinned schema has zero `proxyto`
|
|
68
|
+
* occurrences. PBS is not a cluster product.
|
|
69
|
+
*
|
|
70
|
+
* ## Self-signed TLS
|
|
71
|
+
*
|
|
72
|
+
* Same as PVE: explicitly not handled here or anywhere in this package —
|
|
73
|
+
* the `HttpClient.HttpClient` layer the caller provides owns that
|
|
74
|
+
* decision.
|
|
75
|
+
*/
|
|
76
|
+
import * as Effect from "effect/Effect";
|
|
77
|
+
import * as Redacted from "effect/Redacted";
|
|
78
|
+
import { BadRequest, HTTP_STATUS_MAP, } from "@distilled.cloud/core/errors";
|
|
79
|
+
import { makeRestProtocol, } from "@distilled.cloud/core/protocol-rest";
|
|
80
|
+
import { Credentials } from "./credentials.js";
|
|
81
|
+
import { ParameterVerificationFailed, UnknownProxmoxBackupError, } from "./errors.js";
|
|
82
|
+
/**
|
|
83
|
+
* PBS's failure envelope is `{"data": null, "message": "...", "errors"?:
|
|
84
|
+
* {…}}` — see PVE's identical `errorEnvelope` for why `message` alone is
|
|
85
|
+
* read here (the `errors` sub-object is read straight from the body in
|
|
86
|
+
* `unknownError` below, never here).
|
|
87
|
+
*/
|
|
88
|
+
const errorEnvelope = (body) => {
|
|
89
|
+
if (body === null || typeof body !== "object")
|
|
90
|
+
return undefined;
|
|
91
|
+
const b = body;
|
|
92
|
+
return { message: typeof b.message === "string" ? b.message : undefined };
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* `HTTP_STATUS_MAP` minus 400 — same reasoning as PVE's copy: PBS's 400 is
|
|
96
|
+
* specifically the parameter-verification failure, and the generic
|
|
97
|
+
* `BadRequest` would throw away the per-field `errors` object.
|
|
98
|
+
*/
|
|
99
|
+
const PROXMOX_BACKUP_STATUS_MAP = {
|
|
100
|
+
...HTTP_STATUS_MAP,
|
|
101
|
+
};
|
|
102
|
+
delete PROXMOX_BACKUP_STATUS_MAP[400];
|
|
103
|
+
export const ProxmoxBackupProtocol = makeRestProtocol({
|
|
104
|
+
credentials: Effect.gen(function* () {
|
|
105
|
+
const resolve = yield* Credentials;
|
|
106
|
+
return yield* resolve;
|
|
107
|
+
}),
|
|
108
|
+
baseUrl: (creds) => creds.apiBaseUrl,
|
|
109
|
+
headers: (creds) => ({
|
|
110
|
+
// ⛔ COLON, NOT `=` — see the module header's Authentication section.
|
|
111
|
+
Authorization: `PBSAPIToken=${creds.tokenId}:${Redacted.value(creds.secret)}`,
|
|
112
|
+
Accept: "application/json",
|
|
113
|
+
}),
|
|
114
|
+
errorEnvelope,
|
|
115
|
+
statusMap: PROXMOX_BACKUP_STATUS_MAP,
|
|
116
|
+
// Unwrap PBS's `{"data": …}` envelope BEFORE the schema-driven decode —
|
|
117
|
+
// see the module header. `data` is `null`/absent for a Unit-output
|
|
118
|
+
// operation; `?? {}` is core's own convention for "no body".
|
|
119
|
+
transformResponse: (body) => {
|
|
120
|
+
if (body !== null &&
|
|
121
|
+
typeof body === "object" &&
|
|
122
|
+
"data" in body) {
|
|
123
|
+
return body.data ?? {};
|
|
124
|
+
}
|
|
125
|
+
return body;
|
|
126
|
+
},
|
|
127
|
+
// Reached for a 400 (see PROXMOX_BACKUP_STATUS_MAP above) or a status
|
|
128
|
+
// with no core mapping at all. `body` is the FULL parsed failure
|
|
129
|
+
// envelope, so this is where PBS's per-field `errors` object is read.
|
|
130
|
+
//
|
|
131
|
+
// ⛔ A BARE 400 WITHOUT THE `errors` OBJECT MUST NOT FALL INTO
|
|
132
|
+
// `UnknownProxmoxBackupError` — same retry-amplification hazard
|
|
133
|
+
// PVE's identical comment explains (`ServerError` is retried
|
|
134
|
+
// automatically; a malformed request is permanent). `BadRequest`
|
|
135
|
+
// (`Category.withBadRequestError`, not retryable) is the honest
|
|
136
|
+
// answer for "PBS said 400 and gave no further structure".
|
|
137
|
+
unknownError: ({ status, message, body }) => {
|
|
138
|
+
const b = body !== null && typeof body === "object"
|
|
139
|
+
? body
|
|
140
|
+
: undefined;
|
|
141
|
+
const fieldErrors = b?.errors;
|
|
142
|
+
if (status === 400) {
|
|
143
|
+
if (fieldErrors !== null &&
|
|
144
|
+
typeof fieldErrors === "object" &&
|
|
145
|
+
!Array.isArray(fieldErrors)) {
|
|
146
|
+
const errors = {};
|
|
147
|
+
for (const [k, v] of Object.entries(fieldErrors)) {
|
|
148
|
+
if (typeof v === "string")
|
|
149
|
+
errors[k] = v;
|
|
150
|
+
}
|
|
151
|
+
return new ParameterVerificationFailed({ message, errors });
|
|
152
|
+
}
|
|
153
|
+
return new BadRequest({ message });
|
|
154
|
+
}
|
|
155
|
+
return new UnknownProxmoxBackupError({ status, message, body });
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../src/protocol.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ported from `packages/proxmox/src/protocol.test.ts` in this same
|
|
3
|
+
* distilled clone — same bug class, same shape: a bare 400 (no `errors`
|
|
4
|
+
* object) must decode to the non-retryable `BadRequest`, never the
|
|
5
|
+
* `Category.withServerError`-tagged `UnknownProxmoxBackupError`. See
|
|
6
|
+
* `protocol.ts`'s `unknownError` and `errors.ts`'s module header.
|
|
7
|
+
*
|
|
8
|
+
* Adds one test PVE's file does not need: the auth header itself, because
|
|
9
|
+
* that is the one thing measurably different between the two packages
|
|
10
|
+
* (`PBSAPIToken=<id>:<secret>`, colon separator — see `credentials.ts`'s
|
|
11
|
+
* header) and a wrong separator fails SILENTLY AS A 401 with no other
|
|
12
|
+
* symptom, per that same header's citation of the kit's own warning. All
|
|
13
|
+
* of this runs against a fake `HttpClient` — no live PBS host is
|
|
14
|
+
* contacted anywhere in this file.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, expect, test } from "bun:test";
|
|
17
|
+
import * as Effect from "effect/Effect";
|
|
18
|
+
import * as Layer from "effect/Layer";
|
|
19
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
20
|
+
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
21
|
+
import { credentials } from "./credentials.js";
|
|
22
|
+
import { BadRequest, ParameterVerificationFailed, UnknownProxmoxBackupError, } from "./errors.js";
|
|
23
|
+
import * as Retry from "./retry.js";
|
|
24
|
+
import { getVersion } from "./services/version.js";
|
|
25
|
+
const testCredentials = credentials({
|
|
26
|
+
tokenId: "backup@pbs!test",
|
|
27
|
+
secret: "test-secret",
|
|
28
|
+
baseUrl: "https://pbs.test:8007",
|
|
29
|
+
});
|
|
30
|
+
const fakePbs = (status, body) => Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.sync(() => HttpClientResponse.fromWeb(request, new Response(JSON.stringify(body), { status })))));
|
|
31
|
+
const call = (status, body) => Effect.runPromise(getVersion({}).pipe(Retry.none, Effect.provide(Layer.mergeAll(fakePbs(status, body), testCredentials)), Effect.flip));
|
|
32
|
+
describe("protocol.ts error decoding", () => {
|
|
33
|
+
test("a bare 400 (no `errors` object) is BadRequest, never UnknownProxmoxBackupError", async () => {
|
|
34
|
+
const error = await call(400, { data: null, message: "invalid parameter" });
|
|
35
|
+
expect(error).toBeInstanceOf(BadRequest);
|
|
36
|
+
expect(error).not.toBeInstanceOf(UnknownProxmoxBackupError);
|
|
37
|
+
expect(error).toMatchObject({ message: "invalid parameter" });
|
|
38
|
+
});
|
|
39
|
+
test("a 400 with an `errors` object is ParameterVerificationFailed, carrying the per-field messages", async () => {
|
|
40
|
+
const error = await call(400, {
|
|
41
|
+
data: null,
|
|
42
|
+
message: "parameter verification failed",
|
|
43
|
+
errors: { comment: "value may only be 128 characters long" },
|
|
44
|
+
});
|
|
45
|
+
expect(error).toBeInstanceOf(ParameterVerificationFailed);
|
|
46
|
+
expect(error).toMatchObject({
|
|
47
|
+
message: "parameter verification failed",
|
|
48
|
+
errors: { comment: "value may only be 128 characters long" },
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
test("a genuinely unmapped, non-5xx status still falls back to UnknownProxmoxBackupError", async () => {
|
|
52
|
+
const error = await call(418, { data: null, message: "weird" });
|
|
53
|
+
expect(error).toBeInstanceOf(UnknownProxmoxBackupError);
|
|
54
|
+
});
|
|
55
|
+
test('the {"data": ...} envelope is unwrapped before decode', async () => {
|
|
56
|
+
const result = await Effect.runPromise(getVersion({}).pipe(Effect.provide(Layer.mergeAll(fakePbs(200, {
|
|
57
|
+
data: { version: "4.2.6", release: "4.2", repoid: "abc123" },
|
|
58
|
+
}), testCredentials))));
|
|
59
|
+
expect(result).toMatchObject({ version: "4.2.6", release: "4.2" });
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("credentials.ts auth header", () => {
|
|
63
|
+
test("Authorization is PBSAPIToken=<id>:<secret> — colon, never `=` like PVE's PVEAPIToken", async () => {
|
|
64
|
+
let seenAuth;
|
|
65
|
+
const capturing = Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.sync(() => {
|
|
66
|
+
seenAuth = request.headers["authorization"];
|
|
67
|
+
return HttpClientResponse.fromWeb(request, new Response(JSON.stringify({
|
|
68
|
+
data: { version: "4.2.6", release: "4.2", repoid: "abc" },
|
|
69
|
+
}), { status: 200 }));
|
|
70
|
+
})));
|
|
71
|
+
await Effect.runPromise(getVersion({}).pipe(Effect.provide(Layer.mergeAll(capturing, testCredentials))));
|
|
72
|
+
expect(seenAuth).toBe("PBSAPIToken=backup@pbs!test:test-secret");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=protocol.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../src/protocol.test.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxmox Backup Server retry surface — a veneer over
|
|
3
|
+
* `@distilled.cloud/core/retry`. Copied unchanged from
|
|
4
|
+
* `packages/proxmox/src/retry.ts` (no vendor-specific logic; only the
|
|
5
|
+
* Context.Service tag name below is package-local).
|
|
6
|
+
*
|
|
7
|
+
* The `Retry` service tag is threaded into every generated operation via
|
|
8
|
+
* `API.make({ retry: Retry })`, so a caller-installed policy applies to all
|
|
9
|
+
* Proxmox Backup Server calls below it and core's `makeDefault` is the
|
|
10
|
+
* fallback when none is provided.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import * as ProxmoxBackup from "@distilled.cloud/proxmox-backup";
|
|
15
|
+
*
|
|
16
|
+
* myEffect.pipe(ProxmoxBackup.Retry.transient);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import * as Context from "effect/Context";
|
|
20
|
+
import * as Effect from "effect/Effect";
|
|
21
|
+
import * as Retries from "@distilled.cloud/core/retry";
|
|
22
|
+
export type Options = Retries.Options;
|
|
23
|
+
export type Factory = Retries.Factory;
|
|
24
|
+
export type Policy = Retries.Policy;
|
|
25
|
+
declare const Retry_base: Context.ServiceClass<Retry, "ProxmoxBackupRetry", Retries.Policy>;
|
|
26
|
+
/** Context tag for configuring retry behavior of Proxmox Backup Server API calls. */
|
|
27
|
+
export declare class Retry extends Retry_base {
|
|
28
|
+
}
|
|
29
|
+
/** Provides a custom retry policy to every Proxmox Backup Server API call below it. */
|
|
30
|
+
export declare const policy: {
|
|
31
|
+
(options: Options): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
|
|
32
|
+
(factory: Factory): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
|
|
33
|
+
};
|
|
34
|
+
/** Disables all automatic retries. */
|
|
35
|
+
export declare const none: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
|
|
36
|
+
/**
|
|
37
|
+
* The default retry policy (core's): transient/throttling/retryable errors,
|
|
38
|
+
* capped exponential backoff with jitter, server `retryAfter` hints honored
|
|
39
|
+
* with precedence.
|
|
40
|
+
*/
|
|
41
|
+
export declare const makeDefault: Factory;
|
|
42
|
+
export declare const jittered: <Error, Env>(self: import("effect/Schedule").Schedule<unknown, unknown, Error, Env>) => import("effect/Schedule").Schedule<unknown, unknown, Error, Env>;
|
|
43
|
+
export declare const capped: (max: import("effect/Duration").Duration) => <Error, Env>(self: import("effect/Schedule").Schedule<unknown, unknown, Error, Env>) => import("effect/Schedule").Schedule<unknown, unknown, Error, Env>;
|
|
44
|
+
/** Retry options that retry all throttling errors indefinitely. */
|
|
45
|
+
export declare const throttlingOptions: Options;
|
|
46
|
+
/** Retries all throttling errors indefinitely (honoring server hints). */
|
|
47
|
+
export declare const throttling: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
|
|
48
|
+
/** Retry options that retry all transient errors indefinitely. */
|
|
49
|
+
export declare const transientOptions: Options;
|
|
50
|
+
/** Retries all transient errors indefinitely (honoring server hints). */
|
|
51
|
+
export declare const transient: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;AACtC,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;AACtC,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;;AAEpC,qFAAqF;AACrF,qBAAa,KAAM,SAAQ,UAE1B;CAAG;AAEJ,uFAAuF;AACvF,eAAO,MAAM,MAAM,EAAE;IACnB,CACE,OAAO,EAAE,OAAO,GACf,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,CACE,OAAO,EAAE,OAAO,GACf,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;CAEU,CAAC;AAEzD,sCAAsC;AACtC,eAAO,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAEzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,OAA6B,CAAC;AAExD,eAAO,MAAM,QAAQ,0JAAmB,CAAC;AACzC,eAAO,MAAM,MAAM,uMAAiB,CAAC;AAErC,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,EAAE,OAAmC,CAAC;AAEpE,0EAA0E;AAC1E,eAAO,MAAM,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAqC,CAAC;AAEhF,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,EAAE,OAAkC,CAAC;AAElE,yEAAyE;AACzE,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAoC,CAAC"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxmox Backup Server retry surface — a veneer over
|
|
3
|
+
* `@distilled.cloud/core/retry`. Copied unchanged from
|
|
4
|
+
* `packages/proxmox/src/retry.ts` (no vendor-specific logic; only the
|
|
5
|
+
* Context.Service tag name below is package-local).
|
|
6
|
+
*
|
|
7
|
+
* The `Retry` service tag is threaded into every generated operation via
|
|
8
|
+
* `API.make({ retry: Retry })`, so a caller-installed policy applies to all
|
|
9
|
+
* Proxmox Backup Server calls below it and core's `makeDefault` is the
|
|
10
|
+
* fallback when none is provided.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import * as ProxmoxBackup from "@distilled.cloud/proxmox-backup";
|
|
15
|
+
*
|
|
16
|
+
* myEffect.pipe(ProxmoxBackup.Retry.transient);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import * as Context from "effect/Context";
|
|
20
|
+
import * as Effect from "effect/Effect";
|
|
21
|
+
import * as Layer from "effect/Layer";
|
|
22
|
+
import * as Retries from "@distilled.cloud/core/retry";
|
|
23
|
+
/** Context tag for configuring retry behavior of Proxmox Backup Server API calls. */
|
|
24
|
+
export class Retry extends Context.Service()("ProxmoxBackupRetry") {
|
|
25
|
+
}
|
|
26
|
+
/** Provides a custom retry policy to every Proxmox Backup Server API call below it. */
|
|
27
|
+
export const policy = (optionsOrFactory) => Effect.provide(Layer.succeed(Retry, optionsOrFactory));
|
|
28
|
+
/** Disables all automatic retries. */
|
|
29
|
+
export const none = Effect.provide(Layer.succeed(Retry, { while: () => false }));
|
|
30
|
+
/**
|
|
31
|
+
* The default retry policy (core's): transient/throttling/retryable errors,
|
|
32
|
+
* capped exponential backoff with jitter, server `retryAfter` hints honored
|
|
33
|
+
* with precedence.
|
|
34
|
+
*/
|
|
35
|
+
export const makeDefault = Retries.makeDefault;
|
|
36
|
+
export const jittered = Retries.jittered;
|
|
37
|
+
export const capped = Retries.capped;
|
|
38
|
+
/** Retry options that retry all throttling errors indefinitely. */
|
|
39
|
+
export const throttlingOptions = Retries.throttlingOptions;
|
|
40
|
+
/** Retries all throttling errors indefinitely (honoring server hints). */
|
|
41
|
+
export const throttling = policy(Retries.throttlingFactory);
|
|
42
|
+
/** Retry options that retry all transient errors indefinitely. */
|
|
43
|
+
export const transientOptions = Retries.transientOptions;
|
|
44
|
+
/** Retries all transient errors indefinitely (honoring server hints). */
|
|
45
|
+
export const transient = policy(Retries.transientFactory);
|
|
46
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAMvD,qFAAqF;AACrF,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,OAAO,EAAiB,CACzD,oBAAoB,CACrB;CAAG;AAEJ,uFAAuF;AACvF,MAAM,CAAC,MAAM,MAAM,GAWf,CAAC,gBAAmC,EAAE,EAAE,CAC1C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEzD,sCAAsC;AACtC,MAAM,CAAC,MAAM,IAAI,GAE6B,MAAM,CAAC,OAAO,CAC1D,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,CAC7C,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAY,OAAO,CAAC,WAAW,CAAC;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;AACzC,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AAErC,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAY,OAAO,CAAC,iBAAiB,CAAC;AAEpE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAEuB,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhF,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAY,OAAO,CAAC,gBAAgB,CAAC;AAElE,yEAAyE;AACzE,MAAM,CAAC,MAAM,SAAS,GAEwB,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC"}
|