@tinycloud/sdk-services 2.8.0 → 2.10.0-beta.0
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/index.cjs +210 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +210 -0
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +210 -0
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +28 -1
- package/dist/kv/index.d.ts +28 -1
- package/dist/kv/index.js +210 -0
- package/dist/kv/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchRespo
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { B as BaseService } from './BaseService-DxSU4U-v.cjs';
|
|
5
5
|
import { IKVService } from './kv/index.cjs';
|
|
6
|
-
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.cjs';
|
|
6
|
+
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
7
|
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';
|
|
8
8
|
import { IEncryptionService, DecryptCapabilityProof } from './encryption/index.cjs';
|
|
9
9
|
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
|
@@ -3,7 +3,7 @@ export { g as ErrorCode, h as ErrorCodes, i as FetchRequestInit, j as FetchRespo
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { B as BaseService } from './BaseService-BiYeqCRT.js';
|
|
5
5
|
import { IKVService } from './kv/index.js';
|
|
6
|
-
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVBatchPutItem, KVBatchPutOptions, KVBatchPutResponse, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.js';
|
|
6
|
+
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
7
|
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';
|
|
8
8
|
import { IEncryptionService, DecryptCapabilityProof } from './encryption/index.js';
|
|
9
9
|
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
|
@@ -1277,6 +1277,20 @@ var PrefixedKVService = class _PrefixedKVService {
|
|
|
1277
1277
|
const fullKey = this.getFullKey(key);
|
|
1278
1278
|
return this._kv.get(fullKey, { ...options, prefix: "" });
|
|
1279
1279
|
}
|
|
1280
|
+
async batchGet(keys, options) {
|
|
1281
|
+
const response = await this._kv.batchGet(
|
|
1282
|
+
keys.map((key) => this.getFullKey(key)),
|
|
1283
|
+
{ ...options, prefix: "" }
|
|
1284
|
+
);
|
|
1285
|
+
if (!response.ok) return response;
|
|
1286
|
+
return ok({
|
|
1287
|
+
...response.data,
|
|
1288
|
+
results: response.data.results.map((item, index) => ({
|
|
1289
|
+
...item,
|
|
1290
|
+
key: keys[index]
|
|
1291
|
+
}))
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1280
1294
|
/**
|
|
1281
1295
|
* Store a value at a key.
|
|
1282
1296
|
*/
|
|
@@ -1321,6 +1335,20 @@ var PrefixedKVService = class _PrefixedKVService {
|
|
|
1321
1335
|
const fullKey = this.getFullKey(key);
|
|
1322
1336
|
return this._kv.head(fullKey, { ...options, prefix: "" });
|
|
1323
1337
|
}
|
|
1338
|
+
async batchHead(keys, options) {
|
|
1339
|
+
const response = await this._kv.batchHead(
|
|
1340
|
+
keys.map((key) => this.getFullKey(key)),
|
|
1341
|
+
{ ...options, prefix: "" }
|
|
1342
|
+
);
|
|
1343
|
+
if (!response.ok) return response;
|
|
1344
|
+
return ok({
|
|
1345
|
+
...response.data,
|
|
1346
|
+
results: response.data.results.map((item, index) => ({
|
|
1347
|
+
...item,
|
|
1348
|
+
key: keys[index]
|
|
1349
|
+
}))
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1324
1352
|
/**
|
|
1325
1353
|
* Create a short-lived signed URL for reading a KV object.
|
|
1326
1354
|
*/
|
|
@@ -1349,6 +1377,7 @@ var KVAction = {
|
|
|
1349
1377
|
};
|
|
1350
1378
|
|
|
1351
1379
|
// src/kv/KVService.ts
|
|
1380
|
+
var MAX_KV_BATCH_READ_ITEMS = 100;
|
|
1352
1381
|
function encodeKvBatchPartName(path) {
|
|
1353
1382
|
return encodeURIComponent(path).replace(
|
|
1354
1383
|
/[!'()*]/g,
|
|
@@ -1583,6 +1612,173 @@ var KVService = class extends BaseService {
|
|
|
1583
1612
|
get: (name) => headers.get(name)
|
|
1584
1613
|
};
|
|
1585
1614
|
}
|
|
1615
|
+
createBatchResponseHeaders(values) {
|
|
1616
|
+
const normalized = new Map(
|
|
1617
|
+
Object.entries(values).map(([name, value]) => [name.toLowerCase(), value])
|
|
1618
|
+
);
|
|
1619
|
+
return this.createResponseHeaders({
|
|
1620
|
+
get: (name) => normalized.get(name.toLowerCase()) ?? null
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
parseBatchValue(dataBase64, headers, raw = false, binary = false) {
|
|
1624
|
+
const encoded = globalThis.atob(dataBase64);
|
|
1625
|
+
const bytes = Uint8Array.from(encoded, (character) => character.charCodeAt(0));
|
|
1626
|
+
if (binary) return bytes;
|
|
1627
|
+
const text = new TextDecoder().decode(bytes);
|
|
1628
|
+
if (raw) return text;
|
|
1629
|
+
const contentType = Object.entries(headers).find(
|
|
1630
|
+
([name]) => name.toLowerCase() === "content-type"
|
|
1631
|
+
)?.[1];
|
|
1632
|
+
return contentType?.includes("application/json") ? JSON.parse(text) : text;
|
|
1633
|
+
}
|
|
1634
|
+
normalizeBatchReadResponse(data, paths, requireData) {
|
|
1635
|
+
if (!data || typeof data !== "object") return void 0;
|
|
1636
|
+
const response = data;
|
|
1637
|
+
if (!Array.isArray(response.results) || response.results.length !== paths.length) {
|
|
1638
|
+
return void 0;
|
|
1639
|
+
}
|
|
1640
|
+
for (let index = 0; index < response.results.length; index++) {
|
|
1641
|
+
const item = response.results[index];
|
|
1642
|
+
if (!item || typeof item !== "object" || item.key !== paths[index] || typeof item.ok !== "boolean") {
|
|
1643
|
+
return void 0;
|
|
1644
|
+
}
|
|
1645
|
+
if (item.ok && (!item.headers || typeof item.headers !== "object" || Object.values(item.headers).some((value) => typeof value !== "string") || requireData && typeof item.dataBase64 !== "string")) {
|
|
1646
|
+
return void 0;
|
|
1647
|
+
}
|
|
1648
|
+
if (!item.ok && (!item.error || typeof item.error.code !== "string" || typeof item.error.message !== "string")) {
|
|
1649
|
+
return void 0;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return response;
|
|
1653
|
+
}
|
|
1654
|
+
async batchRead(keys, action, options) {
|
|
1655
|
+
if (!this.requireAuth()) return err(authRequiredError("kv"));
|
|
1656
|
+
if (keys.length === 0) return ok({ results: [], count: 0 });
|
|
1657
|
+
if (keys.length > MAX_KV_BATCH_READ_ITEMS) {
|
|
1658
|
+
return err(serviceError(
|
|
1659
|
+
ErrorCodes.INVALID_INPUT,
|
|
1660
|
+
`KV batch reads accept at most ${MAX_KV_BATCH_READ_ITEMS} keys`,
|
|
1661
|
+
"kv"
|
|
1662
|
+
));
|
|
1663
|
+
}
|
|
1664
|
+
if (keys.length === 1) {
|
|
1665
|
+
const key = keys[0];
|
|
1666
|
+
const result = action === KVAction.GET ? await this.get(key, options) : await this.head(key, options);
|
|
1667
|
+
return ok({
|
|
1668
|
+
results: [{ key, result }],
|
|
1669
|
+
count: 1
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
if (!this.context.invokeAny) {
|
|
1673
|
+
return err(serviceError(
|
|
1674
|
+
ErrorCodes.INVALID_INPUT,
|
|
1675
|
+
"KV batch reads require SDK runtime support for multi-resource invocations",
|
|
1676
|
+
"kv"
|
|
1677
|
+
));
|
|
1678
|
+
}
|
|
1679
|
+
const getOptions = action === KVAction.GET ? options : void 0;
|
|
1680
|
+
if (getOptions?.maxResponseBytes !== void 0 && (!Number.isSafeInteger(getOptions.maxResponseBytes) || getOptions.maxResponseBytes <= 0)) {
|
|
1681
|
+
return err(serviceError(
|
|
1682
|
+
ErrorCodes.INVALID_INPUT,
|
|
1683
|
+
"KV maxResponseBytes must be a positive safe integer",
|
|
1684
|
+
"kv"
|
|
1685
|
+
));
|
|
1686
|
+
}
|
|
1687
|
+
const paths = keys.map((key) => this.getFullPath(key, options?.prefix));
|
|
1688
|
+
if (new Set(paths).size !== paths.length) {
|
|
1689
|
+
return err(serviceError(
|
|
1690
|
+
ErrorCodes.INVALID_INPUT,
|
|
1691
|
+
"KV batch read received duplicate keys after prefix resolution",
|
|
1692
|
+
"kv"
|
|
1693
|
+
));
|
|
1694
|
+
}
|
|
1695
|
+
try {
|
|
1696
|
+
const session = this.context.session;
|
|
1697
|
+
const invocationHeaders = this.context.invokeAny(
|
|
1698
|
+
session,
|
|
1699
|
+
paths.map((path) => ({
|
|
1700
|
+
spaceId: session.spaceId,
|
|
1701
|
+
service: "kv",
|
|
1702
|
+
path,
|
|
1703
|
+
action
|
|
1704
|
+
}))
|
|
1705
|
+
);
|
|
1706
|
+
const limitHeaders = {};
|
|
1707
|
+
if (getOptions?.maxResponseBytes !== void 0) {
|
|
1708
|
+
limitHeaders["x-tinycloud-max-response-bytes"] = String(
|
|
1709
|
+
getOptions.maxResponseBytes
|
|
1710
|
+
);
|
|
1711
|
+
}
|
|
1712
|
+
const headers = Array.isArray(invocationHeaders) ? [...invocationHeaders, ...Object.entries(limitHeaders)] : { ...invocationHeaders, ...limitHeaders };
|
|
1713
|
+
const response = await this.context.fetch(`${this.host}/invoke`, {
|
|
1714
|
+
method: "POST",
|
|
1715
|
+
headers,
|
|
1716
|
+
signal: this.combineSignals(options?.signal)
|
|
1717
|
+
});
|
|
1718
|
+
if (!response.ok) {
|
|
1719
|
+
const errorText = await response.text();
|
|
1720
|
+
if (response.status === 401 || response.status === 403) {
|
|
1721
|
+
const { resource, action: requiredAction } = parseAuthError(errorText);
|
|
1722
|
+
return err(authUnauthorizedError("kv", errorText, {
|
|
1723
|
+
status: response.status,
|
|
1724
|
+
...requiredAction && { requiredAction },
|
|
1725
|
+
...resource && { resource }
|
|
1726
|
+
}));
|
|
1727
|
+
}
|
|
1728
|
+
if (response.status === 413) {
|
|
1729
|
+
return err(serviceError(
|
|
1730
|
+
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
1731
|
+
"A KV batch value exceeds the requested response limit",
|
|
1732
|
+
"kv",
|
|
1733
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1734
|
+
));
|
|
1735
|
+
}
|
|
1736
|
+
return err(serviceError(
|
|
1737
|
+
ErrorCodes.NETWORK_ERROR,
|
|
1738
|
+
`Failed to batch read ${keys.length} key(s): ${response.status} - ${errorText}`,
|
|
1739
|
+
"kv",
|
|
1740
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1741
|
+
));
|
|
1742
|
+
}
|
|
1743
|
+
const payload = this.normalizeBatchReadResponse(
|
|
1744
|
+
await response.json(),
|
|
1745
|
+
paths,
|
|
1746
|
+
action === KVAction.GET
|
|
1747
|
+
);
|
|
1748
|
+
if (!payload) {
|
|
1749
|
+
return err(serviceError(
|
|
1750
|
+
ErrorCodes.NETWORK_ERROR,
|
|
1751
|
+
"KV batch read response did not match the requested keys",
|
|
1752
|
+
"kv"
|
|
1753
|
+
));
|
|
1754
|
+
}
|
|
1755
|
+
const results = payload.results.map((item, index) => {
|
|
1756
|
+
if (!item.ok) {
|
|
1757
|
+
return {
|
|
1758
|
+
key: keys[index],
|
|
1759
|
+
result: err(serviceError(item.error.code, item.error.message, "kv"))
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
const headers2 = item.headers;
|
|
1763
|
+
const data = action === KVAction.HEAD ? void 0 : this.parseBatchValue(
|
|
1764
|
+
item.dataBase64,
|
|
1765
|
+
headers2,
|
|
1766
|
+
getOptions?.raw,
|
|
1767
|
+
getOptions?.binary
|
|
1768
|
+
);
|
|
1769
|
+
return {
|
|
1770
|
+
key: keys[index],
|
|
1771
|
+
result: ok({
|
|
1772
|
+
data,
|
|
1773
|
+
headers: this.createBatchResponseHeaders(headers2)
|
|
1774
|
+
})
|
|
1775
|
+
};
|
|
1776
|
+
});
|
|
1777
|
+
return ok({ results, count: results.length });
|
|
1778
|
+
} catch (error) {
|
|
1779
|
+
return err(wrapError("kv", error));
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1586
1782
|
/**
|
|
1587
1783
|
* Parse response body based on content type.
|
|
1588
1784
|
*
|
|
@@ -1729,6 +1925,13 @@ var KVService = class extends BaseService {
|
|
|
1729
1925
|
}
|
|
1730
1926
|
});
|
|
1731
1927
|
}
|
|
1928
|
+
async batchGet(keys, options) {
|
|
1929
|
+
return this.withTelemetry(
|
|
1930
|
+
"batchGet",
|
|
1931
|
+
String(keys.length),
|
|
1932
|
+
() => this.batchRead(keys, KVAction.GET, options)
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1732
1935
|
/**
|
|
1733
1936
|
* Store a value at a key.
|
|
1734
1937
|
*/
|
|
@@ -2088,6 +2291,13 @@ var KVService = class extends BaseService {
|
|
|
2088
2291
|
}
|
|
2089
2292
|
});
|
|
2090
2293
|
}
|
|
2294
|
+
async batchHead(keys, options) {
|
|
2295
|
+
return this.withTelemetry(
|
|
2296
|
+
"batchHead",
|
|
2297
|
+
String(keys.length),
|
|
2298
|
+
() => this.batchRead(keys, KVAction.HEAD, options)
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2091
2301
|
/**
|
|
2092
2302
|
* Create a short-lived signed URL for reading a KV object.
|
|
2093
2303
|
*/
|