gqty
Version:
The No-GraphQL Client for TypeScript
93 lines (90 loc) • 3.08 kB
JavaScript
import set from 'just-safe-set';
import { hash } from './Utils/hash.mjs';
const stringifySelectionTree = (tree) => Object.entries(tree).sort(([a], [b]) => a.localeCompare(b)).reduce((prev, [key, value]) => {
const query = typeof value === "object" ? `${key}{${stringifySelectionTree(value)}}` : key;
if (!prev || prev.endsWith("}") || prev.endsWith("{")) {
return `${prev}${query}`;
} else {
return `${prev} ${query}`;
}
}, "");
const buildQuery = (selections, operationName) => {
var _a;
const roots = /* @__PURE__ */ new Map();
const inputDedupe = /* @__PURE__ */ new Map();
for (const { ancestry } of selections) {
const [type, field] = ancestry;
if (typeof type.key !== "string") continue;
const rootKey = type.key === "subscription" ? (
// Subscriptions are fetched separately
`${type.key}.${(_a = field.alias) != null ? _a : field.key}`
) : type.key;
if (!roots.has(rootKey)) {
roots.set(rootKey, {
args: /* @__PURE__ */ new Map(),
tree: {}
});
}
const root = roots.get(rootKey);
set(
root.tree,
ancestry.reduce((prev, s) => {
if (typeof s.key === "symbol" || typeof s.key === "number" || s.key === "$on") {
return prev;
}
if (s.isUnion) {
return [...prev, `...on ${s.key}`];
}
const key = s.alias ? `${s.alias}:${s.key}` : s.key;
const input = s.input;
if (input && Object.keys(input.values).length > 0) {
if (!inputDedupe.has(input)) {
const queryInputs = Object.entries(input.values).map(([key2, value]) => {
var _a2;
const variableName = hash(((_a2 = s.alias) != null ? _a2 : s.key) + "_" + key2).slice(
0,
s.aliasLength
);
root.args.set(`${variableName}`, {
value,
type: input.types[key2]
});
return `${key2}:$${variableName}`;
}).filter(Boolean).join(" ");
inputDedupe.set(input, `${key}(${queryInputs})`);
}
return [...prev, inputDedupe.get(input)];
}
return [...prev, key];
}, []),
true
);
}
return [...roots].map(([key, { args, tree }]) => {
const rootKey = key.split(".")[0];
let query = stringifySelectionTree(tree);
if (args.size > 0) {
query = query.replace(
rootKey,
`${rootKey}(${[...args.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([name, { type }]) => `$${name}:${type}`).join("")})`
);
}
if (operationName) {
query = query.replace(rootKey, `${rootKey} ${operationName}`);
}
return {
query,
variables: args.size > 0 ? [...args].reduce(
(prev, [key2, { value }]) => (prev[key2] = value, prev),
{}
) : void 0,
operationName,
extensions: {
type: rootKey,
hash: hash({ query, variables: args })
// For query dedupe and cache keys
}
};
});
};
export { buildQuery };