Skip to content

Commit 142662d

Browse files
committed
feat(cli): add query relationship-types command
Query valid endpoint types for all relationship types. Allows users to discover which node types are valid sources and targets for each relationship type without trial-and-error. Resolves issue #19
1 parent eb740d2 commit 142662d

3 files changed

Lines changed: 74 additions & 0 deletions

File tree

src/cli/commands/query.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
queryNodesOp,
88
queryNodeOp,
99
queryRelationshipsOp,
10+
queryRelationshipTypesOp,
1011
traceFromNodeOp,
1112
timelineOp,
1213
nodeHistoryOp,
@@ -245,6 +246,30 @@ const timelineSubcommand: CommandDef = {
245246
},
246247
};
247248

249+
const relationshipTypesSubcommand: CommandDef = {
250+
name: "relationship-types",
251+
description: queryRelationshipTypesOp.def.description,
252+
apiLink: queryRelationshipTypesOp.def.name,
253+
opts: readOpts,
254+
action(_rawArgs: unknown, rawOpts: unknown) {
255+
const opts = readOpts.parse(rawOpts);
256+
const relTypes = queryRelationshipTypesOp({});
257+
if (opts.json) {
258+
console.log(JSON.stringify(relTypes, null, 2));
259+
} else {
260+
for (const relType of relTypes) {
261+
console.log(pc.bold(relType.type));
262+
console.log(
263+
` ${pc.dim("from")}: ${relType.from.map((t) => pc.cyan(t)).join(", ")}`,
264+
);
265+
console.log(
266+
` ${pc.dim("to")}: ${relType.to.map((t) => pc.cyan(t)).join(", ")}`,
267+
);
268+
}
269+
}
270+
},
271+
};
272+
248273
const stateAtSubcommand: CommandDef = {
249274
name: "state-at",
250275
description: stateAtOp.def.description,
@@ -283,6 +308,7 @@ export const queryCommand: CommandDef = {
283308
nodesSubcommand,
284309
nodeSubcommand,
285310
relsSubcommand,
311+
relationshipTypesSubcommand,
286312
traceSubcommand,
287313
timelineSubcommand,
288314
stateAtSubcommand,

src/operations/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export { planGateOp, type GateResultOutput } from "./plan-gate.js";
2626
export { queryNodesOp } from "./query-nodes.js";
2727
export { queryNodeOp, type NodeDetail } from "./query-node.js";
2828
export { queryRelationshipsOp } from "./query-relationships.js";
29+
export { queryRelationshipTypesOp } from "./query-relationship-types.js";
2930
export { traceFromNodeOp, type TraceNode } from "./trace-from-node.js";
3031

3132
// Temporal operations
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import * as z from "zod";
2+
import { defineOperation } from "./define-operation.js";
3+
import { RelationshipType, NodeType } from "../schema.js";
4+
import { RELATIONSHIP_ENDPOINT_TYPES } from "../endpoint-types.js";
5+
6+
/** Information about valid endpoint types for a relationship type. */
7+
export interface RelationshipTypeInfo {
8+
type: RelationshipType;
9+
from: NodeType[];
10+
to: NodeType[];
11+
}
12+
13+
/** Result of querying relationship endpoint types. */
14+
export const QueryRelationshipTypesResult = z.array(
15+
z.object({
16+
type: RelationshipType,
17+
from: z.array(NodeType),
18+
to: z.array(NodeType),
19+
}),
20+
);
21+
22+
/** Result type for queryRelationshipTypesOp. */
23+
export type QueryRelationshipTypesResult = z.infer<
24+
typeof QueryRelationshipTypesResult
25+
>;
26+
27+
/**
28+
* Query valid endpoint types for all relationship types.
29+
*
30+
* Returns a list of relationship types with their valid source and target node types.
31+
* Useful for discovering valid combinations before attempting to add relationships.
32+
*/
33+
export const queryRelationshipTypesOp = defineOperation({
34+
name: "query-relationship-types",
35+
description: "Query valid endpoint types for all relationship types",
36+
input: z.object({}),
37+
output: QueryRelationshipTypesResult,
38+
fn: (): RelationshipTypeInfo[] => {
39+
return Object.entries(RELATIONSHIP_ENDPOINT_TYPES).map(
40+
([relType, endpoints]) => ({
41+
type: RelationshipType.parse(relType),
42+
from: endpoints.from,
43+
to: endpoints.to,
44+
}),
45+
);
46+
},
47+
});

0 commit comments

Comments
 (0)