@warmhub/sdk-ts 0.47.0 → 0.49.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/{chunk-E32PSLWS.js → chunk-CVMYSRPS.js} +148 -23
- package/dist/chunk-CVMYSRPS.js.map +1 -0
- package/dist/index.d.ts +186 -18
- package/dist/index.js +1 -1
- package/dist/react.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-E32PSLWS.js.map +0 -1
|
@@ -604,16 +604,28 @@ function illegalOpSequences(operations, errors, checkAddAdd) {
|
|
|
604
604
|
}
|
|
605
605
|
|
|
606
606
|
// ../rules/src/reserved-orgs.ts
|
|
607
|
+
var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
|
|
608
|
+
"_app",
|
|
609
|
+
"_static",
|
|
610
|
+
"api",
|
|
611
|
+
"health",
|
|
612
|
+
"healthz",
|
|
613
|
+
"mcp",
|
|
614
|
+
"readyz",
|
|
615
|
+
"robots.txt",
|
|
616
|
+
"sse",
|
|
617
|
+
"trpc",
|
|
618
|
+
"version"
|
|
619
|
+
];
|
|
607
620
|
var RESERVED_ORG_NAMES = [
|
|
621
|
+
...RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES,
|
|
608
622
|
"admin",
|
|
609
|
-
"api",
|
|
610
623
|
"billing",
|
|
611
624
|
"blog",
|
|
612
625
|
"docs",
|
|
613
626
|
"help",
|
|
614
627
|
"login",
|
|
615
628
|
"public",
|
|
616
|
-
"robots.txt",
|
|
617
629
|
"settings",
|
|
618
630
|
"signup",
|
|
619
631
|
"status",
|
|
@@ -624,6 +636,15 @@ var RESERVED_ORG_NAMES = [
|
|
|
624
636
|
];
|
|
625
637
|
new Set(RESERVED_ORG_NAMES);
|
|
626
638
|
|
|
639
|
+
// ../rules/src/shape-field-key.ts
|
|
640
|
+
function foldFieldName(name) {
|
|
641
|
+
const stripped = name.endsWith("?") ? name.slice(0, -1) : name;
|
|
642
|
+
return stripped.toLowerCase();
|
|
643
|
+
}
|
|
644
|
+
function foldFieldPath(path) {
|
|
645
|
+
return path.split(".").map((segment) => foldFieldName(segment)).join(".");
|
|
646
|
+
}
|
|
647
|
+
|
|
627
648
|
// ../rules/src/shape-types.ts
|
|
628
649
|
var BASE_PRIMITIVE_TYPES = [
|
|
629
650
|
"number",
|
|
@@ -1006,6 +1027,37 @@ function collectIndexableShapeFieldPaths(fields, prefix = "") {
|
|
|
1006
1027
|
}
|
|
1007
1028
|
return paths;
|
|
1008
1029
|
}
|
|
1030
|
+
function isNestedFieldsRecord(value) {
|
|
1031
|
+
if (!isPlainObject(value) || Array.isArray(value)) return false;
|
|
1032
|
+
if (isTypeSpecObject(value)) return false;
|
|
1033
|
+
if ("type" in value && typeof value.type === "string" && VALID_PRIMITIVE_TYPES.has(value.type) && Object.keys(value).every((k) => VALID_TYPESPEC_KEYS.has(k))) {
|
|
1034
|
+
return false;
|
|
1035
|
+
}
|
|
1036
|
+
return true;
|
|
1037
|
+
}
|
|
1038
|
+
function validateFieldsRecord(fields, prefix, errors) {
|
|
1039
|
+
const seenDisplayByFolded = /* @__PURE__ */ new Map();
|
|
1040
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
1041
|
+
const folded = foldFieldName(key);
|
|
1042
|
+
const prior = seenDisplayByFolded.get(folded);
|
|
1043
|
+
if (prior !== void 0) {
|
|
1044
|
+
errors.push(
|
|
1045
|
+
`${prefix}.${key}: duplicate field name. Shape already declares "${prior}" (case-insensitive match).`
|
|
1046
|
+
);
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
seenDisplayByFolded.set(folded, key);
|
|
1050
|
+
if (isNestedFieldsRecord(value)) {
|
|
1051
|
+
validateFieldsRecord(
|
|
1052
|
+
value,
|
|
1053
|
+
`${prefix}.${key}`,
|
|
1054
|
+
errors
|
|
1055
|
+
);
|
|
1056
|
+
} else {
|
|
1057
|
+
validateTypeSpec(`${prefix}.${key}`, value, errors);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1009
1061
|
function validateShapeDefinition(data) {
|
|
1010
1062
|
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
1011
1063
|
return { valid: false, errors: ["Shape definition must be a plain object"] };
|
|
@@ -1030,11 +1082,7 @@ function validateShapeDefinition(data) {
|
|
|
1030
1082
|
errors: ['"fields" must be a plain object mapping field names to types']
|
|
1031
1083
|
};
|
|
1032
1084
|
}
|
|
1033
|
-
|
|
1034
|
-
fields
|
|
1035
|
-
)) {
|
|
1036
|
-
validateTypeSpec(`fields.${key}`, value, errors);
|
|
1037
|
-
}
|
|
1085
|
+
validateFieldsRecord(fields, "fields", errors);
|
|
1038
1086
|
const indexableFieldPaths = collectIndexableShapeFieldPaths(
|
|
1039
1087
|
fields
|
|
1040
1088
|
);
|
|
@@ -1042,15 +1090,16 @@ function validateShapeDefinition(data) {
|
|
|
1042
1090
|
const seenIndexableFieldPaths = /* @__PURE__ */ new Set();
|
|
1043
1091
|
const duplicateIndexableFieldPaths = /* @__PURE__ */ new Set();
|
|
1044
1092
|
for (const fieldPath of indexableFieldPaths) {
|
|
1045
|
-
|
|
1046
|
-
|
|
1093
|
+
const foldedPath = foldFieldPath(fieldPath);
|
|
1094
|
+
if (seenIndexableFieldPaths.has(foldedPath)) {
|
|
1095
|
+
duplicateIndexableFieldPaths.add(foldedPath);
|
|
1047
1096
|
continue;
|
|
1048
1097
|
}
|
|
1049
|
-
seenIndexableFieldPaths.add(
|
|
1098
|
+
seenIndexableFieldPaths.add(foldedPath);
|
|
1050
1099
|
}
|
|
1051
1100
|
for (const fieldPath of duplicateIndexableFieldPaths) {
|
|
1052
1101
|
errors.push(
|
|
1053
|
-
`Shape declares ambiguous indexable field path "${fieldPath}"; dotted field names
|
|
1102
|
+
`Shape declares ambiguous indexable field path "${fieldPath}"; dotted field names, optional-key suffixes, and case-insensitive folded paths must not collide with another indexable path`
|
|
1054
1103
|
);
|
|
1055
1104
|
}
|
|
1056
1105
|
if (indexableFieldCount > MAX_INDEXABLE_SCALAR_FIELDS_PER_SHAPE) {
|
|
@@ -1445,12 +1494,18 @@ new Set(
|
|
|
1445
1494
|
|
|
1446
1495
|
// src/operation-normalize.ts
|
|
1447
1496
|
function toBackendStreamOperation(operation) {
|
|
1497
|
+
if (operation.expectedVersion !== void 0 && operation.operation !== "revise") {
|
|
1498
|
+
throw new Error(
|
|
1499
|
+
"expectedVersion is only valid on revise operations \u2014 set operation: 'revise'"
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1448
1502
|
if (operation.operation === "retract") {
|
|
1449
1503
|
return {
|
|
1450
1504
|
operation: "retract",
|
|
1451
1505
|
name: operation.name,
|
|
1452
1506
|
...operation.kind ? { kind: operation.kind } : {},
|
|
1453
|
-
...operation.reason ? { reason: operation.reason } : {}
|
|
1507
|
+
...operation.reason ? { reason: operation.reason } : {},
|
|
1508
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
1454
1509
|
};
|
|
1455
1510
|
}
|
|
1456
1511
|
if (operation.operation === "revise") {
|
|
@@ -1477,14 +1532,18 @@ function toBackendStreamOperation(operation) {
|
|
|
1477
1532
|
operation: "revise",
|
|
1478
1533
|
kind: "assertion",
|
|
1479
1534
|
name,
|
|
1480
|
-
data: operation.data
|
|
1535
|
+
data: operation.data,
|
|
1536
|
+
...operation.expectedVersion !== void 0 ? { expectedVersion: operation.expectedVersion } : {},
|
|
1537
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
1481
1538
|
};
|
|
1482
1539
|
}
|
|
1483
1540
|
return {
|
|
1484
1541
|
operation: "revise",
|
|
1485
1542
|
kind: kind2,
|
|
1486
1543
|
name,
|
|
1487
|
-
data: operation.data
|
|
1544
|
+
data: operation.data,
|
|
1545
|
+
...operation.expectedVersion !== void 0 ? { expectedVersion: operation.expectedVersion } : {},
|
|
1546
|
+
...operation.leaseId ? { leaseId: operation.leaseId } : {}
|
|
1488
1547
|
};
|
|
1489
1548
|
}
|
|
1490
1549
|
const kind = operation.kind ?? inferKind(operation.name, operation);
|
|
@@ -2206,7 +2265,8 @@ var OperationBuilder = class {
|
|
|
2206
2265
|
operation: "retract",
|
|
2207
2266
|
name: target.name,
|
|
2208
2267
|
...target.kind ? { kind: target.kind } : {},
|
|
2209
|
-
...target.reason ? { reason: target.reason } : {}
|
|
2268
|
+
...target.reason ? { reason: target.reason } : {},
|
|
2269
|
+
...target.leaseId ? { leaseId: target.leaseId } : {}
|
|
2210
2270
|
});
|
|
2211
2271
|
this.ops.push(op);
|
|
2212
2272
|
return this;
|
|
@@ -2450,7 +2510,8 @@ function toBackendOp(op) {
|
|
|
2450
2510
|
operation: "retract",
|
|
2451
2511
|
name: op.name,
|
|
2452
2512
|
...op.kind ? { kind: op.kind } : {},
|
|
2453
|
-
...op.reason ? { reason: op.reason } : {}
|
|
2513
|
+
...op.reason ? { reason: op.reason } : {},
|
|
2514
|
+
...op.leaseId ? { leaseId: op.leaseId } : {}
|
|
2454
2515
|
};
|
|
2455
2516
|
}
|
|
2456
2517
|
if (op.operation === "add") {
|
|
@@ -2516,7 +2577,9 @@ function toBackendOp(op) {
|
|
|
2516
2577
|
operation: "revise",
|
|
2517
2578
|
kind,
|
|
2518
2579
|
name,
|
|
2519
|
-
data: op.data ?? {}
|
|
2580
|
+
data: op.data ?? {},
|
|
2581
|
+
...op.expectedVersion !== void 0 ? { expectedVersion: op.expectedVersion } : {},
|
|
2582
|
+
...op.leaseId ? { leaseId: op.leaseId } : {}
|
|
2520
2583
|
};
|
|
2521
2584
|
}
|
|
2522
2585
|
function toPreflightOp(op, kind) {
|
|
@@ -2589,7 +2652,7 @@ function preflightCheckRevise(kind, name, data) {
|
|
|
2589
2652
|
function normalizeWref(wref) {
|
|
2590
2653
|
return wref.replace(/@(?:v\d+|HEAD|ALL)$/i, "");
|
|
2591
2654
|
}
|
|
2592
|
-
var SDK_VERSION = "0.
|
|
2655
|
+
var SDK_VERSION = "0.49.0" ;
|
|
2593
2656
|
var DEFAULT_API_URL = "https://api.warmhub.ai";
|
|
2594
2657
|
var UNBATCHED_TRPC_PATHS = /* @__PURE__ */ new Set([
|
|
2595
2658
|
"repo.shapeInstanceCounts",
|
|
@@ -2721,7 +2784,16 @@ var WarmHubError = class extends Error {
|
|
|
2721
2784
|
* generic `BACKEND` fallback), branch on {@link code} or {@link kind}.
|
|
2722
2785
|
*/
|
|
2723
2786
|
backendCode;
|
|
2724
|
-
|
|
2787
|
+
/**
|
|
2788
|
+
* Structured backend error details, when the response carried them. Branch on
|
|
2789
|
+
* `details.reason`: an `expected_version_mismatch` carries
|
|
2790
|
+
* `expectedVersion`/`currentVersion` so an optimistic-concurrency caller can
|
|
2791
|
+
* re-read HEAD and retry (#3624); a `lease_held` carries `leaseExpiresAt` so a
|
|
2792
|
+
* caller can back off until the lease expires (#3625). Present only when the
|
|
2793
|
+
* backend wire carried `data.warmhub.details`. See {@link WarmHubErrorDetails}.
|
|
2794
|
+
*/
|
|
2795
|
+
details;
|
|
2796
|
+
constructor(code, message, status, hint, retryAfter, backendCode, details) {
|
|
2725
2797
|
super(message);
|
|
2726
2798
|
this.name = "WarmHubError";
|
|
2727
2799
|
this.code = code;
|
|
@@ -2729,6 +2801,7 @@ var WarmHubError = class extends Error {
|
|
|
2729
2801
|
this.hint = hint;
|
|
2730
2802
|
this.retryAfter = retryAfter;
|
|
2731
2803
|
this.backendCode = backendCode;
|
|
2804
|
+
this.details = details;
|
|
2732
2805
|
}
|
|
2733
2806
|
get kind() {
|
|
2734
2807
|
return this.code;
|
|
@@ -2757,7 +2830,8 @@ function toWarmHubError(error) {
|
|
|
2757
2830
|
data?.warmhub?.status,
|
|
2758
2831
|
data?.warmhub?.hint,
|
|
2759
2832
|
data?.warmhub?.retryAfter,
|
|
2760
|
-
wireCode
|
|
2833
|
+
wireCode,
|
|
2834
|
+
data?.warmhub?.details
|
|
2761
2835
|
);
|
|
2762
2836
|
}
|
|
2763
2837
|
if (error instanceof Error) {
|
|
@@ -2769,7 +2843,8 @@ function toWarmHubError(error) {
|
|
|
2769
2843
|
typeof warmhubLike.status === "number" ? warmhubLike.status : void 0,
|
|
2770
2844
|
typeof warmhubLike.hint === "string" ? warmhubLike.hint : void 0,
|
|
2771
2845
|
typeof warmhubLike.retryAfter === "number" ? warmhubLike.retryAfter : void 0,
|
|
2772
|
-
typeof warmhubLike.backendCode === "string" ? warmhubLike.backendCode : void 0
|
|
2846
|
+
typeof warmhubLike.backendCode === "string" ? warmhubLike.backendCode : void 0,
|
|
2847
|
+
warmhubLike.details
|
|
2773
2848
|
);
|
|
2774
2849
|
}
|
|
2775
2850
|
if (error.name === "AbortError") {
|
|
@@ -4423,6 +4498,56 @@ var WarmHubClient = class _WarmHubClient {
|
|
|
4423
4498
|
throw toWarmHubError(error);
|
|
4424
4499
|
}
|
|
4425
4500
|
},
|
|
4501
|
+
/**
|
|
4502
|
+
* Acquire a short, bounded, exclusive lease on a thing AND read it in one
|
|
4503
|
+
* atomic round trip (#3625).
|
|
4504
|
+
*
|
|
4505
|
+
* Returns everything {@link WarmHub.thing.get} returns plus a `lease`
|
|
4506
|
+
* block; the holder echoes `lease.id` back as `leaseId` on the subsequent
|
|
4507
|
+
* `revise`/`retract` (auto-releasing the lease) or calls
|
|
4508
|
+
* {@link WarmHub.thing.releaseLease} to return it early. Requires
|
|
4509
|
+
* `things:write` — never anonymous.
|
|
4510
|
+
*
|
|
4511
|
+
* Fail-fast: if another holder already holds an active lease, throws a
|
|
4512
|
+
* `WarmHubError` with `kind === 'LEASE_UNAVAILABLE'` and
|
|
4513
|
+
* `error.details?.reason === 'lease_held'` (read `leaseExpiresAt` to back
|
|
4514
|
+
* off until expiry). `ttlMs` out of the backend's bounds (default 5s /
|
|
4515
|
+
* min 1s / max 30s) is rejected, never clamped.
|
|
4516
|
+
*/
|
|
4517
|
+
getWithLease: async (orgName, repoName, wref, opts) => {
|
|
4518
|
+
try {
|
|
4519
|
+
return await this.trpc.thing.getWithLease.mutate({
|
|
4520
|
+
orgName,
|
|
4521
|
+
repoName,
|
|
4522
|
+
wref,
|
|
4523
|
+
ttlMs: opts?.ttlMs
|
|
4524
|
+
});
|
|
4525
|
+
} catch (error) {
|
|
4526
|
+
throw toWarmHubError(error);
|
|
4527
|
+
}
|
|
4528
|
+
},
|
|
4529
|
+
/**
|
|
4530
|
+
* Release a lease early (#3625), closing the acquire↔release loop without
|
|
4531
|
+
* waiting out the TTL.
|
|
4532
|
+
*
|
|
4533
|
+
* Idempotent and owner-gated: releasing an absent, already-released,
|
|
4534
|
+
* expired, or non-matching lease is a benign no-op (no error). A
|
|
4535
|
+
* successful `revise`/`retract` carrying the `leaseId` already
|
|
4536
|
+
* auto-releases the lease, so this is only needed when the holder decides
|
|
4537
|
+
* not to mutate. Requires `things:write`.
|
|
4538
|
+
*/
|
|
4539
|
+
releaseLease: async (orgName, repoName, wref, leaseId) => {
|
|
4540
|
+
try {
|
|
4541
|
+
await this.trpc.thing.releaseLease.mutate({
|
|
4542
|
+
orgName,
|
|
4543
|
+
repoName,
|
|
4544
|
+
wref,
|
|
4545
|
+
leaseId
|
|
4546
|
+
});
|
|
4547
|
+
} catch (error) {
|
|
4548
|
+
throw toWarmHubError(error);
|
|
4549
|
+
}
|
|
4550
|
+
},
|
|
4426
4551
|
/**
|
|
4427
4552
|
* Get one record and its embedded assertion, about, and wref graph.
|
|
4428
4553
|
*
|
|
@@ -5399,5 +5524,5 @@ function isAbortError(error) {
|
|
|
5399
5524
|
}
|
|
5400
5525
|
|
|
5401
5526
|
export { AllStreamOperationsFailedError, CLI_INSTALL_REPO_HEADER, CLI_SIGNATURE_HEADER, CLI_TIMESTAMP_HEADER, CONTENT_FIELD_LIMIT_ERROR, CliCallVerificationError, DEFAULT_API_URL, DEFAULT_STREAM_CHUNK_SIZE, MAX_CONTENT_FIELD_BYTES, MAX_STREAM_APPEND_OPERATION_COUNT2 as MAX_STREAM_APPEND_OPERATION_COUNT, OperationBuilder, PartialStreamSubmissionError, SDK_VERSION, WarmHubClient, WarmHubError, connectionErrorMessage, contentFieldLimitError, countStreamAppendResultStatuses, isConnectionError, isRetryable, isWarmHubError, normalizeWref, resolveFunctionLogMode, sanitizeErrorMessage, sdkVersionIsBelowMinimum, streamAppendResultStatus, submitOperationsViaStream, toWarmHubError, validateAgainstShape, verifyCliCall };
|
|
5402
|
-
//# sourceMappingURL=chunk-
|
|
5403
|
-
//# sourceMappingURL=chunk-
|
|
5527
|
+
//# sourceMappingURL=chunk-CVMYSRPS.js.map
|
|
5528
|
+
//# sourceMappingURL=chunk-CVMYSRPS.js.map
|