@tinycloud/sdk-services 2.2.0-beta.10 → 2.2.0-beta.13
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 +157 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +156 -21
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +116 -0
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +99 -1
- package/dist/kv/index.d.ts +99 -1
- package/dist/kv/index.js +115 -0
- package/dist/kv/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { I as IServiceContext, a as InvokeFunction, b as InvokeAnyFunction, F as
|
|
|
2
2
|
export { E as ErrorCode, g as ErrorCodes, h as EventHandler, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, T as TelemetryEvents, s as defaultRetryPolicy, t as err, u as ok, v as serviceError } from './BaseService-BiS6HRwE.cjs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { IKVService } from './kv/index.cjs';
|
|
5
|
-
export { IPrefixedKVService, KVAction, KVActionType, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, PrefixedKVService } from './kv/index.cjs';
|
|
5
|
+
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.cjs';
|
|
6
6
|
export { BatchOptions, BatchResponse, DatabaseHandle, ExecuteOptions, ExecuteResponse, IDatabaseHandle, ISQLService, QueryOptions, QueryResponse, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SqlStatement, SqlValue } from './sql/index.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -1747,6 +1747,7 @@ declare class DataVaultService extends BaseService implements IDataVaultService
|
|
|
1747
1747
|
private encryptionIdentity;
|
|
1748
1748
|
private _isUnlocked;
|
|
1749
1749
|
private vaultConfig;
|
|
1750
|
+
private unlockInFlight;
|
|
1750
1751
|
/**
|
|
1751
1752
|
* Create a new DataVaultService instance.
|
|
1752
1753
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { I as IServiceContext, a as InvokeFunction, b as InvokeAnyFunction, F as
|
|
|
2
2
|
export { E as ErrorCode, g as ErrorCodes, h as EventHandler, i as FetchRequestInit, j as FetchResponse, k as InvocationFact, l as InvocationFacts, m as InvokeAnyEntry, n as ServiceErrorEvent, o as ServiceHeaders, p as ServiceRequestEvent, q as ServiceResponseEvent, r as ServiceRetryEvent, T as TelemetryEvents, s as defaultRetryPolicy, t as err, u as ok, v as serviceError } from './BaseService-BiS6HRwE.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { IKVService } from './kv/index.js';
|
|
5
|
-
export { IPrefixedKVService, KVAction, KVActionType, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, PrefixedKVService } from './kv/index.js';
|
|
5
|
+
export { DEFAULT_SIGNED_READ_URL_EXPIRY_MS, IPrefixedKVService, KVAction, KVActionType, KVCreateSignedReadUrlOptions, KVDeleteOptions, KVGetOptions, KVHeadOptions, KVListOptions, KVListResponse, KVPutOptions, KVResponse, KVResponseHeaders, KVService, KVServiceConfig, KVSignedReadUrlResponse, PrefixedKVService } from './kv/index.js';
|
|
6
6
|
export { BatchOptions, BatchResponse, DatabaseHandle, ExecuteOptions, ExecuteResponse, IDatabaseHandle, ISQLService, QueryOptions, QueryResponse, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SqlStatement, SqlValue } from './sql/index.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -1747,6 +1747,7 @@ declare class DataVaultService extends BaseService implements IDataVaultService
|
|
|
1747
1747
|
private encryptionIdentity;
|
|
1748
1748
|
private _isUnlocked;
|
|
1749
1749
|
private vaultConfig;
|
|
1750
|
+
private unlockInFlight;
|
|
1750
1751
|
/**
|
|
1751
1752
|
* Create a new DataVaultService instance.
|
|
1752
1753
|
*
|
package/dist/index.js
CHANGED
|
@@ -818,6 +818,13 @@ var PrefixedKVService = class _PrefixedKVService {
|
|
|
818
818
|
const fullKey = this.getFullKey(key);
|
|
819
819
|
return this._kv.head(fullKey, { ...options, prefix: "" });
|
|
820
820
|
}
|
|
821
|
+
/**
|
|
822
|
+
* Create a short-lived signed URL for reading a KV object.
|
|
823
|
+
*/
|
|
824
|
+
async createSignedReadUrl(key, options) {
|
|
825
|
+
const fullKey = this.getFullKey(key);
|
|
826
|
+
return this._kv.createSignedReadUrl(fullKey, { ...options, prefix: "" });
|
|
827
|
+
}
|
|
821
828
|
/**
|
|
822
829
|
* Create a nested prefix-scoped view.
|
|
823
830
|
*/
|
|
@@ -829,6 +836,7 @@ var PrefixedKVService = class _PrefixedKVService {
|
|
|
829
836
|
};
|
|
830
837
|
|
|
831
838
|
// src/kv/types.ts
|
|
839
|
+
var DEFAULT_SIGNED_READ_URL_EXPIRY_MS = 5 * 60 * 1e3;
|
|
832
840
|
var KVAction = {
|
|
833
841
|
GET: "tinycloud.kv/get",
|
|
834
842
|
PUT: "tinycloud.kv/put",
|
|
@@ -913,6 +921,15 @@ var KVService = class extends BaseService {
|
|
|
913
921
|
get host() {
|
|
914
922
|
return this.context.hosts[0];
|
|
915
923
|
}
|
|
924
|
+
withJsonContentType(headers) {
|
|
925
|
+
if (Array.isArray(headers)) {
|
|
926
|
+
return [...headers, ["content-type", "application/json"]];
|
|
927
|
+
}
|
|
928
|
+
return {
|
|
929
|
+
...headers,
|
|
930
|
+
"content-type": "application/json"
|
|
931
|
+
};
|
|
932
|
+
}
|
|
916
933
|
/**
|
|
917
934
|
* Execute an invoke operation.
|
|
918
935
|
*
|
|
@@ -982,6 +999,48 @@ var KVService = class extends BaseService {
|
|
|
982
999
|
return text;
|
|
983
1000
|
}
|
|
984
1001
|
}
|
|
1002
|
+
async createSignedReadUrlError(response, key) {
|
|
1003
|
+
let errorText = response.statusText;
|
|
1004
|
+
try {
|
|
1005
|
+
const text = await response.text();
|
|
1006
|
+
if (text) {
|
|
1007
|
+
errorText = text;
|
|
1008
|
+
}
|
|
1009
|
+
} catch {
|
|
1010
|
+
}
|
|
1011
|
+
if (response.status === 401 || response.status === 403) {
|
|
1012
|
+
const { resource, action } = parseAuthError(errorText);
|
|
1013
|
+
return err(authUnauthorizedError("kv", errorText, {
|
|
1014
|
+
status: response.status,
|
|
1015
|
+
...action && { requiredAction: action },
|
|
1016
|
+
...resource && { resource }
|
|
1017
|
+
}));
|
|
1018
|
+
}
|
|
1019
|
+
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
1020
|
+
return err(
|
|
1021
|
+
serviceError(
|
|
1022
|
+
code,
|
|
1023
|
+
`Failed to create signed read URL for key "${key}": ${response.status} - ${errorText}`,
|
|
1024
|
+
"kv",
|
|
1025
|
+
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1026
|
+
)
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
normalizeSignedReadUrlResponse(data) {
|
|
1030
|
+
if (!data || typeof data !== "object") {
|
|
1031
|
+
return void 0;
|
|
1032
|
+
}
|
|
1033
|
+
const response = data;
|
|
1034
|
+
if (typeof response.url !== "string" || typeof response.ticketId !== "string" || typeof response.expiresAt !== "string") {
|
|
1035
|
+
return void 0;
|
|
1036
|
+
}
|
|
1037
|
+
return {
|
|
1038
|
+
url: new URL(response.url, this.host).toString(),
|
|
1039
|
+
relativeUrl: response.url,
|
|
1040
|
+
ticketId: response.ticketId,
|
|
1041
|
+
expiresAt: response.expiresAt
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
985
1044
|
/**
|
|
986
1045
|
* Get a value by key.
|
|
987
1046
|
*/
|
|
@@ -1254,6 +1313,61 @@ var KVService = class extends BaseService {
|
|
|
1254
1313
|
}
|
|
1255
1314
|
});
|
|
1256
1315
|
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Create a short-lived signed URL for reading a KV object.
|
|
1318
|
+
*/
|
|
1319
|
+
async createSignedReadUrl(key, options) {
|
|
1320
|
+
return this.withTelemetry("createSignedReadUrl", key, async () => {
|
|
1321
|
+
if (!this.requireAuth()) {
|
|
1322
|
+
return err(authRequiredError("kv"));
|
|
1323
|
+
}
|
|
1324
|
+
const path = this.getFullPath(key, options?.prefix);
|
|
1325
|
+
const session = this.context.session;
|
|
1326
|
+
const headers = this.context.invoke(
|
|
1327
|
+
session,
|
|
1328
|
+
"kv",
|
|
1329
|
+
path,
|
|
1330
|
+
KVAction.GET
|
|
1331
|
+
);
|
|
1332
|
+
const body = {
|
|
1333
|
+
space: session.spaceId,
|
|
1334
|
+
path,
|
|
1335
|
+
ttl_seconds: options?.expiresInSeconds ?? Math.ceil(DEFAULT_SIGNED_READ_URL_EXPIRY_MS / 1e3)
|
|
1336
|
+
};
|
|
1337
|
+
if (options?.contentHash !== void 0) {
|
|
1338
|
+
body.content_hash = options.contentHash;
|
|
1339
|
+
}
|
|
1340
|
+
if (options?.etag !== void 0) {
|
|
1341
|
+
body.etag = options.etag;
|
|
1342
|
+
}
|
|
1343
|
+
try {
|
|
1344
|
+
const response = await this.context.fetch(`${this.host}/signed/kv`, {
|
|
1345
|
+
method: "POST",
|
|
1346
|
+
headers: this.withJsonContentType(headers),
|
|
1347
|
+
body: JSON.stringify(body),
|
|
1348
|
+
signal: this.combineSignals(options?.signal)
|
|
1349
|
+
});
|
|
1350
|
+
if (!response.ok) {
|
|
1351
|
+
return this.createSignedReadUrlError(response, key);
|
|
1352
|
+
}
|
|
1353
|
+
const signedUrl = this.normalizeSignedReadUrlResponse(
|
|
1354
|
+
await response.json()
|
|
1355
|
+
);
|
|
1356
|
+
if (!signedUrl) {
|
|
1357
|
+
return err(
|
|
1358
|
+
serviceError(
|
|
1359
|
+
ErrorCodes.NETWORK_ERROR,
|
|
1360
|
+
"Signed read URL response did not include url, ticketId, and expiresAt",
|
|
1361
|
+
"kv"
|
|
1362
|
+
)
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
return ok(signedUrl);
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
return err(wrapError("kv", error));
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1257
1371
|
/**
|
|
1258
1372
|
* Create a prefix-scoped view of this KV service.
|
|
1259
1373
|
*
|
|
@@ -2823,6 +2937,9 @@ function base64Decode(str) {
|
|
|
2823
2937
|
}
|
|
2824
2938
|
return bytes;
|
|
2825
2939
|
}
|
|
2940
|
+
function isUnlockSigner(signer) {
|
|
2941
|
+
return typeof signer === "object" && signer !== null && typeof signer.signMessage === "function";
|
|
2942
|
+
}
|
|
2826
2943
|
function defaultVaultMessage(input) {
|
|
2827
2944
|
switch (input.code) {
|
|
2828
2945
|
case "DECRYPTION_FAILED":
|
|
@@ -2860,6 +2977,7 @@ var DataVaultService = class extends BaseService {
|
|
|
2860
2977
|
this.masterKey = null;
|
|
2861
2978
|
this.encryptionIdentity = null;
|
|
2862
2979
|
this._isUnlocked = false;
|
|
2980
|
+
this.unlockInFlight = null;
|
|
2863
2981
|
this.vaultConfig = config;
|
|
2864
2982
|
this._config = config;
|
|
2865
2983
|
}
|
|
@@ -2919,30 +3037,40 @@ var DataVaultService = class extends BaseService {
|
|
|
2919
3037
|
* signatures exist (browser only).
|
|
2920
3038
|
*/
|
|
2921
3039
|
async unlock(signer) {
|
|
2922
|
-
|
|
3040
|
+
const unlockSigner = isUnlockSigner(signer) ? signer : void 0;
|
|
3041
|
+
if (this._isUnlocked && this.masterKey && (this.encryptionIdentity || !unlockSigner)) {
|
|
3042
|
+
return { ok: true, data: void 0 };
|
|
3043
|
+
}
|
|
3044
|
+
if (this.unlockInFlight) {
|
|
3045
|
+
return this.unlockInFlight;
|
|
3046
|
+
}
|
|
3047
|
+
this.unlockInFlight = this.withTelemetry("unlock", void 0, async () => {
|
|
2923
3048
|
const spaceId = this.vaultConfig.spaceId;
|
|
2924
3049
|
const versionConfig = VaultVersionConfig[CURRENT_VAULT_VERSION];
|
|
2925
3050
|
const masterCacheKey = `vault-master:${spaceId}`;
|
|
2926
3051
|
const identityCacheKey = `vault-identity:${this.tc.address}`;
|
|
2927
3052
|
try {
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
if (!
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
3053
|
+
if (!this.masterKey) {
|
|
3054
|
+
let masterSigBytes = await loadCachedSignature(masterCacheKey);
|
|
3055
|
+
if (!masterSigBytes) {
|
|
3056
|
+
if (!unlockSigner) {
|
|
3057
|
+
return vaultError({
|
|
3058
|
+
code: "VAULT_LOCKED",
|
|
3059
|
+
message: "Signer is required when no cached master signature exists"
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
const sig = await unlockSigner.signMessage(
|
|
3063
|
+
versionConfig.masterMessage(spaceId)
|
|
3064
|
+
);
|
|
3065
|
+
masterSigBytes = toBytes(sig);
|
|
3066
|
+
await cacheSignature(masterCacheKey, masterSigBytes);
|
|
2935
3067
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
masterSigBytes,
|
|
2943
|
-
this.crypto.sha256(toBytes(spaceId)),
|
|
2944
|
-
toBytes("vault-master")
|
|
2945
|
-
);
|
|
3068
|
+
this.masterKey = this.crypto.deriveKey(
|
|
3069
|
+
masterSigBytes,
|
|
3070
|
+
this.crypto.sha256(toBytes(spaceId)),
|
|
3071
|
+
toBytes("vault-master")
|
|
3072
|
+
);
|
|
3073
|
+
}
|
|
2946
3074
|
const publicSpaceId = this.tc.makePublicSpaceId(this.tc.address, this.tc.chainId);
|
|
2947
3075
|
let existingPubKey = null;
|
|
2948
3076
|
try {
|
|
@@ -2965,13 +3093,14 @@ var DataVaultService = class extends BaseService {
|
|
|
2965
3093
|
} else {
|
|
2966
3094
|
let identitySigBytes = await loadCachedSignature(identityCacheKey);
|
|
2967
3095
|
if (!identitySigBytes) {
|
|
2968
|
-
if (!
|
|
3096
|
+
if (!unlockSigner) {
|
|
2969
3097
|
this.encryptionIdentity = null;
|
|
2970
3098
|
this._isUnlocked = true;
|
|
2971
3099
|
return ok(void 0);
|
|
2972
3100
|
}
|
|
2973
|
-
const
|
|
2974
|
-
|
|
3101
|
+
const sig = await unlockSigner.signMessage(
|
|
3102
|
+
versionConfig.identityMessage
|
|
3103
|
+
);
|
|
2975
3104
|
identitySigBytes = toBytes(sig);
|
|
2976
3105
|
await cacheSignature(identityCacheKey, identitySigBytes);
|
|
2977
3106
|
}
|
|
@@ -3001,6 +3130,11 @@ var DataVaultService = class extends BaseService {
|
|
|
3001
3130
|
});
|
|
3002
3131
|
}
|
|
3003
3132
|
});
|
|
3133
|
+
try {
|
|
3134
|
+
return await this.unlockInFlight;
|
|
3135
|
+
} finally {
|
|
3136
|
+
this.unlockInFlight = null;
|
|
3137
|
+
}
|
|
3004
3138
|
}
|
|
3005
3139
|
/**
|
|
3006
3140
|
* Clear the cached vault signatures.
|
|
@@ -3885,6 +4019,7 @@ var SecretsService = class {
|
|
|
3885
4019
|
};
|
|
3886
4020
|
export {
|
|
3887
4021
|
BaseService,
|
|
4022
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
3888
4023
|
DataVaultService,
|
|
3889
4024
|
DatabaseHandle,
|
|
3890
4025
|
DuckDbAction,
|