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