@salesforce/graphiti 11.13.2 → 11.15.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/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [11.15.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.14.0...v11.15.0) (2026-07-09)
7
+
8
+ **Note:** Version bump only for package @salesforce/graphiti
9
+
10
+ ## [11.14.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.13.2...v11.14.0) (2026-07-09)
11
+
12
+ ### Features
13
+
14
+ - **graphiti:** promote whole filter/orderBy argument to one optional $var ([#645](https://github.com/salesforce-experience-platform-emu/webapps/issues/645)) ([290c5be](https://github.com/salesforce-experience-platform-emu/webapps/commit/290c5be3e4249581e0f9050d42bb8c8ed9850d25))
15
+
6
16
  ## [11.13.2](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.13.1...v11.13.2) (2026-07-09)
7
17
 
8
18
  **Note:** Version bump only for package @salesforce/graphiti
@@ -9,7 +9,7 @@ import { selectChildRelationship } from "./select-child-relationship.js";
9
9
  import { assertGraphqlName } from "../lib/graphql-name.js";
10
10
  import { selectDottedFieldPath } from "../lib/path-selection.js";
11
11
  import { addVariable, createSession, deepSetArg, selectLeaf } from "../lib/session.js";
12
- import { normalizeOrderBy, promoteVariables } from "../lib/variable-promotion.js";
12
+ import { normalizeOrderBy, promoteArg, promoteVariables } from "../lib/variable-promotion.js";
13
13
  /**
14
14
  * Build a UIAPI list query against a Salesforce org. Implements `sf_gql_list`
15
15
  * intent for the graphiti MCP server.
@@ -58,17 +58,18 @@ export async function buildList(spec, deps) {
58
58
  }
59
59
  }
60
60
  const first = spec.first ?? 10;
61
- deepSetArg(session, connectionPath, "first", [], String(first));
61
+ const firstRendered = promoteArg(session, schema, connectionPath, "first", first).rendered;
62
+ deepSetArg(session, connectionPath, "first", [], firstRendered);
62
63
  selectLeaf(session, [...connectionPath, "pageInfo", "hasNextPage"]);
63
64
  selectLeaf(session, [...connectionPath, "pageInfo", "endCursor"]);
64
65
  if (spec.filter) {
65
- promoteVariables(session, schema, connectionPath, "where", spec.filter, extraWarnings);
66
- deepSetArg(session, connectionPath, "where", [], JSON.stringify(spec.filter));
66
+ const { rendered } = promoteArg(session, schema, connectionPath, "where", spec.filter, extraWarnings);
67
+ deepSetArg(session, connectionPath, "where", [], rendered);
67
68
  }
68
69
  const orderBy = normalizeOrderBy(spec.orderBy);
69
70
  if (orderBy) {
70
- promoteVariables(session, schema, connectionPath, "orderBy", orderBy, extraWarnings);
71
- deepSetArg(session, connectionPath, "orderBy", [], JSON.stringify(orderBy));
71
+ const { rendered } = promoteArg(session, schema, connectionPath, "orderBy", orderBy, extraWarnings);
72
+ deepSetArg(session, connectionPath, "orderBy", [], rendered);
72
73
  }
73
74
  if (spec.scope) {
74
75
  promoteVariables(session, schema, connectionPath, "scope", spec.scope, extraWarnings);
@@ -1 +1 @@
1
- {"version":3,"file":"build-list.js","sourceRoot":"","sources":["../../src/intent/build-list.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-list.js","sourceRoot":"","sources":["../../src/intent/build-list.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { selectDottedFieldPath } from "../lib/path-selection.js";
7
7
  import { deepSetArg } from "../lib/session.js";
8
- import { normalizeOrderBy, promoteVariables } from "../lib/variable-promotion.js";
8
+ import { normalizeOrderBy, promoteArg } from "../lib/variable-promotion.js";
9
9
  /**
10
10
  * Render a UIAPI child relationship onto an existing query session as
11
11
  * `<rel> { edges { node { ... } } }`, with optional `first` / `filter` /
@@ -23,16 +23,17 @@ export function selectChildRelationship(session, schema, parentNodePath, child,
23
23
  selectDottedFieldPath(session, schema, childNodePath, field);
24
24
  }
25
25
  if (child.first !== undefined) {
26
- deepSetArg(session, childConnectionPath, "first", [], String(child.first));
26
+ const firstRendered = promoteArg(session, schema, childConnectionPath, "first", child.first).rendered;
27
+ deepSetArg(session, childConnectionPath, "first", [], firstRendered);
27
28
  }
28
29
  if (child.filter) {
29
- promoteVariables(session, schema, childConnectionPath, "where", child.filter, warnings);
30
- deepSetArg(session, childConnectionPath, "where", [], JSON.stringify(child.filter));
30
+ const { rendered } = promoteArg(session, schema, childConnectionPath, "where", child.filter, warnings);
31
+ deepSetArg(session, childConnectionPath, "where", [], rendered);
31
32
  }
32
33
  const childOrderBy = normalizeOrderBy(child.orderBy);
33
34
  if (childOrderBy) {
34
- promoteVariables(session, schema, childConnectionPath, "orderBy", childOrderBy, warnings);
35
- deepSetArg(session, childConnectionPath, "orderBy", [], JSON.stringify(childOrderBy));
35
+ const { rendered } = promoteArg(session, schema, childConnectionPath, "orderBy", childOrderBy, warnings);
36
+ deepSetArg(session, childConnectionPath, "orderBy", [], rendered);
36
37
  }
37
38
  }
38
39
  //# sourceMappingURL=select-child-relationship.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-child-relationship.js","sourceRoot":"","sources":["../../src/intent/select-child-relationship.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAElF;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACtC,OAAqB,EACrB,MAAqB,EACrB,cAAwB,EACxB,KAA4B,EAC5B,QAAmB;IAEnB,MAAM,mBAAmB,GAAG,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACxE,MAAM,aAAa,GAAG,CAAC,GAAG,mBAAmB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEhE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QAClB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC1F,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IACvF,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"select-child-relationship.js","sourceRoot":"","sources":["../../src/intent/select-child-relationship.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE5E;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACtC,OAAqB,EACrB,MAAqB,EACrB,cAAwB,EACxB,KAA4B,EAC5B,QAAmB;IAEnB,MAAM,mBAAmB,GAAG,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACxE,MAAM,aAAa,GAAG,CAAC,GAAG,mBAAmB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEhE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,UAAU,CAC/B,OAAO,EACP,MAAM,EACN,mBAAmB,EACnB,OAAO,EACP,KAAK,CAAC,KAAK,CACX,CAAC,QAAQ,CAAC;QACX,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAC9B,OAAO,EACP,MAAM,EACN,mBAAmB,EACnB,OAAO,EACP,KAAK,CAAC,MAAM,EACZ,QAAQ,CACR,CAAC;QACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QAClB,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAC9B,OAAO,EACP,MAAM,EACN,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,QAAQ,CACR,CAAC;QACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnE,CAAC;AACF,CAAC"}
@@ -23,9 +23,9 @@ export interface VariableInfo {
23
23
  export interface ChildRelationshipSpec {
24
24
  relationshipName: string;
25
25
  fields: string[];
26
- first?: number;
27
- filter?: Record<string, unknown>;
28
- orderBy?: Record<string, unknown> | Record<string, unknown>[];
26
+ first?: number | string;
27
+ filter?: Record<string, unknown> | string;
28
+ orderBy?: Record<string, unknown> | Record<string, unknown>[] | string;
29
29
  }
30
30
  export interface ListSpec {
31
31
  org: string;
@@ -33,9 +33,9 @@ export interface ListSpec {
33
33
  fields: string[];
34
34
  parentFields?: string[];
35
35
  childRelationships?: ChildRelationshipSpec[];
36
- filter?: Record<string, unknown>;
37
- orderBy?: Record<string, unknown> | Record<string, unknown>[];
38
- first?: number;
36
+ filter?: Record<string, unknown> | string;
37
+ orderBy?: Record<string, unknown> | Record<string, unknown>[] | string;
38
+ first?: number | string;
39
39
  scope?: string;
40
40
  operationName?: string;
41
41
  }
@@ -56,6 +56,32 @@ import { type QuerySession } from "./session.js";
56
56
  * silently rendering the literal.
57
57
  */
58
58
  export declare function promoteVariables(session: QuerySession, schema: GraphQLSchema, fieldSchemaPath: string[], argName: string, value: unknown, warnings?: string[]): void;
59
+ /**
60
+ * Result of promoting one whole argument. `rendered` is what the caller
61
+ * hands to `deepSetArg`: the raw `$var` reference when the entire argument
62
+ * was a single `$varName` string, or the JSON-stringified value otherwise.
63
+ */
64
+ export interface ArgPromotion {
65
+ rendered: string;
66
+ }
67
+ /**
68
+ * Promote a `where` / `orderBy` argument that may be EITHER a normal
69
+ * object (whose `$varName` leaves promote via `promoteVariables`) OR a
70
+ * single top-level `$varName` string standing in for the whole argument.
71
+ *
72
+ * The whole-argument form is the idiomatic UIAPI pattern for an
73
+ * optionally-applied filter: a `null`-bound `where` means "no constraint →
74
+ * all rows", which a nullable leaf cannot express. When `value` is a
75
+ * whole-arg placeholder we infer the argument's own input type
76
+ * (e.g. `Case_Filter`, `Case_OrderBy`), declare one nullable variable, and
77
+ * return its `$ref` so the caller renders `where: $filter` directly.
78
+ *
79
+ * Type inference for a real `where`/`orderBy` argument effectively never
80
+ * fails, but if it does we still emit the variable as `String` and push a
81
+ * loud warning — a best-effort query the user can debug beats a hard error
82
+ * before they see anything.
83
+ */
84
+ export declare function promoteArg(session: QuerySession, schema: GraphQLSchema, fieldSchemaPath: string[], argName: string, value: unknown, warnings?: string[]): ArgPromotion;
59
85
  /**
60
86
  * Collapses an array-shaped orderBy input to its first element, so
61
87
  * callers can pass either shape without knowing Salesforce's
@@ -78,6 +78,49 @@ function walk(session, schema, fieldSchemaPath, argName, value, pathInsideArg, w
78
78
  }
79
79
  }
80
80
  }
81
+ /**
82
+ * Promote a `where` / `orderBy` argument that may be EITHER a normal
83
+ * object (whose `$varName` leaves promote via `promoteVariables`) OR a
84
+ * single top-level `$varName` string standing in for the whole argument.
85
+ *
86
+ * The whole-argument form is the idiomatic UIAPI pattern for an
87
+ * optionally-applied filter: a `null`-bound `where` means "no constraint →
88
+ * all rows", which a nullable leaf cannot express. When `value` is a
89
+ * whole-arg placeholder we infer the argument's own input type
90
+ * (e.g. `Case_Filter`, `Case_OrderBy`), declare one nullable variable, and
91
+ * return its `$ref` so the caller renders `where: $filter` directly.
92
+ *
93
+ * Type inference for a real `where`/`orderBy` argument effectively never
94
+ * fails, but if it does we still emit the variable as `String` and push a
95
+ * loud warning — a best-effort query the user can debug beats a hard error
96
+ * before they see anything.
97
+ */
98
+ export function promoteArg(session, schema, fieldSchemaPath, argName, value, warnings) {
99
+ if (typeof value === "string") {
100
+ const m = VAR_PLACEHOLDER_RE.exec(value);
101
+ if (m && m[1]) {
102
+ const varName = m[1];
103
+ try {
104
+ const { inferredType } = inferTypeFromArgsPath(schema, session.operation, fieldSchemaPath, [
105
+ argName,
106
+ ]);
107
+ const declared = inferredType.endsWith("!") ? inferredType.slice(0, -1) : inferredType;
108
+ addVariable(session, varName, declared);
109
+ }
110
+ catch (err) {
111
+ addVariable(session, varName, "String");
112
+ const hint = err instanceof Error ? ` (${err.message})` : "";
113
+ warnings?.push(`Variable: could not infer the GraphQL type for whole-argument '${value}' on '${argName}'${hint}; declared as 'String'. The rendered query may be invalid — verify the variable type.`);
114
+ }
115
+ return { rendered: value };
116
+ }
117
+ // A `$`-prefixed string that is not a valid placeholder, or any other
118
+ // bare string: fall through to leaf handling, which emits the existing
119
+ // invalid-placeholder warning and renders the literal.
120
+ }
121
+ promoteVariables(session, schema, fieldSchemaPath, argName, value, warnings);
122
+ return { rendered: JSON.stringify(value) };
123
+ }
81
124
  /**
82
125
  * Collapses an array-shaped orderBy input to its first element, so
83
126
  * callers can pass either shape without knowing Salesforce's
@@ -1 +1 @@
1
- {"version":3,"file":"variable-promotion.js","sourceRoot":"","sources":["../../src/lib/variable-promotion.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"variable-promotion.js","sourceRoot":"","sources":["../../src/lib/variable-promotion.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,28 @@
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
6
  import { z } from "zod";
7
+ /**
8
+ * Some MCP clients/models JSON-stringify complex tool arguments (e.g. send
9
+ * `"25"` for a number or `'{"x":1}'` for an object). This coerces such a
10
+ * string back to its parsed value so the real value validates — lossless,
11
+ * and scoped to strings that LOOK like JSON (object/array/number) so `$var`
12
+ * placeholders and enum strings (e.g. scope "MINE") are left untouched.
13
+ * Same "tolerate predictable client encoding quirks" philosophy as the
14
+ * detailOrderBy array-collapse shim.
15
+ */
16
+ export declare const coerceJsonArg: (v: unknown) => unknown;
17
+ /** Wrap a schema so a JSON-stringified value is coerced before validation. */
18
+ export declare const jsonCoercible: (schema: z.ZodTypeAny) => z.ZodEffects<z.ZodTypeAny, any, unknown>;
19
+ /** A string that looks like a JSON object/array literal — used so the advertised
20
+ * schema accepts a stringified object/array; coerceJsonArg then parses it. A
21
+ * `{`/`[`-prefixed but invalid-JSON string is accepted as a literal (rare; the
22
+ * model reliably sends valid JSON) rather than erroring. */
23
+ export declare const jsonLiteralString: () => z.ZodString;
24
+ /** A string of digits — a stringified positive integer for `first`. */
25
+ export declare const intLiteralString: () => z.ZodString;
26
+ /** A JSON-quoted string literal, e.g. "\"$first\"" or "\"25\"" — some models
27
+ * double-encode args. coerceJsonArg unwraps it before validation. */
28
+ export declare const quotedString: () => z.ZodString;
7
29
  /**
8
30
  * Zod string validator that enforces the GraphQL Name production. Returned
9
31
  * schema is `.describe()`-tagged with the supplied description so it appears
@@ -12,11 +34,18 @@ import { z } from "zod";
12
34
  export declare const graphqlName: (description: string) => z.ZodString;
13
35
  export declare const orgAlias: (description: string) => z.ZodString;
14
36
  /**
15
- * `<Object>_OrderBy` shape. UIAPI accepts a singleton object; tools may
16
- * additionally accept arrays as a compat shim depending on their advertised
17
- * schema policy (see `sf-gql-list.ts` vs `sf-gql-detail.ts`).
37
+ * `<Object>_OrderBy` shape. A FACTORY (not a shared instance): each call returns
38
+ * a fresh schema so the MCP SDK's zod-to-json-schema converter INLINES it at every
39
+ * use site instead of collapsing reuse into cross-`$ref`s (which intermittently
40
+ * dropped union branches in the advertised schema).
18
41
  */
19
- export declare const orderByObject: z.ZodRecord<z.ZodString, z.ZodUnknown>;
42
+ export declare const orderByObject: () => z.ZodRecord<z.ZodString, z.ZodUnknown>;
43
+ /**
44
+ * A bare top-level `$varName` string standing in for an entire `filter` /
45
+ * `orderBy` / `first` argument. A FACTORY (not a shared instance) so the advertised
46
+ * JSON Schema inlines it at every use site rather than emitting cross-`$ref`s.
47
+ */
48
+ export declare const varPlaceholder: () => z.ZodString;
20
49
  /**
21
50
  * Build a `childRelationships[]` element schema. The `orderBy` schema is a
22
51
  * parameter because tools differ on whether they advertise the array shape
@@ -31,19 +60,19 @@ export declare const orderByObject: z.ZodRecord<z.ZodString, z.ZodUnknown>;
31
60
  export declare const childRelationshipSchema: (orderBy: z.ZodTypeAny) => z.ZodObject<{
32
61
  relationshipName: z.ZodString;
33
62
  fields: z.ZodArray<z.ZodString, "many">;
34
- first: z.ZodOptional<z.ZodNumber>;
35
- filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
36
- orderBy: z.ZodOptional<z.ZodTypeAny>;
63
+ first: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
64
+ filter: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
65
+ orderBy: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
37
66
  }, "strip", z.ZodTypeAny, {
38
67
  relationshipName: string;
39
68
  fields: string[];
40
- filter?: Record<string, unknown> | undefined;
69
+ filter?: any;
41
70
  orderBy?: any;
42
- first?: number | undefined;
71
+ first?: any;
43
72
  }, {
44
73
  relationshipName: string;
45
74
  fields: string[];
46
- filter?: Record<string, unknown> | undefined;
47
- orderBy?: any;
48
- first?: number | undefined;
75
+ filter?: unknown;
76
+ orderBy?: unknown;
77
+ first?: unknown;
49
78
  }>;
@@ -5,6 +5,49 @@
5
5
  */
6
6
  import { z } from "zod";
7
7
  import { GRAPHQL_NAME_RE } from "../lib/graphql-name.js";
8
+ /**
9
+ * Some MCP clients/models JSON-stringify complex tool arguments (e.g. send
10
+ * `"25"` for a number or `'{"x":1}'` for an object). This coerces such a
11
+ * string back to its parsed value so the real value validates — lossless,
12
+ * and scoped to strings that LOOK like JSON (object/array/number) so `$var`
13
+ * placeholders and enum strings (e.g. scope "MINE") are left untouched.
14
+ * Same "tolerate predictable client encoding quirks" philosophy as the
15
+ * detailOrderBy array-collapse shim.
16
+ */
17
+ export const coerceJsonArg = (v) => {
18
+ const once = coerceJsonOnce(v);
19
+ // Unwrapping a double-quoted string (e.g. '"25"' → "25", '"$first"' → "$first")
20
+ // can yield another coercible string; coerce one more level so '"25"' → 25.
21
+ if (typeof once === "string" && once !== v)
22
+ return coerceJsonOnce(once);
23
+ return once;
24
+ };
25
+ const coerceJsonOnce = (v) => {
26
+ if (typeof v !== "string")
27
+ return v;
28
+ const t = v.trim();
29
+ // object/array, bare number, OR a JSON-quoted string literal
30
+ if (!(t.startsWith("{") || t.startsWith("[") || /^-?\d+(\.\d+)?$/.test(t) || t.startsWith('"')))
31
+ return v;
32
+ try {
33
+ return JSON.parse(t);
34
+ }
35
+ catch {
36
+ return v;
37
+ }
38
+ };
39
+ /** Wrap a schema so a JSON-stringified value is coerced before validation. */
40
+ export const jsonCoercible = (schema) => z.preprocess(coerceJsonArg, schema);
41
+ /** A string that looks like a JSON object/array literal — used so the advertised
42
+ * schema accepts a stringified object/array; coerceJsonArg then parses it. A
43
+ * `{`/`[`-prefixed but invalid-JSON string is accepted as a literal (rare; the
44
+ * model reliably sends valid JSON) rather than erroring. */
45
+ export const jsonLiteralString = () => z.string().regex(/^\s*[{[]/);
46
+ /** A string of digits — a stringified positive integer for `first`. */
47
+ export const intLiteralString = () => z.string().regex(/^\d+$/);
48
+ /** A JSON-quoted string literal, e.g. "\"$first\"" or "\"25\"" — some models
49
+ * double-encode args. coerceJsonArg unwraps it before validation. */
50
+ export const quotedString = () => z.string().regex(/^".*"$/s);
8
51
  /**
9
52
  * Zod string validator that enforces the GraphQL Name production. Returned
10
53
  * schema is `.describe()`-tagged with the supplied description so it appears
@@ -20,11 +63,18 @@ export const graphqlName = (description) => z.string().regex(GRAPHQL_NAME_RE, "m
20
63
  const ORG_ALIAS_RE = /^[A-Za-z0-9_][A-Za-z0-9_.+@-]{0,252}$/;
21
64
  export const orgAlias = (description) => z.string().regex(ORG_ALIAS_RE, "must be a valid org alias or username").describe(description);
22
65
  /**
23
- * `<Object>_OrderBy` shape. UIAPI accepts a singleton object; tools may
24
- * additionally accept arrays as a compat shim depending on their advertised
25
- * schema policy (see `sf-gql-list.ts` vs `sf-gql-detail.ts`).
66
+ * `<Object>_OrderBy` shape. A FACTORY (not a shared instance): each call returns
67
+ * a fresh schema so the MCP SDK's zod-to-json-schema converter INLINES it at every
68
+ * use site instead of collapsing reuse into cross-`$ref`s (which intermittently
69
+ * dropped union branches in the advertised schema).
70
+ */
71
+ export const orderByObject = () => z.record(z.unknown());
72
+ /**
73
+ * A bare top-level `$varName` string standing in for an entire `filter` /
74
+ * `orderBy` / `first` argument. A FACTORY (not a shared instance) so the advertised
75
+ * JSON Schema inlines it at every use site rather than emitting cross-`$ref`s.
26
76
  */
27
- export const orderByObject = z.record(z.unknown());
77
+ export const varPlaceholder = () => z.string().regex(/^\$[A-Za-z_]\w*$/, "must be a $variable placeholder, e.g. $filter");
28
78
  /**
29
79
  * Build a `childRelationships[]` element schema. The `orderBy` schema is a
30
80
  * parameter because tools differ on whether they advertise the array shape
@@ -39,8 +89,8 @@ export const orderByObject = z.record(z.unknown());
39
89
  export const childRelationshipSchema = (orderBy) => z.object({
40
90
  relationshipName: graphqlName('Child relationship API name, e.g. "Contacts", "Opportunities". Must be a valid GraphQL Name.'),
41
91
  fields: z.array(z.string()),
42
- first: z.number().int().positive().optional(),
43
- filter: z.record(z.unknown()).optional(),
44
- orderBy: orderBy.optional(),
92
+ first: jsonCoercible(z.union([z.number().int().positive(), varPlaceholder(), intLiteralString(), quotedString()])).optional(),
93
+ filter: jsonCoercible(z.union([z.record(z.unknown()), varPlaceholder(), jsonLiteralString(), quotedString()])).optional(),
94
+ orderBy: jsonCoercible(z.union([orderBy, varPlaceholder(), jsonLiteralString(), quotedString()])).optional(),
45
95
  });
46
96
  //# sourceMappingURL=fields.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/schemas/fields.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,WAAmB,EAAe,EAAE,CAC/D,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAC7D,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,WAAmB,EAAe,EAAE,CAC5D,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,uCAAuC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAE/F;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAqB,EAAE,EAAE,CAChE,CAAC,CAAC,MAAM,CAAC;IACR,gBAAgB,EAAE,WAAW,CAC5B,8FAA8F,CAC9F;IACD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;IACxC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC"}
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/schemas/fields.ts"],"names":[],"mappings":"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"}
@@ -23,60 +23,60 @@ export declare const LIST_INPUT: z.ZodObject<{
23
23
  childRelationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
24
24
  relationshipName: z.ZodString;
25
25
  fields: z.ZodArray<z.ZodString, "many">;
26
- first: z.ZodOptional<z.ZodNumber>;
27
- filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
28
- orderBy: z.ZodOptional<z.ZodTypeAny>;
26
+ first: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
27
+ filter: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
28
+ orderBy: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
29
29
  }, "strip", z.ZodTypeAny, {
30
30
  relationshipName: string;
31
31
  fields: string[];
32
- filter?: Record<string, unknown> | undefined;
32
+ filter?: any;
33
33
  orderBy?: any;
34
- first?: number | undefined;
34
+ first?: any;
35
35
  }, {
36
36
  relationshipName: string;
37
37
  fields: string[];
38
- filter?: Record<string, unknown> | undefined;
39
- orderBy?: any;
40
- first?: number | undefined;
38
+ filter?: unknown;
39
+ orderBy?: unknown;
40
+ first?: unknown;
41
41
  }>, "many">>;
42
- filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
43
- orderBy: z.ZodOptional<z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">]>>;
44
- first: z.ZodOptional<z.ZodNumber>;
42
+ filter: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
43
+ orderBy: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
44
+ first: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
45
45
  scope: z.ZodOptional<z.ZodString>;
46
46
  operationName: z.ZodOptional<z.ZodString>;
47
47
  }, "strip", z.ZodTypeAny, {
48
48
  object: string;
49
49
  org: string;
50
50
  fields: string[];
51
- filter?: Record<string, unknown> | undefined;
51
+ filter?: any;
52
52
  operationName?: string | undefined;
53
- orderBy?: Record<string, unknown> | Record<string, unknown>[] | undefined;
54
- first?: number | undefined;
53
+ orderBy?: any;
54
+ first?: any;
55
55
  scope?: string | undefined;
56
56
  parentFields?: string[] | undefined;
57
57
  childRelationships?: {
58
58
  relationshipName: string;
59
59
  fields: string[];
60
- filter?: Record<string, unknown> | undefined;
60
+ filter?: any;
61
61
  orderBy?: any;
62
- first?: number | undefined;
62
+ first?: any;
63
63
  }[] | undefined;
64
64
  }, {
65
65
  object: string;
66
66
  org: string;
67
67
  fields: string[];
68
- filter?: Record<string, unknown> | undefined;
68
+ filter?: unknown;
69
69
  operationName?: string | undefined;
70
- orderBy?: Record<string, unknown> | Record<string, unknown>[] | undefined;
71
- first?: number | undefined;
70
+ orderBy?: unknown;
71
+ first?: unknown;
72
72
  scope?: string | undefined;
73
73
  parentFields?: string[] | undefined;
74
74
  childRelationships?: {
75
75
  relationshipName: string;
76
76
  fields: string[];
77
- filter?: Record<string, unknown> | undefined;
78
- orderBy?: any;
79
- first?: number | undefined;
77
+ filter?: unknown;
78
+ orderBy?: unknown;
79
+ first?: unknown;
80
80
  }[] | undefined;
81
81
  }>;
82
82
  export declare const DETAIL_INPUT: z.ZodObject<{
@@ -87,21 +87,21 @@ export declare const DETAIL_INPUT: z.ZodObject<{
87
87
  childRelationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
88
88
  relationshipName: z.ZodString;
89
89
  fields: z.ZodArray<z.ZodString, "many">;
90
- first: z.ZodOptional<z.ZodNumber>;
91
- filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
92
- orderBy: z.ZodOptional<z.ZodTypeAny>;
90
+ first: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
91
+ filter: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
92
+ orderBy: z.ZodOptional<z.ZodEffects<z.ZodTypeAny, any, unknown>>;
93
93
  }, "strip", z.ZodTypeAny, {
94
94
  relationshipName: string;
95
95
  fields: string[];
96
- filter?: Record<string, unknown> | undefined;
96
+ filter?: any;
97
97
  orderBy?: any;
98
- first?: number | undefined;
98
+ first?: any;
99
99
  }, {
100
100
  relationshipName: string;
101
101
  fields: string[];
102
- filter?: Record<string, unknown> | undefined;
103
- orderBy?: any;
104
- first?: number | undefined;
102
+ filter?: unknown;
103
+ orderBy?: unknown;
104
+ first?: unknown;
105
105
  }>, "many">>;
106
106
  idVariable: z.ZodOptional<z.ZodString>;
107
107
  operationName: z.ZodOptional<z.ZodString>;
@@ -114,9 +114,9 @@ export declare const DETAIL_INPUT: z.ZodObject<{
114
114
  childRelationships?: {
115
115
  relationshipName: string;
116
116
  fields: string[];
117
- filter?: Record<string, unknown> | undefined;
117
+ filter?: any;
118
118
  orderBy?: any;
119
- first?: number | undefined;
119
+ first?: any;
120
120
  }[] | undefined;
121
121
  idVariable?: string | undefined;
122
122
  }, {
@@ -128,9 +128,9 @@ export declare const DETAIL_INPUT: z.ZodObject<{
128
128
  childRelationships?: {
129
129
  relationshipName: string;
130
130
  fields: string[];
131
- filter?: Record<string, unknown> | undefined;
132
- orderBy?: any;
133
- first?: number | undefined;
131
+ filter?: unknown;
132
+ orderBy?: unknown;
133
+ first?: unknown;
134
134
  }[] | undefined;
135
135
  idVariable?: string | undefined;
136
136
  }>;
@@ -15,12 +15,19 @@
15
15
  * schemas; behavior is unchanged — this is a pure extraction.
16
16
  */
17
17
  import { z } from "zod";
18
- import { childRelationshipSchema, graphqlName, orderByObject, orgAlias } from "./fields.js";
18
+ import { childRelationshipSchema, graphqlName, intLiteralString, jsonCoercible, jsonLiteralString, orderByObject, orgAlias, quotedString, varPlaceholder, } from "./fields.js";
19
19
  import { GROUP_BY_FUNCTIONS } from "../intent/types.js";
20
20
  // --- sf_gql_list ------------------------------------------------------------
21
21
  // `sf_gql_list` advertises both shapes (singleton + array) for backward
22
22
  // compatibility with early MCP clients that learned the array form.
23
- const listOrderBySchema = z.union([orderByObject, z.array(orderByObject)]);
23
+ // Factory function to avoid cross-$ref deduplication.
24
+ const listOrderBySchema = () => z.union([
25
+ orderByObject(),
26
+ z.array(orderByObject()),
27
+ varPlaceholder(),
28
+ jsonLiteralString(),
29
+ quotedString(),
30
+ ]);
24
31
  export const LIST_INPUT = z.object({
25
32
  org: z.string().describe("Org alias resolved via local Salesforce CLI auth (~/.sf, ~/.sfdx)."),
26
33
  object: graphqlName('SObject API name, e.g. "Account", "Case". Must be a valid GraphQL Name.'),
@@ -31,20 +38,16 @@ export const LIST_INPUT = z.object({
31
38
  .array(z.string())
32
39
  .optional()
33
40
  .describe('Dotted parent-relationship paths, e.g. "Account.Name".'),
34
- childRelationships: z.array(childRelationshipSchema(listOrderBySchema)).optional(),
35
- filter: z
36
- .record(z.unknown())
41
+ childRelationships: z.array(childRelationshipSchema(listOrderBySchema())).optional(),
42
+ filter: jsonCoercible(z.union([z.record(z.unknown()), varPlaceholder(), jsonLiteralString(), quotedString()]))
37
43
  .optional()
38
- .describe("<Object>_Filter shape. String leaves matching $varName promote to typed query variables."),
39
- orderBy: listOrderBySchema
44
+ .describe('<Object>_Filter shape — pass as a JSON OBJECT (e.g. {"Status":{"eq":"New"}}), not a JSON-stringified string. String leaves matching $varName promote to typed query variables. Pass a single "$varName" string to promote the WHOLE filter to one optional <Object>_Filter variable (bind it to null for "no filter → all rows").'),
45
+ orderBy: jsonCoercible(listOrderBySchema())
40
46
  .optional()
41
- .describe("<Object>_OrderBy. Singleton object preferred; arrays are collapsed to the first entry."),
42
- first: z
43
- .number()
44
- .int()
45
- .positive()
47
+ .describe('<Object>_OrderBy — pass as a JSON OBJECT (e.g. {"CreatedDate":{"order":"DESC"}}), not a JSON-stringified string. Singleton object preferred; arrays are collapsed to the first entry. Pass a single "$varName" string to promote the whole orderBy to one optional <Object>_OrderBy variable.'),
48
+ first: jsonCoercible(z.union([z.number().int().positive(), varPlaceholder(), intLiteralString(), quotedString()]))
46
49
  .optional()
47
- .describe("Top-level connection page size; defaults to 10."),
50
+ .describe('Top-level connection page size as a NUMBER (e.g. 25, not "25"); defaults to 10. Pass a single "$varName" string to promote it to an optional Int variable.'),
48
51
  scope: z.string().optional().describe('Scope enum (e.g. "MINE", "EVERYTHING") or $varName.'),
49
52
  operationName: graphqlName("Override the GraphQL operation name. Defaults to <Object>List.").optional(),
50
53
  });
@@ -53,7 +56,8 @@ export const LIST_INPUT = z.object({
53
56
  // arrays at runtime via `z.preprocess` (FR-6.2 compat shim for early MCP
54
57
  // clients that learned the array shape). The transform collapses to the first
55
58
  // element before validation, so downstream code sees a singleton.
56
- const detailOrderBySchema = z.preprocess((v) => (Array.isArray(v) ? v[0] : v), orderByObject);
59
+ // Factory function to avoid cross-$ref deduplication.
60
+ const detailOrderBySchema = () => z.preprocess((v) => (Array.isArray(v) ? v[0] : v), orderByObject());
57
61
  // Note: filter/orderBy/scope/first are intentionally absent at the top level —
58
62
  // `sf_gql_detail` is single-record-by-Id (FR-5.5). Filtering happens via the
59
63
  // declared `$<idVariable>: ID!`; pagination doesn't apply.
@@ -72,7 +76,7 @@ export const DETAIL_INPUT = z
72
76
  .array(z.string())
73
77
  .optional()
74
78
  .describe('Dotted parent-relationship paths, e.g. "Account.Name".'),
75
- childRelationships: z.array(childRelationshipSchema(detailOrderBySchema)).optional(),
79
+ childRelationships: z.array(childRelationshipSchema(detailOrderBySchema())).optional(),
76
80
  idVariable: graphqlName('Name (without leading "$") for the ID variable. Defaults to "id". Declared as <name>: ID! and bound via where { Id: { eq: $<name> } } per FR-5.5. Choose a name that does not appear as a $varName in any childRelationships filter/orderBy — collisions are rejected.').optional(),
77
81
  operationName: graphqlName("Override the GraphQL operation name. Defaults to <Object>Detail.").optional(),
78
82
  })