Created
February 3, 2022 20:53
-
-
Save maxcan/609e575b0acd89df9228041d9e09fac8 to your computer and use it in GitHub Desktop.
Upload gql files to hasura allowed list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ./node_modules/.bin/ts-node-script | |
import { $, argv, fs } from "zx"; | |
import { parse, print, visit, DefinitionNode } from "graphql"; | |
import axios from "axios"; | |
const MAKE_ENV = process.env.MAKE_ENV; | |
if (!MAKE_ENV) { | |
const err = "Misisng MAKE_ENV"; | |
console.error(err); | |
throw err; | |
} | |
require("dotenv").config({ path: `.env.${process.env.MAKE_ENV}` }); | |
function test() { | |
$`echo ENV: ${process.env.SUBDOMAIN_APP_ADMIN}`; | |
} | |
async function addGqlToAllowed() { | |
let file = argv["file"]; | |
let name = argv["name"]; | |
if (!name) { | |
throw "Missing name arg"; | |
} | |
if (!file) { | |
throw "Missing file arg"; | |
} | |
$`echo using file ${argv["file"]}`; | |
const gqlData = fs.readFileSync(file).toString(); | |
const parsed = parseQueryString(gqlData); | |
// console.log(parsed); | |
try { | |
let _ = await axios({ | |
method: "POST", | |
url: `https://${process.env.FQDN_HASURA}/v1/metadata`, | |
headers: { | |
"x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, | |
}, | |
data: { | |
type: "drop_query_collection", | |
args: { | |
collection: name, | |
cascade: true, | |
}, | |
}, | |
}); | |
} catch (e) { | |
console.error(e); | |
throw e; | |
} | |
let _ = await axios({ | |
method: "POST", | |
url: `https://${process.env.FQDN_HASURA}/v1/metadata`, | |
headers: { | |
"x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, | |
}, | |
data: { | |
type: "create_query_collection", | |
args: { | |
name, | |
definition: { | |
queries: parsed, | |
}, | |
}, | |
}, | |
}); | |
_ = await axios({ | |
method: "POST", | |
url: `https://${process.env.FQDN_HASURA}/v1/metadata`, | |
headers: { | |
"x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, | |
}, | |
data: { | |
type: "add_collection_to_allowlist", | |
args: { | |
collection: name, | |
}, | |
}, | |
}); | |
} | |
console.log(argv); | |
const cmd = argv["_"][0]; | |
switch (cmd) { | |
case "add-gql-to-allowed": | |
addGqlToAllowed(); | |
break; | |
case "test": | |
test(); | |
break; | |
default: | |
const err = "unsupported command: " + cmd; | |
console.error(err); | |
throw err; | |
} | |
// ----- Utility functions | |
export type NewDefinitionNode = DefinitionNode & { | |
name?: { | |
value: string; | |
}; | |
}; | |
function parseQueryString(queryString: string) { | |
const queries: { name: string; query: string }[] = []; | |
let parsedQueryString; | |
try { | |
parsedQueryString = parse(queryString); | |
} catch (ex) { | |
throw new Error("Parsing operation failed"); | |
} | |
const definitions: NewDefinitionNode[] = [...parsedQueryString.definitions]; | |
const definitionHash = (definitions || []).reduce( | |
(defObj: Record<string, NewDefinitionNode>, queryObj) => { | |
if (queryObj.name) defObj[queryObj.name.value] = queryObj; | |
return defObj; | |
}, | |
{} | |
); | |
const queryDefs = definitions.filter( | |
(def) => def.kind === "OperationDefinition" | |
); | |
const fragmentDefs = definitions.filter( | |
(def) => def.kind === "FragmentDefinition" | |
); | |
queryDefs.forEach((queryDef) => { | |
const queryName = queryDef.name ? queryDef.name.value : `unnamed`; | |
const query = { | |
name: queryName, | |
query: getQueryString(queryDef, fragmentDefs, definitionHash), | |
}; | |
queries.push(query); | |
}); | |
return queries; | |
} | |
function recurQueryDef( | |
queryDef: NewDefinitionNode, | |
fragments: Set<string>, | |
definitionHash: Record<string, any> | |
) { | |
visit(queryDef, { | |
FragmentSpread(node) { | |
fragments.add(node.name.value); | |
recurQueryDef(definitionHash[node.name.value], fragments, definitionHash); | |
}, | |
}); | |
} | |
function getQueryFragments( | |
queryDef: NewDefinitionNode, | |
definitionHash: Record<string, any> = {} | |
) { | |
const fragments = new Set<string>(); | |
recurQueryDef(queryDef, fragments, definitionHash); | |
return [...Array.from(fragments)]; | |
} | |
function getQueryString( | |
queryDef: NewDefinitionNode, | |
fragmentDefs: NewDefinitionNode[], | |
definitionHash: Record<string, any> = {} | |
) { | |
let queryString = print(queryDef); | |
const queryFragments = getQueryFragments(queryDef, definitionHash); | |
queryFragments.forEach((qf) => { | |
// eslint-disable-next-line array-callback-return | |
const fragmentDef = fragmentDefs.find((fd) => { | |
if (fd.name) return fd.name.value === qf; | |
}); | |
if (fragmentDef) { | |
queryString += `\n\n${print(fragmentDef)}`; | |
} | |
}); | |
return queryString; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment