@tinycloud/operations 0.3.4-beta.2 → 0.3.4-beta.4
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 +62 -80
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +30 -30
- package/dist/artifacts.d.ts +30 -30
- package/dist/artifacts.js +62 -80
- package/dist/artifacts.js.map +1 -1
- package/dist/cli-runtime.cjs +65 -83
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +65 -83
- package/dist/cli-runtime.js.map +1 -1
- package/dist/index.cjs +65 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +65 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1051,6 +1051,18 @@ function storageLimitReachedError(service, message, meta) {
|
|
|
1051
1051
|
meta
|
|
1052
1052
|
};
|
|
1053
1053
|
}
|
|
1054
|
+
function parseStorageQuotaBytes(responseText) {
|
|
1055
|
+
const match = responseText.match(/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i);
|
|
1056
|
+
if (!match) return void 0;
|
|
1057
|
+
return {
|
|
1058
|
+
usedBytes: parseInt(match[1], 10),
|
|
1059
|
+
limitBytes: parseInt(match[2], 10)
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
function storageRejectionError(service, status, meta, responseText) {
|
|
1063
|
+
const quotaMeta = { ...meta, ...parseStorageQuotaBytes(responseText) };
|
|
1064
|
+
return status === 402 ? storageQuotaExceededError(service, STORAGE_FULL_MESSAGE, quotaMeta) : storageLimitReachedError(service, STORAGE_WRITE_TOO_LARGE_MESSAGE, quotaMeta);
|
|
1065
|
+
}
|
|
1054
1066
|
function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
|
|
1055
1067
|
if (error instanceof Error) {
|
|
1056
1068
|
if (error.name === "AbortError") {
|
|
@@ -1180,6 +1192,9 @@ function serializeSqlValues(values) {
|
|
|
1180
1192
|
(value) => value instanceof Uint8Array ? Array.from(value) : value
|
|
1181
1193
|
);
|
|
1182
1194
|
}
|
|
1195
|
+
function isMissingTableError(message) {
|
|
1196
|
+
return /no such table/i.test(message);
|
|
1197
|
+
}
|
|
1183
1198
|
function migrationKey(namespace, id) {
|
|
1184
1199
|
return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
|
|
1185
1200
|
}
|
|
@@ -1665,6 +1680,9 @@ function defaultVaultMessage(input) {
|
|
|
1665
1680
|
return input.message ?? `Public key not found for ${input.did}`;
|
|
1666
1681
|
case "STORAGE_ERROR":
|
|
1667
1682
|
return input.message ?? input.cause.message;
|
|
1683
|
+
case "STORAGE_QUOTA_EXCEEDED":
|
|
1684
|
+
case "STORAGE_LIMIT_REACHED":
|
|
1685
|
+
return input.message;
|
|
1668
1686
|
}
|
|
1669
1687
|
}
|
|
1670
1688
|
function vaultError(input) {
|
|
@@ -1675,6 +1693,15 @@ function vaultError(input) {
|
|
|
1675
1693
|
};
|
|
1676
1694
|
return { ok: false, error };
|
|
1677
1695
|
}
|
|
1696
|
+
function kvWriteError(context, error) {
|
|
1697
|
+
if (error.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error.code === ErrorCodes.STORAGE_LIMIT_REACHED) {
|
|
1698
|
+
return vaultError({ code: error.code, message: error.message, meta: error.meta });
|
|
1699
|
+
}
|
|
1700
|
+
return vaultError({
|
|
1701
|
+
code: "STORAGE_ERROR",
|
|
1702
|
+
cause: new Error(`${context}: ${error.message}`)
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1678
1705
|
function canonicalize(value) {
|
|
1679
1706
|
if (value === void 0) {
|
|
1680
1707
|
return "";
|
|
@@ -2433,7 +2460,7 @@ function encOk(data) {
|
|
|
2433
2460
|
function encErr(error) {
|
|
2434
2461
|
return { ok: false, error };
|
|
2435
2462
|
}
|
|
2436
|
-
var import_zod, import_decrypt_transport_response_error, 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;
|
|
2463
|
+
var import_zod, import_decrypt_transport_response_error, 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, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, 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;
|
|
2437
2464
|
var init_dist2 = __esm({
|
|
2438
2465
|
"../sdk-services/dist/index.js"() {
|
|
2439
2466
|
"use strict";
|
|
@@ -2716,6 +2743,8 @@ var init_dist2 = __esm({
|
|
|
2716
2743
|
/** The session key JWK (required for invoke) */
|
|
2717
2744
|
jwk: import_zod.z.object({}).passthrough()
|
|
2718
2745
|
});
|
|
2746
|
+
STORAGE_FULL_MESSAGE = "TinyCloud storage is full, so this change was not saved. Reading still works. Free up space or upgrade your plan to save again.";
|
|
2747
|
+
STORAGE_WRITE_TOO_LARGE_MESSAGE = "This change is larger than the TinyCloud storage you have left, so it was not saved. Reading still works. Free up space or upgrade your plan to save it.";
|
|
2719
2748
|
BaseService = class {
|
|
2720
2749
|
constructor() {
|
|
2721
2750
|
this.abortController = new AbortController();
|
|
@@ -3064,47 +3093,21 @@ var init_dist2 = __esm({
|
|
|
3064
3093
|
get config() {
|
|
3065
3094
|
return this._config;
|
|
3066
3095
|
}
|
|
3067
|
-
// Parses "Used: X bytes, Limit: Y bytes" from tinycloud-node error responses
|
|
3068
|
-
parseQuotaInfo(errorText) {
|
|
3069
|
-
const match = errorText.match(
|
|
3070
|
-
/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i
|
|
3071
|
-
);
|
|
3072
|
-
if (match) {
|
|
3073
|
-
return {
|
|
3074
|
-
usedBytes: parseInt(match[1], 10),
|
|
3075
|
-
limitBytes: parseInt(match[2], 10)
|
|
3076
|
-
};
|
|
3077
|
-
}
|
|
3078
|
-
return void 0;
|
|
3079
|
-
}
|
|
3080
3096
|
handleQuotaErrorResponse(response, errorText, key) {
|
|
3081
|
-
if (response.status
|
|
3082
|
-
|
|
3083
|
-
return err(
|
|
3084
|
-
storageQuotaExceededError(
|
|
3085
|
-
"kv",
|
|
3086
|
-
`Storage quota exceeded for key ${JSON.stringify(key)}: ${errorText}`,
|
|
3087
|
-
{
|
|
3088
|
-
status: response.status,
|
|
3089
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
3090
|
-
}
|
|
3091
|
-
)
|
|
3092
|
-
);
|
|
3097
|
+
if (response.status !== 402 && response.status !== 413) {
|
|
3098
|
+
return void 0;
|
|
3093
3099
|
}
|
|
3094
|
-
if (response.status === 413) {
|
|
3095
|
-
|
|
3096
|
-
return err(
|
|
3097
|
-
storageLimitReachedError(
|
|
3098
|
-
"kv",
|
|
3099
|
-
`Storage limit reached for key ${JSON.stringify(key)}: ${errorText}`,
|
|
3100
|
-
{
|
|
3101
|
-
status: response.status,
|
|
3102
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
3103
|
-
}
|
|
3104
|
-
)
|
|
3105
|
-
);
|
|
3100
|
+
if (response.status === 413 && !parseStorageQuotaBytes(errorText)) {
|
|
3101
|
+
return void 0;
|
|
3106
3102
|
}
|
|
3107
|
-
return
|
|
3103
|
+
return err(
|
|
3104
|
+
storageRejectionError(
|
|
3105
|
+
"kv",
|
|
3106
|
+
response.status,
|
|
3107
|
+
{ status: response.status, statusText: response.statusText, key },
|
|
3108
|
+
errorText
|
|
3109
|
+
)
|
|
3110
|
+
);
|
|
3108
3111
|
}
|
|
3109
3112
|
/**
|
|
3110
3113
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -4393,21 +4396,24 @@ var init_dist2 = __esm({
|
|
|
4393
4396
|
}
|
|
4394
4397
|
async applyMigrationsOnDbUnlocked(dbName, options) {
|
|
4395
4398
|
return this.withTelemetry("migrations.apply", dbName, async () => {
|
|
4396
|
-
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
4397
|
-
if (!created.ok) return created;
|
|
4398
4399
|
const listed = await this.queryOnDb(
|
|
4399
4400
|
dbName,
|
|
4400
4401
|
`SELECT id FROM ${MIGRATIONS_TABLE} WHERE namespace = ? ORDER BY applied_at, id`,
|
|
4401
4402
|
[options.namespace],
|
|
4402
4403
|
{ signal: options.signal }
|
|
4403
4404
|
);
|
|
4404
|
-
|
|
4405
|
+
const tableMissing = !listed.ok && (listed.error.code === ErrorCodes.SQL_DATABASE_NOT_FOUND || isMissingTableError(listed.error.message));
|
|
4406
|
+
if (!listed.ok && !tableMissing) return listed;
|
|
4405
4407
|
const appliedIds = new Set(
|
|
4406
|
-
listed.data.rows.map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
4408
|
+
(listed.ok ? listed.data.rows : []).map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
4407
4409
|
);
|
|
4408
4410
|
const skipped = options.migrations.filter((migration) => appliedIds.has(migration.id)).map((migration) => migration.id);
|
|
4409
4411
|
const pending = options.migrations.filter((migration) => !appliedIds.has(migration.id));
|
|
4410
4412
|
const applied = [];
|
|
4413
|
+
if (pending.length > 0 && tableMissing) {
|
|
4414
|
+
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
4415
|
+
if (!created.ok) return created;
|
|
4416
|
+
}
|
|
4411
4417
|
for (const migration of pending) {
|
|
4412
4418
|
const result = await this.applyOneMigration(dbName, options.namespace, migration, options.signal);
|
|
4413
4419
|
if (!result.ok) return result;
|
|
@@ -4510,6 +4516,10 @@ var init_dist2 = __esm({
|
|
|
4510
4516
|
}
|
|
4511
4517
|
async handleErrorResponse(response, operation) {
|
|
4512
4518
|
const errorText = await response.text();
|
|
4519
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4520
|
+
if (response.status === 402) {
|
|
4521
|
+
return err(storageRejectionError("sql", 402, meta, errorText));
|
|
4522
|
+
}
|
|
4513
4523
|
const errorBody = parseServiceErrorBody(errorText);
|
|
4514
4524
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
4515
4525
|
response.status,
|
|
@@ -4522,7 +4532,6 @@ var init_dist2 = __esm({
|
|
|
4522
4532
|
errorText,
|
|
4523
4533
|
errorBody
|
|
4524
4534
|
);
|
|
4525
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4526
4535
|
if (response.status === 401) {
|
|
4527
4536
|
const { resource, action } = parseAuthError(errorText);
|
|
4528
4537
|
if (action) meta.requiredAction = action;
|
|
@@ -4858,6 +4867,10 @@ var init_dist2 = __esm({
|
|
|
4858
4867
|
}
|
|
4859
4868
|
async handleErrorResponse(response, operation) {
|
|
4860
4869
|
const errorText = await response.text();
|
|
4870
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4871
|
+
if (response.status === 402) {
|
|
4872
|
+
return err(storageRejectionError("duckdb", 402, meta, errorText));
|
|
4873
|
+
}
|
|
4861
4874
|
const errorBody = parseServiceErrorBody(errorText);
|
|
4862
4875
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
4863
4876
|
response.status,
|
|
@@ -4870,7 +4883,6 @@ var init_dist2 = __esm({
|
|
|
4870
4883
|
errorText,
|
|
4871
4884
|
errorBody
|
|
4872
4885
|
);
|
|
4873
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4874
4886
|
if (response.status === 401) {
|
|
4875
4887
|
const { resource, action } = parseAuthError(errorText);
|
|
4876
4888
|
if (action) meta.requiredAction = action;
|
|
@@ -5605,12 +5617,7 @@ var init_dist2 = __esm({
|
|
|
5605
5617
|
JSON.stringify(envelopeResult.data)
|
|
5606
5618
|
);
|
|
5607
5619
|
if (!valuePutResult.ok) {
|
|
5608
|
-
return
|
|
5609
|
-
code: "STORAGE_ERROR",
|
|
5610
|
-
cause: new Error(
|
|
5611
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
5612
|
-
)
|
|
5613
|
-
});
|
|
5620
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
5614
5621
|
}
|
|
5615
5622
|
return { ok: true, data: void 0 };
|
|
5616
5623
|
} catch (error) {
|
|
@@ -5828,12 +5835,7 @@ var init_dist2 = __esm({
|
|
|
5828
5835
|
keyPayload
|
|
5829
5836
|
);
|
|
5830
5837
|
if (!keyPutResult.ok) {
|
|
5831
|
-
return
|
|
5832
|
-
code: "STORAGE_ERROR",
|
|
5833
|
-
cause: new Error(
|
|
5834
|
-
`Failed to store key blob: ${keyPutResult.error.message}`
|
|
5835
|
-
)
|
|
5836
|
-
});
|
|
5838
|
+
return kvWriteError("Failed to store key blob", keyPutResult.error);
|
|
5837
5839
|
}
|
|
5838
5840
|
const valuePayload = JSON.stringify({
|
|
5839
5841
|
data: base64Encode(encrypted),
|
|
@@ -5844,12 +5846,7 @@ var init_dist2 = __esm({
|
|
|
5844
5846
|
valuePayload
|
|
5845
5847
|
);
|
|
5846
5848
|
if (!valuePutResult.ok) {
|
|
5847
|
-
return
|
|
5848
|
-
code: "STORAGE_ERROR",
|
|
5849
|
-
cause: new Error(
|
|
5850
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
5851
|
-
)
|
|
5852
|
-
});
|
|
5849
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
5853
5850
|
}
|
|
5854
5851
|
return ok(void 0);
|
|
5855
5852
|
} catch (error) {
|
|
@@ -6180,12 +6177,7 @@ var init_dist2 = __esm({
|
|
|
6180
6177
|
grantPayload
|
|
6181
6178
|
);
|
|
6182
6179
|
if (!grantPutResult.ok) {
|
|
6183
|
-
return
|
|
6184
|
-
code: "STORAGE_ERROR",
|
|
6185
|
-
cause: new Error(
|
|
6186
|
-
`Failed to store grant: ${grantPutResult.error.message}`
|
|
6187
|
-
)
|
|
6188
|
-
});
|
|
6180
|
+
return kvWriteError("Failed to store grant", grantPutResult.error);
|
|
6189
6181
|
}
|
|
6190
6182
|
return ok(void 0);
|
|
6191
6183
|
} catch (error) {
|
|
@@ -6530,12 +6522,7 @@ var init_dist2 = __esm({
|
|
|
6530
6522
|
keyPayload
|
|
6531
6523
|
);
|
|
6532
6524
|
if (!keyPutResult.ok) {
|
|
6533
|
-
return
|
|
6534
|
-
code: "STORAGE_ERROR",
|
|
6535
|
-
cause: new Error(
|
|
6536
|
-
`Failed to store rotated key blob: ${keyPutResult.error.message}`
|
|
6537
|
-
)
|
|
6538
|
-
});
|
|
6525
|
+
return kvWriteError("Failed to store rotated key blob", keyPutResult.error);
|
|
6539
6526
|
}
|
|
6540
6527
|
const valuePayload = JSON.stringify({
|
|
6541
6528
|
data: base64Encode(encrypted),
|
|
@@ -6546,12 +6533,7 @@ var init_dist2 = __esm({
|
|
|
6546
6533
|
valuePayload
|
|
6547
6534
|
);
|
|
6548
6535
|
if (!valuePutResult.ok) {
|
|
6549
|
-
return
|
|
6550
|
-
code: "STORAGE_ERROR",
|
|
6551
|
-
cause: new Error(
|
|
6552
|
-
`Failed to store re-encrypted value: ${valuePutResult.error.message}`
|
|
6553
|
-
)
|
|
6554
|
-
});
|
|
6536
|
+
return kvWriteError("Failed to store re-encrypted value", valuePutResult.error);
|
|
6555
6537
|
}
|
|
6556
6538
|
for (const did of remainingGrantees) {
|
|
6557
6539
|
const grantResult = await this.reencrypt(key, did);
|
|
@@ -7818,12 +7800,12 @@ function canonicalizeSpaceUri(space) {
|
|
|
7818
7800
|
}
|
|
7819
7801
|
function buildSecretSetupUrl(reference) {
|
|
7820
7802
|
const parameters = [
|
|
7821
|
-
["
|
|
7803
|
+
["secret", reference.name],
|
|
7822
7804
|
...reference.scope === void 0 ? [] : [["scope", reference.scope]],
|
|
7823
7805
|
["space", reference.space]
|
|
7824
7806
|
];
|
|
7825
7807
|
const query = parameters.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
|
|
7826
|
-
return `${SECRET_MANAGER_BASE_URL}?${query}`;
|
|
7808
|
+
return `${SECRET_MANAGER_BASE_URL}/app?${query}`;
|
|
7827
7809
|
}
|
|
7828
7810
|
function canonicalizeSecretScope(scope) {
|
|
7829
7811
|
if (scope === void 0 || scope === "") return void 0;
|