@tinycloud/operations 0.3.0 → 0.3.1-beta.1
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/artifacts.cjs +231 -5
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.js +231 -5
- package/dist/artifacts.js.map +1 -1
- package/dist/cli-runtime.cjs +232 -6
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +232 -6
- package/dist/cli-runtime.js.map +1 -1
- package/dist/index.cjs +232 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +232 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -2397,7 +2397,7 @@ function encOk(data) {
|
|
|
2397
2397
|
function encErr(error) {
|
|
2398
2398
|
return { ok: false, error };
|
|
2399
2399
|
}
|
|
2400
|
-
var import_zod, import_decrypt_transport_response_error, import_decrypt_transport_response_error2, import_decrypt_transport_response_error3, ErrorCodes, defaultRetryPolicy, TelemetryEvents, REDACTED, SAFE_NUMBER_FIELDS, SAFE_BOOLEAN_FIELDS, DEBUG_FLAG, MAX_EVENTS, TinyCloudDebugLogger, tinyCloudDebugLogger, ServiceErrorSchema, GenericResultSchema, KVResponseHeadersSchema, GenericKVResponseSchema, KVListResponseSchema, KVListResultSchema, ServiceRequestEventSchema, ServiceResponseEventSchema, ServiceErrorEventSchema, ServiceRetryEventSchema, TelemetrySpanEventSchema, RetryPolicySchema, ServiceSessionSchema, BaseService, PrefixedKVService, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, KVAction, KVService, SQLMigrations, DatabaseHandle, SQLAction, DDL_TOKENS, MIGRATIONS_TABLE, MIGRATIONS_SCHEMA, MIGRATIONS_META_NAMESPACE, MIGRATIONS_META_ID, SQLService, DuckDbDatabaseHandle, DuckDbAction, DuckDbService, AsyncQueue, HooksService, VaultVersionConfig, CURRENT_VAULT_VERSION, VaultHeaders, DB_NAME, DB_VERSION, STORE_NAME, WRAP_KEY_ID, DataVaultService, HEX, URN_PREFIX, NETWORK_NAME_RE, PKH_EIP155_DID_RE, NetworkIdError, DEFAULT_ENCRYPTION_ALG, ENVELOPE_VERSION, DEFAULT_KEY_VERSION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, EncryptionService;
|
|
2400
|
+
var import_zod, import_decrypt_transport_response_error, import_decrypt_transport_response_error2, import_decrypt_transport_response_error3, ErrorCodes, defaultRetryPolicy, TelemetryEvents, REDACTED, SAFE_NUMBER_FIELDS, SAFE_BOOLEAN_FIELDS, DEBUG_FLAG, MAX_EVENTS, TinyCloudDebugLogger, tinyCloudDebugLogger, ServiceErrorSchema, GenericResultSchema, KVResponseHeadersSchema, GenericKVResponseSchema, KVListResponseSchema, KVListResultSchema, ServiceRequestEventSchema, ServiceResponseEventSchema, ServiceErrorEventSchema, ServiceRetryEventSchema, TelemetrySpanEventSchema, RetryPolicySchema, ServiceSessionSchema, BaseService, PrefixedKVService, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, KVAction, MAX_KV_BATCH_READ_ITEMS, KVService, SQLMigrations, DatabaseHandle, SQLAction, DDL_TOKENS, MIGRATIONS_TABLE, MIGRATIONS_SCHEMA, MIGRATIONS_META_NAMESPACE, MIGRATIONS_META_ID, SQLService, DuckDbDatabaseHandle, DuckDbAction, DuckDbService, AsyncQueue, HooksService, VaultVersionConfig, CURRENT_VAULT_VERSION, VaultHeaders, DB_NAME, DB_VERSION, STORE_NAME, WRAP_KEY_ID, DataVaultService, HEX, URN_PREFIX, NETWORK_NAME_RE, PKH_EIP155_DID_RE, NetworkIdError, DEFAULT_ENCRYPTION_ALG, ENVELOPE_VERSION, DEFAULT_KEY_VERSION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, EncryptionService;
|
|
2401
2401
|
var init_dist2 = __esm({
|
|
2402
2402
|
"../sdk-services/dist/index.js"() {
|
|
2403
2403
|
"use strict";
|
|
@@ -2615,7 +2615,9 @@ var init_dist2 = __esm({
|
|
|
2615
2615
|
GenericKVResponseSchema = createKVResponseSchema(import_zod.z.unknown());
|
|
2616
2616
|
KVListResponseSchema = import_zod.z.object({
|
|
2617
2617
|
/** Array of keys matching the list criteria */
|
|
2618
|
-
keys: import_zod.z.array(import_zod.z.string())
|
|
2618
|
+
keys: import_zod.z.array(import_zod.z.string()),
|
|
2619
|
+
truncated: import_zod.z.boolean().optional(),
|
|
2620
|
+
nextCursor: import_zod.z.string().optional()
|
|
2619
2621
|
});
|
|
2620
2622
|
KVListResultSchema = createResultSchema(KVListResponseSchema);
|
|
2621
2623
|
ServiceRequestEventSchema = import_zod.z.object({
|
|
@@ -2915,6 +2917,20 @@ var init_dist2 = __esm({
|
|
|
2915
2917
|
const fullKey = this.getFullKey(key);
|
|
2916
2918
|
return this._kv.get(fullKey, { ...options, prefix: "" });
|
|
2917
2919
|
}
|
|
2920
|
+
async batchGet(keys, options) {
|
|
2921
|
+
const response = await this._kv.batchGet(
|
|
2922
|
+
keys.map((key) => this.getFullKey(key)),
|
|
2923
|
+
{ ...options, prefix: "" }
|
|
2924
|
+
);
|
|
2925
|
+
if (!response.ok) return response;
|
|
2926
|
+
return ok({
|
|
2927
|
+
...response.data,
|
|
2928
|
+
results: response.data.results.map((item, index) => ({
|
|
2929
|
+
...item,
|
|
2930
|
+
key: keys[index]
|
|
2931
|
+
}))
|
|
2932
|
+
});
|
|
2933
|
+
}
|
|
2918
2934
|
/**
|
|
2919
2935
|
* Store a value at a key.
|
|
2920
2936
|
*/
|
|
@@ -2959,6 +2975,20 @@ var init_dist2 = __esm({
|
|
|
2959
2975
|
const fullKey = this.getFullKey(key);
|
|
2960
2976
|
return this._kv.head(fullKey, { ...options, prefix: "" });
|
|
2961
2977
|
}
|
|
2978
|
+
async batchHead(keys, options) {
|
|
2979
|
+
const response = await this._kv.batchHead(
|
|
2980
|
+
keys.map((key) => this.getFullKey(key)),
|
|
2981
|
+
{ ...options, prefix: "" }
|
|
2982
|
+
);
|
|
2983
|
+
if (!response.ok) return response;
|
|
2984
|
+
return ok({
|
|
2985
|
+
...response.data,
|
|
2986
|
+
results: response.data.results.map((item, index) => ({
|
|
2987
|
+
...item,
|
|
2988
|
+
key: keys[index]
|
|
2989
|
+
}))
|
|
2990
|
+
});
|
|
2991
|
+
}
|
|
2962
2992
|
/**
|
|
2963
2993
|
* Create a short-lived signed URL for reading a KV object.
|
|
2964
2994
|
*/
|
|
@@ -2983,6 +3013,7 @@ var init_dist2 = __esm({
|
|
|
2983
3013
|
DELETE: "tinycloud.kv/del",
|
|
2984
3014
|
HEAD: "tinycloud.kv/metadata"
|
|
2985
3015
|
};
|
|
3016
|
+
MAX_KV_BATCH_READ_ITEMS = 100;
|
|
2986
3017
|
KVService = class extends BaseService {
|
|
2987
3018
|
/**
|
|
2988
3019
|
* Create a new KVService instance.
|
|
@@ -3211,6 +3242,173 @@ var init_dist2 = __esm({
|
|
|
3211
3242
|
get: (name) => headers.get(name)
|
|
3212
3243
|
};
|
|
3213
3244
|
}
|
|
3245
|
+
createBatchResponseHeaders(values) {
|
|
3246
|
+
const normalized = new Map(
|
|
3247
|
+
Object.entries(values).map(([name, value]) => [name.toLowerCase(), value])
|
|
3248
|
+
);
|
|
3249
|
+
return this.createResponseHeaders({
|
|
3250
|
+
get: (name) => normalized.get(name.toLowerCase()) ?? null
|
|
3251
|
+
});
|
|
3252
|
+
}
|
|
3253
|
+
parseBatchValue(dataBase64, headers, raw = false, binary = false) {
|
|
3254
|
+
const encoded = globalThis.atob(dataBase64);
|
|
3255
|
+
const bytes = Uint8Array.from(encoded, (character) => character.charCodeAt(0));
|
|
3256
|
+
if (binary) return bytes;
|
|
3257
|
+
const text = new TextDecoder().decode(bytes);
|
|
3258
|
+
if (raw) return text;
|
|
3259
|
+
const contentType = Object.entries(headers).find(
|
|
3260
|
+
([name]) => name.toLowerCase() === "content-type"
|
|
3261
|
+
)?.[1];
|
|
3262
|
+
return contentType?.includes("application/json") ? JSON.parse(text) : text;
|
|
3263
|
+
}
|
|
3264
|
+
normalizeBatchReadResponse(data, paths, requireData) {
|
|
3265
|
+
if (!data || typeof data !== "object") return void 0;
|
|
3266
|
+
const response = data;
|
|
3267
|
+
if (!Array.isArray(response.results) || response.results.length !== paths.length) {
|
|
3268
|
+
return void 0;
|
|
3269
|
+
}
|
|
3270
|
+
for (let index = 0; index < response.results.length; index++) {
|
|
3271
|
+
const item = response.results[index];
|
|
3272
|
+
if (!item || typeof item !== "object" || item.key !== paths[index] || typeof item.ok !== "boolean") {
|
|
3273
|
+
return void 0;
|
|
3274
|
+
}
|
|
3275
|
+
if (item.ok && (!item.headers || typeof item.headers !== "object" || Object.values(item.headers).some((value) => typeof value !== "string") || requireData && typeof item.dataBase64 !== "string")) {
|
|
3276
|
+
return void 0;
|
|
3277
|
+
}
|
|
3278
|
+
if (!item.ok && (!item.error || typeof item.error.code !== "string" || typeof item.error.message !== "string")) {
|
|
3279
|
+
return void 0;
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
return response;
|
|
3283
|
+
}
|
|
3284
|
+
async batchRead(keys, action, options) {
|
|
3285
|
+
if (!this.requireAuth()) return err(authRequiredError("kv"));
|
|
3286
|
+
if (keys.length === 0) return ok({ results: [], count: 0 });
|
|
3287
|
+
if (keys.length > MAX_KV_BATCH_READ_ITEMS) {
|
|
3288
|
+
return err(serviceError(
|
|
3289
|
+
ErrorCodes.INVALID_INPUT,
|
|
3290
|
+
`KV batch reads accept at most ${MAX_KV_BATCH_READ_ITEMS} keys`,
|
|
3291
|
+
"kv"
|
|
3292
|
+
));
|
|
3293
|
+
}
|
|
3294
|
+
if (keys.length === 1) {
|
|
3295
|
+
const key = keys[0];
|
|
3296
|
+
const result = action === KVAction.GET ? await this.get(key, options) : await this.head(key, options);
|
|
3297
|
+
return ok({
|
|
3298
|
+
results: [{ key, result }],
|
|
3299
|
+
count: 1
|
|
3300
|
+
});
|
|
3301
|
+
}
|
|
3302
|
+
if (!this.context.invokeAny) {
|
|
3303
|
+
return err(serviceError(
|
|
3304
|
+
ErrorCodes.INVALID_INPUT,
|
|
3305
|
+
"KV batch reads require SDK runtime support for multi-resource invocations",
|
|
3306
|
+
"kv"
|
|
3307
|
+
));
|
|
3308
|
+
}
|
|
3309
|
+
const getOptions = action === KVAction.GET ? options : void 0;
|
|
3310
|
+
if (getOptions?.maxResponseBytes !== void 0 && (!Number.isSafeInteger(getOptions.maxResponseBytes) || getOptions.maxResponseBytes <= 0)) {
|
|
3311
|
+
return err(serviceError(
|
|
3312
|
+
ErrorCodes.INVALID_INPUT,
|
|
3313
|
+
"KV maxResponseBytes must be a positive safe integer",
|
|
3314
|
+
"kv"
|
|
3315
|
+
));
|
|
3316
|
+
}
|
|
3317
|
+
const paths = keys.map((key) => this.getFullPath(key, options?.prefix));
|
|
3318
|
+
if (new Set(paths).size !== paths.length) {
|
|
3319
|
+
return err(serviceError(
|
|
3320
|
+
ErrorCodes.INVALID_INPUT,
|
|
3321
|
+
"KV batch read received duplicate keys after prefix resolution",
|
|
3322
|
+
"kv"
|
|
3323
|
+
));
|
|
3324
|
+
}
|
|
3325
|
+
try {
|
|
3326
|
+
const session = this.context.session;
|
|
3327
|
+
const invocationHeaders = this.context.invokeAny(
|
|
3328
|
+
session,
|
|
3329
|
+
paths.map((path) => ({
|
|
3330
|
+
spaceId: session.spaceId,
|
|
3331
|
+
service: "kv",
|
|
3332
|
+
path,
|
|
3333
|
+
action
|
|
3334
|
+
}))
|
|
3335
|
+
);
|
|
3336
|
+
const limitHeaders = {};
|
|
3337
|
+
if (getOptions?.maxResponseBytes !== void 0) {
|
|
3338
|
+
limitHeaders["x-tinycloud-max-response-bytes"] = String(
|
|
3339
|
+
getOptions.maxResponseBytes
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
const headers = Array.isArray(invocationHeaders) ? [...invocationHeaders, ...Object.entries(limitHeaders)] : { ...invocationHeaders, ...limitHeaders };
|
|
3343
|
+
const response = await this.context.fetch(`${this.host}/invoke`, {
|
|
3344
|
+
method: "POST",
|
|
3345
|
+
headers,
|
|
3346
|
+
signal: this.combineSignals(options?.signal)
|
|
3347
|
+
});
|
|
3348
|
+
if (!response.ok) {
|
|
3349
|
+
const errorText = await response.text();
|
|
3350
|
+
if (response.status === 401 || response.status === 403) {
|
|
3351
|
+
const { resource, action: requiredAction } = parseAuthError(errorText);
|
|
3352
|
+
return err(authUnauthorizedError("kv", errorText, {
|
|
3353
|
+
status: response.status,
|
|
3354
|
+
...requiredAction && { requiredAction },
|
|
3355
|
+
...resource && { resource }
|
|
3356
|
+
}));
|
|
3357
|
+
}
|
|
3358
|
+
if (response.status === 413) {
|
|
3359
|
+
return err(serviceError(
|
|
3360
|
+
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
3361
|
+
"A KV batch value exceeds the requested response limit",
|
|
3362
|
+
"kv",
|
|
3363
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3364
|
+
));
|
|
3365
|
+
}
|
|
3366
|
+
return err(serviceError(
|
|
3367
|
+
ErrorCodes.NETWORK_ERROR,
|
|
3368
|
+
`Failed to batch read ${keys.length} key(s): ${response.status} - ${errorText}`,
|
|
3369
|
+
"kv",
|
|
3370
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
3371
|
+
));
|
|
3372
|
+
}
|
|
3373
|
+
const payload = this.normalizeBatchReadResponse(
|
|
3374
|
+
await response.json(),
|
|
3375
|
+
paths,
|
|
3376
|
+
action === KVAction.GET
|
|
3377
|
+
);
|
|
3378
|
+
if (!payload) {
|
|
3379
|
+
return err(serviceError(
|
|
3380
|
+
ErrorCodes.NETWORK_ERROR,
|
|
3381
|
+
"KV batch read response did not match the requested keys",
|
|
3382
|
+
"kv"
|
|
3383
|
+
));
|
|
3384
|
+
}
|
|
3385
|
+
const results = payload.results.map((item, index) => {
|
|
3386
|
+
if (!item.ok) {
|
|
3387
|
+
return {
|
|
3388
|
+
key: keys[index],
|
|
3389
|
+
result: err(serviceError(item.error.code, item.error.message, "kv"))
|
|
3390
|
+
};
|
|
3391
|
+
}
|
|
3392
|
+
const headers2 = item.headers;
|
|
3393
|
+
const data = action === KVAction.HEAD ? void 0 : this.parseBatchValue(
|
|
3394
|
+
item.dataBase64,
|
|
3395
|
+
headers2,
|
|
3396
|
+
getOptions?.raw,
|
|
3397
|
+
getOptions?.binary
|
|
3398
|
+
);
|
|
3399
|
+
return {
|
|
3400
|
+
key: keys[index],
|
|
3401
|
+
result: ok({
|
|
3402
|
+
data,
|
|
3403
|
+
headers: this.createBatchResponseHeaders(headers2)
|
|
3404
|
+
})
|
|
3405
|
+
};
|
|
3406
|
+
});
|
|
3407
|
+
return ok({ results, count: results.length });
|
|
3408
|
+
} catch (error) {
|
|
3409
|
+
return err(wrapError("kv", error));
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3214
3412
|
/**
|
|
3215
3413
|
* Parse response body based on content type.
|
|
3216
3414
|
*
|
|
@@ -3357,6 +3555,13 @@ var init_dist2 = __esm({
|
|
|
3357
3555
|
}
|
|
3358
3556
|
});
|
|
3359
3557
|
}
|
|
3558
|
+
async batchGet(keys, options) {
|
|
3559
|
+
return this.withTelemetry(
|
|
3560
|
+
"batchGet",
|
|
3561
|
+
String(keys.length),
|
|
3562
|
+
() => this.batchRead(keys, KVAction.GET, options)
|
|
3563
|
+
);
|
|
3564
|
+
}
|
|
3360
3565
|
/**
|
|
3361
3566
|
* Store a value at a key.
|
|
3362
3567
|
*/
|
|
@@ -3564,7 +3769,10 @@ var init_dist2 = __esm({
|
|
|
3564
3769
|
KVAction.LIST,
|
|
3565
3770
|
void 0,
|
|
3566
3771
|
options?.signal,
|
|
3567
|
-
options?.limit === void 0 ? void 0 : {
|
|
3772
|
+
options?.limit === void 0 && options?.cursor === void 0 ? void 0 : {
|
|
3773
|
+
...options?.limit === void 0 ? {} : { "x-tinycloud-limit": String(options.limit) },
|
|
3774
|
+
...options?.cursor === void 0 ? {} : { "x-tinycloud-cursor": options.cursor }
|
|
3775
|
+
}
|
|
3568
3776
|
);
|
|
3569
3777
|
if (!response.ok) {
|
|
3570
3778
|
if (response.status === 401) {
|
|
@@ -3596,7 +3804,8 @@ var init_dist2 = __esm({
|
|
|
3596
3804
|
}
|
|
3597
3805
|
return ok({
|
|
3598
3806
|
keys,
|
|
3599
|
-
...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" }
|
|
3807
|
+
...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" },
|
|
3808
|
+
...response.headers.get("x-tinycloud-next-cursor") === null ? {} : { nextCursor: response.headers.get("x-tinycloud-next-cursor") ?? void 0 }
|
|
3600
3809
|
});
|
|
3601
3810
|
} catch (error) {
|
|
3602
3811
|
return err(wrapError("kv", error));
|
|
@@ -3716,6 +3925,13 @@ var init_dist2 = __esm({
|
|
|
3716
3925
|
}
|
|
3717
3926
|
});
|
|
3718
3927
|
}
|
|
3928
|
+
async batchHead(keys, options) {
|
|
3929
|
+
return this.withTelemetry(
|
|
3930
|
+
"batchHead",
|
|
3931
|
+
String(keys.length),
|
|
3932
|
+
() => this.batchRead(keys, KVAction.HEAD, options)
|
|
3933
|
+
);
|
|
3934
|
+
}
|
|
3719
3935
|
/**
|
|
3720
3936
|
* Create a short-lived signed URL for reading a KV object.
|
|
3721
3937
|
*/
|
|
@@ -5655,6 +5871,10 @@ var init_dist2 = __esm({
|
|
|
5655
5871
|
* @returns Result with array of key names (vault/ prefix stripped)
|
|
5656
5872
|
*/
|
|
5657
5873
|
async list(options) {
|
|
5874
|
+
const page = await this.listPage(options);
|
|
5875
|
+
return page.ok ? { ok: true, data: page.data.keys } : page;
|
|
5876
|
+
}
|
|
5877
|
+
async listPage(options) {
|
|
5658
5878
|
return this.withTelemetry("list", options?.prefix, async () => {
|
|
5659
5879
|
if (!this.isUnlocked) {
|
|
5660
5880
|
return vaultError({
|
|
@@ -5672,7 +5892,9 @@ var init_dist2 = __esm({
|
|
|
5672
5892
|
const listPrefix = options?.prefix ? `vault/${options.prefix}` : "vault/";
|
|
5673
5893
|
const listResult = await this.tc.kv.list({
|
|
5674
5894
|
prefix: listPrefix,
|
|
5675
|
-
removePrefix: true
|
|
5895
|
+
removePrefix: true,
|
|
5896
|
+
...options?.limit === void 0 ? {} : { limit: options.limit },
|
|
5897
|
+
...options?.cursor === void 0 ? {} : { cursor: options.cursor }
|
|
5676
5898
|
});
|
|
5677
5899
|
if (!listResult.ok) {
|
|
5678
5900
|
return vaultError({
|
|
@@ -5689,7 +5911,11 @@ var init_dist2 = __esm({
|
|
|
5689
5911
|
(k) => k.startsWith(userPrefix) ? k.slice(userPrefix.length) : k
|
|
5690
5912
|
);
|
|
5691
5913
|
}
|
|
5692
|
-
return ok(
|
|
5914
|
+
return ok({
|
|
5915
|
+
keys,
|
|
5916
|
+
truncated: listResult.data.truncated === true,
|
|
5917
|
+
...listResult.data.nextCursor === void 0 ? {} : { nextCursor: listResult.data.nextCursor }
|
|
5918
|
+
});
|
|
5693
5919
|
} catch (error) {
|
|
5694
5920
|
return vaultError({
|
|
5695
5921
|
code: "STORAGE_ERROR",
|