@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.js
CHANGED
|
@@ -1050,6 +1050,18 @@ function storageLimitReachedError(service, message, meta) {
|
|
|
1050
1050
|
meta
|
|
1051
1051
|
};
|
|
1052
1052
|
}
|
|
1053
|
+
function parseStorageQuotaBytes(responseText) {
|
|
1054
|
+
const match = responseText.match(/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i);
|
|
1055
|
+
if (!match) return void 0;
|
|
1056
|
+
return {
|
|
1057
|
+
usedBytes: parseInt(match[1], 10),
|
|
1058
|
+
limitBytes: parseInt(match[2], 10)
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
function storageRejectionError(service, status, meta, responseText) {
|
|
1062
|
+
const quotaMeta = { ...meta, ...parseStorageQuotaBytes(responseText) };
|
|
1063
|
+
return status === 402 ? storageQuotaExceededError(service, STORAGE_FULL_MESSAGE, quotaMeta) : storageLimitReachedError(service, STORAGE_WRITE_TOO_LARGE_MESSAGE, quotaMeta);
|
|
1064
|
+
}
|
|
1053
1065
|
function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
|
|
1054
1066
|
if (error instanceof Error) {
|
|
1055
1067
|
if (error.name === "AbortError") {
|
|
@@ -1179,6 +1191,9 @@ function serializeSqlValues(values) {
|
|
|
1179
1191
|
(value) => value instanceof Uint8Array ? Array.from(value) : value
|
|
1180
1192
|
);
|
|
1181
1193
|
}
|
|
1194
|
+
function isMissingTableError(message) {
|
|
1195
|
+
return /no such table/i.test(message);
|
|
1196
|
+
}
|
|
1182
1197
|
function migrationKey(namespace, id) {
|
|
1183
1198
|
return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
|
|
1184
1199
|
}
|
|
@@ -1664,6 +1679,9 @@ function defaultVaultMessage(input) {
|
|
|
1664
1679
|
return input.message ?? `Public key not found for ${input.did}`;
|
|
1665
1680
|
case "STORAGE_ERROR":
|
|
1666
1681
|
return input.message ?? input.cause.message;
|
|
1682
|
+
case "STORAGE_QUOTA_EXCEEDED":
|
|
1683
|
+
case "STORAGE_LIMIT_REACHED":
|
|
1684
|
+
return input.message;
|
|
1667
1685
|
}
|
|
1668
1686
|
}
|
|
1669
1687
|
function vaultError(input) {
|
|
@@ -1674,6 +1692,15 @@ function vaultError(input) {
|
|
|
1674
1692
|
};
|
|
1675
1693
|
return { ok: false, error };
|
|
1676
1694
|
}
|
|
1695
|
+
function kvWriteError(context, error) {
|
|
1696
|
+
if (error.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error.code === ErrorCodes.STORAGE_LIMIT_REACHED) {
|
|
1697
|
+
return vaultError({ code: error.code, message: error.message, meta: error.meta });
|
|
1698
|
+
}
|
|
1699
|
+
return vaultError({
|
|
1700
|
+
code: "STORAGE_ERROR",
|
|
1701
|
+
cause: new Error(`${context}: ${error.message}`)
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1677
1704
|
function canonicalize(value) {
|
|
1678
1705
|
if (value === void 0) {
|
|
1679
1706
|
return "";
|
|
@@ -2432,7 +2459,7 @@ function encOk(data) {
|
|
|
2432
2459
|
function encErr(error) {
|
|
2433
2460
|
return { ok: false, error };
|
|
2434
2461
|
}
|
|
2435
|
-
var 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;
|
|
2462
|
+
var 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;
|
|
2436
2463
|
var init_dist2 = __esm({
|
|
2437
2464
|
"../sdk-services/dist/index.js"() {
|
|
2438
2465
|
"use strict";
|
|
@@ -2714,6 +2741,8 @@ var init_dist2 = __esm({
|
|
|
2714
2741
|
/** The session key JWK (required for invoke) */
|
|
2715
2742
|
jwk: z.object({}).passthrough()
|
|
2716
2743
|
});
|
|
2744
|
+
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.";
|
|
2745
|
+
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.";
|
|
2717
2746
|
BaseService = class {
|
|
2718
2747
|
constructor() {
|
|
2719
2748
|
this.abortController = new AbortController();
|
|
@@ -3062,47 +3091,21 @@ var init_dist2 = __esm({
|
|
|
3062
3091
|
get config() {
|
|
3063
3092
|
return this._config;
|
|
3064
3093
|
}
|
|
3065
|
-
// Parses "Used: X bytes, Limit: Y bytes" from tinycloud-node error responses
|
|
3066
|
-
parseQuotaInfo(errorText) {
|
|
3067
|
-
const match = errorText.match(
|
|
3068
|
-
/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i
|
|
3069
|
-
);
|
|
3070
|
-
if (match) {
|
|
3071
|
-
return {
|
|
3072
|
-
usedBytes: parseInt(match[1], 10),
|
|
3073
|
-
limitBytes: parseInt(match[2], 10)
|
|
3074
|
-
};
|
|
3075
|
-
}
|
|
3076
|
-
return void 0;
|
|
3077
|
-
}
|
|
3078
3094
|
handleQuotaErrorResponse(response, errorText, key) {
|
|
3079
|
-
if (response.status
|
|
3080
|
-
|
|
3081
|
-
return err(
|
|
3082
|
-
storageQuotaExceededError(
|
|
3083
|
-
"kv",
|
|
3084
|
-
`Storage quota exceeded for key ${JSON.stringify(key)}: ${errorText}`,
|
|
3085
|
-
{
|
|
3086
|
-
status: response.status,
|
|
3087
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
3088
|
-
}
|
|
3089
|
-
)
|
|
3090
|
-
);
|
|
3095
|
+
if (response.status !== 402 && response.status !== 413) {
|
|
3096
|
+
return void 0;
|
|
3091
3097
|
}
|
|
3092
|
-
if (response.status === 413) {
|
|
3093
|
-
|
|
3094
|
-
return err(
|
|
3095
|
-
storageLimitReachedError(
|
|
3096
|
-
"kv",
|
|
3097
|
-
`Storage limit reached for key ${JSON.stringify(key)}: ${errorText}`,
|
|
3098
|
-
{
|
|
3099
|
-
status: response.status,
|
|
3100
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
3101
|
-
}
|
|
3102
|
-
)
|
|
3103
|
-
);
|
|
3098
|
+
if (response.status === 413 && !parseStorageQuotaBytes(errorText)) {
|
|
3099
|
+
return void 0;
|
|
3104
3100
|
}
|
|
3105
|
-
return
|
|
3101
|
+
return err(
|
|
3102
|
+
storageRejectionError(
|
|
3103
|
+
"kv",
|
|
3104
|
+
response.status,
|
|
3105
|
+
{ status: response.status, statusText: response.statusText, key },
|
|
3106
|
+
errorText
|
|
3107
|
+
)
|
|
3108
|
+
);
|
|
3106
3109
|
}
|
|
3107
3110
|
/**
|
|
3108
3111
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -4391,21 +4394,24 @@ var init_dist2 = __esm({
|
|
|
4391
4394
|
}
|
|
4392
4395
|
async applyMigrationsOnDbUnlocked(dbName, options) {
|
|
4393
4396
|
return this.withTelemetry("migrations.apply", dbName, async () => {
|
|
4394
|
-
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
4395
|
-
if (!created.ok) return created;
|
|
4396
4397
|
const listed = await this.queryOnDb(
|
|
4397
4398
|
dbName,
|
|
4398
4399
|
`SELECT id FROM ${MIGRATIONS_TABLE} WHERE namespace = ? ORDER BY applied_at, id`,
|
|
4399
4400
|
[options.namespace],
|
|
4400
4401
|
{ signal: options.signal }
|
|
4401
4402
|
);
|
|
4402
|
-
|
|
4403
|
+
const tableMissing = !listed.ok && (listed.error.code === ErrorCodes.SQL_DATABASE_NOT_FOUND || isMissingTableError(listed.error.message));
|
|
4404
|
+
if (!listed.ok && !tableMissing) return listed;
|
|
4403
4405
|
const appliedIds = new Set(
|
|
4404
|
-
listed.data.rows.map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
4406
|
+
(listed.ok ? listed.data.rows : []).map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
4405
4407
|
);
|
|
4406
4408
|
const skipped = options.migrations.filter((migration) => appliedIds.has(migration.id)).map((migration) => migration.id);
|
|
4407
4409
|
const pending = options.migrations.filter((migration) => !appliedIds.has(migration.id));
|
|
4408
4410
|
const applied = [];
|
|
4411
|
+
if (pending.length > 0 && tableMissing) {
|
|
4412
|
+
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
4413
|
+
if (!created.ok) return created;
|
|
4414
|
+
}
|
|
4409
4415
|
for (const migration of pending) {
|
|
4410
4416
|
const result = await this.applyOneMigration(dbName, options.namespace, migration, options.signal);
|
|
4411
4417
|
if (!result.ok) return result;
|
|
@@ -4508,6 +4514,10 @@ var init_dist2 = __esm({
|
|
|
4508
4514
|
}
|
|
4509
4515
|
async handleErrorResponse(response, operation) {
|
|
4510
4516
|
const errorText = await response.text();
|
|
4517
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4518
|
+
if (response.status === 402) {
|
|
4519
|
+
return err(storageRejectionError("sql", 402, meta, errorText));
|
|
4520
|
+
}
|
|
4511
4521
|
const errorBody = parseServiceErrorBody(errorText);
|
|
4512
4522
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
4513
4523
|
response.status,
|
|
@@ -4520,7 +4530,6 @@ var init_dist2 = __esm({
|
|
|
4520
4530
|
errorText,
|
|
4521
4531
|
errorBody
|
|
4522
4532
|
);
|
|
4523
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4524
4533
|
if (response.status === 401) {
|
|
4525
4534
|
const { resource, action } = parseAuthError(errorText);
|
|
4526
4535
|
if (action) meta.requiredAction = action;
|
|
@@ -4856,6 +4865,10 @@ var init_dist2 = __esm({
|
|
|
4856
4865
|
}
|
|
4857
4866
|
async handleErrorResponse(response, operation) {
|
|
4858
4867
|
const errorText = await response.text();
|
|
4868
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4869
|
+
if (response.status === 402) {
|
|
4870
|
+
return err(storageRejectionError("duckdb", 402, meta, errorText));
|
|
4871
|
+
}
|
|
4859
4872
|
const errorBody = parseServiceErrorBody(errorText);
|
|
4860
4873
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
4861
4874
|
response.status,
|
|
@@ -4868,7 +4881,6 @@ var init_dist2 = __esm({
|
|
|
4868
4881
|
errorText,
|
|
4869
4882
|
errorBody
|
|
4870
4883
|
);
|
|
4871
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
4872
4884
|
if (response.status === 401) {
|
|
4873
4885
|
const { resource, action } = parseAuthError(errorText);
|
|
4874
4886
|
if (action) meta.requiredAction = action;
|
|
@@ -5603,12 +5615,7 @@ var init_dist2 = __esm({
|
|
|
5603
5615
|
JSON.stringify(envelopeResult.data)
|
|
5604
5616
|
);
|
|
5605
5617
|
if (!valuePutResult.ok) {
|
|
5606
|
-
return
|
|
5607
|
-
code: "STORAGE_ERROR",
|
|
5608
|
-
cause: new Error(
|
|
5609
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
5610
|
-
)
|
|
5611
|
-
});
|
|
5618
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
5612
5619
|
}
|
|
5613
5620
|
return { ok: true, data: void 0 };
|
|
5614
5621
|
} catch (error) {
|
|
@@ -5826,12 +5833,7 @@ var init_dist2 = __esm({
|
|
|
5826
5833
|
keyPayload
|
|
5827
5834
|
);
|
|
5828
5835
|
if (!keyPutResult.ok) {
|
|
5829
|
-
return
|
|
5830
|
-
code: "STORAGE_ERROR",
|
|
5831
|
-
cause: new Error(
|
|
5832
|
-
`Failed to store key blob: ${keyPutResult.error.message}`
|
|
5833
|
-
)
|
|
5834
|
-
});
|
|
5836
|
+
return kvWriteError("Failed to store key blob", keyPutResult.error);
|
|
5835
5837
|
}
|
|
5836
5838
|
const valuePayload = JSON.stringify({
|
|
5837
5839
|
data: base64Encode(encrypted),
|
|
@@ -5842,12 +5844,7 @@ var init_dist2 = __esm({
|
|
|
5842
5844
|
valuePayload
|
|
5843
5845
|
);
|
|
5844
5846
|
if (!valuePutResult.ok) {
|
|
5845
|
-
return
|
|
5846
|
-
code: "STORAGE_ERROR",
|
|
5847
|
-
cause: new Error(
|
|
5848
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
5849
|
-
)
|
|
5850
|
-
});
|
|
5847
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
5851
5848
|
}
|
|
5852
5849
|
return ok(void 0);
|
|
5853
5850
|
} catch (error) {
|
|
@@ -6178,12 +6175,7 @@ var init_dist2 = __esm({
|
|
|
6178
6175
|
grantPayload
|
|
6179
6176
|
);
|
|
6180
6177
|
if (!grantPutResult.ok) {
|
|
6181
|
-
return
|
|
6182
|
-
code: "STORAGE_ERROR",
|
|
6183
|
-
cause: new Error(
|
|
6184
|
-
`Failed to store grant: ${grantPutResult.error.message}`
|
|
6185
|
-
)
|
|
6186
|
-
});
|
|
6178
|
+
return kvWriteError("Failed to store grant", grantPutResult.error);
|
|
6187
6179
|
}
|
|
6188
6180
|
return ok(void 0);
|
|
6189
6181
|
} catch (error) {
|
|
@@ -6528,12 +6520,7 @@ var init_dist2 = __esm({
|
|
|
6528
6520
|
keyPayload
|
|
6529
6521
|
);
|
|
6530
6522
|
if (!keyPutResult.ok) {
|
|
6531
|
-
return
|
|
6532
|
-
code: "STORAGE_ERROR",
|
|
6533
|
-
cause: new Error(
|
|
6534
|
-
`Failed to store rotated key blob: ${keyPutResult.error.message}`
|
|
6535
|
-
)
|
|
6536
|
-
});
|
|
6523
|
+
return kvWriteError("Failed to store rotated key blob", keyPutResult.error);
|
|
6537
6524
|
}
|
|
6538
6525
|
const valuePayload = JSON.stringify({
|
|
6539
6526
|
data: base64Encode(encrypted),
|
|
@@ -6544,12 +6531,7 @@ var init_dist2 = __esm({
|
|
|
6544
6531
|
valuePayload
|
|
6545
6532
|
);
|
|
6546
6533
|
if (!valuePutResult.ok) {
|
|
6547
|
-
return
|
|
6548
|
-
code: "STORAGE_ERROR",
|
|
6549
|
-
cause: new Error(
|
|
6550
|
-
`Failed to store re-encrypted value: ${valuePutResult.error.message}`
|
|
6551
|
-
)
|
|
6552
|
-
});
|
|
6534
|
+
return kvWriteError("Failed to store re-encrypted value", valuePutResult.error);
|
|
6553
6535
|
}
|
|
6554
6536
|
for (const did of remainingGrantees) {
|
|
6555
6537
|
const grantResult = await this.reencrypt(key, did);
|
|
@@ -7833,12 +7815,12 @@ function canonicalizeSpaceUri(space) {
|
|
|
7833
7815
|
}
|
|
7834
7816
|
function buildSecretSetupUrl(reference) {
|
|
7835
7817
|
const parameters = [
|
|
7836
|
-
["
|
|
7818
|
+
["secret", reference.name],
|
|
7837
7819
|
...reference.scope === void 0 ? [] : [["scope", reference.scope]],
|
|
7838
7820
|
["space", reference.space]
|
|
7839
7821
|
];
|
|
7840
7822
|
const query = parameters.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
|
|
7841
|
-
return `${SECRET_MANAGER_BASE_URL}?${query}`;
|
|
7823
|
+
return `${SECRET_MANAGER_BASE_URL}/app?${query}`;
|
|
7842
7824
|
}
|
|
7843
7825
|
function canonicalizeSecretScope(scope) {
|
|
7844
7826
|
if (scope === void 0 || scope === "") return void 0;
|