@homeflare/distilled-proxmox-backup 0.3.0 → 0.3.2
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/README.md +19 -17
- package/dist/errors.d.ts +6 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/missing-resource.test.d.ts +2 -0
- package/dist/missing-resource.test.d.ts.map +1 -0
- package/dist/missing-resource.test.js +62 -0
- package/dist/missing-resource.test.js.map +1 -0
- package/dist/protocol-boundaries.test.d.ts +2 -0
- package/dist/protocol-boundaries.test.d.ts.map +1 -0
- package/dist/protocol-boundaries.test.js +50 -0
- package/dist/protocol-boundaries.test.js.map +1 -0
- package/dist/protocol-codecs.d.ts +23 -0
- package/dist/protocol-codecs.d.ts.map +1 -0
- package/dist/protocol-codecs.js +49 -0
- package/dist/protocol-codecs.js.map +1 -0
- package/dist/protocol-codecs.test.d.ts +2 -0
- package/dist/protocol-codecs.test.d.ts.map +1 -0
- package/dist/protocol-codecs.test.js +58 -0
- package/dist/protocol-codecs.test.js.map +1 -0
- package/dist/protocol-raw-root.test.d.ts +2 -0
- package/dist/protocol-raw-root.test.d.ts.map +1 -0
- package/dist/protocol-raw-root.test.js +48 -0
- package/dist/protocol-raw-root.test.js.map +1 -0
- package/dist/protocol.d.ts +3 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +7 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocol.test.js +2 -2
- package/dist/protocol.test.js.map +1 -1
- package/dist/services/config.d.ts +44 -4
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +29 -4
- package/dist/services/config.js.map +1 -1
- package/package.json +3 -3
- package/src/errors.ts +7 -11
- package/src/missing-resource.test.ts +98 -0
- package/src/protocol-boundaries.test.ts +60 -0
- package/src/protocol-codecs.test.ts +112 -0
- package/src/protocol-codecs.ts +75 -0
- package/src/protocol-raw-root.test.ts +84 -0
- package/src/protocol.test.ts +2 -2
- package/src/protocol.ts +67 -60
- package/src/services/config.ts +45 -8
package/README.md
CHANGED
|
@@ -18,13 +18,10 @@ here.
|
|
|
18
18
|
|
|
19
19
|
⚠️ **License.** Apache-2.0, not the kit's usual MIT — see `LICENSE`.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
package's measured behavior — never from a live PBS response. Re-verify the
|
|
26
|
-
auth header and envelope shape against the first real PBS token this estate
|
|
27
|
-
gets, before trusting this package in anything that writes.
|
|
21
|
+
Read-only verification on 2026-09-24 exercised the regenerated SDK against PBS
|
|
22
|
+
4.2.3: version, datastore, matcher and sendmail reads succeeded through its
|
|
23
|
+
Credentials layer. No infrastructure write was used to test the transport.
|
|
24
|
+
Protocol fixtures cover writes, repeated array fields and malformed responses.
|
|
28
25
|
|
|
29
26
|
## What's in it
|
|
30
27
|
|
|
@@ -33,6 +30,9 @@ segment — `access`, `admin`, `backup`, `config`, `nodes`, `ping`, `pull`,
|
|
|
33
30
|
`push`, `reader`, `root`, `status`, `tape`, `version` — 0 skipped. Typed
|
|
34
31
|
errors: the shared HTTP status classes and PBS's global
|
|
35
32
|
`ParameterVerificationFailed`/non-retryable `BadRequest` fallback for a 400.
|
|
33
|
+
Missing datastore, prune, sync and verification GETs carry precise typed tags:
|
|
34
|
+
PBS returns these as plain-text 400s, measured read-only on 2026-09-24. Other
|
|
35
|
+
400s and sibling write errors keep their original failure semantics.
|
|
36
36
|
|
|
37
37
|
**No `ClusterNodeUnreachable`.** PVE's sibling package adds a typed 595 for
|
|
38
38
|
cluster-forwarded requests; PBS is not a cluster product and the pinned
|
|
@@ -66,7 +66,7 @@ const program = ProxmoxBackup.Services.version.getVersion({}).pipe(
|
|
|
66
66
|
PVE's `PVEAPIToken` uses.** `credentials()` builds this correctly; the risk
|
|
67
67
|
is a caller who copy-pastes PVE integration code and expects the same
|
|
68
68
|
separator. See `src/credentials.ts`'s header for the two independent,
|
|
69
|
-
|
|
69
|
+
original documentation citations; the read-only SDK probe above now confirms it.
|
|
70
70
|
|
|
71
71
|
Kit code never imports `@homeflare/distilled-proxmox-backup` directly —
|
|
72
72
|
always `@distilled.cloud/proxmox-backup`, aliased in the consuming
|
|
@@ -79,19 +79,21 @@ From the distilled clone's `homeflare/proxmox-backup` worktree:
|
|
|
79
79
|
```sh
|
|
80
80
|
DISTILLED_SPECS_LOCAL=1 pnpm --filter @distilled.cloud/proxmox-backup run convert
|
|
81
81
|
DISTILLED_SPECS_LOCAL=1 pnpm --filter @distilled.cloud/proxmox-backup run generate
|
|
82
|
-
pnpm
|
|
82
|
+
pnpm typecheck:ci
|
|
83
83
|
pnpm format
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
`pnpm specs:check`
|
|
87
|
-
|
|
88
|
-
PBS has no public docs mirror the way PVE does, and there is no PBS host
|
|
89
|
-
in the estate yet to fetch a live schema from. Regenerating today means
|
|
90
|
-
re-copying the same pinned file; a real refresh needs one of those two
|
|
91
|
-
gaps closed first.
|
|
86
|
+
`pnpm specs:check` now passes the 81-mirror coherence gate. The generation above
|
|
87
|
+
uses the pinned local schema; refreshing that schema is a separate operation.
|
|
92
88
|
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
Form arrays use repeated keys rather than the generic REST encoder's indexed
|
|
90
|
+
keys. Successful responses are validated against the generated output schema;
|
|
91
|
+
Unit `data:null` responses remain valid, and extra response fields are preserved.
|
|
92
|
+
Malformed payloads raise `ProxmoxBackupParseError` without copying response data
|
|
93
|
+
into diagnostics, because notification fields can contain secrets.
|
|
94
|
+
|
|
95
|
+
Then copy `src/` here verbatim and add a changeset. The normal release flow
|
|
96
|
+
versions and publishes the package.
|
|
95
97
|
|
|
96
98
|
## License
|
|
97
99
|
|
package/dist/errors.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* `awaitTask` here therefore has a narrower error union than PVE's.
|
|
20
20
|
*/
|
|
21
21
|
export { BadGateway, BadRequest, Conflict, ConfigError, Forbidden, GatewayTimeout, InternalServerError, Locked, NotFound, ServiceUnavailable, TooManyRequests, Unauthorized, UnprocessableEntity, HTTP_STATUS_MAP, DEFAULT_ERRORS, API_ERRORS, } from "@distilled.cloud/core/errors";
|
|
22
|
-
import type {
|
|
22
|
+
import type { API_ERRORS } from "@distilled.cloud/core/errors";
|
|
23
23
|
import * as Schema from "effect/Schema";
|
|
24
24
|
declare const ParameterVerificationFailed_base: Schema.Class<ParameterVerificationFailed, Schema.TaggedStruct<"ParameterVerificationFailed", {
|
|
25
25
|
readonly message: Schema.String;
|
|
@@ -92,9 +92,10 @@ export declare class ProxmoxBackupTaskFailed extends ProxmoxBackupTaskFailed_bas
|
|
|
92
92
|
*/
|
|
93
93
|
export type ClientErrors = UnknownProxmoxBackupError | ProxmoxBackupParseError;
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
95
|
+
* Every status class the protocol's HTTP_STATUS_MAP may return, plus PBS failures.
|
|
96
|
+
* Core's DefaultErrors is only its infrastructure subset; using that here hid mapped
|
|
97
|
+
* NotFound/Forbidden/Conflict from the typed operation union, so a legitimate catchTag
|
|
98
|
+
* could not compile even though that exact error was returned at runtime.
|
|
98
99
|
*/
|
|
99
|
-
export type DefaultErrors =
|
|
100
|
+
export type DefaultErrors = InstanceType<(typeof API_ERRORS)[number]> | ParameterVerificationFailed | ClientErrors;
|
|
100
101
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;;;;;;AAGxC;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,2BAA4B,SAAQ,gCAMb;CAAG;;;;;;;;;;AAEvC;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,8BAOf;CAAG;;;;;;;;;AAEnC,kCAAkC;AAClC,qBAAa,uBAAwB,SAAQ,4BAMd;CAAG;;;;;;AAElC;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,4BAO5C;CAAG;AAEJ;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,yBAAyB,GAAG,uBAAuB,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,YAAY,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GACzC,2BAA2B,GAC3B,YAAY,CAAC"}
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,2BAA4B,SAAQ,MAAM,CAAC,WAAW,EAA+B,CAChG,6BAA6B,EAC7B;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACpD,CACF,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;CAAG;AAEvC;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,MAAM,CAAC,WAAW,EAA6B,CAC5F,2BAA2B,EAC3B;IACE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,OAAO;CACrB,CACF,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;CAAG;AAEnC,kCAAkC;AAClC,MAAM,OAAO,uBAAwB,SAAQ,MAAM,CAAC,WAAW,EAA2B,CACxF,yBAAyB,EACzB;IACE,IAAI,EAAE,MAAM,CAAC,OAAO;IACpB,KAAK,EAAE,MAAM,CAAC,OAAO;CACtB,CACF,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;CAAG;AAElC;;;GAGG;AACH,MAAM,OAAO,uBAAwB,SAAQ,MAAM,CAAC,WAAW,EAA2B,CACxF,yBAAyB,EACzB;IACE,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CACF;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-resource.test.d.ts","sourceRoot":"","sources":["../src/missing-resource.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Read-only PBS wire measurements, 2026-09-24: missing config items use plain-text 400. */
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
6
|
+
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
7
|
+
import { credentials } from "./credentials.js";
|
|
8
|
+
import * as Retry from "./retry.js";
|
|
9
|
+
import * as config from "./services/config.js";
|
|
10
|
+
const testCredentials = credentials({
|
|
11
|
+
tokenId: "backup@pbs!test",
|
|
12
|
+
secret: "test-secret",
|
|
13
|
+
baseUrl: "https://pbs.test:8007",
|
|
14
|
+
});
|
|
15
|
+
const failure = (op, status, body) => Effect.runPromise(op.pipe(Retry.none, Effect.provide(Layer.mergeAll(testCredentials, Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, new Response(body, { status }))))))), Effect.flip));
|
|
16
|
+
const absent = "hf-absent-sdk-0924";
|
|
17
|
+
const cases = [
|
|
18
|
+
{
|
|
19
|
+
op: config.getConfigDatastore({ name: absent }),
|
|
20
|
+
kind: "datastore",
|
|
21
|
+
tag: "DatastoreNotFound",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
op: config.getConfigPrune({ id: absent }),
|
|
25
|
+
kind: "prune",
|
|
26
|
+
tag: "PruneJobNotFound",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
op: config.getConfigSync({ id: absent }),
|
|
30
|
+
kind: "sync",
|
|
31
|
+
tag: "SyncJobNotFound",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
op: config.getConfigVerify({ id: absent }),
|
|
35
|
+
kind: "verification",
|
|
36
|
+
tag: "VerifyJobNotFound",
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
describe("PBS resource absence", () => {
|
|
40
|
+
for (const { op, kind, tag } of cases) {
|
|
41
|
+
test(`${kind}: exact measured 400 is a typed missing resource`, async () => {
|
|
42
|
+
expect(await failure(op, 400, `no such ${kind} '${absent}'`)).toMatchObject({ _tag: tag });
|
|
43
|
+
});
|
|
44
|
+
test(`${kind}: a different status, kind or extended error is not absence`, async () => {
|
|
45
|
+
for (const [status, body] of [
|
|
46
|
+
[403, `no such ${kind} '${absent}'`],
|
|
47
|
+
[500, `no such ${kind} '${absent}'`],
|
|
48
|
+
[400, "no such unrelated 'id'"],
|
|
49
|
+
[400, `no such ${kind} '${absent}': configuration unreadable`],
|
|
50
|
+
[400, "parameter verification failed"],
|
|
51
|
+
]) {
|
|
52
|
+
expect(await failure(op, status, body)).not.toMatchObject({
|
|
53
|
+
_tag: tag,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
test("missing text is scoped to the named GET operation", async () => {
|
|
59
|
+
expect(await failure(config.listConfigDatastore({}), 400, `no such datastore '${absent}'`)).not.toMatchObject({ _tag: "DatastoreNotFound" });
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=missing-resource.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-resource.test.js","sourceRoot":"","sources":["../src/missing-resource.test.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAC;AAE/C,MAAM,eAAe,GAAG,WAAW,CAAC;IAClC,OAAO,EAAE,iBAAiB;IAC1B,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,uBAAuB;CACjC,CAAC,CAAC;AACH,MAAM,OAAO,GAAG,CACd,EAA2D,EAC3D,MAAc,EACd,IAAY,EACZ,EAAE,CACF,MAAM,CAAC,UAAU,CACf,EAAE,CAAC,IAAI,CACL,KAAK,CAAC,IAAI,EACV,MAAM,CAAC,OAAO,CACZ,KAAK,CAAC,QAAQ,CACZ,eAAe,EACf,KAAK,CAAC,OAAO,CACX,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC1B,MAAM,CAAC,OAAO,CACZ,kBAAkB,CAAC,OAAO,CACxB,OAAO,EACP,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAC/B,CACF,CACF,CACF,CACF,CACF,EACD,MAAM,CAAC,IAAI,CACZ,CACF,CAAC;AACJ,MAAM,MAAM,GAAG,oBAAoB,CAAC;AACpC,MAAM,KAAK,GAAG;IACZ;QACE,EAAE,EAAE,MAAM,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC/C,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,mBAAmB;KACzB;IACD;QACE,EAAE,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QACzC,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,kBAAkB;KACxB;IACD;QACE,EAAE,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QACxC,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,iBAAiB;KACvB;IACD;QACE,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAC1C,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,mBAAmB;KACzB;CACO,CAAC;AAEX,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,IAAI,kDAAkD,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,CACJ,MAAM,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,WAAW,IAAI,KAAK,MAAM,GAAG,CAAC,CACtD,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,IAAI,6DAA6D,EAAE,KAAK,IAAI,EAAE;YACpF,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI;gBAC3B,CAAC,GAAG,EAAE,WAAW,IAAI,KAAK,MAAM,GAAG,CAAC;gBACpC,CAAC,GAAG,EAAE,WAAW,IAAI,KAAK,MAAM,GAAG,CAAC;gBACpC,CAAC,GAAG,EAAE,wBAAwB,CAAC;gBAC/B,CAAC,GAAG,EAAE,WAAW,IAAI,KAAK,MAAM,6BAA6B,CAAC;gBAC9D,CAAC,GAAG,EAAE,+BAA+B,CAAC;aAC9B,EAAE,CAAC;gBACX,MAAM,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;oBACxD,IAAI,EAAE,GAAG;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,CACJ,MAAM,OAAO,CACX,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAC9B,GAAG,EACH,sBAAsB,MAAM,GAAG,CAChC,CACF,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-boundaries.test.d.ts","sourceRoot":"","sources":["../src/protocol-boundaries.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** The PBS adapter preserves core's decoded-value and nested-form contracts. */
|
|
2
|
+
import { expect, test } from "bun:test";
|
|
3
|
+
import * as API from "@distilled.cloud/core/api";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
7
|
+
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
8
|
+
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
9
|
+
import { withPbsCodecs } from "./protocol-codecs.js";
|
|
10
|
+
const request = HttpClientRequest.post("https://pbs.test/config").pipe(HttpClientRequest.bodyUrlParams([
|
|
11
|
+
["target[0]", "mail"],
|
|
12
|
+
["target[1]", "hook"],
|
|
13
|
+
["nested[targets][0]", "keep"],
|
|
14
|
+
["scalar", "a,b"],
|
|
15
|
+
]));
|
|
16
|
+
const base = Layer.succeed(API.Protocol, API.Protocol.of({
|
|
17
|
+
encode: () => Effect.succeed(request),
|
|
18
|
+
decode: () => Effect.succeed(42),
|
|
19
|
+
}));
|
|
20
|
+
const protocol = withPbsCodecs(base);
|
|
21
|
+
test("only top-level indexed form lists change", async () => {
|
|
22
|
+
const encoded = await Effect.runPromise(Effect.gen(function* () {
|
|
23
|
+
const adapter = yield* API.Protocol;
|
|
24
|
+
return yield* adapter.encode({
|
|
25
|
+
input: {},
|
|
26
|
+
inputAst: Schema.Unknown.ast,
|
|
27
|
+
config: {},
|
|
28
|
+
});
|
|
29
|
+
}).pipe(Effect.provide(protocol)));
|
|
30
|
+
expect(encoded.body._tag).toBe("Uint8Array");
|
|
31
|
+
if (encoded.body._tag !== "Uint8Array")
|
|
32
|
+
return;
|
|
33
|
+
const form = new URLSearchParams(new TextDecoder().decode(encoded.body.body));
|
|
34
|
+
expect(form.getAll("target")).toEqual(["mail", "hook"]);
|
|
35
|
+
expect(form.get("nested[targets][0]")).toBe("keep");
|
|
36
|
+
expect(form.get("scalar")).toBe("a,b");
|
|
37
|
+
});
|
|
38
|
+
test("core-decoded output is validated on the Type side without decoding twice", async () => {
|
|
39
|
+
const result = await Effect.runPromise(Effect.gen(function* () {
|
|
40
|
+
const adapter = yield* API.Protocol;
|
|
41
|
+
return yield* adapter.decode({
|
|
42
|
+
response: HttpClientResponse.fromWeb(request, new Response("42")),
|
|
43
|
+
outputAst: Schema.NumberFromString.ast,
|
|
44
|
+
config: { output: Schema.NumberFromString },
|
|
45
|
+
errors: [],
|
|
46
|
+
});
|
|
47
|
+
}).pipe(Effect.provide(protocol)));
|
|
48
|
+
expect(result).toBe(42);
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=protocol-boundaries.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-boundaries.test.js","sourceRoot":"","sources":["../src/protocol-boundaries.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PBS 4.2.6-1's form arrays and successful response validation.
|
|
3
|
+
*
|
|
4
|
+
* The vendor's array parameters are repeated keys (`target=a&target=b`), not the Stripe
|
|
5
|
+
* bracket-index encoding used by core's generic REST builder. Measured against the PBS
|
|
6
|
+
* notification provider's existing protocol fixtures, 2026-09-24: indexed headers/secrets
|
|
7
|
+
* disappear from its read-back, and matchers perpetually drift. Preserve core path/auth/key
|
|
8
|
+
* mapping and adapt only its top-level indexed form fields at this vendor boundary.
|
|
9
|
+
*/
|
|
10
|
+
import * as API from "@distilled.cloud/core/api";
|
|
11
|
+
import * as Layer from "effect/Layer";
|
|
12
|
+
/**
|
|
13
|
+
* Core REST decode maps wire keys but does not validate required fields. In particular,
|
|
14
|
+
* PBS data:null unwrapped to {} used to look like a real resource to a caller. Validate
|
|
15
|
+
* with the operation's generated schema: Unit operations still accept {}, while a GET
|
|
16
|
+
* missing its required name/id fails. Preserve the mapped payload after validation: vendor
|
|
17
|
+
* fields absent from the published schema must not silently disappear. Core has already
|
|
18
|
+
* decoded the payload, so validate the schema's Type side instead of re-decoding transforms.
|
|
19
|
+
* Keep server data out of the parse error: notification responses can contain header
|
|
20
|
+
* credentials, and a schema diagnostic can reproduce them.
|
|
21
|
+
*/
|
|
22
|
+
export declare const withPbsCodecs: (base: Layer.Layer<API.Protocol>) => Layer.Layer<API.Protocol>;
|
|
23
|
+
//# sourceMappingURL=protocol-codecs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-codecs.d.ts","sourceRoot":"","sources":["../src/protocol-codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,GAAG,MAAM,2BAA2B,CAAC;AAEjD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAqBtC;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,SAClB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAC9B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CA8BE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PBS 4.2.6-1's form arrays and successful response validation.
|
|
3
|
+
*
|
|
4
|
+
* The vendor's array parameters are repeated keys (`target=a&target=b`), not the Stripe
|
|
5
|
+
* bracket-index encoding used by core's generic REST builder. Measured against the PBS
|
|
6
|
+
* notification provider's existing protocol fixtures, 2026-09-24: indexed headers/secrets
|
|
7
|
+
* disappear from its read-back, and matchers perpetually drift. Preserve core path/auth/key
|
|
8
|
+
* mapping and adapt only its top-level indexed form fields at this vendor boundary.
|
|
9
|
+
*/
|
|
10
|
+
import * as API from "@distilled.cloud/core/api";
|
|
11
|
+
import * as Effect from "effect/Effect";
|
|
12
|
+
import * as Layer from "effect/Layer";
|
|
13
|
+
import * as Schema from "effect/Schema";
|
|
14
|
+
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
15
|
+
import { ProxmoxBackupParseError } from "./errors.js";
|
|
16
|
+
const repeatedFormKeys = (request) => {
|
|
17
|
+
if (request.body._tag !== "Uint8Array" ||
|
|
18
|
+
request.body.contentType !== "application/x-www-form-urlencoded")
|
|
19
|
+
return request;
|
|
20
|
+
const fields = new URLSearchParams(new TextDecoder().decode(request.body.body));
|
|
21
|
+
const repeated = [];
|
|
22
|
+
for (const [key, value] of fields) {
|
|
23
|
+
repeated.push([key.replace(/^([^\[\]]+)\[\d+\]$/, "$1"), value]);
|
|
24
|
+
}
|
|
25
|
+
return HttpClientRequest.bodyUrlParams(request, repeated);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Core REST decode maps wire keys but does not validate required fields. In particular,
|
|
29
|
+
* PBS data:null unwrapped to {} used to look like a real resource to a caller. Validate
|
|
30
|
+
* with the operation's generated schema: Unit operations still accept {}, while a GET
|
|
31
|
+
* missing its required name/id fails. Preserve the mapped payload after validation: vendor
|
|
32
|
+
* fields absent from the published schema must not silently disappear. Core has already
|
|
33
|
+
* decoded the payload, so validate the schema's Type side instead of re-decoding transforms.
|
|
34
|
+
* Keep server data out of the parse error: notification responses can contain header
|
|
35
|
+
* credentials, and a schema diagnostic can reproduce them.
|
|
36
|
+
*/
|
|
37
|
+
export const withPbsCodecs = (base) => Layer.effect(API.Protocol, Effect.gen(function* () {
|
|
38
|
+
const protocol = yield* API.Protocol;
|
|
39
|
+
return API.Protocol.of({
|
|
40
|
+
encode: (args) => protocol.encode(args).pipe(Effect.map(repeatedFormKeys)),
|
|
41
|
+
decode: (args) => protocol.decode(args).pipe(Effect.flatMap((body) => args.config.output === undefined
|
|
42
|
+
? Effect.succeed(body)
|
|
43
|
+
: Schema.decodeUnknownEffect(Schema.toType(args.config.output))(body).pipe(Effect.as(body), Effect.mapError(() => new ProxmoxBackupParseError({
|
|
44
|
+
body: undefined,
|
|
45
|
+
cause: "Response does not match the operation's declared output schema",
|
|
46
|
+
}))))),
|
|
47
|
+
});
|
|
48
|
+
})).pipe(Layer.provide(base));
|
|
49
|
+
//# sourceMappingURL=protocol-codecs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-codecs.js","sourceRoot":"","sources":["../src/protocol-codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,GAAG,MAAM,2BAA2B,CAAC;AACjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,gBAAgB,GAAG,CAAC,OAA4C,EAAE,EAAE;IACxE,IACE,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY;QAClC,OAAO,CAAC,IAAI,CAAC,WAAW,KAAK,mCAAmC;QAEhE,OAAO,OAAO,CAAC;IACjB,MAAM,MAAM,GAAG,IAAI,eAAe,CAChC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAC5C,CAAC;IACF,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,iBAAiB,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,IAA+B,EACJ,EAAE,CAC7B,KAAK,CAAC,MAAM,CACV,GAAG,CAAC,QAAQ,EACZ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;IACrC,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CACxB,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACtB,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;YAC9B,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;YACtB,CAAC,CAAE,MAAM,CAAC,mBAAmB,CACzB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAClC,CAAC,IAAI,CAAC,CAAC,IAAI,CACV,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EACf,MAAM,CAAC,QAAQ,CACb,GAAG,EAAE,CACH,IAAI,uBAAuB,CAAC;gBAC1B,IAAI,EAAE,SAAS;gBACf,KAAK,EACH,gEAAgE;aACnE,CAAC,CACL,CACyB,CACjC,CACF;KACJ,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-codecs.test.d.ts","sourceRoot":"","sources":["../src/protocol-codecs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
5
|
+
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
6
|
+
import { credentials } from "./credentials.js";
|
|
7
|
+
import * as Retry from "./retry.js";
|
|
8
|
+
import { getConfigNotificationMatcher, putConfigNotificationMatcher, } from "./services/config.js";
|
|
9
|
+
const credential = credentials({
|
|
10
|
+
baseUrl: "https://pbs.test:8007",
|
|
11
|
+
tokenId: "test@pbs!fake",
|
|
12
|
+
secret: "fake-not-real",
|
|
13
|
+
});
|
|
14
|
+
const fakePbs = (body, see) => Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.sync(() => {
|
|
15
|
+
see?.(request);
|
|
16
|
+
return HttpClientResponse.fromWeb(request, Response.json({ data: body }));
|
|
17
|
+
})));
|
|
18
|
+
test("PBS arrays use repeated keys and Unit data:null remains a successful write", async () => {
|
|
19
|
+
let pairs = [];
|
|
20
|
+
const client = fakePbs(null, (request) => {
|
|
21
|
+
expect(request.body._tag).toBe("Uint8Array");
|
|
22
|
+
if (request.body._tag === "Uint8Array") {
|
|
23
|
+
pairs = [
|
|
24
|
+
...new URLSearchParams(new TextDecoder().decode(request.body.body)),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
await Effect.runPromise(putConfigNotificationMatcher({
|
|
29
|
+
name: "pager",
|
|
30
|
+
target: ["mail-to-root", "hook"],
|
|
31
|
+
delete: ["match-field", "match-calendar"],
|
|
32
|
+
}).pipe(Retry.none, Effect.provide(Layer.mergeAll(client, credential))));
|
|
33
|
+
expect(pairs.filter(([key]) => key === "target")).toEqual([
|
|
34
|
+
["target", "mail-to-root"],
|
|
35
|
+
["target", "hook"],
|
|
36
|
+
]);
|
|
37
|
+
expect(pairs.filter(([key]) => key === "delete")).toEqual([
|
|
38
|
+
["delete", "match-field"],
|
|
39
|
+
["delete", "match-calendar"],
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
for (const body of [null, { comment: "secret-like-text-must-not-appear" }]) {
|
|
43
|
+
test("incomplete resource output fails without exposing response contents", async () => {
|
|
44
|
+
const error = await Effect.runPromise(getConfigNotificationMatcher({ name: "pager" }).pipe(Retry.none, Effect.flip, Effect.provide(Layer.mergeAll(fakePbs(body), credential))));
|
|
45
|
+
expect(error).toMatchObject({ _tag: "ProxmoxBackupParseError" });
|
|
46
|
+
expect(JSON.stringify(error)).not.toContain("secret-like-text-must-not-appear");
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
test("valid resource output preserves fields omitted from the vendor schema", async () => {
|
|
50
|
+
const result = await Effect.runPromise(getConfigNotificationMatcher({ name: "pager" }).pipe(Retry.none, Effect.provide(Layer.mergeAll(fakePbs({ name: "pager", future_field: "keep-me" }), credential))));
|
|
51
|
+
expect(result).toMatchObject({ name: "pager", future_field: "keep-me" });
|
|
52
|
+
});
|
|
53
|
+
test("mapped NotFound is in the operation's typed union, including a plain-text response", async () => {
|
|
54
|
+
const client = Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, new Response("matcher 'pager' not found", { status: 404 })))));
|
|
55
|
+
const result = await Effect.runPromise(getConfigNotificationMatcher({ name: "pager" }).pipe(Retry.none, Effect.catchTag("NotFound", () => Effect.succeed(undefined)), Effect.provide(Layer.mergeAll(client, credential))));
|
|
56
|
+
expect(result).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=protocol-codecs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-codecs.test.js","sourceRoot":"","sources":["../src/protocol-codecs.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-raw-root.test.d.ts","sourceRoot":"","sources":["../src/protocol-raw-root.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
5
|
+
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
6
|
+
import { credentials } from "./credentials.js";
|
|
7
|
+
import * as Retry from "./retry.js";
|
|
8
|
+
import { deleteConfigDatastore, getConfigAcmeTos, listConfigDatastore, } from "./services/config.js";
|
|
9
|
+
const run = (operation, data) => Effect.runPromise(operation.pipe(Retry.none, Effect.provide(Layer.mergeAll(credentials({
|
|
10
|
+
baseUrl: "https://pbs.test:8007",
|
|
11
|
+
tokenId: "test@pbs!fake",
|
|
12
|
+
secret: "fake-not-real",
|
|
13
|
+
}), Layer.succeed(HttpClient.HttpClient, HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ data })))))))));
|
|
14
|
+
test("raw-root string responses retain task IDs and ACME terms URLs", async () => {
|
|
15
|
+
const upid = "UPID:pbs:00000001:00000002:00000003:delete-datastore:test:root@pam:";
|
|
16
|
+
expect(await run(deleteConfigDatastore({ name: "test" }), upid)).toBe(upid);
|
|
17
|
+
const url = "https://acme.test/terms";
|
|
18
|
+
expect(await run(getConfigAcmeTos({}), url)).toBe(url);
|
|
19
|
+
});
|
|
20
|
+
test("raw-root lists retain empty lists, map wire keys, and preserve extra fields", async () => {
|
|
21
|
+
expect(await run(listConfigDatastore({}), [])).toEqual([]);
|
|
22
|
+
const expected = [
|
|
23
|
+
{ name: "test", path: "/backup/test", keep_last: 2, future_field: "keep" },
|
|
24
|
+
];
|
|
25
|
+
expect(await run(listConfigDatastore({}), [
|
|
26
|
+
{
|
|
27
|
+
name: "test",
|
|
28
|
+
path: "/backup/test",
|
|
29
|
+
"keep-last": 2,
|
|
30
|
+
future_field: "keep",
|
|
31
|
+
},
|
|
32
|
+
])).toEqual(expected);
|
|
33
|
+
});
|
|
34
|
+
// These operations are not Unit responses: null must not become a valid empty object.
|
|
35
|
+
for (const data of [null, {}]) {
|
|
36
|
+
test(`raw-root operations reject ${JSON.stringify(data)} instead of accepting missing output`, async () => {
|
|
37
|
+
const operations = [
|
|
38
|
+
deleteConfigDatastore({ name: "test" }),
|
|
39
|
+
getConfigAcmeTos({}),
|
|
40
|
+
listConfigDatastore({}),
|
|
41
|
+
];
|
|
42
|
+
for (const operation of operations) {
|
|
43
|
+
const error = await run(Effect.flip(operation), data);
|
|
44
|
+
expect(error).toMatchObject({ _tag: "ProxmoxBackupParseError" });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=protocol-raw-root.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-raw-root.test.js","sourceRoot":"","sources":["../src/protocol-raw-root.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,GAAG,GAAG,CACV,SAAsD,EACtD,IAAa,EACb,EAAE,CACF,MAAM,CAAC,UAAU,CACf,SAAS,CAAC,IAAI,CACZ,KAAK,CAAC,IAAI,EACV,MAAM,CAAC,OAAO,CACZ,KAAK,CAAC,QAAQ,CACZ,WAAW,CAAC;IACV,OAAO,EAAE,uBAAuB;IAChC,OAAO,EAAE,eAAe;IACxB,MAAM,EAAE,eAAe;CACxB,CAAC,EACF,KAAK,CAAC,OAAO,CACX,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC1B,MAAM,CAAC,OAAO,CACZ,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAC7D,CACF,CACF,CACF,CACF,CACF,CACF,CAAC;AAEJ,IAAI,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;IAC/E,MAAM,IAAI,GACR,qEAAqE,CAAC;IACxE,MAAM,CAAC,MAAM,GAAG,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,yBAAyB,CAAC;IACtC,MAAM,CAAC,MAAM,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC7F,MAAM,CAAC,MAAM,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG;QACf,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE;KAC3E,CAAC;IACF,MAAM,CACJ,MAAM,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAAE;QACjC;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,MAAM;SACrB;KACF,CAAC,CACH,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,sFAAsF;AACtF,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;IAC9B,IAAI,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACxG,MAAM,UAAU,GAIV;YACJ,qBAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACvC,gBAAgB,CAAC,EAAE,CAAC;YACpB,mBAAmB,CAAC,EAAE,CAAC;SACxB,CAAC;QACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as Layer from "effect/Layer";
|
|
2
|
-
import type * as HttpClient from "effect/
|
|
3
|
-
import type * as HttpClientError from "effect/
|
|
2
|
+
import type * as HttpClient from "effect/http/HttpClient";
|
|
3
|
+
import type * as HttpClientError from "effect/http/HttpClientError";
|
|
4
4
|
import type * as API from "@distilled.cloud/core/api";
|
|
5
5
|
import { type ConfigError } from "@distilled.cloud/core/errors";
|
|
6
6
|
import { Credentials } from "./credentials.ts";
|
|
@@ -15,5 +15,6 @@ import { type DefaultErrors } from "./errors.ts";
|
|
|
15
15
|
export type ProxmoxBackupOpError = DefaultErrors | ConfigError | HttpClientError.HttpClientError;
|
|
16
16
|
/** Context (requirements) shared by every generated Proxmox Backup Server operation. */
|
|
17
17
|
export type ProxmoxBackupOpContext = Credentials | HttpClient.HttpClient;
|
|
18
|
+
/** PBS-specific form encoding and schema validation wrap core without changing other vendors. */
|
|
18
19
|
export declare const ProxmoxBackupProtocol: Layer.Layer<API.Protocol>;
|
|
19
20
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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,wBAAwB,CAAC;AAC1D,OAAO,KAAK,KAAK,eAAe,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,KAAK,GAAG,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAIL,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;AAwFzE,iGAAiG;AACjG,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAC/B,CAAC"}
|
package/dist/protocol.js
CHANGED
|
@@ -78,7 +78,8 @@ import * as Redacted from "effect/Redacted";
|
|
|
78
78
|
import { BadRequest, HTTP_STATUS_MAP, } from "@distilled.cloud/core/errors";
|
|
79
79
|
import { makeRestProtocol, } from "@distilled.cloud/core/protocol-rest";
|
|
80
80
|
import { Credentials } from "./credentials.js";
|
|
81
|
-
import {
|
|
81
|
+
import { withPbsCodecs } from "./protocol-codecs.js";
|
|
82
|
+
import { ParameterVerificationFailed, ProxmoxBackupParseError, UnknownProxmoxBackupError, } from "./errors.js";
|
|
82
83
|
/**
|
|
83
84
|
* PBS's failure envelope is `{"data": null, "message": "...", "errors"?:
|
|
84
85
|
* {…}}` — see PVE's identical `errorEnvelope` for why `message` alone is
|
|
@@ -100,7 +101,7 @@ const PROXMOX_BACKUP_STATUS_MAP = {
|
|
|
100
101
|
...HTTP_STATUS_MAP,
|
|
101
102
|
};
|
|
102
103
|
delete PROXMOX_BACKUP_STATUS_MAP[400];
|
|
103
|
-
|
|
104
|
+
const baseProtocol = makeRestProtocol({
|
|
104
105
|
credentials: Effect.gen(function* () {
|
|
105
106
|
const resolve = yield* Credentials;
|
|
106
107
|
return yield* resolve;
|
|
@@ -134,6 +135,8 @@ export const ProxmoxBackupProtocol = makeRestProtocol({
|
|
|
134
135
|
// automatically; a malformed request is permanent). `BadRequest`
|
|
135
136
|
// (`Category.withBadRequestError`, not retryable) is the honest
|
|
136
137
|
// answer for "PBS said 400 and gave no further structure".
|
|
138
|
+
// A 2xx body that fails strict output validation (core rc.13).
|
|
139
|
+
parseError: ({ body, cause }) => new ProxmoxBackupParseError({ body, cause }),
|
|
137
140
|
unknownError: ({ status, message, body }) => {
|
|
138
141
|
const b = body !== null && typeof body === "object"
|
|
139
142
|
? body
|
|
@@ -155,4 +158,6 @@ export const ProxmoxBackupProtocol = makeRestProtocol({
|
|
|
155
158
|
return new UnknownProxmoxBackupError({ status, message, body });
|
|
156
159
|
},
|
|
157
160
|
});
|
|
161
|
+
/** PBS-specific form encoding and schema validation wrap core without changing other vendors. */
|
|
162
|
+
export const ProxmoxBackupProtocol = withPbsCodecs(baseProtocol);
|
|
158
163
|
//# sourceMappingURL=protocol.js.map
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAI5C,OAAO,EACL,UAAU,EACV,eAAe,GAEhB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,GAEjB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AAiBrB;;;;;GAKG;AACH,MAAM,aAAa,GAAG,CAAC,IAAa,EAAiC,EAAE;IACrE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,yBAAyB,GAA+C;IAC5E,GAAG,eAAe;CACnB,CAAC;AACF,OAAQ,yBAAqD,CAAC,GAAG,CAAC,CAAC;AAEnE,MAAM,
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAI5C,OAAO,EACL,UAAU,EACV,eAAe,GAEhB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gBAAgB,GAEjB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AAiBrB;;;;;GAKG;AACH,MAAM,aAAa,GAAG,CAAC,IAAa,EAAiC,EAAE;IACrE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,yBAAyB,GAA+C;IAC5E,GAAG,eAAe;CACnB,CAAC;AACF,OAAQ,yBAAqD,CAAC,GAAG,CAAC,CAAC;AAEnE,MAAM,YAAY,GAA8B,gBAAgB,CAAS;IACvE,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC;QACnC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;IACxB,CAAC,CAAC;IACF,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU;IACpC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACnB,qEAAqE;QACrE,aAAa,EAAE,eAAe,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;QAC7E,MAAM,EAAE,kBAAkB;KAC3B,CAAC;IACF,aAAa;IACb,SAAS,EAAE,yBAAyB;IACpC,wEAAwE;IACxE,mEAAmE;IACnE,6DAA6D;IAC7D,iBAAiB,EAAE,CAAC,IAAI,EAAE,EAAE;QAC1B,IACE,IAAI,KAAK,IAAI;YACb,OAAO,IAAI,KAAK,QAAQ;YACxB,MAAM,IAAK,IAAgC,EAC3C,CAAC;YACD,OAAQ,IAAgC,CAAC,IAAI,IAAI,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,sEAAsE;IACtE,iEAAiE;IACjE,sEAAsE;IACtE,EAAE;IACF,8DAA8D;IAC9D,kEAAkE;IAClE,+DAA+D;IAC/D,mEAAmE;IACnE,kEAAkE;IAClE,6DAA6D;IAC7D,+DAA+D;IAC/D,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,IAAI,uBAAuB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7E,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QAC1C,MAAM,CAAC,GACL,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YACvC,CAAC,CAAE,IAAgC;YACnC,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,WAAW,GAAG,CAAC,EAAE,MAAM,CAAC;QAC9B,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,IACE,WAAW,KAAK,IAAI;gBACpB,OAAO,WAAW,KAAK,QAAQ;gBAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAC3B,CAAC;gBACD,MAAM,MAAM,GAA2B,EAAE,CAAC;gBAC1C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CACjC,WAAsC,CACvC,EAAE,CAAC;oBACF,IAAI,OAAO,CAAC,KAAK,QAAQ;wBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC3C,CAAC;gBACD,OAAO,IAAI,2BAA2B,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,IAAI,yBAAyB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,iGAAiG;AACjG,MAAM,CAAC,MAAM,qBAAqB,GAChC,aAAa,CAAC,YAAY,CAAC,CAAC"}
|
package/dist/protocol.test.js
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
import { describe, expect, test } from "bun:test";
|
|
17
17
|
import * as Effect from "effect/Effect";
|
|
18
18
|
import * as Layer from "effect/Layer";
|
|
19
|
-
import * as HttpClient from "effect/
|
|
20
|
-
import * as HttpClientResponse from "effect/
|
|
19
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
20
|
+
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
21
21
|
import { credentials } from "./credentials.js";
|
|
22
22
|
import { BadRequest, ParameterVerificationFailed, UnknownProxmoxBackupError, } from "./errors.js";
|
|
23
23
|
import * as Retry from "./retry.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../src/protocol.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,UAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../src/protocol.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,UAAU,EACV,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,eAAe,GAAG,WAAW,CAAC;IAClC,OAAO,EAAE,iBAAiB;IAC1B,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,uBAAuB;CACjC,CAAC,CAAC;AAEH,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,IAAa,EAAE,EAAE,CAChD,KAAK,CAAC,OAAO,CACX,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CACf,kBAAkB,CAAC,OAAO,CACxB,OAAO,EACP,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAC/C,CACF,CACF,CACF,CAAC;AAEJ,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,IAAa,EAAE,EAAE,CAC7C,MAAM,CAAC,UAAU,CACf,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CACjB,KAAK,CAAC,IAAI,EACV,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC,EACtE,MAAM,CAAC,IAAI,CACZ,CACF,CAAC;AAEJ,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAI,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;QAC/G,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE;YAC5B,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,+BAA+B;YACxC,MAAM,EAAE,EAAE,OAAO,EAAE,uCAAuC,EAAE;SAC7D,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YAC1B,OAAO,EAAE,+BAA+B;YACxC,MAAM,EAAE,EAAE,OAAO,EAAE,uCAAuC,EAAE;SAC7D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CACpC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CACjB,MAAM,CAAC,OAAO,CACZ,KAAK,CAAC,QAAQ,CACZ,OAAO,CAAC,GAAG,EAAE;YACX,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE;SAC7D,CAAC,EACF,eAAe,CAChB,CACF,CACF,CACF,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAI,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACtG,IAAI,QAA4B,CAAC;QACjC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAC7B,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACf,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC5C,OAAO,kBAAkB,CAAC,OAAO,CAC/B,OAAO,EACP,IAAI,QAAQ,CACV,IAAI,CAAC,SAAS,CAAC;gBACb,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;aAC1D,CAAC,EACF,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CACF,CAAC;QACJ,CAAC,CAAC,CACH,CACF,CAAC;QACF,MAAM,MAAM,CAAC,UAAU,CACrB,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CACjB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAC3D,CACF,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|