mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-10-13 22:41:57 +00:00
4.0.0-rc13.4
* Fixed: Game directory pages not loading. * Changed: Rewrite GraphQL query merging logic to hopefully perform in a more robust manner less likely to break in the future.
This commit is contained in:
parent
7fc27ff025
commit
551a08bfd0
12 changed files with 158 additions and 186 deletions
|
@ -6,10 +6,11 @@
|
|||
// ============================================================================
|
||||
|
||||
import Module from 'utilities/module';
|
||||
import {has, get} from 'utilities/object';
|
||||
import {get, deep_copy} from 'utilities/object';
|
||||
import merge from 'utilities/graphql';
|
||||
|
||||
|
||||
const BAD_ERRORS = [
|
||||
/*const BAD_ERRORS = [
|
||||
'timeout',
|
||||
'unable to load',
|
||||
'error internal',
|
||||
|
@ -31,7 +32,7 @@ function skip_error(err) {
|
|||
for(const m of BAD_ERRORS)
|
||||
if ( err.message.includes(m) )
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
export class GQLError extends Error {
|
||||
|
@ -212,6 +213,9 @@ export default class Apollo extends Module {
|
|||
query = query_map && query_map.get(id),
|
||||
modifiers = this.modifiers[operation];
|
||||
|
||||
|
||||
const pre_modification = deep_copy(request.query);
|
||||
|
||||
if ( modifiers ) {
|
||||
for(const mod of modifiers) {
|
||||
if ( typeof mod === 'function' )
|
||||
|
@ -245,6 +249,8 @@ export default class Apollo extends Module {
|
|||
this.log.info('Unable to find GQL Print. Clearing store for query:', operation);
|
||||
this.client.queryManager.queryStore.store[id] = null;
|
||||
}
|
||||
|
||||
this.log.info('Query', operation, pre_modification, request.query, request.variables);
|
||||
}
|
||||
|
||||
apolloPostFlight(response) {
|
||||
|
@ -406,71 +412,3 @@ export default class Apollo extends Module {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Query Merging
|
||||
// ============================================================================
|
||||
|
||||
function canMerge(a, b) {
|
||||
return a.kind === b.kind &&
|
||||
a.kind !== 'FragmentDefinition' &&
|
||||
(a.selectionSet == null) === (b.selectionSet == null);
|
||||
}
|
||||
|
||||
|
||||
function merge(a, b) {
|
||||
if ( ! canMerge(a, b) )
|
||||
return a;
|
||||
|
||||
if ( a.definitions ) {
|
||||
const a_def = a.definitions,
|
||||
b_def = b.definitions;
|
||||
|
||||
for(let i=0; i < a_def.length && i < b_def.length; i++)
|
||||
a_def[i] = merge(a_def[i], b_def[i]);
|
||||
}
|
||||
|
||||
if ( a.selectionSet ) {
|
||||
const s = a.selectionSet.selections,
|
||||
selects = {};
|
||||
for(const sel of b.selectionSet.selections) {
|
||||
const name = sel.kind === 'InlineFragment' ?
|
||||
(sel.typeCondition.name ?
|
||||
sel.typeCondition.name.value : null) :
|
||||
(sel.name ? sel.name.value : null),
|
||||
alias = sel.alias ? sel.alias.value : null,
|
||||
key = `${name}:${alias}`;
|
||||
|
||||
if ( name )
|
||||
selects[key] = sel;
|
||||
}
|
||||
|
||||
for(let i=0, l = s.length; i < l; i++) {
|
||||
const sel = s[i],
|
||||
name = sel.kind === 'InlineFragment' ?
|
||||
(sel.typeCondition.name ?
|
||||
sel.typeCondition.name.value : null) :
|
||||
(sel.name ? sel.name.value : null),
|
||||
alias = sel.alias ? sel.alias.value : null,
|
||||
key = `${name}:${alias}`,
|
||||
other = selects[key];
|
||||
|
||||
if ( other ) {
|
||||
s[i] = merge(sel, other);
|
||||
selects[key] = null;
|
||||
}
|
||||
}
|
||||
|
||||
for(const key in selects)
|
||||
if ( has(selects, key) ) {
|
||||
const val = selects[key];
|
||||
if ( val )
|
||||
s.push(val);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Variables?
|
||||
|
||||
return a;
|
||||
}
|
113
src/utilities/graphql.js
Normal file
113
src/utilities/graphql.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { deep_copy } from "./object";
|
||||
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
// GraphQL Document Manipulation
|
||||
// ============================================================================
|
||||
|
||||
export const MERGE_METHODS = {
|
||||
Document: (a, b) => {
|
||||
if ( a.definitions && b.definitions )
|
||||
a.definitions = mergeList(a.definitions, b.definitions);
|
||||
else if ( b.definitions )
|
||||
a.definitions = b.definitions;
|
||||
|
||||
return a;
|
||||
},
|
||||
|
||||
Field: (a, b) => {
|
||||
if ( a.name && (! b.name || b.name.value !== a.name.value) )
|
||||
return a;
|
||||
|
||||
// TODO: arguments
|
||||
// TODO: directives
|
||||
|
||||
if ( a.selectionSet && b.selectionSet )
|
||||
a.selectionSet = merge(a.selectionSet, b.selectionSet);
|
||||
else if ( b.selectionSet )
|
||||
a.selectionSet = b.selectionSet;
|
||||
|
||||
return a;
|
||||
},
|
||||
|
||||
OperationDefinition: (a, b) => {
|
||||
if ( a.operation !== b.operation )
|
||||
return a;
|
||||
|
||||
// TODO: variableDefinitions
|
||||
// TODO: directives
|
||||
|
||||
if ( a.selectionSet && b.selectionSet )
|
||||
a.selectionSet = merge(a.selectionSet, b.selectionSet);
|
||||
else if ( b.selectionSet )
|
||||
a.selectionSet = b.selectionSet;
|
||||
|
||||
return a;
|
||||
},
|
||||
|
||||
FragmentDefinition: (a, b) => {
|
||||
if ( a.typeCondition && b.typeCondition ) {
|
||||
if ( a.typeCondition.kind !== b.typeCondition.kind )
|
||||
return a;
|
||||
|
||||
if ( a.typeCondition.name.value != b.typeCondition.name.value )
|
||||
return a;
|
||||
}
|
||||
|
||||
// TODO: directives
|
||||
|
||||
if ( a.selectionSet && b.selectionSet )
|
||||
a.selectionSet = merge(a.selectionSet, b.selectionSet);
|
||||
else if ( b.selectionSet )
|
||||
a.selectionSet = b.selectionSet;
|
||||
|
||||
return a;
|
||||
},
|
||||
|
||||
SelectionSet: (a, b) => {
|
||||
if ( a.selections && b.selections )
|
||||
a.selections = mergeList(a.selections, b.selections);
|
||||
else if ( b.selections )
|
||||
a.selections = b.selections;
|
||||
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function mergeList(a, b) {
|
||||
const a_names = {};
|
||||
for(const item of a) {
|
||||
if ( ! item || ! item.name || item.name.kind !== 'Name' )
|
||||
continue;
|
||||
|
||||
a_names[item.name.value] = item;
|
||||
}
|
||||
|
||||
for(const item of b) {
|
||||
if ( ! item || ! item.name || item.name.kind !== 'Name' )
|
||||
continue;
|
||||
|
||||
const name = item.name.value,
|
||||
idx = a_names[name] ? a.indexOf(a_names[name]) : -1;
|
||||
|
||||
if ( idx !== -1 )
|
||||
a[idx] = merge(a[idx], item);
|
||||
else
|
||||
a.push(item);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
export default function merge(a, b) {
|
||||
if ( a.kind !== b.kind )
|
||||
return a;
|
||||
|
||||
if ( MERGE_METHODS[a.kind] )
|
||||
return MERGE_METHODS[a.kind](a, b);
|
||||
|
||||
return a;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue