@salesforce/graphiti 10.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/AGENT_GUIDE.md +424 -0
  2. package/CHANGELOG.md +448 -0
  3. package/LICENSE.txt +82 -0
  4. package/README.md +204 -0
  5. package/TASK.md +249 -0
  6. package/dist/cli.d.ts +7 -0
  7. package/dist/cli.js +683 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/args.d.ts +13 -0
  10. package/dist/commands/args.js +207 -0
  11. package/dist/commands/args.js.map +1 -0
  12. package/dist/commands/build.d.ts +11 -0
  13. package/dist/commands/build.js +209 -0
  14. package/dist/commands/build.js.map +1 -0
  15. package/dist/commands/connect.d.ts +8 -0
  16. package/dist/commands/connect.js +55 -0
  17. package/dist/commands/connect.js.map +1 -0
  18. package/dist/commands/describe.d.ts +6 -0
  19. package/dist/commands/describe.js +229 -0
  20. package/dist/commands/describe.js.map +1 -0
  21. package/dist/commands/meta.d.ts +9 -0
  22. package/dist/commands/meta.js +140 -0
  23. package/dist/commands/meta.js.map +1 -0
  24. package/dist/commands/navigate.d.ts +14 -0
  25. package/dist/commands/navigate.js +105 -0
  26. package/dist/commands/navigate.js.map +1 -0
  27. package/dist/commands/query-helpers.d.ts +80 -0
  28. package/dist/commands/query-helpers.js +865 -0
  29. package/dist/commands/query-helpers.js.map +1 -0
  30. package/dist/commands/query.d.ts +26 -0
  31. package/dist/commands/query.js +901 -0
  32. package/dist/commands/query.js.map +1 -0
  33. package/dist/commands/review.d.ts +18 -0
  34. package/dist/commands/review.js +533 -0
  35. package/dist/commands/review.js.map +1 -0
  36. package/dist/commands/session-mgmt.d.ts +25 -0
  37. package/dist/commands/session-mgmt.js +206 -0
  38. package/dist/commands/session-mgmt.js.map +1 -0
  39. package/dist/commands/type.d.ts +6 -0
  40. package/dist/commands/type.js +342 -0
  41. package/dist/commands/type.js.map +1 -0
  42. package/dist/commands/validate-input.d.ts +6 -0
  43. package/dist/commands/validate-input.js +32 -0
  44. package/dist/commands/validate-input.js.map +1 -0
  45. package/dist/intent/build-aggregate.d.ts +33 -0
  46. package/dist/intent/build-aggregate.js +134 -0
  47. package/dist/intent/build-aggregate.js.map +1 -0
  48. package/dist/intent/build-create.d.ts +14 -0
  49. package/dist/intent/build-create.js +16 -0
  50. package/dist/intent/build-create.js.map +1 -0
  51. package/dist/intent/build-delete.d.ts +30 -0
  52. package/dist/intent/build-delete.js +53 -0
  53. package/dist/intent/build-delete.js.map +1 -0
  54. package/dist/intent/build-detail.d.ts +32 -0
  55. package/dist/intent/build-detail.js +80 -0
  56. package/dist/intent/build-detail.js.map +1 -0
  57. package/dist/intent/build-discover.d.ts +30 -0
  58. package/dist/intent/build-discover.js +149 -0
  59. package/dist/intent/build-discover.js.map +1 -0
  60. package/dist/intent/build-list.d.ts +28 -0
  61. package/dist/intent/build-list.js +75 -0
  62. package/dist/intent/build-list.js.map +1 -0
  63. package/dist/intent/build-mutation.d.ts +23 -0
  64. package/dist/intent/build-mutation.js +54 -0
  65. package/dist/intent/build-mutation.js.map +1 -0
  66. package/dist/intent/build-output.d.ts +27 -0
  67. package/dist/intent/build-output.js +60 -0
  68. package/dist/intent/build-output.js.map +1 -0
  69. package/dist/intent/build-raw.d.ts +23 -0
  70. package/dist/intent/build-raw.js +54 -0
  71. package/dist/intent/build-raw.js.map +1 -0
  72. package/dist/intent/build-update.d.ts +14 -0
  73. package/dist/intent/build-update.js +16 -0
  74. package/dist/intent/build-update.js.map +1 -0
  75. package/dist/intent/get-schema-with-priming.d.ts +26 -0
  76. package/dist/intent/get-schema-with-priming.js +32 -0
  77. package/dist/intent/get-schema-with-priming.js.map +1 -0
  78. package/dist/intent/select-child-relationship.d.ts +19 -0
  79. package/dist/intent/select-child-relationship.js +38 -0
  80. package/dist/intent/select-child-relationship.js.map +1 -0
  81. package/dist/intent/types.d.ts +159 -0
  82. package/dist/intent/types.js +21 -0
  83. package/dist/intent/types.js.map +1 -0
  84. package/dist/lib/apply-command.d.ts +15 -0
  85. package/dist/lib/apply-command.js +238 -0
  86. package/dist/lib/apply-command.js.map +1 -0
  87. package/dist/lib/auth.d.ts +38 -0
  88. package/dist/lib/auth.js +113 -0
  89. package/dist/lib/auth.js.map +1 -0
  90. package/dist/lib/codegen.d.ts +32 -0
  91. package/dist/lib/codegen.js +700 -0
  92. package/dist/lib/codegen.js.map +1 -0
  93. package/dist/lib/command-registry.d.ts +59 -0
  94. package/dist/lib/command-registry.js +366 -0
  95. package/dist/lib/command-registry.js.map +1 -0
  96. package/dist/lib/formatter.d.ts +76 -0
  97. package/dist/lib/formatter.js +419 -0
  98. package/dist/lib/formatter.js.map +1 -0
  99. package/dist/lib/fs-utils.d.ts +23 -0
  100. package/dist/lib/fs-utils.js +46 -0
  101. package/dist/lib/fs-utils.js.map +1 -0
  102. package/dist/lib/graphql-name.d.ts +27 -0
  103. package/dist/lib/graphql-name.js +32 -0
  104. package/dist/lib/graphql-name.js.map +1 -0
  105. package/dist/lib/interactive.d.ts +6 -0
  106. package/dist/lib/interactive.js +562 -0
  107. package/dist/lib/interactive.js.map +1 -0
  108. package/dist/lib/introspect.d.ts +40 -0
  109. package/dist/lib/introspect.js +280 -0
  110. package/dist/lib/introspect.js.map +1 -0
  111. package/dist/lib/object-info.d.ts +79 -0
  112. package/dist/lib/object-info.js +313 -0
  113. package/dist/lib/object-info.js.map +1 -0
  114. package/dist/lib/path-selection.d.ts +50 -0
  115. package/dist/lib/path-selection.js +146 -0
  116. package/dist/lib/path-selection.js.map +1 -0
  117. package/dist/lib/prime-schema.d.ts +59 -0
  118. package/dist/lib/prime-schema.js +158 -0
  119. package/dist/lib/prime-schema.js.map +1 -0
  120. package/dist/lib/query-builder.d.ts +10 -0
  121. package/dist/lib/query-builder.js +168 -0
  122. package/dist/lib/query-builder.js.map +1 -0
  123. package/dist/lib/query-commands.d.ts +19 -0
  124. package/dist/lib/query-commands.js +262 -0
  125. package/dist/lib/query-commands.js.map +1 -0
  126. package/dist/lib/session.d.ts +205 -0
  127. package/dist/lib/session.js +1075 -0
  128. package/dist/lib/session.js.map +1 -0
  129. package/dist/lib/tokenize.d.ts +12 -0
  130. package/dist/lib/tokenize.js +48 -0
  131. package/dist/lib/tokenize.js.map +1 -0
  132. package/dist/lib/uiapi.d.ts +109 -0
  133. package/dist/lib/uiapi.js +159 -0
  134. package/dist/lib/uiapi.js.map +1 -0
  135. package/dist/lib/validator.d.ts +27 -0
  136. package/dist/lib/validator.js +100 -0
  137. package/dist/lib/validator.js.map +1 -0
  138. package/dist/lib/variable-promotion.d.ts +69 -0
  139. package/dist/lib/variable-promotion.js +95 -0
  140. package/dist/lib/variable-promotion.js.map +1 -0
  141. package/dist/lib/walker.d.ts +147 -0
  142. package/dist/lib/walker.js +723 -0
  143. package/dist/lib/walker.js.map +1 -0
  144. package/dist/mcp/server.d.ts +7 -0
  145. package/dist/mcp/server.js +34 -0
  146. package/dist/mcp/server.js.map +1 -0
  147. package/dist/mcp/stdio.d.ts +7 -0
  148. package/dist/mcp/stdio.js +25 -0
  149. package/dist/mcp/stdio.js.map +1 -0
  150. package/dist/mcp/tools/echo.d.ts +7 -0
  151. package/dist/mcp/tools/echo.js +17 -0
  152. package/dist/mcp/tools/echo.js.map +1 -0
  153. package/dist/mcp/tools/sf-gql-aggregate.d.ts +11 -0
  154. package/dist/mcp/tools/sf-gql-aggregate.js +75 -0
  155. package/dist/mcp/tools/sf-gql-aggregate.js.map +1 -0
  156. package/dist/mcp/tools/sf-gql-create.d.ts +11 -0
  157. package/dist/mcp/tools/sf-gql-create.js +35 -0
  158. package/dist/mcp/tools/sf-gql-create.js.map +1 -0
  159. package/dist/mcp/tools/sf-gql-delete.d.ts +11 -0
  160. package/dist/mcp/tools/sf-gql-delete.js +31 -0
  161. package/dist/mcp/tools/sf-gql-delete.js.map +1 -0
  162. package/dist/mcp/tools/sf-gql-detail.d.ts +11 -0
  163. package/dist/mcp/tools/sf-gql-detail.js +58 -0
  164. package/dist/mcp/tools/sf-gql-detail.js.map +1 -0
  165. package/dist/mcp/tools/sf-gql-discover.d.ts +9 -0
  166. package/dist/mcp/tools/sf-gql-discover.js +51 -0
  167. package/dist/mcp/tools/sf-gql-discover.js.map +1 -0
  168. package/dist/mcp/tools/sf-gql-list.d.ts +11 -0
  169. package/dist/mcp/tools/sf-gql-list.js +53 -0
  170. package/dist/mcp/tools/sf-gql-list.js.map +1 -0
  171. package/dist/mcp/tools/sf-gql-raw.d.ts +11 -0
  172. package/dist/mcp/tools/sf-gql-raw.js +39 -0
  173. package/dist/mcp/tools/sf-gql-raw.js.map +1 -0
  174. package/dist/mcp/tools/sf-gql-update.d.ts +11 -0
  175. package/dist/mcp/tools/sf-gql-update.js +35 -0
  176. package/dist/mcp/tools/sf-gql-update.js.map +1 -0
  177. package/dist/mcp/tools/shared/zod-schemas.d.ts +49 -0
  178. package/dist/mcp/tools/shared/zod-schemas.js +46 -0
  179. package/dist/mcp/tools/shared/zod-schemas.js.map +1 -0
  180. package/package.json +36 -0
  181. package/ralph-loop.sh +120 -0
  182. package/scripts/smoke-orderby.sh +190 -0
  183. package/src/__tests__/helpers/prime-deps.ts +46 -0
  184. package/src/__tests__/helpers/schema.ts +73 -0
  185. package/src/__tests__/helpers/stdout.ts +33 -0
  186. package/src/__tests__/setup.ts +19 -0
  187. package/src/cli.ts +764 -0
  188. package/src/commands/__tests__/query.spec.ts +137 -0
  189. package/src/commands/args.ts +306 -0
  190. package/src/commands/build.ts +288 -0
  191. package/src/commands/connect.ts +60 -0
  192. package/src/commands/describe.ts +246 -0
  193. package/src/commands/meta.ts +171 -0
  194. package/src/commands/navigate.ts +134 -0
  195. package/src/commands/query-helpers.ts +1202 -0
  196. package/src/commands/query.ts +1085 -0
  197. package/src/commands/review.ts +670 -0
  198. package/src/commands/session-mgmt.ts +256 -0
  199. package/src/commands/type.ts +437 -0
  200. package/src/commands/validate-input.ts +38 -0
  201. package/src/intent/__tests__/build-aggregate.spec.ts +931 -0
  202. package/src/intent/__tests__/build-create-validation.spec.ts +135 -0
  203. package/src/intent/__tests__/build-delete.spec.ts +121 -0
  204. package/src/intent/__tests__/build-detail.spec.ts +333 -0
  205. package/src/intent/__tests__/build-discover.spec.ts +432 -0
  206. package/src/intent/__tests__/build-list.spec.ts +284 -0
  207. package/src/intent/__tests__/build-mutation.spec.ts +108 -0
  208. package/src/intent/__tests__/build-output.spec.ts +55 -0
  209. package/src/intent/__tests__/build-raw.spec.ts +153 -0
  210. package/src/intent/__tests__/build-update-validation.spec.ts +134 -0
  211. package/src/intent/build-aggregate.ts +182 -0
  212. package/src/intent/build-create.ts +19 -0
  213. package/src/intent/build-delete.ts +62 -0
  214. package/src/intent/build-detail.ts +95 -0
  215. package/src/intent/build-discover.ts +199 -0
  216. package/src/intent/build-list.ts +91 -0
  217. package/src/intent/build-mutation.ts +75 -0
  218. package/src/intent/build-output.ts +72 -0
  219. package/src/intent/build-raw.ts +61 -0
  220. package/src/intent/build-update.ts +19 -0
  221. package/src/intent/get-schema-with-priming.ts +43 -0
  222. package/src/intent/select-child-relationship.ts +48 -0
  223. package/src/intent/types.ts +181 -0
  224. package/src/lib/__tests__/apply-command.parity.spec.ts +97 -0
  225. package/src/lib/__tests__/apply-command.spec.ts +171 -0
  226. package/src/lib/__tests__/auth.spec.ts +292 -0
  227. package/src/lib/__tests__/formatter.spec.ts +86 -0
  228. package/src/lib/__tests__/graphql-name.spec.ts +64 -0
  229. package/src/lib/__tests__/introspect.spec.ts +399 -0
  230. package/src/lib/__tests__/object-info.spec.ts +124 -0
  231. package/src/lib/__tests__/path-selection.spec.ts +219 -0
  232. package/src/lib/__tests__/prime-schema.spec.ts +269 -0
  233. package/src/lib/__tests__/query-builder.spec.ts +95 -0
  234. package/src/lib/__tests__/query-commands.spec.ts +74 -0
  235. package/src/lib/__tests__/session.spec.ts +292 -0
  236. package/src/lib/__tests__/tokenize.spec.ts +33 -0
  237. package/src/lib/__tests__/uiapi.spec.ts +192 -0
  238. package/src/lib/__tests__/variable-promotion.spec.ts +211 -0
  239. package/src/lib/__tests__/walker.spec.ts +250 -0
  240. package/src/lib/apply-command.ts +286 -0
  241. package/src/lib/auth.ts +157 -0
  242. package/src/lib/codegen.ts +899 -0
  243. package/src/lib/command-registry.ts +434 -0
  244. package/src/lib/formatter.ts +587 -0
  245. package/src/lib/fs-utils.ts +46 -0
  246. package/src/lib/graphql-name.ts +35 -0
  247. package/src/lib/interactive.ts +634 -0
  248. package/src/lib/introspect.ts +320 -0
  249. package/src/lib/object-info.ts +409 -0
  250. package/src/lib/path-selection.ts +162 -0
  251. package/src/lib/prime-schema.ts +195 -0
  252. package/src/lib/query-builder.ts +193 -0
  253. package/src/lib/query-commands.ts +290 -0
  254. package/src/lib/session.ts +1304 -0
  255. package/src/lib/tokenize.ts +43 -0
  256. package/src/lib/uiapi.ts +176 -0
  257. package/src/lib/validator.ts +143 -0
  258. package/src/lib/variable-promotion.ts +145 -0
  259. package/src/lib/walker.ts +975 -0
  260. package/src/mcp/__tests__/server.spec.ts +155 -0
  261. package/src/mcp/server.ts +38 -0
  262. package/src/mcp/stdio.ts +29 -0
  263. package/src/mcp/tools/__tests__/sf-gql-aggregate.spec.ts +173 -0
  264. package/src/mcp/tools/__tests__/sf-gql-create.spec.ts +235 -0
  265. package/src/mcp/tools/__tests__/sf-gql-delete.spec.ts +194 -0
  266. package/src/mcp/tools/__tests__/sf-gql-detail.spec.ts +246 -0
  267. package/src/mcp/tools/__tests__/sf-gql-discover.spec.ts +320 -0
  268. package/src/mcp/tools/__tests__/sf-gql-list.spec.ts +128 -0
  269. package/src/mcp/tools/__tests__/sf-gql-raw.spec.ts +141 -0
  270. package/src/mcp/tools/__tests__/sf-gql-update.spec.ts +207 -0
  271. package/src/mcp/tools/echo.ts +24 -0
  272. package/src/mcp/tools/sf-gql-aggregate.ts +102 -0
  273. package/src/mcp/tools/sf-gql-create.ts +55 -0
  274. package/src/mcp/tools/sf-gql-delete.ts +49 -0
  275. package/src/mcp/tools/sf-gql-detail.ts +85 -0
  276. package/src/mcp/tools/sf-gql-discover.ts +67 -0
  277. package/src/mcp/tools/sf-gql-list.ts +73 -0
  278. package/src/mcp/tools/sf-gql-raw.ts +56 -0
  279. package/src/mcp/tools/sf-gql-update.ts +55 -0
  280. package/src/mcp/tools/shared/zod-schemas.ts +55 -0
  281. package/tsconfig.json +18 -0
  282. package/vitest.config.ts +14 -0
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # graphiti
2
+
3
+ Progressive GraphQL query builder CLI for Salesforce orgs. Treats a query as a **projection of the schema** — navigate the schema like a filesystem, select leaf fields, set arguments, and compose queries without ever writing raw GraphQL.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install
9
+ npm run build
10
+ ```
11
+
12
+ Run via `node dist/cli.js` (built) or `npx tsx src/cli.ts` (dev).
13
+
14
+ ## Prerequisites
15
+
16
+ - [Salesforce CLI](https://developer.salesforce.com/tools/salesforcecli) installed and authenticated (`sf org login web --alias myorg`)
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # 1. Connect to an org (downloads GraphQL schema once)
22
+ graphiti connect myorg
23
+
24
+ # 2. Start a new query session
25
+ graphiti query new myorg
26
+ # → prints Session: s_xxxx and root fields
27
+
28
+ # 3. Navigate the schema like a directory
29
+ graphiti query s_xxxx ls # list available fields
30
+ graphiti query s_xxxx ls -l # long listing (type, args, selections)
31
+ graphiti query s_xxxx ls --search Account # filter by name
32
+ graphiti query s_xxxx cd accounts # enter a field directory
33
+ graphiti query s_xxxx cd accounts/edges/node # multi-level nav
34
+ graphiti query s_xxxx pwd # print current path
35
+ graphiti query s_xxxx cd .. # go up one level
36
+ graphiti query s_xxxx cd / # go back to root
37
+
38
+ # 4. Select leaf fields (parent path added automatically)
39
+ graphiti query s_xxxx select Id
40
+ graphiti query s_xxxx select Name --as accountName
41
+
42
+ # 5. Remove a selection
43
+ graphiti query s_xxxx rm Id
44
+
45
+ # 6. Navigate union/interface fragment directories
46
+ graphiti query s_xxxx cd search # field of union type
47
+ graphiti query s_xxxx cd [Account] # inline fragment directory
48
+ graphiti query s_xxxx select name
49
+
50
+ # 7. Set field arguments
51
+ graphiti query s_xxxx cd accounts
52
+ graphiti query s_xxxx args set first 10
53
+ graphiti query s_xxxx args set where '{"Status":{"eq":"Open"}}'
54
+ graphiti query s_xxxx args ls
55
+ graphiti query s_xxxx args rm first
56
+
57
+ # 8. Bind arguments to query variables
58
+ graphiti query s_xxxx vars set \$whereInput AccountWhere
59
+ graphiti query s_xxxx bind set where \$whereInput
60
+
61
+ # 9. Set directory-scoped default argument values
62
+ graphiti query s_xxxx defaults set first 20
63
+
64
+ # 10. Preview and execute
65
+ graphiti query s_xxxx show
66
+ graphiti query s_xxxx validate
67
+ graphiti query s_xxxx execute
68
+ ```
69
+
70
+ ## Interactive Mode
71
+
72
+ Start an interactive REPL session for faster iteration — same commands, no need to repeat the session ID each time. Bare commands like `select`, `cd`, and `args set` show guided pick-lists.
73
+
74
+ ```bash
75
+ graphiti query s_xxxx interactive
76
+ ```
77
+
78
+ REPL prompt: `graphiti [s_xxxx] /accounts > `
79
+
80
+ Inside the REPL:
81
+
82
+ - Type any subcommand (`ls`, `cd edges`, `select Id`, etc.) without the `graphiti query s_xxxx` prefix.
83
+ - `select` with no argument → guided pick-list of available leaf fields.
84
+ - `cd` with no argument → guided pick-list of navigable directories.
85
+ - `args set` with no argument → guided pick-list of available field arguments.
86
+ - `vars set` with just `set` → guided prompts for name, type, and default value.
87
+ - `exit` or `Ctrl-C` to quit.
88
+
89
+ ## Commands Reference
90
+
91
+ ### Setup
92
+
93
+ | Command | Description |
94
+ | ------------------------------------------- | ----------------------------------------------------------- |
95
+ | `graphiti connect <org>` | Connect to a Salesforce org and download its GraphQL schema |
96
+ | `graphiti type <org> <TypeName>` | Inspect a named GraphQL type |
97
+ | `graphiti validate <org> <TypeName> <json>` | Validate a JSON value against an input type |
98
+
99
+ ### Session lifecycle
100
+
101
+ | Command | Description |
102
+ | ----------------------------------------------------- | -------------------------------------------------- |
103
+ | `graphiti query new <org> [--mutation] [--aggregate]` | Create a new query, mutation, or aggregate session |
104
+ | `graphiti query help [topic]` | Show command help, optionally scoped to a topic |
105
+
106
+ ### Navigation
107
+
108
+ | Command | Description |
109
+ | --------------------------------------------- | ----------------------------------------------------------- |
110
+ | `graphiti query <sid> pwd` | Print current schema navigation path |
111
+ | `graphiti query <sid> ls [-l] [--search pat]` | List schema entries at current path |
112
+ | `graphiti query <sid> cd <path>` | Navigate to a schema path (supports `..`, `/`, multi-level) |
113
+
114
+ ### Projection
115
+
116
+ | Command | Description |
117
+ | ------------------------------------------------- | ---------------------------------------- |
118
+ | `graphiti query <sid> select <leaf> [--as alias]` | Select a leaf field (parents auto-added) |
119
+ | `graphiti query <sid> rm <field-or-alias>` | Remove a leaf selection |
120
+
121
+ ### Multiple instances & aliases
122
+
123
+ | Command | Description |
124
+ | ---------------------------------------------- | ---------------------------------------------- |
125
+ | `graphiti query <sid> alias ls` | List all projection instances at current path |
126
+ | `graphiti query <sid> alias set <name>` | Set alias on the focused instance |
127
+ | `graphiti query <sid> alias new <name>` | Create a new projection instance with an alias |
128
+ | `graphiti query <sid> alias use <alias-or-id>` | Switch focus to a different instance |
129
+ | `graphiti query <sid> alias clear` | Remove alias from the focused instance |
130
+
131
+ Use `alias new` to select the same field multiple times with different arguments (e.g., two aliased versions of `accounts` with different `where` clauses).
132
+
133
+ ### Arguments
134
+
135
+ | Command | Description |
136
+ | ---------------------------------------------- | -------------------------------------------- |
137
+ | `graphiti query <sid> args ls` | List args on the focused projection instance |
138
+ | `graphiti query <sid> args set <name> <value>` | Set an argument value |
139
+ | `graphiti query <sid> args rm <name>` | Remove an argument |
140
+
141
+ ### Variable bindings
142
+
143
+ | Command | Description |
144
+ | -------------------------------------------- | ---------------------------------------------- |
145
+ | `graphiti query <sid> bind ls` | List variable bindings on the focused instance |
146
+ | `graphiti query <sid> bind set <arg> <$var>` | Bind an argument to a query variable |
147
+ | `graphiti query <sid> bind rm <arg>` | Remove a binding |
148
+
149
+ ### Directory-scoped defaults
150
+
151
+ Default argument values applied to all projection instances under the current path unless an instance overrides them.
152
+
153
+ | Command | Description |
154
+ | -------------------------------------------------- | ----------------------------- |
155
+ | `graphiti query <sid> defaults ls` | List defaults at current path |
156
+ | `graphiti query <sid> defaults set <name> <value>` | Set a default |
157
+ | `graphiti query <sid> defaults rm <name>` | Remove a default |
158
+
159
+ ### Variables
160
+
161
+ | Command | Description |
162
+ | -------------------------------------------------------- | ------------------------ |
163
+ | `graphiti query <sid> vars ls` | List all query variables |
164
+ | `graphiti query <sid> vars set <$name> <type> [default]` | Define a variable |
165
+ | `graphiti query <sid> vars value <$name> <value>` | Set the runtime value |
166
+ | `graphiti query <sid> vars rm <$name>` | Remove a variable |
167
+
168
+ ### Query output
169
+
170
+ | Command | Description |
171
+ | ------------------------------- | -------------------------------------------- |
172
+ | `graphiti query <sid> show` | Print the current GraphQL query string |
173
+ | `graphiti query <sid> validate` | Validate the query against the schema |
174
+ | `graphiti query <sid> execute` | Execute the query against the Salesforce org |
175
+
176
+ ### Interactive
177
+
178
+ | Command | Description |
179
+ | ---------------------------------- | --------------------------------- |
180
+ | `graphiti query <sid> interactive` | Start an interactive REPL session |
181
+
182
+ ## Performance
183
+
184
+ Schema and auth data are cached aggressively to minimize cold-start overhead:
185
+
186
+ - **Auth memoization** — `sf org display` is called at most once per process; the result is cached for the lifetime of the command or interactive session.
187
+ - **Session-stored instanceUrl** — The Salesforce instance URL is resolved once at `query new` time and persisted in the session file. Subsequent commands use this URL to locate the cached schema file directly, completely bypassing `sf org display`.
188
+ - **SDL schema cache** — After a schema is first built from the introspection JSON, it is serialized to a compact SDL file (`~/.graphiti/schemas/<cacheKey>.graphql`) next to the introspection JSON. Subsequent cold starts load the SDL file instead, which is faster than re-processing the raw introspection format.
189
+ - **In-process schema cache** — Within a single interactive session, the parsed `GraphQLSchema` is kept in memory so every command after the first is near-instant.
190
+
191
+ ## Schema storage
192
+
193
+ Schemas are stored in `~/.graphiti/schemas/` keyed by a hash of the normalized Salesforce instance URL. This means:
194
+
195
+ - Reusing an org alias for a different org will always pick up the correct schema.
196
+ - `graphiti connect <org>` re-downloads and refreshes the cache for that org.
197
+ - The companion SDL file (`<cacheKey>.graphql`) is regenerated automatically whenever the introspection JSON is updated.
198
+
199
+ ## Development
200
+
201
+ ```bash
202
+ npm run build # compile TypeScript
203
+ npm test # build + run tests
204
+ ```
package/TASK.md ADDED
@@ -0,0 +1,249 @@
1
+ # Graphiti CLI Evaluation Task
2
+
3
+ You are evaluating the **graphiti** CLI — a progressive GraphQL query builder for Salesforce orgs. Your job is to use it end-to-end to build every query two real-world apps would need, then reflect on the experience and ship improvements.
4
+
5
+ Start by reading `AGENT_GUIDE.md` in this repo to learn the full command surface.
6
+
7
+ Use `vscodeOrg` as the org alias for all commands. Run graphiti via `npx graphiti` from the repo root.
8
+
9
+ ---
10
+
11
+ ## Phase 1: Build Queries for an Order Management App
12
+
13
+ **App prompt:**
14
+
15
+ > I need an order management app for sales and fulfillment staff. The home screen should show a breakdown of orders by status. There should be a product catalog page where staff can browse and search products. The orders page should let users filter by status and date. Clicking an order should open a detail view showing the order header and all line items with product name, quantity, and price. Staff should be able to update the order status, add line items, and remove line items. There should also be a way to create a new order by selecting an account and adding products.
16
+
17
+ ### Instructions
18
+
19
+ 1. Use `npx graphiti describe` to explore the relevant SObjects (Order, OrderItem, Product2, PricebookEntry, Account, etc.) and understand available fields, picklist values, and relationships.
20
+ 2. For each screen / feature below, create a named session and build the complete query using graphiti CLI commands (`new`, `select`, `set`, `var`, `check`, `show`).
21
+ 3. Run `check` on every query to validate it.
22
+ 4. Run `show` on every query to capture the final GraphQL.
23
+ 5. Run `codegen` on each query to generate TypeScript types.
24
+
25
+ **Queries to build:**
26
+
27
+ | # | Session Name | Purpose |
28
+ | --- | --------------------- | ----------------------------------------------------------------------- |
29
+ | 1 | `order-home-status` | Home screen — count/list orders grouped by status |
30
+ | 2 | `product-catalog` | Product catalog — browse/search products with pagination |
31
+ | 3 | `order-list` | Order list — filterable by status and date, sortable |
32
+ | 4 | `order-detail` | Order detail — header fields + line items with product name, qty, price |
33
+ | 5 | `order-update-status` | Mutation — update order status |
34
+ | 6 | `order-add-line` | Mutation — add a line item to an order |
35
+ | 7 | `order-remove-line` | Mutation — remove a line item |
36
+ | 8 | `order-create` | Mutation — create a new order for an account |
37
+ | 9 | `account-lookup` | Account lookup/search for order creation |
38
+
39
+ ---
40
+
41
+ ## Phase 2: Build Queries for a Support Queue App
42
+
43
+ **App prompt:**
44
+
45
+ > I need a support queue React app for our support team. The home view should have tiles showing case counts by status — New, In Progress, Waiting on Customer, Resolved — plus a list of unassigned cases and a list of cases assigned to me. There should be a case list page with filters for status, priority, and owner, sortable by date and priority. Opening a case should show the full case details including the related account and contact. From the detail view, agents should be able to update the case status and priority, assign it to themselves, and add a note. There should also be a form to create a new case with account and contact lookups. Show the current user's name in the header.
46
+
47
+ ### Instructions
48
+
49
+ Same workflow as Phase 1. Use `describe` to explore, then build each query.
50
+
51
+ **Queries to build:**
52
+
53
+ | # | Session Name | Purpose |
54
+ | --- | ---------------------- | -------------------------------------------------------------------------- |
55
+ | 1 | `case-home-new` | Home tile — cases with Status = New |
56
+ | 2 | `case-home-inprogress` | Home tile — cases with Status = In Progress |
57
+ | 3 | `case-home-waiting` | Home tile — cases with Status = Waiting on Customer |
58
+ | 4 | `case-home-resolved` | Home tile — cases with Status = Resolved |
59
+ | 5 | `case-home-unassigned` | Home — unassigned cases list |
60
+ | 6 | `case-home-mine` | Home — cases assigned to current user |
61
+ | 7 | `case-list` | Case list — filterable by status/priority/owner, sortable by date/priority |
62
+ | 8 | `case-detail` | Case detail — full case with related account and contact |
63
+ | 9 | `case-update` | Mutation — update case status and priority |
64
+ | 10 | `case-assign` | Mutation — assign case to current user |
65
+ | 11 | `case-add-note` | Mutation — add a CaseComment / note |
66
+ | 12 | `case-create` | Mutation — create a new case with account and contact |
67
+ | 13 | `account-search` | Account lookup for case creation |
68
+ | 14 | `contact-search` | Contact lookup for case creation |
69
+ | 15 | `current-user` | Header — current user's name |
70
+
71
+ ---
72
+
73
+ ## Phase 3: Validate TypeScript Type Accuracy
74
+
75
+ The generated TypeScript types are consumed by agents and developers to build app code against query results. Type accuracy is critical — wrong types cause runtime errors, missing optionality causes null-pointer crashes, and weak types (`Record<string, unknown>`) force consumers to cast blindly.
76
+
77
+ Run `codegen` on every query built in Phases 1 and 2 and audit the output for the following:
78
+
79
+ ### 3a. Result type accuracy
80
+
81
+ For each query, check that the generated `*Result` interface accurately reflects the GraphQL response shape:
82
+
83
+ 1. **Field names match the query.** Aliased fields should use the alias name, not the underlying field name. If you selected `Subject.value:subject`, the type should have `subject: string`, not `value: string`.
84
+ 2. **Nullability is correct.** Parent relationship fields (Account, Contact, Owner, CreatedBy) should be `| null`. Connection types (edges, pageInfo) should NOT be nullable. Scalar value wrappers (`{ value: string }`) should be `| null` when the field is optional in the schema.
85
+ 3. **Picklist values are union types, not plain `string`.** `Status.value` should be `CaseStatus` (a union of the actual picklist values), not `string`. Verify picklist unions contain the correct values from the org.
86
+ 4. **Union/polymorphic types are represented.** `Owner` (a union of `User | Group`) should have the inline fragment structure, not a flat object. Both branches should be present.
87
+ 5. **Connection pagination types are present.** `pageInfo { hasNextPage, endCursor }` and `totalCount` should be typed when selected.
88
+ 6. **Nested child relationships are typed.** `CaseComments` inside a Case should have its own connection structure with edges/node, not be flattened.
89
+
90
+ ### 3b. Variable type accuracy
91
+
92
+ For each query with variables, check that the generated `*Variables` interface is strongly typed:
93
+
94
+ 1. **Filter variables use the real filter type.** `$where` should be typed as `Case_Filter` (with all Case field names and operator types), NOT `Record<string, unknown>`.
95
+ 2. **OrderBy variables use the real orderBy type.** `$orderBy` should be `Case_OrderBy` with field-level `OrderByClause` entries and `ResultOrder` (`"ASC" | "DESC"`) enums.
96
+ 3. **Mutation input variables are fully expanded.** `$input: CaseCreateInput` should expand to show `{ Case: CaseCreateRepresentation }` with all settable fields (`Subject?: string`, `Status?: string`, `AccountId?: string`, etc.), NOT `Record<string, unknown>`.
97
+ 4. **Operator types are expanded.** Filter fields should have concrete operator interfaces (`PicklistOperators { eq?: string; ne?: string; in?: string[]; ... }`), not `Record<string, unknown>`.
98
+ 5. **Scalar variables use correct primitives.** `$first` should be `number`, `$after` should be `string`, `$caseId` should be `string`.
99
+ 6. **Required vs optional is correct.** Variables with `!` in their GraphQL type (e.g. `$input: CaseCreateInput!`) should be required in the interface (no `?`). Variables without `!` should be optional (`?`) and include `| null`.
100
+
101
+ ### 3c. Picklist type accuracy (inputs and results)
102
+
103
+ Picklists are a critical pain point. An agent building a case creation form, a status filter, or a priority dropdown needs to know the exact valid values — not just `string`. Audit every picklist field across both result types and input/variable types:
104
+
105
+ #### Result-side picklists
106
+
107
+ 1. **Every picklist field in a result type should use a union type alias.** `Status.value` should be `CaseStatus` (not `string`), `Priority.value` should be `CasePriority`, `Origin.value` should be `CaseOrigin`, etc.
108
+ 2. **The union type should contain the actual org values.** Run `describe <SObject>` and cross-reference the picklist values listed there against the generated union. They must match exactly. If the org has `Status` values `["New", "On Hold", "Escalated", "Closed"]`, the type must be `"New" | "On Hold" | "Escalated" | "Closed"` — not a subset, not a superset.
109
+ 3. **Picklist fields on related objects should also be enriched.** If case-detail selects `Account.Industry.value`, that should be `AccountIndustry`, not `string`.
110
+
111
+ #### Input-side picklists
112
+
113
+ 4. **Mutation input picklist fields should use the same union type or be constrained.** In `CaseCreateRepresentation`, `Status?: string` is too weak — an agent could pass `"Invalid"` and only discover the error at runtime. Verify whether codegen constrains these to the picklist union (e.g. `Status?: CaseStatus`). If it doesn't, document this as a type accuracy issue.
114
+ 5. **Filter operator types for picklist fields should indicate valid values.** In `Case_Filter`, `Status?: PicklistOperators` where `PicklistOperators { eq?: string }` means an agent filtering by status has no autocomplete for valid values. Check whether the filter operator type carries the picklist constraint. If `eq` is just `string`, document this.
115
+ 6. **OrderBy fields for picklists should be fine** (they only need `ASC`/`DESC`), but verify they aren't incorrectly typed.
116
+
117
+ #### What to test
118
+
119
+ Pick at least 3 queries that touch picklist fields and verify both sides:
120
+
121
+ - `case-list` or `case-home-*` — `Status` and `Priority` in both the result type AND the `$where` filter variable type
122
+ - `case-create` — `Status`, `Priority`, `Origin`, `Reason`, `Type` in the `CaseCreateRepresentation` input
123
+ - `case-detail` — `Status` and `Priority` in the result, plus any picklist on related Account or Contact
124
+ - `order-list` or `order-detail` — `Status` on Order (if it's a picklist)
125
+
126
+ For each picklist field, note:
127
+
128
+ - The field name and which SObject it belongs to
129
+ - Whether the result type uses a union alias (good) or plain `string` (bad)
130
+ - Whether the input/filter type uses a union alias, plain `string`, or `Record<string, unknown>`
131
+ - The actual valid values from `describe`
132
+
133
+ ### 3d. @optional directive handling
134
+
135
+ For any fields selected with `@optional` (FLS safety), verify:
136
+
137
+ 1. **The field is marked optional in the TypeScript type** (`fieldName?: Type | undefined`).
138
+ 2. **Fields without `@optional` are NOT marked optional** (no spurious `?`).
139
+ 3. If no fields use `@optional`, add it to at least 2 fields on one query (e.g. `optional Description Subject` on case-detail) and verify the codegen output changes correctly.
140
+
141
+ ### 3e. Agent usability audit
142
+
143
+ Pretend you are an agent writing React components that consume these types. For each query, verify:
144
+
145
+ 1. **Can you write a data access expression without `as` casts?** E.g. `data.uiapi.query.Case.edges[0].node.Status.value` should typecheck without casting. If you need `as unknown as X` anywhere, the type is wrong.
146
+ 2. **Do mutation input types give autocomplete?** When constructing a `CreateCaseVariables` value, do you get field name suggestions for the input object, or is it `Record<string, unknown>` where anything goes?
147
+ 3. **Are there any `unknown` types that should be concrete?** Scan for `unknown` in the output — each one is a place where an agent would have to guess or hardcode.
148
+
149
+ ### What to do with findings
150
+
151
+ - Document every type accuracy issue in your reflection (Phase 4) under a new **"Type Accuracy Issues"** section.
152
+ - For each issue, note: the session name, the field/variable, what the type IS vs. what it SHOULD be.
153
+ - In Phase 5 (Improve), prioritize type accuracy fixes alongside other improvements. Type accuracy issues that affect agent usability should be treated as high priority.
154
+
155
+ ---
156
+
157
+ ## Phase 4: Reflect
158
+
159
+ After completing Phases 1–3, write a structured reflection. Create or update a file called `REFLECTION.md` in the repo root with the following sections:
160
+
161
+ ### What Went Well
162
+
163
+ - Which commands were intuitive and efficient?
164
+ - Where did the CLI save time vs. writing raw GraphQL?
165
+ - What patterns emerged that felt natural?
166
+
167
+ ### What Was Painful
168
+
169
+ - Which tasks required too many commands or felt clunky?
170
+ - Where did you get stuck, hit confusing errors, or have to guess?
171
+ - What information was missing or hard to discover?
172
+ - Were there queries you couldn't build, or that required awkward workarounds?
173
+
174
+ ### Type Accuracy Issues
175
+
176
+ For each codegen issue found in Phase 3, document:
177
+
178
+ - **Session:** which query/mutation
179
+ - **Field/Variable:** the specific field or variable name
180
+ - **Current type:** what codegen produces now
181
+ - **Expected type:** what it should produce for correct agent consumption
182
+ - **Impact:** how this would affect an agent writing code against the type (e.g. "agent would need an `as` cast", "agent gets no autocomplete for mutation fields", "agent could pass invalid status value")
183
+
184
+ ### Missing Capabilities
185
+
186
+ - What commands or features would have made the process significantly easier?
187
+ - Are there common query patterns that should be first-class operations?
188
+
189
+ ### Friction Log
190
+
191
+ For each moment of friction, note:
192
+
193
+ - The exact command(s) you ran
194
+ - What you expected to happen
195
+ - What actually happened
196
+ - How you worked around it (if you did)
197
+
198
+ ---
199
+
200
+ ## Phase 5: Improve the CLI
201
+
202
+ Based on your reflection, do the following:
203
+
204
+ 1. **Prioritize**: Pick the top 3–5 improvements that would have the highest impact on making GraphQL query authoring seamless for both humans and AI agents. **Type accuracy issues that affect agent usability should be weighted heavily** — an agent that can trust the types will write correct code on the first try.
205
+ 2. **Plan**: For each improvement, write a brief design (what changes, where in the codebase, any new commands or flags).
206
+ 3. **Implement**: Make the code changes. Run `npm run build` and `npm test` after each change to verify nothing breaks.
207
+ 4. **Verify**: Re-run `codegen` on the affected queries and confirm the types are now correct. For type accuracy fixes, write out the before/after comparison in the reflection.
208
+
209
+ ### Simplicity discipline
210
+
211
+ Before adding ANY new flag, command, or shorthand, ask yourself:
212
+
213
+ 1. **Can this be solved by better error messages or help text instead?** A self-documenting CLI that tells you what to do next when something goes wrong is more valuable than a shorthand that saves one command. If the existing commands can do the job in 2-3 steps and the error messages guide you there, that's good enough — don't add a flag.
214
+
215
+ 2. **Can this be solved by improving existing command behavior?** Auto-correction (like auto-injecting `Record/` for mutations or `@args/` for set) is better than adding a new flag. Making the existing command smarter is always preferable to adding surface area.
216
+
217
+ 3. **Does this new flag compose well, or does it create combinatorial complexity?** A command like `clone --set --unset --var --select --force` has 5 flags that interact with each other. Each new flag multiplies the testing/documentation burden. If a flag only makes sense in combination with other flags, it's probably not pulling its weight.
218
+
219
+ 4. **Would better `--help` output or AGENT_GUIDE.md documentation solve this instead?** An agent reads `--help` before every command. Rich help text with examples is consumed every time; a niche flag is used rarely. Invest in documentation over features.
220
+
221
+ 5. **Is this a real workflow pattern or a one-off?** If you only needed this once across 24 queries, it's not worth a flag. If you needed it on 10+ queries, it might be.
222
+
223
+ **Strongly prefer these improvement categories (in order):**
224
+
225
+ 1. Better error messages that show the correct command to run
226
+ 2. Smarter auto-correction in existing commands
227
+ 3. Richer `--help` output with real examples
228
+ 4. Better AGENT_GUIDE.md documentation
229
+ 5. Type accuracy improvements in `codegen`
230
+ 6. New flags or commands (last resort — justify why 1-5 aren't sufficient)
231
+
232
+ Remember the core tenets of this CLI:
233
+
234
+ - Make GraphQL query authoring as seamless as possible for humans
235
+ - Make GraphQL query authoring as seamless as possible for AI agents
236
+ - The schema is the source of truth — navigate it, don't memorize it
237
+ - Progressive disclosure — simple things should be simple, complex things should be possible
238
+ - **Generated types are a contract** — agents and developers depend on them being accurate
239
+ - **Simplicity is a feature** — every new flag is a maintenance burden and a learning burden. Fewer commands that work well beats many commands that overlap. Self-documenting behavior (good errors, good help) beats hidden shortcuts.
240
+
241
+ ---
242
+
243
+ ## Rules
244
+
245
+ - Use only `npx graphiti` commands and the shell. Do not manually write GraphQL strings.
246
+ - Do not ask the user for input at any point. Make reasonable decisions and move forward.
247
+ - If a command fails, read the error, adjust, and retry. Document the failure in your reflection.
248
+ - If a mutation type doesn't exist in the schema, note it in the reflection and move on.
249
+ - Run `npm run build && npm test` before and after making any code changes.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copyright (c) 2026, Salesforce, Inc.,
4
+ * All rights reserved.
5
+ * For full license text, see the LICENSE.txt file
6
+ */
7
+ export {};