summaryrefslogtreecommitdiff
path: root/source/github-helpers/api.ts
diff options
context:
space:
mode:
authorGravatar Federico Brigante <me@fregante.com> 2023-05-24 02:07:43 +0800
committerGravatar GitHub <noreply@github.com> 2023-05-23 18:07:43 +0000
commitf589546ddd9a1a1147620c15499b56ce5aa8e7d0 (patch)
tree9216d0575b303878c8a0725a218dd9302fd2188c /source/github-helpers/api.ts
parent4a9a27982f487375070b623c16a76d92e2c6efad (diff)
downloadrefined-github-f589546ddd9a1a1147620c15499b56ce5aa8e7d0.tar.gz
refined-github-f589546ddd9a1a1147620c15499b56ce5aa8e7d0.tar.zst
refined-github-f589546ddd9a1a1147620c15499b56ce5aa8e7d0.zip
Meta: Use variables in GraphQL (#6674)
Diffstat (limited to 'source/github-helpers/api.ts')
-rw-r--r--source/github-helpers/api.ts39
1 files changed, 31 insertions, 8 deletions
diff --git a/source/github-helpers/api.ts b/source/github-helpers/api.ts
index 2f2dd2e0..e85e2c2f 100644
--- a/source/github-helpers/api.ts
+++ b/source/github-helpers/api.ts
@@ -72,7 +72,7 @@ export async function expectTokenScope(scope: string): Promise<void> {
const {headers} = await v3('/');
const tokenScopes = headers.get('X-OAuth-Scopes')!;
if (!tokenScopes.split(', ').includes(scope)) {
- throw new Error('The token you provided does not have ' + (tokenScopes ? `the \`${scope}\` scope. It only includes \`${tokenScopes}\`.` : 'any scope.'));
+ throw new Error('The token you provided does not have ' + (tokenScopes ? `the \`${scope}\` scope. It only includes \`${tokenScopes}\`.` : 'any scope. You can change the scope of your token at https://github.com/settings/tokens'));
}
}
@@ -94,6 +94,7 @@ type GHRestApiOptions = {
type GHGraphQLApiOptions = {
allowErrors?: boolean;
+ variables?: JsonObject;
};
const v3defaults: GHRestApiOptions = {
@@ -170,15 +171,34 @@ export const v4uncached = async (
): Promise<AnyObject> => {
const personalToken = await expectToken();
- if (/^(query )?{/.test(query.trimStart())) {
- throw new TypeError('`query` should only be what’s inside \'query {...}\', like \'user(login: "foo") { name }\', but is \n' + query);
+ // TODO: Remove automatic usage of globals via `getRepo()`
+ // https://github.com/refined-github/refined-github/issues/5821
+ const currentRepoIfAny = getRepo(); // Don't destructure, it's `undefined` outside repos
+ query = query.replace('repository() {', () => 'repository(owner: $owner, name: $name) {');
+
+ // Automatically provide variables common variables only when used.
+ // GraphQL doesn't like unused variables.
+ const variables: JsonObject = {};
+ const parameters: string[] = [];
+ if (query.includes('$owner')) {
+ variables.owner = currentRepoIfAny!.owner;
+ parameters.push('$owner: String!');
}
- query = query.replace('repository() {', () => `repository(owner: "${getRepo()!.owner}", name: "${getRepo()!.name}") {`);
+ if (query.includes('$name')) {
+ variables.name = currentRepoIfAny!.name;
+ parameters.push('$name: String!');
+ }
+
+ Object.assign(variables, options.variables);
+
+ const fullQuery = /^\s*(query|mutation)/.test(query)
+ ? query
+ : parameters.length === 0
+ ? `query {${query}}`
+ : `query (${parameters.join(',')}) {${query}}`;
- features.log.http(`{
- ${query}
- }`);
+ features.log.http(fullQuery);
const response = await fetch(api4, {
headers: {
@@ -187,7 +207,10 @@ export const v4uncached = async (
Authorization: `bearer ${personalToken}`,
},
method: 'POST',
- body: JSON.stringify({query: query.trimStart().startsWith('mutation') ? query : `{${query}}`}),
+ body: JSON.stringify({
+ variables,
+ query: fullQuery,
+ }),
});
const apiResponse: GraphQLResponse = await response.json();