@tinycloud/operations 0.3.4-beta.0 → 0.3.4-beta.2
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 +84 -71
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.js +84 -71
- package/dist/artifacts.js.map +1 -1
- package/dist/cli-runtime.cjs +84 -71
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +84 -71
- package/dist/cli-runtime.js.map +1 -1
- package/dist/index.cjs +84 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +84 -71
- package/dist/index.js.map +1 -1
- package/dist/profile.cjs.map +1 -1
- package/dist/profile.js.map +1 -1
- package/dist/state.cjs +9 -4
- package/dist/state.cjs.map +1 -1
- package/dist/state.js +9 -4
- package/dist/state.js.map +1 -1
- package/package.json +3 -3
package/dist/artifacts.js
CHANGED
|
@@ -1636,7 +1636,7 @@ var KVService = class extends BaseService {
|
|
|
1636
1636
|
return err(
|
|
1637
1637
|
storageQuotaExceededError(
|
|
1638
1638
|
"kv",
|
|
1639
|
-
`Storage quota exceeded for key
|
|
1639
|
+
`Storage quota exceeded for key ${JSON.stringify(key)}: ${errorText}`,
|
|
1640
1640
|
{
|
|
1641
1641
|
status: response.status,
|
|
1642
1642
|
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
@@ -1649,7 +1649,7 @@ var KVService = class extends BaseService {
|
|
|
1649
1649
|
return err(
|
|
1650
1650
|
storageLimitReachedError(
|
|
1651
1651
|
"kv",
|
|
1652
|
-
`Storage limit reached for key
|
|
1652
|
+
`Storage limit reached for key ${JSON.stringify(key)}: ${errorText}`,
|
|
1653
1653
|
{
|
|
1654
1654
|
status: response.status,
|
|
1655
1655
|
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
@@ -1935,12 +1935,11 @@ var KVService = class extends BaseService {
|
|
|
1935
1935
|
if (!response.ok) {
|
|
1936
1936
|
const errorText = await response.text();
|
|
1937
1937
|
if (response.status === 401 || response.status === 403) {
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
}));
|
|
1938
|
+
return this.authorizationFailure(
|
|
1939
|
+
`Failed to batch read ${keys.length} key(s)`,
|
|
1940
|
+
response,
|
|
1941
|
+
errorText
|
|
1942
|
+
);
|
|
1944
1943
|
}
|
|
1945
1944
|
if (response.status === 413) {
|
|
1946
1945
|
return err(serviceError(
|
|
@@ -2039,23 +2038,39 @@ var KVService = class extends BaseService {
|
|
|
2039
2038
|
} catch {
|
|
2040
2039
|
}
|
|
2041
2040
|
if (response.status === 401 || response.status === 403) {
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
}));
|
|
2041
|
+
return this.authorizationFailure(
|
|
2042
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}`,
|
|
2043
|
+
response,
|
|
2044
|
+
errorText
|
|
2045
|
+
);
|
|
2048
2046
|
}
|
|
2049
2047
|
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
2050
2048
|
return err(
|
|
2051
2049
|
serviceError(
|
|
2052
2050
|
code,
|
|
2053
|
-
`Failed to create signed read URL for key
|
|
2051
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2054
2052
|
"kv",
|
|
2055
2053
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2056
2054
|
)
|
|
2057
2055
|
);
|
|
2058
2056
|
}
|
|
2057
|
+
/**
|
|
2058
|
+
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
2059
|
+
* status and the server text (`<context>: <status> - <text>`, the same
|
|
2060
|
+
* shape as every other KV failure) so callers that rethrow only the message
|
|
2061
|
+
* still see the status; `meta.status` carries it for typed callers.
|
|
2062
|
+
* Resource/ability hints are parsed from the raw body, never the message.
|
|
2063
|
+
*/
|
|
2064
|
+
authorizationFailure(context, response, errorText, extraMeta = {}) {
|
|
2065
|
+
const { resource, action } = parseAuthError(errorText);
|
|
2066
|
+
const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
|
|
2067
|
+
return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
|
|
2068
|
+
status: response.status,
|
|
2069
|
+
...action && { requiredAction: action },
|
|
2070
|
+
...resource && { resource },
|
|
2071
|
+
...extraMeta
|
|
2072
|
+
}));
|
|
2073
|
+
}
|
|
2059
2074
|
normalizeSignedReadUrlResponse(data) {
|
|
2060
2075
|
if (!data || typeof data !== "object") {
|
|
2061
2076
|
return void 0;
|
|
@@ -2098,14 +2113,13 @@ var KVService = class extends BaseService {
|
|
|
2098
2113
|
if (!response.ok) {
|
|
2099
2114
|
if (response.status === 401 || response.status === 403) {
|
|
2100
2115
|
const errorText2 = await response.text();
|
|
2101
|
-
const { resource, action } = parseAuthError(errorText2);
|
|
2102
2116
|
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
2103
|
-
return
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2117
|
+
return this.authorizationFailure(
|
|
2118
|
+
`Failed to get key ${JSON.stringify(key)}`,
|
|
2119
|
+
response,
|
|
2120
|
+
errorText2,
|
|
2121
|
+
permissionHint === void 0 ? {} : { permissionHint }
|
|
2122
|
+
);
|
|
2109
2123
|
}
|
|
2110
2124
|
if (response.status === 404) {
|
|
2111
2125
|
return this.classifyNotFound(response, key);
|
|
@@ -2114,7 +2128,7 @@ var KVService = class extends BaseService {
|
|
|
2114
2128
|
if (response.status === 413) {
|
|
2115
2129
|
return err(serviceError(
|
|
2116
2130
|
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
2117
|
-
`KV value at key
|
|
2131
|
+
`KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
|
|
2118
2132
|
"kv",
|
|
2119
2133
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2120
2134
|
));
|
|
@@ -2122,7 +2136,7 @@ var KVService = class extends BaseService {
|
|
|
2122
2136
|
return err(
|
|
2123
2137
|
serviceError(
|
|
2124
2138
|
ErrorCodes.NETWORK_ERROR,
|
|
2125
|
-
`Failed to get key
|
|
2139
|
+
`Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2126
2140
|
"kv",
|
|
2127
2141
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2128
2142
|
)
|
|
@@ -2178,21 +2192,18 @@ var KVService = class extends BaseService {
|
|
|
2178
2192
|
}
|
|
2179
2193
|
);
|
|
2180
2194
|
if (response.status === 401 || response.status === 403) {
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
...requiredAction && { requiredAction },
|
|
2187
|
-
...resource && { resource }
|
|
2188
|
-
}));
|
|
2195
|
+
return this.authorizationFailure(
|
|
2196
|
+
`Failed to put key ${JSON.stringify(key)}`,
|
|
2197
|
+
response,
|
|
2198
|
+
await response.text()
|
|
2199
|
+
);
|
|
2189
2200
|
}
|
|
2190
2201
|
if (!response.ok) {
|
|
2191
2202
|
const errorText = await response.text();
|
|
2192
2203
|
if (response.status === 412) {
|
|
2193
2204
|
return err(serviceError(
|
|
2194
2205
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
2195
|
-
`KV precondition failed for key
|
|
2206
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
2196
2207
|
"kv",
|
|
2197
2208
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2198
2209
|
));
|
|
@@ -2200,7 +2211,7 @@ var KVService = class extends BaseService {
|
|
|
2200
2211
|
if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
|
|
2201
2212
|
return err(serviceError(
|
|
2202
2213
|
ErrorCodes.KV_CONFLICT,
|
|
2203
|
-
`Concurrent KV update conflicted for key
|
|
2214
|
+
`Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
|
|
2204
2215
|
"kv",
|
|
2205
2216
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2206
2217
|
));
|
|
@@ -2216,7 +2227,7 @@ var KVService = class extends BaseService {
|
|
|
2216
2227
|
return err(
|
|
2217
2228
|
serviceError(
|
|
2218
2229
|
ErrorCodes.KV_WRITE_FAILED,
|
|
2219
|
-
`Failed to put key
|
|
2230
|
+
`Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2220
2231
|
"kv",
|
|
2221
2232
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2222
2233
|
)
|
|
@@ -2310,12 +2321,11 @@ var KVService = class extends BaseService {
|
|
|
2310
2321
|
);
|
|
2311
2322
|
}
|
|
2312
2323
|
if (response.status === 401 || response.status === 403) {
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
}));
|
|
2324
|
+
return this.authorizationFailure(
|
|
2325
|
+
`Failed to batch put ${items.length} key(s)`,
|
|
2326
|
+
response,
|
|
2327
|
+
errorText
|
|
2328
|
+
);
|
|
2319
2329
|
}
|
|
2320
2330
|
const quotaError = this.handleQuotaErrorResponse(
|
|
2321
2331
|
response,
|
|
@@ -2436,13 +2446,11 @@ var KVService = class extends BaseService {
|
|
|
2436
2446
|
);
|
|
2437
2447
|
if (!response.ok) {
|
|
2438
2448
|
if (response.status === 401) {
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
...resource && { resource }
|
|
2445
|
-
}));
|
|
2449
|
+
return this.authorizationFailure(
|
|
2450
|
+
"Failed to list keys",
|
|
2451
|
+
response,
|
|
2452
|
+
await response.text()
|
|
2453
|
+
);
|
|
2446
2454
|
}
|
|
2447
2455
|
const errorText = await response.text();
|
|
2448
2456
|
return err(
|
|
@@ -2491,13 +2499,11 @@ var KVService = class extends BaseService {
|
|
|
2491
2499
|
);
|
|
2492
2500
|
if (!response.ok) {
|
|
2493
2501
|
if (response.status === 401) {
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
...resource && { resource }
|
|
2500
|
-
}));
|
|
2502
|
+
return this.authorizationFailure(
|
|
2503
|
+
`Failed to delete key ${JSON.stringify(key)}`,
|
|
2504
|
+
response,
|
|
2505
|
+
await response.text()
|
|
2506
|
+
);
|
|
2501
2507
|
}
|
|
2502
2508
|
if (response.status === 404) {
|
|
2503
2509
|
return this.classifyNotFound(response, key);
|
|
@@ -2506,7 +2512,7 @@ var KVService = class extends BaseService {
|
|
|
2506
2512
|
if (response.status === 412) {
|
|
2507
2513
|
return err(serviceError(
|
|
2508
2514
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
2509
|
-
`KV precondition failed for key
|
|
2515
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
2510
2516
|
"kv",
|
|
2511
2517
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2512
2518
|
));
|
|
@@ -2514,7 +2520,7 @@ var KVService = class extends BaseService {
|
|
|
2514
2520
|
if (response.status === 503 && options?.ifMatch !== void 0) {
|
|
2515
2521
|
return err(serviceError(
|
|
2516
2522
|
ErrorCodes.KV_CONFLICT,
|
|
2517
|
-
`Concurrent KV delete conflicted for key
|
|
2523
|
+
`Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
|
|
2518
2524
|
"kv",
|
|
2519
2525
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2520
2526
|
));
|
|
@@ -2522,7 +2528,7 @@ var KVService = class extends BaseService {
|
|
|
2522
2528
|
return err(
|
|
2523
2529
|
serviceError(
|
|
2524
2530
|
ErrorCodes.NETWORK_ERROR,
|
|
2525
|
-
`Failed to delete key
|
|
2531
|
+
`Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2526
2532
|
"kv",
|
|
2527
2533
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2528
2534
|
)
|
|
@@ -2555,13 +2561,11 @@ var KVService = class extends BaseService {
|
|
|
2555
2561
|
);
|
|
2556
2562
|
if (!response.ok) {
|
|
2557
2563
|
if (response.status === 401) {
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
...resource && { resource }
|
|
2564
|
-
}));
|
|
2564
|
+
return this.authorizationFailure(
|
|
2565
|
+
`Failed to get metadata for key ${JSON.stringify(key)}`,
|
|
2566
|
+
response,
|
|
2567
|
+
await response.text()
|
|
2568
|
+
);
|
|
2565
2569
|
}
|
|
2566
2570
|
if (response.status === 404) {
|
|
2567
2571
|
return this.classifyNotFound(response, key);
|
|
@@ -2570,7 +2574,7 @@ var KVService = class extends BaseService {
|
|
|
2570
2574
|
return err(
|
|
2571
2575
|
serviceError(
|
|
2572
2576
|
ErrorCodes.NETWORK_ERROR,
|
|
2573
|
-
`Failed to get metadata for key
|
|
2577
|
+
`Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2574
2578
|
"kv",
|
|
2575
2579
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2576
2580
|
)
|
|
@@ -4029,10 +4033,14 @@ async function responseError(service, message, response) {
|
|
|
4029
4033
|
}
|
|
4030
4034
|
} catch {
|
|
4031
4035
|
}
|
|
4032
|
-
|
|
4036
|
+
const error = wrapError(
|
|
4033
4037
|
service,
|
|
4034
4038
|
new Error(`${message}: ${response.status} ${detail}`)
|
|
4035
4039
|
);
|
|
4040
|
+
return {
|
|
4041
|
+
...error,
|
|
4042
|
+
meta: { ...error.meta, status: response.status, statusText: response.statusText }
|
|
4043
|
+
};
|
|
4036
4044
|
}
|
|
4037
4045
|
function isAbortError(error) {
|
|
4038
4046
|
return error instanceof DOMException && error.name === "AbortError";
|
|
@@ -7066,9 +7074,12 @@ async function acquireProfileLock(profile, options) {
|
|
|
7066
7074
|
const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_LOCK_MS;
|
|
7067
7075
|
const startedAt = Date.now();
|
|
7068
7076
|
const lockPath = profileLockPath(profile);
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7077
|
+
const directory = profilePath(profile);
|
|
7078
|
+
await mkdir(directory, { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
7079
|
+
for (const path of [tinycloudHomePath(), profilesPath(), directory]) {
|
|
7080
|
+
await chmod(path, PRIVATE_DIR_MODE).catch((error) => {
|
|
7081
|
+
if (path !== directory || !isErrno(error, "ENOENT")) throw error;
|
|
7082
|
+
});
|
|
7072
7083
|
}
|
|
7073
7084
|
while (true) {
|
|
7074
7085
|
const token = randomUUID();
|
|
@@ -7091,7 +7102,9 @@ async function publishProfileLock(profile, lockPath, token) {
|
|
|
7091
7102
|
await mkdir(lockPath, { mode: PRIVATE_DIR_MODE });
|
|
7092
7103
|
} catch (error) {
|
|
7093
7104
|
if (isErrno(error, "EEXIST")) return false;
|
|
7094
|
-
throw error;
|
|
7105
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
7106
|
+
await mkdir(profilePath(profile), { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
7107
|
+
return false;
|
|
7095
7108
|
}
|
|
7096
7109
|
await waitForTestBarrier(TEST_LOCK_PUBLISH_BARRIER_DIR, profile);
|
|
7097
7110
|
const staged = join(dirname(lockPath), `.lock-owner-${token}.tmp`);
|