@tinycloud/sdk-services 3.2.0-beta.2 → 3.2.0-beta.3
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-DWbPbov7.d.cts → BaseService-BDQXjWMx.d.cts} +1 -1
- package/dist/{BaseService-B_UKhVht.d.ts → BaseService-Di_hVfUV.d.ts} +1 -1
- package/dist/encryption/index.cjs +7 -1
- 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 +7 -1
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +595 -353
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -26
- package/dist/index.d.ts +36 -26
- package/dist/index.js +590 -353
- 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 +530 -334
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +17 -468
- package/dist/kv/index.d.ts +17 -468
- package/dist/kv/index.js +524 -333
- package/dist/kv/index.js.map +1 -1
- package/dist/kv/replication/index.cjs +1375 -0
- package/dist/kv/replication/index.cjs.map +1 -0
- package/dist/kv/replication/index.d.cts +9 -0
- package/dist/kv/replication/index.d.ts +9 -0
- package/dist/kv/replication/index.js +1342 -0
- package/dist/kv/replication/index.js.map +1 -0
- package/dist/scope-BmLxwyl-.d.ts +957 -0
- package/dist/scope-D855kRDx.d.cts +957 -0
- package/dist/sql/index.cjs +12 -6
- 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 +12 -6
- package/dist/sql/index.js.map +1 -1
- package/dist/{types-CVwwxqXF.d.cts → types-7A5rHWRY.d.cts} +10 -1
- package/dist/{types-CVwwxqXF.d.ts → types-7A5rHWRY.d.ts} +10 -1
- package/package.json +18 -1
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
BaseService: () => BaseService,
|
|
24
|
+
CLEAR_PENDING_WARNING: () => CLEAR_PENDING_WARNING,
|
|
24
25
|
DECRYPT_ACTION: () => DECRYPT_ACTION,
|
|
25
26
|
DECRYPT_FACT_TYPE: () => DECRYPT_FACT_TYPE,
|
|
26
27
|
DECRYPT_RESULT_TYPE: () => DECRYPT_RESULT_TYPE,
|
|
@@ -88,6 +89,7 @@ __export(src_exports, {
|
|
|
88
89
|
buildDecryptInvocation: () => buildDecryptInvocation,
|
|
89
90
|
buildNetworkId: () => buildNetworkId,
|
|
90
91
|
canonicalHashHex: () => canonicalHashHex,
|
|
92
|
+
canonicalReplicationIdentity: () => canonicalReplicationIdentity,
|
|
91
93
|
canonicalSignedResponse: () => canonicalSignedResponse,
|
|
92
94
|
canonicalizeEncryptionJson: () => canonicalize,
|
|
93
95
|
canonicalizeSecretScope: () => canonicalizeSecretScope,
|
|
@@ -114,6 +116,7 @@ __export(src_exports, {
|
|
|
114
116
|
installTinyCloudDebugGlobals: () => installTinyCloudDebugGlobals,
|
|
115
117
|
isNetworkId: () => isNetworkId,
|
|
116
118
|
isStorageFullError: () => isStorageFullError,
|
|
119
|
+
kvPrefixCovers: () => kvPrefixCovers,
|
|
117
120
|
networkDiscoveryKey: () => networkDiscoveryKey,
|
|
118
121
|
networkError: () => networkError,
|
|
119
122
|
notFoundError: () => notFoundError,
|
|
@@ -127,6 +130,8 @@ __export(src_exports, {
|
|
|
127
130
|
parseSecretCatalogKey: () => parseSecretCatalogKey,
|
|
128
131
|
parseStorageQuotaBytes: () => parseStorageQuotaBytes,
|
|
129
132
|
permissionDeniedError: () => permissionDeniedError,
|
|
133
|
+
replicationIdentityKey: () => replicationIdentityKey,
|
|
134
|
+
requiresSecretsOptIn: () => requiresSecretsOptIn,
|
|
130
135
|
resolveSecretListPrefix: () => resolveSecretListPrefix,
|
|
131
136
|
resolveSecretPath: () => resolveSecretPath,
|
|
132
137
|
serviceError: () => serviceError,
|
|
@@ -214,7 +219,12 @@ var TelemetryEvents = {
|
|
|
214
219
|
SERVICE_ERROR: "service.error",
|
|
215
220
|
SERVICE_RETRY: "service.retry",
|
|
216
221
|
SESSION_CHANGED: "session.changed",
|
|
217
|
-
SESSION_EXPIRED: "session.expired"
|
|
222
|
+
SESSION_EXPIRED: "session.expired",
|
|
223
|
+
REPLICATION_READ: "replication.read",
|
|
224
|
+
REPLICATION_WRITE: "replication.write",
|
|
225
|
+
REPLICATION_SYNC: "replication.sync",
|
|
226
|
+
REPLICATION_STATE: "replication.state",
|
|
227
|
+
REPLICATION_DIVERGENCE: "replication.divergence"
|
|
218
228
|
};
|
|
219
229
|
function ok(data) {
|
|
220
230
|
return { ok: true, data };
|
|
@@ -240,9 +250,34 @@ var SAFE_NUMBER_FIELDS = /* @__PURE__ */ new Set([
|
|
|
240
250
|
"endedAt",
|
|
241
251
|
"startedAt",
|
|
242
252
|
"status",
|
|
243
|
-
"timestamp"
|
|
253
|
+
"timestamp",
|
|
254
|
+
"latencyMs",
|
|
255
|
+
"stalenessMs",
|
|
256
|
+
"count",
|
|
257
|
+
"changes",
|
|
258
|
+
"deleted",
|
|
259
|
+
"fetched",
|
|
260
|
+
"pages",
|
|
261
|
+
"lagMs",
|
|
262
|
+
"pendingCleared"
|
|
244
263
|
]);
|
|
245
264
|
var SAFE_BOOLEAN_FIELDS = /* @__PURE__ */ new Set(["authenticated", "ok", "persisted"]);
|
|
265
|
+
var SAFE_REPLICATION_FIELDS = {
|
|
266
|
+
source: ["replica", "network", "none"],
|
|
267
|
+
reason: ["hit", "absent", "deleted", "content_missing", "coverage_incomplete", "not_covered", "pending_write", "grant_missing", "grant_expired", "grant_revoked", "grant_not_yet_valid", "stale", "replica_error", "runtime_unsupported", "replica_unavailable", "unsupported_option", "network_cursor", "cursor_restart", "aborted", "REPLICA_BEHIND_OWN_WRITES", "REPLICA_UNPROVEN_SINCE_START", "NETWORK_REQUESTED"],
|
|
268
|
+
op: ["get", "list", "put", "delete", "batchPut"],
|
|
269
|
+
trigger: ["start", "interval", "stale_read", "manual"],
|
|
270
|
+
outcome: ["found", "not_found", "error", "committed", "failed", "ambiguous", "ok", "busy", "aborted"],
|
|
271
|
+
class: ["offline", "authority", "storage", "node"],
|
|
272
|
+
state: ["opened", "grant_installed", "grant_missing", "runtime_unsupported", "unavailable", "revoked", "recreated", "purged", "purge_failed", "pending_store_error", "pinned", "pending_cleared", "closed", "idle", "ready"],
|
|
273
|
+
kind: ["value", "missing_local", "extra_local", "keys", "order"],
|
|
274
|
+
coverage: ["empty", "bootstrapping", "complete"],
|
|
275
|
+
authority: ["valid", "expired", "revoked", "not-yet-valid"],
|
|
276
|
+
code: ["NETWORK_ERROR", "TIMEOUT", "ABORTED", "REPLICA_BUSY", "REPLICA_BEHIND_OWN_WRITES", "REPLICA_UNPROVEN_SINCE_START", "NETWORK_REQUESTED", "INTEGRITY_ERROR", "STORAGE_ERROR", "REPLICA_CLOSED", "RUNTIME_UNSUPPORTED", "GRANT_EXPIRED", "GRANT_REVOKED", "GRANT_NOT_YET_VALID", "GRANT_MISSING", "GRANT_INVALID", "SOURCE_CHANGED", "PROTOCOL_ERROR", "SCOPE_VIOLATION", "NODE_ERROR", "CONTENT_MISMATCH", "STORAGE_FULL"],
|
|
277
|
+
pendingState: ["in_flight", "committed", "ambiguous"],
|
|
278
|
+
strategy: ["session", "minted", "installed"],
|
|
279
|
+
verify: ["match", "diverged", "error", "aborted"]
|
|
280
|
+
};
|
|
246
281
|
function finiteNumber(value) {
|
|
247
282
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
248
283
|
}
|
|
@@ -279,6 +314,12 @@ function projectDiagnosticData(value) {
|
|
|
279
314
|
const boolean = read(value, key);
|
|
280
315
|
if (typeof boolean === "boolean") projected[key] = boolean;
|
|
281
316
|
}
|
|
317
|
+
for (const [key, allowed] of Object.entries(SAFE_REPLICATION_FIELDS)) {
|
|
318
|
+
const candidate = read(value, key);
|
|
319
|
+
if (typeof candidate === "string" && allowed.includes(candidate)) {
|
|
320
|
+
projected[key] = candidate;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
282
323
|
const url = read(value, "url");
|
|
283
324
|
if (url !== void 0) projected.url = REDACTED;
|
|
284
325
|
const error = read(value, "error");
|
|
@@ -903,6 +944,12 @@ var ServiceContext = class {
|
|
|
903
944
|
get abortSignal() {
|
|
904
945
|
return this._abortController.signal;
|
|
905
946
|
}
|
|
947
|
+
get operationAbortSignal() {
|
|
948
|
+
return this._operationAbortSignal;
|
|
949
|
+
}
|
|
950
|
+
setOperationAbortSignal(signal) {
|
|
951
|
+
this._operationAbortSignal = signal;
|
|
952
|
+
}
|
|
906
953
|
/**
|
|
907
954
|
* Permanently retire this graph after its owner installs a replacement.
|
|
908
955
|
* Unlike `abort()`, retirement never creates a fresh controller, so captured
|
|
@@ -1654,6 +1701,7 @@ var BaseService = class {
|
|
|
1654
1701
|
const parents = [
|
|
1655
1702
|
this.abortController.signal,
|
|
1656
1703
|
this.context?.abortSignal,
|
|
1704
|
+
this.context?.operationAbortSignal,
|
|
1657
1705
|
signal
|
|
1658
1706
|
].filter((parent) => parent !== void 0);
|
|
1659
1707
|
for (const parent of parents) {
|
|
@@ -1899,14 +1947,28 @@ var KVService = class extends BaseService {
|
|
|
1899
1947
|
*/
|
|
1900
1948
|
constructor(config = {}) {
|
|
1901
1949
|
super();
|
|
1950
|
+
this.readThrough = null;
|
|
1951
|
+
this.readThroughReady = null;
|
|
1902
1952
|
this._config = config;
|
|
1903
1953
|
}
|
|
1954
|
+
/** Delay KV routing until an asynchronously loaded read-through is attached. */
|
|
1955
|
+
setReadThroughReady(ready) {
|
|
1956
|
+
const settled = ready.then(() => void 0, () => void 0);
|
|
1957
|
+
this.readThroughReady = settled;
|
|
1958
|
+
void settled.then(() => {
|
|
1959
|
+
if (this.readThroughReady === settled) this.readThroughReady = null;
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1904
1962
|
/**
|
|
1905
1963
|
* Get the service configuration.
|
|
1906
1964
|
*/
|
|
1907
1965
|
get config() {
|
|
1908
1966
|
return this._config;
|
|
1909
1967
|
}
|
|
1968
|
+
/** Install or remove the optional replication read-through policy. */
|
|
1969
|
+
setReadThrough(readThrough) {
|
|
1970
|
+
this.readThrough = readThrough;
|
|
1971
|
+
}
|
|
1910
1972
|
handleQuotaErrorResponse(response, errorText, key) {
|
|
1911
1973
|
if (response.status !== 402 && response.status !== 413) {
|
|
1912
1974
|
return void 0;
|
|
@@ -2160,6 +2222,7 @@ var KVService = class extends BaseService {
|
|
|
2160
2222
|
return aligned;
|
|
2161
2223
|
}
|
|
2162
2224
|
async batchRead(keys, action, options) {
|
|
2225
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
2163
2226
|
if (!this.requireAuth()) return err(authRequiredError("kv"));
|
|
2164
2227
|
if (keys.length === 0) return ok({ results: [], count: 0 });
|
|
2165
2228
|
if (keys.length > MAX_KV_BATCH_READ_ITEMS) {
|
|
@@ -2410,6 +2473,7 @@ var KVService = class extends BaseService {
|
|
|
2410
2473
|
*/
|
|
2411
2474
|
async get(key, options) {
|
|
2412
2475
|
return this.withTelemetry("get", key, async () => {
|
|
2476
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
2413
2477
|
if (!this.requireAuth()) {
|
|
2414
2478
|
return err(authRequiredError("kv"));
|
|
2415
2479
|
}
|
|
@@ -2423,64 +2487,38 @@ var KVService = class extends BaseService {
|
|
|
2423
2487
|
const path = this.getFullPath(key, options?.prefix);
|
|
2424
2488
|
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2425
2489
|
try {
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
response,
|
|
2449
|
-
errorText2,
|
|
2450
|
-
[path],
|
|
2451
|
-
KVAction.GET,
|
|
2452
|
-
structuredCapability ? { permissionHint, ...structuredCapability } : {}
|
|
2453
|
-
);
|
|
2454
|
-
}
|
|
2455
|
-
if (response.status === 404) {
|
|
2456
|
-
return await this.classifyNotFound(response, key);
|
|
2457
|
-
}
|
|
2458
|
-
const errorText = await response.text();
|
|
2459
|
-
if (response.status === 413) {
|
|
2460
|
-
return err(serviceError(
|
|
2461
|
-
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
2462
|
-
`KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
|
|
2463
|
-
"kv",
|
|
2464
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2465
|
-
));
|
|
2490
|
+
const network = () => this.getFromNetwork(key, path, options, request.signal);
|
|
2491
|
+
if (options?.source === "network") {
|
|
2492
|
+
const observer = this.readThrough;
|
|
2493
|
+
if (observer === null) return await network();
|
|
2494
|
+
let outcome = "error";
|
|
2495
|
+
const startedAt = Date.now();
|
|
2496
|
+
try {
|
|
2497
|
+
const result = await network();
|
|
2498
|
+
outcome = result.ok ? "found" : result.error.code === ErrorCodes.KV_NOT_FOUND ? "not_found" : "error";
|
|
2499
|
+
return result;
|
|
2500
|
+
} finally {
|
|
2501
|
+
try {
|
|
2502
|
+
observer.observeNetworkRequested({
|
|
2503
|
+
op: "get",
|
|
2504
|
+
space: this.context.session.spaceId,
|
|
2505
|
+
path,
|
|
2506
|
+
reason: "NETWORK_REQUESTED",
|
|
2507
|
+
outcome,
|
|
2508
|
+
latencyMs: Date.now() - startedAt
|
|
2509
|
+
});
|
|
2510
|
+
} catch {
|
|
2511
|
+
}
|
|
2466
2512
|
}
|
|
2467
|
-
return err(
|
|
2468
|
-
serviceError(
|
|
2469
|
-
ErrorCodes.NETWORK_ERROR,
|
|
2470
|
-
`Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2471
|
-
"kv",
|
|
2472
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2473
|
-
)
|
|
2474
|
-
);
|
|
2475
2513
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2514
|
+
if (this.readThrough === null) return await network();
|
|
2515
|
+
return await this.readThrough.get({
|
|
2516
|
+
space: this.context.session.spaceId,
|
|
2517
|
+
key,
|
|
2518
|
+
path,
|
|
2519
|
+
options,
|
|
2520
|
+
signal: request.signal,
|
|
2521
|
+
network
|
|
2484
2522
|
});
|
|
2485
2523
|
} catch (error) {
|
|
2486
2524
|
return err(wrapError("kv", error));
|
|
@@ -2489,6 +2527,56 @@ var KVService = class extends BaseService {
|
|
|
2489
2527
|
}
|
|
2490
2528
|
});
|
|
2491
2529
|
}
|
|
2530
|
+
async getFromNetwork(key, path, options, signal) {
|
|
2531
|
+
const response = await this.invokeOperation(
|
|
2532
|
+
path,
|
|
2533
|
+
KVAction.GET,
|
|
2534
|
+
void 0,
|
|
2535
|
+
signal,
|
|
2536
|
+
options?.maxResponseBytes === void 0 ? void 0 : { "x-tinycloud-max-response-bytes": String(options.maxResponseBytes) }
|
|
2537
|
+
);
|
|
2538
|
+
if (!response.ok) {
|
|
2539
|
+
if (response.status === 401 || response.status === 403) {
|
|
2540
|
+
const errorText2 = await this.readAuthorizationText(response);
|
|
2541
|
+
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
2542
|
+
const structuredCapability = permissionHint?.service === "tinycloud.kv" && permissionHint.space === this.context.session.spaceId && permissionHint.path === path ? validatedCapabilityOf({
|
|
2543
|
+
service: "kv",
|
|
2544
|
+
code: ErrorCodes.AUTH_UNAUTHORIZED,
|
|
2545
|
+
meta: {
|
|
2546
|
+
status: response.status,
|
|
2547
|
+
resource: `${this.context.session.spaceId}/kv/${path}`,
|
|
2548
|
+
requiredAction: KVAction.GET
|
|
2549
|
+
}
|
|
2550
|
+
}) : void 0;
|
|
2551
|
+
return this.authorizationFailure(
|
|
2552
|
+
`Failed to get key ${JSON.stringify(key)}`,
|
|
2553
|
+
response,
|
|
2554
|
+
errorText2,
|
|
2555
|
+
[path],
|
|
2556
|
+
KVAction.GET,
|
|
2557
|
+
structuredCapability ? { permissionHint, ...structuredCapability } : {}
|
|
2558
|
+
);
|
|
2559
|
+
}
|
|
2560
|
+
if (response.status === 404) return this.classifyNotFound(response, key);
|
|
2561
|
+
const errorText = await response.text();
|
|
2562
|
+
if (response.status === 413) {
|
|
2563
|
+
return err(serviceError(
|
|
2564
|
+
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
2565
|
+
`KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
|
|
2566
|
+
"kv",
|
|
2567
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2568
|
+
));
|
|
2569
|
+
}
|
|
2570
|
+
return err(serviceError(
|
|
2571
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2572
|
+
`Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2573
|
+
"kv",
|
|
2574
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2575
|
+
));
|
|
2576
|
+
}
|
|
2577
|
+
const data = await this.parseResponse(response, options?.raw, options?.binary);
|
|
2578
|
+
return ok({ data, headers: this.createResponseHeaders(response.headers) });
|
|
2579
|
+
}
|
|
2492
2580
|
async batchGet(keys, options) {
|
|
2493
2581
|
return this.withTelemetry(
|
|
2494
2582
|
"batchGet",
|
|
@@ -2501,6 +2589,7 @@ var KVService = class extends BaseService {
|
|
|
2501
2589
|
*/
|
|
2502
2590
|
async put(key, value, options) {
|
|
2503
2591
|
return this.withTelemetry("put", key, async () => {
|
|
2592
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
2504
2593
|
if (!this.requireAuth()) {
|
|
2505
2594
|
return err(authRequiredError("kv"));
|
|
2506
2595
|
}
|
|
@@ -2515,63 +2604,15 @@ var KVService = class extends BaseService {
|
|
|
2515
2604
|
const body = this.serializePutValue(value, options?.contentType);
|
|
2516
2605
|
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2517
2606
|
try {
|
|
2518
|
-
const
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
{
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
);
|
|
2528
|
-
if (response.status === 401 || response.status === 403) {
|
|
2529
|
-
return this.authorizationFailure(
|
|
2530
|
-
`Failed to put key ${JSON.stringify(key)}`,
|
|
2531
|
-
response,
|
|
2532
|
-
await this.readAuthorizationText(response),
|
|
2533
|
-
[path],
|
|
2534
|
-
KVAction.PUT
|
|
2535
|
-
);
|
|
2536
|
-
}
|
|
2537
|
-
if (!response.ok) {
|
|
2538
|
-
const errorText = await response.text();
|
|
2539
|
-
if (response.status === 412) {
|
|
2540
|
-
return err(serviceError(
|
|
2541
|
-
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
2542
|
-
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
2543
|
-
"kv",
|
|
2544
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2545
|
-
));
|
|
2546
|
-
}
|
|
2547
|
-
if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
|
|
2548
|
-
return err(serviceError(
|
|
2549
|
-
ErrorCodes.KV_CONFLICT,
|
|
2550
|
-
`Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
|
|
2551
|
-
"kv",
|
|
2552
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2553
|
-
));
|
|
2554
|
-
}
|
|
2555
|
-
const quotaError = this.handleQuotaErrorResponse(
|
|
2556
|
-
response,
|
|
2557
|
-
errorText,
|
|
2558
|
-
key
|
|
2559
|
-
);
|
|
2560
|
-
if (quotaError) {
|
|
2561
|
-
return quotaError;
|
|
2562
|
-
}
|
|
2563
|
-
return err(
|
|
2564
|
-
serviceError(
|
|
2565
|
-
ErrorCodes.KV_WRITE_FAILED,
|
|
2566
|
-
`Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2567
|
-
"kv",
|
|
2568
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2569
|
-
)
|
|
2570
|
-
);
|
|
2571
|
-
}
|
|
2572
|
-
return ok({
|
|
2573
|
-
data: void 0,
|
|
2574
|
-
headers: this.createResponseHeaders(response.headers)
|
|
2607
|
+
const network = () => this.putToNetwork(key, path, body, options, request.signal);
|
|
2608
|
+
if (this.readThrough === null) return await network();
|
|
2609
|
+
return await this.readThrough.write({
|
|
2610
|
+
op: "put",
|
|
2611
|
+
space: this.context.session.spaceId,
|
|
2612
|
+
entries: [{ path, body }],
|
|
2613
|
+
signal: request.signal,
|
|
2614
|
+
conditional: options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0,
|
|
2615
|
+
network
|
|
2575
2616
|
});
|
|
2576
2617
|
} catch (error) {
|
|
2577
2618
|
return err(wrapError("kv", error));
|
|
@@ -2580,11 +2621,64 @@ var KVService = class extends BaseService {
|
|
|
2580
2621
|
}
|
|
2581
2622
|
});
|
|
2582
2623
|
}
|
|
2624
|
+
async putToNetwork(key, path, body, options, signal) {
|
|
2625
|
+
const response = await this.invokeOperation(
|
|
2626
|
+
path,
|
|
2627
|
+
KVAction.PUT,
|
|
2628
|
+
body,
|
|
2629
|
+
signal,
|
|
2630
|
+
{
|
|
2631
|
+
...options?.ifMatch === void 0 ? {} : { "if-match": options.ifMatch },
|
|
2632
|
+
...options?.ifNoneMatch === void 0 ? {} : { "if-none-match": options.ifNoneMatch }
|
|
2633
|
+
}
|
|
2634
|
+
);
|
|
2635
|
+
if (response.status === 401 || response.status === 403) {
|
|
2636
|
+
return this.authorizationFailure(
|
|
2637
|
+
`Failed to put key ${JSON.stringify(key)}`,
|
|
2638
|
+
response,
|
|
2639
|
+
await this.readAuthorizationText(response),
|
|
2640
|
+
[path],
|
|
2641
|
+
KVAction.PUT
|
|
2642
|
+
);
|
|
2643
|
+
}
|
|
2644
|
+
if (!response.ok) {
|
|
2645
|
+
const errorText = await response.text();
|
|
2646
|
+
if (response.status === 412) {
|
|
2647
|
+
return err(serviceError(
|
|
2648
|
+
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
2649
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
2650
|
+
"kv",
|
|
2651
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2652
|
+
));
|
|
2653
|
+
}
|
|
2654
|
+
if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
|
|
2655
|
+
return err(serviceError(
|
|
2656
|
+
ErrorCodes.KV_CONFLICT,
|
|
2657
|
+
`Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
|
|
2658
|
+
"kv",
|
|
2659
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2660
|
+
));
|
|
2661
|
+
}
|
|
2662
|
+
const quotaError = this.handleQuotaErrorResponse(response, errorText, key);
|
|
2663
|
+
if (quotaError) return quotaError;
|
|
2664
|
+
return err(serviceError(
|
|
2665
|
+
ErrorCodes.KV_WRITE_FAILED,
|
|
2666
|
+
`Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2667
|
+
"kv",
|
|
2668
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2669
|
+
));
|
|
2670
|
+
}
|
|
2671
|
+
return ok({
|
|
2672
|
+
data: void 0,
|
|
2673
|
+
headers: this.createResponseHeaders(response.headers)
|
|
2674
|
+
});
|
|
2675
|
+
}
|
|
2583
2676
|
/**
|
|
2584
2677
|
* Store multiple values in one TinyCloud KV invocation.
|
|
2585
2678
|
*/
|
|
2586
2679
|
async batchPut(items, options) {
|
|
2587
2680
|
return this.withTelemetry("batchPut", String(items.length), async () => {
|
|
2681
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
2588
2682
|
if (!this.requireAuth()) {
|
|
2589
2683
|
return err(authRequiredError("kv"));
|
|
2590
2684
|
}
|
|
@@ -2615,155 +2709,177 @@ var KVService = class extends BaseService {
|
|
|
2615
2709
|
}
|
|
2616
2710
|
seen.add(path);
|
|
2617
2711
|
}
|
|
2618
|
-
let requestMayHaveDispatched = false;
|
|
2619
2712
|
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2620
2713
|
try {
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
session,
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2714
|
+
const network = () => this.batchPutToNetwork(items, paths, request.signal);
|
|
2715
|
+
if (this.readThrough === null) return await network();
|
|
2716
|
+
const entries = items.map((item, index) => ({
|
|
2717
|
+
path: paths[index],
|
|
2718
|
+
body: this.serializeBatchPutValue(item)
|
|
2719
|
+
}));
|
|
2720
|
+
return await this.readThrough.write({
|
|
2721
|
+
op: "batchPut",
|
|
2722
|
+
space: session.spaceId,
|
|
2723
|
+
entries,
|
|
2724
|
+
signal: request.signal,
|
|
2725
|
+
network: () => this.batchPutToNetwork(items, paths, request.signal, entries)
|
|
2726
|
+
});
|
|
2727
|
+
} catch (error) {
|
|
2728
|
+
const wrapped = wrapError("kv", error);
|
|
2729
|
+
return err({ ...wrapped, meta: { ...wrapped.meta, requestMayHaveDispatched: false } });
|
|
2730
|
+
} finally {
|
|
2731
|
+
request.dispose();
|
|
2732
|
+
}
|
|
2733
|
+
});
|
|
2734
|
+
}
|
|
2735
|
+
async batchPutToNetwork(items, paths, signal, entries) {
|
|
2736
|
+
const session = this.context.session;
|
|
2737
|
+
let requestMayHaveDispatched = false;
|
|
2738
|
+
try {
|
|
2739
|
+
const body = new FormData();
|
|
2740
|
+
for (let index = 0; index < items.length; index++) {
|
|
2741
|
+
body.append(
|
|
2742
|
+
encodeKvBatchPartName(paths[index]),
|
|
2743
|
+
entries?.[index]?.body ?? this.serializeBatchPutValue(items[index])
|
|
2636
2744
|
);
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
return this.authorizationFailure(
|
|
2664
|
-
`Failed to batch put ${items.length} key(s)`,
|
|
2665
|
-
response,
|
|
2666
|
-
errorText,
|
|
2667
|
-
paths,
|
|
2668
|
-
KVAction.PUT
|
|
2669
|
-
);
|
|
2670
|
-
}
|
|
2671
|
-
const quotaError = this.handleQuotaErrorResponse(
|
|
2672
|
-
response,
|
|
2673
|
-
errorText,
|
|
2674
|
-
"batch"
|
|
2675
|
-
);
|
|
2676
|
-
if (quotaError) {
|
|
2677
|
-
return quotaError;
|
|
2678
|
-
}
|
|
2745
|
+
}
|
|
2746
|
+
const headers = this.context.invokeAny(
|
|
2747
|
+
session,
|
|
2748
|
+
paths.map((path) => ({
|
|
2749
|
+
spaceId: session.spaceId,
|
|
2750
|
+
service: "kv",
|
|
2751
|
+
path,
|
|
2752
|
+
action: KVAction.PUT
|
|
2753
|
+
}))
|
|
2754
|
+
);
|
|
2755
|
+
const url = `${this.host}/invoke`;
|
|
2756
|
+
const init = {
|
|
2757
|
+
method: "POST",
|
|
2758
|
+
headers,
|
|
2759
|
+
body,
|
|
2760
|
+
signal
|
|
2761
|
+
};
|
|
2762
|
+
const fetchFn = this.context.fetch;
|
|
2763
|
+
requestMayHaveDispatched = true;
|
|
2764
|
+
const response = await fetchFn(url, init);
|
|
2765
|
+
if (!response.ok) {
|
|
2766
|
+
let errorText;
|
|
2767
|
+
try {
|
|
2768
|
+
errorText = await response.text();
|
|
2769
|
+
} catch (textError) {
|
|
2770
|
+
const cause = textError instanceof Error ? textError : new Error(String(textError));
|
|
2679
2771
|
return err(
|
|
2680
2772
|
serviceError(
|
|
2681
2773
|
ErrorCodes.KV_WRITE_FAILED,
|
|
2682
|
-
`Failed to batch put ${items.length} key(s): ${response.status} - ${
|
|
2774
|
+
`Failed to batch put ${items.length} key(s): ${response.status} - <response body could not be read: ${cause.message}>`,
|
|
2683
2775
|
"kv",
|
|
2684
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2776
|
+
{ cause, meta: { status: response.status, statusText: response.statusText } }
|
|
2685
2777
|
)
|
|
2686
2778
|
);
|
|
2687
2779
|
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
serviceError(
|
|
2696
|
-
timedOut ? ErrorCodes.TIMEOUT : ErrorCodes.NETWORK_ERROR,
|
|
2697
|
-
timedOut ? `KV batchPut response body did not arrive in time: ${cause.message}` : `KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2698
|
-
"kv",
|
|
2699
|
-
{
|
|
2700
|
-
cause,
|
|
2701
|
-
meta: {
|
|
2702
|
-
...timedOut ? { timeoutMs: cause.timeoutMs } : {},
|
|
2703
|
-
requestMayHaveDispatched: true,
|
|
2704
|
-
responseReceived: true,
|
|
2705
|
-
status: response.status,
|
|
2706
|
-
outcome: "batch-unconfirmed"
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
)
|
|
2780
|
+
if (response.status === 401 || response.status === 403) {
|
|
2781
|
+
return this.authorizationFailure(
|
|
2782
|
+
`Failed to batch put ${items.length} key(s)`,
|
|
2783
|
+
response,
|
|
2784
|
+
errorText,
|
|
2785
|
+
paths,
|
|
2786
|
+
KVAction.PUT
|
|
2710
2787
|
);
|
|
2711
2788
|
}
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
{
|
|
2720
|
-
meta: {
|
|
2721
|
-
requestMayHaveDispatched: true,
|
|
2722
|
-
responseReceived: true,
|
|
2723
|
-
status: response.status,
|
|
2724
|
-
outcome: "batch-unconfirmed"
|
|
2725
|
-
}
|
|
2726
|
-
}
|
|
2727
|
-
)
|
|
2728
|
-
);
|
|
2789
|
+
const quotaError = this.handleQuotaErrorResponse(
|
|
2790
|
+
response,
|
|
2791
|
+
errorText,
|
|
2792
|
+
"batch"
|
|
2793
|
+
);
|
|
2794
|
+
if (quotaError) {
|
|
2795
|
+
return quotaError;
|
|
2729
2796
|
}
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2797
|
+
return err(
|
|
2798
|
+
serviceError(
|
|
2799
|
+
ErrorCodes.KV_WRITE_FAILED,
|
|
2800
|
+
`Failed to batch put ${items.length} key(s): ${response.status} - ${errorText}`,
|
|
2801
|
+
"kv",
|
|
2802
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2803
|
+
)
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2806
|
+
let rawBody;
|
|
2807
|
+
try {
|
|
2808
|
+
rawBody = await response.json();
|
|
2809
|
+
} catch (jsonError) {
|
|
2810
|
+
const cause = jsonError instanceof Error ? jsonError : new Error(String(jsonError));
|
|
2811
|
+
const timedOut = isRequestTimeoutError(cause);
|
|
2812
|
+
return err(
|
|
2813
|
+
serviceError(
|
|
2814
|
+
timedOut ? ErrorCodes.TIMEOUT : ErrorCodes.NETWORK_ERROR,
|
|
2815
|
+
timedOut ? `KV batchPut response body did not arrive in time: ${cause.message}` : `KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2816
|
+
"kv",
|
|
2817
|
+
{
|
|
2818
|
+
cause,
|
|
2819
|
+
meta: {
|
|
2820
|
+
...timedOut ? { timeoutMs: cause.timeoutMs } : {},
|
|
2821
|
+
requestMayHaveDispatched: true,
|
|
2822
|
+
responseReceived: true,
|
|
2823
|
+
status: response.status,
|
|
2824
|
+
outcome: "batch-unconfirmed"
|
|
2746
2825
|
}
|
|
2747
|
-
|
|
2748
|
-
)
|
|
2749
|
-
|
|
2750
|
-
return ok(batchResponse);
|
|
2751
|
-
} catch (error) {
|
|
2752
|
-
const wrapped = wrapError("kv", error);
|
|
2753
|
-
return err({
|
|
2754
|
-
...wrapped,
|
|
2755
|
-
meta: { ...wrapped.meta, requestMayHaveDispatched }
|
|
2756
|
-
});
|
|
2757
|
-
} finally {
|
|
2758
|
-
request.dispose();
|
|
2826
|
+
}
|
|
2827
|
+
)
|
|
2828
|
+
);
|
|
2759
2829
|
}
|
|
2760
|
-
|
|
2830
|
+
const batchResponse = this.normalizeBatchPutResponse(rawBody);
|
|
2831
|
+
if (!batchResponse) {
|
|
2832
|
+
return err(
|
|
2833
|
+
serviceError(
|
|
2834
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2835
|
+
"KV batchPut response did not include matching written keys and count",
|
|
2836
|
+
"kv",
|
|
2837
|
+
{
|
|
2838
|
+
meta: {
|
|
2839
|
+
requestMayHaveDispatched: true,
|
|
2840
|
+
responseReceived: true,
|
|
2841
|
+
status: response.status,
|
|
2842
|
+
outcome: "batch-unconfirmed"
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
)
|
|
2846
|
+
);
|
|
2847
|
+
}
|
|
2848
|
+
const requestedPaths = new Set(paths);
|
|
2849
|
+
const writtenPaths = new Set(batchResponse.written);
|
|
2850
|
+
const matchesRequest = batchResponse.count === paths.length && batchResponse.written.length === paths.length && writtenPaths.size === paths.length && batchResponse.written.every((key) => requestedPaths.has(key));
|
|
2851
|
+
if (!matchesRequest) {
|
|
2852
|
+
return err(
|
|
2853
|
+
serviceError(
|
|
2854
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2855
|
+
`KV batchPut response did not confirm all ${paths.length} requested key(s) were written`,
|
|
2856
|
+
"kv",
|
|
2857
|
+
{
|
|
2858
|
+
meta: {
|
|
2859
|
+
requestMayHaveDispatched: true,
|
|
2860
|
+
responseReceived: true,
|
|
2861
|
+
status: response.status,
|
|
2862
|
+
outcome: "batch-unconfirmed"
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
)
|
|
2866
|
+
);
|
|
2867
|
+
}
|
|
2868
|
+
return ok(batchResponse);
|
|
2869
|
+
} catch (error) {
|
|
2870
|
+
const wrapped = wrapError("kv", error);
|
|
2871
|
+
return err({
|
|
2872
|
+
...wrapped,
|
|
2873
|
+
meta: { ...wrapped.meta, requestMayHaveDispatched }
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2761
2876
|
}
|
|
2762
2877
|
/**
|
|
2763
2878
|
* List keys with optional prefix filtering.
|
|
2764
2879
|
*/
|
|
2765
2880
|
async list(options) {
|
|
2766
2881
|
return this.withTelemetry("list", options?.prefix, async () => {
|
|
2882
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
2767
2883
|
if (!this.requireAuth()) {
|
|
2768
2884
|
return err(authRequiredError("kv"));
|
|
2769
2885
|
}
|
|
@@ -2780,49 +2896,44 @@ var KVService = class extends BaseService {
|
|
|
2780
2896
|
}
|
|
2781
2897
|
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2782
2898
|
try {
|
|
2783
|
-
const
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2899
|
+
const network = () => this.listFromNetwork(listPath, options, request.signal);
|
|
2900
|
+
let page;
|
|
2901
|
+
if (options?.source === "network") {
|
|
2902
|
+
const observer = this.readThrough;
|
|
2903
|
+
if (observer === null) {
|
|
2904
|
+
page = await network();
|
|
2905
|
+
} else {
|
|
2906
|
+
let outcome = "error";
|
|
2907
|
+
const startedAt = Date.now();
|
|
2908
|
+
try {
|
|
2909
|
+
page = await network();
|
|
2910
|
+
outcome = page.ok ? "found" : "error";
|
|
2911
|
+
} finally {
|
|
2912
|
+
try {
|
|
2913
|
+
observer.observeNetworkRequested({
|
|
2914
|
+
op: "list",
|
|
2915
|
+
space: this.context.session.spaceId,
|
|
2916
|
+
path: listPath,
|
|
2917
|
+
reason: "NETWORK_REQUESTED",
|
|
2918
|
+
outcome,
|
|
2919
|
+
latencyMs: Date.now() - startedAt
|
|
2920
|
+
});
|
|
2921
|
+
} catch {
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2802
2924
|
}
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
let keys = await this.parseResponse(response, options?.raw);
|
|
2814
|
-
keys = keys ?? [];
|
|
2815
|
-
if (options?.removePrefix && listPath) {
|
|
2816
|
-
const prefixWithSlash = listPath.endsWith("/") ? listPath : `${listPath}/`;
|
|
2817
|
-
keys = keys.map(
|
|
2818
|
-
(key) => key.startsWith(prefixWithSlash) ? key.slice(prefixWithSlash.length) : key
|
|
2819
|
-
);
|
|
2925
|
+
} else if (this.readThrough === null) {
|
|
2926
|
+
page = await network();
|
|
2927
|
+
} else {
|
|
2928
|
+
page = await this.readThrough.list({
|
|
2929
|
+
space: this.context.session.spaceId,
|
|
2930
|
+
listPath,
|
|
2931
|
+
options,
|
|
2932
|
+
signal: request.signal,
|
|
2933
|
+
network
|
|
2934
|
+
});
|
|
2820
2935
|
}
|
|
2821
|
-
return ok(
|
|
2822
|
-
keys,
|
|
2823
|
-
...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" },
|
|
2824
|
-
...response.headers.get("x-tinycloud-next-cursor") === null ? {} : { nextCursor: response.headers.get("x-tinycloud-next-cursor") ?? void 0 }
|
|
2825
|
-
});
|
|
2936
|
+
return page.ok ? this.finishList(page.data, listPath, options?.removePrefix) : page;
|
|
2826
2937
|
} catch (error) {
|
|
2827
2938
|
return err(wrapError("kv", error));
|
|
2828
2939
|
} finally {
|
|
@@ -2830,6 +2941,56 @@ var KVService = class extends BaseService {
|
|
|
2830
2941
|
}
|
|
2831
2942
|
});
|
|
2832
2943
|
}
|
|
2944
|
+
async listFromNetwork(listPath, options, signal) {
|
|
2945
|
+
const response = await this.invokeOperation(
|
|
2946
|
+
listPath,
|
|
2947
|
+
KVAction.LIST,
|
|
2948
|
+
void 0,
|
|
2949
|
+
signal,
|
|
2950
|
+
options?.limit === void 0 && options?.cursor === void 0 ? void 0 : {
|
|
2951
|
+
...options?.limit === void 0 ? {} : { "x-tinycloud-limit": String(options.limit) },
|
|
2952
|
+
...options?.cursor === void 0 ? {} : { "x-tinycloud-cursor": options.cursor }
|
|
2953
|
+
}
|
|
2954
|
+
);
|
|
2955
|
+
if (!response.ok) {
|
|
2956
|
+
if (response.status === 401 || response.status === 403) {
|
|
2957
|
+
return this.authorizationFailure(
|
|
2958
|
+
"Failed to list keys",
|
|
2959
|
+
response,
|
|
2960
|
+
await this.readAuthorizationText(response),
|
|
2961
|
+
[listPath],
|
|
2962
|
+
KVAction.LIST
|
|
2963
|
+
);
|
|
2964
|
+
}
|
|
2965
|
+
const errorText = await response.text();
|
|
2966
|
+
return err(serviceError(
|
|
2967
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2968
|
+
`Failed to list keys: ${response.status} - ${errorText}`,
|
|
2969
|
+
"kv",
|
|
2970
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2971
|
+
));
|
|
2972
|
+
}
|
|
2973
|
+
const keys = await this.parseResponse(response, options?.raw) ?? [];
|
|
2974
|
+
return ok({
|
|
2975
|
+
keys,
|
|
2976
|
+
...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" },
|
|
2977
|
+
...response.headers.get("x-tinycloud-next-cursor") === null ? {} : { nextCursor: response.headers.get("x-tinycloud-next-cursor") ?? void 0 }
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
finishList(page, listPath, removePrefix) {
|
|
2981
|
+
let keys = page.keys;
|
|
2982
|
+
if (removePrefix && listPath) {
|
|
2983
|
+
const prefixWithSlash = listPath.endsWith("/") ? listPath : `${listPath}/`;
|
|
2984
|
+
keys = keys.map(
|
|
2985
|
+
(key) => key.startsWith(prefixWithSlash) ? key.slice(prefixWithSlash.length) : key
|
|
2986
|
+
);
|
|
2987
|
+
}
|
|
2988
|
+
return ok({
|
|
2989
|
+
keys,
|
|
2990
|
+
...page.truncated === void 0 ? {} : { truncated: page.truncated },
|
|
2991
|
+
...page.nextCursor === void 0 ? {} : { nextCursor: page.nextCursor }
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2833
2994
|
/**
|
|
2834
2995
|
* Read one page of the `tinycloud.kv/sync` change feed for a prefix.
|
|
2835
2996
|
*/
|
|
@@ -2998,61 +3159,22 @@ var KVService = class extends BaseService {
|
|
|
2998
3159
|
*/
|
|
2999
3160
|
async delete(key, options) {
|
|
3000
3161
|
return this.withTelemetry("delete", key, async () => {
|
|
3162
|
+
if (this.readThroughReady !== null) await this.readThroughReady;
|
|
3001
3163
|
if (!this.requireAuth()) {
|
|
3002
3164
|
return err(authRequiredError("kv"));
|
|
3003
3165
|
}
|
|
3004
3166
|
const path = this.getFullPath(key, options?.prefix);
|
|
3005
3167
|
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
3006
3168
|
try {
|
|
3007
|
-
const
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
return this.authorizationFailure(
|
|
3017
|
-
`Failed to delete key ${JSON.stringify(key)}`,
|
|
3018
|
-
response,
|
|
3019
|
-
await this.readAuthorizationText(response),
|
|
3020
|
-
[path],
|
|
3021
|
-
KVAction.DELETE
|
|
3022
|
-
);
|
|
3023
|
-
}
|
|
3024
|
-
if (response.status === 404) {
|
|
3025
|
-
return await this.classifyNotFound(response, key);
|
|
3026
|
-
}
|
|
3027
|
-
const errorText = await response.text();
|
|
3028
|
-
if (response.status === 412) {
|
|
3029
|
-
return err(serviceError(
|
|
3030
|
-
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
3031
|
-
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
3032
|
-
"kv",
|
|
3033
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3034
|
-
));
|
|
3035
|
-
}
|
|
3036
|
-
if (response.status === 503 && options?.ifMatch !== void 0) {
|
|
3037
|
-
return err(serviceError(
|
|
3038
|
-
ErrorCodes.KV_CONFLICT,
|
|
3039
|
-
`Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
|
|
3040
|
-
"kv",
|
|
3041
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3042
|
-
));
|
|
3043
|
-
}
|
|
3044
|
-
return err(
|
|
3045
|
-
serviceError(
|
|
3046
|
-
ErrorCodes.NETWORK_ERROR,
|
|
3047
|
-
`Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
3048
|
-
"kv",
|
|
3049
|
-
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3050
|
-
)
|
|
3051
|
-
);
|
|
3052
|
-
}
|
|
3053
|
-
return ok({
|
|
3054
|
-
data: void 0,
|
|
3055
|
-
headers: this.createResponseHeaders(response.headers)
|
|
3169
|
+
const network = () => this.deleteFromNetwork(key, path, options, request.signal);
|
|
3170
|
+
if (this.readThrough === null) return await network();
|
|
3171
|
+
return await this.readThrough.write({
|
|
3172
|
+
op: "delete",
|
|
3173
|
+
space: this.context.session.spaceId,
|
|
3174
|
+
entries: [{ path }],
|
|
3175
|
+
signal: request.signal,
|
|
3176
|
+
conditional: options?.ifMatch !== void 0,
|
|
3177
|
+
network
|
|
3056
3178
|
});
|
|
3057
3179
|
} catch (error) {
|
|
3058
3180
|
return err(wrapError("kv", error));
|
|
@@ -3061,6 +3183,54 @@ var KVService = class extends BaseService {
|
|
|
3061
3183
|
}
|
|
3062
3184
|
});
|
|
3063
3185
|
}
|
|
3186
|
+
async deleteFromNetwork(key, path, options, signal) {
|
|
3187
|
+
const response = await this.invokeOperation(
|
|
3188
|
+
path,
|
|
3189
|
+
KVAction.DELETE,
|
|
3190
|
+
void 0,
|
|
3191
|
+
signal,
|
|
3192
|
+
options?.ifMatch === void 0 ? void 0 : { "if-match": options.ifMatch }
|
|
3193
|
+
);
|
|
3194
|
+
if (!response.ok) {
|
|
3195
|
+
if (response.status === 401 || response.status === 403) {
|
|
3196
|
+
return this.authorizationFailure(
|
|
3197
|
+
`Failed to delete key ${JSON.stringify(key)}`,
|
|
3198
|
+
response,
|
|
3199
|
+
await this.readAuthorizationText(response),
|
|
3200
|
+
[path],
|
|
3201
|
+
KVAction.DELETE
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3204
|
+
if (response.status === 404) return this.classifyNotFound(response, key);
|
|
3205
|
+
const errorText = await response.text();
|
|
3206
|
+
if (response.status === 412) {
|
|
3207
|
+
return err(serviceError(
|
|
3208
|
+
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
3209
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
3210
|
+
"kv",
|
|
3211
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3212
|
+
));
|
|
3213
|
+
}
|
|
3214
|
+
if (response.status === 503 && options?.ifMatch !== void 0) {
|
|
3215
|
+
return err(serviceError(
|
|
3216
|
+
ErrorCodes.KV_CONFLICT,
|
|
3217
|
+
`Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
|
|
3218
|
+
"kv",
|
|
3219
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3220
|
+
));
|
|
3221
|
+
}
|
|
3222
|
+
return err(serviceError(
|
|
3223
|
+
ErrorCodes.NETWORK_ERROR,
|
|
3224
|
+
`Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
3225
|
+
"kv",
|
|
3226
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3227
|
+
));
|
|
3228
|
+
}
|
|
3229
|
+
return ok({
|
|
3230
|
+
data: void 0,
|
|
3231
|
+
headers: this.createResponseHeaders(response.headers)
|
|
3232
|
+
});
|
|
3233
|
+
}
|
|
3064
3234
|
/**
|
|
3065
3235
|
* Get metadata for a key without retrieving the value.
|
|
3066
3236
|
*/
|
|
@@ -3228,6 +3398,64 @@ var KVService = class extends BaseService {
|
|
|
3228
3398
|
*/
|
|
3229
3399
|
KVService.serviceName = "kv";
|
|
3230
3400
|
|
|
3401
|
+
// src/kv/replication/constants.ts
|
|
3402
|
+
var CLEAR_PENDING_WARNING = "Clearing pending writes surrenders read-your-writes protection for the cleared keys. If a write whose record was cleared had an unknown outcome or never finished, it may commit now or later; this device can serve an older value until the next sync after that commit, as it would for a write from another device.";
|
|
3403
|
+
|
|
3404
|
+
// src/kv/replication/identity.ts
|
|
3405
|
+
var SPACE_ID = /^(tinycloud:pkh:eip155:\d+:)([^:]+)(:.+)$/;
|
|
3406
|
+
var PRINCIPAL_DID = /^(did:pkh:eip155:\d+:)([^:]+)$/;
|
|
3407
|
+
function canonicalReplicationIdentity(raw) {
|
|
3408
|
+
if (!raw || typeof raw.host !== "string" || typeof raw.space !== "string" || typeof raw.principal !== "string") {
|
|
3409
|
+
throw new TypeError(
|
|
3410
|
+
"Replication identity host, space, and principal must be strings"
|
|
3411
|
+
);
|
|
3412
|
+
}
|
|
3413
|
+
const authority = /^https?:\/\/([^/?#]*)/i.exec(raw.host)?.[1];
|
|
3414
|
+
let url;
|
|
3415
|
+
try {
|
|
3416
|
+
url = new URL(raw.host);
|
|
3417
|
+
} catch {
|
|
3418
|
+
throw new TypeError(
|
|
3419
|
+
"Replication identity host must be an absolute HTTP(S) URL"
|
|
3420
|
+
);
|
|
3421
|
+
}
|
|
3422
|
+
if (!authority || authority.includes("@") || raw.host.includes("?") || raw.host.includes("#") || url.username || url.password) {
|
|
3423
|
+
throw new TypeError(
|
|
3424
|
+
"Replication identity host must be HTTP(S) without credentials, query, or fragment"
|
|
3425
|
+
);
|
|
3426
|
+
}
|
|
3427
|
+
const space = SPACE_ID.exec(raw.space);
|
|
3428
|
+
const principal = PRINCIPAL_DID.exec(raw.principal);
|
|
3429
|
+
if (!space || !principal) {
|
|
3430
|
+
throw new TypeError(
|
|
3431
|
+
"Replication identity requires a full TinyCloud space id and a pkh principal DID"
|
|
3432
|
+
);
|
|
3433
|
+
}
|
|
3434
|
+
return {
|
|
3435
|
+
host: `${url.origin}${url.pathname.replace(/\/+$/, "")}`,
|
|
3436
|
+
space: `${space[1]}${space[2].toLowerCase()}${space[3]}`,
|
|
3437
|
+
principal: `${principal[1]}${principal[2].toLowerCase()}`
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3440
|
+
function replicationIdentityKey(id) {
|
|
3441
|
+
const canonical = canonicalReplicationIdentity(id);
|
|
3442
|
+
return `tc-replication/v1
|
|
3443
|
+
${canonical.host}
|
|
3444
|
+
${canonical.space}
|
|
3445
|
+
${canonical.principal}`;
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
// src/kv/replication/scope.ts
|
|
3449
|
+
function kvPrefixCovers(prefix, key) {
|
|
3450
|
+
if (prefix === "") return true;
|
|
3451
|
+
if (prefix.endsWith("/")) return key.startsWith(prefix);
|
|
3452
|
+
return key === prefix || key.startsWith(`${prefix}/`);
|
|
3453
|
+
}
|
|
3454
|
+
function requiresSecretsOptIn(space, prefix) {
|
|
3455
|
+
if (space === "secrets" || space.endsWith(":secrets")) return true;
|
|
3456
|
+
return prefix.split("/", 1)[0] === "vault";
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3231
3459
|
// src/responseErrors.ts
|
|
3232
3460
|
function parseServiceErrorBody(errorText) {
|
|
3233
3461
|
try {
|
|
@@ -3404,7 +3632,7 @@ var SQLService = class extends BaseService {
|
|
|
3404
3632
|
request.signal
|
|
3405
3633
|
);
|
|
3406
3634
|
if (!response.ok) {
|
|
3407
|
-
return this.handleErrorResponse(response, "query", dbName, [action]);
|
|
3635
|
+
return await this.handleErrorResponse(response, "query", dbName, [action]);
|
|
3408
3636
|
}
|
|
3409
3637
|
const data = await response.json();
|
|
3410
3638
|
return ok(data);
|
|
@@ -3444,7 +3672,7 @@ var SQLService = class extends BaseService {
|
|
|
3444
3672
|
request.signal
|
|
3445
3673
|
);
|
|
3446
3674
|
if (!response.ok) {
|
|
3447
|
-
return this.handleErrorResponse(response, "execute", dbName, requestedActions);
|
|
3675
|
+
return await this.handleErrorResponse(response, "execute", dbName, requestedActions);
|
|
3448
3676
|
}
|
|
3449
3677
|
const data = await response.json();
|
|
3450
3678
|
return ok(data);
|
|
@@ -3470,7 +3698,7 @@ var SQLService = class extends BaseService {
|
|
|
3470
3698
|
request.signal
|
|
3471
3699
|
);
|
|
3472
3700
|
if (!response.ok) {
|
|
3473
|
-
return this.handleErrorResponse(response, "batch", dbName, requestedActions);
|
|
3701
|
+
return await this.handleErrorResponse(response, "batch", dbName, requestedActions);
|
|
3474
3702
|
}
|
|
3475
3703
|
const data = await response.json();
|
|
3476
3704
|
return ok(data);
|
|
@@ -3495,7 +3723,7 @@ var SQLService = class extends BaseService {
|
|
|
3495
3723
|
request.signal
|
|
3496
3724
|
);
|
|
3497
3725
|
if (!response.ok) {
|
|
3498
|
-
return this.handleErrorResponse(response, "executeStatement", dbName, [SQLAction.WRITE]);
|
|
3726
|
+
return await this.handleErrorResponse(response, "executeStatement", dbName, [SQLAction.WRITE]);
|
|
3499
3727
|
}
|
|
3500
3728
|
const data = await response.json();
|
|
3501
3729
|
return ok(data);
|
|
@@ -3520,7 +3748,7 @@ var SQLService = class extends BaseService {
|
|
|
3520
3748
|
request.signal
|
|
3521
3749
|
);
|
|
3522
3750
|
if (!response.ok) {
|
|
3523
|
-
return this.handleErrorResponse(response, "export", dbName, [SQLAction.READ]);
|
|
3751
|
+
return await this.handleErrorResponse(response, "export", dbName, [SQLAction.READ]);
|
|
3524
3752
|
}
|
|
3525
3753
|
const resp = response;
|
|
3526
3754
|
if (typeof resp.blob === "function") {
|
|
@@ -3896,7 +4124,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3896
4124
|
request.signal
|
|
3897
4125
|
);
|
|
3898
4126
|
if (!response.ok) {
|
|
3899
|
-
return this.handleErrorResponse(response, "query");
|
|
4127
|
+
return await this.handleErrorResponse(response, "query");
|
|
3900
4128
|
}
|
|
3901
4129
|
const data = await response.json();
|
|
3902
4130
|
return ok(data);
|
|
@@ -3922,7 +4150,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3922
4150
|
{ Accept: "application/vnd.apache.arrow.stream" }
|
|
3923
4151
|
);
|
|
3924
4152
|
if (!response.ok) {
|
|
3925
|
-
return this.handleErrorResponse(response, "queryArrow");
|
|
4153
|
+
return await this.handleErrorResponse(response, "queryArrow");
|
|
3926
4154
|
}
|
|
3927
4155
|
const buffer = await response.arrayBuffer();
|
|
3928
4156
|
return ok(buffer);
|
|
@@ -3955,7 +4183,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3955
4183
|
request.signal
|
|
3956
4184
|
);
|
|
3957
4185
|
if (!response.ok) {
|
|
3958
|
-
return this.handleErrorResponse(response, "execute");
|
|
4186
|
+
return await this.handleErrorResponse(response, "execute");
|
|
3959
4187
|
}
|
|
3960
4188
|
const data = await response.json();
|
|
3961
4189
|
return ok(data);
|
|
@@ -3987,7 +4215,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3987
4215
|
request.signal
|
|
3988
4216
|
);
|
|
3989
4217
|
if (!response.ok) {
|
|
3990
|
-
return this.handleErrorResponse(response, "batch");
|
|
4218
|
+
return await this.handleErrorResponse(response, "batch");
|
|
3991
4219
|
}
|
|
3992
4220
|
const data = await response.json();
|
|
3993
4221
|
return ok(data);
|
|
@@ -4012,7 +4240,7 @@ var DuckDbService = class extends BaseService {
|
|
|
4012
4240
|
request.signal
|
|
4013
4241
|
);
|
|
4014
4242
|
if (!response.ok) {
|
|
4015
|
-
return this.handleErrorResponse(response, "executeStatement");
|
|
4243
|
+
return await this.handleErrorResponse(response, "executeStatement");
|
|
4016
4244
|
}
|
|
4017
4245
|
const data = await response.json();
|
|
4018
4246
|
return ok(data);
|
|
@@ -4037,7 +4265,7 @@ var DuckDbService = class extends BaseService {
|
|
|
4037
4265
|
request.signal
|
|
4038
4266
|
);
|
|
4039
4267
|
if (!response.ok) {
|
|
4040
|
-
return this.handleErrorResponse(response, "describe");
|
|
4268
|
+
return await this.handleErrorResponse(response, "describe");
|
|
4041
4269
|
}
|
|
4042
4270
|
const data = await response.json();
|
|
4043
4271
|
return ok(data);
|
|
@@ -4062,7 +4290,7 @@ var DuckDbService = class extends BaseService {
|
|
|
4062
4290
|
request.signal
|
|
4063
4291
|
);
|
|
4064
4292
|
if (!response.ok) {
|
|
4065
|
-
return this.handleErrorResponse(response, "export");
|
|
4293
|
+
return await this.handleErrorResponse(response, "export");
|
|
4066
4294
|
}
|
|
4067
4295
|
const blob = await response.blob();
|
|
4068
4296
|
return ok(blob);
|
|
@@ -4097,7 +4325,7 @@ var DuckDbService = class extends BaseService {
|
|
|
4097
4325
|
signal: request.signal
|
|
4098
4326
|
});
|
|
4099
4327
|
if (!response.ok) {
|
|
4100
|
-
return this.handleErrorResponse(response, "import");
|
|
4328
|
+
return await this.handleErrorResponse(response, "import");
|
|
4101
4329
|
}
|
|
4102
4330
|
return ok(void 0);
|
|
4103
4331
|
} catch (error) {
|
|
@@ -5809,7 +6037,8 @@ var DataVaultService = class extends BaseService {
|
|
|
5809
6037
|
}
|
|
5810
6038
|
try {
|
|
5811
6039
|
const valueResult = await this.tc.kv.get(`vault/${key}`, {
|
|
5812
|
-
raw: true
|
|
6040
|
+
raw: true,
|
|
6041
|
+
...options?.source === void 0 ? {} : { source: options.source }
|
|
5813
6042
|
});
|
|
5814
6043
|
if (!valueResult.ok) {
|
|
5815
6044
|
return vaultError({ code: "KEY_NOT_FOUND", key });
|
|
@@ -5854,7 +6083,7 @@ var DataVaultService = class extends BaseService {
|
|
|
5854
6083
|
}
|
|
5855
6084
|
let valueResult;
|
|
5856
6085
|
try {
|
|
5857
|
-
valueResult = await this.tc.kv.get(`vault/${key}`, { raw: true });
|
|
6086
|
+
valueResult = await this.tc.kv.get(`vault/${key}`, { raw: true, source: "network" });
|
|
5858
6087
|
} catch {
|
|
5859
6088
|
return { status: "node_unreachable" };
|
|
5860
6089
|
}
|
|
@@ -5923,7 +6152,8 @@ var DataVaultService = class extends BaseService {
|
|
|
5923
6152
|
}
|
|
5924
6153
|
try {
|
|
5925
6154
|
const valueResult = await this.tc.kv.get(`vault/${key}`, {
|
|
5926
|
-
raw: true
|
|
6155
|
+
raw: true,
|
|
6156
|
+
source: "network"
|
|
5927
6157
|
});
|
|
5928
6158
|
if (!valueResult.ok) {
|
|
5929
6159
|
return vaultError({ code: "KEY_NOT_FOUND", key });
|
|
@@ -6057,7 +6287,8 @@ var DataVaultService = class extends BaseService {
|
|
|
6057
6287
|
}
|
|
6058
6288
|
try {
|
|
6059
6289
|
const keyResult = await this.tc.kv.get(`keys/${key}`, {
|
|
6060
|
-
raw: true
|
|
6290
|
+
raw: true,
|
|
6291
|
+
...options?.source === void 0 ? {} : { source: options.source }
|
|
6061
6292
|
});
|
|
6062
6293
|
if (!keyResult.ok) {
|
|
6063
6294
|
return vaultError({ code: "KEY_NOT_FOUND", key });
|
|
@@ -6066,7 +6297,8 @@ var DataVaultService = class extends BaseService {
|
|
|
6066
6297
|
const keyBlobBytes = base64Decode(keyEnvelope.key);
|
|
6067
6298
|
const entryKey = this.crypto.decrypt(this.masterKey, keyBlobBytes);
|
|
6068
6299
|
const valueResult = await this.tc.kv.get(`vault/${key}`, {
|
|
6069
|
-
raw: true
|
|
6300
|
+
raw: true,
|
|
6301
|
+
...options?.source === void 0 ? {} : { source: options.source }
|
|
6070
6302
|
});
|
|
6071
6303
|
if (!valueResult.ok) {
|
|
6072
6304
|
return vaultError({ code: "KEY_NOT_FOUND", key });
|
|
@@ -6176,6 +6408,7 @@ var DataVaultService = class extends BaseService {
|
|
|
6176
6408
|
prefix: listPrefix,
|
|
6177
6409
|
removePrefix: true,
|
|
6178
6410
|
...options?.limit === void 0 ? {} : { limit: options.limit },
|
|
6411
|
+
...options?.source === void 0 ? {} : { source: options.source },
|
|
6179
6412
|
...options?.cursor === void 0 ? {} : { cursor: options.cursor }
|
|
6180
6413
|
});
|
|
6181
6414
|
if (!listResult.ok) {
|
|
@@ -6900,7 +7133,9 @@ var SecretsService = class {
|
|
|
6900
7133
|
async get(name, options) {
|
|
6901
7134
|
const secretPath = resolveSecretPathResult(name, options);
|
|
6902
7135
|
if ("ok" in secretPath) return secretPath;
|
|
6903
|
-
const result = await this.vault.get(secretPath.vaultKey)
|
|
7136
|
+
const result = options?.source === void 0 ? await this.vault.get(secretPath.vaultKey) : await this.vault.get(secretPath.vaultKey, {
|
|
7137
|
+
source: options.source
|
|
7138
|
+
});
|
|
6904
7139
|
if (!result.ok) {
|
|
6905
7140
|
return result;
|
|
6906
7141
|
}
|
|
@@ -6934,7 +7169,8 @@ var SecretsService = class {
|
|
|
6934
7169
|
}
|
|
6935
7170
|
const result = await this.vault.list({
|
|
6936
7171
|
prefix,
|
|
6937
|
-
removePrefix: true
|
|
7172
|
+
removePrefix: true,
|
|
7173
|
+
...options?.source === void 0 ? {} : { source: options.source }
|
|
6938
7174
|
});
|
|
6939
7175
|
if (!result.ok) {
|
|
6940
7176
|
return result;
|
|
@@ -6953,6 +7189,7 @@ var SecretsService = class {
|
|
|
6953
7189
|
prefix: "secrets/",
|
|
6954
7190
|
removePrefix: true,
|
|
6955
7191
|
limit: 1e3,
|
|
7192
|
+
source: "network",
|
|
6956
7193
|
...cursor === void 0 ? {} : { cursor }
|
|
6957
7194
|
});
|
|
6958
7195
|
if (!result.ok) {
|
|
@@ -7945,6 +8182,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
7945
8182
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7946
8183
|
0 && (module.exports = {
|
|
7947
8184
|
BaseService,
|
|
8185
|
+
CLEAR_PENDING_WARNING,
|
|
7948
8186
|
DECRYPT_ACTION,
|
|
7949
8187
|
DECRYPT_FACT_TYPE,
|
|
7950
8188
|
DECRYPT_RESULT_TYPE,
|
|
@@ -8012,6 +8250,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
8012
8250
|
buildDecryptInvocation,
|
|
8013
8251
|
buildNetworkId,
|
|
8014
8252
|
canonicalHashHex,
|
|
8253
|
+
canonicalReplicationIdentity,
|
|
8015
8254
|
canonicalSignedResponse,
|
|
8016
8255
|
canonicalizeEncryptionJson,
|
|
8017
8256
|
canonicalizeSecretScope,
|
|
@@ -8038,6 +8277,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
8038
8277
|
installTinyCloudDebugGlobals,
|
|
8039
8278
|
isNetworkId,
|
|
8040
8279
|
isStorageFullError,
|
|
8280
|
+
kvPrefixCovers,
|
|
8041
8281
|
networkDiscoveryKey,
|
|
8042
8282
|
networkError,
|
|
8043
8283
|
notFoundError,
|
|
@@ -8051,6 +8291,8 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
8051
8291
|
parseSecretCatalogKey,
|
|
8052
8292
|
parseStorageQuotaBytes,
|
|
8053
8293
|
permissionDeniedError,
|
|
8294
|
+
replicationIdentityKey,
|
|
8295
|
+
requiresSecretsOptIn,
|
|
8054
8296
|
resolveSecretListPrefix,
|
|
8055
8297
|
resolveSecretPath,
|
|
8056
8298
|
serviceError,
|