@warmhub/cli 0.66.0 → 0.68.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/wh.js +1267 -304
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -18478,10 +18478,21 @@ var import_awaitAsyncGenerator = __toESM(require_awaitAsyncGenerator(), 1);
|
|
|
18478
18478
|
var import_wrapAsyncGenerator = __toESM(require_wrapAsyncGenerator(), 1);
|
|
18479
18479
|
var import_objectSpread29 = __toESM(require_objectSpread2(), 1);
|
|
18480
18480
|
// ../../packages/rules/src/builtin-shapes.ts
|
|
18481
|
-
var BUILTIN_SHAPE_NAMES = ["Pair", "
|
|
18481
|
+
var BUILTIN_SHAPE_NAMES = ["Pair", "Set", "List"];
|
|
18482
|
+
var RETIRED_COLLECTION_SHAPE_NAMES = ["Triple"];
|
|
18483
|
+
var RESERVED_COLLECTION_SHAPE_NAMES = [
|
|
18484
|
+
...BUILTIN_SHAPE_NAMES,
|
|
18485
|
+
...RETIRED_COLLECTION_SHAPE_NAMES
|
|
18486
|
+
];
|
|
18482
18487
|
function isBuiltinCollectionShape(name) {
|
|
18483
18488
|
return BUILTIN_SHAPE_NAMES.includes(name);
|
|
18484
18489
|
}
|
|
18490
|
+
function isRetiredCollectionShape(name) {
|
|
18491
|
+
return RETIRED_COLLECTION_SHAPE_NAMES.includes(name);
|
|
18492
|
+
}
|
|
18493
|
+
function isReservedCollectionShape(name) {
|
|
18494
|
+
return RESERVED_COLLECTION_SHAPE_NAMES.includes(name);
|
|
18495
|
+
}
|
|
18485
18496
|
var BUILTIN_CONTENT_SHAPE_NAMES = ["Content"];
|
|
18486
18497
|
var STORED_CONTENT_NAMES = ["Readme", "Agents"];
|
|
18487
18498
|
var SYNTHESIZED_CONTENT_NAMES = ["LlmsTxt"];
|
|
@@ -18499,14 +18510,6 @@ var BUILTIN_SHAPE_DEFS = {
|
|
|
18499
18510
|
},
|
|
18500
18511
|
description: "An ordered pair of two things"
|
|
18501
18512
|
},
|
|
18502
|
-
Triple: {
|
|
18503
|
-
fields: {
|
|
18504
|
-
first: { type: "wref", description: "First member of the triple" },
|
|
18505
|
-
second: { type: "wref", description: "Second member of the triple" },
|
|
18506
|
-
third: { type: "wref", description: "Third member of the triple" }
|
|
18507
|
-
},
|
|
18508
|
-
description: "An ordered triple of three things"
|
|
18509
|
-
},
|
|
18510
18513
|
Set: {
|
|
18511
18514
|
fields: {
|
|
18512
18515
|
members: [{ type: "wref", description: "Members of the set" }]
|
|
@@ -18553,36 +18556,6 @@ var COMMIT_OPERATION_KINDS = [
|
|
|
18553
18556
|
"assertion",
|
|
18554
18557
|
"collection"
|
|
18555
18558
|
];
|
|
18556
|
-
function isCollectionAbout(value) {
|
|
18557
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
18558
|
-
return false;
|
|
18559
|
-
const record = value;
|
|
18560
|
-
const keys = Object.keys(record);
|
|
18561
|
-
if (keys.length !== 1)
|
|
18562
|
-
return false;
|
|
18563
|
-
const key = keys[0];
|
|
18564
|
-
if (key !== "pair" && key !== "triple" && key !== "set" && key !== "list")
|
|
18565
|
-
return false;
|
|
18566
|
-
return Array.isArray(record[key]);
|
|
18567
|
-
}
|
|
18568
|
-
function collectionAboutType(about) {
|
|
18569
|
-
if ("pair" in about)
|
|
18570
|
-
return "pair";
|
|
18571
|
-
if ("triple" in about)
|
|
18572
|
-
return "triple";
|
|
18573
|
-
if ("set" in about)
|
|
18574
|
-
return "set";
|
|
18575
|
-
return "list";
|
|
18576
|
-
}
|
|
18577
|
-
function collectionAboutMembers(about) {
|
|
18578
|
-
if ("pair" in about)
|
|
18579
|
-
return about.pair;
|
|
18580
|
-
if ("triple" in about)
|
|
18581
|
-
return about.triple;
|
|
18582
|
-
if ("set" in about)
|
|
18583
|
-
return about.set;
|
|
18584
|
-
return about.list;
|
|
18585
|
-
}
|
|
18586
18559
|
function splitLocalPath(name) {
|
|
18587
18560
|
const idx = name.indexOf("/");
|
|
18588
18561
|
if (idx === -1)
|
|
@@ -18602,21 +18575,6 @@ function inferOperationKind(op) {
|
|
|
18602
18575
|
const segments = op.name ? op.name.split("/").filter(Boolean) : [];
|
|
18603
18576
|
return segments.length >= 3 ? "assertion" : "thing";
|
|
18604
18577
|
}
|
|
18605
|
-
// ../../packages/rules/src/component-manifest-hash.ts
|
|
18606
|
-
function stableJson(value) {
|
|
18607
|
-
if (!value || typeof value !== "object") {
|
|
18608
|
-
return JSON.stringify(value);
|
|
18609
|
-
}
|
|
18610
|
-
if (Array.isArray(value)) {
|
|
18611
|
-
return `[${value.map((entry) => stableJson(entry)).join(",")}]`;
|
|
18612
|
-
}
|
|
18613
|
-
const record = value;
|
|
18614
|
-
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
|
|
18615
|
-
}
|
|
18616
|
-
function stableJsonEquals(left, right) {
|
|
18617
|
-
return stableJson(left) === stableJson(right);
|
|
18618
|
-
}
|
|
18619
|
-
|
|
18620
18578
|
// ../../packages/rules/src/component-name-templates.ts
|
|
18621
18579
|
var COMPONENT_TEMPLATE_VALUES = {
|
|
18622
18580
|
"org-name": (ctx) => ctx.orgName,
|
|
@@ -18645,6 +18603,21 @@ function resolveComponentTemplate(value, ctx) {
|
|
|
18645
18603
|
});
|
|
18646
18604
|
}
|
|
18647
18605
|
|
|
18606
|
+
// ../../packages/rules/src/stable-json.ts
|
|
18607
|
+
function stableJson(value) {
|
|
18608
|
+
if (!value || typeof value !== "object") {
|
|
18609
|
+
return JSON.stringify(value);
|
|
18610
|
+
}
|
|
18611
|
+
if (Array.isArray(value)) {
|
|
18612
|
+
return `[${value.map((entry) => stableJson(entry)).join(",")}]`;
|
|
18613
|
+
}
|
|
18614
|
+
const record = value;
|
|
18615
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
|
|
18616
|
+
}
|
|
18617
|
+
function stableJsonEquals(left, right) {
|
|
18618
|
+
return stableJson(left) === stableJson(right);
|
|
18619
|
+
}
|
|
18620
|
+
|
|
18648
18621
|
// ../../packages/rules/src/component-install.ts
|
|
18649
18622
|
function manifestShapeData(shape) {
|
|
18650
18623
|
const data = { fields: shape.fields };
|
|
@@ -19949,9 +19922,99 @@ var PLATFORM_STATUS_PROBE_ARTIFACT_FIELDS = {
|
|
|
19949
19922
|
description: "Optional URL associated with this artifact."
|
|
19950
19923
|
}
|
|
19951
19924
|
};
|
|
19925
|
+
// ../../packages/rules/src/tokens.ts
|
|
19926
|
+
var COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE = "$N/#N commit-token syntax is no longer supported. Use explicit names and explicit wrefs. For assertions about newly created things, create the thing with a deterministic name and set about to that wref in the same commit.";
|
|
19927
|
+
var ANY_TOKEN_RE = /[$#]\d+/;
|
|
19928
|
+
function hasAnyTokens(s) {
|
|
19929
|
+
return ANY_TOKEN_RE.test(s);
|
|
19930
|
+
}
|
|
19931
|
+
|
|
19932
|
+
// ../../packages/rules/src/preflight-commit.ts
|
|
19933
|
+
function preflightCommitDiagnostics(operations, options) {
|
|
19934
|
+
const errors = [];
|
|
19935
|
+
rejectCommitTokenSyntax(operations, errors);
|
|
19936
|
+
illegalOpSequences(operations, errors, options?.checkAddAdd ?? true);
|
|
19937
|
+
return errors;
|
|
19938
|
+
}
|
|
19939
|
+
function getOpName(op) {
|
|
19940
|
+
return op.name;
|
|
19941
|
+
}
|
|
19942
|
+
function tokenStringFields(op) {
|
|
19943
|
+
const fields = [getOpName(op), op.newName];
|
|
19944
|
+
if (typeof op.about === "string") {
|
|
19945
|
+
fields.push(op.about);
|
|
19946
|
+
}
|
|
19947
|
+
if (op.members) {
|
|
19948
|
+
fields.push(...op.members);
|
|
19949
|
+
}
|
|
19950
|
+
return fields;
|
|
19951
|
+
}
|
|
19952
|
+
function rejectCommitTokenSyntax(operations, errors) {
|
|
19953
|
+
for (let i = 0;i < operations.length; i++) {
|
|
19954
|
+
const op = operations[i];
|
|
19955
|
+
if (!op)
|
|
19956
|
+
continue;
|
|
19957
|
+
for (const field of tokenStringFields(op)) {
|
|
19958
|
+
if (field && hasAnyTokens(field)) {
|
|
19959
|
+
errors.push({
|
|
19960
|
+
code: "COMMIT_TOKEN_SYNTAX_REMOVED",
|
|
19961
|
+
operationIndex: i,
|
|
19962
|
+
message: COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE
|
|
19963
|
+
});
|
|
19964
|
+
break;
|
|
19965
|
+
}
|
|
19966
|
+
}
|
|
19967
|
+
}
|
|
19968
|
+
}
|
|
19969
|
+
function illegalOpSequences(operations, errors, checkAddAdd) {
|
|
19970
|
+
const opHistory = new Map;
|
|
19971
|
+
for (let i = 0;i < operations.length; i++) {
|
|
19972
|
+
const op = operations[i];
|
|
19973
|
+
if (!op)
|
|
19974
|
+
continue;
|
|
19975
|
+
const name = getOpName(op);
|
|
19976
|
+
if (!name)
|
|
19977
|
+
continue;
|
|
19978
|
+
if (hasAnyTokens(name))
|
|
19979
|
+
continue;
|
|
19980
|
+
const kind = inferOperationKind({ ...op, name });
|
|
19981
|
+
const qualName = kind === "shape" ? `shape:${name}` : `thing:${name}`;
|
|
19982
|
+
const history = opHistory.get(qualName) ?? [];
|
|
19983
|
+
history.push({ operation: op.operation, index: i });
|
|
19984
|
+
opHistory.set(qualName, history);
|
|
19985
|
+
}
|
|
19986
|
+
for (const [qualName, history] of opHistory) {
|
|
19987
|
+
if (history.length < 2)
|
|
19988
|
+
continue;
|
|
19989
|
+
for (let i = 1;i < history.length; i++) {
|
|
19990
|
+
const prev = history[i - 1];
|
|
19991
|
+
const curr = history[i];
|
|
19992
|
+
if (!prev || !curr)
|
|
19993
|
+
continue;
|
|
19994
|
+
const pair = `${prev.operation}+${curr.operation}`;
|
|
19995
|
+
if (checkAddAdd && pair === "add+add") {
|
|
19996
|
+
errors.push({
|
|
19997
|
+
code: "ILLEGAL_OP_SEQUENCE",
|
|
19998
|
+
operationIndex: curr.index,
|
|
19999
|
+
message: `Cannot add "${qualName}" twice in the same commit`
|
|
20000
|
+
});
|
|
20001
|
+
}
|
|
20002
|
+
if (pair === "revise+add") {
|
|
20003
|
+
errors.push({
|
|
20004
|
+
code: "ILLEGAL_OP_SEQUENCE",
|
|
20005
|
+
operationIndex: curr.index,
|
|
20006
|
+
message: `Cannot revise then add "${qualName}" in the same commit`
|
|
20007
|
+
});
|
|
20008
|
+
}
|
|
20009
|
+
}
|
|
20010
|
+
}
|
|
20011
|
+
}
|
|
20012
|
+
|
|
19952
20013
|
// ../../packages/rules/src/preflight-operation.ts
|
|
19953
|
-
var collectionTypes = ["pair", "
|
|
20014
|
+
var collectionTypes = ["pair", "set", "list"];
|
|
19954
20015
|
var collectionOps = ["add", "revise"];
|
|
20016
|
+
var COLLECTION_CREATE_REQUIRES_NAME_MESSAGE = "Collection create requires a name. Collections are ordinary named things (ADR 0004).";
|
|
20017
|
+
var COLLECTION_ABOUT_REMOVED_MESSAGE = 'about accepts a wref. Create the collection as its own named operation, then point the assertion at it. Prefer deterministic relationship names, for example: [{"operation":"add","kind":"collection","type":"pair","name":"a-b-relationship","members":["A","B"]},{"operation":"add","kind":"assertion","about":"Pair/a-b-relationship","name":"Assertion/example","data":{}}]. For CLI usage, use wh commit submit --file with the two operations.';
|
|
19955
20018
|
function preflightOpDiagnostics(op, operationIndex) {
|
|
19956
20019
|
const errors = [];
|
|
19957
20020
|
errors.push(...builtinShapeGuard(op, operationIndex));
|
|
@@ -19964,17 +20027,36 @@ function preflightOpDiagnostics(op, operationIndex) {
|
|
|
19964
20027
|
function builtinShapeGuard(op, operationIndex) {
|
|
19965
20028
|
const errors = [];
|
|
19966
20029
|
const name = op.name;
|
|
19967
|
-
if (
|
|
20030
|
+
if (name && isRetiredCollectionShape(name)) {
|
|
20031
|
+
errors.push({
|
|
20032
|
+
code: "RESERVED_NAME",
|
|
20033
|
+
operationIndex,
|
|
20034
|
+
message: `Shape "${name}" is a retired collection shape and cannot be written manually`
|
|
20035
|
+
});
|
|
20036
|
+
}
|
|
20037
|
+
if (op.operation === "rename" && (op.kind === "shape" || op.name !== undefined && !splitLocalPath(op.name)) && op.newName && isRetiredCollectionShape(op.newName)) {
|
|
20038
|
+
errors.push({
|
|
20039
|
+
code: "RESERVED_NAME",
|
|
20040
|
+
operationIndex,
|
|
20041
|
+
message: `Shape "${op.newName}" is a retired collection shape and cannot be written manually`
|
|
20042
|
+
});
|
|
20043
|
+
} else if (op.operation !== "retract" && op.kind === "shape" && name && isBuiltinShape(name)) {
|
|
19968
20044
|
errors.push({
|
|
19969
20045
|
code: "RESERVED_NAME",
|
|
19970
20046
|
operationIndex,
|
|
19971
20047
|
message: `Shape "${name}" is a built-in shape and cannot be ${op.operation === "add" ? "created" : "revised"} manually`
|
|
19972
20048
|
});
|
|
19973
20049
|
}
|
|
19974
|
-
if (
|
|
20050
|
+
if (name) {
|
|
19975
20051
|
const local = splitLocalPath(name);
|
|
19976
|
-
if (local &&
|
|
19977
|
-
|
|
20052
|
+
if (local && isRetiredCollectionShape(local.shapePrefix)) {
|
|
20053
|
+
errors.push({
|
|
20054
|
+
code: "VALIDATION_ERROR",
|
|
20055
|
+
operationIndex,
|
|
20056
|
+
message: `Cannot ${op.operation} under retired collection shape "${local.shapePrefix}". Triple is read-only and retired for new collection writes.`
|
|
20057
|
+
});
|
|
20058
|
+
} else if (op.kind === "thing" && local && isBuiltinCollectionShape(local.shapePrefix)) {
|
|
20059
|
+
const message = op.operation === "add" ? `Cannot add kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" instead.` : `Cannot revise kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" to revise a collection.`;
|
|
19978
20060
|
errors.push({
|
|
19979
20061
|
code: "VALIDATION_ERROR",
|
|
19980
20062
|
operationIndex,
|
|
@@ -20014,16 +20096,32 @@ function contentNameGuard(op, operationIndex) {
|
|
|
20014
20096
|
function plusSignGuard(op, operationIndex) {
|
|
20015
20097
|
const errors = [];
|
|
20016
20098
|
const name = op.name;
|
|
20017
|
-
if (op.
|
|
20099
|
+
if (op.newName?.includes("+")) {
|
|
20100
|
+
errors.push({
|
|
20101
|
+
code: "VALIDATION_ERROR",
|
|
20102
|
+
operationIndex,
|
|
20103
|
+
message: `Name "${op.newName}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
|
|
20104
|
+
});
|
|
20018
20105
|
return errors;
|
|
20106
|
+
}
|
|
20019
20107
|
if (name?.includes("+")) {
|
|
20108
|
+
if (op.kind === "collection" && op.operation === "add") {
|
|
20109
|
+
errors.push({
|
|
20110
|
+
code: "VALIDATION_ERROR",
|
|
20111
|
+
operationIndex,
|
|
20112
|
+
message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
|
|
20113
|
+
});
|
|
20114
|
+
return errors;
|
|
20115
|
+
}
|
|
20116
|
+
if (op.kind === "collection")
|
|
20117
|
+
return errors;
|
|
20020
20118
|
const local = splitLocalPath(name);
|
|
20021
|
-
if (local &&
|
|
20119
|
+
if (local && isReservedCollectionShape(local.shapePrefix))
|
|
20022
20120
|
return errors;
|
|
20023
20121
|
errors.push({
|
|
20024
20122
|
code: "VALIDATION_ERROR",
|
|
20025
20123
|
operationIndex,
|
|
20026
|
-
message: `Name "${name}" contains reserved character "+". The "+" character is reserved for collection names.`
|
|
20124
|
+
message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
|
|
20027
20125
|
});
|
|
20028
20126
|
}
|
|
20029
20127
|
return errors;
|
|
@@ -20032,102 +20130,79 @@ function validateCollectionAbouts(op, operationIndex) {
|
|
|
20032
20130
|
const errors = [];
|
|
20033
20131
|
if (!op.about || typeof op.about === "string")
|
|
20034
20132
|
return errors;
|
|
20035
|
-
|
|
20036
|
-
|
|
20133
|
+
errors.push({
|
|
20134
|
+
code: "VALIDATION_ERROR",
|
|
20135
|
+
operationIndex,
|
|
20136
|
+
message: COLLECTION_ABOUT_REMOVED_MESSAGE
|
|
20137
|
+
});
|
|
20138
|
+
return errors;
|
|
20139
|
+
}
|
|
20140
|
+
function validateCollectionOps(op, operationIndex) {
|
|
20141
|
+
const errors = [];
|
|
20142
|
+
if (op.kind !== "collection")
|
|
20143
|
+
return errors;
|
|
20144
|
+
if (!collectionOps.includes(op.operation)) {
|
|
20145
|
+
return errors;
|
|
20146
|
+
}
|
|
20147
|
+
if (op.operation === "add" && !op.name) {
|
|
20037
20148
|
errors.push({
|
|
20038
20149
|
code: "VALIDATION_ERROR",
|
|
20039
20150
|
operationIndex,
|
|
20040
|
-
message:
|
|
20151
|
+
message: COLLECTION_CREATE_REQUIRES_NAME_MESSAGE
|
|
20041
20152
|
});
|
|
20042
|
-
return errors;
|
|
20043
|
-
}
|
|
20044
|
-
const tag = collectionAboutType(op.about);
|
|
20045
|
-
const members = collectionAboutMembers(op.about);
|
|
20046
|
-
for (let i = 0;i < members.length; i++) {
|
|
20047
|
-
if (typeof members[i] !== "string") {
|
|
20048
|
-
errors.push({
|
|
20049
|
-
code: "VALIDATION_ERROR",
|
|
20050
|
-
operationIndex,
|
|
20051
|
-
message: `Collection member at index ${i} must be a string, got ${typeof members[i]}`
|
|
20052
|
-
});
|
|
20053
|
-
}
|
|
20054
20153
|
}
|
|
20055
|
-
|
|
20056
|
-
if (arityError) {
|
|
20154
|
+
if (!op.type || !collectionTypes.includes(op.type)) {
|
|
20057
20155
|
errors.push({
|
|
20058
20156
|
code: "VALIDATION_ERROR",
|
|
20059
20157
|
operationIndex,
|
|
20060
|
-
message:
|
|
20158
|
+
message: `Collection "type" must be one of: pair, set, list. Got: "${op.type ?? ""}"`
|
|
20061
20159
|
});
|
|
20062
20160
|
}
|
|
20063
|
-
|
|
20064
|
-
}
|
|
20065
|
-
function validateCollectionOps(op, operationIndex) {
|
|
20066
|
-
const errors = [];
|
|
20067
|
-
if (op.kind !== "collection")
|
|
20068
|
-
return errors;
|
|
20069
|
-
if (!collectionOps.includes(op.operation)) {
|
|
20161
|
+
if (!op.members || !Array.isArray(op.members)) {
|
|
20070
20162
|
errors.push({
|
|
20071
20163
|
code: "VALIDATION_ERROR",
|
|
20072
20164
|
operationIndex,
|
|
20073
|
-
message:
|
|
20165
|
+
message: 'Collection requires a "members" array'
|
|
20074
20166
|
});
|
|
20075
|
-
|
|
20076
|
-
|
|
20077
|
-
|
|
20078
|
-
if (!op.type || !collectionTypes.includes(op.type)) {
|
|
20079
|
-
errors.push({
|
|
20080
|
-
code: "VALIDATION_ERROR",
|
|
20081
|
-
operationIndex,
|
|
20082
|
-
message: `Collection "type" must be one of: pair, triple, set, list. Got: "${op.type ?? ""}"`
|
|
20083
|
-
});
|
|
20084
|
-
}
|
|
20085
|
-
if (!op.members || !Array.isArray(op.members)) {
|
|
20086
|
-
errors.push({
|
|
20087
|
-
code: "VALIDATION_ERROR",
|
|
20088
|
-
operationIndex,
|
|
20089
|
-
message: 'Collection requires a "members" array'
|
|
20090
|
-
});
|
|
20091
|
-
} else {
|
|
20092
|
-
for (let i = 0;i < op.members.length; i++) {
|
|
20093
|
-
if (typeof op.members[i] !== "string") {
|
|
20094
|
-
errors.push({
|
|
20095
|
-
code: "VALIDATION_ERROR",
|
|
20096
|
-
operationIndex,
|
|
20097
|
-
message: `Collection member at index ${i} must be a string`
|
|
20098
|
-
});
|
|
20099
|
-
}
|
|
20100
|
-
}
|
|
20101
|
-
}
|
|
20102
|
-
if (op.type && op.members) {
|
|
20103
|
-
const arityError = collectionArityError(op.type, op.members);
|
|
20104
|
-
if (arityError) {
|
|
20167
|
+
} else {
|
|
20168
|
+
for (let i = 0;i < op.members.length; i++) {
|
|
20169
|
+
if (typeof op.members[i] !== "string") {
|
|
20105
20170
|
errors.push({
|
|
20106
20171
|
code: "VALIDATION_ERROR",
|
|
20107
20172
|
operationIndex,
|
|
20108
|
-
message:
|
|
20173
|
+
message: `Collection member at index ${i} must be a string`
|
|
20109
20174
|
});
|
|
20110
20175
|
}
|
|
20111
20176
|
}
|
|
20112
20177
|
}
|
|
20178
|
+
if (op.type && op.members) {
|
|
20179
|
+
const arityError = collectionArityError(op.type, op.members);
|
|
20180
|
+
if (arityError) {
|
|
20181
|
+
errors.push({
|
|
20182
|
+
code: "VALIDATION_ERROR",
|
|
20183
|
+
operationIndex,
|
|
20184
|
+
message: arityError
|
|
20185
|
+
});
|
|
20186
|
+
}
|
|
20187
|
+
}
|
|
20113
20188
|
return errors;
|
|
20114
20189
|
}
|
|
20115
20190
|
function collectionArityError(tag, members) {
|
|
20116
20191
|
switch (tag) {
|
|
20117
20192
|
case "pair":
|
|
20118
20193
|
return members.length !== 2 ? `Pair requires exactly 2 members, got ${members.length}` : null;
|
|
20119
|
-
case "triple":
|
|
20120
|
-
return members.length !== 3 ? `Triple requires exactly 3 members, got ${members.length}` : null;
|
|
20121
20194
|
case "set":
|
|
20122
20195
|
case "list":
|
|
20123
20196
|
return members.length < 1 ? `${tag === "set" ? "Set" : "List"} requires at least 1 member, got 0` : null;
|
|
20124
20197
|
}
|
|
20125
20198
|
}
|
|
20126
|
-
|
|
20127
20199
|
// ../../packages/rules/src/preflight.ts
|
|
20128
20200
|
function preflightOpDiagnostics2(op, operationIndex) {
|
|
20129
20201
|
return preflightOpDiagnostics(op, operationIndex);
|
|
20130
20202
|
}
|
|
20203
|
+
function preflightCommitDiagnostics2(operations, options) {
|
|
20204
|
+
return preflightCommitDiagnostics(operations, options);
|
|
20205
|
+
}
|
|
20131
20206
|
// ../../packages/rules/src/reserved-orgs.ts
|
|
20132
20207
|
var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
|
|
20133
20208
|
"_app",
|
|
@@ -27352,7 +27427,7 @@ function findSystemComponent(componentId) {
|
|
|
27352
27427
|
// ../../packages/sdk-ts/package.json
|
|
27353
27428
|
var package_default = {
|
|
27354
27429
|
name: "@warmhub/sdk-ts",
|
|
27355
|
-
version: "0.
|
|
27430
|
+
version: "0.67.0",
|
|
27356
27431
|
private: false,
|
|
27357
27432
|
type: "module",
|
|
27358
27433
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -27460,16 +27535,38 @@ function shapeDefinitionPreflightError(name, data, verb) {
|
|
|
27460
27535
|
}
|
|
27461
27536
|
|
|
27462
27537
|
// ../../packages/sdk-ts/src/collection-operation-normalize.ts
|
|
27463
|
-
var collectionTypes2 = new Set([
|
|
27464
|
-
"pair",
|
|
27465
|
-
"triple",
|
|
27466
|
-
"set",
|
|
27467
|
-
"list"
|
|
27468
|
-
]);
|
|
27538
|
+
var collectionTypes2 = new Set(["pair", "set", "list"]);
|
|
27469
27539
|
function normalizeBackendCollectionAdd(operation, source) {
|
|
27470
|
-
const
|
|
27540
|
+
const normalized = normalizeCollectionWrite(operation, source, "add");
|
|
27541
|
+
return {
|
|
27471
27542
|
operation: "add",
|
|
27472
27543
|
kind: "collection",
|
|
27544
|
+
name: normalized.name,
|
|
27545
|
+
type: normalized.type,
|
|
27546
|
+
members: normalized.members,
|
|
27547
|
+
...operation.skipExisting === true ? { skipExisting: true } : {}
|
|
27548
|
+
};
|
|
27549
|
+
}
|
|
27550
|
+
function normalizeBackendCollectionRevise(operation, source) {
|
|
27551
|
+
const normalized = normalizeCollectionWrite(operation, source, "revise");
|
|
27552
|
+
if (!normalized.name) {
|
|
27553
|
+
throw new Error(`${source}: collection revise requires a target name`);
|
|
27554
|
+
}
|
|
27555
|
+
return {
|
|
27556
|
+
operation: "revise",
|
|
27557
|
+
kind: "collection",
|
|
27558
|
+
name: normalized.name,
|
|
27559
|
+
type: normalized.type,
|
|
27560
|
+
members: normalized.members,
|
|
27561
|
+
...typeof operation.expectedVersion === "number" ? { expectedVersion: operation.expectedVersion } : {},
|
|
27562
|
+
...typeof operation.leaseId === "string" && operation.leaseId.length > 0 ? { leaseId: operation.leaseId } : {}
|
|
27563
|
+
};
|
|
27564
|
+
}
|
|
27565
|
+
function normalizeCollectionWrite(operation, source, writeOperation) {
|
|
27566
|
+
const diagnostics = preflightOpDiagnostics2({
|
|
27567
|
+
operation: writeOperation,
|
|
27568
|
+
kind: "collection",
|
|
27569
|
+
name: typeof operation.name === "string" ? operation.name : undefined,
|
|
27473
27570
|
type: typeof operation.type === "string" ? operation.type : undefined,
|
|
27474
27571
|
members: Array.isArray(operation.members) ? operation.members : undefined
|
|
27475
27572
|
}, 0);
|
|
@@ -27478,29 +27575,32 @@ function normalizeBackendCollectionAdd(operation, source) {
|
|
|
27478
27575
|
}
|
|
27479
27576
|
const type = normalizeCollectionType(operation.type);
|
|
27480
27577
|
if (!type) {
|
|
27481
|
-
throw new Error(`${source}: collection
|
|
27578
|
+
throw new Error(`${source}: collection ${writeOperation} requires 'type' to be one of: pair, set, list`);
|
|
27482
27579
|
}
|
|
27483
27580
|
if (!Array.isArray(operation.members)) {
|
|
27484
|
-
throw new Error(`${source}: collection
|
|
27581
|
+
throw new Error(`${source}: collection ${writeOperation} requires a 'members' array`);
|
|
27485
27582
|
}
|
|
27486
27583
|
const name = normalizeOptionalName(operation.name);
|
|
27487
|
-
if (
|
|
27488
|
-
throw new Error(`${source}: collection
|
|
27584
|
+
if (!name) {
|
|
27585
|
+
throw new Error(`${source}: collection ${writeOperation} name must be a non-empty string`);
|
|
27489
27586
|
}
|
|
27490
|
-
|
|
27587
|
+
assertNoUnsupportedCollectionFields(operation, source, writeOperation);
|
|
27491
27588
|
return {
|
|
27492
|
-
|
|
27493
|
-
kind: "collection",
|
|
27494
|
-
...name ? { name } : {},
|
|
27589
|
+
name,
|
|
27495
27590
|
type,
|
|
27496
|
-
members: operation.members
|
|
27497
|
-
...operation.skipExisting === true ? { skipExisting: true } : {}
|
|
27591
|
+
members: operation.members
|
|
27498
27592
|
};
|
|
27499
27593
|
}
|
|
27500
|
-
function
|
|
27501
|
-
const unsupportedFields = [
|
|
27594
|
+
function assertNoUnsupportedCollectionFields(operation, source, writeOperation) {
|
|
27595
|
+
const unsupportedFields = [
|
|
27596
|
+
"about",
|
|
27597
|
+
"aboutWref",
|
|
27598
|
+
"shapeWref",
|
|
27599
|
+
"data",
|
|
27600
|
+
...writeOperation === "revise" ? ["skipExisting"] : []
|
|
27601
|
+
].filter((field) => operation[field] !== undefined);
|
|
27502
27602
|
if (unsupportedFields.length > 0) {
|
|
27503
|
-
throw new Error(`${source}: collection
|
|
27603
|
+
throw new Error(`${source}: collection ${writeOperation} does not support ${unsupportedFields.map((field) => `'${field}'`).join(", ")}`);
|
|
27504
27604
|
}
|
|
27505
27605
|
}
|
|
27506
27606
|
function normalizeCollectionType(value) {
|
|
@@ -27550,12 +27650,12 @@ function toBackendStreamOperation(operation) {
|
|
|
27550
27650
|
if (Object.hasOwn(operation, "active")) {
|
|
27551
27651
|
throw new Error(`${kind2} revise operation no longer supports 'active' — use retract('${name}') instead`);
|
|
27552
27652
|
}
|
|
27653
|
+
if (kind2 === "collection") {
|
|
27654
|
+
return normalizeBackendCollectionRevise(operation, "commit.apply");
|
|
27655
|
+
}
|
|
27553
27656
|
if (operation.data === undefined) {
|
|
27554
27657
|
throw new Error(`${kind2} revise operation requires 'data'`);
|
|
27555
27658
|
}
|
|
27556
|
-
if (kind2 === "collection") {
|
|
27557
|
-
throw new Error(`collection revise is no longer supported — use retract('${name}') instead`);
|
|
27558
|
-
}
|
|
27559
27659
|
if (kind2 === "assertion") {
|
|
27560
27660
|
return {
|
|
27561
27661
|
operation: "revise",
|
|
@@ -27590,6 +27690,9 @@ function toBackendStreamOperation(operation) {
|
|
|
27590
27690
|
if (!("about" in operation) || operation.about === undefined) {
|
|
27591
27691
|
throw new Error("assertion add operation requires 'about'");
|
|
27592
27692
|
}
|
|
27693
|
+
if (typeof operation.about !== "string") {
|
|
27694
|
+
throw new Error(COLLECTION_ABOUT_REMOVED_MESSAGE);
|
|
27695
|
+
}
|
|
27593
27696
|
if (operation.data === undefined) {
|
|
27594
27697
|
throw new Error("assertion add operation requires 'data'");
|
|
27595
27698
|
}
|
|
@@ -27782,34 +27885,14 @@ function computeBackoffDelayMs(attempt, policy) {
|
|
|
27782
27885
|
function sleep2(ms) {
|
|
27783
27886
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
27784
27887
|
}
|
|
27785
|
-
var TOKEN_REF_REGEX = /[$#]\d+/;
|
|
27786
|
-
function stringHasTokenRef(value) {
|
|
27787
|
-
return typeof value === "string" && TOKEN_REF_REGEX.test(value);
|
|
27788
|
-
}
|
|
27789
|
-
function structuralValueHasTokenRef(value, seen = new WeakSet) {
|
|
27790
|
-
if (stringHasTokenRef(value))
|
|
27791
|
-
return true;
|
|
27792
|
-
if (value !== null && typeof value === "object") {
|
|
27793
|
-
if (seen.has(value))
|
|
27794
|
-
return false;
|
|
27795
|
-
seen.add(value);
|
|
27796
|
-
if (Array.isArray(value)) {
|
|
27797
|
-
return value.some((entry) => structuralValueHasTokenRef(entry, seen));
|
|
27798
|
-
}
|
|
27799
|
-
return Object.values(value).some((entry) => structuralValueHasTokenRef(entry, seen));
|
|
27800
|
-
}
|
|
27801
|
-
return false;
|
|
27802
|
-
}
|
|
27803
|
-
function opUsesTokens(op) {
|
|
27804
|
-
return stringHasTokenRef(op.name) || stringHasTokenRef(op.wref) || structuralValueHasTokenRef(op.about) || stringHasTokenRef(op.aboutWref) || structuralValueHasTokenRef(op.members) || structuralValueHasTokenRef(op.data);
|
|
27805
|
-
}
|
|
27806
27888
|
|
|
27807
27889
|
// ../../packages/sdk-ts/src/stream-submit-submit.ts
|
|
27808
27890
|
class StreamValidationError extends Error {
|
|
27809
|
-
code
|
|
27891
|
+
code;
|
|
27810
27892
|
status = 400;
|
|
27811
|
-
constructor(message) {
|
|
27893
|
+
constructor(message, code = "VALIDATION_ERROR") {
|
|
27812
27894
|
super(message);
|
|
27895
|
+
this.code = code;
|
|
27813
27896
|
this.name = "WarmHubError";
|
|
27814
27897
|
}
|
|
27815
27898
|
}
|
|
@@ -27830,6 +27913,7 @@ async function submitOperationsViaStream(client, args) {
|
|
|
27830
27913
|
}
|
|
27831
27914
|
return streamOperation;
|
|
27832
27915
|
});
|
|
27916
|
+
validateNormalizedOperations(operations);
|
|
27833
27917
|
const chunkSize = normalizeChunkSize(args.chunkSize);
|
|
27834
27918
|
let streamId = args.streamId ?? createStreamId();
|
|
27835
27919
|
const policy = args.streamId !== undefined ? false : resolveRetryPolicy(args.retry);
|
|
@@ -27841,7 +27925,6 @@ async function submitOperationsViaStream(client, args) {
|
|
|
27841
27925
|
let attempt = 1;
|
|
27842
27926
|
let priorAttemptAmbiguous = false;
|
|
27843
27927
|
const chunkIsAtomic = chunk.length === 1;
|
|
27844
|
-
const chunkUsesTokens = chunk.some(opUsesTokens);
|
|
27845
27928
|
while (true) {
|
|
27846
27929
|
try {
|
|
27847
27930
|
const appendResult = await client.stream.append({
|
|
@@ -27864,7 +27947,7 @@ async function submitOperationsViaStream(client, args) {
|
|
|
27864
27947
|
if (chunkResults.length === 0 && !priorAttemptAmbiguous && isDefiniteClientError(cause)) {
|
|
27865
27948
|
throw cause;
|
|
27866
27949
|
}
|
|
27867
|
-
if (chunkResults.length === 0 && chunkIsAtomic &&
|
|
27950
|
+
if (chunkResults.length === 0 && chunkIsAtomic && policy !== false && attempt < policy.maxAttempts && isTransientStreamFailure(cause)) {
|
|
27868
27951
|
await sleep2(computeBackoffDelayMs(attempt, policy));
|
|
27869
27952
|
attempt += 1;
|
|
27870
27953
|
priorAttemptAmbiguous = true;
|
|
@@ -27898,6 +27981,16 @@ async function submitOperationsViaStream(client, args) {
|
|
|
27898
27981
|
}
|
|
27899
27982
|
return result;
|
|
27900
27983
|
}
|
|
27984
|
+
function validateNormalizedOperations(operations) {
|
|
27985
|
+
const diagnostics = preflightCommitDiagnostics2(operations).filter((diagnostic) => !isServerAuthoritativeSequenceDiagnostic(diagnostic));
|
|
27986
|
+
const firstDiagnostic = diagnostics[0];
|
|
27987
|
+
if (!firstDiagnostic)
|
|
27988
|
+
return;
|
|
27989
|
+
throw new StreamValidationError(`Invalid operation at index ${firstDiagnostic.operationIndex}: ${firstDiagnostic.message}`, firstDiagnostic.code);
|
|
27990
|
+
}
|
|
27991
|
+
function isServerAuthoritativeSequenceDiagnostic(diagnostic) {
|
|
27992
|
+
return diagnostic.code === "ILLEGAL_OP_SEQUENCE" && diagnostic.message.includes("Cannot revise then add ");
|
|
27993
|
+
}
|
|
27901
27994
|
function isAllSubmittedOperationsFailed(result, submittedOperationCount) {
|
|
27902
27995
|
if (submittedOperationCount <= 0) {
|
|
27903
27996
|
return false;
|
|
@@ -28098,6 +28191,35 @@ function sanitizeSubscriptionUpdateInput(input) {
|
|
|
28098
28191
|
} = input;
|
|
28099
28192
|
return supported;
|
|
28100
28193
|
}
|
|
28194
|
+
function hasCollectionQuerySource(source) {
|
|
28195
|
+
return !!source && (!!source.shape || !!source.kind || !!source.about || !!source.match || !!source.componentRef || source.excludeComponents === true || (source.where?.length ?? 0) > 0);
|
|
28196
|
+
}
|
|
28197
|
+
function hasCollectionSelectorAnchor(source) {
|
|
28198
|
+
return !!source && (!!source.shape || !!source.about || !!source.match || !!source.componentRef || (source.where?.length ?? 0) > 0);
|
|
28199
|
+
}
|
|
28200
|
+
function hasExplicitCollectionMembers(opts) {
|
|
28201
|
+
const members = opts.members;
|
|
28202
|
+
return Array.isArray(members) && members.length > 0;
|
|
28203
|
+
}
|
|
28204
|
+
function collectionTypeFromWref(wref) {
|
|
28205
|
+
const local = wref.replace(/^wh:[^/]+\/[^/]+\//, "").replace(/@(?:HEAD|ALL|v\d+)$/, "");
|
|
28206
|
+
const shape = local.split("/")[0]?.toLowerCase();
|
|
28207
|
+
return shape === "pair" || shape === "set" || shape === "list" ? shape : undefined;
|
|
28208
|
+
}
|
|
28209
|
+
function assertSelectorBackedCollectionType(type, opts) {
|
|
28210
|
+
if (hasCollectionQuerySource(opts.query) && !hasCollectionSelectorAnchor(opts.query)) {
|
|
28211
|
+
throw new WarmHubError("VALIDATION_ERROR", "Selector-backed collection sources require shape, about, match, componentRef, or where; kind and excludeComponents only narrow an existing selector.");
|
|
28212
|
+
}
|
|
28213
|
+
if (opts.sourceRepo && !hasCollectionSelectorAnchor(opts.query)) {
|
|
28214
|
+
throw new WarmHubError("VALIDATION_ERROR", "sourceRepo requires a selector-backed collection query");
|
|
28215
|
+
}
|
|
28216
|
+
if (opts.sourceRepo && hasExplicitCollectionMembers(opts)) {
|
|
28217
|
+
throw new WarmHubError("VALIDATION_ERROR", "sourceRepo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit sourceRepo.");
|
|
28218
|
+
}
|
|
28219
|
+
if (hasCollectionQuerySource(opts.query) && type !== "set") {
|
|
28220
|
+
throw new WarmHubError("VALIDATION_ERROR", "Selector-backed collection sources are only supported for set collections");
|
|
28221
|
+
}
|
|
28222
|
+
}
|
|
28101
28223
|
function trpcClientCodeToWarmHubCode(code) {
|
|
28102
28224
|
switch (code) {
|
|
28103
28225
|
case "BAD_REQUEST":
|
|
@@ -28926,6 +29048,23 @@ class WarmHubClient {
|
|
|
28926
29048
|
throw toWarmHubError(error);
|
|
28927
29049
|
}
|
|
28928
29050
|
},
|
|
29051
|
+
explore: async (opts) => {
|
|
29052
|
+
try {
|
|
29053
|
+
return await this.trpc.repo.explore.query({
|
|
29054
|
+
search: opts?.search,
|
|
29055
|
+
org: opts?.org,
|
|
29056
|
+
activity: opts?.activity,
|
|
29057
|
+
hasSubscriptions: opts?.hasSubscriptions,
|
|
29058
|
+
minThings: opts?.minThings,
|
|
29059
|
+
sort: opts?.sort,
|
|
29060
|
+
limit: opts?.limit,
|
|
29061
|
+
cursor: opts?.cursor,
|
|
29062
|
+
slugs: opts?.slugs
|
|
29063
|
+
});
|
|
29064
|
+
} catch (error) {
|
|
29065
|
+
throw toWarmHubError(error);
|
|
29066
|
+
}
|
|
29067
|
+
},
|
|
28929
29068
|
getReadme: async (orgName, repoName) => {
|
|
28930
29069
|
try {
|
|
28931
29070
|
return await this.trpc.repo.getReadme.query({
|
|
@@ -29302,87 +29441,226 @@ class WarmHubClient {
|
|
|
29302
29441
|
}
|
|
29303
29442
|
}
|
|
29304
29443
|
};
|
|
29305
|
-
|
|
29306
|
-
|
|
29444
|
+
collection = {
|
|
29445
|
+
create: async (orgName, repoName, opts) => {
|
|
29307
29446
|
try {
|
|
29308
|
-
|
|
29309
|
-
return await this.trpc.
|
|
29447
|
+
assertSelectorBackedCollectionType(opts.type, opts);
|
|
29448
|
+
return await this.trpc.collection.create.mutate({
|
|
29310
29449
|
orgName,
|
|
29311
29450
|
repoName,
|
|
29312
|
-
|
|
29313
|
-
|
|
29314
|
-
|
|
29315
|
-
|
|
29316
|
-
|
|
29451
|
+
type: opts.type,
|
|
29452
|
+
name: opts.name,
|
|
29453
|
+
members: opts.members,
|
|
29454
|
+
from: opts.from,
|
|
29455
|
+
add: opts.add,
|
|
29456
|
+
remove: opts.remove,
|
|
29457
|
+
replaceMembers: opts.replaceMembers,
|
|
29458
|
+
query: opts.query,
|
|
29459
|
+
sourceOrgName: opts.sourceRepo?.orgName,
|
|
29460
|
+
sourceRepoName: opts.sourceRepo?.repoName,
|
|
29461
|
+
skipExisting: opts.skipExisting,
|
|
29462
|
+
message: opts.message,
|
|
29463
|
+
committer: opts.committer
|
|
29464
|
+
});
|
|
29465
|
+
} catch (error) {
|
|
29466
|
+
throw toWarmHubError(error);
|
|
29467
|
+
}
|
|
29468
|
+
},
|
|
29469
|
+
members: async (orgName, repoName, wref, opts) => {
|
|
29470
|
+
try {
|
|
29471
|
+
return await this.trpc.collection.members.query({
|
|
29472
|
+
orgName,
|
|
29473
|
+
repoName,
|
|
29474
|
+
wref,
|
|
29475
|
+
version: opts?.version,
|
|
29317
29476
|
limit: opts?.limit,
|
|
29318
|
-
cursor: opts?.cursor
|
|
29319
|
-
componentRef: opts?.componentRef,
|
|
29320
|
-
excludeComponents: opts?.excludeComponents,
|
|
29321
|
-
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
29322
|
-
where: opts?.where
|
|
29477
|
+
cursor: opts?.cursor
|
|
29323
29478
|
});
|
|
29324
29479
|
} catch (error) {
|
|
29325
29480
|
throw toWarmHubError(error);
|
|
29326
29481
|
}
|
|
29327
29482
|
},
|
|
29328
|
-
|
|
29329
|
-
|
|
29483
|
+
membersIter: (orgName, repoName, wref, opts) => {
|
|
29484
|
+
let snapshotVersion = opts?.version;
|
|
29485
|
+
return paginate(async (cursor) => {
|
|
29486
|
+
const page = await this.collection.members(orgName, repoName, wref, {
|
|
29487
|
+
...opts,
|
|
29488
|
+
version: snapshotVersion,
|
|
29489
|
+
cursor
|
|
29490
|
+
});
|
|
29491
|
+
snapshotVersion ??= page.version;
|
|
29492
|
+
return page;
|
|
29493
|
+
}, (page) => page.items, opts?.cursor);
|
|
29330
29494
|
},
|
|
29331
|
-
|
|
29495
|
+
membersAll: async (orgName, repoName, wref, opts) => {
|
|
29332
29496
|
const { max, ...pageOpts } = opts ?? {};
|
|
29333
|
-
|
|
29497
|
+
let snapshotVersion = pageOpts.version;
|
|
29498
|
+
return await collectPaginatedPages(async (cursor) => {
|
|
29499
|
+
const page = await this.collection.members(orgName, repoName, wref, {
|
|
29500
|
+
...pageOpts,
|
|
29501
|
+
version: snapshotVersion,
|
|
29502
|
+
cursor
|
|
29503
|
+
});
|
|
29504
|
+
snapshotVersion ??= page.version;
|
|
29505
|
+
return page;
|
|
29506
|
+
}, (page) => page.items, max, pageOpts.cursor);
|
|
29334
29507
|
},
|
|
29335
|
-
|
|
29508
|
+
contains: async (orgName, repoName, wref, members, opts) => {
|
|
29336
29509
|
try {
|
|
29337
|
-
return await this.trpc.
|
|
29510
|
+
return await this.trpc.collection.contains.query({
|
|
29338
29511
|
orgName,
|
|
29339
29512
|
repoName,
|
|
29340
29513
|
wref,
|
|
29341
|
-
version,
|
|
29342
|
-
|
|
29514
|
+
version: opts?.version,
|
|
29515
|
+
members,
|
|
29516
|
+
position: opts?.position
|
|
29343
29517
|
});
|
|
29344
29518
|
} catch (error) {
|
|
29345
29519
|
throw toWarmHubError(error);
|
|
29346
29520
|
}
|
|
29347
29521
|
},
|
|
29348
|
-
|
|
29522
|
+
diff: async (orgName, repoName, leftWref, rightWref, opts) => {
|
|
29349
29523
|
try {
|
|
29350
|
-
return await this.trpc.
|
|
29524
|
+
return await this.trpc.collection.diff.query({
|
|
29351
29525
|
orgName,
|
|
29352
29526
|
repoName,
|
|
29353
|
-
|
|
29354
|
-
|
|
29527
|
+
leftWref,
|
|
29528
|
+
rightWref,
|
|
29529
|
+
leftVersion: opts?.leftVersion,
|
|
29530
|
+
rightVersion: opts?.rightVersion,
|
|
29531
|
+
mode: opts?.mode
|
|
29355
29532
|
});
|
|
29356
29533
|
} catch (error) {
|
|
29357
29534
|
throw toWarmHubError(error);
|
|
29358
29535
|
}
|
|
29359
29536
|
},
|
|
29360
|
-
|
|
29537
|
+
revise: async (orgName, repoName, wref, opts) => {
|
|
29361
29538
|
try {
|
|
29362
|
-
|
|
29539
|
+
const targetType = collectionTypeFromWref(wref);
|
|
29540
|
+
if (hasCollectionQuerySource(opts.query) && !hasCollectionSelectorAnchor(opts.query)) {
|
|
29541
|
+
throw new WarmHubError("VALIDATION_ERROR", "Selector-backed collection sources require shape, about, match, componentRef, or where; kind and excludeComponents only narrow an existing selector.");
|
|
29542
|
+
}
|
|
29543
|
+
if (opts.sourceRepo && !hasCollectionSelectorAnchor(opts.query)) {
|
|
29544
|
+
throw new WarmHubError("VALIDATION_ERROR", "sourceRepo requires a selector-backed collection query");
|
|
29545
|
+
}
|
|
29546
|
+
if (opts.sourceRepo && hasExplicitCollectionMembers(opts)) {
|
|
29547
|
+
throw new WarmHubError("VALIDATION_ERROR", "sourceRepo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit sourceRepo.");
|
|
29548
|
+
}
|
|
29549
|
+
if (hasCollectionQuerySource(opts.query) && targetType && targetType !== "set") {
|
|
29550
|
+
throw new WarmHubError("VALIDATION_ERROR", "Selector-backed revise requires a Set/<name> target wref");
|
|
29551
|
+
}
|
|
29552
|
+
return await this.trpc.collection.revise.mutate({
|
|
29363
29553
|
orgName,
|
|
29364
29554
|
repoName,
|
|
29365
29555
|
wref,
|
|
29366
|
-
|
|
29556
|
+
members: opts.members,
|
|
29557
|
+
add: opts.add,
|
|
29558
|
+
remove: opts.remove,
|
|
29559
|
+
query: opts.query,
|
|
29560
|
+
sourceOrgName: opts.sourceRepo?.orgName,
|
|
29561
|
+
sourceRepoName: opts.sourceRepo?.repoName,
|
|
29562
|
+
message: opts.message,
|
|
29563
|
+
committer: opts.committer
|
|
29367
29564
|
});
|
|
29368
29565
|
} catch (error) {
|
|
29369
29566
|
throw toWarmHubError(error);
|
|
29370
29567
|
}
|
|
29371
29568
|
},
|
|
29372
|
-
|
|
29569
|
+
stats: async (orgName, repoName, wref, opts) => {
|
|
29373
29570
|
try {
|
|
29374
|
-
return await this.trpc.
|
|
29571
|
+
return await this.trpc.collection.stats.query({
|
|
29375
29572
|
orgName,
|
|
29376
29573
|
repoName,
|
|
29377
29574
|
wref,
|
|
29378
|
-
version: opts?.version
|
|
29379
|
-
depth: opts?.depth,
|
|
29380
|
-
limit: opts?.limit
|
|
29575
|
+
version: opts?.version
|
|
29381
29576
|
});
|
|
29382
29577
|
} catch (error) {
|
|
29383
29578
|
throw toWarmHubError(error);
|
|
29384
29579
|
}
|
|
29385
|
-
}
|
|
29580
|
+
}
|
|
29581
|
+
};
|
|
29582
|
+
thing = {
|
|
29583
|
+
head: async (orgName, repoName, opts) => {
|
|
29584
|
+
try {
|
|
29585
|
+
const kind = opts?.kind === "shape" || opts?.kind === "thing" || opts?.kind === "assertion" || opts?.kind === "collection" ? opts.kind : undefined;
|
|
29586
|
+
return await this.trpc.thing.head.query({
|
|
29587
|
+
orgName,
|
|
29588
|
+
repoName,
|
|
29589
|
+
shape: opts?.shape,
|
|
29590
|
+
kind,
|
|
29591
|
+
match: opts?.match,
|
|
29592
|
+
dataMode: opts?.dataMode,
|
|
29593
|
+
includeRetracted: opts?.includeRetracted,
|
|
29594
|
+
limit: opts?.limit,
|
|
29595
|
+
cursor: opts?.cursor,
|
|
29596
|
+
componentRef: opts?.componentRef,
|
|
29597
|
+
excludeComponents: opts?.excludeComponents,
|
|
29598
|
+
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
29599
|
+
where: opts?.where
|
|
29600
|
+
});
|
|
29601
|
+
} catch (error) {
|
|
29602
|
+
throw toWarmHubError(error);
|
|
29603
|
+
}
|
|
29604
|
+
},
|
|
29605
|
+
headIter: (orgName, repoName, opts) => {
|
|
29606
|
+
return paginate((cursor) => this.thing.head(orgName, repoName, { ...opts, cursor }), (page) => page.items, opts?.cursor);
|
|
29607
|
+
},
|
|
29608
|
+
headAll: async (orgName, repoName, opts) => {
|
|
29609
|
+
const { max, ...pageOpts } = opts ?? {};
|
|
29610
|
+
return await collectPaginatedPages((cursor) => this.thing.head(orgName, repoName, { ...pageOpts, cursor }), (page) => page.items, max, pageOpts.cursor);
|
|
29611
|
+
},
|
|
29612
|
+
get: async (orgName, repoName, wref, version, opts) => {
|
|
29613
|
+
try {
|
|
29614
|
+
return await this.trpc.thing.get.query({
|
|
29615
|
+
orgName,
|
|
29616
|
+
repoName,
|
|
29617
|
+
wref,
|
|
29618
|
+
version,
|
|
29619
|
+
includeRetracted: opts?.includeRetracted,
|
|
29620
|
+
dataMode: opts?.dataMode
|
|
29621
|
+
});
|
|
29622
|
+
} catch (error) {
|
|
29623
|
+
throw toWarmHubError(error);
|
|
29624
|
+
}
|
|
29625
|
+
},
|
|
29626
|
+
getWithLease: async (orgName, repoName, wref, opts) => {
|
|
29627
|
+
try {
|
|
29628
|
+
return await this.trpc.thing.getWithLease.mutate({
|
|
29629
|
+
orgName,
|
|
29630
|
+
repoName,
|
|
29631
|
+
wref,
|
|
29632
|
+
ttlMs: opts?.ttlMs
|
|
29633
|
+
});
|
|
29634
|
+
} catch (error) {
|
|
29635
|
+
throw toWarmHubError(error);
|
|
29636
|
+
}
|
|
29637
|
+
},
|
|
29638
|
+
releaseLease: async (orgName, repoName, wref, leaseId) => {
|
|
29639
|
+
try {
|
|
29640
|
+
await this.trpc.thing.releaseLease.mutate({
|
|
29641
|
+
orgName,
|
|
29642
|
+
repoName,
|
|
29643
|
+
wref,
|
|
29644
|
+
leaseId
|
|
29645
|
+
});
|
|
29646
|
+
} catch (error) {
|
|
29647
|
+
throw toWarmHubError(error);
|
|
29648
|
+
}
|
|
29649
|
+
},
|
|
29650
|
+
graph: async (orgName, repoName, wref, opts) => {
|
|
29651
|
+
try {
|
|
29652
|
+
return await this.trpc.thing.graph.query({
|
|
29653
|
+
orgName,
|
|
29654
|
+
repoName,
|
|
29655
|
+
wref,
|
|
29656
|
+
version: opts?.version,
|
|
29657
|
+
depth: opts?.depth,
|
|
29658
|
+
limit: opts?.limit
|
|
29659
|
+
});
|
|
29660
|
+
} catch (error) {
|
|
29661
|
+
throw toWarmHubError(error);
|
|
29662
|
+
}
|
|
29663
|
+
},
|
|
29386
29664
|
getMany: async (orgName, repoName, wrefs, version, opts) => {
|
|
29387
29665
|
try {
|
|
29388
29666
|
if (wrefs.length === 0) {
|
|
@@ -29400,7 +29678,8 @@ class WarmHubClient {
|
|
|
29400
29678
|
repoName,
|
|
29401
29679
|
wrefs: chunkWrefs,
|
|
29402
29680
|
version,
|
|
29403
|
-
includeRetracted: opts?.includeRetracted
|
|
29681
|
+
includeRetracted: opts?.includeRetracted,
|
|
29682
|
+
dataMode: opts?.dataMode
|
|
29404
29683
|
});
|
|
29405
29684
|
};
|
|
29406
29685
|
if (wrefs.length <= chunkSize) {
|
|
@@ -29571,7 +29850,8 @@ class WarmHubClient {
|
|
|
29571
29850
|
componentRef: opts?.componentRef,
|
|
29572
29851
|
excludeComponents: opts?.excludeComponents,
|
|
29573
29852
|
excludeInfraShapes: opts?.excludeInfraShapes,
|
|
29574
|
-
mode: opts?.mode
|
|
29853
|
+
mode: opts?.mode,
|
|
29854
|
+
nameMatch: opts?.nameMatch
|
|
29575
29855
|
});
|
|
29576
29856
|
} catch (error) {
|
|
29577
29857
|
throw toWarmHubError(error);
|
|
@@ -32864,7 +33144,7 @@ function emitPartialPageHint(ctx, count, _nextCursor, _limit) {
|
|
|
32864
33144
|
}
|
|
32865
33145
|
|
|
32866
33146
|
// ../../packages/warmhub-cli/src/domains/assertion/shared.ts
|
|
32867
|
-
var COLLECTION_TAGS = ["pair", "
|
|
33147
|
+
var COLLECTION_TAGS = ["pair", "set", "list"];
|
|
32868
33148
|
function parseAbout(raw) {
|
|
32869
33149
|
const colonIdx = raw.indexOf(":");
|
|
32870
33150
|
if (colonIdx === -1) {
|
|
@@ -32874,32 +33154,7 @@ function parseAbout(raw) {
|
|
|
32874
33154
|
if (!COLLECTION_TAGS.includes(tag)) {
|
|
32875
33155
|
return raw;
|
|
32876
33156
|
}
|
|
32877
|
-
|
|
32878
|
-
const members = membersStr.split(",").map((m) => m.trim()).filter(Boolean);
|
|
32879
|
-
switch (tag) {
|
|
32880
|
-
case "pair":
|
|
32881
|
-
if (members.length !== 2) {
|
|
32882
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `pair requires exactly 2 members, got ${members.length}`, undefined, "Example: --about pair:Location/a,Location/b");
|
|
32883
|
-
}
|
|
32884
|
-
return { pair: members };
|
|
32885
|
-
case "triple":
|
|
32886
|
-
if (members.length !== 3) {
|
|
32887
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `triple requires exactly 3 members, got ${members.length}`, undefined, "Example: --about triple:Location/a,Location/b,Location/c");
|
|
32888
|
-
}
|
|
32889
|
-
return { triple: members };
|
|
32890
|
-
case "set":
|
|
32891
|
-
if (members.length === 0) {
|
|
32892
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", "set requires at least 1 member", undefined, "Example: --about set:Location/a,Location/b");
|
|
32893
|
-
}
|
|
32894
|
-
return { set: members };
|
|
32895
|
-
case "list":
|
|
32896
|
-
if (members.length === 0) {
|
|
32897
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", "list requires at least 1 member", undefined, "Example: --about list:Location/a,Location/b");
|
|
32898
|
-
}
|
|
32899
|
-
return { list: members };
|
|
32900
|
-
default:
|
|
32901
|
-
return raw;
|
|
32902
|
-
}
|
|
33157
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", COLLECTION_ABOUT_REMOVED_MESSAGE, undefined, "Use wh commit submit --file with a named collection add followed by an assertion add.");
|
|
32903
33158
|
}
|
|
32904
33159
|
function renderAbout(out, c, result) {
|
|
32905
33160
|
const target = result.target;
|
|
@@ -32997,7 +33252,7 @@ var createFlags = {
|
|
|
32997
33252
|
name: flag.string({ description: "Assertion name" }),
|
|
32998
33253
|
shape: flag.string({ description: "Shape for assertion (required)" }),
|
|
32999
33254
|
data: flag.string({ description: "Data payload (JSON)" }),
|
|
33000
|
-
about: flag.string({ description: "Target wref
|
|
33255
|
+
about: flag.string({ description: "Target wref" }),
|
|
33001
33256
|
message: flag.string({ short: "m", description: "Commit message" }),
|
|
33002
33257
|
committer: flag.string({
|
|
33003
33258
|
description: "Committer thing wref (e.g. Agent/bot-1)"
|
|
@@ -33356,6 +33611,9 @@ function renderThing(out, c, result) {
|
|
|
33356
33611
|
out(` ${c.dim}revisedOn:${c.reset} ${formatTime(meta.revisedOn, now)}`);
|
|
33357
33612
|
}
|
|
33358
33613
|
}
|
|
33614
|
+
if (result.collection) {
|
|
33615
|
+
renderCollectionSummary(out, c, result.collection);
|
|
33616
|
+
}
|
|
33359
33617
|
const fields = shapeName && result.data ? collectionFields(shapeName, result.data) : null;
|
|
33360
33618
|
if (fields) {
|
|
33361
33619
|
for (const field of fields) {
|
|
@@ -33378,6 +33636,21 @@ function renderThing(out, c, result) {
|
|
|
33378
33636
|
}
|
|
33379
33637
|
}
|
|
33380
33638
|
}
|
|
33639
|
+
function renderCollectionSummary(out, c, collection) {
|
|
33640
|
+
out(` ${c.dim}collection:${c.reset} ${collection.type}`);
|
|
33641
|
+
out(` ${c.dim}members:${c.reset} ${collection.memberCount}`);
|
|
33642
|
+
if (collection.fullData)
|
|
33643
|
+
return;
|
|
33644
|
+
const limit = collection.inlineLimit ? ` > ${collection.inlineLimit}` : " above inline limit";
|
|
33645
|
+
out(` ${c.dim}data:${c.reset} elided (${collection.memberCount}${limit}; use --data-mode full)`);
|
|
33646
|
+
const preview = collection.preview ?? [];
|
|
33647
|
+
if (preview.length === 0)
|
|
33648
|
+
return;
|
|
33649
|
+
out(` ${c.dim}preview:${c.reset}`);
|
|
33650
|
+
for (const wref of preview) {
|
|
33651
|
+
out(` ${pinnedWref(c, wref)}`);
|
|
33652
|
+
}
|
|
33653
|
+
}
|
|
33381
33654
|
function renderDataBlock(out, data, indent) {
|
|
33382
33655
|
const lines = JSON.stringify(data, null, 2).split(`
|
|
33383
33656
|
`);
|
|
@@ -33569,7 +33842,7 @@ var historyFlags = {
|
|
|
33569
33842
|
description: "Allow retracted shape/about targets to resolve"
|
|
33570
33843
|
}),
|
|
33571
33844
|
"resolve-collections": flag.boolean({
|
|
33572
|
-
description: "Include assertions about collections (Pair/
|
|
33845
|
+
description: "Include assertions about collections (Pair/Set/List) containing the target. Only applies with --about."
|
|
33573
33846
|
})
|
|
33574
33847
|
};
|
|
33575
33848
|
var handleHistory = async (ctx, { flags, args }) => {
|
|
@@ -33960,7 +34233,7 @@ var queryFlags = {
|
|
|
33960
34233
|
description: "Include retracted things"
|
|
33961
34234
|
}),
|
|
33962
34235
|
"resolve-collections": flag.boolean({
|
|
33963
|
-
description: "Include assertions about collections (Pair/
|
|
34236
|
+
description: "Include assertions about collections (Pair/Set/List) containing the target. Only applies with --about."
|
|
33964
34237
|
}),
|
|
33965
34238
|
component: flag.string({
|
|
33966
34239
|
description: "Filter to things owned by this component (Org/Name ref)"
|
|
@@ -34373,7 +34646,7 @@ var searchFlags = {
|
|
|
34373
34646
|
description: "Include retracted things"
|
|
34374
34647
|
}),
|
|
34375
34648
|
"resolve-collections": flag.boolean({
|
|
34376
|
-
description: "Include assertions about collections (Pair/
|
|
34649
|
+
description: "Include assertions about collections (Pair/Set/List) containing the target. Only applies with --about."
|
|
34377
34650
|
}),
|
|
34378
34651
|
limit: flag.number({ description: "Max results (default: 25, max: 500)" }),
|
|
34379
34652
|
cursor: flag.string({ description: "Opaque pagination cursor (text mode)" }),
|
|
@@ -34536,6 +34809,9 @@ var viewFlags = {
|
|
|
34536
34809
|
}),
|
|
34537
34810
|
file: flag.string({
|
|
34538
34811
|
description: "Read additional wrefs from <path>, one per line. Use `--file=-` for stdin (the `=` form is required) or pass bare `-` as a positional. Lines starting with '#' and blank lines are ignored; lines are not split on any other character."
|
|
34812
|
+
}),
|
|
34813
|
+
"data-mode": flag.string({
|
|
34814
|
+
description: "Collection data mode: auto (default) or full. Use full to force large collection bodies into thing view output."
|
|
34539
34815
|
})
|
|
34540
34816
|
};
|
|
34541
34817
|
var MAX_GET_MANY_WREFS = 500;
|
|
@@ -34550,6 +34826,13 @@ async function readStreamUtf8(input) {
|
|
|
34550
34826
|
function parseLineList(text) {
|
|
34551
34827
|
return text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
34552
34828
|
}
|
|
34829
|
+
function validateDataMode(value) {
|
|
34830
|
+
if (value === undefined)
|
|
34831
|
+
return;
|
|
34832
|
+
if (value === "auto" || value === "full")
|
|
34833
|
+
return value;
|
|
34834
|
+
usageError("--data-mode must be auto or full", "wh thing view Set/wake-voters --data-mode full");
|
|
34835
|
+
}
|
|
34553
34836
|
async function collectWrefs(opts) {
|
|
34554
34837
|
const dashPositional = opts.positionals.includes("-");
|
|
34555
34838
|
const cleanPositionals = opts.positionals.filter((a) => a !== "-");
|
|
@@ -34588,12 +34871,16 @@ async function runSingleView(ctx, wref, flags) {
|
|
|
34588
34871
|
const depth = flags.depth;
|
|
34589
34872
|
const { org, repo } = looksLikeDurableId(wref) && depth === undefined ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
34590
34873
|
const includeRetracted = flags["include-retracted"] || version !== undefined;
|
|
34874
|
+
const dataMode = validateDataMode(flags["data-mode"]);
|
|
34591
34875
|
if (depth !== undefined && (depth < 1 || depth > 5)) {
|
|
34592
34876
|
usageError("Usage: wh thing view <wref> --depth <1-5>", "wh thing view Game/base --depth 2");
|
|
34593
34877
|
}
|
|
34594
34878
|
if (depth !== undefined && ctx.liveMode) {
|
|
34595
34879
|
usageError("--depth is not supported with --live", "wh thing view Game/base --depth 2");
|
|
34596
34880
|
}
|
|
34881
|
+
if (depth !== undefined && dataMode !== undefined) {
|
|
34882
|
+
usageError("--data-mode cannot be combined with --depth on `view` (graph reads use a separate payload shape).", "wh thing view Set/wake-voters --data-mode full");
|
|
34883
|
+
}
|
|
34597
34884
|
if (depth !== undefined && (flags["include-retracted"] || version !== undefined)) {
|
|
34598
34885
|
usageError("--depth cannot be combined with --include-retracted or --version on `view` (graph reads are active-only). Use `wh thing graph` for version-pinned graph reads.", "wh thing view Game/base --depth 2");
|
|
34599
34886
|
}
|
|
@@ -34601,7 +34888,8 @@ async function runSingleView(ctx, wref, flags) {
|
|
|
34601
34888
|
await runLive({
|
|
34602
34889
|
apiUrl: ctx.config.apiUrl,
|
|
34603
34890
|
poll: (c) => c.thing.get(org, repo, wref, version, {
|
|
34604
|
-
includeRetracted
|
|
34891
|
+
includeRetracted,
|
|
34892
|
+
dataMode
|
|
34605
34893
|
}),
|
|
34606
34894
|
render: (r) => renderThing(ctx.out, ctx.colors, r),
|
|
34607
34895
|
out: ctx.out,
|
|
@@ -34626,7 +34914,8 @@ async function runSingleView(ctx, wref, flags) {
|
|
|
34626
34914
|
return;
|
|
34627
34915
|
}
|
|
34628
34916
|
const result = await ctx.client.thing.get(org, repo, wref, version, {
|
|
34629
|
-
includeRetracted
|
|
34917
|
+
includeRetracted,
|
|
34918
|
+
dataMode
|
|
34630
34919
|
});
|
|
34631
34920
|
writeOutput(ctx, result, () => renderThing(ctx.out, ctx.colors, result));
|
|
34632
34921
|
}
|
|
@@ -34634,7 +34923,8 @@ async function runBatchView(ctx, wrefs, flags) {
|
|
|
34634
34923
|
const allDurable = wrefs.length > 0 && wrefs.every(looksLikeDurableId);
|
|
34635
34924
|
const { org, repo } = allDurable ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
34636
34925
|
const includeRetracted = flags["include-retracted"] || flags.version !== undefined;
|
|
34637
|
-
const
|
|
34926
|
+
const dataMode = validateDataMode(flags["data-mode"]);
|
|
34927
|
+
const result = await ctx.client.thing.getMany(org, repo, wrefs, flags.version, { includeRetracted, dataMode });
|
|
34638
34928
|
if (ctx.format === "jsonl") {
|
|
34639
34929
|
for (const event of walkBatchResult(wrefs, result, flags.version)) {
|
|
34640
34930
|
if (event.kind === "miss") {
|
|
@@ -34977,7 +35267,9 @@ var handleHistory2 = async (ctx, { flags, args }) => {
|
|
|
34977
35267
|
writePageOutput(ctx, result.versions, { limit, nextCursor: result.nextCursor ?? null }, () => renderHistory(ctx.out, ctx.colors, result));
|
|
34978
35268
|
};
|
|
34979
35269
|
var listFlags = {
|
|
34980
|
-
about: flag.string({
|
|
35270
|
+
about: flag.string({
|
|
35271
|
+
description: "Target wref (thing or shape, required)"
|
|
35272
|
+
}),
|
|
34981
35273
|
shape: flag.string({ description: "Filter by shape" }),
|
|
34982
35274
|
depth: flag.number({ description: "Assertion depth" }),
|
|
34983
35275
|
limit: flag.number({
|
|
@@ -34988,7 +35280,7 @@ var listFlags = {
|
|
|
34988
35280
|
count: flag.boolean({ description: "Return count of matching assertions" }),
|
|
34989
35281
|
match: flag.string({ description: "Filter by wref glob pattern" }),
|
|
34990
35282
|
"resolve-collections": flag.boolean({
|
|
34991
|
-
description: "Include assertions about collections (Pair/
|
|
35283
|
+
description: "Include assertions about collections (Pair/Set/List) containing the target."
|
|
34992
35284
|
}),
|
|
34993
35285
|
"include-retracted": flag.boolean({
|
|
34994
35286
|
description: "Include retracted assertions"
|
|
@@ -35171,7 +35463,7 @@ var ASSERTION_DOMAIN = defineDomain({
|
|
|
35171
35463
|
flags: createFlags,
|
|
35172
35464
|
examples: [
|
|
35173
35465
|
`wh assertion create --shape belief --about player --data '{"confidence":0.8}'`,
|
|
35174
|
-
`wh assertion create --shape Distance --about
|
|
35466
|
+
`wh assertion create --shape Distance --about Pair/location-distance --data '{"value":5}'`
|
|
35175
35467
|
],
|
|
35176
35468
|
handler: handleCreate
|
|
35177
35469
|
},
|
|
@@ -36562,6 +36854,693 @@ var CHANNEL_DOMAIN = defineDomain({
|
|
|
36562
36854
|
handler: handleChannel
|
|
36563
36855
|
});
|
|
36564
36856
|
|
|
36857
|
+
// ../../packages/warmhub-cli/src/domains/collection-helpers.ts
|
|
36858
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
36859
|
+
function parseMemberList(values) {
|
|
36860
|
+
return (values ?? []).flatMap((value) => value.split(",")).map((value) => value.trim()).filter(Boolean);
|
|
36861
|
+
}
|
|
36862
|
+
async function readMembersFromSources(ctx, opts) {
|
|
36863
|
+
const field = opts.wrefField ?? "wref";
|
|
36864
|
+
const members = [
|
|
36865
|
+
...opts.positionals ?? [],
|
|
36866
|
+
...parseMemberList(opts.members)
|
|
36867
|
+
];
|
|
36868
|
+
const fileIsStdin = opts.file === "-";
|
|
36869
|
+
if ((opts.stdin || fileIsStdin) && isTTY(ctx.stdin ?? process.stdin)) {
|
|
36870
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "Stdin requested but stdin is a terminal. Pipe input or remove the stdin flag.", undefined, "Example: wh collection create --type set --name audited --stdin");
|
|
36871
|
+
}
|
|
36872
|
+
if (opts.file && !fileIsStdin) {
|
|
36873
|
+
let raw;
|
|
36874
|
+
try {
|
|
36875
|
+
raw = readFileSync6(opts.file, "utf8");
|
|
36876
|
+
} catch (error) {
|
|
36877
|
+
const code = error.code;
|
|
36878
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read ${opts.file}${code ? ` (${code})` : ""}.`, error, "Check the path or use --file - to read collection members from stdin.");
|
|
36879
|
+
}
|
|
36880
|
+
members.push(...parseMembersPayload(raw, opts.label ?? "--file", field));
|
|
36881
|
+
}
|
|
36882
|
+
if (opts.stdin || fileIsStdin) {
|
|
36883
|
+
const raw = await readStreamUtf82(ctx.stdin ?? process.stdin);
|
|
36884
|
+
members.push(...parseMembersPayload(raw, opts.label ?? "stdin", field));
|
|
36885
|
+
}
|
|
36886
|
+
return members;
|
|
36887
|
+
}
|
|
36888
|
+
function hasCollectionQuerySource2(source) {
|
|
36889
|
+
return !!source.shape || !!source.kind || !!source.about || !!source.match || !!source.componentRef || source.excludeComponents === true || (source.where?.length ?? 0) > 0;
|
|
36890
|
+
}
|
|
36891
|
+
function hasCollectionSelectorAnchor2(source) {
|
|
36892
|
+
return !!source.shape || !!source.about || !!source.match || !!source.componentRef || (source.where?.length ?? 0) > 0;
|
|
36893
|
+
}
|
|
36894
|
+
function requireMembers(members, example) {
|
|
36895
|
+
if (members.length === 0) {
|
|
36896
|
+
usageError("At least one collection member is required", example);
|
|
36897
|
+
}
|
|
36898
|
+
}
|
|
36899
|
+
function renderMutation(ctx, result) {
|
|
36900
|
+
const c = ctx.colors;
|
|
36901
|
+
const action = result.status === "noop" ? "=" : "+";
|
|
36902
|
+
const color = result.status === "noop" ? c.dim : c.green;
|
|
36903
|
+
ctx.out(`${color}${action}${c.reset} ${displayName(c, result.wref)} ${c.dim}${result.type} ${result.memberCount} members${c.reset}`);
|
|
36904
|
+
}
|
|
36905
|
+
function renderMembers(ctx, result) {
|
|
36906
|
+
const c = ctx.colors;
|
|
36907
|
+
if (result.items.length === 0) {
|
|
36908
|
+
ctx.out(`${c.dim}No members${c.reset}`);
|
|
36909
|
+
return;
|
|
36910
|
+
}
|
|
36911
|
+
for (const item of result.items) {
|
|
36912
|
+
const position = item.position ?? 0;
|
|
36913
|
+
ctx.out(`${String(position).padStart(4, " ")} ${pinnedWref(c, item.wref)}`);
|
|
36914
|
+
}
|
|
36915
|
+
}
|
|
36916
|
+
function renderContains(ctx, result) {
|
|
36917
|
+
const c = ctx.colors;
|
|
36918
|
+
for (const item of result.results) {
|
|
36919
|
+
const marker = item.contains ? ctx.chars.check : ctx.chars.cross;
|
|
36920
|
+
const color = item.contains ? c.green : c.red;
|
|
36921
|
+
const at = item.positions === undefined || item.positions.length === 0 ? "" : ` ${c.dim}@${item.positions.join(",")}${c.reset}`;
|
|
36922
|
+
ctx.out(`${color}${marker}${c.reset} ${pinnedWref(c, item.member)}${at}`);
|
|
36923
|
+
}
|
|
36924
|
+
}
|
|
36925
|
+
function renderDiff(ctx, result) {
|
|
36926
|
+
const c = ctx.colors;
|
|
36927
|
+
if (result.mode === "ordered") {
|
|
36928
|
+
if (result.changed.length === 0) {
|
|
36929
|
+
ctx.out(`${c.dim}No ordered differences${c.reset}`);
|
|
36930
|
+
return;
|
|
36931
|
+
}
|
|
36932
|
+
for (const item of result.changed) {
|
|
36933
|
+
const left = item.left?.wref ?? `${c.dim}(none)${c.reset}`;
|
|
36934
|
+
const right = item.right?.wref ?? `${c.dim}(none)${c.reset}`;
|
|
36935
|
+
ctx.out(`${String(item.position).padStart(4, " ")} ${left} -> ${right}`);
|
|
36936
|
+
}
|
|
36937
|
+
return;
|
|
36938
|
+
}
|
|
36939
|
+
if (result.added.length === 0 && result.removed.length === 0) {
|
|
36940
|
+
ctx.out(`${c.dim}No membership differences${c.reset}`);
|
|
36941
|
+
return;
|
|
36942
|
+
}
|
|
36943
|
+
for (const member of result.added) {
|
|
36944
|
+
ctx.out(`${c.green}+${c.reset} ${member.wref}`);
|
|
36945
|
+
}
|
|
36946
|
+
for (const member of result.removed) {
|
|
36947
|
+
ctx.out(`${c.red}-${c.reset} ${member.wref}`);
|
|
36948
|
+
}
|
|
36949
|
+
}
|
|
36950
|
+
function renderStats(ctx, result) {
|
|
36951
|
+
const c = ctx.colors;
|
|
36952
|
+
ctx.out(`${pinnedWref(c, result.wref)} ${c.dim}${result.type}${c.reset}`);
|
|
36953
|
+
ctx.out(`members: ${result.memberCount}`);
|
|
36954
|
+
ctx.out(`unique: ${result.uniqueMemberCount}`);
|
|
36955
|
+
}
|
|
36956
|
+
function memberFromUnknown(value, field, label) {
|
|
36957
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
36958
|
+
return value.trim();
|
|
36959
|
+
}
|
|
36960
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
36961
|
+
const raw = value[field];
|
|
36962
|
+
if (typeof raw === "string" && raw.trim().length > 0) {
|
|
36963
|
+
return raw.trim();
|
|
36964
|
+
}
|
|
36965
|
+
}
|
|
36966
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid member entry in ${label}. Expected a string wref or an object with "${field}".`, undefined, `Use string wrefs or objects like {"${field}":"Shape/name"}.`);
|
|
36967
|
+
}
|
|
36968
|
+
function parseMembersPayload(raw, label, field = "wref") {
|
|
36969
|
+
const trimmed = raw.trim();
|
|
36970
|
+
if (!trimmed)
|
|
36971
|
+
return [];
|
|
36972
|
+
if (trimmed.startsWith("[")) {
|
|
36973
|
+
const parsed = safeParseJson(trimmed, label);
|
|
36974
|
+
if (!Array.isArray(parsed)) {
|
|
36975
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid ${label}. Expected a JSON array.`, undefined, `Use a JSON array of string wrefs or objects with "${field}".`);
|
|
36976
|
+
}
|
|
36977
|
+
return parsed.map((entry) => memberFromUnknown(entry, field, label));
|
|
36978
|
+
}
|
|
36979
|
+
if (trimmed.startsWith("{")) {
|
|
36980
|
+
let objectParseError;
|
|
36981
|
+
try {
|
|
36982
|
+
const parsed = safeParseJson(trimmed, label);
|
|
36983
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && Array.isArray(parsed.members)) {
|
|
36984
|
+
return parsed.members.map((entry) => memberFromUnknown(entry, field, label));
|
|
36985
|
+
}
|
|
36986
|
+
return [memberFromUnknown(parsed, field, label)];
|
|
36987
|
+
} catch (error) {
|
|
36988
|
+
objectParseError = error;
|
|
36989
|
+
}
|
|
36990
|
+
const lines = trimmed.split(/\r?\n/).filter((line) => line.trim());
|
|
36991
|
+
if (lines.length > 1) {
|
|
36992
|
+
return lines.map((line) => memberFromUnknown(safeParseJson(line, label), field, label));
|
|
36993
|
+
}
|
|
36994
|
+
throw objectParseError;
|
|
36995
|
+
}
|
|
36996
|
+
return trimmed.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
36997
|
+
}
|
|
36998
|
+
async function readStreamUtf82(input) {
|
|
36999
|
+
let data = "";
|
|
37000
|
+
input.setEncoding?.("utf8");
|
|
37001
|
+
for await (const chunk of input) {
|
|
37002
|
+
data += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
37003
|
+
}
|
|
37004
|
+
return data;
|
|
37005
|
+
}
|
|
37006
|
+
|
|
37007
|
+
// ../../packages/warmhub-cli/src/domains/collection.ts
|
|
37008
|
+
var COLLECTION_TYPES = ["pair", "set", "list"];
|
|
37009
|
+
var commonWriteFlags = {
|
|
37010
|
+
message: flag.string({ short: "m", description: "Commit message" }),
|
|
37011
|
+
committer: flag.string({
|
|
37012
|
+
description: "Committer thing wref (e.g. Agent/bot-1)"
|
|
37013
|
+
})
|
|
37014
|
+
};
|
|
37015
|
+
var collectionInputFlags = {
|
|
37016
|
+
members: flag.string({
|
|
37017
|
+
multiple: true,
|
|
37018
|
+
description: "Collection member wrefs. May be repeated; comma-separated values are also accepted."
|
|
37019
|
+
}),
|
|
37020
|
+
file: flag.string({
|
|
37021
|
+
description: "Read member wrefs from a file. Supports newline text, JSON array, JSON object with members, or JSONL. Use --file=- for stdin."
|
|
37022
|
+
}),
|
|
37023
|
+
stdin: flag.boolean({
|
|
37024
|
+
description: "Read member wrefs from stdin. Supports newline text, JSON array, JSON object with members, or JSONL."
|
|
37025
|
+
}),
|
|
37026
|
+
"wref-field": flag.string({
|
|
37027
|
+
description: "Object field to read when --file/--stdin contains JSON objects (default: wref)."
|
|
37028
|
+
})
|
|
37029
|
+
};
|
|
37030
|
+
var collectionQueryFlags = {
|
|
37031
|
+
shape: flag.string({ description: "Select set members by shape" }),
|
|
37032
|
+
kind: flag.string({ description: "Select set members by kind" }),
|
|
37033
|
+
about: flag.string({ description: "Select set members by about wref" }),
|
|
37034
|
+
match: flag.string({
|
|
37035
|
+
description: "Select set members by the same name pattern accepted by wh thing query --match"
|
|
37036
|
+
}),
|
|
37037
|
+
component: flag.string({
|
|
37038
|
+
description: "Select set members owned by this component (Org/Name ref)"
|
|
37039
|
+
}),
|
|
37040
|
+
"exclude-components": flag.boolean({
|
|
37041
|
+
description: "Exclude component-owned records from selector-backed sets"
|
|
37042
|
+
}),
|
|
37043
|
+
where: flag.string({
|
|
37044
|
+
multiple: true,
|
|
37045
|
+
description: `Select set members by field-value WHERE predicate (repeatable). Same syntax as wh thing query --where; in:[...] accepts at most ${MAX_WHERE_IN_VALUES} values.`
|
|
37046
|
+
}),
|
|
37047
|
+
"source-repo": flag.string({
|
|
37048
|
+
description: "Read selector-backed set members from this source repo (org/repo). The collection is written to the target repo."
|
|
37049
|
+
})
|
|
37050
|
+
};
|
|
37051
|
+
var collectionCreateFlags = {
|
|
37052
|
+
type: flag.string({
|
|
37053
|
+
description: "Collection type: pair, set, or list"
|
|
37054
|
+
}),
|
|
37055
|
+
name: flag.string({
|
|
37056
|
+
description: "Collection local name. Collections are ordinary named things."
|
|
37057
|
+
}),
|
|
37058
|
+
"skip-existing": flag.boolean({
|
|
37059
|
+
description: "No-op if a named collection already exists. Only valid with --name."
|
|
37060
|
+
}),
|
|
37061
|
+
from: flag.string({
|
|
37062
|
+
description: "Initialize from an existing collection wref"
|
|
37063
|
+
}),
|
|
37064
|
+
add: flag.string({
|
|
37065
|
+
multiple: true,
|
|
37066
|
+
description: "With --from, member wrefs to add. May be repeated; comma-separated values are also accepted."
|
|
37067
|
+
}),
|
|
37068
|
+
remove: flag.string({
|
|
37069
|
+
multiple: true,
|
|
37070
|
+
description: "With --from, member wrefs to remove. May be repeated; comma-separated values are also accepted."
|
|
37071
|
+
}),
|
|
37072
|
+
"replace-file": flag.string({
|
|
37073
|
+
description: "With --from, replace membership from a file. Supports newline text, JSON array, JSON object with members, or JSONL."
|
|
37074
|
+
}),
|
|
37075
|
+
"replace-stdin": flag.boolean({
|
|
37076
|
+
description: "With --from, replace membership from stdin. Supports newline text, JSON array, JSON object with members, or JSONL."
|
|
37077
|
+
}),
|
|
37078
|
+
...collectionInputFlags,
|
|
37079
|
+
...collectionQueryFlags,
|
|
37080
|
+
...commonWriteFlags
|
|
37081
|
+
};
|
|
37082
|
+
var collectionMembersFlags = {
|
|
37083
|
+
limit: flag.number({
|
|
37084
|
+
description: "Max members per page (default: 50, max: 500)"
|
|
37085
|
+
}),
|
|
37086
|
+
cursor: flag.string({ description: "Opaque pagination cursor" }),
|
|
37087
|
+
all: flag.boolean({ description: "Fetch all pages" }),
|
|
37088
|
+
version: flag.number({ description: "Specific version number" })
|
|
37089
|
+
};
|
|
37090
|
+
var collectionContainsFlags = {
|
|
37091
|
+
position: flag.number({
|
|
37092
|
+
description: "For list checks, require the member at this zero-based index"
|
|
37093
|
+
}),
|
|
37094
|
+
version: flag.number({
|
|
37095
|
+
description: "Specific collection version number. Member inputs are still pinned before comparison; use pinned @vN members for historical membership checks."
|
|
37096
|
+
}),
|
|
37097
|
+
...collectionInputFlags
|
|
37098
|
+
};
|
|
37099
|
+
var collectionDiffFlags = {
|
|
37100
|
+
mode: flag.string({
|
|
37101
|
+
description: "Diff mode: auto, membership, or ordered"
|
|
37102
|
+
}),
|
|
37103
|
+
"left-version": flag.number({
|
|
37104
|
+
description: "Specific left collection version"
|
|
37105
|
+
}),
|
|
37106
|
+
"right-version": flag.number({
|
|
37107
|
+
description: "Specific right collection version"
|
|
37108
|
+
})
|
|
37109
|
+
};
|
|
37110
|
+
var collectionReviseFlags = {
|
|
37111
|
+
add: flag.string({
|
|
37112
|
+
multiple: true,
|
|
37113
|
+
description: "For set collections, member wrefs to add. May be repeated; comma-separated values are also accepted."
|
|
37114
|
+
}),
|
|
37115
|
+
remove: flag.string({
|
|
37116
|
+
multiple: true,
|
|
37117
|
+
description: "For set collections, member wrefs to remove. May be repeated; comma-separated values are also accepted."
|
|
37118
|
+
}),
|
|
37119
|
+
...collectionInputFlags,
|
|
37120
|
+
...collectionQueryFlags,
|
|
37121
|
+
...commonWriteFlags
|
|
37122
|
+
};
|
|
37123
|
+
var collectionStatsFlags = {
|
|
37124
|
+
version: flag.number({ description: "Specific collection version number" })
|
|
37125
|
+
};
|
|
37126
|
+
function validateCollectionType(value) {
|
|
37127
|
+
if (!value || !COLLECTION_TYPES.includes(value)) {
|
|
37128
|
+
usageError("Usage: wh collection create --type <pair|set|list> --members <wref...>", 'wh collection create --type set --name audited --members Location/a,Location/b -m "audit snapshot"');
|
|
37129
|
+
}
|
|
37130
|
+
return value;
|
|
37131
|
+
}
|
|
37132
|
+
function validateDiffMode(value) {
|
|
37133
|
+
if (value === undefined)
|
|
37134
|
+
return;
|
|
37135
|
+
if (value === "auto" || value === "membership" || value === "ordered") {
|
|
37136
|
+
return value;
|
|
37137
|
+
}
|
|
37138
|
+
usageError("--mode must be one of: auto, membership, ordered", "wh collection diff Set/a Set/b --mode membership");
|
|
37139
|
+
}
|
|
37140
|
+
function collectionQuerySourceFromFlags(flags) {
|
|
37141
|
+
const where = (flags.where ?? []).map(parseWhereFlag);
|
|
37142
|
+
const kind = validateKind(flags.kind);
|
|
37143
|
+
return {
|
|
37144
|
+
...flags.shape ? { shape: flags.shape } : {},
|
|
37145
|
+
...kind ? { kind } : {},
|
|
37146
|
+
...flags.about ? { about: flags.about } : {},
|
|
37147
|
+
...flags.match ? { match: flags.match } : {},
|
|
37148
|
+
...flags.component ? { componentRef: flags.component } : {},
|
|
37149
|
+
...flags["exclude-components"] ? { excludeComponents: flags["exclude-components"] } : {},
|
|
37150
|
+
...where.length > 0 ? { where } : {}
|
|
37151
|
+
};
|
|
37152
|
+
}
|
|
37153
|
+
function parseSourceRepoFlag(value) {
|
|
37154
|
+
if (!value)
|
|
37155
|
+
return;
|
|
37156
|
+
const parsed = splitRepoSlug(value);
|
|
37157
|
+
if (!parsed) {
|
|
37158
|
+
usageError("--source-repo must be an org/repo slug", "wh collection create --type set --name wake-voters --source-repo data/nc-voters --shape Voter --where county=Wake");
|
|
37159
|
+
}
|
|
37160
|
+
return { orgName: parsed.org, repoName: parsed.repo };
|
|
37161
|
+
}
|
|
37162
|
+
function requireQuerySourceForSourceRepo(sourceRepo, querySource, example) {
|
|
37163
|
+
if (!sourceRepo || hasCollectionSelectorAnchor2(querySource))
|
|
37164
|
+
return;
|
|
37165
|
+
usageError("--source-repo requires a selector source", example);
|
|
37166
|
+
}
|
|
37167
|
+
function requireSelectorAnchorForQuerySource(querySource, example) {
|
|
37168
|
+
if (!hasCollectionQuerySource2(querySource) || hasCollectionSelectorAnchor2(querySource)) {
|
|
37169
|
+
return;
|
|
37170
|
+
}
|
|
37171
|
+
usageError("Selector-backed collection sources require shape, about, match, componentRef, or where; kind and exclude-components only narrow an existing selector.", example);
|
|
37172
|
+
}
|
|
37173
|
+
function requireSetForQuerySource(type, source, example) {
|
|
37174
|
+
if (!hasCollectionQuerySource2(source) || type === "set")
|
|
37175
|
+
return;
|
|
37176
|
+
usageError("Selector-backed collection sources are only supported for set collections", example);
|
|
37177
|
+
}
|
|
37178
|
+
function normalizeCreateMembers(type, members) {
|
|
37179
|
+
return type === "set" ? Array.from(new Set(members)) : members;
|
|
37180
|
+
}
|
|
37181
|
+
function hasDeferredMemberSource(flags) {
|
|
37182
|
+
return !!flags.file || !!flags.stdin;
|
|
37183
|
+
}
|
|
37184
|
+
function isMissingCollectionMemberError(error) {
|
|
37185
|
+
const candidate = error;
|
|
37186
|
+
const code = candidate.code ?? candidate.kind;
|
|
37187
|
+
return code === "VALIDATION_ERROR" && /requires (?:at least|exactly) \d+ member/.test(candidate.message ?? "");
|
|
37188
|
+
}
|
|
37189
|
+
function collectionTypeFromWref2(wref) {
|
|
37190
|
+
const local = wref.replace(/^wh:[^/]+\/[^/]+\//, "").replace(/@(?:HEAD|ALL|v\d+)$/, "");
|
|
37191
|
+
const shape = local.split("/")[0]?.toLowerCase();
|
|
37192
|
+
return COLLECTION_TYPES.includes(shape) ? shape : undefined;
|
|
37193
|
+
}
|
|
37194
|
+
function parseCollectionReadRepo(ctx, wrefs) {
|
|
37195
|
+
const allDurable = wrefs.length > 0 && wrefs.every(looksLikeDurableId);
|
|
37196
|
+
return allDurable ? parseOrgRepoOptional(getRepoRef(ctx), ctx.config) : parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
37197
|
+
}
|
|
37198
|
+
var handleCollectionCreate = async (ctx, { flags, args }) => {
|
|
37199
|
+
if (args.length > 0) {
|
|
37200
|
+
usageError(`Unexpected argument: '${args[0]}'`, "Use --members for explicit collection members: wh collection create --type set --name audited --members Location/a,Location/b");
|
|
37201
|
+
}
|
|
37202
|
+
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
37203
|
+
const type = validateCollectionType(flags.type);
|
|
37204
|
+
const querySource = collectionQuerySourceFromFlags(flags);
|
|
37205
|
+
const sourceRepo = parseSourceRepoFlag(flags["source-repo"]);
|
|
37206
|
+
const add = parseMemberList(flags.add);
|
|
37207
|
+
const remove = parseMemberList(flags.remove);
|
|
37208
|
+
requireQuerySourceForSourceRepo(sourceRepo, querySource, "wh collection create --type set --name wake-voters --source-repo data/nc-voters --shape Voter --where county=Wake");
|
|
37209
|
+
requireSelectorAnchorForQuerySource(querySource, 'wh collection create --type set --name voters --match "Voter/*" -m "snapshot"');
|
|
37210
|
+
requireSetForQuerySource(type, querySource, 'wh collection create --type set --name voters --match "Voter/*" -m "snapshot"');
|
|
37211
|
+
if (flags.from && hasCollectionQuerySource2(querySource)) {
|
|
37212
|
+
usageError("--from cannot be combined with selector flags", 'wh collection create --type set --name today --from Set/yesterday --add Location/c -m "delta"');
|
|
37213
|
+
}
|
|
37214
|
+
if (flags.from && sourceRepo) {
|
|
37215
|
+
usageError("--from cannot be combined with --source-repo", 'wh collection create --type set --name today --from Set/yesterday --add Location/c -m "delta"');
|
|
37216
|
+
}
|
|
37217
|
+
if (flags.from && (flags.members || flags.file || flags.stdin)) {
|
|
37218
|
+
usageError("--from cannot be combined with --members, --file, or --stdin; use --add/--remove for set deltas or --replace-file/--replace-stdin for full replacement", 'wh collection create --type set --name today --from Set/yesterday --add Location/c -m "delta"');
|
|
37219
|
+
}
|
|
37220
|
+
if ((flags["replace-file"] || flags["replace-stdin"]) && (add.length > 0 || remove.length > 0)) {
|
|
37221
|
+
usageError("--replace-file/--replace-stdin cannot be combined with --add or --remove", 'wh collection create --type set --name today --from Set/yesterday --replace-file members.txt -m "snapshot copy"');
|
|
37222
|
+
}
|
|
37223
|
+
if (!flags.from && (add.length > 0 || remove.length > 0 || flags["replace-file"] || flags["replace-stdin"])) {
|
|
37224
|
+
usageError("--add, --remove, --replace-file, and --replace-stdin require --from", 'wh collection create --type set --name today --from Set/yesterday --add Location/c -m "delta"');
|
|
37225
|
+
}
|
|
37226
|
+
if (!flags.name) {
|
|
37227
|
+
usageError("Collection create requires --name", 'wh collection create --type set --name audited --members Location/a,Location/b -m "audit snapshot"');
|
|
37228
|
+
}
|
|
37229
|
+
if (flags["skip-existing"] && !flags.name) {
|
|
37230
|
+
usageError("--skip-existing requires --name", "wh collection create --type set --name voters --members Voter/a --skip-existing");
|
|
37231
|
+
}
|
|
37232
|
+
const queryBacked = hasCollectionQuerySource2(querySource);
|
|
37233
|
+
const replaceMembers = flags.from && (flags["replace-file"] || flags["replace-stdin"]) ? await readMembersFromSources(ctx, {
|
|
37234
|
+
file: flags["replace-file"],
|
|
37235
|
+
stdin: flags["replace-stdin"],
|
|
37236
|
+
wrefField: flags["wref-field"],
|
|
37237
|
+
label: "replacement members"
|
|
37238
|
+
}) : undefined;
|
|
37239
|
+
const inlineMembers = normalizeCreateMembers(type, parseMemberList(flags.members));
|
|
37240
|
+
if (flags["skip-existing"] && flags.name && !queryBacked && inlineMembers.length === 0 && hasDeferredMemberSource(flags)) {
|
|
37241
|
+
try {
|
|
37242
|
+
const result2 = await ctx.client.collection.create(org, repo, {
|
|
37243
|
+
type,
|
|
37244
|
+
name: flags.name,
|
|
37245
|
+
members: [],
|
|
37246
|
+
skipExisting: true,
|
|
37247
|
+
message: flags.message,
|
|
37248
|
+
committer: flags.committer
|
|
37249
|
+
});
|
|
37250
|
+
writeOutput(ctx, result2, () => renderMutation(ctx, result2));
|
|
37251
|
+
return;
|
|
37252
|
+
} catch (error) {
|
|
37253
|
+
if (!isMissingCollectionMemberError(error)) {
|
|
37254
|
+
throw error;
|
|
37255
|
+
}
|
|
37256
|
+
}
|
|
37257
|
+
}
|
|
37258
|
+
const explicitMembers = await readMembersFromSources(ctx, {
|
|
37259
|
+
members: flags.members,
|
|
37260
|
+
file: flags.from ? undefined : flags.file,
|
|
37261
|
+
stdin: flags.from ? undefined : flags.stdin,
|
|
37262
|
+
wrefField: flags["wref-field"],
|
|
37263
|
+
label: "collection members"
|
|
37264
|
+
});
|
|
37265
|
+
const members = normalizeCreateMembers(type, explicitMembers);
|
|
37266
|
+
if (sourceRepo && members.length > 0) {
|
|
37267
|
+
usageError("--source-repo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit --source-repo.", "wh collection create --type set --name wake-voters --source-repo data/nc-voters --shape Voter --where county=Wake");
|
|
37268
|
+
}
|
|
37269
|
+
if (!queryBacked && !flags.from) {
|
|
37270
|
+
requireMembers(members, 'wh collection create --type set --name audited --members Location/a,Location/b -m "audit snapshot"');
|
|
37271
|
+
}
|
|
37272
|
+
const result = queryBacked ? sourceRepo ? await ctx.client.collection.create(org, repo, {
|
|
37273
|
+
type,
|
|
37274
|
+
name: flags.name,
|
|
37275
|
+
...flags.from ? { from: flags.from } : {},
|
|
37276
|
+
...add.length > 0 ? { add } : {},
|
|
37277
|
+
...remove.length > 0 ? { remove } : {},
|
|
37278
|
+
...replaceMembers ? { replaceMembers } : {},
|
|
37279
|
+
query: querySource,
|
|
37280
|
+
sourceRepo,
|
|
37281
|
+
skipExisting: flags["skip-existing"],
|
|
37282
|
+
message: flags.message,
|
|
37283
|
+
committer: flags.committer
|
|
37284
|
+
}) : await ctx.client.collection.create(org, repo, {
|
|
37285
|
+
type,
|
|
37286
|
+
name: flags.name,
|
|
37287
|
+
members,
|
|
37288
|
+
...flags.from ? { from: flags.from } : {},
|
|
37289
|
+
...add.length > 0 ? { add } : {},
|
|
37290
|
+
...remove.length > 0 ? { remove } : {},
|
|
37291
|
+
...replaceMembers ? { replaceMembers } : {},
|
|
37292
|
+
query: querySource,
|
|
37293
|
+
skipExisting: flags["skip-existing"],
|
|
37294
|
+
message: flags.message,
|
|
37295
|
+
committer: flags.committer
|
|
37296
|
+
}) : await ctx.client.collection.create(org, repo, {
|
|
37297
|
+
type,
|
|
37298
|
+
name: flags.name,
|
|
37299
|
+
members,
|
|
37300
|
+
...flags.from ? { from: flags.from } : {},
|
|
37301
|
+
...add.length > 0 ? { add } : {},
|
|
37302
|
+
...remove.length > 0 ? { remove } : {},
|
|
37303
|
+
...replaceMembers ? { replaceMembers } : {},
|
|
37304
|
+
skipExisting: flags["skip-existing"],
|
|
37305
|
+
message: flags.message,
|
|
37306
|
+
committer: flags.committer
|
|
37307
|
+
});
|
|
37308
|
+
writeOutput(ctx, result, () => renderMutation(ctx, result));
|
|
37309
|
+
};
|
|
37310
|
+
var handleCollectionMembers = async (ctx, { flags, args }) => {
|
|
37311
|
+
const wref = args[0];
|
|
37312
|
+
if (!wref) {
|
|
37313
|
+
usageError("Usage: wh collection members <wref> [--limit N] [--cursor TOKEN] [--all]", "wh collection members Set/audited --all");
|
|
37314
|
+
}
|
|
37315
|
+
if (flags.cursor && !flags.limit) {
|
|
37316
|
+
usageError("Usage: wh collection members <wref> --limit N --cursor TOKEN", "wh collection members Set/audited --limit 50 --cursor <token>");
|
|
37317
|
+
}
|
|
37318
|
+
const { org, repo } = parseCollectionReadRepo(ctx, [wref]);
|
|
37319
|
+
const boundedLimit = Math.min(flags.limit ?? DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT);
|
|
37320
|
+
const pageLimit = flags.all ? Math.min(flags.limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedLimit;
|
|
37321
|
+
if (flags.all) {
|
|
37322
|
+
const items = [];
|
|
37323
|
+
let cursor = flags.cursor;
|
|
37324
|
+
let snapshotVersion = flags.version;
|
|
37325
|
+
let firstPage;
|
|
37326
|
+
while (true) {
|
|
37327
|
+
const page = await ctx.client.collection.members(org, repo, wref, {
|
|
37328
|
+
version: snapshotVersion,
|
|
37329
|
+
limit: pageLimit,
|
|
37330
|
+
cursor
|
|
37331
|
+
});
|
|
37332
|
+
firstPage ??= {
|
|
37333
|
+
type: page.type,
|
|
37334
|
+
wref: page.wref,
|
|
37335
|
+
version: page.version
|
|
37336
|
+
};
|
|
37337
|
+
items.push(...page.items);
|
|
37338
|
+
snapshotVersion ??= page.version;
|
|
37339
|
+
if (!page.nextCursor)
|
|
37340
|
+
break;
|
|
37341
|
+
cursor = page.nextCursor;
|
|
37342
|
+
}
|
|
37343
|
+
writeCollectionMembersOutput(ctx, {
|
|
37344
|
+
type: firstPage?.type ?? "set",
|
|
37345
|
+
wref: firstPage?.wref ?? wref,
|
|
37346
|
+
version: snapshotVersion ?? firstPage?.version ?? flags.version ?? 1,
|
|
37347
|
+
items,
|
|
37348
|
+
nextCursor: undefined
|
|
37349
|
+
}, { limit: pageLimit, nextCursor: null });
|
|
37350
|
+
return;
|
|
37351
|
+
}
|
|
37352
|
+
const result = await ctx.client.collection.members(org, repo, wref, {
|
|
37353
|
+
version: flags.version,
|
|
37354
|
+
limit: boundedLimit,
|
|
37355
|
+
cursor: flags.cursor
|
|
37356
|
+
});
|
|
37357
|
+
if (result.nextCursor) {
|
|
37358
|
+
emitPartialPageHint(ctx, result.items.length, result.nextCursor, boundedLimit);
|
|
37359
|
+
}
|
|
37360
|
+
writeCollectionMembersOutput(ctx, result, {
|
|
37361
|
+
limit: boundedLimit,
|
|
37362
|
+
nextCursor: result.nextCursor ?? null
|
|
37363
|
+
});
|
|
37364
|
+
};
|
|
37365
|
+
function writeCollectionMembersOutput(ctx, result, page) {
|
|
37366
|
+
if (ctx.format === "json") {
|
|
37367
|
+
const envelope = pageEnvelope(result.items, page);
|
|
37368
|
+
printJson(ctx.out, {
|
|
37369
|
+
type: result.type,
|
|
37370
|
+
wref: result.wref,
|
|
37371
|
+
version: result.version,
|
|
37372
|
+
items: result.items,
|
|
37373
|
+
page: envelope.page
|
|
37374
|
+
});
|
|
37375
|
+
return;
|
|
37376
|
+
}
|
|
37377
|
+
if (ctx.format === "jsonl") {
|
|
37378
|
+
printJsonl(ctx.out, result.items);
|
|
37379
|
+
return;
|
|
37380
|
+
}
|
|
37381
|
+
renderMembers(ctx, result);
|
|
37382
|
+
}
|
|
37383
|
+
var handleCollectionContains = async (ctx, { flags, args }) => {
|
|
37384
|
+
const wref = args[0];
|
|
37385
|
+
if (!wref) {
|
|
37386
|
+
usageError("Usage: wh collection contains <wref> <member...>", "wh collection contains Set/audited Location/a Location/b");
|
|
37387
|
+
}
|
|
37388
|
+
const members = await readMembersFromSources(ctx, {
|
|
37389
|
+
positionals: args.slice(1),
|
|
37390
|
+
members: flags.members,
|
|
37391
|
+
file: flags.file,
|
|
37392
|
+
stdin: flags.stdin,
|
|
37393
|
+
wrefField: flags["wref-field"],
|
|
37394
|
+
label: "collection contains members"
|
|
37395
|
+
});
|
|
37396
|
+
requireMembers(members, "wh collection contains Set/audited Location/a Location/b");
|
|
37397
|
+
const { org, repo } = parseCollectionReadRepo(ctx, [wref]);
|
|
37398
|
+
const result = await ctx.client.collection.contains(org, repo, wref, members, {
|
|
37399
|
+
version: flags.version,
|
|
37400
|
+
position: flags.position
|
|
37401
|
+
});
|
|
37402
|
+
writeOutput(ctx, result, () => renderContains(ctx, result));
|
|
37403
|
+
};
|
|
37404
|
+
var handleCollectionDiff = async (ctx, { flags, args }) => {
|
|
37405
|
+
const [leftWref, rightWref] = args;
|
|
37406
|
+
if (!leftWref || !rightWref) {
|
|
37407
|
+
usageError("Usage: wh collection diff <left-wref> <right-wref> [--mode auto|membership|ordered]", "wh collection diff Set/yesterday Set/today --mode membership");
|
|
37408
|
+
}
|
|
37409
|
+
const { org, repo } = parseCollectionReadRepo(ctx, [leftWref, rightWref]);
|
|
37410
|
+
const result = await ctx.client.collection.diff(org, repo, leftWref, rightWref, {
|
|
37411
|
+
leftVersion: flags["left-version"],
|
|
37412
|
+
rightVersion: flags["right-version"],
|
|
37413
|
+
mode: validateDiffMode(flags.mode)
|
|
37414
|
+
});
|
|
37415
|
+
writeOutput(ctx, result, () => renderDiff(ctx, result));
|
|
37416
|
+
};
|
|
37417
|
+
var handleCollectionRevise = async (ctx, { flags, args }) => {
|
|
37418
|
+
const wref = args[0];
|
|
37419
|
+
if (!wref) {
|
|
37420
|
+
usageError('Usage: wh collection revise <named-wref> --file members.txt -m "message"', 'wh collection revise Set/audited --file members.txt -m "refresh audit set"');
|
|
37421
|
+
}
|
|
37422
|
+
const add = parseMemberList(flags.add);
|
|
37423
|
+
const remove = parseMemberList(flags.remove);
|
|
37424
|
+
if ((add.length > 0 || remove.length > 0) && (flags.members || flags.file || flags.stdin)) {
|
|
37425
|
+
usageError("--add/--remove cannot be combined with replacement members or selector flags", 'wh collection revise Set/audited --add Location/c --remove Location/a -m "delta"');
|
|
37426
|
+
}
|
|
37427
|
+
const members = await readMembersFromSources(ctx, {
|
|
37428
|
+
members: flags.members,
|
|
37429
|
+
file: add.length > 0 || remove.length > 0 ? undefined : flags.file,
|
|
37430
|
+
stdin: add.length > 0 || remove.length > 0 ? undefined : flags.stdin,
|
|
37431
|
+
wrefField: flags["wref-field"],
|
|
37432
|
+
label: "replacement members"
|
|
37433
|
+
});
|
|
37434
|
+
const querySource = collectionQuerySourceFromFlags(flags);
|
|
37435
|
+
const sourceRepo = parseSourceRepoFlag(flags["source-repo"]);
|
|
37436
|
+
requireQuerySourceForSourceRepo(sourceRepo, querySource, 'wh collection revise Set/audited --source-repo data/nc-voters --shape Voter -m "refresh audit set"');
|
|
37437
|
+
requireSelectorAnchorForQuerySource(querySource, 'wh collection revise Set/audited --match "Location/*" -m "refresh audit set"');
|
|
37438
|
+
if (sourceRepo && members.length > 0) {
|
|
37439
|
+
usageError("--source-repo cannot be combined with explicit members; use canonical wh:org/repo/... member wrefs or omit --source-repo.", 'wh collection revise Set/audited --source-repo data/nc-voters --shape Voter -m "refresh audit set"');
|
|
37440
|
+
}
|
|
37441
|
+
if ((add.length > 0 || remove.length > 0) && (members.length > 0 || hasCollectionQuerySource2(querySource))) {
|
|
37442
|
+
usageError("--add/--remove cannot be combined with replacement members or selector flags", 'wh collection revise Set/audited --add Location/c --remove Location/a -m "delta"');
|
|
37443
|
+
}
|
|
37444
|
+
const targetType = collectionTypeFromWref2(wref);
|
|
37445
|
+
if (hasCollectionQuerySource2(querySource) && targetType && targetType !== "set") {
|
|
37446
|
+
usageError("Selector-backed revise requires a Set/<name> target wref", 'wh collection revise Set/audited --match "Location/*" -m "refresh audit set"');
|
|
37447
|
+
}
|
|
37448
|
+
const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
|
|
37449
|
+
const queryBacked = hasCollectionQuerySource2(querySource);
|
|
37450
|
+
if (!queryBacked && add.length === 0 && remove.length === 0) {
|
|
37451
|
+
requireMembers(members, 'wh collection revise Set/audited --file members.txt -m "refresh audit set"');
|
|
37452
|
+
}
|
|
37453
|
+
const result = queryBacked ? sourceRepo ? await ctx.client.collection.revise(org, repo, wref, {
|
|
37454
|
+
query: querySource,
|
|
37455
|
+
sourceRepo,
|
|
37456
|
+
message: flags.message,
|
|
37457
|
+
committer: flags.committer
|
|
37458
|
+
}) : await ctx.client.collection.revise(org, repo, wref, {
|
|
37459
|
+
members,
|
|
37460
|
+
query: querySource,
|
|
37461
|
+
message: flags.message,
|
|
37462
|
+
committer: flags.committer
|
|
37463
|
+
}) : await ctx.client.collection.revise(org, repo, wref, {
|
|
37464
|
+
members,
|
|
37465
|
+
...add.length > 0 ? { add } : {},
|
|
37466
|
+
...remove.length > 0 ? { remove } : {},
|
|
37467
|
+
message: flags.message,
|
|
37468
|
+
committer: flags.committer
|
|
37469
|
+
});
|
|
37470
|
+
writeOutput(ctx, result, () => renderMutation(ctx, result));
|
|
37471
|
+
};
|
|
37472
|
+
var handleCollectionStats = async (ctx, { flags, args }) => {
|
|
37473
|
+
const wref = args[0];
|
|
37474
|
+
if (!wref) {
|
|
37475
|
+
usageError("Usage: wh collection stats <wref>", "wh collection stats Set/audited");
|
|
37476
|
+
}
|
|
37477
|
+
const { org, repo } = parseCollectionReadRepo(ctx, [wref]);
|
|
37478
|
+
const result = await ctx.client.collection.stats(org, repo, wref, {
|
|
37479
|
+
version: flags.version
|
|
37480
|
+
});
|
|
37481
|
+
writeOutput(ctx, result, () => renderStats(ctx, result));
|
|
37482
|
+
};
|
|
37483
|
+
var COLLECTION_DOMAIN = defineDomain({
|
|
37484
|
+
name: "collection",
|
|
37485
|
+
summary: "Create, inspect, compare, and revise WarmHub collections (Pair, Set, List).",
|
|
37486
|
+
group: "resource",
|
|
37487
|
+
verbs: {
|
|
37488
|
+
create: {
|
|
37489
|
+
summary: "Create a collection thing from explicit members or a set selector",
|
|
37490
|
+
args: "",
|
|
37491
|
+
flags: collectionCreateFlags,
|
|
37492
|
+
examples: [
|
|
37493
|
+
'wh collection create --type set --name audited --members Location/a,Location/b -m "audit snapshot"',
|
|
37494
|
+
'wh collection create --type set --name voters --match "Voter/*" -m "voter snapshot"',
|
|
37495
|
+
'wh collection create --type set --name wake-voters --shape Voter --where state=NC --where county=Wake -m "snapshot Wake County voters"',
|
|
37496
|
+
'wh collection create --type set --name today --from Set/yesterday --add Location/c --remove Location/a -m "delta"'
|
|
37497
|
+
],
|
|
37498
|
+
handler: handleCollectionCreate
|
|
37499
|
+
},
|
|
37500
|
+
revise: {
|
|
37501
|
+
summary: "Revise a named collection by replacement, selector, or set delta",
|
|
37502
|
+
args: "<named-wref>",
|
|
37503
|
+
flags: collectionReviseFlags,
|
|
37504
|
+
examples: [
|
|
37505
|
+
'wh collection revise Set/audited --file members.txt -m "refresh audit set"',
|
|
37506
|
+
'wh collection revise Set/audited --match "Location/*" -m "refresh audit set"',
|
|
37507
|
+
'wh collection revise Set/audited --add Location/c --remove Location/a -m "delta"'
|
|
37508
|
+
],
|
|
37509
|
+
handler: handleCollectionRevise
|
|
37510
|
+
},
|
|
37511
|
+
members: {
|
|
37512
|
+
summary: "List collection members with pagination",
|
|
37513
|
+
args: "<wref>",
|
|
37514
|
+
flags: collectionMembersFlags,
|
|
37515
|
+
examples: ["wh collection members Set/audited --all"],
|
|
37516
|
+
handler: handleCollectionMembers
|
|
37517
|
+
},
|
|
37518
|
+
contains: {
|
|
37519
|
+
summary: "Check collection membership for one or more wrefs",
|
|
37520
|
+
args: "<wref> <member...>",
|
|
37521
|
+
flags: collectionContainsFlags,
|
|
37522
|
+
examples: ["wh collection contains Set/audited Location/a Location/b"],
|
|
37523
|
+
handler: handleCollectionContains
|
|
37524
|
+
},
|
|
37525
|
+
diff: {
|
|
37526
|
+
summary: "Compare two collections by membership or order",
|
|
37527
|
+
args: "<left-wref> <right-wref>",
|
|
37528
|
+
flags: collectionDiffFlags,
|
|
37529
|
+
examples: [
|
|
37530
|
+
"wh collection diff Set/yesterday Set/today --mode membership"
|
|
37531
|
+
],
|
|
37532
|
+
handler: handleCollectionDiff
|
|
37533
|
+
},
|
|
37534
|
+
stats: {
|
|
37535
|
+
summary: "Summarize collection size and identity",
|
|
37536
|
+
args: "<wref>",
|
|
37537
|
+
flags: collectionStatsFlags,
|
|
37538
|
+
examples: ["wh collection stats Set/audited"],
|
|
37539
|
+
handler: handleCollectionStats
|
|
37540
|
+
}
|
|
37541
|
+
}
|
|
37542
|
+
});
|
|
37543
|
+
|
|
36565
37544
|
// ../../packages/warmhub-cli/src/domains/commit-submit-flags.ts
|
|
36566
37545
|
var createFlags3 = {
|
|
36567
37546
|
ops: flag.string({
|
|
@@ -36626,7 +37605,10 @@ var createFlags3 = {
|
|
|
36626
37605
|
multiple: true
|
|
36627
37606
|
}),
|
|
36628
37607
|
type: flag.string({
|
|
36629
|
-
description: "Collection type: pair,
|
|
37608
|
+
description: "Collection type: pair, set, list"
|
|
37609
|
+
}),
|
|
37610
|
+
name: flag.string({
|
|
37611
|
+
description: "Collection name for --type shorthand"
|
|
36630
37612
|
}),
|
|
36631
37613
|
members: flag.string({
|
|
36632
37614
|
description: "Collection members (comma-separated wrefs)"
|
|
@@ -36771,32 +37753,12 @@ function emitTemplateHint(ctx, operationType) {
|
|
|
36771
37753
|
const assertionArgs = operationType === "add" ? "--kind assertion --about <Target/FILL_IN>" : "--kind assertion";
|
|
36772
37754
|
ctx.err(`Template note: shapes define payload fields. To scaffold an assertion, rerun with ${assertionArgs}.`);
|
|
36773
37755
|
}
|
|
36774
|
-
var COLLECTION_ABOUT_PREFIX_RE = /^(pair|
|
|
37756
|
+
var COLLECTION_ABOUT_PREFIX_RE = /^(pair|set|list):(.*)$/;
|
|
36775
37757
|
function parseCollectionAboutFlag(raw) {
|
|
36776
37758
|
const match = COLLECTION_ABOUT_PREFIX_RE.exec(raw);
|
|
36777
37759
|
if (!match)
|
|
36778
37760
|
return raw;
|
|
36779
|
-
|
|
36780
|
-
const members = match[2].split(",").map((m) => m.trim()).filter(Boolean);
|
|
36781
|
-
switch (tag) {
|
|
36782
|
-
case "pair":
|
|
36783
|
-
if (members.length !== 2) {
|
|
36784
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `pair requires exactly 2 members, got ${members.length}`, undefined, "Example: --about pair:Location/a,Location/b");
|
|
36785
|
-
}
|
|
36786
|
-
break;
|
|
36787
|
-
case "triple":
|
|
36788
|
-
if (members.length !== 3) {
|
|
36789
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `triple requires exactly 3 members, got ${members.length}`, undefined, "Example: --about triple:Location/a,Location/b,Location/c");
|
|
36790
|
-
}
|
|
36791
|
-
break;
|
|
36792
|
-
case "set":
|
|
36793
|
-
case "list":
|
|
36794
|
-
if (members.length === 0) {
|
|
36795
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT", `${tag} requires at least 1 member`, undefined, `Example: --about ${tag}:Location/a,Location/b`);
|
|
36796
|
-
}
|
|
36797
|
-
break;
|
|
36798
|
-
}
|
|
36799
|
-
return { [tag]: members };
|
|
37761
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", COLLECTION_ABOUT_REMOVED_MESSAGE, undefined, "Use wh commit submit --file with a named collection add followed by an assertion add.");
|
|
36800
37762
|
}
|
|
36801
37763
|
var handleTemplate = async (ctx, { flags, args }) => {
|
|
36802
37764
|
const shapeNames = args;
|
|
@@ -37600,7 +38562,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37600
38562
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --kind "${k}". Must be one of: ${validKinds.join(", ")}`);
|
|
37601
38563
|
}
|
|
37602
38564
|
}
|
|
37603
|
-
const validCollectionTypes = ["pair", "
|
|
38565
|
+
const validCollectionTypes = ["pair", "set", "list"];
|
|
37604
38566
|
if (flags.type && !validCollectionTypes.includes(flags.type)) {
|
|
37605
38567
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --type "${flags.type}". Must be one of: ${validCollectionTypes.join(", ")}`);
|
|
37606
38568
|
}
|
|
@@ -37632,11 +38594,14 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37632
38594
|
if (streamInput) {
|
|
37633
38595
|
operations = [];
|
|
37634
38596
|
} else if (collectionType) {
|
|
38597
|
+
if (!flags.name) {
|
|
38598
|
+
usageError("Usage: wh commit submit --type <pair|set|list> --name <collection-name> --members <wref1,wref2,...>", "wh commit submit --type pair --name location-distance --members Location/a,Location/b");
|
|
38599
|
+
}
|
|
37635
38600
|
if (!flags.members) {
|
|
37636
|
-
usageError("Usage: wh commit submit --type <pair|
|
|
38601
|
+
usageError("Usage: wh commit submit --type <pair|set|list> --name <collection-name> --members <wref1,wref2,...>", "wh commit submit --type pair --name location-distance --members Location/a,Location/b");
|
|
37637
38602
|
}
|
|
37638
38603
|
const members = flags.members.split(",").map((m) => m.trim()).filter(Boolean);
|
|
37639
|
-
const arityMap = { pair: 2
|
|
38604
|
+
const arityMap = { pair: 2 };
|
|
37640
38605
|
const expected = arityMap[collectionType];
|
|
37641
38606
|
if (expected && members.length !== expected) {
|
|
37642
38607
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `${collectionType} requires exactly ${expected} members, got ${members.length}`);
|
|
@@ -37649,6 +38614,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
|
|
|
37649
38614
|
operation: "add",
|
|
37650
38615
|
kind: "collection",
|
|
37651
38616
|
type: collectionType,
|
|
38617
|
+
name: flags.name,
|
|
37652
38618
|
members
|
|
37653
38619
|
}
|
|
37654
38620
|
];
|
|
@@ -37799,8 +38765,8 @@ var COMMIT_DOMAIN = defineDomain({
|
|
|
37799
38765
|
`printf '%s\\n' '{"operation":"add","kind":"thing","name":"Player/alice","data":{"score":1}}' | wh commit submit --stream --stream-id bulk-2026-06-04 --skip-existing --repo acme/world -m "stdin stream"`,
|
|
37800
38766
|
'wh commit submit --file dataset.jsonl --stream-id bulk-2026-06-04 --skip-existing --progress -m "bulk stream"',
|
|
37801
38767
|
"wh shape template Session HypothesisCandidate -o ops.json",
|
|
37802
|
-
"wh commit submit --type pair --members Location/a,Location/b",
|
|
37803
|
-
'wh commit submit --type set --members Location/a,Location/b,Location/c -m "Create location set"'
|
|
38768
|
+
"wh commit submit --type pair --name location-distance --members Location/a,Location/b",
|
|
38769
|
+
'wh commit submit --type set --name active-locations --members Location/a,Location/b,Location/c -m "Create location set"'
|
|
37804
38770
|
],
|
|
37805
38771
|
notes: [
|
|
37806
38772
|
"Need to build an ops file? Run `wh shape template <Shape>` to scaffold the JSON from a shape definition, edit the FILL_IN placeholders, then pass it to `--file`.",
|
|
@@ -37814,7 +38780,7 @@ var COMMIT_DOMAIN = defineDomain({
|
|
|
37814
38780
|
import {
|
|
37815
38781
|
existsSync as existsSync7,
|
|
37816
38782
|
mkdirSync as mkdirSync6,
|
|
37817
|
-
readFileSync as
|
|
38783
|
+
readFileSync as readFileSync7,
|
|
37818
38784
|
renameSync as renameSync3,
|
|
37819
38785
|
rmSync as rmSync4,
|
|
37820
38786
|
writeFileSync as writeFileSync6
|
|
@@ -37850,7 +38816,7 @@ function loadInstallSnapshotCacheRaw(repoSlug) {
|
|
|
37850
38816
|
if (!path2 || !existsSync7(path2))
|
|
37851
38817
|
return null;
|
|
37852
38818
|
try {
|
|
37853
|
-
const raw =
|
|
38819
|
+
const raw = readFileSync7(path2, "utf-8");
|
|
37854
38820
|
return JSON.parse(raw);
|
|
37855
38821
|
} catch {
|
|
37856
38822
|
return null;
|
|
@@ -38620,7 +39586,7 @@ function formatReservedNameWarning(name) {
|
|
|
38620
39586
|
}
|
|
38621
39587
|
|
|
38622
39588
|
// ../../packages/warmhub-cli/src/manifest/parser.ts
|
|
38623
|
-
import { existsSync as existsSync8, readFileSync as
|
|
39589
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
|
|
38624
39590
|
import { resolve } from "node:path";
|
|
38625
39591
|
function parseComponentPackage(dirPath) {
|
|
38626
39592
|
const rootDir = resolve(dirPath);
|
|
@@ -38633,7 +39599,7 @@ function parseComponentPackage(dirPath) {
|
|
|
38633
39599
|
}
|
|
38634
39600
|
let componentRaw;
|
|
38635
39601
|
try {
|
|
38636
|
-
componentRaw = JSON.parse(
|
|
39602
|
+
componentRaw = JSON.parse(readFileSync8(componentJsonPath, "utf-8"));
|
|
38637
39603
|
} catch (err) {
|
|
38638
39604
|
errors.push(`Failed to parse warmhub/component.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
38639
39605
|
return { ok: false, errors, warnings };
|
|
@@ -38648,7 +39614,7 @@ function parseComponentPackage(dirPath) {
|
|
|
38648
39614
|
}
|
|
38649
39615
|
let manifestRaw;
|
|
38650
39616
|
try {
|
|
38651
|
-
manifestRaw = JSON.parse(
|
|
39617
|
+
manifestRaw = JSON.parse(readFileSync8(manifestJsonPath, "utf-8"));
|
|
38652
39618
|
} catch (err) {
|
|
38653
39619
|
errors.push(`Failed to parse warmhub/manifest.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
38654
39620
|
return { ok: false, errors, warnings };
|
|
@@ -38849,7 +39815,7 @@ function formatLifecycleUrl(url, colors) {
|
|
|
38849
39815
|
}
|
|
38850
39816
|
|
|
38851
39817
|
// ../../packages/warmhub-cli/src/domains/component-utils.ts
|
|
38852
|
-
import { readFileSync as
|
|
39818
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
38853
39819
|
function isRegisteredComponentSource(source) {
|
|
38854
39820
|
return /^[a-z0-9-]+\/[a-z0-9-]+$/.test(source);
|
|
38855
39821
|
}
|
|
@@ -38889,7 +39855,7 @@ function resolveMintedTokensFlag(args) {
|
|
|
38889
39855
|
function readManifestArg(path2) {
|
|
38890
39856
|
let raw;
|
|
38891
39857
|
try {
|
|
38892
|
-
raw =
|
|
39858
|
+
raw = readFileSync9(path2, "utf8");
|
|
38893
39859
|
} catch {
|
|
38894
39860
|
throw new CliError(2 /* UserInput */, "USER_INPUT", `Cannot read manifest file: ${path2}`, undefined, "Pass --manifest <path to warmhub/manifest.json>");
|
|
38895
39861
|
}
|
|
@@ -41508,7 +42474,7 @@ wh assertion create --shape ShapeName --about Target/name --name my-assertion --
|
|
|
41508
42474
|
wh thing list --repo org/repo # all things at HEAD
|
|
41509
42475
|
wh thing view Shape/name --repo org/repo # inspect a thing
|
|
41510
42476
|
wh thing query --shape MyShape --repo org/repo # find things by shape
|
|
41511
|
-
wh thing about Shape/name --repo org/repo # assertions about
|
|
42477
|
+
wh thing about Shape/name --repo org/repo # assertions about thing/shape
|
|
41512
42478
|
wh assertion list --repo org/repo # all assertions at HEAD
|
|
41513
42479
|
wh thing history Shape/name --repo org/repo # version history
|
|
41514
42480
|
|
|
@@ -41520,17 +42486,16 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
41520
42486
|
|
|
41521
42487
|
## Wref Quick Reference
|
|
41522
42488
|
|
|
41523
|
-
|
|
41524
|
-
|
|
41525
|
-
|
|
41526
|
-
- Example: \`Player/player-$1\` + about \`Player/player-#1\` → \`Player/player-a1b2c3d4e5f6a7b8\`
|
|
42489
|
+
Write operations use explicit names and explicit wrefs. To connect operations
|
|
42490
|
+
inside one commit, create the first thing with a deterministic name and point
|
|
42491
|
+
later operations at that wref.
|
|
41527
42492
|
|
|
41528
42493
|
## Command Reference
|
|
41529
42494
|
|
|
41530
42495
|
**Global flags**: \`--repo\`, \`--format\`, \`--json\`, \`--live\`
|
|
41531
42496
|
### thing — Thing operations
|
|
41532
42497
|
- \`wh thing list [--shape] [--kind] [--match] [--include-retracted]\` — Current HEAD state
|
|
41533
|
-
- \`wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted]\` — Thing details. Variadic
|
|
42498
|
+
- \`wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted] [--data-mode auto|full]\` — Thing details. Variadic (max 500). \`--version\` implies \`--include-retracted\`. Batch JSON returns \`{ requested, items, missing }\`; jsonl emits one row per deduped requested wref. Large Set/List bodies summarize by default; use \`--data-mode full\` for canonical collection JSON.
|
|
41534
42499
|
- \`wh thing history [wref] [--shape] [--about] [--include-retracted]\` — Version history
|
|
41535
42500
|
- \`wh thing resolve <wref>\` — Resolve wref
|
|
41536
42501
|
- \`wh thing create <name|Shape/name> --data <json-object> [--shape] [--message] [--committer]\` — Create
|
|
@@ -41539,7 +42504,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
41539
42504
|
- \`wh thing query [--shape] [--kind] [--about] [--match]\` — Query by filters
|
|
41540
42505
|
- \`wh thing search <query> [--shape] [--kind] [--about] [--mode]\` — Search text
|
|
41541
42506
|
- \`wh thing rename <Shape/oldName> <newName>\` — Rename
|
|
41542
|
-
- \`wh thing refs <wref> [--inbound] [--outbound] [--field]\` — Show field references; use \`wh thing about\` for assertions about
|
|
42507
|
+
- \`wh thing refs <wref> [--inbound] [--outbound] [--field]\` — Show field references; use \`wh thing about\` for assertions about things/shapes
|
|
41543
42508
|
- \`wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--limit] [--include-retracted]\` — Show assertions about the target identity; \`--resolve-collections\` expands collection members for bare/@HEAD/@ALL inputs, not pinned @vN
|
|
41544
42509
|
|
|
41545
42510
|
### commit — Write operations
|
|
@@ -41625,12 +42590,12 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
|
|
|
41625
42590
|
wh thing list --repo org/repo # see all things in HEAD
|
|
41626
42591
|
wh thing view Shape/name --repo org/repo # inspect a specific thing
|
|
41627
42592
|
wh thing history Shape/name --repo org/repo # inspect version history
|
|
41628
|
-
wh thing about Shape/name # assertions about
|
|
42593
|
+
wh thing about Shape/name # assertions about thing/shape
|
|
41629
42594
|
\`\`\`
|
|
41630
42595
|
|
|
41631
42596
|
**Create an assertion** (most common write):
|
|
41632
42597
|
\`\`\`bash
|
|
41633
|
-
# --about takes a wref
|
|
42598
|
+
# --about takes a target wref: Shape/name thing, or Shape itself.
|
|
41634
42599
|
wh assertion create --shape MyShape --about TargetShape/target-name \\
|
|
41635
42600
|
--name my-assertion --data '{"field_a":1,"field_b":"value"}' --repo org/repo
|
|
41636
42601
|
# Output includes per-operation status; relay failures when present.
|
|
@@ -41659,17 +42624,15 @@ wh commit submit --file ops.jsonl --stream-id "$ID" --chunk-size 5000 \\
|
|
|
41659
42624
|
# --chunk-size: ops per append chunk (default 1000, max 10000); chunk≈1 is ~60× slower
|
|
41660
42625
|
# --skip-existing: skips already-written add ops (drops per-row read-before-write)
|
|
41661
42626
|
# Add-stream restart: rerun the WHOLE file with the SAME --stream-id.
|
|
41662
|
-
# Fixed-name adds are idempotent via --skip-existing
|
|
41663
|
-
#
|
|
41664
|
-
#
|
|
41665
|
-
# is not a CLI mode. Mixed revise/retract JSONL streams are not full-rerun safe
|
|
41666
|
-
# after an ambiguous append; inspect repo state and reconcile explicitly.
|
|
42627
|
+
# Fixed-name adds are idempotent via --skip-existing. Mid-stream resume is not
|
|
42628
|
+
# a CLI mode. Mixed revise/retract JSONL streams are not full-rerun safe after
|
|
42629
|
+
# an ambiguous append; inspect repo state and reconcile explicitly.
|
|
41667
42630
|
\`\`\`
|
|
41668
42631
|
|
|
41669
42632
|
**Create collections:**
|
|
41670
42633
|
\`\`\`bash
|
|
41671
|
-
wh commit submit --type pair --members Location/a,Location/b --repo org/repo
|
|
41672
|
-
wh assertion create --shape Distance --about
|
|
42634
|
+
wh commit submit --type pair --name location-distance --members Location/a,Location/b --repo org/repo
|
|
42635
|
+
wh assertion create --shape Distance --about Pair/location-distance --data '{"value":5}' --repo org/repo
|
|
41673
42636
|
\`\`\`
|
|
41674
42637
|
|
|
41675
42638
|
**Modify data:**
|
|
@@ -41759,8 +42722,7 @@ var wrefSyntax = {
|
|
|
41759
42722
|
"GameState/round-1/state"
|
|
41760
42723
|
],
|
|
41761
42724
|
canonicalFormat: "wh:org/repo/Shape/name",
|
|
41762
|
-
versionModifiers: ["@HEAD", "@vN", "@ALL"]
|
|
41763
|
-
batchTokens: { allocate: "$N", reference: "#N" }
|
|
42725
|
+
versionModifiers: ["@HEAD", "@vN", "@ALL"]
|
|
41764
42726
|
};
|
|
41765
42727
|
var handlePrime = async (ctx) => {
|
|
41766
42728
|
writeOutput(ctx, {
|
|
@@ -44084,7 +45046,7 @@ var TOKEN_DOMAIN = defineDomain({
|
|
|
44084
45046
|
});
|
|
44085
45047
|
|
|
44086
45048
|
// ../../packages/warmhub-cli/src/update-check-cache.ts
|
|
44087
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
45049
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
|
|
44088
45050
|
import { homedir as homedir5 } from "node:os";
|
|
44089
45051
|
import { dirname as dirname7, resolve as resolve3 } from "node:path";
|
|
44090
45052
|
|
|
@@ -44153,7 +45115,7 @@ var WH_CACHE_PACKAGE_NAME = WH_CLI_PACKAGE_NAME;
|
|
|
44153
45115
|
var cachePath = (homePath) => resolve3(homePath, ".warmhub", "cli", "update-check.json");
|
|
44154
45116
|
var readCache = (homePath) => {
|
|
44155
45117
|
try {
|
|
44156
|
-
return JSON.parse(
|
|
45118
|
+
return JSON.parse(readFileSync10(cachePath(homePath), "utf8"));
|
|
44157
45119
|
} catch {
|
|
44158
45120
|
return;
|
|
44159
45121
|
}
|
|
@@ -44177,7 +45139,7 @@ var markUpdateNoticeShown = ({
|
|
|
44177
45139
|
|
|
44178
45140
|
// ../../packages/warmhub-cli/src/domains/update-install.ts
|
|
44179
45141
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
44180
|
-
import { existsSync as existsSync9, readFileSync as
|
|
45142
|
+
import { existsSync as existsSync9, readFileSync as readFileSync11, realpathSync } from "node:fs";
|
|
44181
45143
|
import { homedir as homedir6 } from "node:os";
|
|
44182
45144
|
import { dirname as dirname8, resolve as resolve4 } from "node:path";
|
|
44183
45145
|
var DEV_INSTALL_PACKAGE_SEARCH_DEPTH = 8;
|
|
@@ -44327,7 +45289,7 @@ var isDevInstall = (scriptPath) => {
|
|
|
44327
45289
|
for (let i = 0;i < DEV_INSTALL_PACKAGE_SEARCH_DEPTH; i += 1) {
|
|
44328
45290
|
const pkgPath = resolve4(dir, "package.json");
|
|
44329
45291
|
try {
|
|
44330
|
-
const pkg = JSON.parse(
|
|
45292
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
44331
45293
|
if (pkg.name === "@warmhub/cli") {
|
|
44332
45294
|
if (pkg.private === true)
|
|
44333
45295
|
return true;
|
|
@@ -44613,6 +45575,7 @@ function registerAllDomains(registry2) {
|
|
|
44613
45575
|
registry2.register(INIT_DOMAIN);
|
|
44614
45576
|
registry2.register(REPO_DOMAIN);
|
|
44615
45577
|
registry2.register(THING_DOMAIN);
|
|
45578
|
+
registry2.register(COLLECTION_DOMAIN);
|
|
44616
45579
|
registry2.register(COMMIT_DOMAIN);
|
|
44617
45580
|
registry2.register(ASSERTION_DOMAIN);
|
|
44618
45581
|
registry2.register(SHAPE_DOMAIN);
|
|
@@ -45735,7 +46698,7 @@ function resolveLogLevel(flags, env) {
|
|
|
45735
46698
|
// package.json
|
|
45736
46699
|
var package_default3 = {
|
|
45737
46700
|
name: "@warmhub/cli",
|
|
45738
|
-
version: "0.
|
|
46701
|
+
version: "0.68.0",
|
|
45739
46702
|
private: false,
|
|
45740
46703
|
type: "module",
|
|
45741
46704
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -46390,4 +47353,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
|
|
|
46390
47353
|
var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
|
|
46391
47354
|
process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
|
|
46392
47355
|
|
|
46393
|
-
//# debugId=
|
|
47356
|
+
//# debugId=201635543D774B8564756E2164756E21
|