MCPcopy Create free account
hub / github.com/codemix/graph / createPostprocessor

Function createPostprocessor

packages/graph/src/index.ts:177–261  ·  view source on GitHub ↗

* Creates a function which takes the array of values returned by the graph traversal * and returns an object with the values mapped to the variable names in the RETURN clause. * * When multiple properties from the same variable are returned (e.g., `RETURN c.name, c.description`), * they are grou

(
  ast: Query | UnionQuery | MultiStatement,
)

Source from the content-addressed store, hash-verified

175 * @param ast The AST of the query (Query, UnionQuery, or MultiStatement).
176 */
177function createPostprocessor(
178 ast: Query | UnionQuery | MultiStatement,
179): (row: readonly unknown[]) => Record<string, unknown> {
180 // For multi-statement queries, pass through results as-is
181 // (each statement has different schema, results include _statementIndex)
182 if (ast.type === "MultiStatement") {
183 return (row) => {
184 if (row && typeof row === "object" && !Array.isArray(row)) {
185 return row as unknown as Record<string, unknown>;
186 }
187 return { _value: row };
188 };
189 }
190
191 // For union queries, use the first query's RETURN clause for variable names
192 // (all queries in a UNION must return the same columns)
193 const query = ast.type === "UnionQuery" ? ast.queries[0]! : ast;
194
195 // For mutation-only queries without RETURN, return empty object
196 if (!query.return) {
197 return () => ({});
198 }
199
200 const items = query.return.items;
201
202 // Build a map of output key -> list of {index, property}
203 // This groups properties that should be merged under the same key
204 const keyMapping = new Map<string, Array<{ index: number; property: string | undefined }>>();
205
206 for (let i = 0; i < items.length; i++) {
207 const item = items[i]!;
208 // Use alias if present, otherwise use variable name, or generate a key for expressions
209 let key: string;
210 if (item.alias) {
211 key = item.alias;
212 } else if (item.variable) {
213 key = item.variable;
214 } else if (item.expression) {
215 // For expression-based items without alias, generate a key
216 key = `expr_${i}`;
217 } else {
218 key = `item_${i}`;
219 }
220 if (!keyMapping.has(key)) {
221 keyMapping.set(key, []);
222 }
223 keyMapping.get(key)!.push({ index: i, property: item.property });
224 }
225
226 return (row) => {
227 // Normalize row to array for aggregate-only queries that yield raw values
228 // (e.g., COUNT yields a number, not an array)
229 const normalizedRow = Array.isArray(row) ? row : [row];
230 const result: Record<string, unknown> = {};
231
232 for (const [key, mappings] of keyMapping) {
233 if (mappings.length === 1) {
234 // Single mapping for this key - return value directly

Callers 1

parseQueryToStepsFunction · 0.85

Calls 3

getMethod · 0.65
hasMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected