@tinycloud/sdk-services 3.1.0-beta.7 → 3.1.0-beta.9
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/{BaseService-DU-lE-Qx.d.ts → BaseService-B_UKhVht.d.ts} +1 -1
- package/dist/{BaseService-C8zRy0ww.d.cts → BaseService-DWbPbov7.d.cts} +1 -1
- package/dist/encryption/index.cjs +8 -0
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +2 -2
- package/dist/encryption/index.d.ts +2 -2
- package/dist/encryption/index.js +8 -0
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +212 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +212 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/decrypt-transport-response-error.d.cts +1 -1
- package/dist/internal/decrypt-transport-response-error.d.ts +1 -1
- package/dist/kv/index.cjs +203 -1
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +172 -3
- package/dist/kv/index.d.ts +172 -3
- package/dist/kv/index.js +203 -1
- package/dist/kv/index.js.map +1 -1
- package/dist/sql/index.cjs +8 -0
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.d.cts +2 -2
- package/dist/sql/index.d.ts +2 -2
- package/dist/sql/index.js +8 -0
- package/dist/sql/index.js.map +1 -1
- package/dist/{types-qwMmB7qB.d.cts → types-CVwwxqXF.d.cts} +8 -0
- package/dist/{types-qwMmB7qB.d.ts → types-CVwwxqXF.d.ts} +8 -0
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { a as IServiceContext, c as InvokeFunction, d as InvokeAnyFunction, F as FetchFunction, S as ServiceSession, e as RetryPolicy, T as TelemetryConfig, I as IService, E as EventHandler, b as ServiceError, R as Result, P as PermissionHint, f as StorageQuotaInfo } from './types-
|
|
2
|
-
export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, s as TelemetryEventHandler, t as TelemetryEvents, u as TelemetrySpanEvent, v as defaultRetryPolicy, w as err, x as ok, y as serviceError } from './types-
|
|
1
|
+
import { a as IServiceContext, c as InvokeFunction, d as InvokeAnyFunction, F as FetchFunction, S as ServiceSession, e as RetryPolicy, T as TelemetryConfig, I as IService, E as EventHandler, b as ServiceError, R as Result, P as PermissionHint, f as StorageQuotaInfo } from './types-CVwwxqXF.cjs';
|
|
2
|
+
export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, s as TelemetryEventHandler, t as TelemetryEvents, u as TelemetrySpanEvent, v as defaultRetryPolicy, w as err, x as ok, y as serviceError } from './types-CVwwxqXF.cjs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { B as BaseService } from './BaseService-
|
|
5
|
-
export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-
|
|
4
|
+
import { B as BaseService } from './BaseService-DWbPbov7.cjs';
|
|
5
|
+
export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-DWbPbov7.cjs';
|
|
6
6
|
import { IKVService } from './kv/index.cjs';
|
|
7
|
-
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.cjs';
|
|
7
|
+
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVBatchReadResponse, KVChange, KVChangesAuthority, KVChangesOptions, KVChangesResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.cjs';
|
|
8
8
|
export { BatchOptions, BatchResponse, DatabaseHandle, ExecuteOptions, ExecuteResponse, IDatabaseHandle, ISQLMigrations, ISQLService, QueryOptions, QueryResponse, SQLAction, SQLActionType, SQLMigrations, SQLService, SQLServiceConfig, SqlMigration, SqlMigrationApplyOptions, SqlMigrationApplyResponse, SqlStatement, SqlValue } from './sql/index.cjs';
|
|
9
9
|
import { IEncryptionService, DecryptCapabilityProof } from './encryption/index.cjs';
|
|
10
10
|
export { BuildCanonicalDecryptRequestInput, BuildDecryptFactsInput, BuildDecryptInvocationInput, BuiltDecryptInvocation, CanonicalDecryptRequest, CanonicalJson, DECRYPT_ACTION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, DEFAULT_ENCRYPTION_ALG, DEFAULT_KEY_VERSION, DecryptEnvelopeOptions, DecryptInvocationFact, DecryptInvocationSigner, DecryptRequestBody, DecryptResponseBody, DecryptTransport, DiscoverNetworkInput, DiscoveredNetwork, DiscoverySource, ENCRYPTION_NETWORK_URN_PREFIX, ENCRYPTION_SERVICE, ENCRYPTION_SERVICE_SHORT, ENVELOPE_VERSION, EncryptToNetworkInput, EncryptToNetworkOptions, EncryptToNetworkResult, EncryptionCrypto, EncryptionError, EncryptionErrorInput, EncryptionService, EncryptionServiceConfig, InlineEncryptedEnvelope, Json, NETWORK_NAME_PATTERN, NetworkDescriptor, NetworkIdError, NodeDescriptorFetcher, ParsedNetworkId, RandomReceiverKeyInput, ReceiverKeyPair, ReceiverKeySigner, SignedReceiverKeyInput, VerifyDecryptResponseInput, WellKnownDescriptorFetcher, base64Decode, base64Encode, buildCanonicalDecryptRequest, buildDecryptAttenuation, buildDecryptFacts, buildDecryptInvocation, buildNetworkId, canonicalHashHex, canonicalSignedResponse, canonicalize as canonicalizeEncryptionJson, checkDecryptInvocationInput, decryptEnvelopeWithKey, deriveSignedReceiverKey, discoverNetwork, encryptToNetwork, encryptionError, ensureNetworkUsableForDecrypt, generateRandomReceiverKey, hexDecode, hexEncode, isNetworkId, networkDiscoveryKey, openWrappedKey, parseNetworkId, utf8Decode, utf8Encode, validateEnvelope, verifyDecryptResponse } from './encryption/index.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { a as IServiceContext, c as InvokeFunction, d as InvokeAnyFunction, F as FetchFunction, S as ServiceSession, e as RetryPolicy, T as TelemetryConfig, I as IService, E as EventHandler, b as ServiceError, R as Result, P as PermissionHint, f as StorageQuotaInfo } from './types-
|
|
2
|
-
export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, s as TelemetryEventHandler, t as TelemetryEvents, u as TelemetrySpanEvent, v as defaultRetryPolicy, w as err, x as ok, y as serviceError } from './types-
|
|
1
|
+
import { a as IServiceContext, c as InvokeFunction, d as InvokeAnyFunction, F as FetchFunction, S as ServiceSession, e as RetryPolicy, T as TelemetryConfig, I as IService, E as EventHandler, b as ServiceError, R as Result, P as PermissionHint, f as StorageQuotaInfo } from './types-CVwwxqXF.js';
|
|
2
|
+
export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, s as TelemetryEventHandler, t as TelemetryEvents, u as TelemetrySpanEvent, v as defaultRetryPolicy, w as err, x as ok, y as serviceError } from './types-CVwwxqXF.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { B as BaseService } from './BaseService-
|
|
5
|
-
export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-
|
|
4
|
+
import { B as BaseService } from './BaseService-B_UKhVht.js';
|
|
5
|
+
export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-B_UKhVht.js';
|
|
6
6
|
import { IKVService } from './kv/index.js';
|
|
7
|
-
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.js';
|
|
7
|
+
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVBatchReadResponse, KVChange, KVChangesAuthority, KVChangesOptions, KVChangesResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.js';
|
|
8
8
|
export { BatchOptions, BatchResponse, DatabaseHandle, ExecuteOptions, ExecuteResponse, IDatabaseHandle, ISQLMigrations, ISQLService, QueryOptions, QueryResponse, SQLAction, SQLActionType, SQLMigrations, SQLService, SQLServiceConfig, SqlMigration, SqlMigrationApplyOptions, SqlMigrationApplyResponse, SqlStatement, SqlValue } from './sql/index.js';
|
|
9
9
|
import { IEncryptionService, DecryptCapabilityProof } from './encryption/index.js';
|
|
10
10
|
export { BuildCanonicalDecryptRequestInput, BuildDecryptFactsInput, BuildDecryptInvocationInput, BuiltDecryptInvocation, CanonicalDecryptRequest, CanonicalJson, DECRYPT_ACTION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, DEFAULT_ENCRYPTION_ALG, DEFAULT_KEY_VERSION, DecryptEnvelopeOptions, DecryptInvocationFact, DecryptInvocationSigner, DecryptRequestBody, DecryptResponseBody, DecryptTransport, DiscoverNetworkInput, DiscoveredNetwork, DiscoverySource, ENCRYPTION_NETWORK_URN_PREFIX, ENCRYPTION_SERVICE, ENCRYPTION_SERVICE_SHORT, ENVELOPE_VERSION, EncryptToNetworkInput, EncryptToNetworkOptions, EncryptToNetworkResult, EncryptionCrypto, EncryptionError, EncryptionErrorInput, EncryptionService, EncryptionServiceConfig, InlineEncryptedEnvelope, Json, NETWORK_NAME_PATTERN, NetworkDescriptor, NetworkIdError, NodeDescriptorFetcher, ParsedNetworkId, RandomReceiverKeyInput, ReceiverKeyPair, ReceiverKeySigner, SignedReceiverKeyInput, VerifyDecryptResponseInput, WellKnownDescriptorFetcher, base64Decode, base64Encode, buildCanonicalDecryptRequest, buildDecryptAttenuation, buildDecryptFacts, buildDecryptInvocation, buildNetworkId, canonicalHashHex, canonicalSignedResponse, canonicalize as canonicalizeEncryptionJson, checkDecryptInvocationInput, decryptEnvelopeWithKey, deriveSignedReceiverKey, discoverNetwork, encryptToNetwork, encryptionError, ensureNetworkUsableForDecrypt, generateRandomReceiverKey, hexDecode, hexEncode, isNetworkId, networkDiscoveryKey, openWrappedKey, parseNetworkId, utf8Decode, utf8Encode, validateEnvelope, verifyDecryptResponse } from './encryption/index.js';
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,10 @@ var ErrorCodes = {
|
|
|
5
5
|
AUTH_EXPIRED: "AUTH_EXPIRED",
|
|
6
6
|
AUTH_REQUIRED: "AUTH_REQUIRED",
|
|
7
7
|
AUTH_UNAUTHORIZED: "AUTH_UNAUTHORIZED",
|
|
8
|
+
/** HTTP 401: the delegation the invocation cites was revoked. */
|
|
9
|
+
AUTH_DELEGATION_REVOKED: "AUTH_DELEGATION_REVOKED",
|
|
10
|
+
/** HTTP 401: a delegation the cited one rests on was revoked. */
|
|
11
|
+
AUTH_DELEGATION_ANCESTOR_REVOKED: "AUTH_DELEGATION_ANCESTOR_REVOKED",
|
|
8
12
|
NETWORK_ERROR: "NETWORK_ERROR",
|
|
9
13
|
TIMEOUT: "TIMEOUT",
|
|
10
14
|
ABORTED: "ABORTED",
|
|
@@ -16,6 +20,10 @@ var ErrorCodes = {
|
|
|
16
20
|
KV_PRECONDITION_FAILED: "KV_PRECONDITION_FAILED",
|
|
17
21
|
KV_CONFLICT: "KV_CONFLICT",
|
|
18
22
|
KV_RESPONSE_TOO_LARGE: "KV_RESPONSE_TOO_LARGE",
|
|
23
|
+
/** HTTP 410 from the change feed: discard sync state and restart without a cursor; `meta.reason` says why. */
|
|
24
|
+
KV_SYNC_RESET_REQUIRED: "KV_SYNC_RESET_REQUIRED",
|
|
25
|
+
/** HTTP 403 from the change feed: the retention grant was refused; `meta.reason` says why. */
|
|
26
|
+
KV_RETENTION_GRANT_REFUSED: "KV_RETENTION_GRANT_REFUSED",
|
|
19
27
|
// SQL-specific errors
|
|
20
28
|
SQL_ERROR: "SQL_ERROR",
|
|
21
29
|
SQL_PERMISSION_DENIED: "SQL_PERMISSION_DENIED",
|
|
@@ -1617,6 +1625,30 @@ var PrefixedKVService = class _PrefixedKVService {
|
|
|
1617
1625
|
removePrefix
|
|
1618
1626
|
});
|
|
1619
1627
|
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Read the change feed for everything under this prefix. A view with an
|
|
1630
|
+
* empty prefix (`""` or `"/"`) is refused: the node does not serve a
|
|
1631
|
+
* whole-space feed.
|
|
1632
|
+
*/
|
|
1633
|
+
async changes(options) {
|
|
1634
|
+
if (this._prefix.replace(/\/+$/, "") === "") {
|
|
1635
|
+
return err(serviceError(
|
|
1636
|
+
ErrorCodes.INVALID_INPUT,
|
|
1637
|
+
"KV changes needs a non-empty prefix; this view has none",
|
|
1638
|
+
"kv"
|
|
1639
|
+
));
|
|
1640
|
+
}
|
|
1641
|
+
const syncPrefix = `${this._prefix}/`;
|
|
1642
|
+
const response = await this._kv.changes({ ...options, prefix: syncPrefix });
|
|
1643
|
+
if (!response.ok) return response;
|
|
1644
|
+
return ok({
|
|
1645
|
+
...response.data,
|
|
1646
|
+
changes: response.data.changes.map((change) => ({
|
|
1647
|
+
...change,
|
|
1648
|
+
key: change.key.startsWith(syncPrefix) ? change.key.slice(syncPrefix.length) : change.key
|
|
1649
|
+
}))
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1620
1652
|
/**
|
|
1621
1653
|
* Delete a key.
|
|
1622
1654
|
*/
|
|
@@ -1669,11 +1701,18 @@ var KVAction = {
|
|
|
1669
1701
|
PUT: "tinycloud.kv/put",
|
|
1670
1702
|
LIST: "tinycloud.kv/list",
|
|
1671
1703
|
DELETE: "tinycloud.kv/del",
|
|
1672
|
-
HEAD: "tinycloud.kv/metadata"
|
|
1704
|
+
HEAD: "tinycloud.kv/metadata",
|
|
1705
|
+
/** The change feed; never implied by `*` or `tinycloud.kv/*`. */
|
|
1706
|
+
SYNC: "tinycloud.kv/sync",
|
|
1707
|
+
/** Retention attestation; presented through `retentionGrant`, never invoked or implied. */
|
|
1708
|
+
RETAIN: "tinycloud.kv/retain"
|
|
1673
1709
|
};
|
|
1674
1710
|
|
|
1675
1711
|
// src/kv/KVService.ts
|
|
1676
1712
|
var MAX_KV_BATCH_READ_ITEMS = 100;
|
|
1713
|
+
function isJsonObject(value) {
|
|
1714
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1715
|
+
}
|
|
1677
1716
|
function encodeKvBatchPartName(path) {
|
|
1678
1717
|
return encodeURIComponent(path).replace(
|
|
1679
1718
|
/[!'()*]/g,
|
|
@@ -2592,6 +2631,169 @@ var KVService = class extends BaseService {
|
|
|
2592
2631
|
}
|
|
2593
2632
|
});
|
|
2594
2633
|
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Read one page of the `tinycloud.kv/sync` change feed for a prefix.
|
|
2636
|
+
*/
|
|
2637
|
+
async changes(options) {
|
|
2638
|
+
return this.withTelemetry("changes", options?.prefix, async () => {
|
|
2639
|
+
if (!this.requireAuth()) {
|
|
2640
|
+
return err(authRequiredError("kv"));
|
|
2641
|
+
}
|
|
2642
|
+
if (typeof options?.prefix !== "string" || options.prefix.length === 0) {
|
|
2643
|
+
return err(serviceError(
|
|
2644
|
+
ErrorCodes.INVALID_INPUT,
|
|
2645
|
+
"KV changes prefix must be a non-empty string",
|
|
2646
|
+
"kv"
|
|
2647
|
+
));
|
|
2648
|
+
}
|
|
2649
|
+
if (options.limit !== void 0 && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 1e3)) {
|
|
2650
|
+
return err(serviceError(
|
|
2651
|
+
ErrorCodes.INVALID_INPUT,
|
|
2652
|
+
"KV changes limit must be an integer from 1 through 1000",
|
|
2653
|
+
"kv"
|
|
2654
|
+
));
|
|
2655
|
+
}
|
|
2656
|
+
const headers = {};
|
|
2657
|
+
if (options.limit !== void 0) headers["x-tinycloud-limit"] = String(options.limit);
|
|
2658
|
+
if (options.cursor !== void 0) headers["x-tinycloud-cursor"] = options.cursor;
|
|
2659
|
+
if (options.retentionGrant !== void 0) {
|
|
2660
|
+
headers["x-tinycloud-retention-grant"] = options.retentionGrant;
|
|
2661
|
+
}
|
|
2662
|
+
const request = this.createRequestSignal(options.signal, options.timeout);
|
|
2663
|
+
try {
|
|
2664
|
+
const response = await this.invokeOperation(
|
|
2665
|
+
options.prefix,
|
|
2666
|
+
KVAction.SYNC,
|
|
2667
|
+
void 0,
|
|
2668
|
+
request.signal,
|
|
2669
|
+
headers
|
|
2670
|
+
);
|
|
2671
|
+
if (!response.ok) {
|
|
2672
|
+
return await this.changesFailure(response, options.prefix, request.signal);
|
|
2673
|
+
}
|
|
2674
|
+
const text = await response.text();
|
|
2675
|
+
let body;
|
|
2676
|
+
try {
|
|
2677
|
+
body = JSON.parse(text);
|
|
2678
|
+
} catch {
|
|
2679
|
+
body = void 0;
|
|
2680
|
+
}
|
|
2681
|
+
const page = this.normalizeChangesResponse(body);
|
|
2682
|
+
if (!page) {
|
|
2683
|
+
return err(serviceError(
|
|
2684
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2685
|
+
"KV changes response was not a tinycloud.kv/sync page",
|
|
2686
|
+
"kv",
|
|
2687
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2688
|
+
));
|
|
2689
|
+
}
|
|
2690
|
+
return ok(page);
|
|
2691
|
+
} catch (error) {
|
|
2692
|
+
return err(wrapError("kv", error));
|
|
2693
|
+
} finally {
|
|
2694
|
+
request.dispose();
|
|
2695
|
+
}
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* Map a failed `kv/sync` response. 410 and the retention 403 carry
|
|
2700
|
+
* `{"error":{"code","reason"}}`; a revoked grant is a 401 whose text names
|
|
2701
|
+
* `delegation-revoked` or `delegation-ancestor-revoked`. A body read that
|
|
2702
|
+
* fails because the request was cancelled or timed out rethrows, so the
|
|
2703
|
+
* caller sees `ABORTED`/`TIMEOUT` rather than a mapped status.
|
|
2704
|
+
*/
|
|
2705
|
+
async changesFailure(response, prefix, signal) {
|
|
2706
|
+
if (response.status === 404) {
|
|
2707
|
+
return this.classifyNotFound(response, prefix);
|
|
2708
|
+
}
|
|
2709
|
+
let errorText;
|
|
2710
|
+
try {
|
|
2711
|
+
errorText = await response.text();
|
|
2712
|
+
} catch (error) {
|
|
2713
|
+
if (signal.aborted) throw error;
|
|
2714
|
+
errorText = "";
|
|
2715
|
+
}
|
|
2716
|
+
const meta = { status: response.status, statusText: response.statusText };
|
|
2717
|
+
let reason;
|
|
2718
|
+
let bodyCode;
|
|
2719
|
+
try {
|
|
2720
|
+
const body = JSON.parse(errorText);
|
|
2721
|
+
const error = isJsonObject(body) ? body.error : void 0;
|
|
2722
|
+
if (isJsonObject(error)) {
|
|
2723
|
+
if (typeof error.code === "string") bodyCode = error.code;
|
|
2724
|
+
if (typeof error.reason === "string") reason = error.reason;
|
|
2725
|
+
}
|
|
2726
|
+
} catch {
|
|
2727
|
+
}
|
|
2728
|
+
const context = `Failed to read KV changes for ${JSON.stringify(prefix)}`;
|
|
2729
|
+
if (response.status === 410) {
|
|
2730
|
+
return err(serviceError(
|
|
2731
|
+
ErrorCodes.KV_SYNC_RESET_REQUIRED,
|
|
2732
|
+
`${context}: the node requires a reset (${reason ?? "reason not given"}); discard sync state and restart without a cursor`,
|
|
2733
|
+
"kv",
|
|
2734
|
+
{ meta: { ...meta, reason } }
|
|
2735
|
+
));
|
|
2736
|
+
}
|
|
2737
|
+
if (response.status === 403 && bodyCode === "RETENTION_GRANT_REFUSED") {
|
|
2738
|
+
return err(serviceError(
|
|
2739
|
+
ErrorCodes.KV_RETENTION_GRANT_REFUSED,
|
|
2740
|
+
`${context}: the retention grant was refused (${reason ?? "reason not given"})`,
|
|
2741
|
+
"kv",
|
|
2742
|
+
{ meta: { ...meta, reason } }
|
|
2743
|
+
));
|
|
2744
|
+
}
|
|
2745
|
+
if (response.status === 401) {
|
|
2746
|
+
const revoked = /\bdelegation-ancestor-revoked\b/.test(errorText) ? ErrorCodes.AUTH_DELEGATION_ANCESTOR_REVOKED : /\bdelegation-revoked\b/.test(errorText) ? ErrorCodes.AUTH_DELEGATION_REVOKED : void 0;
|
|
2747
|
+
if (revoked !== void 0) {
|
|
2748
|
+
return err(serviceError(revoked, `${context}: 401 - ${errorText}`, "kv", { meta }));
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
if (response.status === 401 || response.status === 403) {
|
|
2752
|
+
return this.authorizationFailure(context, response, errorText, [prefix], KVAction.SYNC);
|
|
2753
|
+
}
|
|
2754
|
+
return err(serviceError(
|
|
2755
|
+
response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR,
|
|
2756
|
+
`${context}: ${response.status} - ${errorText}`,
|
|
2757
|
+
"kv",
|
|
2758
|
+
{ meta }
|
|
2759
|
+
));
|
|
2760
|
+
}
|
|
2761
|
+
normalizeChangesResponse(data) {
|
|
2762
|
+
if (!isJsonObject(data)) return void 0;
|
|
2763
|
+
const { changes, more, cursor, source, authority } = data;
|
|
2764
|
+
if (!Array.isArray(changes) || typeof more !== "boolean" || typeof cursor !== "string" || !isJsonObject(source) || typeof source.nodeDid !== "string" || typeof source.space !== "string" || typeof source.prefix !== "string" || !isJsonObject(authority)) {
|
|
2765
|
+
return void 0;
|
|
2766
|
+
}
|
|
2767
|
+
const { notBefore, expiresAt, retainUntil } = authority;
|
|
2768
|
+
if (notBefore !== null && typeof notBefore !== "string" || expiresAt !== null && typeof expiresAt !== "string" || retainUntil !== null && typeof retainUntil !== "string") {
|
|
2769
|
+
return void 0;
|
|
2770
|
+
}
|
|
2771
|
+
const parsed = [];
|
|
2772
|
+
for (const change of changes) {
|
|
2773
|
+
if (!isJsonObject(change) || typeof change.key !== "string") return void 0;
|
|
2774
|
+
if (change.deleted === true) {
|
|
2775
|
+
parsed.push({ key: change.key, deleted: true });
|
|
2776
|
+
continue;
|
|
2777
|
+
}
|
|
2778
|
+
const { metadata } = change;
|
|
2779
|
+
if (change.deleted !== false || typeof change.etag !== "string" || !isJsonObject(metadata) || !Object.values(metadata).every((value) => typeof value === "string")) {
|
|
2780
|
+
return void 0;
|
|
2781
|
+
}
|
|
2782
|
+
parsed.push({
|
|
2783
|
+
key: change.key,
|
|
2784
|
+
deleted: false,
|
|
2785
|
+
etag: change.etag,
|
|
2786
|
+
metadata
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
return {
|
|
2790
|
+
changes: parsed,
|
|
2791
|
+
more,
|
|
2792
|
+
cursor,
|
|
2793
|
+
source: { nodeDid: source.nodeDid, space: source.space, prefix: source.prefix },
|
|
2794
|
+
authority: { notBefore, expiresAt, retainUntil }
|
|
2795
|
+
};
|
|
2796
|
+
}
|
|
2595
2797
|
/**
|
|
2596
2798
|
* Delete a key.
|
|
2597
2799
|
*/
|
|
@@ -6139,6 +6341,7 @@ var SecretsService = class {
|
|
|
6139
6341
|
}
|
|
6140
6342
|
async listAll() {
|
|
6141
6343
|
const entries = /* @__PURE__ */ new Map();
|
|
6344
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
6142
6345
|
let cursor;
|
|
6143
6346
|
do {
|
|
6144
6347
|
const result = await this.vault.listPage({
|
|
@@ -6161,6 +6364,14 @@ var SecretsService = class {
|
|
|
6161
6364
|
"Secret catalog listing was truncated without a continuation cursor."
|
|
6162
6365
|
);
|
|
6163
6366
|
}
|
|
6367
|
+
if (cursor !== void 0) {
|
|
6368
|
+
if (seenCursors.has(cursor)) {
|
|
6369
|
+
return invalidSecretInput(
|
|
6370
|
+
"Secret catalog listing repeated a continuation cursor; the node does not support paged KV lists."
|
|
6371
|
+
);
|
|
6372
|
+
}
|
|
6373
|
+
seenCursors.add(cursor);
|
|
6374
|
+
}
|
|
6164
6375
|
} while (cursor !== void 0);
|
|
6165
6376
|
return {
|
|
6166
6377
|
ok: true,
|