From 76c6a57b3afd05eafaf75c305e522a1d868ff3ca Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 28 May 2024 10:49:20 -0600 Subject: [PATCH 1/9] - initial work on moving Query Composer to 3rd party plugin --- .../src/components/Explorer.js | 2481 +++++++++++++++++ .../src/components/QueryComposer.js | 23 + plugins/third-party-plugin/src/index.js | 81 +- .../third-party-plugin/third-party-plugin.php | 3 +- plugins/third-party-plugin/webpack.config.js | 44 + 5 files changed, 2607 insertions(+), 25 deletions(-) create mode 100644 plugins/third-party-plugin/src/components/Explorer.js create mode 100644 plugins/third-party-plugin/src/components/QueryComposer.js create mode 100644 plugins/third-party-plugin/webpack.config.js diff --git a/plugins/third-party-plugin/src/components/Explorer.js b/plugins/third-party-plugin/src/components/Explorer.js new file mode 100644 index 0000000..e11f7fd --- /dev/null +++ b/plugins/third-party-plugin/src/components/Explorer.js @@ -0,0 +1,2481 @@ +import React from 'react'; + +// import { GraphQL } from 'wpgraphql-ide'; + +import { + getNamedType, + GraphQLObjectType, + isEnumType, + isInputObjectType, + isInterfaceType, + isLeafType, + isNonNullType, + isObjectType, + isRequiredInputField, + isScalarType, + isUnionType, + isWrappingType, + parse, + print, + parseType, + visit, +} from 'graphql'; + +function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +const defaultColors = { + keyword: '#B11A04', + def: '#D2054E', + property: '#1F61A0', + qualifier: '#1C92A9', + attribute: '#8B2BB9', + number: '#2882F9', + string: '#D64292', + builtin: '#D47509', + string2: '#0B7FC7', + variable: '#397D13', + atom: '#CA9800', +}; + +const defaultArrowOpen = ( + + + +); + +const defaultArrowClosed = ( + + + +); + +const defaultCheckboxChecked = ( + + + +); + +const defaultCheckboxUnchecked = ( + + + +); + +function Checkbox(props) { + return props.checked + ? props.styleConfig.checkboxChecked + : props.styleConfig.checkboxUnchecked; +} + +export function defaultValue( + argType, +) { + if (isEnumType(argType)) { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } else { + switch (argType.name) { + case 'String': + return {kind: 'StringValue', value: ''}; + case 'Float': + return {kind: 'FloatValue', value: '1.5'}; + case 'Int': + return {kind: 'IntValue', value: '10'}; + case 'Boolean': + return {kind: 'BooleanValue', value: false}; + default: + return {kind: 'StringValue', value: ''}; + } + } +} + +function defaultGetDefaultScalarArgValue( + parentField, + arg, + argType, +) { + return defaultValue(argType); +} + +function defaultGetDefaultFieldNames(type) { + const fields = type.getFields(); + + if (fields['id']) { + const res = ['id']; + if (fields['email']) { + res.push('email'); + } else if (fields['name']) { + res.push('name'); + } + return res; + } + + if (fields['edges']) { + return ['edges']; + } + + if (fields['node']) { + return ['node']; + } + + if (fields['nodes']) { + return ['nodes']; + } + + const leafFieldNames = []; + Object.keys(fields).forEach(fieldName => { + if (isLeafType(fields[fieldName].type)) { + leafFieldNames.push(fieldName); + } + }); + + if (!leafFieldNames.length) { + return ['__typename']; + } + return leafFieldNames.slice(0, 2); +} + +function isRequiredArgument(arg) { + return isNonNullType(arg.type) && arg.defaultValue === undefined; +} + +function unwrapOutputType(outputType) { + let unwrappedType = outputType; + while (isWrappingType(unwrappedType)) { + unwrappedType = unwrappedType.ofType; + } + return unwrappedType; +} + +function unwrapInputType(inputType) { + let unwrappedType = inputType; + while (isWrappingType(unwrappedType)) { + unwrappedType = unwrappedType.ofType; + } + return unwrappedType; +} + +function coerceArgValue(argType, value) { + if (typeof value !== 'string' && value.kind === 'VariableDefinition') { + return value.variable; + } else if (isScalarType(argType)) { + try { + switch (argType.name) { + case 'String': + return { + kind: 'StringValue', + value: String(argType.parseValue(value)), + }; + case 'Float': + return { + kind: 'FloatValue', + value: String(argType.parseValue(parseFloat(value))), + }; + case 'Int': + return { + kind: 'IntValue', + value: String(argType.parseValue(parseInt(value, 10))), + }; + case 'Boolean': + try { + const parsed = JSON.parse(value); + if (typeof parsed === 'boolean') { + return {kind: 'BooleanValue', value: parsed}; + } else { + return {kind: 'BooleanValue', value: false}; + } + } catch (e) { + return { + kind: 'BooleanValue', + value: false, + }; + } + default: + return { + kind: 'StringValue', + value: String(argType.parseValue(value)), + }; + } + } catch (e) { + console.error('error coercing arg value', e, value); + return {kind: 'StringValue', value: value}; + } + } else { + try { + const parsedValue = argType.parseValue(value); + if (parsedValue) { + return {kind: 'EnumValue', value: String(parsedValue)}; + } else { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } + } catch (e) { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } + } +} + +class InputArgView extends React.PureComponent { + _previousArgSelection; + _getArgSelection = () => { + return this.props.selection.fields.find( + field => field.name.value === this.props.arg.name, + ); + }; + + _removeArg = () => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + this._previousArgSelection = argSelection; + this.props.modifyFields( + selection.fields.filter(field => field !== argSelection), + true, + ); + }; + + _addArg = () => { + const { + selection, + arg, + getDefaultScalarArgValue, + parentField, + makeDefaultArg, + } = this.props; + const argType = unwrapInputType(arg.type); + + let argSelection = null; + if (this._previousArgSelection) { + argSelection = this._previousArgSelection; + } else if (isInputObjectType(argType)) { + const fields = argType.getFields(); + argSelection = { + kind: 'ObjectField', + name: {kind: 'Name', value: arg.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + Object.keys(fields).map(k => fields[k]), + ), + }, + }; + } else if (isLeafType(argType)) { + argSelection = { + kind: 'ObjectField', + name: {kind: 'Name', value: arg.name}, + value: getDefaultScalarArgValue(parentField, arg, argType), + }; + } + + if (!argSelection) { + console.error('Unable to add arg for argType', argType); + } else { + return this.props.modifyFields( + [...(selection.fields || []), argSelection], + true, + ); + } + }; + + _setArgValue = (event, options) => { + let settingToNull = false; + let settingToVariable = false; + let settingToLiteralValue = false; + try { + if (event.kind === 'VariableDefinition') { + settingToVariable = true; + } else if (event === null || typeof event === 'undefined') { + settingToNull = true; + } else if (typeof event.kind === 'string') { + settingToLiteralValue = true; + } + } catch (e) {} + + const {selection} = this.props; + + const argSelection = this._getArgSelection(); + + if (!argSelection) { + console.error('missing arg selection when setting arg value'); + return; + } + const argType = unwrapInputType(this.props.arg.type); + + const handleable = + isLeafType(argType) || + settingToVariable || + settingToNull || + settingToLiteralValue; + + if (!handleable) { + console.warn( + 'Unable to handle non leaf types in InputArgView.setArgValue', + event, + ); + return; + } + let targetValue; + let value; + + if (event === null || typeof event === 'undefined') { + value = null; + } else if ( + !event.target && + !!event.kind && + event.kind === 'VariableDefinition' + ) { + targetValue = event; + value = targetValue.variable; + } else if (typeof event.kind === 'string') { + value = event; + } else if (event.target && typeof event.target.value === 'string') { + targetValue = event.target.value; + value = coerceArgValue(argType, targetValue); + } + + const newDoc = this.props.modifyFields( + (selection.fields || []).map(field => { + const isTarget = field === argSelection; + const newField = isTarget + ? { + ...field, + value: value, + } + : field; + + return newField; + }), + options, + ); + + return newDoc; + }; + + _modifyChildFields = fields => { + return this.props.modifyFields( + this.props.selection.fields.map(field => + field.name.value === this.props.arg.name + ? { + ...field, + value: { + kind: 'ObjectValue', + fields: fields, + }, + } + : field, + ), + true, + ); + }; + + render() { + const {arg, parentField} = this.props; + const argSelection = this._getArgSelection(); + + return ( + + ); + } +} + +class ArgView extends React.PureComponent { + _previousArgSelection; + _getArgSelection = () => { + const {selection} = this.props; + + return (selection.arguments || []).find( + arg => arg.name.value === this.props.arg.name, + ); + }; + _removeArg = commit => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + this._previousArgSelection = argSelection; + return this.props.modifyArguments( + (selection.arguments || []).filter(arg => arg !== argSelection), + commit, + ); + }; + _addArg = commit => { + const { + selection, + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + arg, + } = this.props; + const argType = unwrapInputType(arg.type); + + let argSelection = null; + if (this._previousArgSelection) { + argSelection = this._previousArgSelection; + } else if (isInputObjectType(argType)) { + const fields = argType.getFields(); + argSelection = { + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + Object.keys(fields).map(k => fields[k]), + ), + }, + }; + } else if (isLeafType(argType)) { + argSelection = { + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: getDefaultScalarArgValue(parentField, arg, argType), + }; + } + + if (!argSelection) { + console.error('Unable to add arg for argType', argType); + return null; + } else { + return this.props.modifyArguments( + [...(selection.arguments || []), argSelection], + commit, + ); + } + }; + _setArgValue = (event, options) => { + let settingToNull = false; + let settingToVariable = false; + let settingToLiteralValue = false; + try { + if (event.kind === 'VariableDefinition') { + settingToVariable = true; + } else if (event === null || typeof event === 'undefined') { + settingToNull = true; + } else if (typeof event.kind === 'string') { + settingToLiteralValue = true; + } + } catch (e) {} + const {selection} = this.props; + const argSelection = this._getArgSelection(); + if (!argSelection && !settingToVariable) { + console.error('missing arg selection when setting arg value'); + return; + } + const argType = unwrapInputType(this.props.arg.type); + + const handleable = + isLeafType(argType) || + settingToVariable || + settingToNull || + settingToLiteralValue; + + if (!handleable) { + console.warn('Unable to handle non leaf types in ArgView._setArgValue'); + return; + } + + let targetValue; + let value; + + if (event === null || typeof event === 'undefined') { + value = null; + } else if (event.target && typeof event.target.value === 'string') { + targetValue = event.target.value; + value = coerceArgValue(argType, targetValue); + } else if (!event.target && event.kind === 'VariableDefinition') { + targetValue = event; + value = targetValue.variable; + } else if (typeof event.kind === 'string') { + value = event; + } + + return this.props.modifyArguments( + (selection.arguments || []).map(a => + a === argSelection + ? { + ...a, + value: value, + } + : a, + ), + options, + ); + }; + + _setArgFields = (fields, commit) => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + if (!argSelection) { + console.error('missing arg selection when setting arg value'); + return; + } + + return this.props.modifyArguments( + (selection.arguments || []).map(a => + a === argSelection + ? { + ...a, + value: { + kind: 'ObjectValue', + fields, + }, + } + : a, + ), + commit, + ); + }; + + render() { + const {arg, parentField} = this.props; + const argSelection = this._getArgSelection(); + + return ( + + ); + } +} + +function isRunShortcut(event) { + return event.ctrlKey && event.key === 'Enter'; +} + +function canRunOperation(operationName) { + return operationName !== 'FragmentDefinition'; +} + +class ScalarInput extends React.PureComponent { + _ref; + _handleChange = event => { + this.props.setArgValue(event, true); + }; + + componentDidMount() { + const input = this._ref; + const activeElement = document.activeElement; + if ( + input && + activeElement && + !(activeElement instanceof HTMLTextAreaElement) + ) { + input.focus(); + input.setSelectionRange(0, input.value.length); + } + } + + render() { + const {arg, argValue, styleConfig} = this.props; + const argType = unwrapInputType(arg.type); + const value = typeof argValue.value === 'string' ? argValue.value : ''; + const color = + this.props.argValue.kind === 'StringValue' + ? styleConfig.colors.string + : styleConfig.colors.number; + return ( + + {argType.name === 'String' ? '"' : ''} + { + this._ref = ref; + }} + type="text" + onChange={this._handleChange} + value={value} + /> + {argType.name === 'String' ? '"' : ''} + + ); + } +} + +class AbstractArgView extends React.PureComponent { + state = {displayArgActions: false}; + render() { + const {argValue, arg, styleConfig} = this.props; + const argType = unwrapInputType(arg.type); + + let input = null; + if (argValue) { + if (argValue.kind === 'Variable') { + input = ( + + ${argValue.name.value} + + ); + } else if (isScalarType(argType)) { + if (argType.name === 'Boolean') { + input = ( + + ); + } else { + input = ( + + ); + } + } else if (isEnumType(argType)) { + if (argValue.kind === 'EnumValue') { + input = ( + + ); + } else { + console.error( + 'arg mismatch between arg and selection', + argType, + argValue, + ); + } + } else if (isInputObjectType(argType)) { + if (argValue.kind === 'ObjectValue') { + const fields = argType.getFields(); + input = ( +
+ {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ); + } else { + console.error( + 'arg mismatch between arg and selection', + argType, + argValue, + ); + } + } + } + + const variablize = () => { + const baseVariableName = arg.name; + const conflictingNameCount = ( + this.props.definition.variableDefinitions || [] + ).filter(varDef => + varDef.variable.name.value.startsWith(baseVariableName), + ).length; + + let variableName; + if (conflictingNameCount > 0) { + variableName = `${baseVariableName}${conflictingNameCount}`; + } else { + variableName = baseVariableName; + } + const argPrintedType = arg.type.toString(); + const argType = parseType(argPrintedType); + + const base = { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { + kind: 'Name', + value: variableName, + }, + }, + type: argType, + directives: [], + }; + + const variableDefinitionByName = name => + (this.props.definition.variableDefinitions || []).find( + varDef => varDef.variable.name.value === name, + ); + + let variable; + + let subVariableUsageCountByName = {}; + + if (typeof argValue !== 'undefined' && argValue !== null) { + const cleanedDefaultValue = visit(argValue, { + Variable(node) { + const varName = node.name.value; + const varDef = variableDefinitionByName(varName); + + subVariableUsageCountByName[varName] = + subVariableUsageCountByName[varName] + 1 || 1; + + if (!varDef) { + return; + } + + return varDef.defaultValue; + }, + }); + + const isNonNullable = base.type.kind === 'NonNullType'; + + const unwrappedBase = isNonNullable + ? {...base, type: base.type.type} + : base; + + variable = {...unwrappedBase, defaultValue: cleanedDefaultValue}; + } else { + variable = base; + } + + const newlyUnusedVariables = Object.entries(subVariableUsageCountByName) + .filter(([_, usageCount]) => usageCount < 2) + .map(([varName, _]) => varName); + + if (variable) { + const newDoc = this.props.setArgValue(variable, false); + + if (newDoc) { + const targetOperation = newDoc.definitions.find(definition => { + if ( + !!definition.operation && + !!definition.name && + !!definition.name.value && + !!this.props.definition.name && + !!this.props.definition.name.value + ) { + return definition.name.value === this.props.definition.name.value; + } else { + return false; + } + }); + + const newVariableDefinitions = [ + ...(targetOperation.variableDefinitions || []), + variable, + ].filter( + varDef => + newlyUnusedVariables.indexOf(varDef.variable.name.value) === -1, + ); + + const newOperation = { + ...targetOperation, + variableDefinitions: newVariableDefinitions, + }; + + const existingDefs = newDoc.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + const finalDoc = { + ...newDoc, + definitions: newDefinitions, + }; + + this.props.onCommit(finalDoc); + } + } + }; + + const devariablize = () => { + if (!argValue || !argValue.name || !argValue.name.value) { + return; + } + + const variableName = argValue.name.value; + const variableDefinition = ( + this.props.definition.variableDefinitions || [] + ).find(varDef => varDef.variable.name.value === variableName); + + if (!variableDefinition) { + return; + } + + const defaultValue = variableDefinition.defaultValue; + + const newDoc = this.props.setArgValue(defaultValue, { + commit: false, + }); + + if (newDoc) { + const targetOperation = newDoc.definitions.find( + definition => + definition.name.value === this.props.definition.name.value, + ); + + if (!targetOperation) { + return; + } + + let variableUseCount = 0; + + visit(targetOperation, { + Variable(node) { + if (node.name.value === variableName) { + variableUseCount = variableUseCount + 1; + } + }, + }); + + let newVariableDefinitions = targetOperation.variableDefinitions || []; + + if (variableUseCount < 2) { + newVariableDefinitions = newVariableDefinitions.filter( + varDef => varDef.variable.name.value !== variableName, + ); + } + + const newOperation = { + ...targetOperation, + variableDefinitions: newVariableDefinitions, + }; + + const existingDefs = newDoc.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + const finalDoc = { + ...newDoc, + definitions: newDefinitions, + }; + + this.props.onCommit(finalDoc); + } + }; + + const isArgValueVariable = argValue && argValue.kind === 'Variable'; + + const variablizeActionButton = !this.state.displayArgActions ? null : ( + + ); + + return ( +
+ { + const shouldAdd = !argValue; + if (shouldAdd) { + this.props.addArg(true); + } else { + this.props.removeArg(true); + } + this.setState({displayArgActions: shouldAdd}); + }}> + {isInputObjectType(argType) ? ( + + {!!argValue + ? this.props.styleConfig.arrowOpen + : this.props.styleConfig.arrowClosed} + + ) : ( + + )} + { + if (argValue !== null && typeof argValue !== 'undefined') { + this.setState({displayArgActions: true}); + } + }} + onMouseLeave={() => this.setState({displayArgActions: false})}> + {arg.name} + {isRequiredArgument(arg) ? '*' : ''}: {variablizeActionButton}{' '} + {' '} + + {input || }{' '} +
+ ); + } +} + +class AbstractView extends React.PureComponent { + _previousSelection; + _addFragment = () => { + this.props.modifySelections([ + ...this.props.selections, + this._previousSelection || { + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: {kind: 'Name', value: this.props.implementingType.name}, + }, + selectionSet: { + kind: 'SelectionSet', + selections: this.props + .getDefaultFieldNames(this.props.implementingType) + .map(fieldName => ({ + kind: 'Field', + name: {kind: 'Name', value: fieldName}, + })), + }, + }, + ]); + }; + _removeFragment = () => { + const thisSelection = this._getSelection(); + this._previousSelection = thisSelection; + this.props.modifySelections( + this.props.selections.filter(s => s !== thisSelection), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find( + selection => + selection.kind === 'InlineFragment' && + selection.typeCondition && + this.props.implementingType.name === selection.typeCondition.name.value, + ); + if (!selection) { + return null; + } + if (selection.kind === 'InlineFragment') { + return selection; + } + }; + + _modifyChildSelections = (selections, options) => { + const thisSelection = this._getSelection(); + return this.props.modifySelections( + this.props.selections.map(selection => { + if (selection === thisSelection) { + return { + directives: selection.directives, + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: {kind: 'Name', value: this.props.implementingType.name}, + }, + selectionSet: { + kind: 'SelectionSet', + selections, + }, + }; + } + return selection; + }), + options, + ); + }; + + render() { + const { + implementingType, + schema, + getDefaultFieldNames, + styleConfig, + } = this.props; + const selection = this._getSelection(); + const fields = implementingType.getFields(); + const childSelections = selection + ? selection.selectionSet + ? selection.selectionSet.selections + : [] + : []; + + return ( +
+ + + + {this.props.implementingType.name} + + + {selection ? ( +
+ {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ) : null} +
+ ); + } +} + +class FragmentView extends React.PureComponent { + _previousSelection; + _addFragment = () => { + this.props.modifySelections([ + ...this.props.selections, + this._previousSelection || { + kind: 'FragmentSpread', + name: this.props.fragment.name, + }, + ]); + }; + _removeFragment = () => { + const thisSelection = this._getSelection(); + this._previousSelection = thisSelection; + this.props.modifySelections( + this.props.selections.filter(s => { + const isTargetSelection = + s.kind === 'FragmentSpread' && + s.name.value === this.props.fragment.name.value; + + return !isTargetSelection; + }), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find(selection => { + return ( + selection.kind === 'FragmentSpread' && + selection.name.value === this.props.fragment.name.value + ); + }); + + return selection; + }; + + render() { + const {styleConfig} = this.props; + const selection = this._getSelection(); + return ( +
+ + + + {this.props.fragment.name.value} + + +
+ ); + } +} + +class FieldView extends React.PureComponent { + state = {displayFieldActions: false}; + + _previousSelection; + _addAllFieldsToSelections = rawSubfields => { + const subFields = !!rawSubfields + ? Object.keys(rawSubfields).map(fieldName => { + return { + kind: 'Field', + name: {kind: 'Name', value: fieldName}, + arguments: [], + }; + }) + : []; + + const subSelectionSet = { + kind: 'SelectionSet', + selections: subFields, + }; + + const nextSelections = [ + ...this.props.selections.filter(selection => { + if (selection.kind === 'InlineFragment') { + return true; + } else { + return selection.name.value !== this.props.field.name; + } + }), + { + kind: 'Field', + name: {kind: 'Name', value: this.props.field.name}, + arguments: defaultArgs( + this.props.getDefaultScalarArgValue, + this.props.makeDefaultArg, + this.props.field, + ), + selectionSet: subSelectionSet, + }, + ]; + + this.props.modifySelections(nextSelections); + }; + + _addFieldToSelections = rawSubfields => { + const nextSelections = [ + ...this.props.selections, + this._previousSelection || { + kind: 'Field', + name: {kind: 'Name', value: this.props.field.name}, + arguments: defaultArgs( + this.props.getDefaultScalarArgValue, + this.props.makeDefaultArg, + this.props.field, + ), + }, + ]; + + this.props.modifySelections(nextSelections); + }; + + _handleUpdateSelections = event => { + const selection = this._getSelection(); + if (selection && !event.altKey) { + this._removeFieldFromSelections(); + } else { + const fieldType = getNamedType(this.props.field.type); + const rawSubfields = isObjectType(fieldType) && fieldType.getFields(); + + const shouldSelectAllSubfields = !!rawSubfields && event.altKey; + + shouldSelectAllSubfields + ? this._addAllFieldsToSelections(rawSubfields) + : this._addFieldToSelections(rawSubfields); + } + }; + + _removeFieldFromSelections = () => { + const previousSelection = this._getSelection(); + this._previousSelection = previousSelection; + this.props.modifySelections( + this.props.selections.filter( + selection => selection !== previousSelection, + ), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find( + selection => + selection.kind === 'Field' && + this.props.field.name === selection.name.value, + ); + if (!selection) { + return null; + } + if (selection.kind === 'Field') { + return selection; + } + }; + + _setArguments = (argumentNodes, options) => { + const selection = this._getSelection(); + if (!selection) { + console.error('Missing selection when setting arguments', argumentNodes); + return; + } + return this.props.modifySelections( + this.props.selections.map(s => + s === selection + ? { + alias: selection.alias, + arguments: argumentNodes, + directives: selection.directives, + kind: 'Field', + name: selection.name, + selectionSet: selection.selectionSet, + } + : s, + ), + options, + ); + }; + + _modifyChildSelections = (selections, options) => { + return this.props.modifySelections( + this.props.selections.map(selection => { + if ( + selection.kind === 'Field' && + this.props.field.name === selection.name.value + ) { + if (selection.kind !== 'Field') { + throw new Error('invalid selection'); + } + return { + alias: selection.alias, + arguments: selection.arguments, + directives: selection.directives, + kind: 'Field', + name: selection.name, + selectionSet: { + kind: 'SelectionSet', + selections, + }, + }; + } + return selection; + }), + options, + ); + }; + + render() { + const {field, schema, getDefaultFieldNames, styleConfig} = this.props; + const selection = this._getSelection(); + const type = unwrapOutputType(field.type); + const args = field.args.sort((a, b) => a.name.localeCompare(b.name)); + let className = `graphiql-explorer-node graphiql-explorer-${field.name}`; + + if (field.isDeprecated) { + className += ' graphiql-explorer-deprecated'; + } + + const applicableFragments = + isObjectType(type) || isInterfaceType(type) || isUnionType(type) + ? this.props.availableFragments && + this.props.availableFragments[type.name] + : null; + + const node = ( +
+ { + const containsMeaningfulSubselection = + isObjectType(type) && + selection && + selection.selectionSet && + selection.selectionSet.selections.filter( + selection => selection.kind !== 'FragmentSpread', + ).length > 0; + + if (containsMeaningfulSubselection) { + this.setState({displayFieldActions: true}); + } + }} + onMouseLeave={() => this.setState({displayFieldActions: false})}> + {isObjectType(type) ? ( + + {!!selection + ? this.props.styleConfig.arrowOpen + : this.props.styleConfig.arrowClosed} + + ) : null} + {isObjectType(type) ? null : ( + + )} + + {field.name} + + {!this.state.displayFieldActions ? null : ( + + )} + + {selection && args.length ? ( +
+ {args.map(arg => ( + + ))} +
+ ) : null} +
+ ); + + if ( + selection && + (isObjectType(type) || isInterfaceType(type) || isUnionType(type)) + ) { + const fields = isUnionType(type) ? {} : type.getFields(); + const childSelections = selection + ? selection.selectionSet + ? selection.selectionSet.selections + : [] + : []; + return ( +
+ {node} +
+ {!!applicableFragments + ? applicableFragments.map(fragment => { + const type = schema.getType( + fragment.typeCondition.name.value, + ); + const fragmentName = fragment.name.value; + return !type ? null : ( + + ); + }) + : null} + {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} + {isInterfaceType(type) || isUnionType(type) + ? schema + .getPossibleTypes(type) + .map(type => ( + + )) + : null} +
+
+ ); + } + return node; + } +} + +function parseQuery(text) { + try { + if (!text.trim()) { + return null; + } + return parse( + text, + {noLocation: true}, + ); + } catch (e) { + return new Error(e); + } +} + +const DEFAULT_OPERATION = { + kind: 'OperationDefinition', + operation: 'query', + variableDefinitions: [], + name: {kind: 'Name', value: 'MyQuery'}, + directives: [], + selectionSet: { + kind: 'SelectionSet', + selections: [], + }, +}; +const DEFAULT_DOCUMENT = { + kind: 'Document', + definitions: [DEFAULT_OPERATION], +}; +let parseQueryMemoize = null; +function memoizeParseQuery(query) { + if (parseQueryMemoize && parseQueryMemoize[0] === query) { + return parseQueryMemoize[1]; + } else { + const result = parseQuery(query); + if (!result) { + return DEFAULT_DOCUMENT; + } else if (result instanceof Error) { + if (parseQueryMemoize) { + return parseQueryMemoize[1]; + } else { + return DEFAULT_DOCUMENT; + } + } else { + parseQueryMemoize = [query, result]; + return result; + } + } +} + +const defaultStyles = { + buttonStyle: { + fontSize: '1.2em', + padding: '0px', + backgroundColor: 'white', + border: 'none', + margin: '5px 0px', + height: '40px', + width: '100%', + display: 'block', + maxWidth: 'none', + }, + + actionButtonStyle: { + padding: '0px', + backgroundColor: 'white', + border: 'none', + margin: '0px', + maxWidth: 'none', + height: '15px', + width: '15px', + display: 'inline-block', + fontSize: 'smaller', + }, + + explorerActionsStyle: { + margin: '4px -8px -8px', + paddingLeft: '8px', + bottom: '0px', + width: '100%', + textAlign: 'center', + background: 'none', + borderTop: 'none', + borderBottom: 'none', + }, +}; + +class RootView extends React.PureComponent { + state = {newOperationType: 'query', displayTitleActions: false}; + _previousOperationDef; + + _modifySelections = (selections, options) => { + let operationDef = this.props.definition; + + if ( + operationDef.selectionSet.selections.length === 0 && + this._previousOperationDef + ) { + operationDef = this._previousOperationDef; + } + + let newOperationDef; + + if (operationDef.kind === 'FragmentDefinition') { + newOperationDef = { + ...operationDef, + selectionSet: { + ...operationDef.selectionSet, + selections, + }, + }; + } else if (operationDef.kind === 'OperationDefinition') { + let cleanedSelections = selections.filter(selection => { + return !( + selection.kind === 'Field' && selection.name.value === '__typename' + ); + }); + + if (cleanedSelections.length === 0) { + cleanedSelections = [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename ## Placeholder value', + }, + }, + ]; + } + + newOperationDef = { + ...operationDef, + selectionSet: { + ...operationDef.selectionSet, + selections: cleanedSelections, + }, + }; + } + + return this.props.onEdit(newOperationDef, options); + }; + + _onOperationRename = event => + this.props.onOperationRename(event.target.value); + + _handlePotentialRun = event => { + if (isRunShortcut(event) && canRunOperation(this.props.definition.kind)) { + this.props.onRunOperation(this.props.name); + } + }; + + _rootViewElId = () => { + const {operationType, name} = this.props; + const rootViewElId = `${operationType}-${name || 'unknown'}`; + return rootViewElId; + }; + + componentDidMount() { + const rootViewElId = this._rootViewElId(); + + this.props.onMount(rootViewElId); + } + + render() { + const { + operationType, + definition, + schema, + getDefaultFieldNames, + styleConfig, + } = this.props; + const rootViewElId = this._rootViewElId(); + + const fields = this.props.fields || {}; + const operationDef = definition; + const selections = operationDef.selectionSet.selections; + + const operationDisplayName = + this.props.name || `${capitalize(operationType)} Name`; + + return ( +
+
this.setState({displayTitleActions: true})} + onMouseLeave={() => this.setState({displayTitleActions: false})}> + {operationType}{' '} + + + + {!!this.props.onTypeName ? ( + +
+ {`on ${this.props.onTypeName}`} +
+ ) : ( + '' + )} + {!!this.state.displayTitleActions ? ( + + + + + ) : ( + '' + )} +
+ + {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ); + } +} + +function Attribution() { + return ( +
+
+ GraphiQL Explorer by OneGraph +
+
+ Contribute on{' '} + GitHub +
+
+ ); +} + +class Explorer extends React.PureComponent { + + state = { + newOperationType: 'query', + operation: null, + operationToScrollTo: null, + }; + + _ref; + _resetScroll = () => { + const container = this._ref; + if (container) { + container.scrollLeft = 0; + } + }; + componentDidMount() { + this._resetScroll(); + } + + _onEdit = query => this.props.onEdit(query); + + _setAddOperationType = value => { + this.setState({newOperationType: value}); + }; + + _handleRootViewMount = rootViewElId => { + if ( + !!this.state.operationToScrollTo && + this.state.operationToScrollTo === rootViewElId + ) { + var selector = `.graphiql-explorer-root #${rootViewElId}`; + + var el = document.querySelector(selector); + el && el.scrollIntoView(); + } + }; + + render() { + const {schema, query, makeDefaultArg} = this.props; + + if (!schema) { + return ( +
+ No Schema Available +
+ ); + } + const styleConfig = { + colors: this.props.colors || defaultColors, + checkboxChecked: this.props.checkboxChecked || defaultCheckboxChecked, + checkboxUnchecked: + this.props.checkboxUnchecked || defaultCheckboxUnchecked, + arrowClosed: this.props.arrowClosed || defaultArrowClosed, + arrowOpen: this.props.arrowOpen || defaultArrowOpen, + styles: this.props.styles + ? { + ...defaultStyles, + ...this.props.styles, + } + : defaultStyles, + }; + const queryType = schema.getQueryType(); + const mutationType = schema.getMutationType(); + const subscriptionType = schema.getSubscriptionType(); + if (!queryType && !mutationType && !subscriptionType) { + return
Missing query type
; + } + const queryFields = queryType && queryType.getFields(); + const mutationFields = mutationType && mutationType.getFields(); + const subscriptionFields = subscriptionType && subscriptionType.getFields(); + + const parsedQuery = memoizeParseQuery(query); + const getDefaultFieldNames = + this.props.getDefaultFieldNames || defaultGetDefaultFieldNames; + const getDefaultScalarArgValue = + this.props.getDefaultScalarArgValue || defaultGetDefaultScalarArgValue; + + const definitions = parsedQuery.definitions; + + const _relevantOperations = definitions + .map(definition => { + if (definition.kind === 'FragmentDefinition') { + return definition; + } else if (definition.kind === 'OperationDefinition') { + return definition; + } else { + return null; + } + }) + .filter(Boolean); + + const relevantOperations = + _relevantOperations.length === 0 + ? DEFAULT_DOCUMENT.definitions + : _relevantOperations; + + const renameOperation = (targetOperation, name) => { + const newName = + name == null || name === '' + ? null + : {kind: 'Name', value: name, loc: undefined}; + const newOperation = {...targetOperation, name: newName}; + + const existingDefs = parsedQuery.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const cloneOperation = targetOperation => { + let kind; + if (targetOperation.kind === 'FragmentDefinition') { + kind = 'fragment'; + } else { + kind = targetOperation.operation; + } + + const newOperationName = + ((targetOperation.name && targetOperation.name.value) || '') + 'Copy'; + + const newName = { + kind: 'Name', + value: newOperationName, + loc: undefined, + }; + + const newOperation = {...targetOperation, name: newName}; + + const existingDefs = parsedQuery.definitions; + + const newDefinitions = [...existingDefs, newOperation]; + + this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const destroyOperation = targetOperation => { + const existingDefs = parsedQuery.definitions; + + const newDefinitions = existingDefs.filter(existingOperation => { + if (targetOperation === existingOperation) { + return false; + } else { + return true; + } + }); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const addOperation = kind => { + const existingDefs = parsedQuery.definitions; + + const viewingDefaultOperation = + parsedQuery.definitions.length === 1 && + parsedQuery.definitions[0] === DEFAULT_DOCUMENT.definitions[0]; + + const MySiblingDefs = viewingDefaultOperation + ? [] + : existingDefs.filter(def => { + if (def.kind === 'OperationDefinition') { + return def.operation === kind; + } else { + return false; + } + }); + + const newOperationName = `My${capitalize(kind)}${ + MySiblingDefs.length === 0 ? '' : MySiblingDefs.length + 1 + }`; + + const firstFieldName = '__typename # Placeholder value'; + + const selectionSet = { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: firstFieldName, + loc: null, + }, + arguments: [], + directives: [], + selectionSet: null, + loc: null, + }, + ], + loc: null, + }; + + const newDefinition = { + kind: 'OperationDefinition', + operation: kind, + name: {kind: 'Name', value: newOperationName}, + variableDefinitions: [], + directives: [], + selectionSet: selectionSet, + loc: null, + }; + + const newDefinitions = + viewingDefaultOperation + ? [newDefinition] + : [...parsedQuery.definitions, newDefinition]; + + const newOperationDef = { + ...parsedQuery, + definitions: newDefinitions, + }; + + this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + + this.props.onEdit(print(newOperationDef)); + }; + + const actionsOptions = [ + !!queryFields ? ( + + ) : null, + !!mutationFields ? ( + + ) : null, + !!subscriptionFields ? ( + + ) : null, + ].filter(Boolean); + + const actionsEl = + actionsOptions.length === 0 || this.props.hideActions ? null : ( +
+
event.preventDefault()}> + + Add new{' '} + + + +
+
+ ); + + const externalFragments = + this.props.externalFragments && + this.props.externalFragments.reduce((acc, fragment) => { + if (fragment.kind === 'FragmentDefinition') { + const fragmentTypeName = fragment.typeCondition.name.value; + const existingFragmentsForType = acc[fragmentTypeName] || []; + const newFragmentsForType = [ + ...existingFragmentsForType, + fragment, + ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + return { + ...acc, + [fragmentTypeName]: newFragmentsForType, + }; + } + + return acc; + }, {}); + + const documentFragments = relevantOperations.reduce( + (acc, operation) => { + if (operation.kind === 'FragmentDefinition') { + const fragmentTypeName = operation.typeCondition.name.value; + const existingFragmentsForType = acc[fragmentTypeName] || []; + const newFragmentsForType = [ + ...existingFragmentsForType, + operation, + ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + return { + ...acc, + [fragmentTypeName]: newFragmentsForType, + }; + } + + return acc; + }, + {}, + ); + + const availableFragments = {...documentFragments, ...externalFragments}; + + const attribution = this.props.showAttribution ? : null; + + return ( +
{ + this._ref = ref; + }} + style={{ + fontSize: 12, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + margin: 0, + padding: 8, + fontFamily: + 'Consolas, Inconsolata, "Droid Sans Mono", Monaco, monospace', + display: 'flex', + flexDirection: 'column', + height: '100%', + }} + className="graphiql-explorer-root"> +
+ {relevantOperations.map((operation, index) => { + const operationName = + operation && operation.name && operation.name.value; + + const operationType = + operation.kind === 'FragmentDefinition' + ? 'fragment' + : (operation && operation.operation) || 'query'; + + const onOperationRename = newName => { + const newOperationDef = renameOperation(operation, newName); + this.props.onEdit(print(newOperationDef)); + }; + + const onOperationClone = () => { + const newOperationDef = cloneOperation(operation); + this.props.onEdit(print(newOperationDef)); + }; + + const onOperationDestroy = () => { + const newOperationDef = destroyOperation(operation); + this.props.onEdit(print(newOperationDef)); + }; + + const fragmentType = + operation.kind === 'FragmentDefinition' && + operation.typeCondition.kind === 'NamedType' && + schema.getType(operation.typeCondition.name.value); + + const fragmentFields = + fragmentType instanceof GraphQLObjectType + ? fragmentType.getFields() + : null; + + const fields = + operationType === 'query' + ? queryFields + : operationType === 'mutation' + ? mutationFields + : operationType === 'subscription' + ? subscriptionFields + : operation.kind === 'FragmentDefinition' + ? fragmentFields + : null; + + const fragmentTypeName = + operation.kind === 'FragmentDefinition' + ? operation.typeCondition.name.value + : null; + + const onCommit = parsedDocument => { + const textualNewDocument = print(parsedDocument); + + this.props.onEdit(textualNewDocument); + }; + + return ( + { + let commit; + if ( + typeof options === 'object' && + typeof options.commit !== 'undefined' + ) { + commit = options.commit; + } else { + commit = true; + } + + if (!!newDefinition) { + const newQuery = { + ...parsedQuery, + definitions: parsedQuery.definitions.map( + existingDefinition => + existingDefinition === operation + ? newDefinition + : existingDefinition, + ), + }; + + if (commit) { + onCommit(newQuery); + return newQuery; + } else { + return newQuery; + } + } else { + return parsedQuery; + } + }} + schema={schema} + getDefaultFieldNames={getDefaultFieldNames} + getDefaultScalarArgValue={getDefaultScalarArgValue} + makeDefaultArg={makeDefaultArg} + onRunOperation={() => { + if (!!this.props.onRunOperation) { + this.props.onRunOperation(operationName); + } + }} + styleConfig={styleConfig} + availableFragments={availableFragments} + /> + ); + })} + {attribution} +
+ + {actionsEl} +
+ ); + } +} + +class ErrorBoundary extends React.Component { + state = {hasError: false, error: null, errorInfo: null}; + + componentDidCatch(error, errorInfo) { + this.setState({hasError: true, error: error, errorInfo: errorInfo}); + console.error('Error in component', error, errorInfo); + } + + render() { + if (this.state.hasError) { + return ( +
+
Something went wrong
+
+ {this.state.error ? this.state.error.toString() : null} +
+ {this.state.errorInfo ? this.state.errorInfo.componentStack : null} +
+
+ ); + } + return this.props.children; + } +} + +class ExplorerWrapper extends React.PureComponent { + + render() { + return ( +
+
+
{this.props.title}
+
+
+ {'\u2715'} +
+
+
+
+ + + +
+
+ ); + } +} + +export default ExplorerWrapper; diff --git a/plugins/third-party-plugin/src/components/QueryComposer.js b/plugins/third-party-plugin/src/components/QueryComposer.js new file mode 100644 index 0000000..8766082 --- /dev/null +++ b/plugins/third-party-plugin/src/components/QueryComposer.js @@ -0,0 +1,23 @@ +import { useSelect } from '@wordpress/data'; +import Explorer from './Explorer' + +export const QueryComposer = () => { + + const schema = useSelect( ( select ) => + select( 'wpgraphql-ide/app' ).schema() + ); + + const query = useSelect( ( select ) => + select( 'wpgraphql-ide/app' ).getQuery() + ); + + return ( + <> + Query Composer... + + + ); +} diff --git a/plugins/third-party-plugin/src/index.js b/plugins/third-party-plugin/src/index.js index 839db0e..8da5bf0 100644 --- a/plugins/third-party-plugin/src/index.js +++ b/plugins/third-party-plugin/src/index.js @@ -2,27 +2,62 @@ * External dependencies */ import { explorerPlugin } from '@graphiql/plugin-explorer'; +import { addAction } from '@wordpress/hooks'; +import {QueryComposer} from "./components/QueryComposer"; + +addAction( 'wpgraphqlide_rendered', 'third-party', () => { + if ( ! window.WPGraphQLIDE || ! window.WPGraphQLIDE.GraphQL ) { + return; + } + console.log({ + message: 'Third Party Plugin Loaded', + WPGraphQL: window.WPGraphQLIDE || null, + }) + const { registerActivityBarPanel } = window.WPGraphQLIDE || {}; + + if ( typeof registerActivityBarPanel === 'function' ) { + + registerActivityBarPanel( 'query-composer', () => { + return { + title: 'Query Composer', + icon: () => <>Query Composer, + content: () => ( +
+ +
+ ) + }; + }, 4 ); + + // registerActivityBarPanel( 'explorer', explorerPlugin, 4 ); + } else { + console.log( 'CANNOT Registering Mock Explorer Panel' ); + } +} ); + +console.log( { + message: 'Third Party Plugin Loaded', + WPGraphQL: window.WPGraphQLIDE || null, +}) + +// return; +// + +// const mockExplorerPanel = () => { +// return { +// title: 'Mock Explorer', +// icon: 'icon', +// content: () => ( +// <> +//

Test

+// +// ), +// }; +// }; +// +// /** +// * Ensure the code only runs once WPGraphQLIDEReady is fired and registerActivityBarPanel is defined. +// */ + + -/** - * Ensure the code only runs once WPGraphQLIDEReady is fired and registerActivityBarPanel is defined. - */ -window.addEventListener( 'WPGraphQLIDEReady', () => { - const { registerActivityBarPanel } = window.WPGraphQLIDE || {}; - const mockExplorerPanel = { - title: 'Mock Explorer', - icon: 'icon', - content: () => ( - <> -

Test

- - ), - }; - - if ( typeof registerActivityBarPanel === 'function' ) { - registerActivityBarPanel( 'explorer', mockExplorerPanel, 4 ); - - // registerActivityBarPanel( 'explorer', explorerPlugin, 4 ); - } else { - console.error( 'registerActivityBarPanel is not defined.' ); - } -}); diff --git a/plugins/third-party-plugin/third-party-plugin.php b/plugins/third-party-plugin/third-party-plugin.php index 108a901..d3b4ebb 100644 --- a/plugins/third-party-plugin/third-party-plugin.php +++ b/plugins/third-party-plugin/third-party-plugin.php @@ -27,8 +27,7 @@ 'third-party-plugin', plugins_url( 'build/index.js', __FILE__ ), array_merge( $asset_file['dependencies'], ['wpgraphql-ide'] ), - $asset_file['version'], - true + $asset_file['version'] ); wp_enqueue_style( diff --git a/plugins/third-party-plugin/webpack.config.js b/plugins/third-party-plugin/webpack.config.js new file mode 100644 index 0000000..3128d92 --- /dev/null +++ b/plugins/third-party-plugin/webpack.config.js @@ -0,0 +1,44 @@ +const defaults = require( '@wordpress/scripts/config/webpack.config' ); +const path = require( 'path' ); + +const defaultExternals = { + react: 'React', + 'react-dom': 'ReactDOM', + 'wpgraphql-ide': 'window.WPGraphQLIDE', +} + +// Define a mapping of entries to their respective externals +const entryExternals = { + setup: { + ...defaultExternals + }, + index: { + ...defaultExternals, + GraphiQL: 'GraphiQL', + }, + // Define externals for other entries as needed +}; + +module.exports = { + ...defaults, + entry: { + index: path.resolve( process.cwd(), 'src', 'index.js' ), + }, + externals: ({context, request}, callback) => { + // Determine the current entry from context or other means + const currentEntry = determineCurrentEntry(context); + // Apply the externals based on the current entry + if (entryExternals[currentEntry] && entryExternals[currentEntry][request]) { + return callback(null, entryExternals[currentEntry][request]); + } + // Fallback to default behavior if no externals are defined for the current entry + callback(); + }, +}; + +function determineCurrentEntry(context) { + // Implement logic to determine the current entry based on context + // This might involve checking the context path to infer which entry is being processed + // Placeholder implementation: + return 'index'; // Replace with actual logic to determine the entry +} From a9d026260db15b1a94601010c42f53b602cfadc7 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 28 May 2024 12:34:53 -0600 Subject: [PATCH 2/9] - GraphQL is in different realms --- plugins/third-party-plugin/package-lock.json | 1434 +---------------- plugins/third-party-plugin/package.json | 2 - .../src/components/Explorer.js | 6 +- .../src/components/QueryComposer.js | 21 +- plugins/third-party-plugin/src/index.js | 30 +- plugins/third-party-plugin/webpack.config.js | 15 +- src/graphql.js | 2 + src/index.js | 34 +- src/render.js | 28 + webpack.config.js | 15 + wpgraphql-ide.php | 28 +- 11 files changed, 150 insertions(+), 1465 deletions(-) create mode 100644 src/graphql.js create mode 100644 src/render.js create mode 100644 webpack.config.js diff --git a/plugins/third-party-plugin/package-lock.json b/plugins/third-party-plugin/package-lock.json index 3d85407..aff8169 100644 --- a/plugins/third-party-plugin/package-lock.json +++ b/plugins/third-party-plugin/package-lock.json @@ -8,10 +8,8 @@ "name": "third-party-plugin", "version": "1.0.0", "dependencies": { - "@graphiql/plugin-explorer": "^3.0.1", "@wordpress/data": "^9.26.0", "@wordpress/element": "^5.33.0", - "graphql": "^15.8.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -2019,37 +2017,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@codemirror/language": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.0.0.tgz", - "integrity": "sha512-rtjk5ifyMzOna1c7PBu7J1VCt0PvA5wy3o8eMVnxMKb7z8KA7JFecvD04dSn14vj/bBaAbqRsGed5OjtofEnLA==", - "peer": true, - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/state": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", - "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", - "peer": true - }, - "node_modules/@codemirror/view": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz", - "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", - "peer": true, - "dependencies": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, "node_modules/@csstools/selector-specificity": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", @@ -2075,23 +2042,6 @@ "node": ">=10.0.0" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "optional": true, - "peer": true, - "dependencies": { - "@emotion/memoize": "0.7.4" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", - "optional": true, - "peer": true - }, "node_modules/@es-joy/jsdoccomment": { "version": "0.41.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", @@ -2241,168 +2191,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", - "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", - "peer": true, - "dependencies": { - "@floating-ui/utils": "^0.2.0" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", - "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", - "peer": true, - "dependencies": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", - "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", - "peer": true, - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", - "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==", - "peer": true - }, - "node_modules/@graphiql/plugin-explorer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@graphiql/plugin-explorer/-/plugin-explorer-3.0.1.tgz", - "integrity": "sha512-d8GE+5qXOwGHC01lw/vUlWurvcSdJbDKxiXUNJAtr+45/o2X8cLflOThavEjsTD8O400UbjG9kiI7n97zw7cKA==", - "dependencies": { - "graphiql-explorer": "^0.9.0" - }, - "peerDependencies": { - "@graphiql/react": "^0.22.1", - "graphql": "^15.5.0 || ^16.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" - } - }, - "node_modules/@graphiql/plugin-explorer/node_modules/graphiql-explorer": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/graphiql-explorer/-/graphiql-explorer-0.9.0.tgz", - "integrity": "sha512-fZC/wsuatqiQDO2otchxriFO0LaWIo/ovF/CQJ1yOudmY0P7pzDiP+l9CEHUiWbizk3e99x6DQG4XG1VxA+d6A==", - "peerDependencies": { - "graphql": "^0.6.0 || ^0.7.0 || ^0.8.0-b || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0", - "react": "^15.6.0 || ^16.0.0", - "react-dom": "^15.6.0 || ^16.0.0" - } - }, - "node_modules/@graphiql/react": { - "version": "0.22.1", - "resolved": "https://registry.npmjs.org/@graphiql/react/-/react-0.22.1.tgz", - "integrity": "sha512-PBClhO2juCvVvmE5qD4PHivJLkhp0dqIX1zgId8Z83UCKpxO2M+bEspRL9aOQQaE4F4xqExCUk5B2AL+wc+agg==", - "peer": true, - "dependencies": { - "@graphiql/toolkit": "^0.9.1", - "@headlessui/react": "^1.7.15", - "@radix-ui/react-dialog": "^1.0.4", - "@radix-ui/react-dropdown-menu": "^2.0.5", - "@radix-ui/react-tooltip": "^1.0.6", - "@radix-ui/react-visually-hidden": "^1.0.3", - "@types/codemirror": "^5.60.8", - "clsx": "^1.2.1", - "codemirror": "^5.65.3", - "codemirror-graphql": "^2.0.11", - "copy-to-clipboard": "^3.2.0", - "framer-motion": "^6.5.1", - "graphql-language-service": "^5.2.0", - "markdown-it": "^14.1.0", - "set-value": "^4.1.0" - }, - "peerDependencies": { - "graphql": "^15.5.0 || ^16.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" - } - }, - "node_modules/@graphiql/react/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true - }, - "node_modules/@graphiql/react/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@graphiql/react/node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "peer": true, - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/@graphiql/react/node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "peer": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/@graphiql/react/node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "peer": true - }, - "node_modules/@graphiql/react/node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "peer": true - }, - "node_modules/@graphiql/toolkit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.9.1.tgz", - "integrity": "sha512-LVt9pdk0830so50ZnU2Znb2rclcoWznG8r8asqAENzV0U1FM1kuY0sdPpc/rBc9MmmNgnB6A+WZzDhq6dbhTHA==", - "peer": true, - "dependencies": { - "@n1ru4l/push-pull-async-iterable-iterator": "^3.1.0", - "meros": "^1.1.4" - }, - "peerDependencies": { - "graphql": "^15.5.0 || ^16.0.0", - "graphql-ws": ">= 4.5.0" - }, - "peerDependenciesMeta": { - "graphql-ws": { - "optional": true - } - } - }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -2418,23 +2206,6 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@headlessui/react": { - "version": "1.7.19", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz", - "integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==", - "peer": true, - "dependencies": { - "@tanstack/react-virtual": "^3.0.0-beta.60", - "client-only": "^0.0.1" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -3010,103 +2781,6 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, - "node_modules/@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", - "peer": true - }, - "node_modules/@lezer/highlight": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", - "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", - "peer": true, - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", - "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", - "peer": true, - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@motionone/animation": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.17.0.tgz", - "integrity": "sha512-ANfIN9+iq1kGgsZxs+Nz96uiNcPLGTXwfNo2Xz/fcJXniPYpaz/Uyrfa+7I5BPLxCP82sh7quVDudf1GABqHbg==", - "peer": true, - "dependencies": { - "@motionone/easing": "^10.17.0", - "@motionone/types": "^10.17.0", - "@motionone/utils": "^10.17.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/dom": { - "version": "10.12.0", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", - "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", - "peer": true, - "dependencies": { - "@motionone/animation": "^10.12.0", - "@motionone/generators": "^10.12.0", - "@motionone/types": "^10.12.0", - "@motionone/utils": "^10.12.0", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/easing": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.17.0.tgz", - "integrity": "sha512-Bxe2wSuLu/qxqW4rBFS5m9tMLOw+QBh8v5A7Z5k4Ul4sTj5jAOfZG5R0bn5ywmk+Fs92Ij1feZ5pmC4TeXA8Tg==", - "peer": true, - "dependencies": { - "@motionone/utils": "^10.17.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/generators": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.17.0.tgz", - "integrity": "sha512-T6Uo5bDHrZWhIfxG/2Aut7qyWQyJIWehk6OB4qNvr/jwA/SRmixwbd7SOrxZi1z5rH3LIeFFBKK1xHnSbGPZSQ==", - "peer": true, - "dependencies": { - "@motionone/types": "^10.17.0", - "@motionone/utils": "^10.17.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/types": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.0.tgz", - "integrity": "sha512-EgeeqOZVdRUTEHq95Z3t8Rsirc7chN5xFAPMYFobx8TPubkEfRSm5xihmMUkbaR2ErKJTUw3347QDPTHIW12IA==", - "peer": true - }, - "node_modules/@motionone/utils": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.17.0.tgz", - "integrity": "sha512-bGwrki4896apMWIj9yp5rAS2m0xyhxblg6gTB/leWDPt+pb410W8lYWsxyurX+DH+gO1zsQsfx2su/c1/LtTpg==", - "peer": true, - "dependencies": { - "@motionone/types": "^10.17.0", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@n1ru4l/push-pull-async-iterable-iterator": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz", - "integrity": "sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==", - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -3273,682 +2947,32 @@ } }, "node_modules/@puppeteer/browsers/node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/@puppeteer/browsers/node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - } - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", - "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", - "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", - "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", - "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", - "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", - "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", - "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-menu": "2.0.6", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", - "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", - "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", - "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", - "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", - "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", - "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", - "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", - "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", - "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", - "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", - "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-visually-hidden": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", - "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", - "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", - "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", - "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", - "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", - "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", - "peer": true, + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, - "node_modules/@radix-ui/rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", - "peer": true, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, "node_modules/@sentry/core": { @@ -4419,33 +3443,6 @@ "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==" }, - "node_modules/@tanstack/react-virtual": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz", - "integrity": "sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==", - "peer": true, - "dependencies": { - "@tanstack/virtual-core": "3.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz", - "integrity": "sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, "node_modules/@testing-library/dom": { "version": "9.3.4", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", @@ -4706,15 +3703,6 @@ "@types/responselike": "^1.0.0" } }, - "node_modules/@types/codemirror": { - "version": "5.60.15", - "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz", - "integrity": "sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==", - "peer": true, - "dependencies": { - "@types/tern": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -4757,7 +3745,8 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.21", @@ -4906,7 +3895,7 @@ "version": "20.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "devOptional": true, + "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -5044,15 +4033,6 @@ "integrity": "sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==", "dev": true }, - "node_modules/@types/tern": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", - "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", - "peer": true, - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -6649,18 +5629,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", - "peer": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -7977,12 +6945,6 @@ "node": ">= 10" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "peer": true - }, "node_modules/clipboard": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", @@ -8063,36 +7025,6 @@ "node": ">= 0.12.0" } }, - "node_modules/codemirror": { - "version": "5.65.16", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz", - "integrity": "sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==", - "peer": true - }, - "node_modules/codemirror-graphql": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-2.0.11.tgz", - "integrity": "sha512-j1QDDXKVkpin2VsyS0ke2nAhKal6/N1UJtgnBGrPe3gj9ZSP6/K8Xytft94k0xW6giIU/JhZjvW0GwwERNzbFA==", - "peer": true, - "dependencies": { - "@types/codemirror": "^0.0.90", - "graphql-language-service": "5.2.0" - }, - "peerDependencies": { - "@codemirror/language": "6.0.0", - "codemirror": "^5.65.3", - "graphql": "^15.5.0 || ^16.0.0" - } - }, - "node_modules/codemirror-graphql/node_modules/@types/codemirror": { - "version": "0.0.90", - "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.90.tgz", - "integrity": "sha512-8Z9+tSg27NPRGubbUPUCrt5DDG/OWzLph5BvcDykwR5D7RyZh5mhHG0uS1ePKV1YFCA+/cwc4Ey2AJAEFfV3IA==", - "peer": true, - "dependencies": { - "@types/tern": "*" - } - }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", @@ -8439,15 +7371,6 @@ "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", "dev": true }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "peer": true, - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, "node_modules/copy-webpack-plugin": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", @@ -9507,12 +8430,6 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "peer": true - }, "node_modules/devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", @@ -9796,6 +8713,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -11708,36 +10626,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/framer-motion": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", - "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", - "peer": true, - "dependencies": { - "@motionone/dom": "10.12.0", - "framesync": "6.0.1", - "hey-listen": "^1.0.8", - "popmotion": "11.0.3", - "style-value-types": "5.0.0", - "tslib": "^2.1.0" - }, - "optionalDependencies": { - "@emotion/is-prop-valid": "^0.8.2" - }, - "peerDependencies": { - "react": ">=16.8 || ^17.0.0 || ^18.0.0", - "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/framesync": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", - "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", - "peer": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -11896,15 +10784,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -12195,30 +11074,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/graphql": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", - "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/graphql-language-service": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.2.0.tgz", - "integrity": "sha512-o/ZgTS0pBxWm3hSF4+6GwiV1//DxzoLWEbS38+jqpzzy1d/QXBidwQuVYTOksclbtOJZ3KR/tZ8fi/tI6VpVMg==", - "peer": true, - "dependencies": { - "nullthrows": "^1.0.0", - "vscode-languageserver-types": "^3.17.1" - }, - "bin": { - "graphql": "dist/temp-bin.js" - }, - "peerDependencies": { - "graphql": "^15.5.0 || ^16.0.0" - } - }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -12339,12 +11194,6 @@ "tslib": "^2.0.3" } }, - "node_modules/hey-listen": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", - "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", - "peer": true - }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -12926,15 +11775,6 @@ "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", "dev": true }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -13348,6 +12188,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -13361,15 +12202,6 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, - "node_modules/is-primitive": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", - "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -13570,6 +12402,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -16114,23 +14947,6 @@ "node": ">= 8" } }, - "node_modules/meros": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", - "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", - "peer": true, - "engines": { - "node": ">=13" - }, - "peerDependencies": { - "@types/node": ">=13" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, "node_modules/metaviewport-parser": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", @@ -16793,12 +15609,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "peer": true - }, "node_modules/nwsapi": { "version": "2.2.9", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", @@ -17627,18 +16437,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/popmotion": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", - "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", - "peer": true, - "dependencies": { - "framesync": "6.0.1", - "hey-listen": "^1.0.8", - "style-value-types": "5.0.0", - "tslib": "^2.1.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -18531,15 +17329,6 @@ "node": ">=6" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/puppeteer-core": { "version": "13.7.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz", @@ -18769,76 +17558,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-remove-scroll": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", - "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", - "peer": true, - "dependencies": { - "react-remove-scroll-bar": "^2.3.3", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", - "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", - "peer": true, - "dependencies": { - "react-style-singleton": "^2.2.1", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", - "peer": true, - "dependencies": { - "get-nonce": "^1.0.0", - "invariant": "^2.2.4", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -19735,24 +18454,6 @@ "node": ">= 0.4" } }, - "node_modules/set-value": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-4.1.0.tgz", - "integrity": "sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==", - "funding": [ - "https://github.com/sponsors/jonschlinkert", - "https://paypal.me/jonathanschlinkert", - "https://jonschlinkert.dev/sponsor" - ], - "peer": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "is-primitive": "^3.0.1" - }, - "engines": { - "node": ">=11.0" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -20535,28 +19236,12 @@ "node": ">=0.8.0" } }, - "node_modules/style-mod": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", - "peer": true - }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "dev": true }, - "node_modules/style-value-types": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", - "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", - "peer": true, - "dependencies": { - "hey-listen": "^1.0.8", - "tslib": "^2.1.0" - } - }, "node_modules/stylehacks": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", @@ -21147,12 +19832,6 @@ "node": ">=8.0" } }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", - "peer": true - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -21491,7 +20170,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true + "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -21655,27 +20334,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/use-callback-ref": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", - "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", - "peer": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/use-memo-one": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", @@ -21684,28 +20342,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/use-sidecar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", - "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", - "peer": true, - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -21791,18 +20427,6 @@ "node": ">= 0.8" } }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "peer": true - }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "peer": true - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/plugins/third-party-plugin/package.json b/plugins/third-party-plugin/package.json index 270fec2..f6f3f97 100644 --- a/plugins/third-party-plugin/package.json +++ b/plugins/third-party-plugin/package.json @@ -41,10 +41,8 @@ "sort-package-json": "^2.7.0" }, "dependencies": { - "@graphiql/plugin-explorer": "^3.0.1", "@wordpress/data": "^9.26.0", "@wordpress/element": "^5.33.0", - "graphql": "^15.8.0", "react": "^18.3.1", "react-dom": "^18.3.1" } diff --git a/plugins/third-party-plugin/src/components/Explorer.js b/plugins/third-party-plugin/src/components/Explorer.js index e11f7fd..3db9cb6 100644 --- a/plugins/third-party-plugin/src/components/Explorer.js +++ b/plugins/third-party-plugin/src/components/Explorer.js @@ -1,8 +1,6 @@ import React from 'react'; -// import { GraphQL } from 'wpgraphql-ide'; - -import { +const { getNamedType, GraphQLObjectType, isEnumType, @@ -19,7 +17,7 @@ import { print, parseType, visit, -} from 'graphql'; +} = window.WPGraphQLIDE.GraphQL; function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1); diff --git a/plugins/third-party-plugin/src/components/QueryComposer.js b/plugins/third-party-plugin/src/components/QueryComposer.js index 8766082..dfde51a 100644 --- a/plugins/third-party-plugin/src/components/QueryComposer.js +++ b/plugins/third-party-plugin/src/components/QueryComposer.js @@ -1,5 +1,5 @@ import { useSelect } from '@wordpress/data'; -import Explorer from './Explorer' +import { Suspense, lazy } from '@wordpress/element'; export const QueryComposer = () => { @@ -11,13 +11,24 @@ export const QueryComposer = () => { select( 'wpgraphql-ide/app' ).getQuery() ); + const Explorer = lazy(() => import('./Explorer')); + + console.log( { + queryComposer: { + WPGraphQLIDE: window.WPGraphQLIDE + } + }) + return ( <> Query Composer... - + Loading...}> + + + {/*
{JSON.stringify( window.WPGraphQLIDE, null, 2 )}
*/} ); } diff --git a/plugins/third-party-plugin/src/index.js b/plugins/third-party-plugin/src/index.js index 8da5bf0..4cd63b4 100644 --- a/plugins/third-party-plugin/src/index.js +++ b/plugins/third-party-plugin/src/index.js @@ -5,18 +5,23 @@ import { explorerPlugin } from '@graphiql/plugin-explorer'; import { addAction } from '@wordpress/hooks'; import {QueryComposer} from "./components/QueryComposer"; -addAction( 'wpgraphqlide_rendered', 'third-party', () => { - if ( ! window.WPGraphQLIDE || ! window.WPGraphQLIDE.GraphQL ) { +console.log( 'Third Party Plugin loading...' ); + +window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { + console.log( 'Third Party Plugin Loaded' ); + + if ( ! window.WPGraphQLIDE.GraphQL ) { + console.log( `GraphQL Library not loaded` ); + console.log( window?.WPGraphQLIDE ); return; } - console.log({ - message: 'Third Party Plugin Loaded', - WPGraphQL: window.WPGraphQLIDE || null, - }) + const { registerActivityBarPanel } = window.WPGraphQLIDE || {}; if ( typeof registerActivityBarPanel === 'function' ) { + console.log( `Registering Mock Explorer Panel`); + registerActivityBarPanel( 'query-composer', () => { return { title: 'Query Composer', @@ -33,12 +38,15 @@ addAction( 'wpgraphqlide_rendered', 'third-party', () => { } else { console.log( 'CANNOT Registering Mock Explorer Panel' ); } -} ); -console.log( { - message: 'Third Party Plugin Loaded', - WPGraphQL: window.WPGraphQLIDE || null, -}) + // Perform your desired actions here +}); + + + + + + // return; // diff --git a/plugins/third-party-plugin/webpack.config.js b/plugins/third-party-plugin/webpack.config.js index 3128d92..f0cc19a 100644 --- a/plugins/third-party-plugin/webpack.config.js +++ b/plugins/third-party-plugin/webpack.config.js @@ -1,20 +1,15 @@ -const defaults = require( '@wordpress/scripts/config/webpack.config' ); -const path = require( 'path' ); +const defaults = require('@wordpress/scripts/config/webpack.config'); +const path = require('path'); const defaultExternals = { react: 'React', 'react-dom': 'ReactDOM', - 'wpgraphql-ide': 'window.WPGraphQLIDE', -} +}; // Define a mapping of entries to their respective externals const entryExternals = { - setup: { - ...defaultExternals - }, index: { ...defaultExternals, - GraphiQL: 'GraphiQL', }, // Define externals for other entries as needed }; @@ -22,9 +17,9 @@ const entryExternals = { module.exports = { ...defaults, entry: { - index: path.resolve( process.cwd(), 'src', 'index.js' ), + index: path.resolve(process.cwd(), 'src', 'index.js'), }, - externals: ({context, request}, callback) => { + externals: ({ context, request }, callback) => { // Determine the current entry from context or other means const currentEntry = determineCurrentEntry(context); // Apply the externals based on the current entry diff --git a/src/graphql.js b/src/graphql.js new file mode 100644 index 0000000..3031c5d --- /dev/null +++ b/src/graphql.js @@ -0,0 +1,2 @@ +import * as GraphQL from 'graphql/index.js'; +export default GraphQL; diff --git a/src/index.js b/src/index.js index de429ce..83f8539 100644 --- a/src/index.js +++ b/src/index.js @@ -6,12 +6,11 @@ // External dependencies import { createRoot } from '@wordpress/element'; -import * as GraphQL from 'graphql/index.js'; +import GraphQL from './graphql.js'; import * as accessFunctions from './access-functions'; // Local imports including the hook configuration and the main App component. import hooks from './wordpress-hooks'; -import AppWrapper from './components/AppWrapper'; import { registerStores } from './stores'; import { initializeRegistry } from './registry'; @@ -33,25 +32,20 @@ init(); */ window.WPGraphQLIDE = { hooks, - GraphQL, ...accessFunctions, + GraphQL }; -/** - * Get our root element id from the localized script. - */ -const { rootElementId } = window.WPGRAPHQL_IDE_DATA; +window.dispatchEvent( new Event( 'WPGraphQLIDE_Window_Ready' ) ); +// +// // Dynamically import the GraphQL library and assign it to `window.WPGraphQLIDE.GraphQL` +// import('graphql/index.js').then(GraphQL => { +// window.WPGraphQLIDE.GraphQL = GraphQL; +// window.WPGraphQLIDE.GraphQLLoaded = true; +// console.log( `WPGraphQLIDE is ready` ); +// window.dispatchEvent( new Event( 'WPGraphQLIDE_Window_Ready' ) ); +// }).catch(error => { +// console.error('Failed to load GraphQL library:', error); +// }); + -/** - * Attempts to render the React application to a specified mount point in the DOM. - * Logs an error to the console if the mount point is missing. - */ -const appMountPoint = document.getElementById( rootElementId ); -if ( appMountPoint ) { - createRoot( appMountPoint ).render( ); - window.dispatchEvent( new Event( 'WPGraphQLIDEReady' ) ); -} else { - console.error( - `WPGraphQL IDE mount point not found. Please ensure an element with ID "${rootElementId}" exists.` - ); -} diff --git a/src/render.js b/src/render.js new file mode 100644 index 0000000..38c6dfa --- /dev/null +++ b/src/render.js @@ -0,0 +1,28 @@ +import {createRoot} from "@wordpress/element"; +import AppWrapper from "./components/AppWrapper"; + +window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { + + /** + * Get our root element id from the localized script. + */ + const { rootElementId } = window.WPGRAPHQL_IDE_DATA; + + /** + * Attempts to render the React application to a specified mount point in the DOM. + * Logs an error to the console if the mount point is missing. + */ + const appMountPoint = document.getElementById( rootElementId ); + if ( appMountPoint ) { + console.log( `RENDER....` ) + createRoot( appMountPoint ).render( ); + window.dispatchEvent( new Event( 'WPGraphQLIDEReady' ) ); + } else { + console.error( + `WPGraphQL IDE mount point not found. Please ensure an element with ID "${rootElementId}" exists.` + ); + } + +}); + + diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..601e601 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +const defaults = require("@wordpress/scripts/config/webpack.config"); +const path = require("path"); + + +module.exports = { + ...defaults, + entry: { + index: path.resolve(process.cwd(), "src", "index.js"), + render: path.resolve(process.cwd(), "src", "render.js"), + }, + externals: { + react: "React", + "react-dom": "ReactDOM" + }, +}; diff --git a/wpgraphql-ide.php b/wpgraphql-ide.php index 8b3dd39..6be1b55 100644 --- a/wpgraphql-ide.php +++ b/wpgraphql-ide.php @@ -245,6 +245,7 @@ function enqueue_react_app_with_styles(): void { } $asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/index.asset.php'; + $render_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/render.asset.php'; $app_context = get_app_context(); @@ -256,24 +257,35 @@ function enqueue_react_app_with_styles(): void { false ); + $localized_data = [ + 'nonce' => wp_create_nonce( 'wp_rest' ), + 'graphqlEndpoint' => trailingslashit( site_url() ) . 'index.php?' . \WPGraphQL\Router::$route, + 'rootElementId' => WPGRAPHQL_IDE_ROOT_ELEMENT_ID, + 'context' => $app_context, + 'isDedicatedIdePage' => current_screen_is_dedicated_ide_page(), + 'dedicatedIdeBaseUrl' => get_dedicated_ide_base_url(), + ]; + wp_localize_script( 'wpgraphql-ide', 'WPGRAPHQL_IDE_DATA', - [ - 'nonce' => wp_create_nonce( 'wp_rest' ), - 'graphqlEndpoint' => trailingslashit( site_url() ) . 'index.php?' . \WPGraphQL\Router::$route, - 'rootElementId' => WPGRAPHQL_IDE_ROOT_ELEMENT_ID, - 'context' => $app_context, - 'isDedicatedIdePage' => current_screen_is_dedicated_ide_page(), - 'dedicatedIdeBaseUrl' => get_dedicated_ide_base_url(), - ] + $localized_data ); // Extensions looking to extend GraphiQL can hook in here, // after the window object is established, but before the App renders do_action( 'wpgraphqlide_enqueue_script', $app_context ); + wp_enqueue_script( + 'wpgraphql-ide-render', + plugins_url( 'build/render.js', __FILE__ ), + $render_asset_file['dependencies'], + $render_asset_file['version'], + false + ); + wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $asset_file['version'] ); // Avoid running custom styles through a build process for an improved developer experience. wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $asset_file['version'] ); From 70994b162ac316102675f9d54765573a6b756d56 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 28 May 2024 14:53:43 -0600 Subject: [PATCH 3/9] - update graphql to be its own dependency --- .../third-party-plugin/src/components/Explorer.js | 4 ++-- .../src/components/QueryComposer.js | 1 - plugins/third-party-plugin/src/index.js | 6 +++--- plugins/third-party-plugin/webpack.config.js | 1 + src/graphql.js | 2 +- src/index.js | 4 +--- webpack.config.js | 4 +++- wpgraphql-ide.php | 13 +++++++++++-- 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/plugins/third-party-plugin/src/components/Explorer.js b/plugins/third-party-plugin/src/components/Explorer.js index 3db9cb6..805cce1 100644 --- a/plugins/third-party-plugin/src/components/Explorer.js +++ b/plugins/third-party-plugin/src/components/Explorer.js @@ -1,6 +1,6 @@ import React from 'react'; -const { +import { getNamedType, GraphQLObjectType, isEnumType, @@ -17,7 +17,7 @@ const { print, parseType, visit, -} = window.WPGraphQLIDE.GraphQL; +} from 'graphql'; function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1); diff --git a/plugins/third-party-plugin/src/components/QueryComposer.js b/plugins/third-party-plugin/src/components/QueryComposer.js index dfde51a..e26740a 100644 --- a/plugins/third-party-plugin/src/components/QueryComposer.js +++ b/plugins/third-party-plugin/src/components/QueryComposer.js @@ -21,7 +21,6 @@ export const QueryComposer = () => { return ( <> - Query Composer... Loading...}> Date: Tue, 28 May 2024 17:22:01 -0400 Subject: [PATCH 4/9] script alias --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6feb6b3..1022895 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ }, "scripts": { "check-engines": "wp-scripts check-engines", - "build": "wp-scripts build && npm run build:zip", + "build": "wp-scripts build && npm run build:third-party-plugin && npm run build:zip", + "build:third-party-plugin": "wp-scripts build --webpack-src-dir=plugins/third-party-plugin", "build:zip": "wp-scripts plugin-zip", "start": "wp-scripts start", + "start:third-party-plugin": "wp-scripts start --webpack-src-dir=plugins/third-party-plugin", "pretest:e2e": "npm run wp-env start", "pretest:e2e:ui": "npm run wp-env start", "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js", From 03dff8dc58712b5415bc4931bafa382cb4e018b1 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 29 May 2024 16:32:02 -0600 Subject: [PATCH 5/9] - fix third-party style enqueue - update third-party index - split Explorer into its own components - move Explorer utils into its own file - simplify App.jsx - move Query Composer styles from main plugin into 3rd party --- .../src/components/AbstractArgView.jsx | 385 +++ .../src/components/AbstractView.jsx | 129 + .../src/components/ArgView.jsx | 178 ++ .../src/components/ArrowClosed.jsx | 18 + .../src/components/ArrowOpen.jsx | 18 + .../src/components/Checkbox.jsx | 71 + .../src/components/DefaultArrowClosed.jsx | 9 + .../src/components/DefaultArrowOpen.jsx | 9 + .../src/components/ErrorBoundary.jsx | 28 + .../src/components/Explorer.js | 2479 ----------------- .../src/components/ExplorerView.jsx | 522 ++++ .../src/components/ExplorerWrapper.jsx | 46 + .../src/components/FieldView.jsx | 410 +++ .../src/components/FragmentView.jsx | 62 + .../src/components/InputArgView.jsx | 184 ++ .../src/components/QueryComposer.js | 75 +- .../src/components/RootView.jsx | 218 ++ .../src/components/ScalarInput.jsx | 55 + plugins/third-party-plugin/src/index.js | 58 +- plugins/third-party-plugin/src/style.css | 77 + plugins/third-party-plugin/src/utils.js | 349 +++ .../third-party-plugin/third-party-plugin.php | 12 +- src/components/App.jsx | 80 +- styles/explorer.css | 0 styles/wpgraphql-ide.css | 76 - 25 files changed, 2862 insertions(+), 2686 deletions(-) create mode 100644 plugins/third-party-plugin/src/components/AbstractArgView.jsx create mode 100644 plugins/third-party-plugin/src/components/AbstractView.jsx create mode 100644 plugins/third-party-plugin/src/components/ArgView.jsx create mode 100644 plugins/third-party-plugin/src/components/ArrowClosed.jsx create mode 100644 plugins/third-party-plugin/src/components/ArrowOpen.jsx create mode 100644 plugins/third-party-plugin/src/components/Checkbox.jsx create mode 100644 plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx create mode 100644 plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx create mode 100644 plugins/third-party-plugin/src/components/ErrorBoundary.jsx delete mode 100644 plugins/third-party-plugin/src/components/Explorer.js create mode 100644 plugins/third-party-plugin/src/components/ExplorerView.jsx create mode 100644 plugins/third-party-plugin/src/components/ExplorerWrapper.jsx create mode 100644 plugins/third-party-plugin/src/components/FieldView.jsx create mode 100644 plugins/third-party-plugin/src/components/FragmentView.jsx create mode 100644 plugins/third-party-plugin/src/components/InputArgView.jsx create mode 100644 plugins/third-party-plugin/src/components/RootView.jsx create mode 100644 plugins/third-party-plugin/src/components/ScalarInput.jsx create mode 100644 plugins/third-party-plugin/src/style.css create mode 100644 plugins/third-party-plugin/src/utils.js delete mode 100644 styles/explorer.css diff --git a/plugins/third-party-plugin/src/components/AbstractArgView.jsx b/plugins/third-party-plugin/src/components/AbstractArgView.jsx new file mode 100644 index 0000000..b8ddb99 --- /dev/null +++ b/plugins/third-party-plugin/src/components/AbstractArgView.jsx @@ -0,0 +1,385 @@ +import React from "react"; +import {isRequiredArgument, unwrapInputType} from "../utils"; +import {isEnumType, isInputObjectType, isScalarType, parseType, visit} from "graphql"; +import ScalarInput from "./ScalarInput"; +import InputArgView from "./InputArgView"; +import Checkbox from "./Checkbox"; + +class AbstractArgView extends React.PureComponent { + state = {displayArgActions: false}; + render() { + const {argValue, arg, styleConfig} = this.props; + const argType = unwrapInputType(arg.type); + + let input = null; + if (argValue) { + if (argValue.kind === 'Variable') { + input = ( + + ${argValue.name.value} + + ); + } else if (isScalarType(argType)) { + if (argType.name === 'Boolean') { + input = ( + + ); + } else { + input = ( + + ); + } + } else if (isEnumType(argType)) { + if (argValue.kind === 'EnumValue') { + input = ( + + ); + } else { + console.error( + 'arg mismatch between arg and selection', + argType, + argValue, + ); + } + } else if (isInputObjectType(argType)) { + if (argValue.kind === 'ObjectValue') { + const fields = argType.getFields(); + input = ( +
+ {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ); + } else { + console.error( + 'arg mismatch between arg and selection', + argType, + argValue, + ); + } + } + } + + const variablize = () => { + const baseVariableName = arg.name; + const conflictingNameCount = ( + this.props.definition.variableDefinitions || [] + ).filter(varDef => + varDef.variable.name.value.startsWith(baseVariableName), + ).length; + + let variableName; + if (conflictingNameCount > 0) { + variableName = `${baseVariableName}${conflictingNameCount}`; + } else { + variableName = baseVariableName; + } + const argPrintedType = arg.type.toString(); + const argType = parseType(argPrintedType); + + const base = { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { + kind: 'Name', + value: variableName, + }, + }, + type: argType, + directives: [], + }; + + const variableDefinitionByName = name => + (this.props.definition.variableDefinitions || []).find( + varDef => varDef.variable.name.value === name, + ); + + let variable; + + let subVariableUsageCountByName = {}; + + if (typeof argValue !== 'undefined' && argValue !== null) { + const cleanedDefaultValue = visit(argValue, { + Variable(node) { + const varName = node.name.value; + const varDef = variableDefinitionByName(varName); + + subVariableUsageCountByName[varName] = + subVariableUsageCountByName[varName] + 1 || 1; + + if (!varDef) { + return; + } + + return varDef.defaultValue; + }, + }); + + const isNonNullable = base.type.kind === 'NonNullType'; + + const unwrappedBase = isNonNullable + ? {...base, type: base.type.type} + : base; + + variable = {...unwrappedBase, defaultValue: cleanedDefaultValue}; + } else { + variable = base; + } + + const newlyUnusedVariables = Object.entries(subVariableUsageCountByName) + .filter(([_, usageCount]) => usageCount < 2) + .map(([varName, _]) => varName); + + if (variable) { + const newDoc = this.props.setArgValue(variable, false); + + if (newDoc) { + const targetOperation = newDoc.definitions.find(definition => { + if ( + !!definition.operation && + !!definition.name && + !!definition.name.value && + !!this.props.definition.name && + !!this.props.definition.name.value + ) { + return definition.name.value === this.props.definition.name.value; + } else { + return false; + } + }); + + const newVariableDefinitions = [ + ...(targetOperation.variableDefinitions || []), + variable, + ].filter( + varDef => + newlyUnusedVariables.indexOf(varDef.variable.name.value) === -1, + ); + + const newOperation = { + ...targetOperation, + variableDefinitions: newVariableDefinitions, + }; + + const existingDefs = newDoc.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + const finalDoc = { + ...newDoc, + definitions: newDefinitions, + }; + + this.props.onCommit(finalDoc); + } + } + }; + + const devariablize = () => { + if (!argValue || !argValue.name || !argValue.name.value) { + return; + } + + const variableName = argValue.name.value; + const variableDefinition = ( + this.props.definition.variableDefinitions || [] + ).find(varDef => varDef.variable.name.value === variableName); + + if (!variableDefinition) { + return; + } + + const defaultValue = variableDefinition.defaultValue; + + const newDoc = this.props.setArgValue(defaultValue, { + commit: false, + }); + + if (newDoc) { + const targetOperation = newDoc.definitions.find( + definition => + definition.name.value === this.props.definition.name.value, + ); + + if (!targetOperation) { + return; + } + + let variableUseCount = 0; + + visit(targetOperation, { + Variable(node) { + if (node.name.value === variableName) { + variableUseCount = variableUseCount + 1; + } + }, + }); + + let newVariableDefinitions = targetOperation.variableDefinitions || []; + + if (variableUseCount < 2) { + newVariableDefinitions = newVariableDefinitions.filter( + varDef => varDef.variable.name.value !== variableName, + ); + } + + const newOperation = { + ...targetOperation, + variableDefinitions: newVariableDefinitions, + }; + + const existingDefs = newDoc.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + const finalDoc = { + ...newDoc, + definitions: newDefinitions, + }; + + this.props.onCommit(finalDoc); + } + }; + + const isArgValueVariable = argValue && argValue.kind === 'Variable'; + + const variablizeActionButton = !this.state.displayArgActions ? null : ( + + ); + + return ( +
+ { + const shouldAdd = !argValue; + if (shouldAdd) { + this.props.addArg(true); + } else { + this.props.removeArg(true); + } + this.setState({displayArgActions: shouldAdd}); + }}> + {isInputObjectType(argType) ? ( + + {!!argValue + ? this.props.styleConfig.arrowOpen + : this.props.styleConfig.arrowClosed} + + ) : ( + + )} + { + if (argValue !== null && typeof argValue !== 'undefined') { + this.setState({displayArgActions: true}); + } + }} + onMouseLeave={() => this.setState({displayArgActions: false})}> + {arg.name} + {isRequiredArgument(arg) ? '*' : ''}: {variablizeActionButton}{' '} + {' '} + + {input || }{' '} +
+ ); + } +} + +export default AbstractArgView; diff --git a/plugins/third-party-plugin/src/components/AbstractView.jsx b/plugins/third-party-plugin/src/components/AbstractView.jsx new file mode 100644 index 0000000..94ed840 --- /dev/null +++ b/plugins/third-party-plugin/src/components/AbstractView.jsx @@ -0,0 +1,129 @@ +import React from "react"; +import Checkbox from "./Checkbox"; + +class AbstractView extends React.PureComponent { + _previousSelection; + _addFragment = () => { + this.props.modifySelections([ + ...this.props.selections, + this._previousSelection || { + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: {kind: 'Name', value: this.props.implementingType.name}, + }, + selectionSet: { + kind: 'SelectionSet', + selections: this.props + .getDefaultFieldNames(this.props.implementingType) + .map(fieldName => ({ + kind: 'Field', + name: {kind: 'Name', value: fieldName}, + })), + }, + }, + ]); + }; + _removeFragment = () => { + const thisSelection = this._getSelection(); + this._previousSelection = thisSelection; + this.props.modifySelections( + this.props.selections.filter(s => s !== thisSelection), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find( + selection => + selection.kind === 'InlineFragment' && + selection.typeCondition && + this.props.implementingType.name === selection.typeCondition.name.value, + ); + if (!selection) { + return null; + } + if (selection.kind === 'InlineFragment') { + return selection; + } + }; + + _modifyChildSelections = (selections, options) => { + const thisSelection = this._getSelection(); + return this.props.modifySelections( + this.props.selections.map(selection => { + if (selection === thisSelection) { + return { + directives: selection.directives, + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: {kind: 'Name', value: this.props.implementingType.name}, + }, + selectionSet: { + kind: 'SelectionSet', + selections, + }, + }; + } + return selection; + }), + options, + ); + }; + + render() { + const { + implementingType, + schema, + getDefaultFieldNames, + styleConfig, + } = this.props; + const selection = this._getSelection(); + const fields = implementingType.getFields(); + const childSelections = selection + ? selection.selectionSet + ? selection.selectionSet.selections + : [] + : []; + + return ( +
+ + + + {this.props.implementingType.name} + + + {selection ? ( +
+ {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ) : null} +
+ ); + } +} + +export default AbstractView; diff --git a/plugins/third-party-plugin/src/components/ArgView.jsx b/plugins/third-party-plugin/src/components/ArgView.jsx new file mode 100644 index 0000000..f7d64b8 --- /dev/null +++ b/plugins/third-party-plugin/src/components/ArgView.jsx @@ -0,0 +1,178 @@ +import React from "react"; +import {coerceArgValue, unwrapInputType} from "../utils"; +import {isInputObjectType, isLeafType} from "graphql"; +import AbstractArgView from "./AbstractArgView"; + +class ArgView extends React.PureComponent { + _previousArgSelection; + _getArgSelection = () => { + const {selection} = this.props; + + return (selection.arguments || []).find( + arg => arg.name.value === this.props.arg.name, + ); + }; + _removeArg = commit => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + this._previousArgSelection = argSelection; + return this.props.modifyArguments( + (selection.arguments || []).filter(arg => arg !== argSelection), + commit, + ); + }; + _addArg = commit => { + const { + selection, + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + arg, + } = this.props; + const argType = unwrapInputType(arg.type); + + let argSelection = null; + if (this._previousArgSelection) { + argSelection = this._previousArgSelection; + } else if (isInputObjectType(argType)) { + const fields = argType.getFields(); + argSelection = { + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + Object.keys(fields).map(k => fields[k]), + ), + }, + }; + } else if (isLeafType(argType)) { + argSelection = { + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: getDefaultScalarArgValue(parentField, arg, argType), + }; + } + + if (!argSelection) { + console.error('Unable to add arg for argType', argType); + return null; + } else { + return this.props.modifyArguments( + [...(selection.arguments || []), argSelection], + commit, + ); + } + }; + _setArgValue = (event, options) => { + let settingToNull = false; + let settingToVariable = false; + let settingToLiteralValue = false; + try { + if (event.kind === 'VariableDefinition') { + settingToVariable = true; + } else if (event === null || typeof event === 'undefined') { + settingToNull = true; + } else if (typeof event.kind === 'string') { + settingToLiteralValue = true; + } + } catch (e) {} + const {selection} = this.props; + const argSelection = this._getArgSelection(); + if (!argSelection && !settingToVariable) { + console.error('missing arg selection when setting arg value'); + return; + } + const argType = unwrapInputType(this.props.arg.type); + + const handleable = + isLeafType(argType) || + settingToVariable || + settingToNull || + settingToLiteralValue; + + if (!handleable) { + console.warn('Unable to handle non leaf types in ArgView._setArgValue'); + return; + } + + let targetValue; + let value; + + if (event === null || typeof event === 'undefined') { + value = null; + } else if (event.target && typeof event.target.value === 'string') { + targetValue = event.target.value; + value = coerceArgValue(argType, targetValue); + } else if (!event.target && event.kind === 'VariableDefinition') { + targetValue = event; + value = targetValue.variable; + } else if (typeof event.kind === 'string') { + value = event; + } + + return this.props.modifyArguments( + (selection.arguments || []).map(a => + a === argSelection + ? { + ...a, + value: value, + } + : a, + ), + options, + ); + }; + + _setArgFields = (fields, commit) => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + if (!argSelection) { + console.error('missing arg selection when setting arg value'); + return; + } + + return this.props.modifyArguments( + (selection.arguments || []).map(a => + a === argSelection + ? { + ...a, + value: { + kind: 'ObjectValue', + fields, + }, + } + : a, + ), + commit, + ); + }; + + render() { + const {arg, parentField} = this.props; + const argSelection = this._getArgSelection(); + + return ( + + ); + } +} + +export default ArgView; diff --git a/plugins/third-party-plugin/src/components/ArrowClosed.jsx b/plugins/third-party-plugin/src/components/ArrowClosed.jsx new file mode 100644 index 0000000..cc6809c --- /dev/null +++ b/plugins/third-party-plugin/src/components/ArrowClosed.jsx @@ -0,0 +1,18 @@ +const ArrowClosed = () => ( + + + +); + +export default ArrowClosed; diff --git a/plugins/third-party-plugin/src/components/ArrowOpen.jsx b/plugins/third-party-plugin/src/components/ArrowOpen.jsx new file mode 100644 index 0000000..dea4667 --- /dev/null +++ b/plugins/third-party-plugin/src/components/ArrowOpen.jsx @@ -0,0 +1,18 @@ +const ArrowOpen = () => ( + + + +); + +export default ArrowOpen; diff --git a/plugins/third-party-plugin/src/components/Checkbox.jsx b/plugins/third-party-plugin/src/components/Checkbox.jsx new file mode 100644 index 0000000..5779873 --- /dev/null +++ b/plugins/third-party-plugin/src/components/Checkbox.jsx @@ -0,0 +1,71 @@ +import React from "react"; + +export const checkboxUnchecked = ( + + + +); + +export const checkboxChecked = ( + + + + +); + +export const defaultCheckboxChecked = ( + + + +); + +export const defaultCheckboxUnchecked = ( + + + +); + +export default function Checkbox(props) { + return props.checked + ? props.styleConfig.checkboxChecked + : props.styleConfig.checkboxUnchecked; +} diff --git a/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx b/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx new file mode 100644 index 0000000..e254e8a --- /dev/null +++ b/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +export default function DefaultArrowOpen(){ + return ( + + + + ); +} diff --git a/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx b/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx new file mode 100644 index 0000000..8089c35 --- /dev/null +++ b/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +export default function DefaultArrowOpen(){ + return ( + + + + ); +} diff --git a/plugins/third-party-plugin/src/components/ErrorBoundary.jsx b/plugins/third-party-plugin/src/components/ErrorBoundary.jsx new file mode 100644 index 0000000..53781ed --- /dev/null +++ b/plugins/third-party-plugin/src/components/ErrorBoundary.jsx @@ -0,0 +1,28 @@ +import React from "react"; + +class ErrorBoundary extends React.Component { + state = {hasError: false, error: null, errorInfo: null}; + + componentDidCatch(error, errorInfo) { + this.setState({hasError: true, error: error, errorInfo: errorInfo}); + console.error('Error in component', error, errorInfo); + } + + render() { + if (this.state.hasError) { + return ( +
+
Something went wrong
+
+ {this.state.error ? this.state.error.toString() : null} +
+ {this.state.errorInfo ? this.state.errorInfo.componentStack : null} +
+
+ ); + } + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/plugins/third-party-plugin/src/components/Explorer.js b/plugins/third-party-plugin/src/components/Explorer.js deleted file mode 100644 index 805cce1..0000000 --- a/plugins/third-party-plugin/src/components/Explorer.js +++ /dev/null @@ -1,2479 +0,0 @@ -import React from 'react'; - -import { - getNamedType, - GraphQLObjectType, - isEnumType, - isInputObjectType, - isInterfaceType, - isLeafType, - isNonNullType, - isObjectType, - isRequiredInputField, - isScalarType, - isUnionType, - isWrappingType, - parse, - print, - parseType, - visit, -} from 'graphql'; - -function capitalize(string) { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -const defaultColors = { - keyword: '#B11A04', - def: '#D2054E', - property: '#1F61A0', - qualifier: '#1C92A9', - attribute: '#8B2BB9', - number: '#2882F9', - string: '#D64292', - builtin: '#D47509', - string2: '#0B7FC7', - variable: '#397D13', - atom: '#CA9800', -}; - -const defaultArrowOpen = ( - - - -); - -const defaultArrowClosed = ( - - - -); - -const defaultCheckboxChecked = ( - - - -); - -const defaultCheckboxUnchecked = ( - - - -); - -function Checkbox(props) { - return props.checked - ? props.styleConfig.checkboxChecked - : props.styleConfig.checkboxUnchecked; -} - -export function defaultValue( - argType, -) { - if (isEnumType(argType)) { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; - } else { - switch (argType.name) { - case 'String': - return {kind: 'StringValue', value: ''}; - case 'Float': - return {kind: 'FloatValue', value: '1.5'}; - case 'Int': - return {kind: 'IntValue', value: '10'}; - case 'Boolean': - return {kind: 'BooleanValue', value: false}; - default: - return {kind: 'StringValue', value: ''}; - } - } -} - -function defaultGetDefaultScalarArgValue( - parentField, - arg, - argType, -) { - return defaultValue(argType); -} - -function defaultGetDefaultFieldNames(type) { - const fields = type.getFields(); - - if (fields['id']) { - const res = ['id']; - if (fields['email']) { - res.push('email'); - } else if (fields['name']) { - res.push('name'); - } - return res; - } - - if (fields['edges']) { - return ['edges']; - } - - if (fields['node']) { - return ['node']; - } - - if (fields['nodes']) { - return ['nodes']; - } - - const leafFieldNames = []; - Object.keys(fields).forEach(fieldName => { - if (isLeafType(fields[fieldName].type)) { - leafFieldNames.push(fieldName); - } - }); - - if (!leafFieldNames.length) { - return ['__typename']; - } - return leafFieldNames.slice(0, 2); -} - -function isRequiredArgument(arg) { - return isNonNullType(arg.type) && arg.defaultValue === undefined; -} - -function unwrapOutputType(outputType) { - let unwrappedType = outputType; - while (isWrappingType(unwrappedType)) { - unwrappedType = unwrappedType.ofType; - } - return unwrappedType; -} - -function unwrapInputType(inputType) { - let unwrappedType = inputType; - while (isWrappingType(unwrappedType)) { - unwrappedType = unwrappedType.ofType; - } - return unwrappedType; -} - -function coerceArgValue(argType, value) { - if (typeof value !== 'string' && value.kind === 'VariableDefinition') { - return value.variable; - } else if (isScalarType(argType)) { - try { - switch (argType.name) { - case 'String': - return { - kind: 'StringValue', - value: String(argType.parseValue(value)), - }; - case 'Float': - return { - kind: 'FloatValue', - value: String(argType.parseValue(parseFloat(value))), - }; - case 'Int': - return { - kind: 'IntValue', - value: String(argType.parseValue(parseInt(value, 10))), - }; - case 'Boolean': - try { - const parsed = JSON.parse(value); - if (typeof parsed === 'boolean') { - return {kind: 'BooleanValue', value: parsed}; - } else { - return {kind: 'BooleanValue', value: false}; - } - } catch (e) { - return { - kind: 'BooleanValue', - value: false, - }; - } - default: - return { - kind: 'StringValue', - value: String(argType.parseValue(value)), - }; - } - } catch (e) { - console.error('error coercing arg value', e, value); - return {kind: 'StringValue', value: value}; - } - } else { - try { - const parsedValue = argType.parseValue(value); - if (parsedValue) { - return {kind: 'EnumValue', value: String(parsedValue)}; - } else { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; - } - } catch (e) { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; - } - } -} - -class InputArgView extends React.PureComponent { - _previousArgSelection; - _getArgSelection = () => { - return this.props.selection.fields.find( - field => field.name.value === this.props.arg.name, - ); - }; - - _removeArg = () => { - const {selection} = this.props; - const argSelection = this._getArgSelection(); - this._previousArgSelection = argSelection; - this.props.modifyFields( - selection.fields.filter(field => field !== argSelection), - true, - ); - }; - - _addArg = () => { - const { - selection, - arg, - getDefaultScalarArgValue, - parentField, - makeDefaultArg, - } = this.props; - const argType = unwrapInputType(arg.type); - - let argSelection = null; - if (this._previousArgSelection) { - argSelection = this._previousArgSelection; - } else if (isInputObjectType(argType)) { - const fields = argType.getFields(); - argSelection = { - kind: 'ObjectField', - name: {kind: 'Name', value: arg.name}, - value: { - kind: 'ObjectValue', - fields: defaultInputObjectFields( - getDefaultScalarArgValue, - makeDefaultArg, - parentField, - Object.keys(fields).map(k => fields[k]), - ), - }, - }; - } else if (isLeafType(argType)) { - argSelection = { - kind: 'ObjectField', - name: {kind: 'Name', value: arg.name}, - value: getDefaultScalarArgValue(parentField, arg, argType), - }; - } - - if (!argSelection) { - console.error('Unable to add arg for argType', argType); - } else { - return this.props.modifyFields( - [...(selection.fields || []), argSelection], - true, - ); - } - }; - - _setArgValue = (event, options) => { - let settingToNull = false; - let settingToVariable = false; - let settingToLiteralValue = false; - try { - if (event.kind === 'VariableDefinition') { - settingToVariable = true; - } else if (event === null || typeof event === 'undefined') { - settingToNull = true; - } else if (typeof event.kind === 'string') { - settingToLiteralValue = true; - } - } catch (e) {} - - const {selection} = this.props; - - const argSelection = this._getArgSelection(); - - if (!argSelection) { - console.error('missing arg selection when setting arg value'); - return; - } - const argType = unwrapInputType(this.props.arg.type); - - const handleable = - isLeafType(argType) || - settingToVariable || - settingToNull || - settingToLiteralValue; - - if (!handleable) { - console.warn( - 'Unable to handle non leaf types in InputArgView.setArgValue', - event, - ); - return; - } - let targetValue; - let value; - - if (event === null || typeof event === 'undefined') { - value = null; - } else if ( - !event.target && - !!event.kind && - event.kind === 'VariableDefinition' - ) { - targetValue = event; - value = targetValue.variable; - } else if (typeof event.kind === 'string') { - value = event; - } else if (event.target && typeof event.target.value === 'string') { - targetValue = event.target.value; - value = coerceArgValue(argType, targetValue); - } - - const newDoc = this.props.modifyFields( - (selection.fields || []).map(field => { - const isTarget = field === argSelection; - const newField = isTarget - ? { - ...field, - value: value, - } - : field; - - return newField; - }), - options, - ); - - return newDoc; - }; - - _modifyChildFields = fields => { - return this.props.modifyFields( - this.props.selection.fields.map(field => - field.name.value === this.props.arg.name - ? { - ...field, - value: { - kind: 'ObjectValue', - fields: fields, - }, - } - : field, - ), - true, - ); - }; - - render() { - const {arg, parentField} = this.props; - const argSelection = this._getArgSelection(); - - return ( - - ); - } -} - -class ArgView extends React.PureComponent { - _previousArgSelection; - _getArgSelection = () => { - const {selection} = this.props; - - return (selection.arguments || []).find( - arg => arg.name.value === this.props.arg.name, - ); - }; - _removeArg = commit => { - const {selection} = this.props; - const argSelection = this._getArgSelection(); - this._previousArgSelection = argSelection; - return this.props.modifyArguments( - (selection.arguments || []).filter(arg => arg !== argSelection), - commit, - ); - }; - _addArg = commit => { - const { - selection, - getDefaultScalarArgValue, - makeDefaultArg, - parentField, - arg, - } = this.props; - const argType = unwrapInputType(arg.type); - - let argSelection = null; - if (this._previousArgSelection) { - argSelection = this._previousArgSelection; - } else if (isInputObjectType(argType)) { - const fields = argType.getFields(); - argSelection = { - kind: 'Argument', - name: {kind: 'Name', value: arg.name}, - value: { - kind: 'ObjectValue', - fields: defaultInputObjectFields( - getDefaultScalarArgValue, - makeDefaultArg, - parentField, - Object.keys(fields).map(k => fields[k]), - ), - }, - }; - } else if (isLeafType(argType)) { - argSelection = { - kind: 'Argument', - name: {kind: 'Name', value: arg.name}, - value: getDefaultScalarArgValue(parentField, arg, argType), - }; - } - - if (!argSelection) { - console.error('Unable to add arg for argType', argType); - return null; - } else { - return this.props.modifyArguments( - [...(selection.arguments || []), argSelection], - commit, - ); - } - }; - _setArgValue = (event, options) => { - let settingToNull = false; - let settingToVariable = false; - let settingToLiteralValue = false; - try { - if (event.kind === 'VariableDefinition') { - settingToVariable = true; - } else if (event === null || typeof event === 'undefined') { - settingToNull = true; - } else if (typeof event.kind === 'string') { - settingToLiteralValue = true; - } - } catch (e) {} - const {selection} = this.props; - const argSelection = this._getArgSelection(); - if (!argSelection && !settingToVariable) { - console.error('missing arg selection when setting arg value'); - return; - } - const argType = unwrapInputType(this.props.arg.type); - - const handleable = - isLeafType(argType) || - settingToVariable || - settingToNull || - settingToLiteralValue; - - if (!handleable) { - console.warn('Unable to handle non leaf types in ArgView._setArgValue'); - return; - } - - let targetValue; - let value; - - if (event === null || typeof event === 'undefined') { - value = null; - } else if (event.target && typeof event.target.value === 'string') { - targetValue = event.target.value; - value = coerceArgValue(argType, targetValue); - } else if (!event.target && event.kind === 'VariableDefinition') { - targetValue = event; - value = targetValue.variable; - } else if (typeof event.kind === 'string') { - value = event; - } - - return this.props.modifyArguments( - (selection.arguments || []).map(a => - a === argSelection - ? { - ...a, - value: value, - } - : a, - ), - options, - ); - }; - - _setArgFields = (fields, commit) => { - const {selection} = this.props; - const argSelection = this._getArgSelection(); - if (!argSelection) { - console.error('missing arg selection when setting arg value'); - return; - } - - return this.props.modifyArguments( - (selection.arguments || []).map(a => - a === argSelection - ? { - ...a, - value: { - kind: 'ObjectValue', - fields, - }, - } - : a, - ), - commit, - ); - }; - - render() { - const {arg, parentField} = this.props; - const argSelection = this._getArgSelection(); - - return ( - - ); - } -} - -function isRunShortcut(event) { - return event.ctrlKey && event.key === 'Enter'; -} - -function canRunOperation(operationName) { - return operationName !== 'FragmentDefinition'; -} - -class ScalarInput extends React.PureComponent { - _ref; - _handleChange = event => { - this.props.setArgValue(event, true); - }; - - componentDidMount() { - const input = this._ref; - const activeElement = document.activeElement; - if ( - input && - activeElement && - !(activeElement instanceof HTMLTextAreaElement) - ) { - input.focus(); - input.setSelectionRange(0, input.value.length); - } - } - - render() { - const {arg, argValue, styleConfig} = this.props; - const argType = unwrapInputType(arg.type); - const value = typeof argValue.value === 'string' ? argValue.value : ''; - const color = - this.props.argValue.kind === 'StringValue' - ? styleConfig.colors.string - : styleConfig.colors.number; - return ( - - {argType.name === 'String' ? '"' : ''} - { - this._ref = ref; - }} - type="text" - onChange={this._handleChange} - value={value} - /> - {argType.name === 'String' ? '"' : ''} - - ); - } -} - -class AbstractArgView extends React.PureComponent { - state = {displayArgActions: false}; - render() { - const {argValue, arg, styleConfig} = this.props; - const argType = unwrapInputType(arg.type); - - let input = null; - if (argValue) { - if (argValue.kind === 'Variable') { - input = ( - - ${argValue.name.value} - - ); - } else if (isScalarType(argType)) { - if (argType.name === 'Boolean') { - input = ( - - ); - } else { - input = ( - - ); - } - } else if (isEnumType(argType)) { - if (argValue.kind === 'EnumValue') { - input = ( - - ); - } else { - console.error( - 'arg mismatch between arg and selection', - argType, - argValue, - ); - } - } else if (isInputObjectType(argType)) { - if (argValue.kind === 'ObjectValue') { - const fields = argType.getFields(); - input = ( -
- {Object.keys(fields) - .sort() - .map(fieldName => ( - - ))} -
- ); - } else { - console.error( - 'arg mismatch between arg and selection', - argType, - argValue, - ); - } - } - } - - const variablize = () => { - const baseVariableName = arg.name; - const conflictingNameCount = ( - this.props.definition.variableDefinitions || [] - ).filter(varDef => - varDef.variable.name.value.startsWith(baseVariableName), - ).length; - - let variableName; - if (conflictingNameCount > 0) { - variableName = `${baseVariableName}${conflictingNameCount}`; - } else { - variableName = baseVariableName; - } - const argPrintedType = arg.type.toString(); - const argType = parseType(argPrintedType); - - const base = { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { - kind: 'Name', - value: variableName, - }, - }, - type: argType, - directives: [], - }; - - const variableDefinitionByName = name => - (this.props.definition.variableDefinitions || []).find( - varDef => varDef.variable.name.value === name, - ); - - let variable; - - let subVariableUsageCountByName = {}; - - if (typeof argValue !== 'undefined' && argValue !== null) { - const cleanedDefaultValue = visit(argValue, { - Variable(node) { - const varName = node.name.value; - const varDef = variableDefinitionByName(varName); - - subVariableUsageCountByName[varName] = - subVariableUsageCountByName[varName] + 1 || 1; - - if (!varDef) { - return; - } - - return varDef.defaultValue; - }, - }); - - const isNonNullable = base.type.kind === 'NonNullType'; - - const unwrappedBase = isNonNullable - ? {...base, type: base.type.type} - : base; - - variable = {...unwrappedBase, defaultValue: cleanedDefaultValue}; - } else { - variable = base; - } - - const newlyUnusedVariables = Object.entries(subVariableUsageCountByName) - .filter(([_, usageCount]) => usageCount < 2) - .map(([varName, _]) => varName); - - if (variable) { - const newDoc = this.props.setArgValue(variable, false); - - if (newDoc) { - const targetOperation = newDoc.definitions.find(definition => { - if ( - !!definition.operation && - !!definition.name && - !!definition.name.value && - !!this.props.definition.name && - !!this.props.definition.name.value - ) { - return definition.name.value === this.props.definition.name.value; - } else { - return false; - } - }); - - const newVariableDefinitions = [ - ...(targetOperation.variableDefinitions || []), - variable, - ].filter( - varDef => - newlyUnusedVariables.indexOf(varDef.variable.name.value) === -1, - ); - - const newOperation = { - ...targetOperation, - variableDefinitions: newVariableDefinitions, - }; - - const existingDefs = newDoc.definitions; - - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { - return newOperation; - } else { - return existingOperation; - } - }); - - const finalDoc = { - ...newDoc, - definitions: newDefinitions, - }; - - this.props.onCommit(finalDoc); - } - } - }; - - const devariablize = () => { - if (!argValue || !argValue.name || !argValue.name.value) { - return; - } - - const variableName = argValue.name.value; - const variableDefinition = ( - this.props.definition.variableDefinitions || [] - ).find(varDef => varDef.variable.name.value === variableName); - - if (!variableDefinition) { - return; - } - - const defaultValue = variableDefinition.defaultValue; - - const newDoc = this.props.setArgValue(defaultValue, { - commit: false, - }); - - if (newDoc) { - const targetOperation = newDoc.definitions.find( - definition => - definition.name.value === this.props.definition.name.value, - ); - - if (!targetOperation) { - return; - } - - let variableUseCount = 0; - - visit(targetOperation, { - Variable(node) { - if (node.name.value === variableName) { - variableUseCount = variableUseCount + 1; - } - }, - }); - - let newVariableDefinitions = targetOperation.variableDefinitions || []; - - if (variableUseCount < 2) { - newVariableDefinitions = newVariableDefinitions.filter( - varDef => varDef.variable.name.value !== variableName, - ); - } - - const newOperation = { - ...targetOperation, - variableDefinitions: newVariableDefinitions, - }; - - const existingDefs = newDoc.definitions; - - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { - return newOperation; - } else { - return existingOperation; - } - }); - - const finalDoc = { - ...newDoc, - definitions: newDefinitions, - }; - - this.props.onCommit(finalDoc); - } - }; - - const isArgValueVariable = argValue && argValue.kind === 'Variable'; - - const variablizeActionButton = !this.state.displayArgActions ? null : ( - - ); - - return ( -
- { - const shouldAdd = !argValue; - if (shouldAdd) { - this.props.addArg(true); - } else { - this.props.removeArg(true); - } - this.setState({displayArgActions: shouldAdd}); - }}> - {isInputObjectType(argType) ? ( - - {!!argValue - ? this.props.styleConfig.arrowOpen - : this.props.styleConfig.arrowClosed} - - ) : ( - - )} - { - if (argValue !== null && typeof argValue !== 'undefined') { - this.setState({displayArgActions: true}); - } - }} - onMouseLeave={() => this.setState({displayArgActions: false})}> - {arg.name} - {isRequiredArgument(arg) ? '*' : ''}: {variablizeActionButton}{' '} - {' '} - - {input || }{' '} -
- ); - } -} - -class AbstractView extends React.PureComponent { - _previousSelection; - _addFragment = () => { - this.props.modifySelections([ - ...this.props.selections, - this._previousSelection || { - kind: 'InlineFragment', - typeCondition: { - kind: 'NamedType', - name: {kind: 'Name', value: this.props.implementingType.name}, - }, - selectionSet: { - kind: 'SelectionSet', - selections: this.props - .getDefaultFieldNames(this.props.implementingType) - .map(fieldName => ({ - kind: 'Field', - name: {kind: 'Name', value: fieldName}, - })), - }, - }, - ]); - }; - _removeFragment = () => { - const thisSelection = this._getSelection(); - this._previousSelection = thisSelection; - this.props.modifySelections( - this.props.selections.filter(s => s !== thisSelection), - ); - }; - _getSelection = () => { - const selection = this.props.selections.find( - selection => - selection.kind === 'InlineFragment' && - selection.typeCondition && - this.props.implementingType.name === selection.typeCondition.name.value, - ); - if (!selection) { - return null; - } - if (selection.kind === 'InlineFragment') { - return selection; - } - }; - - _modifyChildSelections = (selections, options) => { - const thisSelection = this._getSelection(); - return this.props.modifySelections( - this.props.selections.map(selection => { - if (selection === thisSelection) { - return { - directives: selection.directives, - kind: 'InlineFragment', - typeCondition: { - kind: 'NamedType', - name: {kind: 'Name', value: this.props.implementingType.name}, - }, - selectionSet: { - kind: 'SelectionSet', - selections, - }, - }; - } - return selection; - }), - options, - ); - }; - - render() { - const { - implementingType, - schema, - getDefaultFieldNames, - styleConfig, - } = this.props; - const selection = this._getSelection(); - const fields = implementingType.getFields(); - const childSelections = selection - ? selection.selectionSet - ? selection.selectionSet.selections - : [] - : []; - - return ( -
- - - - {this.props.implementingType.name} - - - {selection ? ( -
- {Object.keys(fields) - .sort() - .map(fieldName => ( - - ))} -
- ) : null} -
- ); - } -} - -class FragmentView extends React.PureComponent { - _previousSelection; - _addFragment = () => { - this.props.modifySelections([ - ...this.props.selections, - this._previousSelection || { - kind: 'FragmentSpread', - name: this.props.fragment.name, - }, - ]); - }; - _removeFragment = () => { - const thisSelection = this._getSelection(); - this._previousSelection = thisSelection; - this.props.modifySelections( - this.props.selections.filter(s => { - const isTargetSelection = - s.kind === 'FragmentSpread' && - s.name.value === this.props.fragment.name.value; - - return !isTargetSelection; - }), - ); - }; - _getSelection = () => { - const selection = this.props.selections.find(selection => { - return ( - selection.kind === 'FragmentSpread' && - selection.name.value === this.props.fragment.name.value - ); - }); - - return selection; - }; - - render() { - const {styleConfig} = this.props; - const selection = this._getSelection(); - return ( -
- - - - {this.props.fragment.name.value} - - -
- ); - } -} - -class FieldView extends React.PureComponent { - state = {displayFieldActions: false}; - - _previousSelection; - _addAllFieldsToSelections = rawSubfields => { - const subFields = !!rawSubfields - ? Object.keys(rawSubfields).map(fieldName => { - return { - kind: 'Field', - name: {kind: 'Name', value: fieldName}, - arguments: [], - }; - }) - : []; - - const subSelectionSet = { - kind: 'SelectionSet', - selections: subFields, - }; - - const nextSelections = [ - ...this.props.selections.filter(selection => { - if (selection.kind === 'InlineFragment') { - return true; - } else { - return selection.name.value !== this.props.field.name; - } - }), - { - kind: 'Field', - name: {kind: 'Name', value: this.props.field.name}, - arguments: defaultArgs( - this.props.getDefaultScalarArgValue, - this.props.makeDefaultArg, - this.props.field, - ), - selectionSet: subSelectionSet, - }, - ]; - - this.props.modifySelections(nextSelections); - }; - - _addFieldToSelections = rawSubfields => { - const nextSelections = [ - ...this.props.selections, - this._previousSelection || { - kind: 'Field', - name: {kind: 'Name', value: this.props.field.name}, - arguments: defaultArgs( - this.props.getDefaultScalarArgValue, - this.props.makeDefaultArg, - this.props.field, - ), - }, - ]; - - this.props.modifySelections(nextSelections); - }; - - _handleUpdateSelections = event => { - const selection = this._getSelection(); - if (selection && !event.altKey) { - this._removeFieldFromSelections(); - } else { - const fieldType = getNamedType(this.props.field.type); - const rawSubfields = isObjectType(fieldType) && fieldType.getFields(); - - const shouldSelectAllSubfields = !!rawSubfields && event.altKey; - - shouldSelectAllSubfields - ? this._addAllFieldsToSelections(rawSubfields) - : this._addFieldToSelections(rawSubfields); - } - }; - - _removeFieldFromSelections = () => { - const previousSelection = this._getSelection(); - this._previousSelection = previousSelection; - this.props.modifySelections( - this.props.selections.filter( - selection => selection !== previousSelection, - ), - ); - }; - _getSelection = () => { - const selection = this.props.selections.find( - selection => - selection.kind === 'Field' && - this.props.field.name === selection.name.value, - ); - if (!selection) { - return null; - } - if (selection.kind === 'Field') { - return selection; - } - }; - - _setArguments = (argumentNodes, options) => { - const selection = this._getSelection(); - if (!selection) { - console.error('Missing selection when setting arguments', argumentNodes); - return; - } - return this.props.modifySelections( - this.props.selections.map(s => - s === selection - ? { - alias: selection.alias, - arguments: argumentNodes, - directives: selection.directives, - kind: 'Field', - name: selection.name, - selectionSet: selection.selectionSet, - } - : s, - ), - options, - ); - }; - - _modifyChildSelections = (selections, options) => { - return this.props.modifySelections( - this.props.selections.map(selection => { - if ( - selection.kind === 'Field' && - this.props.field.name === selection.name.value - ) { - if (selection.kind !== 'Field') { - throw new Error('invalid selection'); - } - return { - alias: selection.alias, - arguments: selection.arguments, - directives: selection.directives, - kind: 'Field', - name: selection.name, - selectionSet: { - kind: 'SelectionSet', - selections, - }, - }; - } - return selection; - }), - options, - ); - }; - - render() { - const {field, schema, getDefaultFieldNames, styleConfig} = this.props; - const selection = this._getSelection(); - const type = unwrapOutputType(field.type); - const args = field.args.sort((a, b) => a.name.localeCompare(b.name)); - let className = `graphiql-explorer-node graphiql-explorer-${field.name}`; - - if (field.isDeprecated) { - className += ' graphiql-explorer-deprecated'; - } - - const applicableFragments = - isObjectType(type) || isInterfaceType(type) || isUnionType(type) - ? this.props.availableFragments && - this.props.availableFragments[type.name] - : null; - - const node = ( -
- { - const containsMeaningfulSubselection = - isObjectType(type) && - selection && - selection.selectionSet && - selection.selectionSet.selections.filter( - selection => selection.kind !== 'FragmentSpread', - ).length > 0; - - if (containsMeaningfulSubselection) { - this.setState({displayFieldActions: true}); - } - }} - onMouseLeave={() => this.setState({displayFieldActions: false})}> - {isObjectType(type) ? ( - - {!!selection - ? this.props.styleConfig.arrowOpen - : this.props.styleConfig.arrowClosed} - - ) : null} - {isObjectType(type) ? null : ( - - )} - - {field.name} - - {!this.state.displayFieldActions ? null : ( - - )} - - {selection && args.length ? ( -
- {args.map(arg => ( - - ))} -
- ) : null} -
- ); - - if ( - selection && - (isObjectType(type) || isInterfaceType(type) || isUnionType(type)) - ) { - const fields = isUnionType(type) ? {} : type.getFields(); - const childSelections = selection - ? selection.selectionSet - ? selection.selectionSet.selections - : [] - : []; - return ( -
- {node} -
- {!!applicableFragments - ? applicableFragments.map(fragment => { - const type = schema.getType( - fragment.typeCondition.name.value, - ); - const fragmentName = fragment.name.value; - return !type ? null : ( - - ); - }) - : null} - {Object.keys(fields) - .sort() - .map(fieldName => ( - - ))} - {isInterfaceType(type) || isUnionType(type) - ? schema - .getPossibleTypes(type) - .map(type => ( - - )) - : null} -
-
- ); - } - return node; - } -} - -function parseQuery(text) { - try { - if (!text.trim()) { - return null; - } - return parse( - text, - {noLocation: true}, - ); - } catch (e) { - return new Error(e); - } -} - -const DEFAULT_OPERATION = { - kind: 'OperationDefinition', - operation: 'query', - variableDefinitions: [], - name: {kind: 'Name', value: 'MyQuery'}, - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [], - }, -}; -const DEFAULT_DOCUMENT = { - kind: 'Document', - definitions: [DEFAULT_OPERATION], -}; -let parseQueryMemoize = null; -function memoizeParseQuery(query) { - if (parseQueryMemoize && parseQueryMemoize[0] === query) { - return parseQueryMemoize[1]; - } else { - const result = parseQuery(query); - if (!result) { - return DEFAULT_DOCUMENT; - } else if (result instanceof Error) { - if (parseQueryMemoize) { - return parseQueryMemoize[1]; - } else { - return DEFAULT_DOCUMENT; - } - } else { - parseQueryMemoize = [query, result]; - return result; - } - } -} - -const defaultStyles = { - buttonStyle: { - fontSize: '1.2em', - padding: '0px', - backgroundColor: 'white', - border: 'none', - margin: '5px 0px', - height: '40px', - width: '100%', - display: 'block', - maxWidth: 'none', - }, - - actionButtonStyle: { - padding: '0px', - backgroundColor: 'white', - border: 'none', - margin: '0px', - maxWidth: 'none', - height: '15px', - width: '15px', - display: 'inline-block', - fontSize: 'smaller', - }, - - explorerActionsStyle: { - margin: '4px -8px -8px', - paddingLeft: '8px', - bottom: '0px', - width: '100%', - textAlign: 'center', - background: 'none', - borderTop: 'none', - borderBottom: 'none', - }, -}; - -class RootView extends React.PureComponent { - state = {newOperationType: 'query', displayTitleActions: false}; - _previousOperationDef; - - _modifySelections = (selections, options) => { - let operationDef = this.props.definition; - - if ( - operationDef.selectionSet.selections.length === 0 && - this._previousOperationDef - ) { - operationDef = this._previousOperationDef; - } - - let newOperationDef; - - if (operationDef.kind === 'FragmentDefinition') { - newOperationDef = { - ...operationDef, - selectionSet: { - ...operationDef.selectionSet, - selections, - }, - }; - } else if (operationDef.kind === 'OperationDefinition') { - let cleanedSelections = selections.filter(selection => { - return !( - selection.kind === 'Field' && selection.name.value === '__typename' - ); - }); - - if (cleanedSelections.length === 0) { - cleanedSelections = [ - { - kind: 'Field', - name: { - kind: 'Name', - value: '__typename ## Placeholder value', - }, - }, - ]; - } - - newOperationDef = { - ...operationDef, - selectionSet: { - ...operationDef.selectionSet, - selections: cleanedSelections, - }, - }; - } - - return this.props.onEdit(newOperationDef, options); - }; - - _onOperationRename = event => - this.props.onOperationRename(event.target.value); - - _handlePotentialRun = event => { - if (isRunShortcut(event) && canRunOperation(this.props.definition.kind)) { - this.props.onRunOperation(this.props.name); - } - }; - - _rootViewElId = () => { - const {operationType, name} = this.props; - const rootViewElId = `${operationType}-${name || 'unknown'}`; - return rootViewElId; - }; - - componentDidMount() { - const rootViewElId = this._rootViewElId(); - - this.props.onMount(rootViewElId); - } - - render() { - const { - operationType, - definition, - schema, - getDefaultFieldNames, - styleConfig, - } = this.props; - const rootViewElId = this._rootViewElId(); - - const fields = this.props.fields || {}; - const operationDef = definition; - const selections = operationDef.selectionSet.selections; - - const operationDisplayName = - this.props.name || `${capitalize(operationType)} Name`; - - return ( -
-
this.setState({displayTitleActions: true})} - onMouseLeave={() => this.setState({displayTitleActions: false})}> - {operationType}{' '} - - - - {!!this.props.onTypeName ? ( - -
- {`on ${this.props.onTypeName}`} -
- ) : ( - '' - )} - {!!this.state.displayTitleActions ? ( - - - - - ) : ( - '' - )} -
- - {Object.keys(fields) - .sort() - .map(fieldName => ( - - ))} -
- ); - } -} - -function Attribution() { - return ( -
-
- GraphiQL Explorer by OneGraph -
-
- Contribute on{' '} - GitHub -
-
- ); -} - -class Explorer extends React.PureComponent { - - state = { - newOperationType: 'query', - operation: null, - operationToScrollTo: null, - }; - - _ref; - _resetScroll = () => { - const container = this._ref; - if (container) { - container.scrollLeft = 0; - } - }; - componentDidMount() { - this._resetScroll(); - } - - _onEdit = query => this.props.onEdit(query); - - _setAddOperationType = value => { - this.setState({newOperationType: value}); - }; - - _handleRootViewMount = rootViewElId => { - if ( - !!this.state.operationToScrollTo && - this.state.operationToScrollTo === rootViewElId - ) { - var selector = `.graphiql-explorer-root #${rootViewElId}`; - - var el = document.querySelector(selector); - el && el.scrollIntoView(); - } - }; - - render() { - const {schema, query, makeDefaultArg} = this.props; - - if (!schema) { - return ( -
- No Schema Available -
- ); - } - const styleConfig = { - colors: this.props.colors || defaultColors, - checkboxChecked: this.props.checkboxChecked || defaultCheckboxChecked, - checkboxUnchecked: - this.props.checkboxUnchecked || defaultCheckboxUnchecked, - arrowClosed: this.props.arrowClosed || defaultArrowClosed, - arrowOpen: this.props.arrowOpen || defaultArrowOpen, - styles: this.props.styles - ? { - ...defaultStyles, - ...this.props.styles, - } - : defaultStyles, - }; - const queryType = schema.getQueryType(); - const mutationType = schema.getMutationType(); - const subscriptionType = schema.getSubscriptionType(); - if (!queryType && !mutationType && !subscriptionType) { - return
Missing query type
; - } - const queryFields = queryType && queryType.getFields(); - const mutationFields = mutationType && mutationType.getFields(); - const subscriptionFields = subscriptionType && subscriptionType.getFields(); - - const parsedQuery = memoizeParseQuery(query); - const getDefaultFieldNames = - this.props.getDefaultFieldNames || defaultGetDefaultFieldNames; - const getDefaultScalarArgValue = - this.props.getDefaultScalarArgValue || defaultGetDefaultScalarArgValue; - - const definitions = parsedQuery.definitions; - - const _relevantOperations = definitions - .map(definition => { - if (definition.kind === 'FragmentDefinition') { - return definition; - } else if (definition.kind === 'OperationDefinition') { - return definition; - } else { - return null; - } - }) - .filter(Boolean); - - const relevantOperations = - _relevantOperations.length === 0 - ? DEFAULT_DOCUMENT.definitions - : _relevantOperations; - - const renameOperation = (targetOperation, name) => { - const newName = - name == null || name === '' - ? null - : {kind: 'Name', value: name, loc: undefined}; - const newOperation = {...targetOperation, name: newName}; - - const existingDefs = parsedQuery.definitions; - - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { - return newOperation; - } else { - return existingOperation; - } - }); - - return { - ...parsedQuery, - definitions: newDefinitions, - }; - }; - - const cloneOperation = targetOperation => { - let kind; - if (targetOperation.kind === 'FragmentDefinition') { - kind = 'fragment'; - } else { - kind = targetOperation.operation; - } - - const newOperationName = - ((targetOperation.name && targetOperation.name.value) || '') + 'Copy'; - - const newName = { - kind: 'Name', - value: newOperationName, - loc: undefined, - }; - - const newOperation = {...targetOperation, name: newName}; - - const existingDefs = parsedQuery.definitions; - - const newDefinitions = [...existingDefs, newOperation]; - - this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); - - return { - ...parsedQuery, - definitions: newDefinitions, - }; - }; - - const destroyOperation = targetOperation => { - const existingDefs = parsedQuery.definitions; - - const newDefinitions = existingDefs.filter(existingOperation => { - if (targetOperation === existingOperation) { - return false; - } else { - return true; - } - }); - - return { - ...parsedQuery, - definitions: newDefinitions, - }; - }; - - const addOperation = kind => { - const existingDefs = parsedQuery.definitions; - - const viewingDefaultOperation = - parsedQuery.definitions.length === 1 && - parsedQuery.definitions[0] === DEFAULT_DOCUMENT.definitions[0]; - - const MySiblingDefs = viewingDefaultOperation - ? [] - : existingDefs.filter(def => { - if (def.kind === 'OperationDefinition') { - return def.operation === kind; - } else { - return false; - } - }); - - const newOperationName = `My${capitalize(kind)}${ - MySiblingDefs.length === 0 ? '' : MySiblingDefs.length + 1 - }`; - - const firstFieldName = '__typename # Placeholder value'; - - const selectionSet = { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: firstFieldName, - loc: null, - }, - arguments: [], - directives: [], - selectionSet: null, - loc: null, - }, - ], - loc: null, - }; - - const newDefinition = { - kind: 'OperationDefinition', - operation: kind, - name: {kind: 'Name', value: newOperationName}, - variableDefinitions: [], - directives: [], - selectionSet: selectionSet, - loc: null, - }; - - const newDefinitions = - viewingDefaultOperation - ? [newDefinition] - : [...parsedQuery.definitions, newDefinition]; - - const newOperationDef = { - ...parsedQuery, - definitions: newDefinitions, - }; - - this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); - - this.props.onEdit(print(newOperationDef)); - }; - - const actionsOptions = [ - !!queryFields ? ( - - ) : null, - !!mutationFields ? ( - - ) : null, - !!subscriptionFields ? ( - - ) : null, - ].filter(Boolean); - - const actionsEl = - actionsOptions.length === 0 || this.props.hideActions ? null : ( -
-
event.preventDefault()}> - - Add new{' '} - - - -
-
- ); - - const externalFragments = - this.props.externalFragments && - this.props.externalFragments.reduce((acc, fragment) => { - if (fragment.kind === 'FragmentDefinition') { - const fragmentTypeName = fragment.typeCondition.name.value; - const existingFragmentsForType = acc[fragmentTypeName] || []; - const newFragmentsForType = [ - ...existingFragmentsForType, - fragment, - ].sort((a, b) => a.name.value.localeCompare(b.name.value)); - return { - ...acc, - [fragmentTypeName]: newFragmentsForType, - }; - } - - return acc; - }, {}); - - const documentFragments = relevantOperations.reduce( - (acc, operation) => { - if (operation.kind === 'FragmentDefinition') { - const fragmentTypeName = operation.typeCondition.name.value; - const existingFragmentsForType = acc[fragmentTypeName] || []; - const newFragmentsForType = [ - ...existingFragmentsForType, - operation, - ].sort((a, b) => a.name.value.localeCompare(b.name.value)); - return { - ...acc, - [fragmentTypeName]: newFragmentsForType, - }; - } - - return acc; - }, - {}, - ); - - const availableFragments = {...documentFragments, ...externalFragments}; - - const attribution = this.props.showAttribution ? : null; - - return ( -
{ - this._ref = ref; - }} - style={{ - fontSize: 12, - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - margin: 0, - padding: 8, - fontFamily: - 'Consolas, Inconsolata, "Droid Sans Mono", Monaco, monospace', - display: 'flex', - flexDirection: 'column', - height: '100%', - }} - className="graphiql-explorer-root"> -
- {relevantOperations.map((operation, index) => { - const operationName = - operation && operation.name && operation.name.value; - - const operationType = - operation.kind === 'FragmentDefinition' - ? 'fragment' - : (operation && operation.operation) || 'query'; - - const onOperationRename = newName => { - const newOperationDef = renameOperation(operation, newName); - this.props.onEdit(print(newOperationDef)); - }; - - const onOperationClone = () => { - const newOperationDef = cloneOperation(operation); - this.props.onEdit(print(newOperationDef)); - }; - - const onOperationDestroy = () => { - const newOperationDef = destroyOperation(operation); - this.props.onEdit(print(newOperationDef)); - }; - - const fragmentType = - operation.kind === 'FragmentDefinition' && - operation.typeCondition.kind === 'NamedType' && - schema.getType(operation.typeCondition.name.value); - - const fragmentFields = - fragmentType instanceof GraphQLObjectType - ? fragmentType.getFields() - : null; - - const fields = - operationType === 'query' - ? queryFields - : operationType === 'mutation' - ? mutationFields - : operationType === 'subscription' - ? subscriptionFields - : operation.kind === 'FragmentDefinition' - ? fragmentFields - : null; - - const fragmentTypeName = - operation.kind === 'FragmentDefinition' - ? operation.typeCondition.name.value - : null; - - const onCommit = parsedDocument => { - const textualNewDocument = print(parsedDocument); - - this.props.onEdit(textualNewDocument); - }; - - return ( - { - let commit; - if ( - typeof options === 'object' && - typeof options.commit !== 'undefined' - ) { - commit = options.commit; - } else { - commit = true; - } - - if (!!newDefinition) { - const newQuery = { - ...parsedQuery, - definitions: parsedQuery.definitions.map( - existingDefinition => - existingDefinition === operation - ? newDefinition - : existingDefinition, - ), - }; - - if (commit) { - onCommit(newQuery); - return newQuery; - } else { - return newQuery; - } - } else { - return parsedQuery; - } - }} - schema={schema} - getDefaultFieldNames={getDefaultFieldNames} - getDefaultScalarArgValue={getDefaultScalarArgValue} - makeDefaultArg={makeDefaultArg} - onRunOperation={() => { - if (!!this.props.onRunOperation) { - this.props.onRunOperation(operationName); - } - }} - styleConfig={styleConfig} - availableFragments={availableFragments} - /> - ); - })} - {attribution} -
- - {actionsEl} -
- ); - } -} - -class ErrorBoundary extends React.Component { - state = {hasError: false, error: null, errorInfo: null}; - - componentDidCatch(error, errorInfo) { - this.setState({hasError: true, error: error, errorInfo: errorInfo}); - console.error('Error in component', error, errorInfo); - } - - render() { - if (this.state.hasError) { - return ( -
-
Something went wrong
-
- {this.state.error ? this.state.error.toString() : null} -
- {this.state.errorInfo ? this.state.errorInfo.componentStack : null} -
-
- ); - } - return this.props.children; - } -} - -class ExplorerWrapper extends React.PureComponent { - - render() { - return ( -
-
-
{this.props.title}
-
-
- {'\u2715'} -
-
-
-
- - - -
-
- ); - } -} - -export default ExplorerWrapper; diff --git a/plugins/third-party-plugin/src/components/ExplorerView.jsx b/plugins/third-party-plugin/src/components/ExplorerView.jsx new file mode 100644 index 0000000..3f61403 --- /dev/null +++ b/plugins/third-party-plugin/src/components/ExplorerView.jsx @@ -0,0 +1,522 @@ +import React from "react"; +import { + capitalize, + DEFAULT_DOCUMENT, + defaultColors, + defaultGetDefaultFieldNames, defaultGetDefaultScalarArgValue, + defaultStyles, + memoizeParseQuery +} from "../utils"; +import {GraphQLObjectType, print} from "graphql"; +import RootView from "./RootView"; + +class ExplorerView extends React.PureComponent { + + state = { + newOperationType: 'query', + operation: null, + operationToScrollTo: null, + }; + + _ref; + _resetScroll = () => { + const container = this._ref; + if (container) { + container.scrollLeft = 0; + } + }; + componentDidMount() { + this._resetScroll(); + } + + _onEdit = query => this.props.onEdit(query); + + _setAddOperationType = value => { + this.setState({newOperationType: value}); + }; + + _handleRootViewMount = rootViewElId => { + if ( + !!this.state.operationToScrollTo && + this.state.operationToScrollTo === rootViewElId + ) { + var selector = `.graphiql-explorer-root #${rootViewElId}`; + + var el = document.querySelector(selector); + el && el.scrollIntoView(); + } + }; + + render() { + const {schema, query, makeDefaultArg} = this.props; + + if (!schema) { + return ( +
+ No Schema Available +
+ ); + } + const styleConfig = { + colors: this.props.colors || defaultColors, + checkboxChecked: this.props.checkboxChecked || defaultCheckboxChecked, + checkboxUnchecked: + this.props.checkboxUnchecked || defaultCheckboxUnchecked, + arrowClosed: this.props.arrowClosed || defaultArrowClosed, + arrowOpen: this.props.arrowOpen || defaultArrowOpen, + styles: this.props.styles + ? { + ...defaultStyles, + ...this.props.styles, + } + : defaultStyles, + }; + const queryType = schema.getQueryType(); + const mutationType = schema.getMutationType(); + const subscriptionType = schema.getSubscriptionType(); + if (!queryType && !mutationType && !subscriptionType) { + return
Missing query type
; + } + const queryFields = queryType && queryType.getFields(); + const mutationFields = mutationType && mutationType.getFields(); + const subscriptionFields = subscriptionType && subscriptionType.getFields(); + + const parsedQuery = memoizeParseQuery(query); + const getDefaultFieldNames = + this.props.getDefaultFieldNames || defaultGetDefaultFieldNames; + const getDefaultScalarArgValue = + this.props.getDefaultScalarArgValue || defaultGetDefaultScalarArgValue; + + const definitions = parsedQuery.definitions; + + const _relevantOperations = definitions + .map(definition => { + if (definition.kind === 'FragmentDefinition') { + return definition; + } else if (definition.kind === 'OperationDefinition') { + return definition; + } else { + return null; + } + }) + .filter(Boolean); + + const relevantOperations = + _relevantOperations.length === 0 + ? DEFAULT_DOCUMENT.definitions + : _relevantOperations; + + const renameOperation = (targetOperation, name) => { + const newName = + name == null || name === '' + ? null + : {kind: 'Name', value: name, loc: undefined}; + const newOperation = {...targetOperation, name: newName}; + + const existingDefs = parsedQuery.definitions; + + const newDefinitions = existingDefs.map(existingOperation => { + if (targetOperation === existingOperation) { + return newOperation; + } else { + return existingOperation; + } + }); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const cloneOperation = targetOperation => { + let kind; + if (targetOperation.kind === 'FragmentDefinition') { + kind = 'fragment'; + } else { + kind = targetOperation.operation; + } + + const newOperationName = + ((targetOperation.name && targetOperation.name.value) || '') + 'Copy'; + + const newName = { + kind: 'Name', + value: newOperationName, + loc: undefined, + }; + + const newOperation = {...targetOperation, name: newName}; + + const existingDefs = parsedQuery.definitions; + + const newDefinitions = [...existingDefs, newOperation]; + + this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const destroyOperation = targetOperation => { + const existingDefs = parsedQuery.definitions; + + const newDefinitions = existingDefs.filter(existingOperation => { + if (targetOperation === existingOperation) { + return false; + } else { + return true; + } + }); + + return { + ...parsedQuery, + definitions: newDefinitions, + }; + }; + + const addOperation = kind => { + const existingDefs = parsedQuery.definitions; + + const viewingDefaultOperation = + parsedQuery.definitions.length === 1 && + parsedQuery.definitions[0] === DEFAULT_DOCUMENT.definitions[0]; + + const MySiblingDefs = viewingDefaultOperation + ? [] + : existingDefs.filter(def => { + if (def.kind === 'OperationDefinition') { + return def.operation === kind; + } else { + return false; + } + }); + + const newOperationName = `My${capitalize(kind)}${ + MySiblingDefs.length === 0 ? '' : MySiblingDefs.length + 1 + }`; + + const firstFieldName = '__typename # Placeholder value'; + + const selectionSet = { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: firstFieldName, + loc: null, + }, + arguments: [], + directives: [], + selectionSet: null, + loc: null, + }, + ], + loc: null, + }; + + const newDefinition = { + kind: 'OperationDefinition', + operation: kind, + name: {kind: 'Name', value: newOperationName}, + variableDefinitions: [], + directives: [], + selectionSet: selectionSet, + loc: null, + }; + + const newDefinitions = + viewingDefaultOperation + ? [newDefinition] + : [...parsedQuery.definitions, newDefinition]; + + const newOperationDef = { + ...parsedQuery, + definitions: newDefinitions, + }; + + this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + + this.props.onEdit(print(newOperationDef)); + }; + + const actionsOptions = [ + !!queryFields ? ( + + ) : null, + !!mutationFields ? ( + + ) : null, + !!subscriptionFields ? ( + + ) : null, + ].filter(Boolean); + + const actionsEl = + actionsOptions.length === 0 || this.props.hideActions ? null : ( +
+
event.preventDefault()}> + + Add new{' '} + + + +
+
+ ); + + const externalFragments = + this.props.externalFragments && + this.props.externalFragments.reduce((acc, fragment) => { + if (fragment.kind === 'FragmentDefinition') { + const fragmentTypeName = fragment.typeCondition.name.value; + const existingFragmentsForType = acc[fragmentTypeName] || []; + const newFragmentsForType = [ + ...existingFragmentsForType, + fragment, + ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + return { + ...acc, + [fragmentTypeName]: newFragmentsForType, + }; + } + + return acc; + }, {}); + + const documentFragments = relevantOperations.reduce( + (acc, operation) => { + if (operation.kind === 'FragmentDefinition') { + const fragmentTypeName = operation.typeCondition.name.value; + const existingFragmentsForType = acc[fragmentTypeName] || []; + const newFragmentsForType = [ + ...existingFragmentsForType, + operation, + ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + return { + ...acc, + [fragmentTypeName]: newFragmentsForType, + }; + } + + return acc; + }, + {}, + ); + + const availableFragments = {...documentFragments, ...externalFragments}; + + const attribution = this.props.showAttribution ? : null; + + return ( +
{ + this._ref = ref; + }} + style={{ + fontSize: 12, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + margin: 0, + padding: 8, + fontFamily: + 'Consolas, Inconsolata, "Droid Sans Mono", Monaco, monospace', + display: 'flex', + flexDirection: 'column', + height: '100%', + }} + className="graphiql-explorer-root"> +
+ {relevantOperations.map((operation, index) => { + const operationName = + operation && operation.name && operation.name.value; + + const operationType = + operation.kind === 'FragmentDefinition' + ? 'fragment' + : (operation && operation.operation) || 'query'; + + const onOperationRename = newName => { + const newOperationDef = renameOperation(operation, newName); + this.props.onEdit(print(newOperationDef)); + }; + + const onOperationClone = () => { + const newOperationDef = cloneOperation(operation); + this.props.onEdit(print(newOperationDef)); + }; + + const onOperationDestroy = () => { + const newOperationDef = destroyOperation(operation); + this.props.onEdit(print(newOperationDef)); + }; + + const fragmentType = + operation.kind === 'FragmentDefinition' && + operation.typeCondition.kind === 'NamedType' && + schema.getType(operation.typeCondition.name.value); + + const fragmentFields = + fragmentType instanceof GraphQLObjectType + ? fragmentType.getFields() + : null; + + const fields = + operationType === 'query' + ? queryFields + : operationType === 'mutation' + ? mutationFields + : operationType === 'subscription' + ? subscriptionFields + : operation.kind === 'FragmentDefinition' + ? fragmentFields + : null; + + const fragmentTypeName = + operation.kind === 'FragmentDefinition' + ? operation.typeCondition.name.value + : null; + + const onCommit = parsedDocument => { + const textualNewDocument = print(parsedDocument); + + this.props.onEdit(textualNewDocument); + }; + + return ( + { + let commit; + if ( + typeof options === 'object' && + typeof options.commit !== 'undefined' + ) { + commit = options.commit; + } else { + commit = true; + } + + if (!!newDefinition) { + const newQuery = { + ...parsedQuery, + definitions: parsedQuery.definitions.map( + existingDefinition => + existingDefinition === operation + ? newDefinition + : existingDefinition, + ), + }; + + if (commit) { + onCommit(newQuery); + return newQuery; + } else { + return newQuery; + } + } else { + return parsedQuery; + } + }} + schema={schema} + getDefaultFieldNames={getDefaultFieldNames} + getDefaultScalarArgValue={getDefaultScalarArgValue} + makeDefaultArg={makeDefaultArg} + onRunOperation={() => { + if (!!this.props.onRunOperation) { + this.props.onRunOperation(operationName); + } + }} + styleConfig={styleConfig} + availableFragments={availableFragments} + /> + ); + })} + {attribution} +
+ + {actionsEl} +
+ ); + } +} + +export default ExplorerView; diff --git a/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx b/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx new file mode 100644 index 0000000..cacffdf --- /dev/null +++ b/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx @@ -0,0 +1,46 @@ +import React from "react"; +import ErrorBoundary from "./ErrorBoundary"; +import ExplorerView from "./ExplorerView"; + +class ExplorerWrapper extends React.PureComponent { + + render() { + return ( +
+
+
{this.props.title}
+
+
+ {'\u2715'} +
+
+
+
+ + + +
+
+ ); + } +} + +export default ExplorerWrapper; diff --git a/plugins/third-party-plugin/src/components/FieldView.jsx b/plugins/third-party-plugin/src/components/FieldView.jsx new file mode 100644 index 0000000..4581cad --- /dev/null +++ b/plugins/third-party-plugin/src/components/FieldView.jsx @@ -0,0 +1,410 @@ +import React from "react"; +import {defaultArgs, unwrapOutputType} from "../utils"; +import {getNamedType, isInterfaceType, isObjectType, isUnionType} from "graphql"; +import Checkbox from "./Checkbox"; +import ArgView from "./ArgView"; +import FragmentView from "./FragmentView"; +import AbstractView from "./AbstractView"; + +class FieldView extends React.PureComponent { + state = {displayFieldActions: false}; + + _previousSelection; + _addAllFieldsToSelections = rawSubfields => { + const subFields = !!rawSubfields + ? Object.keys(rawSubfields).map(fieldName => { + return { + kind: 'Field', + name: {kind: 'Name', value: fieldName}, + arguments: [], + }; + }) + : []; + + const subSelectionSet = { + kind: 'SelectionSet', + selections: subFields, + }; + + const nextSelections = [ + ...this.props.selections.filter(selection => { + if (selection.kind === 'InlineFragment') { + return true; + } else { + return selection.name.value !== this.props.field.name; + } + }), + { + kind: 'Field', + name: {kind: 'Name', value: this.props.field.name}, + arguments: defaultArgs( + this.props.getDefaultScalarArgValue, + this.props.makeDefaultArg, + this.props.field, + ), + selectionSet: subSelectionSet, + }, + ]; + + this.props.modifySelections(nextSelections); + }; + + _addFieldToSelections = rawSubfields => { + const nextSelections = [ + ...this.props.selections, + this._previousSelection || { + kind: 'Field', + name: {kind: 'Name', value: this.props.field.name}, + arguments: defaultArgs( + this.props.getDefaultScalarArgValue, + this.props.makeDefaultArg, + this.props.field, + ), + }, + ]; + + this.props.modifySelections(nextSelections); + }; + + _handleUpdateSelections = event => { + const selection = this._getSelection(); + if (selection && !event.altKey) { + this._removeFieldFromSelections(); + } else { + const fieldType = getNamedType(this.props.field.type); + const rawSubfields = isObjectType(fieldType) && fieldType.getFields(); + + const shouldSelectAllSubfields = !!rawSubfields && event.altKey; + + shouldSelectAllSubfields + ? this._addAllFieldsToSelections(rawSubfields) + : this._addFieldToSelections(rawSubfields); + } + }; + + _removeFieldFromSelections = () => { + const previousSelection = this._getSelection(); + this._previousSelection = previousSelection; + this.props.modifySelections( + this.props.selections.filter( + selection => selection !== previousSelection, + ), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find( + selection => + selection.kind === 'Field' && + this.props.field.name === selection.name.value, + ); + if (!selection) { + return null; + } + if (selection.kind === 'Field') { + return selection; + } + }; + + _setArguments = (argumentNodes, options) => { + const selection = this._getSelection(); + if (!selection) { + console.error('Missing selection when setting arguments', argumentNodes); + return; + } + return this.props.modifySelections( + this.props.selections.map(s => + s === selection + ? { + alias: selection.alias, + arguments: argumentNodes, + directives: selection.directives, + kind: 'Field', + name: selection.name, + selectionSet: selection.selectionSet, + } + : s, + ), + options, + ); + }; + + _modifyChildSelections = (selections, options) => { + return this.props.modifySelections( + this.props.selections.map(selection => { + if ( + selection.kind === 'Field' && + this.props.field.name === selection.name.value + ) { + if (selection.kind !== 'Field') { + throw new Error('invalid selection'); + } + return { + alias: selection.alias, + arguments: selection.arguments, + directives: selection.directives, + kind: 'Field', + name: selection.name, + selectionSet: { + kind: 'SelectionSet', + selections, + }, + }; + } + return selection; + }), + options, + ); + }; + + render() { + const {field, schema, getDefaultFieldNames, styleConfig} = this.props; + const selection = this._getSelection(); + const type = unwrapOutputType(field.type); + const args = field.args.sort((a, b) => a.name.localeCompare(b.name)); + let className = `graphiql-explorer-node graphiql-explorer-${field.name}`; + + if (field.isDeprecated) { + className += ' graphiql-explorer-deprecated'; + } + + const applicableFragments = + isObjectType(type) || isInterfaceType(type) || isUnionType(type) + ? this.props.availableFragments && + this.props.availableFragments[type.name] + : null; + + const node = ( +
+ { + const containsMeaningfulSubselection = + isObjectType(type) && + selection && + selection.selectionSet && + selection.selectionSet.selections.filter( + selection => selection.kind !== 'FragmentSpread', + ).length > 0; + + if (containsMeaningfulSubselection) { + this.setState({displayFieldActions: true}); + } + }} + onMouseLeave={() => this.setState({displayFieldActions: false})}> + {isObjectType(type) ? ( + + {!!selection + ? this.props.styleConfig.arrowOpen + : this.props.styleConfig.arrowClosed} + + ) : null} + {isObjectType(type) ? null : ( + + )} + + {field.name} + + {!this.state.displayFieldActions ? null : ( + + )} + + {selection && args.length ? ( +
+ {args.map(arg => ( + + ))} +
+ ) : null} +
+ ); + + if ( + selection && + (isObjectType(type) || isInterfaceType(type) || isUnionType(type)) + ) { + const fields = isUnionType(type) ? {} : type.getFields(); + const childSelections = selection + ? selection.selectionSet + ? selection.selectionSet.selections + : [] + : []; + return ( +
+ {node} +
+ {!!applicableFragments + ? applicableFragments.map(fragment => { + const type = schema.getType( + fragment.typeCondition.name.value, + ); + const fragmentName = fragment.name.value; + return !type ? null : ( + + ); + }) + : null} + {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} + {isInterfaceType(type) || isUnionType(type) + ? schema + .getPossibleTypes(type) + .map(type => ( + + )) + : null} +
+
+ ); + } + return node; + } +} + +export default FieldView; diff --git a/plugins/third-party-plugin/src/components/FragmentView.jsx b/plugins/third-party-plugin/src/components/FragmentView.jsx new file mode 100644 index 0000000..5d48ceb --- /dev/null +++ b/plugins/third-party-plugin/src/components/FragmentView.jsx @@ -0,0 +1,62 @@ +import React from "react"; +import Checkbox from "./Checkbox"; + +class FragmentView extends React.PureComponent { + _previousSelection; + _addFragment = () => { + this.props.modifySelections([ + ...this.props.selections, + this._previousSelection || { + kind: 'FragmentSpread', + name: this.props.fragment.name, + }, + ]); + }; + _removeFragment = () => { + const thisSelection = this._getSelection(); + this._previousSelection = thisSelection; + this.props.modifySelections( + this.props.selections.filter(s => { + const isTargetSelection = + s.kind === 'FragmentSpread' && + s.name.value === this.props.fragment.name.value; + + return !isTargetSelection; + }), + ); + }; + _getSelection = () => { + const selection = this.props.selections.find(selection => { + return ( + selection.kind === 'FragmentSpread' && + selection.name.value === this.props.fragment.name.value + ); + }); + + return selection; + }; + + render() { + const {styleConfig} = this.props; + const selection = this._getSelection(); + return ( +
+ + + + {this.props.fragment.name.value} + + +
+ ); + } +} + +export default FragmentView; diff --git a/plugins/third-party-plugin/src/components/InputArgView.jsx b/plugins/third-party-plugin/src/components/InputArgView.jsx new file mode 100644 index 0000000..86a4e24 --- /dev/null +++ b/plugins/third-party-plugin/src/components/InputArgView.jsx @@ -0,0 +1,184 @@ +import React from "react"; +import {coerceArgValue, unwrapInputType} from "../utils"; +import {isInputObjectType, isLeafType} from "graphql"; + +class InputArgView extends React.PureComponent { + _previousArgSelection; + _getArgSelection = () => { + return this.props.selection.fields.find( + field => field.name.value === this.props.arg.name, + ); + }; + + _removeArg = () => { + const {selection} = this.props; + const argSelection = this._getArgSelection(); + this._previousArgSelection = argSelection; + this.props.modifyFields( + selection.fields.filter(field => field !== argSelection), + true, + ); + }; + + _addArg = () => { + const { + selection, + arg, + getDefaultScalarArgValue, + parentField, + makeDefaultArg, + } = this.props; + const argType = unwrapInputType(arg.type); + + let argSelection = null; + if (this._previousArgSelection) { + argSelection = this._previousArgSelection; + } else if (isInputObjectType(argType)) { + const fields = argType.getFields(); + argSelection = { + kind: 'ObjectField', + name: {kind: 'Name', value: arg.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + Object.keys(fields).map(k => fields[k]), + ), + }, + }; + } else if (isLeafType(argType)) { + argSelection = { + kind: 'ObjectField', + name: {kind: 'Name', value: arg.name}, + value: getDefaultScalarArgValue(parentField, arg, argType), + }; + } + + if (!argSelection) { + console.error('Unable to add arg for argType', argType); + } else { + return this.props.modifyFields( + [...(selection.fields || []), argSelection], + true, + ); + } + }; + + _setArgValue = (event, options) => { + let settingToNull = false; + let settingToVariable = false; + let settingToLiteralValue = false; + try { + if (event.kind === 'VariableDefinition') { + settingToVariable = true; + } else if (event === null || typeof event === 'undefined') { + settingToNull = true; + } else if (typeof event.kind === 'string') { + settingToLiteralValue = true; + } + } catch (e) {} + + const {selection} = this.props; + + const argSelection = this._getArgSelection(); + + if (!argSelection) { + console.error('missing arg selection when setting arg value'); + return; + } + const argType = unwrapInputType(this.props.arg.type); + + const handleable = + isLeafType(argType) || + settingToVariable || + settingToNull || + settingToLiteralValue; + + if (!handleable) { + console.warn( + 'Unable to handle non leaf types in InputArgView.setArgValue', + event, + ); + return; + } + let targetValue; + let value; + + if (event === null || typeof event === 'undefined') { + value = null; + } else if ( + !event.target && + !!event.kind && + event.kind === 'VariableDefinition' + ) { + targetValue = event; + value = targetValue.variable; + } else if (typeof event.kind === 'string') { + value = event; + } else if (event.target && typeof event.target.value === 'string') { + targetValue = event.target.value; + value = coerceArgValue(argType, targetValue); + } + + const newDoc = this.props.modifyFields( + (selection.fields || []).map(field => { + const isTarget = field === argSelection; + const newField = isTarget + ? { + ...field, + value: value, + } + : field; + + return newField; + }), + options, + ); + + return newDoc; + }; + + _modifyChildFields = fields => { + return this.props.modifyFields( + this.props.selection.fields.map(field => + field.name.value === this.props.arg.name + ? { + ...field, + value: { + kind: 'ObjectValue', + fields: fields, + }, + } + : field, + ), + true, + ); + }; + + render() { + const {arg, parentField} = this.props; + const argSelection = this._getArgSelection(); + + return ( + + ); + } +} + +export default InputArgView; diff --git a/plugins/third-party-plugin/src/components/QueryComposer.js b/plugins/third-party-plugin/src/components/QueryComposer.js index e26740a..a7030bb 100644 --- a/plugins/third-party-plugin/src/components/QueryComposer.js +++ b/plugins/third-party-plugin/src/components/QueryComposer.js @@ -1,7 +1,45 @@ -import { useSelect } from '@wordpress/data'; -import { Suspense, lazy } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import ExplorerWrapper from './ExplorerWrapper'; +import '../style.css'; +import ArrowOpen from "./ArrowOpen"; +import ArrowClosed from "./ArrowClosed"; +import { checkboxUnchecked, checkboxChecked } from './Checkbox'; -export const QueryComposer = () => { +const colors = { + keyword: 'hsl(var(--color-primary))', + def: 'hsl(var(--color-tertiary))', + property: 'hsl(var(--color-info))', + qualifier: 'hsl(var(--color-secondary))', + attribute: 'hsl(var(--color-tertiary))', + number: 'hsl(var(--color-success))', + string: 'hsl(var(--color-warning))', + builtin: 'hsl(var(--color-success))', + string2: 'hsl(var(--color-secondary))', + variable: 'hsl(var(--color-secondary))', + atom: 'hsl(var(--color-tertiary))', +}; + +const styles = { + buttonStyle: { + backgroundColor: 'transparent', + border: 'none', + color: 'hsla(var(--color-neutral), var(--alpha-secondary, 0.6))', + cursor: 'pointer', + fontSize: '1em', + }, + explorerActionsStyle: { + padding: 'var(--px-8) var(--px-4)', + }, + actionButtonStyle: { + backgroundColor: 'transparent', + border: 'none', + color: 'hsla(var(--color-neutral), var(--alpha-secondary, 0.6))', + cursor: 'pointer', + fontSize: '1em', + }, +}; + +export const QueryComposer = (props) => { const schema = useSelect( ( select ) => select( 'wpgraphql-ide/app' ).schema() @@ -11,23 +49,26 @@ export const QueryComposer = () => { select( 'wpgraphql-ide/app' ).getQuery() ); - const Explorer = lazy(() => import('./Explorer')); - - console.log( { - queryComposer: { - WPGraphQLIDE: window.WPGraphQLIDE - } - }) + const { setQuery } = useDispatch( 'wpgraphql-ide/app' ); return ( <> - Loading...}> - - - {/*
{JSON.stringify( window.WPGraphQLIDE, null, 2 )}
*/} + { + setQuery( newQuery ); + }} + /> ); } diff --git a/plugins/third-party-plugin/src/components/RootView.jsx b/plugins/third-party-plugin/src/components/RootView.jsx new file mode 100644 index 0000000..491c80a --- /dev/null +++ b/plugins/third-party-plugin/src/components/RootView.jsx @@ -0,0 +1,218 @@ +import React from "react"; +import {canRunOperation, capitalize, isRunShortcut} from "../utils"; +import FieldView from "./FieldView"; + +class RootView extends React.PureComponent { + state = {newOperationType: 'query', displayTitleActions: false}; + _previousOperationDef; + + _modifySelections = (selections, options) => { + let operationDef = this.props.definition; + + if ( + operationDef.selectionSet.selections.length === 0 && + this._previousOperationDef + ) { + operationDef = this._previousOperationDef; + } + + let newOperationDef; + + if (operationDef.kind === 'FragmentDefinition') { + newOperationDef = { + ...operationDef, + selectionSet: { + ...operationDef.selectionSet, + selections, + }, + }; + } else if (operationDef.kind === 'OperationDefinition') { + let cleanedSelections = selections.filter(selection => { + return !( + selection.kind === 'Field' && selection.name.value === '__typename' + ); + }); + + if (cleanedSelections.length === 0) { + cleanedSelections = [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename ## Placeholder value', + }, + }, + ]; + } + + newOperationDef = { + ...operationDef, + selectionSet: { + ...operationDef.selectionSet, + selections: cleanedSelections, + }, + }; + } + + return this.props.onEdit(newOperationDef, options); + }; + + _onOperationRename = event => + this.props.onOperationRename(event.target.value); + + _handlePotentialRun = event => { + if (isRunShortcut(event) && canRunOperation(this.props.definition.kind)) { + this.props.onRunOperation(this.props.name); + } + }; + + _rootViewElId = () => { + const {operationType, name} = this.props; + const rootViewElId = `${operationType}-${name || 'unknown'}`; + return rootViewElId; + }; + + componentDidMount() { + const rootViewElId = this._rootViewElId(); + + this.props.onMount(rootViewElId); + } + + render() { + const { + operationType, + definition, + schema, + getDefaultFieldNames, + styleConfig, + } = this.props; + const rootViewElId = this._rootViewElId(); + + const fields = this.props.fields || {}; + const operationDef = definition; + const selections = operationDef.selectionSet.selections; + + const operationDisplayName = + this.props.name || `${capitalize(operationType)} Name`; + + return ( +
+
this.setState({displayTitleActions: true})} + onMouseLeave={() => this.setState({displayTitleActions: false})}> + {operationType}{' '} + + + + {!!this.props.onTypeName ? ( + +
+ {`on ${this.props.onTypeName}`} +
+ ) : ( + '' + )} + {!!this.state.displayTitleActions ? ( + + + + + ) : ( + '' + )} +
+ + {Object.keys(fields) + .sort() + .map(fieldName => ( + + ))} +
+ ); + } +} + +function Attribution() { + return ( +
+
+ GraphiQL Explorer by OneGraph +
+
+ Contribute on{' '} + GitHub +
+
+ ); +} + +export default RootView; diff --git a/plugins/third-party-plugin/src/components/ScalarInput.jsx b/plugins/third-party-plugin/src/components/ScalarInput.jsx new file mode 100644 index 0000000..6ac00f1 --- /dev/null +++ b/plugins/third-party-plugin/src/components/ScalarInput.jsx @@ -0,0 +1,55 @@ +import React from "react"; +import {unwrapInputType} from "../utils"; + +class ScalarInput extends React.PureComponent { + _ref; + _handleChange = event => { + this.props.setArgValue(event, true); + }; + + componentDidMount() { + const input = this._ref; + const activeElement = document.activeElement; + if ( + input && + activeElement && + !(activeElement instanceof HTMLTextAreaElement) + ) { + input.focus(); + input.setSelectionRange(0, input.value.length); + } + } + + render() { + const {arg, argValue, styleConfig} = this.props; + const argType = unwrapInputType(arg.type); + const value = typeof argValue.value === 'string' ? argValue.value : ''; + const color = + this.props.argValue.kind === 'StringValue' + ? styleConfig.colors.string + : styleConfig.colors.number; + return ( + + {argType.name === 'String' ? '"' : ''} + { + this._ref = ref; + }} + type="text" + onChange={this._handleChange} + value={value} + /> + {argType.name === 'String' ? '"' : ''} + + ); + } +} + +export default ScalarInput; diff --git a/plugins/third-party-plugin/src/index.js b/plugins/third-party-plugin/src/index.js index 004d5d0..bbebcfb 100644 --- a/plugins/third-party-plugin/src/index.js +++ b/plugins/third-party-plugin/src/index.js @@ -1,71 +1,33 @@ /** * External dependencies */ -import { explorerPlugin } from '@graphiql/plugin-explorer'; -import { addAction } from '@wordpress/hooks'; import {QueryComposer} from "./components/QueryComposer"; - -console.log( 'Third Party Plugin loading...' ); +import {edit as editIcon, Icon} from '@wordpress/icons'; window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { - console.log( 'Third Party Plugin Loaded' ); if ( ! window.WPGraphQLIDE ) { - console.log( `WPGraphQLIDE not loaded` ); - console.log( window.WPGraphQLIDE ); return; } const { registerActivityBarPanel } = window.WPGraphQLIDE || {}; if ( typeof registerActivityBarPanel === 'function' ) { - - console.log( `Registering Mock Explorer Panel`); - registerActivityBarPanel( 'query-composer', () => { return { title: 'Query Composer', - icon: () => <>Query Composer, - content: () => ( -
- -
- ) + icon: () => ( + + ), + content: () => }; }, 4 ); - - // registerActivityBarPanel( 'explorer', explorerPlugin, 4 ); - } else { - console.log( 'CANNOT Registering Mock Explorer Panel' ); } - - // Perform your desired actions here }); - - - - - -// return; -// - -// const mockExplorerPanel = () => { -// return { -// title: 'Mock Explorer', -// icon: 'icon', -// content: () => ( -// <> -//

Test

-// -// ), -// }; -// }; -// -// /** -// * Ensure the code only runs once WPGraphQLIDEReady is fired and registerActivityBarPanel is defined. -// */ - - - diff --git a/plugins/third-party-plugin/src/style.css b/plugins/third-party-plugin/src/style.css new file mode 100644 index 0000000..5d545e4 --- /dev/null +++ b/plugins/third-party-plugin/src/style.css @@ -0,0 +1,77 @@ +/** + * GraphiQL Explorer Styles + */ +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap { + width: 100% !important; + +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .doc-explorer-title { + font-weight: var(--font-weight-medium); + font-size: var(--font-size-h2); + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .doc-explorer-title-bar { + padding: var(--px-16); + padding-bottom: 0; +} + +#wpgraphql-ide-app .graphiql-plugin .doc-explorer-rhs { + display: none!important; +} + +#wpgraphql-ide-app .graphiql-plugin .doc-explorer-contents { + height: 100%; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root { + padding: 0!important; +} + +#wpgraphql-ide-app .graphiql-plugin:has(div.docExplorerWrap) { + padding: 0!important; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root > div:first-of-type { + padding: 20px!important; + flex: 3 1 0!important; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root input { + width: auto!important; + padding: 0 8px; + line-height: 2; + min-height: 30px; + box-shadow: 0 0 0 transparent; + border-radius: 4px; + border: 1px solid + hsla(var(--color-neutral), var(--alpha-background-heavy))!important; + background: transparent; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions { + border-top: 1px solid + hsla(var(--color-neutral), var(--alpha-background-heavy))!important; +} +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions > span:first-of-type{ + padding: 10px; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root>div>div { + border-bottom: 1px solid hsla(var(--color-neutral), var(--alpha-background-heavy))!important; + margin-bottom: 15px!important; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root>div>div:last-of-type { + border-bottom: none!important; + margin-bottom: 0!important; +} + +#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions > select { + color: hsl(var(--color-primary)); + border: 1px solid + hsla(var(--color-neutral), var(--alpha-background-heavy))!important; + background: transparent; +} diff --git a/plugins/third-party-plugin/src/utils.js b/plugins/third-party-plugin/src/utils.js new file mode 100644 index 0000000..0c073c4 --- /dev/null +++ b/plugins/third-party-plugin/src/utils.js @@ -0,0 +1,349 @@ +import { + isEnumType, + isInputObjectType, + isLeafType, + isNonNullType, + isRequiredInputField, + isScalarType, + isWrappingType, parse +} from "graphql"; + +export const defaultColors = { + keyword: '#B11A04', + def: '#D2054E', + property: '#1F61A0', + qualifier: '#1C92A9', + attribute: '#8B2BB9', + number: '#2882F9', + string: '#D64292', + builtin: '#D47509', + string2: '#0B7FC7', + variable: '#397D13', + atom: '#CA9800', +}; + +export function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +export function defaultValue( + argType, +) { + if (isEnumType(argType)) { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } else { + switch (argType.name) { + case 'String': + return {kind: 'StringValue', value: ''}; + case 'Float': + return {kind: 'FloatValue', value: '1.5'}; + case 'Int': + return {kind: 'IntValue', value: '10'}; + case 'Boolean': + return {kind: 'BooleanValue', value: false}; + default: + return {kind: 'StringValue', value: ''}; + } + } +} + +export function defaultGetDefaultScalarArgValue( + parentField, + arg, + argType, +) { + return defaultValue(argType); +} + +export function defaultGetDefaultFieldNames(type) { + const fields = type.getFields(); + + if (fields['id']) { + const res = ['id']; + if (fields['email']) { + res.push('email'); + } else if (fields['name']) { + res.push('name'); + } + return res; + } + + if (fields['edges']) { + return ['edges']; + } + + if (fields['node']) { + return ['node']; + } + + if (fields['nodes']) { + return ['nodes']; + } + + const leafFieldNames = []; + Object.keys(fields).forEach(fieldName => { + if (isLeafType(fields[fieldName].type)) { + leafFieldNames.push(fieldName); + } + }); + + if (!leafFieldNames.length) { + return ['__typename']; + } + return leafFieldNames.slice(0, 2); +} + +export function isRequiredArgument(arg) { + return isNonNullType(arg.type) && arg.defaultValue === undefined; +} + +export function unwrapOutputType(outputType) { + let unwrappedType = outputType; + while (isWrappingType(unwrappedType)) { + unwrappedType = unwrappedType.ofType; + } + return unwrappedType; +} + +export function unwrapInputType(inputType) { + let unwrappedType = inputType; + while (isWrappingType(unwrappedType)) { + unwrappedType = unwrappedType.ofType; + } + return unwrappedType; +} + +export function coerceArgValue(argType, value) { + if (typeof value !== 'string' && value.kind === 'VariableDefinition') { + return value.variable; + } else if (isScalarType(argType)) { + try { + switch (argType.name) { + case 'String': + return { + kind: 'StringValue', + value: String(argType.parseValue(value)), + }; + case 'Float': + return { + kind: 'FloatValue', + value: String(argType.parseValue(parseFloat(value))), + }; + case 'Int': + return { + kind: 'IntValue', + value: String(argType.parseValue(parseInt(value, 10))), + }; + case 'Boolean': + try { + const parsed = JSON.parse(value); + if (typeof parsed === 'boolean') { + return {kind: 'BooleanValue', value: parsed}; + } else { + return {kind: 'BooleanValue', value: false}; + } + } catch (e) { + return { + kind: 'BooleanValue', + value: false, + }; + } + default: + return { + kind: 'StringValue', + value: String(argType.parseValue(value)), + }; + } + } catch (e) { + console.error('error coercing arg value', e, value); + return {kind: 'StringValue', value: value}; + } + } else { + try { + const parsedValue = argType.parseValue(value); + if (parsedValue) { + return {kind: 'EnumValue', value: String(parsedValue)}; + } else { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } + } catch (e) { + return {kind: 'EnumValue', value: argType.getValues()[0].name}; + } + } +} + +export function isRunShortcut(event) { + return event.ctrlKey && event.key === 'Enter'; +} + +export function canRunOperation(operationName) { + return operationName !== 'FragmentDefinition'; +} + +export function defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + fields, +) { + const nodes = []; + for (const field of fields) { + if ( + isRequiredInputField(field) || + (makeDefaultArg && makeDefaultArg(parentField, field)) + ) { + const fieldType = unwrapInputType(field.type); + if (isInputObjectType(fieldType)) { + const fields = fieldType.getFields(); + nodes.push({ + kind: 'ObjectField', + name: {kind: 'Name', value: field.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + parentField, + Object.keys(fields).map(k => fields[k]), + ), + }, + }); + } else if (isLeafType(fieldType)) { + nodes.push({ + kind: 'ObjectField', + name: {kind: 'Name', value: field.name}, + value: getDefaultScalarArgValue(parentField, field, fieldType), + }); + } + } + } + return nodes; +} + +export function defaultArgs( + getDefaultScalarArgValue, + makeDefaultArg, + field, +) { + const args = []; + for (const arg of field.args) { + if ( + isRequiredArgument(arg) || + (makeDefaultArg && makeDefaultArg(field, arg)) + ) { + const argType = unwrapInputType(arg.type); + if (isInputObjectType(argType)) { + const fields = argType.getFields(); + args.push({ + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: { + kind: 'ObjectValue', + fields: defaultInputObjectFields( + getDefaultScalarArgValue, + makeDefaultArg, + field, + Object.keys(fields).map(k => fields[k]), + ), + }, + }); + } else if (isLeafType(argType)) { + args.push({ + kind: 'Argument', + name: {kind: 'Name', value: arg.name}, + value: getDefaultScalarArgValue(field, arg, argType), + }); + } + } + } + return args; +} + +export function parseQuery(text) { + try { + if (!text.trim()) { + return null; + } + return parse( + text, + {noLocation: true}, + ); + } catch (e) { + return new Error(e); + } +} + +export const DEFAULT_OPERATION = { + kind: 'OperationDefinition', + operation: 'query', + variableDefinitions: [], + name: {kind: 'Name', value: 'MyQuery'}, + directives: [], + selectionSet: { + kind: 'SelectionSet', + selections: [], + }, +}; + +export const DEFAULT_DOCUMENT = { + kind: 'Document', + definitions: [DEFAULT_OPERATION], +}; + +let parseQueryMemoize = null; +export function memoizeParseQuery(query) { + if (parseQueryMemoize && parseQueryMemoize[0] === query) { + return parseQueryMemoize[1]; + } else { + const result = parseQuery(query); + if (!result) { + return DEFAULT_DOCUMENT; + } else if (result instanceof Error) { + if (parseQueryMemoize) { + return parseQueryMemoize[1]; + } else { + return DEFAULT_DOCUMENT; + } + } else { + parseQueryMemoize = [query, result]; + return result; + } + } +} + +export const defaultStyles = { + buttonStyle: { + fontSize: '1.2em', + padding: '0px', + backgroundColor: 'white', + border: 'none', + margin: '5px 0px', + height: '40px', + width: '100%', + display: 'block', + maxWidth: 'none', + }, + + actionButtonStyle: { + padding: '0px', + backgroundColor: 'white', + border: 'none', + margin: '0px', + maxWidth: 'none', + height: '15px', + width: '15px', + display: 'inline-block', + fontSize: 'smaller', + }, + + explorerActionsStyle: { + margin: '4px -8px -8px', + paddingLeft: '8px', + bottom: '0px', + width: '100%', + textAlign: 'center', + background: 'none', + borderTop: 'none', + borderBottom: 'none', + }, +}; diff --git a/plugins/third-party-plugin/third-party-plugin.php b/plugins/third-party-plugin/third-party-plugin.php index d3b4ebb..5172f26 100644 --- a/plugins/third-party-plugin/third-party-plugin.php +++ b/plugins/third-party-plugin/third-party-plugin.php @@ -30,12 +30,12 @@ $asset_file['version'] ); - wp_enqueue_style( - 'third-party-plugin', - plugins_url( 'build/index.css', __FILE__ ), - [], - $asset_file['version'], - ); + wp_enqueue_style( + 'third-party-plugin', + plugins_url( 'build/style-index.css', __FILE__ ), + [], + $asset_file['version'], + ); }); diff --git a/src/components/App.jsx b/src/components/App.jsx index dbcb51c..55cdf26 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -2,34 +2,29 @@ import React, { useEffect, useCallback } from 'react'; import { GraphiQL } from './GraphiQL'; import { useDispatch, useSelect, dispatch } from '@wordpress/data'; import { parse, visit } from 'graphql'; -import { explorerPlugin } from '@graphiql/plugin-explorer'; -import { helpPanel as helpPlugin } from '../registry/activity-bar-panels/helpPanel'; - import 'graphiql/graphiql.min.css'; -import '../../styles/explorer.css'; - -const explorer = explorerPlugin(); -const help = helpPlugin(); export function App() { - const query = useSelect( ( select ) => - select( 'wpgraphql-ide/app' ).getQuery() - ); - - const { setQuery } = useDispatch( 'wpgraphql-ide/app' ); - - const shouldRenderStandalone = useSelect( ( select ) => - select( 'wpgraphql-ide/app' ).shouldRenderStandalone() - ); - const { setDrawerOpen, setSchema } = useDispatch( 'wpgraphql-ide/app' ); - - const isAuthenticated = useSelect( ( select ) => - select( 'wpgraphql-ide/app' ).isAuthenticated() - ); - - const schema = useSelect( ( select ) => - select( 'wpgraphql-ide/app' ).schema() - ); + const { + query, + shouldRenderStandalone, + isAuthenticated, + schema, + } = useSelect( ( select ) => { + const wpgraphqlIDEApp = select( 'wpgraphql-ide/app' ); + return { + query: wpgraphqlIDEApp.getQuery(), + shouldRenderStandalone: wpgraphqlIDEApp.shouldRenderStandalone(), + isAuthenticated: wpgraphqlIDEApp.isAuthenticated(), + schema: wpgraphqlIDEApp.schema(), + }; + }); + + const { + setQuery, + setDrawerOpen, + setSchema, + } = useDispatch( 'wpgraphql-ide/app' ); useEffect( () => { // create a ref @@ -56,31 +51,6 @@ export function App() { ); }, [ isAuthenticated ] ); - // const handleEditQuery = (editedQuery) => { - // let update = false; - - // if (editedQuery === query) { - // return; - // } - - // if (null === editedQuery || "" === editedQuery) { - // update = true; - // } else { - // try { - // parse(editedQuery); - // update = true; - // } catch (error) { - // return; - // } - // } - - // // If the query is valid and should be updated - // if (update) { - // // Update the state with the new query - // setQuery(editedQuery); - // } - // }; - const fetcher = useCallback( async ( graphQLParams ) => { let isIntrospectionQuery = false; @@ -151,17 +121,7 @@ export function App() { setSchema( newSchema ); } } } - // plugins={ () => { - // return [ explorer, help ]; - // // return useSelect( ( select ) => select( 'wpgraphql-ide/activity-bar' ).activityPanels() ); - // } } plugins={ activityPanels } - // visiblePlugin={ () => { - // return useSelect( ( select ) => select( 'wpgraphql-ide/activity-bar' ).visibleActivityPanel() ); - // } } - onTogglePluginVisibility={ ( panel ) => { - dispatch( 'wpgraphql-ide/activity-bar' ).toggleActivityPanelVisibility( panel ) - }} > { ! shouldRenderStandalone && ( diff --git a/styles/explorer.css b/styles/explorer.css deleted file mode 100644 index e69de29..0000000 diff --git a/styles/wpgraphql-ide.css b/styles/wpgraphql-ide.css index 7895c6b..61f0795 100644 --- a/styles/wpgraphql-ide.css +++ b/styles/wpgraphql-ide.css @@ -153,83 +153,7 @@ body.graphql_page_graphql-ide .AppRoot { height: 100%; } -/** - * GraphiQL Explorer Styles - */ -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap { - width: 100% !important; - -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .doc-explorer-title { - font-weight: var(--font-weight-medium); - font-size: var(--font-size-h2); - overflow-x: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .doc-explorer-title-bar { - padding: var(--px-16); - padding-bottom: 0; -} -#wpgraphql-ide-app .graphiql-plugin .doc-explorer-rhs { - display: none!important; -} - -#wpgraphql-ide-app .graphiql-plugin .doc-explorer-contents { - height: 100%; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root { - padding: 0!important; -} - -#wpgraphql-ide-app .graphiql-plugin:has(div.docExplorerWrap) { - padding: 0!important; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root > div:first-of-type { - padding: 20px!important; - flex: 3 1 0!important; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root input { - width: auto!important; - padding: 0 8px; - line-height: 2; - min-height: 30px; - box-shadow: 0 0 0 transparent; - border-radius: 4px; - border: 1px solid - hsla(var(--color-neutral), var(--alpha-background-heavy))!important; - background: transparent; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions { - border-top: 1px solid - hsla(var(--color-neutral), var(--alpha-background-heavy))!important; -} -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions > span:first-of-type{ - padding: 10px; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root>div>div { - border-bottom: 1px solid hsla(var(--color-neutral), var(--alpha-background-heavy))!important; - margin-bottom: 15px!important; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root>div>div:last-of-type { - border-bottom: none!important; - margin-bottom: 0!important; -} - -#wpgraphql-ide-app .graphiql-plugin .docExplorerWrap .graphiql-explorer-root .graphiql-explorer-actions > select { - color: hsl(var(--color-primary)); - border: 1px solid - hsla(var(--color-neutral), var(--alpha-background-heavy))!important; - background: transparent; -} .graphiql-container .graphiql-editor-tools>button.active { background-color: hsla(var(--color-neutral), var(--alpha-background-medium)); From df3d98f4f9225b91c7ed303d07d2a2144ae7b67f Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 29 May 2024 16:44:48 -0600 Subject: [PATCH 6/9] - npm run lint:js:fix --- .../src/components/AbstractArgView.jsx | 384 ++++++------ .../src/components/AbstractView.jsx | 128 ++-- .../src/components/ArgView.jsx | 157 ++--- .../src/components/ArrowClosed.jsx | 4 +- .../src/components/ArrowOpen.jsx | 4 +- .../src/components/Checkbox.jsx | 22 +- .../src/components/DefaultArrowClosed.jsx | 4 +- .../src/components/DefaultArrowOpen.jsx | 4 +- .../src/components/ErrorBoundary.jsx | 24 +- .../src/components/ExplorerView.jsx | 413 +++++++------ .../src/components/ExplorerWrapper.jsx | 28 +- .../src/components/FieldView.jsx | 581 ++++++++++-------- .../src/components/FragmentView.jsx | 54 +- .../src/components/InputArgView.jsx | 134 ++-- .../src/components/QueryComposer.js | 25 +- .../src/components/RootView.jsx | 201 +++--- .../src/components/ScalarInput.jsx | 41 +- plugins/third-party-plugin/src/index.js | 43 +- plugins/third-party-plugin/src/utils.js | 270 ++++---- plugins/third-party-plugin/webpack.config.js | 21 +- src/access-functions.js | 11 +- src/components/App.jsx | 43 +- src/index.js | 4 +- .../helpPanel/HelpIcon.jsx | 16 +- .../activity-bar-panels/helpPanel/index.js | 7 +- src/render.js | 16 +- .../activity-bar/activity-bar-reducer.js | 9 +- .../primary-sidebar-actions.js | 4 +- webpack.config.js | 17 +- 29 files changed, 1428 insertions(+), 1241 deletions(-) diff --git a/plugins/third-party-plugin/src/components/AbstractArgView.jsx b/plugins/third-party-plugin/src/components/AbstractArgView.jsx index b8ddb99..44efcff 100644 --- a/plugins/third-party-plugin/src/components/AbstractArgView.jsx +++ b/plugins/third-party-plugin/src/components/AbstractArgView.jsx @@ -1,35 +1,44 @@ -import React from "react"; -import {isRequiredArgument, unwrapInputType} from "../utils"; -import {isEnumType, isInputObjectType, isScalarType, parseType, visit} from "graphql"; -import ScalarInput from "./ScalarInput"; -import InputArgView from "./InputArgView"; -import Checkbox from "./Checkbox"; +import React from 'react'; +import { isRequiredArgument, unwrapInputType } from '../utils'; +import { + isEnumType, + isInputObjectType, + isScalarType, + parseType, + visit, +} from 'graphql'; +import ScalarInput from './ScalarInput'; +import InputArgView from './InputArgView'; +import Checkbox from './Checkbox'; class AbstractArgView extends React.PureComponent { - state = {displayArgActions: false}; + state = { displayArgActions: false }; render() { - const {argValue, arg, styleConfig} = this.props; - const argType = unwrapInputType(arg.type); + const { argValue, arg, styleConfig } = this.props; + const argType = unwrapInputType( arg.type ); let input = null; - if (argValue) { - if (argValue.kind === 'Variable') { + if ( argValue ) { + if ( argValue.kind === 'Variable' ) { input = ( - - ${argValue.name.value} - + + ${ argValue.name.value } + ); - } else if (isScalarType(argType)) { - if (argType.name === 'Boolean') { + } else if ( isScalarType( argType ) ) { + if ( argType.name === 'Boolean' ) { input = ( - {argType.getValues().map(value => ( - - ))} + ) ) } ); } else { console.error( 'arg mismatch between arg and selection', argType, - argValue, + argValue ); } - } else if (isInputObjectType(argType)) { - if (argValue.kind === 'ObjectValue') { + } else if ( isInputObjectType( argType ) ) { + if ( argValue.kind === 'ObjectValue' ) { const fields = argType.getFields(); input = ( -
- {Object.keys(fields) +
+ { Object.keys( fields ) .sort() - .map(fieldName => ( + .map( ( fieldName ) => ( - ))} + ) ) }
); } else { console.error( 'arg mismatch between arg and selection', argType, - argValue, + argValue ); } } @@ -113,18 +127,18 @@ class AbstractArgView extends React.PureComponent { const baseVariableName = arg.name; const conflictingNameCount = ( this.props.definition.variableDefinitions || [] - ).filter(varDef => - varDef.variable.name.value.startsWith(baseVariableName), + ).filter( ( varDef ) => + varDef.variable.name.value.startsWith( baseVariableName ) ).length; let variableName; - if (conflictingNameCount > 0) { - variableName = `${baseVariableName}${conflictingNameCount}`; + if ( conflictingNameCount > 0 ) { + variableName = `${ baseVariableName }${ conflictingNameCount }`; } else { variableName = baseVariableName; } const argPrintedType = arg.type.toString(); - const argType = parseType(argPrintedType); + const argType = parseType( argPrintedType ); const base = { kind: 'VariableDefinition', @@ -139,71 +153,82 @@ class AbstractArgView extends React.PureComponent { directives: [], }; - const variableDefinitionByName = name => - (this.props.definition.variableDefinitions || []).find( - varDef => varDef.variable.name.value === name, + const variableDefinitionByName = ( name ) => + ( this.props.definition.variableDefinitions || [] ).find( + ( varDef ) => varDef.variable.name.value === name ); let variable; - let subVariableUsageCountByName = {}; + const subVariableUsageCountByName = {}; - if (typeof argValue !== 'undefined' && argValue !== null) { - const cleanedDefaultValue = visit(argValue, { - Variable(node) { + if ( typeof argValue !== 'undefined' && argValue !== null ) { + const cleanedDefaultValue = visit( argValue, { + Variable( node ) { const varName = node.name.value; - const varDef = variableDefinitionByName(varName); + const varDef = variableDefinitionByName( varName ); - subVariableUsageCountByName[varName] = - subVariableUsageCountByName[varName] + 1 || 1; + subVariableUsageCountByName[ varName ] = + subVariableUsageCountByName[ varName ] + 1 || 1; - if (!varDef) { + if ( ! varDef ) { return; } return varDef.defaultValue; }, - }); + } ); const isNonNullable = base.type.kind === 'NonNullType'; const unwrappedBase = isNonNullable - ? {...base, type: base.type.type} + ? { ...base, type: base.type.type } : base; - variable = {...unwrappedBase, defaultValue: cleanedDefaultValue}; + variable = { + ...unwrappedBase, + defaultValue: cleanedDefaultValue, + }; } else { variable = base; } - const newlyUnusedVariables = Object.entries(subVariableUsageCountByName) - .filter(([_, usageCount]) => usageCount < 2) - .map(([varName, _]) => varName); - - if (variable) { - const newDoc = this.props.setArgValue(variable, false); - - if (newDoc) { - const targetOperation = newDoc.definitions.find(definition => { - if ( - !!definition.operation && - !!definition.name && - !!definition.name.value && - !!this.props.definition.name && - !!this.props.definition.name.value - ) { - return definition.name.value === this.props.definition.name.value; - } else { + const newlyUnusedVariables = Object.entries( + subVariableUsageCountByName + ) + .filter( ( [ _, usageCount ] ) => usageCount < 2 ) + .map( ( [ varName, _ ] ) => varName ); + + if ( variable ) { + const newDoc = this.props.setArgValue( variable, false ); + + if ( newDoc ) { + const targetOperation = newDoc.definitions.find( + ( definition ) => { + if ( + !! definition.operation && + !! definition.name && + !! definition.name.value && + !! this.props.definition.name && + !! this.props.definition.name.value + ) { + return ( + definition.name.value === + this.props.definition.name.value + ); + } return false; } - }); + ); const newVariableDefinitions = [ - ...(targetOperation.variableDefinitions || []), + ...( targetOperation.variableDefinitions || [] ), variable, ].filter( - varDef => - newlyUnusedVariables.indexOf(varDef.variable.name.value) === -1, + ( varDef ) => + newlyUnusedVariables.indexOf( + varDef.variable.name.value + ) === -1 ); const newOperation = { @@ -213,69 +238,73 @@ class AbstractArgView extends React.PureComponent { const existingDefs = newDoc.definitions; - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { - return newOperation; - } else { + const newDefinitions = existingDefs.map( + ( existingOperation ) => { + if ( targetOperation === existingOperation ) { + return newOperation; + } return existingOperation; } - }); + ); const finalDoc = { ...newDoc, definitions: newDefinitions, }; - this.props.onCommit(finalDoc); + this.props.onCommit( finalDoc ); } } }; const devariablize = () => { - if (!argValue || !argValue.name || !argValue.name.value) { + if ( ! argValue || ! argValue.name || ! argValue.name.value ) { return; } const variableName = argValue.name.value; const variableDefinition = ( this.props.definition.variableDefinitions || [] - ).find(varDef => varDef.variable.name.value === variableName); + ).find( ( varDef ) => varDef.variable.name.value === variableName ); - if (!variableDefinition) { + if ( ! variableDefinition ) { return; } const defaultValue = variableDefinition.defaultValue; - const newDoc = this.props.setArgValue(defaultValue, { + const newDoc = this.props.setArgValue( defaultValue, { commit: false, - }); + } ); - if (newDoc) { + if ( newDoc ) { const targetOperation = newDoc.definitions.find( - definition => - definition.name.value === this.props.definition.name.value, + ( definition ) => + definition.name.value === + this.props.definition.name.value ); - if (!targetOperation) { + if ( ! targetOperation ) { return; } let variableUseCount = 0; - visit(targetOperation, { - Variable(node) { - if (node.name.value === variableName) { + visit( targetOperation, { + Variable( node ) { + if ( node.name.value === variableName ) { variableUseCount = variableUseCount + 1; } }, - }); + } ); - let newVariableDefinitions = targetOperation.variableDefinitions || []; + let newVariableDefinitions = + targetOperation.variableDefinitions || []; - if (variableUseCount < 2) { + if ( variableUseCount < 2 ) { newVariableDefinitions = newVariableDefinitions.filter( - varDef => varDef.variable.name.value !== variableName, + ( varDef ) => + varDef.variable.name.value !== variableName ); } @@ -286,26 +315,27 @@ class AbstractArgView extends React.PureComponent { const existingDefs = newDoc.definitions; - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { - return newOperation; - } else { + const newDefinitions = existingDefs.map( + ( existingOperation ) => { + if ( targetOperation === existingOperation ) { + return newOperation; + } return existingOperation; } - }); + ); const finalDoc = { ...newDoc, definitions: newDefinitions, }; - this.props.onCommit(finalDoc); + this.props.onCommit( finalDoc ); } }; const isArgValueVariable = argValue && argValue.kind === 'Variable'; - const variablizeActionButton = !this.state.displayArgActions ? null : ( + const variablizeActionButton = ! this.state.displayArgActions ? null : ( ); return (
- { - const shouldAdd = !argValue; - if (shouldAdd) { - this.props.addArg(true); - } else { - this.props.removeArg(true); - } - this.setState({displayArgActions: shouldAdd}); - }}> - {isInputObjectType(argType) ? ( - - {!!argValue - ? this.props.styleConfig.arrowOpen - : this.props.styleConfig.arrowClosed} - - ) : ( - - )} - { - if (argValue !== null && typeof argValue !== 'undefined') { - this.setState({displayArgActions: true}); - } - }} - onMouseLeave={() => this.setState({displayArgActions: false})}> - {arg.name} - {isRequiredArgument(arg) ? '*' : ''}: {variablizeActionButton}{' '} - {' '} - - {input || }{' '} + } } + data-arg-name={ arg.name } + data-arg-type={ argType.name } + className={ `graphiql-explorer-${ arg.name }` } + > + { + const shouldAdd = ! argValue; + if ( shouldAdd ) { + this.props.addArg( true ); + } else { + this.props.removeArg( true ); + } + this.setState( { displayArgActions: shouldAdd } ); + } } + > + { isInputObjectType( argType ) ? ( + + { !! argValue + ? this.props.styleConfig.arrowOpen + : this.props.styleConfig.arrowClosed } + + ) : ( + + ) } + { + if ( + argValue !== null && + typeof argValue !== 'undefined' + ) { + this.setState( { displayArgActions: true } ); + } + } } + onMouseLeave={ () => + this.setState( { displayArgActions: false } ) + } + > + { arg.name } + { isRequiredArgument( arg ) ? '*' : '' }:{ ' ' } + { variablizeActionButton }{ ' ' } + { ' ' } + + { input || }{ ' ' }
); } diff --git a/plugins/third-party-plugin/src/components/AbstractView.jsx b/plugins/third-party-plugin/src/components/AbstractView.jsx index 94ed840..3f1ac27 100644 --- a/plugins/third-party-plugin/src/components/AbstractView.jsx +++ b/plugins/third-party-plugin/src/components/AbstractView.jsx @@ -1,62 +1,69 @@ -import React from "react"; -import Checkbox from "./Checkbox"; +import React from 'react'; +import Checkbox from './Checkbox'; class AbstractView extends React.PureComponent { _previousSelection; _addFragment = () => { - this.props.modifySelections([ + this.props.modifySelections( [ ...this.props.selections, this._previousSelection || { kind: 'InlineFragment', typeCondition: { kind: 'NamedType', - name: {kind: 'Name', value: this.props.implementingType.name}, + name: { + kind: 'Name', + value: this.props.implementingType.name, + }, }, selectionSet: { kind: 'SelectionSet', selections: this.props - .getDefaultFieldNames(this.props.implementingType) - .map(fieldName => ({ + .getDefaultFieldNames( this.props.implementingType ) + .map( ( fieldName ) => ( { kind: 'Field', - name: {kind: 'Name', value: fieldName}, - })), + name: { kind: 'Name', value: fieldName }, + } ) ), }, }, - ]); + ] ); }; _removeFragment = () => { const thisSelection = this._getSelection(); this._previousSelection = thisSelection; this.props.modifySelections( - this.props.selections.filter(s => s !== thisSelection), + this.props.selections.filter( ( s ) => s !== thisSelection ) ); }; _getSelection = () => { const selection = this.props.selections.find( - selection => + ( selection ) => selection.kind === 'InlineFragment' && selection.typeCondition && - this.props.implementingType.name === selection.typeCondition.name.value, + this.props.implementingType.name === + selection.typeCondition.name.value ); - if (!selection) { + if ( ! selection ) { return null; } - if (selection.kind === 'InlineFragment') { + if ( selection.kind === 'InlineFragment' ) { return selection; } }; - _modifyChildSelections = (selections, options) => { + _modifyChildSelections = ( selections, options ) => { const thisSelection = this._getSelection(); return this.props.modifySelections( - this.props.selections.map(selection => { - if (selection === thisSelection) { + this.props.selections.map( ( selection ) => { + if ( selection === thisSelection ) { return { directives: selection.directives, kind: 'InlineFragment', typeCondition: { kind: 'NamedType', - name: {kind: 'Name', value: this.props.implementingType.name}, + name: { + kind: 'Name', + value: this.props.implementingType.name, + }, }, selectionSet: { kind: 'SelectionSet', @@ -65,18 +72,14 @@ class AbstractView extends React.PureComponent { }; } return selection; - }), - options, + } ), + options ); }; render() { - const { - implementingType, - schema, - getDefaultFieldNames, - styleConfig, - } = this.props; + const { implementingType, schema, getDefaultFieldNames, styleConfig } = + this.props; const selection = this._getSelection(); const fields = implementingType.getFields(); const childSelections = selection @@ -86,41 +89,52 @@ class AbstractView extends React.PureComponent { : []; return ( -
- - - - {this.props.implementingType.name} - - - {selection ? ( -
- {Object.keys(fields) +
+ + + + { this.props.implementingType.name } + + + { selection ? ( +
+ { Object.keys( fields ) .sort() - .map(fieldName => ( + .map( ( fieldName ) => ( - ))} + ) ) }
- ) : null} + ) : null }
); } diff --git a/plugins/third-party-plugin/src/components/ArgView.jsx b/plugins/third-party-plugin/src/components/ArgView.jsx index f7d64b8..6de0153 100644 --- a/plugins/third-party-plugin/src/components/ArgView.jsx +++ b/plugins/third-party-plugin/src/components/ArgView.jsx @@ -1,27 +1,29 @@ -import React from "react"; -import {coerceArgValue, unwrapInputType} from "../utils"; -import {isInputObjectType, isLeafType} from "graphql"; -import AbstractArgView from "./AbstractArgView"; +import React from 'react'; +import { coerceArgValue, unwrapInputType } from '../utils'; +import { isInputObjectType, isLeafType } from 'graphql'; +import AbstractArgView from './AbstractArgView'; class ArgView extends React.PureComponent { _previousArgSelection; _getArgSelection = () => { - const {selection} = this.props; + const { selection } = this.props; - return (selection.arguments || []).find( - arg => arg.name.value === this.props.arg.name, + return ( selection.arguments || [] ).find( + ( arg ) => arg.name.value === this.props.arg.name ); }; - _removeArg = commit => { - const {selection} = this.props; + _removeArg = ( commit ) => { + const { selection } = this.props; const argSelection = this._getArgSelection(); this._previousArgSelection = argSelection; return this.props.modifyArguments( - (selection.arguments || []).filter(arg => arg !== argSelection), - commit, + ( selection.arguments || [] ).filter( + ( arg ) => arg !== argSelection + ), + commit ); }; - _addArg = commit => { + _addArg = ( commit ) => { const { selection, getDefaultScalarArgValue, @@ -29,147 +31,148 @@ class ArgView extends React.PureComponent { parentField, arg, } = this.props; - const argType = unwrapInputType(arg.type); + const argType = unwrapInputType( arg.type ); let argSelection = null; - if (this._previousArgSelection) { + if ( this._previousArgSelection ) { argSelection = this._previousArgSelection; - } else if (isInputObjectType(argType)) { + } else if ( isInputObjectType( argType ) ) { const fields = argType.getFields(); argSelection = { kind: 'Argument', - name: {kind: 'Name', value: arg.name}, + name: { kind: 'Name', value: arg.name }, value: { kind: 'ObjectValue', fields: defaultInputObjectFields( getDefaultScalarArgValue, makeDefaultArg, parentField, - Object.keys(fields).map(k => fields[k]), + Object.keys( fields ).map( ( k ) => fields[ k ] ) ), }, }; - } else if (isLeafType(argType)) { + } else if ( isLeafType( argType ) ) { argSelection = { kind: 'Argument', - name: {kind: 'Name', value: arg.name}, - value: getDefaultScalarArgValue(parentField, arg, argType), + name: { kind: 'Name', value: arg.name }, + value: getDefaultScalarArgValue( parentField, arg, argType ), }; } - if (!argSelection) { - console.error('Unable to add arg for argType', argType); + if ( ! argSelection ) { + console.error( 'Unable to add arg for argType', argType ); return null; - } else { - return this.props.modifyArguments( - [...(selection.arguments || []), argSelection], - commit, - ); } + return this.props.modifyArguments( + [ ...( selection.arguments || [] ), argSelection ], + commit + ); }; - _setArgValue = (event, options) => { + _setArgValue = ( event, options ) => { let settingToNull = false; let settingToVariable = false; let settingToLiteralValue = false; try { - if (event.kind === 'VariableDefinition') { + if ( event.kind === 'VariableDefinition' ) { settingToVariable = true; - } else if (event === null || typeof event === 'undefined') { + } else if ( event === null || typeof event === 'undefined' ) { settingToNull = true; - } else if (typeof event.kind === 'string') { + } else if ( typeof event.kind === 'string' ) { settingToLiteralValue = true; } - } catch (e) {} - const {selection} = this.props; + } catch ( e ) {} + const { selection } = this.props; const argSelection = this._getArgSelection(); - if (!argSelection && !settingToVariable) { - console.error('missing arg selection when setting arg value'); + if ( ! argSelection && ! settingToVariable ) { + console.error( 'missing arg selection when setting arg value' ); return; } - const argType = unwrapInputType(this.props.arg.type); + const argType = unwrapInputType( this.props.arg.type ); const handleable = - isLeafType(argType) || + isLeafType( argType ) || settingToVariable || settingToNull || settingToLiteralValue; - if (!handleable) { - console.warn('Unable to handle non leaf types in ArgView._setArgValue'); + if ( ! handleable ) { + console.warn( + 'Unable to handle non leaf types in ArgView._setArgValue' + ); return; } let targetValue; let value; - if (event === null || typeof event === 'undefined') { + if ( event === null || typeof event === 'undefined' ) { value = null; - } else if (event.target && typeof event.target.value === 'string') { + } else if ( event.target && typeof event.target.value === 'string' ) { targetValue = event.target.value; - value = coerceArgValue(argType, targetValue); - } else if (!event.target && event.kind === 'VariableDefinition') { + value = coerceArgValue( argType, targetValue ); + } else if ( ! event.target && event.kind === 'VariableDefinition' ) { targetValue = event; value = targetValue.variable; - } else if (typeof event.kind === 'string') { + } else if ( typeof event.kind === 'string' ) { value = event; } return this.props.modifyArguments( - (selection.arguments || []).map(a => + ( selection.arguments || [] ).map( ( a ) => a === argSelection ? { - ...a, - value: value, - } - : a, + ...a, + value, + } + : a ), - options, + options ); }; - _setArgFields = (fields, commit) => { - const {selection} = this.props; + _setArgFields = ( fields, commit ) => { + const { selection } = this.props; const argSelection = this._getArgSelection(); - if (!argSelection) { - console.error('missing arg selection when setting arg value'); + if ( ! argSelection ) { + console.error( 'missing arg selection when setting arg value' ); return; } return this.props.modifyArguments( - (selection.arguments || []).map(a => + ( selection.arguments || [] ).map( ( a ) => a === argSelection ? { - ...a, - value: { - kind: 'ObjectValue', - fields, - }, - } - : a, + ...a, + value: { + kind: 'ObjectValue', + fields, + }, + } + : a ), - commit, + commit ); }; render() { - const {arg, parentField} = this.props; + const { arg, parentField } = this.props; const argSelection = this._getArgSelection(); return ( ); } diff --git a/plugins/third-party-plugin/src/components/ArrowClosed.jsx b/plugins/third-party-plugin/src/components/ArrowClosed.jsx index cc6809c..c710b2c 100644 --- a/plugins/third-party-plugin/src/components/ArrowClosed.jsx +++ b/plugins/third-party-plugin/src/components/ArrowClosed.jsx @@ -1,12 +1,12 @@ const ArrowClosed = () => ( ( @@ -17,12 +17,12 @@ export const checkboxUnchecked = ( export const checkboxChecked = ( + xmlns="http://www.w3.org/2000/svg" + > + xmlns="http://www.w3.org/2000/svg" + > ); -export default function Checkbox(props) { +export default function Checkbox( props ) { return props.checked ? props.styleConfig.checkboxChecked : props.styleConfig.checkboxUnchecked; diff --git a/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx b/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx index e254e8a..096e46e 100644 --- a/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx +++ b/plugins/third-party-plugin/src/components/DefaultArrowClosed.jsx @@ -1,6 +1,6 @@ -import React from "react"; +import React from 'react'; -export default function DefaultArrowOpen(){ +export default function DefaultArrowOpen() { return ( diff --git a/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx b/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx index 8089c35..1ba64f8 100644 --- a/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx +++ b/plugins/third-party-plugin/src/components/DefaultArrowOpen.jsx @@ -1,6 +1,6 @@ -import React from "react"; +import React from 'react'; -export default function DefaultArrowOpen(){ +export default function DefaultArrowOpen() { return ( diff --git a/plugins/third-party-plugin/src/components/ErrorBoundary.jsx b/plugins/third-party-plugin/src/components/ErrorBoundary.jsx index 53781ed..4c8a3e3 100644 --- a/plugins/third-party-plugin/src/components/ErrorBoundary.jsx +++ b/plugins/third-party-plugin/src/components/ErrorBoundary.jsx @@ -1,22 +1,26 @@ -import React from "react"; +import React from 'react'; class ErrorBoundary extends React.Component { - state = {hasError: false, error: null, errorInfo: null}; + state = { hasError: false, error: null, errorInfo: null }; - componentDidCatch(error, errorInfo) { - this.setState({hasError: true, error: error, errorInfo: errorInfo}); - console.error('Error in component', error, errorInfo); + componentDidCatch( error, errorInfo ) { + this.setState( { hasError: true, error, errorInfo } ); + console.error( 'Error in component', error, errorInfo ); } render() { - if (this.state.hasError) { + if ( this.state.hasError ) { return ( -
+
Something went wrong
-
- {this.state.error ? this.state.error.toString() : null} +
+ { this.state.error + ? this.state.error.toString() + : null }
- {this.state.errorInfo ? this.state.errorInfo.componentStack : null} + { this.state.errorInfo + ? this.state.errorInfo.componentStack + : null }
); diff --git a/plugins/third-party-plugin/src/components/ExplorerView.jsx b/plugins/third-party-plugin/src/components/ExplorerView.jsx index 3f61403..6363db1 100644 --- a/plugins/third-party-plugin/src/components/ExplorerView.jsx +++ b/plugins/third-party-plugin/src/components/ExplorerView.jsx @@ -1,17 +1,17 @@ -import React from "react"; +import React from 'react'; import { capitalize, DEFAULT_DOCUMENT, defaultColors, - defaultGetDefaultFieldNames, defaultGetDefaultScalarArgValue, + defaultGetDefaultFieldNames, + defaultGetDefaultScalarArgValue, defaultStyles, - memoizeParseQuery -} from "../utils"; -import {GraphQLObjectType, print} from "graphql"; -import RootView from "./RootView"; + memoizeParseQuery, +} from '../utils'; +import { GraphQLObjectType, print } from 'graphql'; +import RootView from './RootView'; class ExplorerView extends React.PureComponent { - state = { newOperationType: 'query', operation: null, @@ -21,7 +21,7 @@ class ExplorerView extends React.PureComponent { _ref; _resetScroll = () => { const container = this._ref; - if (container) { + if ( container ) { container.scrollLeft = 0; } }; @@ -29,99 +29,103 @@ class ExplorerView extends React.PureComponent { this._resetScroll(); } - _onEdit = query => this.props.onEdit(query); + _onEdit = ( query ) => this.props.onEdit( query ); - _setAddOperationType = value => { - this.setState({newOperationType: value}); + _setAddOperationType = ( value ) => { + this.setState( { newOperationType: value } ); }; - _handleRootViewMount = rootViewElId => { + _handleRootViewMount = ( rootViewElId ) => { if ( - !!this.state.operationToScrollTo && + !! this.state.operationToScrollTo && this.state.operationToScrollTo === rootViewElId ) { - var selector = `.graphiql-explorer-root #${rootViewElId}`; + const selector = `.graphiql-explorer-root #${ rootViewElId }`; - var el = document.querySelector(selector); + const el = document.querySelector( selector ); el && el.scrollIntoView(); } }; render() { - const {schema, query, makeDefaultArg} = this.props; + const { schema, query, makeDefaultArg } = this.props; - if (!schema) { + if ( ! schema ) { return ( -
+
No Schema Available
); } const styleConfig = { colors: this.props.colors || defaultColors, - checkboxChecked: this.props.checkboxChecked || defaultCheckboxChecked, + checkboxChecked: + this.props.checkboxChecked || defaultCheckboxChecked, checkboxUnchecked: this.props.checkboxUnchecked || defaultCheckboxUnchecked, arrowClosed: this.props.arrowClosed || defaultArrowClosed, arrowOpen: this.props.arrowOpen || defaultArrowOpen, styles: this.props.styles ? { - ...defaultStyles, - ...this.props.styles, - } + ...defaultStyles, + ...this.props.styles, + } : defaultStyles, }; const queryType = schema.getQueryType(); const mutationType = schema.getMutationType(); const subscriptionType = schema.getSubscriptionType(); - if (!queryType && !mutationType && !subscriptionType) { + if ( ! queryType && ! mutationType && ! subscriptionType ) { return
Missing query type
; } const queryFields = queryType && queryType.getFields(); const mutationFields = mutationType && mutationType.getFields(); - const subscriptionFields = subscriptionType && subscriptionType.getFields(); + const subscriptionFields = + subscriptionType && subscriptionType.getFields(); - const parsedQuery = memoizeParseQuery(query); + const parsedQuery = memoizeParseQuery( query ); const getDefaultFieldNames = this.props.getDefaultFieldNames || defaultGetDefaultFieldNames; const getDefaultScalarArgValue = - this.props.getDefaultScalarArgValue || defaultGetDefaultScalarArgValue; + this.props.getDefaultScalarArgValue || + defaultGetDefaultScalarArgValue; const definitions = parsedQuery.definitions; const _relevantOperations = definitions - .map(definition => { - if (definition.kind === 'FragmentDefinition') { + .map( ( definition ) => { + if ( definition.kind === 'FragmentDefinition' ) { return definition; - } else if (definition.kind === 'OperationDefinition') { + } else if ( definition.kind === 'OperationDefinition' ) { return definition; - } else { - return null; } - }) - .filter(Boolean); + return null; + } ) + .filter( Boolean ); const relevantOperations = _relevantOperations.length === 0 ? DEFAULT_DOCUMENT.definitions : _relevantOperations; - const renameOperation = (targetOperation, name) => { + const renameOperation = ( targetOperation, name ) => { const newName = name == null || name === '' ? null - : {kind: 'Name', value: name, loc: undefined}; - const newOperation = {...targetOperation, name: newName}; + : { kind: 'Name', value: name, loc: undefined }; + const newOperation = { ...targetOperation, name: newName }; const existingDefs = parsedQuery.definitions; - const newDefinitions = existingDefs.map(existingOperation => { - if (targetOperation === existingOperation) { + const newDefinitions = existingDefs.map( ( existingOperation ) => { + if ( targetOperation === existingOperation ) { return newOperation; - } else { - return existingOperation; } - }); + return existingOperation; + } ); return { ...parsedQuery, @@ -129,16 +133,17 @@ class ExplorerView extends React.PureComponent { }; }; - const cloneOperation = targetOperation => { + const cloneOperation = ( targetOperation ) => { let kind; - if (targetOperation.kind === 'FragmentDefinition') { + if ( targetOperation.kind === 'FragmentDefinition' ) { kind = 'fragment'; } else { kind = targetOperation.operation; } const newOperationName = - ((targetOperation.name && targetOperation.name.value) || '') + 'Copy'; + ( ( targetOperation.name && targetOperation.name.value ) || + '' ) + 'Copy'; const newName = { kind: 'Name', @@ -146,13 +151,15 @@ class ExplorerView extends React.PureComponent { loc: undefined, }; - const newOperation = {...targetOperation, name: newName}; + const newOperation = { ...targetOperation, name: newName }; const existingDefs = parsedQuery.definitions; - const newDefinitions = [...existingDefs, newOperation]; + const newDefinitions = [ ...existingDefs, newOperation ]; - this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + this.setState( { + operationToScrollTo: `${ kind }-${ newOperationName }`, + } ); return { ...parsedQuery, @@ -160,16 +167,17 @@ class ExplorerView extends React.PureComponent { }; }; - const destroyOperation = targetOperation => { + const destroyOperation = ( targetOperation ) => { const existingDefs = parsedQuery.definitions; - const newDefinitions = existingDefs.filter(existingOperation => { - if (targetOperation === existingOperation) { - return false; - } else { + const newDefinitions = existingDefs.filter( + ( existingOperation ) => { + if ( targetOperation === existingOperation ) { + return false; + } return true; } - }); + ); return { ...parsedQuery, @@ -177,24 +185,24 @@ class ExplorerView extends React.PureComponent { }; }; - const addOperation = kind => { + const addOperation = ( kind ) => { const existingDefs = parsedQuery.definitions; const viewingDefaultOperation = parsedQuery.definitions.length === 1 && - parsedQuery.definitions[0] === DEFAULT_DOCUMENT.definitions[0]; + parsedQuery.definitions[ 0 ] === + DEFAULT_DOCUMENT.definitions[ 0 ]; const MySiblingDefs = viewingDefaultOperation ? [] - : existingDefs.filter(def => { - if (def.kind === 'OperationDefinition') { - return def.operation === kind; - } else { + : existingDefs.filter( ( def ) => { + if ( def.kind === 'OperationDefinition' ) { + return def.operation === kind; + } return false; - } - }); + } ); - const newOperationName = `My${capitalize(kind)}${ + const newOperationName = `My${ capitalize( kind ) }${ MySiblingDefs.length === 0 ? '' : MySiblingDefs.length + 1 }`; @@ -222,106 +230,119 @@ class ExplorerView extends React.PureComponent { const newDefinition = { kind: 'OperationDefinition', operation: kind, - name: {kind: 'Name', value: newOperationName}, + name: { kind: 'Name', value: newOperationName }, variableDefinitions: [], directives: [], - selectionSet: selectionSet, + selectionSet, loc: null, }; - const newDefinitions = - viewingDefaultOperation - ? [newDefinition] - : [...parsedQuery.definitions, newDefinition]; + const newDefinitions = viewingDefaultOperation + ? [ newDefinition ] + : [ ...parsedQuery.definitions, newDefinition ]; const newOperationDef = { ...parsedQuery, definitions: newDefinitions, }; - this.setState({operationToScrollTo: `${kind}-${newOperationName}`}); + this.setState( { + operationToScrollTo: `${ kind }-${ newOperationName }`, + } ); - this.props.onEdit(print(newOperationDef)); + this.props.onEdit( print( newOperationDef ) ); }; const actionsOptions = [ - !!queryFields ? ( + !! queryFields ? ( ) : null, - !!mutationFields ? ( + !! mutationFields ? ( ) : null, - !!subscriptionFields ? ( + !! subscriptionFields ? ( ) : null, - ].filter(Boolean); + ].filter( Boolean ); const actionsEl = actionsOptions.length === 0 || this.props.hideActions ? null : (
+ } } + >
event.preventDefault()}> - - Add new{' '} - + } } + onSubmit={ ( event ) => event.preventDefault() } + > + + Add new{ ' ' } +
@@ -330,53 +351,62 @@ class ExplorerView extends React.PureComponent { const externalFragments = this.props.externalFragments && - this.props.externalFragments.reduce((acc, fragment) => { - if (fragment.kind === 'FragmentDefinition') { + this.props.externalFragments.reduce( ( acc, fragment ) => { + if ( fragment.kind === 'FragmentDefinition' ) { const fragmentTypeName = fragment.typeCondition.name.value; - const existingFragmentsForType = acc[fragmentTypeName] || []; + const existingFragmentsForType = + acc[ fragmentTypeName ] || []; const newFragmentsForType = [ ...existingFragmentsForType, fragment, - ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + ].sort( ( a, b ) => + a.name.value.localeCompare( b.name.value ) + ); return { ...acc, - [fragmentTypeName]: newFragmentsForType, + [ fragmentTypeName ]: newFragmentsForType, }; } return acc; - }, {}); + }, {} ); const documentFragments = relevantOperations.reduce( - (acc, operation) => { - if (operation.kind === 'FragmentDefinition') { + ( acc, operation ) => { + if ( operation.kind === 'FragmentDefinition' ) { const fragmentTypeName = operation.typeCondition.name.value; - const existingFragmentsForType = acc[fragmentTypeName] || []; + const existingFragmentsForType = + acc[ fragmentTypeName ] || []; const newFragmentsForType = [ ...existingFragmentsForType, operation, - ].sort((a, b) => a.name.value.localeCompare(b.name.value)); + ].sort( ( a, b ) => + a.name.value.localeCompare( b.name.value ) + ); return { ...acc, - [fragmentTypeName]: newFragmentsForType, + [ fragmentTypeName ]: newFragmentsForType, }; } return acc; }, - {}, + {} ); - const availableFragments = {...documentFragments, ...externalFragments}; + const availableFragments = { + ...documentFragments, + ...externalFragments, + }; const attribution = this.props.showAttribution ? : null; return (
{ + ref={ ( ref ) => { this._ref = ref; - }} - style={{ + } } + style={ { fontSize: 12, textOverflow: 'ellipsis', whiteSpace: 'nowrap', @@ -387,41 +417,50 @@ class ExplorerView extends React.PureComponent { display: 'flex', flexDirection: 'column', height: '100%', - }} - className="graphiql-explorer-root"> + } } + className="graphiql-explorer-root" + >
- {relevantOperations.map((operation, index) => { + } } + > + { relevantOperations.map( ( operation, index ) => { const operationName = operation && operation.name && operation.name.value; const operationType = operation.kind === 'FragmentDefinition' ? 'fragment' - : (operation && operation.operation) || 'query'; - - const onOperationRename = newName => { - const newOperationDef = renameOperation(operation, newName); - this.props.onEdit(print(newOperationDef)); + : ( operation && operation.operation ) || + 'query'; + + const onOperationRename = ( newName ) => { + const newOperationDef = renameOperation( + operation, + newName + ); + this.props.onEdit( print( newOperationDef ) ); }; const onOperationClone = () => { - const newOperationDef = cloneOperation(operation); - this.props.onEdit(print(newOperationDef)); + const newOperationDef = cloneOperation( operation ); + this.props.onEdit( print( newOperationDef ) ); }; const onOperationDestroy = () => { - const newOperationDef = destroyOperation(operation); - this.props.onEdit(print(newOperationDef)); + const newOperationDef = + destroyOperation( operation ); + this.props.onEdit( print( newOperationDef ) ); }; const fragmentType = operation.kind === 'FragmentDefinition' && operation.typeCondition.kind === 'NamedType' && - schema.getType(operation.typeCondition.name.value); + schema.getType( + operation.typeCondition.name.value + ); const fragmentFields = fragmentType instanceof GraphQLObjectType @@ -432,39 +471,41 @@ class ExplorerView extends React.PureComponent { operationType === 'query' ? queryFields : operationType === 'mutation' - ? mutationFields - : operationType === 'subscription' - ? subscriptionFields - : operation.kind === 'FragmentDefinition' - ? fragmentFields - : null; + ? mutationFields + : operationType === 'subscription' + ? subscriptionFields + : operation.kind === 'FragmentDefinition' + ? fragmentFields + : null; const fragmentTypeName = operation.kind === 'FragmentDefinition' ? operation.typeCondition.name.value : null; - const onCommit = parsedDocument => { - const textualNewDocument = print(parsedDocument); + const onCommit = ( parsedDocument ) => { + const textualNewDocument = print( parsedDocument ); - this.props.onEdit(textualNewDocument); + this.props.onEdit( textualNewDocument ); }; return ( { + key={ index } + isLast={ + index === relevantOperations.length - 1 + } + fields={ fields } + operationType={ operationType } + name={ operationName } + definition={ operation } + onOperationRename={ onOperationRename } + onOperationDestroy={ onOperationDestroy } + onOperationClone={ onOperationClone } + onTypeName={ fragmentTypeName } + onMount={ this._handleRootViewMount } + onCommit={ onCommit } + onEdit={ ( newDefinition, options ) => { let commit; if ( typeof options === 'object' && @@ -475,45 +516,49 @@ class ExplorerView extends React.PureComponent { commit = true; } - if (!!newDefinition) { + if ( !! newDefinition ) { const newQuery = { ...parsedQuery, - definitions: parsedQuery.definitions.map( - existingDefinition => - existingDefinition === operation - ? newDefinition - : existingDefinition, - ), + definitions: + parsedQuery.definitions.map( + ( existingDefinition ) => + existingDefinition === + operation + ? newDefinition + : existingDefinition + ), }; - if (commit) { - onCommit(newQuery); - return newQuery; - } else { + if ( commit ) { + onCommit( newQuery ); return newQuery; } - } else { - return parsedQuery; + return newQuery; } - }} - schema={schema} - getDefaultFieldNames={getDefaultFieldNames} - getDefaultScalarArgValue={getDefaultScalarArgValue} - makeDefaultArg={makeDefaultArg} - onRunOperation={() => { - if (!!this.props.onRunOperation) { - this.props.onRunOperation(operationName); + return parsedQuery; + } } + schema={ schema } + getDefaultFieldNames={ getDefaultFieldNames } + getDefaultScalarArgValue={ + getDefaultScalarArgValue + } + makeDefaultArg={ makeDefaultArg } + onRunOperation={ () => { + if ( !! this.props.onRunOperation ) { + this.props.onRunOperation( + operationName + ); } - }} - styleConfig={styleConfig} - availableFragments={availableFragments} + } } + styleConfig={ styleConfig } + availableFragments={ availableFragments } /> ); - })} - {attribution} + } ) } + { attribution }
- {actionsEl} + { actionsEl }
); } diff --git a/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx b/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx index cacffdf..9cb9ba4 100644 --- a/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx +++ b/plugins/third-party-plugin/src/components/ExplorerWrapper.jsx @@ -1,15 +1,14 @@ -import React from "react"; -import ErrorBoundary from "./ErrorBoundary"; -import ExplorerView from "./ExplorerView"; +import React from 'react'; +import ErrorBoundary from './ErrorBoundary'; +import ExplorerView from './ExplorerView'; class ExplorerWrapper extends React.PureComponent { - render() { return (
+ } } + >
-
{this.props.title}
+
+ { this.props.title } +
- {'\u2715'} + onClick={ this.props.onToggleExplorer } + > + { '\u2715' }
+ } } + > - +
diff --git a/plugins/third-party-plugin/src/components/FieldView.jsx b/plugins/third-party-plugin/src/components/FieldView.jsx index 4581cad..5440658 100644 --- a/plugins/third-party-plugin/src/components/FieldView.jsx +++ b/plugins/third-party-plugin/src/components/FieldView.jsx @@ -1,24 +1,29 @@ -import React from "react"; -import {defaultArgs, unwrapOutputType} from "../utils"; -import {getNamedType, isInterfaceType, isObjectType, isUnionType} from "graphql"; -import Checkbox from "./Checkbox"; -import ArgView from "./ArgView"; -import FragmentView from "./FragmentView"; -import AbstractView from "./AbstractView"; +import React from 'react'; +import { defaultArgs, unwrapOutputType } from '../utils'; +import { + getNamedType, + isInterfaceType, + isObjectType, + isUnionType, +} from 'graphql'; +import Checkbox from './Checkbox'; +import ArgView from './ArgView'; +import FragmentView from './FragmentView'; +import AbstractView from './AbstractView'; class FieldView extends React.PureComponent { - state = {displayFieldActions: false}; + state = { displayFieldActions: false }; _previousSelection; - _addAllFieldsToSelections = rawSubfields => { - const subFields = !!rawSubfields - ? Object.keys(rawSubfields).map(fieldName => { - return { - kind: 'Field', - name: {kind: 'Name', value: fieldName}, - arguments: [], - }; - }) + _addAllFieldsToSelections = ( rawSubfields ) => { + const subFields = !! rawSubfields + ? Object.keys( rawSubfields ).map( ( fieldName ) => { + return { + kind: 'Field', + name: { kind: 'Name', value: fieldName }, + arguments: [], + }; + } ) : []; const subSelectionSet = { @@ -27,58 +32,58 @@ class FieldView extends React.PureComponent { }; const nextSelections = [ - ...this.props.selections.filter(selection => { - if (selection.kind === 'InlineFragment') { + ...this.props.selections.filter( ( selection ) => { + if ( selection.kind === 'InlineFragment' ) { return true; - } else { - return selection.name.value !== this.props.field.name; } - }), + return selection.name.value !== this.props.field.name; + } ), { kind: 'Field', - name: {kind: 'Name', value: this.props.field.name}, + name: { kind: 'Name', value: this.props.field.name }, arguments: defaultArgs( this.props.getDefaultScalarArgValue, this.props.makeDefaultArg, - this.props.field, + this.props.field ), selectionSet: subSelectionSet, }, ]; - this.props.modifySelections(nextSelections); + this.props.modifySelections( nextSelections ); }; - _addFieldToSelections = rawSubfields => { + _addFieldToSelections = ( rawSubfields ) => { const nextSelections = [ ...this.props.selections, this._previousSelection || { kind: 'Field', - name: {kind: 'Name', value: this.props.field.name}, + name: { kind: 'Name', value: this.props.field.name }, arguments: defaultArgs( this.props.getDefaultScalarArgValue, this.props.makeDefaultArg, - this.props.field, + this.props.field ), }, ]; - this.props.modifySelections(nextSelections); + this.props.modifySelections( nextSelections ); }; - _handleUpdateSelections = event => { + _handleUpdateSelections = ( event ) => { const selection = this._getSelection(); - if (selection && !event.altKey) { + if ( selection && ! event.altKey ) { this._removeFieldFromSelections(); } else { - const fieldType = getNamedType(this.props.field.type); - const rawSubfields = isObjectType(fieldType) && fieldType.getFields(); + const fieldType = getNamedType( this.props.field.type ); + const rawSubfields = + isObjectType( fieldType ) && fieldType.getFields(); - const shouldSelectAllSubfields = !!rawSubfields && event.altKey; + const shouldSelectAllSubfields = !! rawSubfields && event.altKey; shouldSelectAllSubfields - ? this._addAllFieldsToSelections(rawSubfields) - : this._addFieldToSelections(rawSubfields); + ? this._addAllFieldsToSelections( rawSubfields ) + : this._addFieldToSelections( rawSubfields ); } }; @@ -87,56 +92,59 @@ class FieldView extends React.PureComponent { this._previousSelection = previousSelection; this.props.modifySelections( this.props.selections.filter( - selection => selection !== previousSelection, - ), + ( selection ) => selection !== previousSelection + ) ); }; _getSelection = () => { const selection = this.props.selections.find( - selection => + ( selection ) => selection.kind === 'Field' && - this.props.field.name === selection.name.value, + this.props.field.name === selection.name.value ); - if (!selection) { + if ( ! selection ) { return null; } - if (selection.kind === 'Field') { + if ( selection.kind === 'Field' ) { return selection; } }; - _setArguments = (argumentNodes, options) => { + _setArguments = ( argumentNodes, options ) => { const selection = this._getSelection(); - if (!selection) { - console.error('Missing selection when setting arguments', argumentNodes); + if ( ! selection ) { + console.error( + 'Missing selection when setting arguments', + argumentNodes + ); return; } return this.props.modifySelections( - this.props.selections.map(s => + this.props.selections.map( ( s ) => s === selection ? { - alias: selection.alias, - arguments: argumentNodes, - directives: selection.directives, - kind: 'Field', - name: selection.name, - selectionSet: selection.selectionSet, - } - : s, + alias: selection.alias, + arguments: argumentNodes, + directives: selection.directives, + kind: 'Field', + name: selection.name, + selectionSet: selection.selectionSet, + } + : s ), - options, + options ); }; - _modifyChildSelections = (selections, options) => { + _modifyChildSelections = ( selections, options ) => { return this.props.modifySelections( - this.props.selections.map(selection => { + this.props.selections.map( ( selection ) => { if ( selection.kind === 'Field' && this.props.field.name === selection.name.value ) { - if (selection.kind !== 'Field') { - throw new Error('invalid selection'); + if ( selection.kind !== 'Field' ) { + throw new Error( 'invalid selection' ); } return { alias: selection.alias, @@ -151,254 +159,299 @@ class FieldView extends React.PureComponent { }; } return selection; - }), - options, + } ), + options ); }; render() { - const {field, schema, getDefaultFieldNames, styleConfig} = this.props; + const { field, schema, getDefaultFieldNames, styleConfig } = this.props; const selection = this._getSelection(); - const type = unwrapOutputType(field.type); - const args = field.args.sort((a, b) => a.name.localeCompare(b.name)); - let className = `graphiql-explorer-node graphiql-explorer-${field.name}`; + const type = unwrapOutputType( field.type ); + const args = field.args.sort( ( a, b ) => + a.name.localeCompare( b.name ) + ); + let className = `graphiql-explorer-node graphiql-explorer-${ field.name }`; - if (field.isDeprecated) { + if ( field.isDeprecated ) { className += ' graphiql-explorer-deprecated'; } const applicableFragments = - isObjectType(type) || isInterfaceType(type) || isUnionType(type) + isObjectType( type ) || + isInterfaceType( type ) || + isUnionType( type ) ? this.props.availableFragments && - this.props.availableFragments[type.name] + this.props.availableFragments[ type.name ] : null; const node = ( -
- { - const containsMeaningfulSubselection = - isObjectType(type) && - selection && - selection.selectionSet && - selection.selectionSet.selections.filter( - selection => selection.kind !== 'FragmentSpread', - ).length > 0; +
+ { + const containsMeaningfulSubselection = + isObjectType( type ) && + selection && + selection.selectionSet && + selection.selectionSet.selections.filter( + ( selection ) => + selection.kind !== 'FragmentSpread' + ).length > 0; - if (containsMeaningfulSubselection) { - this.setState({displayFieldActions: true}); - } - }} - onMouseLeave={() => this.setState({displayFieldActions: false})}> - {isObjectType(type) ? ( - - {!!selection - ? this.props.styleConfig.arrowOpen - : this.props.styleConfig.arrowClosed} - - ) : null} - {isObjectType(type) ? null : ( - - )} - - {field.name} - - {!this.state.displayFieldActions ? null : ( - - )} - - {selection && args.length ? ( + this.props.onCommit( newDocWithFragment ); + } else { + console.warn( + 'Unable to complete extractFragment operation' + ); + } + } } + style={ { + ...styleConfig.styles.actionButtonStyle, + } } + > + { '…' } + + ) } + + { selection && args.length ? (
- {args.map(arg => ( + style={ { marginLeft: 16 } } + className="graphiql-explorer-graphql-arguments" + > + { args.map( ( arg ) => ( - ))} + ) ) }
- ) : null} + ) : null }
); if ( selection && - (isObjectType(type) || isInterfaceType(type) || isUnionType(type)) + ( isObjectType( type ) || + isInterfaceType( type ) || + isUnionType( type ) ) ) { - const fields = isUnionType(type) ? {} : type.getFields(); + const fields = isUnionType( type ) ? {} : type.getFields(); const childSelections = selection ? selection.selectionSet ? selection.selectionSet.selections : [] : []; return ( -
- {node} -
- {!!applicableFragments - ? applicableFragments.map(fragment => { - const type = schema.getType( - fragment.typeCondition.name.value, - ); - const fragmentName = fragment.name.value; - return !type ? null : ( - - ); - }) - : null} - {Object.keys(fields) +
+ { node } +
+ { !! applicableFragments + ? applicableFragments.map( ( fragment ) => { + const type = schema.getType( + fragment.typeCondition.name.value + ); + const fragmentName = fragment.name.value; + return ! type ? null : ( + + ); + } ) + : null } + { Object.keys( fields ) .sort() - .map(fieldName => ( + .map( ( fieldName ) => ( - ))} - {isInterfaceType(type) || isUnionType(type) + ) ) } + { isInterfaceType( type ) || isUnionType( type ) ? schema - .getPossibleTypes(type) - .map(type => ( - - )) - : null} + .getPossibleTypes( type ) + .map( ( type ) => ( + + ) ) + : null }
); diff --git a/plugins/third-party-plugin/src/components/FragmentView.jsx b/plugins/third-party-plugin/src/components/FragmentView.jsx index 5d48ceb..b454fc7 100644 --- a/plugins/third-party-plugin/src/components/FragmentView.jsx +++ b/plugins/third-party-plugin/src/components/FragmentView.jsx @@ -1,59 +1,65 @@ -import React from "react"; -import Checkbox from "./Checkbox"; +import React from 'react'; +import Checkbox from './Checkbox'; class FragmentView extends React.PureComponent { _previousSelection; _addFragment = () => { - this.props.modifySelections([ + this.props.modifySelections( [ ...this.props.selections, this._previousSelection || { kind: 'FragmentSpread', name: this.props.fragment.name, }, - ]); + ] ); }; _removeFragment = () => { const thisSelection = this._getSelection(); this._previousSelection = thisSelection; this.props.modifySelections( - this.props.selections.filter(s => { + this.props.selections.filter( ( s ) => { const isTargetSelection = s.kind === 'FragmentSpread' && s.name.value === this.props.fragment.name.value; - return !isTargetSelection; - }), + return ! isTargetSelection; + } ) ); }; _getSelection = () => { - const selection = this.props.selections.find(selection => { + const selection = this.props.selections.find( ( selection ) => { return ( selection.kind === 'FragmentSpread' && selection.name.value === this.props.fragment.name.value ); - }); + } ); return selection; }; render() { - const {styleConfig} = this.props; + const { styleConfig } = this.props; const selection = this._getSelection(); return ( -
- - - - {this.props.fragment.name.value} - - +
+ + + + { this.props.fragment.name.value } + +
); } diff --git a/plugins/third-party-plugin/src/components/InputArgView.jsx b/plugins/third-party-plugin/src/components/InputArgView.jsx index 86a4e24..3aaa3bc 100644 --- a/plugins/third-party-plugin/src/components/InputArgView.jsx +++ b/plugins/third-party-plugin/src/components/InputArgView.jsx @@ -1,22 +1,22 @@ -import React from "react"; -import {coerceArgValue, unwrapInputType} from "../utils"; -import {isInputObjectType, isLeafType} from "graphql"; +import React from 'react'; +import { coerceArgValue, unwrapInputType } from '../utils'; +import { isInputObjectType, isLeafType } from 'graphql'; class InputArgView extends React.PureComponent { _previousArgSelection; _getArgSelection = () => { return this.props.selection.fields.find( - field => field.name.value === this.props.arg.name, + ( field ) => field.name.value === this.props.arg.name ); }; _removeArg = () => { - const {selection} = this.props; + const { selection } = this.props; const argSelection = this._getArgSelection(); this._previousArgSelection = argSelection; this.props.modifyFields( - selection.fields.filter(field => field !== argSelection), - true, + selection.fields.filter( ( field ) => field !== argSelection ), + true ); }; @@ -28,154 +28,154 @@ class InputArgView extends React.PureComponent { parentField, makeDefaultArg, } = this.props; - const argType = unwrapInputType(arg.type); + const argType = unwrapInputType( arg.type ); let argSelection = null; - if (this._previousArgSelection) { + if ( this._previousArgSelection ) { argSelection = this._previousArgSelection; - } else if (isInputObjectType(argType)) { + } else if ( isInputObjectType( argType ) ) { const fields = argType.getFields(); argSelection = { kind: 'ObjectField', - name: {kind: 'Name', value: arg.name}, + name: { kind: 'Name', value: arg.name }, value: { kind: 'ObjectValue', fields: defaultInputObjectFields( getDefaultScalarArgValue, makeDefaultArg, parentField, - Object.keys(fields).map(k => fields[k]), + Object.keys( fields ).map( ( k ) => fields[ k ] ) ), }, }; - } else if (isLeafType(argType)) { + } else if ( isLeafType( argType ) ) { argSelection = { kind: 'ObjectField', - name: {kind: 'Name', value: arg.name}, - value: getDefaultScalarArgValue(parentField, arg, argType), + name: { kind: 'Name', value: arg.name }, + value: getDefaultScalarArgValue( parentField, arg, argType ), }; } - if (!argSelection) { - console.error('Unable to add arg for argType', argType); + if ( ! argSelection ) { + console.error( 'Unable to add arg for argType', argType ); } else { return this.props.modifyFields( - [...(selection.fields || []), argSelection], - true, + [ ...( selection.fields || [] ), argSelection ], + true ); } }; - _setArgValue = (event, options) => { + _setArgValue = ( event, options ) => { let settingToNull = false; let settingToVariable = false; let settingToLiteralValue = false; try { - if (event.kind === 'VariableDefinition') { + if ( event.kind === 'VariableDefinition' ) { settingToVariable = true; - } else if (event === null || typeof event === 'undefined') { + } else if ( event === null || typeof event === 'undefined' ) { settingToNull = true; - } else if (typeof event.kind === 'string') { + } else if ( typeof event.kind === 'string' ) { settingToLiteralValue = true; } - } catch (e) {} + } catch ( e ) {} - const {selection} = this.props; + const { selection } = this.props; const argSelection = this._getArgSelection(); - if (!argSelection) { - console.error('missing arg selection when setting arg value'); + if ( ! argSelection ) { + console.error( 'missing arg selection when setting arg value' ); return; } - const argType = unwrapInputType(this.props.arg.type); + const argType = unwrapInputType( this.props.arg.type ); const handleable = - isLeafType(argType) || + isLeafType( argType ) || settingToVariable || settingToNull || settingToLiteralValue; - if (!handleable) { + if ( ! handleable ) { console.warn( 'Unable to handle non leaf types in InputArgView.setArgValue', - event, + event ); return; } let targetValue; let value; - if (event === null || typeof event === 'undefined') { + if ( event === null || typeof event === 'undefined' ) { value = null; } else if ( - !event.target && - !!event.kind && + ! event.target && + !! event.kind && event.kind === 'VariableDefinition' ) { targetValue = event; value = targetValue.variable; - } else if (typeof event.kind === 'string') { + } else if ( typeof event.kind === 'string' ) { value = event; - } else if (event.target && typeof event.target.value === 'string') { + } else if ( event.target && typeof event.target.value === 'string' ) { targetValue = event.target.value; - value = coerceArgValue(argType, targetValue); + value = coerceArgValue( argType, targetValue ); } const newDoc = this.props.modifyFields( - (selection.fields || []).map(field => { + ( selection.fields || [] ).map( ( field ) => { const isTarget = field === argSelection; const newField = isTarget ? { - ...field, - value: value, - } + ...field, + value, + } : field; return newField; - }), - options, + } ), + options ); return newDoc; }; - _modifyChildFields = fields => { + _modifyChildFields = ( fields ) => { return this.props.modifyFields( - this.props.selection.fields.map(field => + this.props.selection.fields.map( ( field ) => field.name.value === this.props.arg.name ? { - ...field, - value: { - kind: 'ObjectValue', - fields: fields, - }, - } - : field, + ...field, + value: { + kind: 'ObjectValue', + fields, + }, + } + : field ), - true, + true ); }; render() { - const {arg, parentField} = this.props; + const { arg, parentField } = this.props; const argSelection = this._getArgSelection(); return ( ); } diff --git a/plugins/third-party-plugin/src/components/QueryComposer.js b/plugins/third-party-plugin/src/components/QueryComposer.js index a7030bb..9ec8a77 100644 --- a/plugins/third-party-plugin/src/components/QueryComposer.js +++ b/plugins/third-party-plugin/src/components/QueryComposer.js @@ -1,8 +1,8 @@ import { useSelect, useDispatch } from '@wordpress/data'; import ExplorerWrapper from './ExplorerWrapper'; import '../style.css'; -import ArrowOpen from "./ArrowOpen"; -import ArrowClosed from "./ArrowClosed"; +import ArrowOpen from './ArrowOpen'; +import ArrowClosed from './ArrowClosed'; import { checkboxUnchecked, checkboxChecked } from './Checkbox'; const colors = { @@ -39,8 +39,7 @@ const styles = { }, }; -export const QueryComposer = (props) => { - +export const QueryComposer = ( props ) => { const schema = useSelect( ( select ) => select( 'wpgraphql-ide/app' ).schema() ); @@ -54,21 +53,21 @@ export const QueryComposer = (props) => { return ( <> { setQuery( newQuery ); - }} + } } /> ); -} +}; diff --git a/plugins/third-party-plugin/src/components/RootView.jsx b/plugins/third-party-plugin/src/components/RootView.jsx index 491c80a..99c1557 100644 --- a/plugins/third-party-plugin/src/components/RootView.jsx +++ b/plugins/third-party-plugin/src/components/RootView.jsx @@ -1,12 +1,12 @@ -import React from "react"; -import {canRunOperation, capitalize, isRunShortcut} from "../utils"; -import FieldView from "./FieldView"; +import React from 'react'; +import { canRunOperation, capitalize, isRunShortcut } from '../utils'; +import FieldView from './FieldView'; class RootView extends React.PureComponent { - state = {newOperationType: 'query', displayTitleActions: false}; + state = { newOperationType: 'query', displayTitleActions: false }; _previousOperationDef; - _modifySelections = (selections, options) => { + _modifySelections = ( selections, options ) => { let operationDef = this.props.definition; if ( @@ -18,7 +18,7 @@ class RootView extends React.PureComponent { let newOperationDef; - if (operationDef.kind === 'FragmentDefinition') { + if ( operationDef.kind === 'FragmentDefinition' ) { newOperationDef = { ...operationDef, selectionSet: { @@ -26,14 +26,15 @@ class RootView extends React.PureComponent { selections, }, }; - } else if (operationDef.kind === 'OperationDefinition') { - let cleanedSelections = selections.filter(selection => { - return !( - selection.kind === 'Field' && selection.name.value === '__typename' + } else if ( operationDef.kind === 'OperationDefinition' ) { + let cleanedSelections = selections.filter( ( selection ) => { + return ! ( + selection.kind === 'Field' && + selection.name.value === '__typename' ); - }); + } ); - if (cleanedSelections.length === 0) { + if ( cleanedSelections.length === 0 ) { cleanedSelections = [ { kind: 'Field', @@ -54,28 +55,31 @@ class RootView extends React.PureComponent { }; } - return this.props.onEdit(newOperationDef, options); + return this.props.onEdit( newOperationDef, options ); }; - _onOperationRename = event => - this.props.onOperationRename(event.target.value); + _onOperationRename = ( event ) => + this.props.onOperationRename( event.target.value ); - _handlePotentialRun = event => { - if (isRunShortcut(event) && canRunOperation(this.props.definition.kind)) { - this.props.onRunOperation(this.props.name); + _handlePotentialRun = ( event ) => { + if ( + isRunShortcut( event ) && + canRunOperation( this.props.definition.kind ) + ) { + this.props.onRunOperation( this.props.name ); } }; _rootViewElId = () => { - const {operationType, name} = this.props; - const rootViewElId = `${operationType}-${name || 'unknown'}`; + const { operationType, name } = this.props; + const rootViewElId = `${ operationType }-${ name || 'unknown' }`; return rootViewElId; }; componentDidMount() { const rootViewElId = this._rootViewElId(); - this.props.onMount(rootViewElId); + this.props.onMount( rootViewElId ); } render() { @@ -93,93 +97,115 @@ class RootView extends React.PureComponent { const selections = operationDef.selectionSet.selections; const operationDisplayName = - this.props.name || `${capitalize(operationType)} Name`; + this.props.name || `${ capitalize( operationType ) } Name`; return (
+ } } + >
this.setState({displayTitleActions: true})} - onMouseLeave={() => this.setState({displayTitleActions: false})}> - {operationType}{' '} - - - - {!!this.props.onTypeName ? ( + onMouseEnter={ () => + this.setState( { displayTitleActions: true } ) + } + onMouseLeave={ () => + this.setState( { displayTitleActions: false } ) + } + > + { operationType }{ ' ' } + + + + { !! this.props.onTypeName ? ( -
- {`on ${this.props.onTypeName}`} -
+
+ { `on ${ this.props.onTypeName }` } + ) : ( '' - )} - {!!this.state.displayTitleActions ? ( + ) } + { !! this.state.displayTitleActions ? ( ) : ( '' - )} + ) }
- {Object.keys(fields) + { Object.keys( fields ) .sort() - .map(fieldName => ( + .map( ( fieldName ) => ( - ))} + ) ) }
); } @@ -188,7 +214,7 @@ class RootView extends React.PureComponent { function Attribution() { return (
+ } } + >
- GraphiQL Explorer by OneGraph + } } + > + GraphiQL Explorer by{ ' ' } + OneGraph
- Contribute on{' '} - GitHub + Contribute on{ ' ' } + + GitHub +
); diff --git a/plugins/third-party-plugin/src/components/ScalarInput.jsx b/plugins/third-party-plugin/src/components/ScalarInput.jsx index 6ac00f1..37437df 100644 --- a/plugins/third-party-plugin/src/components/ScalarInput.jsx +++ b/plugins/third-party-plugin/src/components/ScalarInput.jsx @@ -1,10 +1,10 @@ -import React from "react"; -import {unwrapInputType} from "../utils"; +import React from 'react'; +import { unwrapInputType } from '../utils'; class ScalarInput extends React.PureComponent { _ref; - _handleChange = event => { - this.props.setArgValue(event, true); + _handleChange = ( event ) => { + this.props.setArgValue( event, true ); }; componentDidMount() { @@ -13,41 +13,44 @@ class ScalarInput extends React.PureComponent { if ( input && activeElement && - !(activeElement instanceof HTMLTextAreaElement) + ! ( activeElement instanceof HTMLTextAreaElement ) ) { input.focus(); - input.setSelectionRange(0, input.value.length); + input.setSelectionRange( 0, input.value.length ); } } render() { - const {arg, argValue, styleConfig} = this.props; - const argType = unwrapInputType(arg.type); + const { arg, argValue, styleConfig } = this.props; + const argType = unwrapInputType( arg.type ); const value = typeof argValue.value === 'string' ? argValue.value : ''; const color = this.props.argValue.kind === 'StringValue' ? styleConfig.colors.string : styleConfig.colors.number; return ( - - {argType.name === 'String' ? '"' : ''} + + { argType.name === 'String' ? '"' : '' } { + } } + ref={ ( ref ) => { this._ref = ref; - }} + } } type="text" - onChange={this._handleChange} - value={value} + onChange={ this._handleChange } + value={ value } /> - {argType.name === 'String' ? '"' : ''} - + { argType.name === 'String' ? '"' : '' } + ); } } diff --git a/plugins/third-party-plugin/src/index.js b/plugins/third-party-plugin/src/index.js index bbebcfb..e01bee8 100644 --- a/plugins/third-party-plugin/src/index.js +++ b/plugins/third-party-plugin/src/index.js @@ -1,11 +1,10 @@ /** * External dependencies */ -import {QueryComposer} from "./components/QueryComposer"; -import {edit as editIcon, Icon} from '@wordpress/icons'; - -window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { +import { QueryComposer } from './components/QueryComposer'; +import { edit as editIcon, Icon } from '@wordpress/icons'; +window.addEventListener( 'WPGraphQLIDE_Window_Ready', function ( event ) { if ( ! window.WPGraphQLIDE ) { return; } @@ -13,21 +12,23 @@ window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { const { registerActivityBarPanel } = window.WPGraphQLIDE || {}; if ( typeof registerActivityBarPanel === 'function' ) { - registerActivityBarPanel( 'query-composer', () => { - return { - title: 'Query Composer', - icon: () => ( - - ), - content: () => - }; - }, 4 ); + registerActivityBarPanel( + 'query-composer', + () => { + return { + title: 'Query Composer', + icon: () => ( + + ), + content: () => , + }; + }, + 4 + ); } -}); - - +} ); diff --git a/plugins/third-party-plugin/src/utils.js b/plugins/third-party-plugin/src/utils.js index 0c073c4..8ad8f91 100644 --- a/plugins/third-party-plugin/src/utils.js +++ b/plugins/third-party-plugin/src/utils.js @@ -5,8 +5,9 @@ import { isNonNullType, isRequiredInputField, isScalarType, - isWrappingType, parse -} from "graphql"; + isWrappingType, + parse, +} from 'graphql'; export const defaultColors = { keyword: '#B11A04', @@ -22,127 +23,123 @@ export const defaultColors = { atom: '#CA9800', }; -export function capitalize(string) { - return string.charAt(0).toUpperCase() + string.slice(1); +export function capitalize( string ) { + return string.charAt( 0 ).toUpperCase() + string.slice( 1 ); } -export function defaultValue( - argType, -) { - if (isEnumType(argType)) { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; - } else { - switch (argType.name) { - case 'String': - return {kind: 'StringValue', value: ''}; - case 'Float': - return {kind: 'FloatValue', value: '1.5'}; - case 'Int': - return {kind: 'IntValue', value: '10'}; - case 'Boolean': - return {kind: 'BooleanValue', value: false}; - default: - return {kind: 'StringValue', value: ''}; - } +export function defaultValue( argType ) { + if ( isEnumType( argType ) ) { + return { kind: 'EnumValue', value: argType.getValues()[ 0 ].name }; + } + switch ( argType.name ) { + case 'String': + return { kind: 'StringValue', value: '' }; + case 'Float': + return { kind: 'FloatValue', value: '1.5' }; + case 'Int': + return { kind: 'IntValue', value: '10' }; + case 'Boolean': + return { kind: 'BooleanValue', value: false }; + default: + return { kind: 'StringValue', value: '' }; } } -export function defaultGetDefaultScalarArgValue( - parentField, - arg, - argType, -) { - return defaultValue(argType); +export function defaultGetDefaultScalarArgValue( parentField, arg, argType ) { + return defaultValue( argType ); } -export function defaultGetDefaultFieldNames(type) { +export function defaultGetDefaultFieldNames( type ) { const fields = type.getFields(); - if (fields['id']) { - const res = ['id']; - if (fields['email']) { - res.push('email'); - } else if (fields['name']) { - res.push('name'); + if ( fields.id ) { + const res = [ 'id' ]; + if ( fields.email ) { + res.push( 'email' ); + } else if ( fields.name ) { + res.push( 'name' ); } return res; } - if (fields['edges']) { - return ['edges']; + if ( fields.edges ) { + return [ 'edges' ]; } - if (fields['node']) { - return ['node']; + if ( fields.node ) { + return [ 'node' ]; } - if (fields['nodes']) { - return ['nodes']; + if ( fields.nodes ) { + return [ 'nodes' ]; } const leafFieldNames = []; - Object.keys(fields).forEach(fieldName => { - if (isLeafType(fields[fieldName].type)) { - leafFieldNames.push(fieldName); + Object.keys( fields ).forEach( ( fieldName ) => { + if ( isLeafType( fields[ fieldName ].type ) ) { + leafFieldNames.push( fieldName ); } - }); + } ); - if (!leafFieldNames.length) { - return ['__typename']; + if ( ! leafFieldNames.length ) { + return [ '__typename' ]; } - return leafFieldNames.slice(0, 2); + return leafFieldNames.slice( 0, 2 ); } -export function isRequiredArgument(arg) { - return isNonNullType(arg.type) && arg.defaultValue === undefined; +export function isRequiredArgument( arg ) { + return isNonNullType( arg.type ) && arg.defaultValue === undefined; } -export function unwrapOutputType(outputType) { +export function unwrapOutputType( outputType ) { let unwrappedType = outputType; - while (isWrappingType(unwrappedType)) { + while ( isWrappingType( unwrappedType ) ) { unwrappedType = unwrappedType.ofType; } return unwrappedType; } -export function unwrapInputType(inputType) { +export function unwrapInputType( inputType ) { let unwrappedType = inputType; - while (isWrappingType(unwrappedType)) { + while ( isWrappingType( unwrappedType ) ) { unwrappedType = unwrappedType.ofType; } return unwrappedType; } -export function coerceArgValue(argType, value) { - if (typeof value !== 'string' && value.kind === 'VariableDefinition') { +export function coerceArgValue( argType, value ) { + if ( typeof value !== 'string' && value.kind === 'VariableDefinition' ) { return value.variable; - } else if (isScalarType(argType)) { + } else if ( isScalarType( argType ) ) { try { - switch (argType.name) { + switch ( argType.name ) { case 'String': return { kind: 'StringValue', - value: String(argType.parseValue(value)), + value: String( argType.parseValue( value ) ), }; case 'Float': return { kind: 'FloatValue', - value: String(argType.parseValue(parseFloat(value))), + value: String( + argType.parseValue( parseFloat( value ) ) + ), }; case 'Int': return { kind: 'IntValue', - value: String(argType.parseValue(parseInt(value, 10))), + value: String( + argType.parseValue( parseInt( value, 10 ) ) + ), }; case 'Boolean': try { - const parsed = JSON.parse(value); - if (typeof parsed === 'boolean') { - return {kind: 'BooleanValue', value: parsed}; - } else { - return {kind: 'BooleanValue', value: false}; + const parsed = JSON.parse( value ); + if ( typeof parsed === 'boolean' ) { + return { kind: 'BooleanValue', value: parsed }; } - } catch (e) { + return { kind: 'BooleanValue', value: false }; + } catch ( e ) { return { kind: 'BooleanValue', value: false, @@ -151,32 +148,31 @@ export function coerceArgValue(argType, value) { default: return { kind: 'StringValue', - value: String(argType.parseValue(value)), + value: String( argType.parseValue( value ) ), }; } - } catch (e) { - console.error('error coercing arg value', e, value); - return {kind: 'StringValue', value: value}; + } catch ( e ) { + console.error( 'error coercing arg value', e, value ); + return { kind: 'StringValue', value }; } } else { try { - const parsedValue = argType.parseValue(value); - if (parsedValue) { - return {kind: 'EnumValue', value: String(parsedValue)}; - } else { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; + const parsedValue = argType.parseValue( value ); + if ( parsedValue ) { + return { kind: 'EnumValue', value: String( parsedValue ) }; } - } catch (e) { - return {kind: 'EnumValue', value: argType.getValues()[0].name}; + return { kind: 'EnumValue', value: argType.getValues()[ 0 ].name }; + } catch ( e ) { + return { kind: 'EnumValue', value: argType.getValues()[ 0 ].name }; } } } -export function isRunShortcut(event) { +export function isRunShortcut( event ) { return event.ctrlKey && event.key === 'Enter'; } -export function canRunOperation(operationName) { +export function canRunOperation( operationName ) { return operationName !== 'FragmentDefinition'; } @@ -184,92 +180,89 @@ export function defaultInputObjectFields( getDefaultScalarArgValue, makeDefaultArg, parentField, - fields, + fields ) { const nodes = []; - for (const field of fields) { + for ( const field of fields ) { if ( - isRequiredInputField(field) || - (makeDefaultArg && makeDefaultArg(parentField, field)) + isRequiredInputField( field ) || + ( makeDefaultArg && makeDefaultArg( parentField, field ) ) ) { - const fieldType = unwrapInputType(field.type); - if (isInputObjectType(fieldType)) { + const fieldType = unwrapInputType( field.type ); + if ( isInputObjectType( fieldType ) ) { const fields = fieldType.getFields(); - nodes.push({ + nodes.push( { kind: 'ObjectField', - name: {kind: 'Name', value: field.name}, + name: { kind: 'Name', value: field.name }, value: { kind: 'ObjectValue', fields: defaultInputObjectFields( getDefaultScalarArgValue, makeDefaultArg, parentField, - Object.keys(fields).map(k => fields[k]), + Object.keys( fields ).map( ( k ) => fields[ k ] ) ), }, - }); - } else if (isLeafType(fieldType)) { - nodes.push({ + } ); + } else if ( isLeafType( fieldType ) ) { + nodes.push( { kind: 'ObjectField', - name: {kind: 'Name', value: field.name}, - value: getDefaultScalarArgValue(parentField, field, fieldType), - }); + name: { kind: 'Name', value: field.name }, + value: getDefaultScalarArgValue( + parentField, + field, + fieldType + ), + } ); } } } return nodes; } -export function defaultArgs( - getDefaultScalarArgValue, - makeDefaultArg, - field, -) { +export function defaultArgs( getDefaultScalarArgValue, makeDefaultArg, field ) { const args = []; - for (const arg of field.args) { + for ( const arg of field.args ) { if ( - isRequiredArgument(arg) || - (makeDefaultArg && makeDefaultArg(field, arg)) + isRequiredArgument( arg ) || + ( makeDefaultArg && makeDefaultArg( field, arg ) ) ) { - const argType = unwrapInputType(arg.type); - if (isInputObjectType(argType)) { + const argType = unwrapInputType( arg.type ); + if ( isInputObjectType( argType ) ) { const fields = argType.getFields(); - args.push({ + args.push( { kind: 'Argument', - name: {kind: 'Name', value: arg.name}, + name: { kind: 'Name', value: arg.name }, value: { kind: 'ObjectValue', fields: defaultInputObjectFields( getDefaultScalarArgValue, makeDefaultArg, field, - Object.keys(fields).map(k => fields[k]), + Object.keys( fields ).map( ( k ) => fields[ k ] ) ), }, - }); - } else if (isLeafType(argType)) { - args.push({ + } ); + } else if ( isLeafType( argType ) ) { + args.push( { kind: 'Argument', - name: {kind: 'Name', value: arg.name}, - value: getDefaultScalarArgValue(field, arg, argType), - }); + name: { kind: 'Name', value: arg.name }, + value: getDefaultScalarArgValue( field, arg, argType ), + } ); } } } return args; } -export function parseQuery(text) { +export function parseQuery( text ) { try { - if (!text.trim()) { + if ( ! text.trim() ) { return null; } - return parse( - text, - {noLocation: true}, - ); - } catch (e) { - return new Error(e); + return parse( text, { noLocation: true } ); + } catch ( e ) { + return new Error( e ); } } @@ -277,7 +270,7 @@ export const DEFAULT_OPERATION = { kind: 'OperationDefinition', operation: 'query', variableDefinitions: [], - name: {kind: 'Name', value: 'MyQuery'}, + name: { kind: 'Name', value: 'MyQuery' }, directives: [], selectionSet: { kind: 'SelectionSet', @@ -287,28 +280,25 @@ export const DEFAULT_OPERATION = { export const DEFAULT_DOCUMENT = { kind: 'Document', - definitions: [DEFAULT_OPERATION], + definitions: [ DEFAULT_OPERATION ], }; let parseQueryMemoize = null; -export function memoizeParseQuery(query) { - if (parseQueryMemoize && parseQueryMemoize[0] === query) { - return parseQueryMemoize[1]; - } else { - const result = parseQuery(query); - if (!result) { - return DEFAULT_DOCUMENT; - } else if (result instanceof Error) { - if (parseQueryMemoize) { - return parseQueryMemoize[1]; - } else { - return DEFAULT_DOCUMENT; - } - } else { - parseQueryMemoize = [query, result]; - return result; +export function memoizeParseQuery( query ) { + if ( parseQueryMemoize && parseQueryMemoize[ 0 ] === query ) { + return parseQueryMemoize[ 1 ]; + } + const result = parseQuery( query ); + if ( ! result ) { + return DEFAULT_DOCUMENT; + } else if ( result instanceof Error ) { + if ( parseQueryMemoize ) { + return parseQueryMemoize[ 1 ]; } + return DEFAULT_DOCUMENT; } + parseQueryMemoize = [ query, result ]; + return result; } export const defaultStyles = { diff --git a/plugins/third-party-plugin/webpack.config.js b/plugins/third-party-plugin/webpack.config.js index 9b73b34..a5e3dc6 100644 --- a/plugins/third-party-plugin/webpack.config.js +++ b/plugins/third-party-plugin/webpack.config.js @@ -1,10 +1,10 @@ -const defaults = require('@wordpress/scripts/config/webpack.config'); -const path = require('path'); +const defaults = require( '@wordpress/scripts/config/webpack.config' ); +const path = require( 'path' ); const defaultExternals = { react: 'React', 'react-dom': 'ReactDOM', - graphql: "graphql", + graphql: 'graphql', }; // Define a mapping of entries to their respective externals @@ -18,21 +18,24 @@ const entryExternals = { module.exports = { ...defaults, entry: { - index: path.resolve(process.cwd(), 'src', 'index.js'), + index: path.resolve( process.cwd(), 'src', 'index.js' ), }, - externals: ({ context, request }, callback) => { + externals: ( { context, request }, callback ) => { // Determine the current entry from context or other means - const currentEntry = determineCurrentEntry(context); + const currentEntry = determineCurrentEntry( context ); // Apply the externals based on the current entry - if (entryExternals[currentEntry] && entryExternals[currentEntry][request]) { - return callback(null, entryExternals[currentEntry][request]); + if ( + entryExternals[ currentEntry ] && + entryExternals[ currentEntry ][ request ] + ) { + return callback( null, entryExternals[ currentEntry ][ request ] ); } // Fallback to default behavior if no externals are defined for the current entry callback(); }, }; -function determineCurrentEntry(context) { +function determineCurrentEntry( context ) { // Implement logic to determine the current entry based on context // This might involve checking the context path to infer which entry is being processed // Placeholder implementation: diff --git a/src/access-functions.js b/src/access-functions.js index 9d160fb..c2dda84 100644 --- a/src/access-functions.js +++ b/src/access-functions.js @@ -34,11 +34,7 @@ export function registerDocumentEditorToolbarButton( } } -export function registerActivityBarPanel( - name, - config, - priority = 10 -) { +export function registerActivityBarPanel( name, config, priority = 10 ) { try { dispatch( 'wpgraphql-ide/activity-bar' ).registerPanel( name, @@ -52,7 +48,10 @@ export function registerActivityBarPanel( priority ); } catch ( error ) { - console.error( `Failed to register activity bar panel: ${ name }`, error ); + console.error( + `Failed to register activity bar panel: ${ name }`, + error + ); hooks.doAction( 'registerActivityBarPanelError', name, diff --git a/src/components/App.jsx b/src/components/App.jsx index 55cdf26..b305ab4 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -5,26 +5,20 @@ import { parse, visit } from 'graphql'; import 'graphiql/graphiql.min.css'; export function App() { - const { - query, - shouldRenderStandalone, - isAuthenticated, - schema, - } = useSelect( ( select ) => { - const wpgraphqlIDEApp = select( 'wpgraphql-ide/app' ); - return { - query: wpgraphqlIDEApp.getQuery(), - shouldRenderStandalone: wpgraphqlIDEApp.shouldRenderStandalone(), - isAuthenticated: wpgraphqlIDEApp.isAuthenticated(), - schema: wpgraphqlIDEApp.schema(), - }; - }); + const { query, shouldRenderStandalone, isAuthenticated, schema } = + useSelect( ( select ) => { + const wpgraphqlIDEApp = select( 'wpgraphql-ide/app' ); + return { + query: wpgraphqlIDEApp.getQuery(), + shouldRenderStandalone: + wpgraphqlIDEApp.shouldRenderStandalone(), + isAuthenticated: wpgraphqlIDEApp.isAuthenticated(), + schema: wpgraphqlIDEApp.schema(), + }; + } ); - const { - setQuery, - setDrawerOpen, - setSchema, - } = useDispatch( 'wpgraphql-ide/app' ); + const { setQuery, setDrawerOpen, setSchema } = + useDispatch( 'wpgraphql-ide/app' ); useEffect( () => { // create a ref @@ -101,13 +95,14 @@ export function App() { ); const activityPanels = useSelect( ( select ) => { - const activityPanels = select( 'wpgraphql-ide/activity-bar' ).activityPanels(); + const activityPanels = select( + 'wpgraphql-ide/activity-bar' + ).activityPanels(); console.log( { - activityPanels - }) + activityPanels, + } ); return activityPanels; - }) - + } ); return ( diff --git a/src/index.js b/src/index.js index 978d736..630096d 100644 --- a/src/index.js +++ b/src/index.js @@ -31,7 +31,7 @@ init(); */ window.WPGraphQLIDE = { hooks, - ...accessFunctions + ...accessFunctions, }; window.dispatchEvent( new Event( 'WPGraphQLIDE_Window_Ready' ) ); @@ -45,5 +45,3 @@ window.dispatchEvent( new Event( 'WPGraphQLIDE_Window_Ready' ) ); // }).catch(error => { // console.error('Failed to load GraphQL library:', error); // }); - - diff --git a/src/registry/activity-bar-panels/helpPanel/HelpIcon.jsx b/src/registry/activity-bar-panels/helpPanel/HelpIcon.jsx index 6dd1c37..4f98321 100644 --- a/src/registry/activity-bar-panels/helpPanel/HelpIcon.jsx +++ b/src/registry/activity-bar-panels/helpPanel/HelpIcon.jsx @@ -1,12 +1,12 @@ import { help, Icon } from '@wordpress/icons'; export function HelpIcon() { - return ( - - ) + return ( + + ); } diff --git a/src/registry/activity-bar-panels/helpPanel/index.js b/src/registry/activity-bar-panels/helpPanel/index.js index 9390ca8..de19d68 100644 --- a/src/registry/activity-bar-panels/helpPanel/index.js +++ b/src/registry/activity-bar-panels/helpPanel/index.js @@ -6,7 +6,6 @@ export const helpPanel = () => { title: 'help', // TODO: possibly handle title generation for user // label: 'Help!', icon: () => , - content: () => - } -} - + content: () => , + }; +}; diff --git a/src/render.js b/src/render.js index 38c6dfa..534efad 100644 --- a/src/render.js +++ b/src/render.js @@ -1,8 +1,7 @@ -import {createRoot} from "@wordpress/element"; -import AppWrapper from "./components/AppWrapper"; - -window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { +import { createRoot } from '@wordpress/element'; +import AppWrapper from './components/AppWrapper'; +window.addEventListener( 'WPGraphQLIDE_Window_Ready', function ( event ) { /** * Get our root element id from the localized script. */ @@ -14,15 +13,12 @@ window.addEventListener('WPGraphQLIDE_Window_Ready', function(event) { */ const appMountPoint = document.getElementById( rootElementId ); if ( appMountPoint ) { - console.log( `RENDER....` ) + console.log( `RENDER....` ); createRoot( appMountPoint ).render( ); window.dispatchEvent( new Event( 'WPGraphQLIDEReady' ) ); } else { console.error( - `WPGraphQL IDE mount point not found. Please ensure an element with ID "${rootElementId}" exists.` + `WPGraphQL IDE mount point not found. Please ensure an element with ID "${ rootElementId }" exists.` ); } - -}); - - +} ); diff --git a/src/stores/activity-bar/activity-bar-reducer.js b/src/stores/activity-bar/activity-bar-reducer.js index 181066a..ea582f5 100644 --- a/src/stores/activity-bar/activity-bar-reducer.js +++ b/src/stores/activity-bar/activity-bar-reducer.js @@ -52,7 +52,9 @@ const reducer = ( state = initialState, action ) => { // Ensure config is a function before calling it if ( typeof action.config !== 'function' ) { - console.error( `Config for panel "${action.name}" is not a function.` ); + console.error( + `Config for panel "${ action.name }" is not a function.` + ); return state; } @@ -75,10 +77,11 @@ const reducer = ( state = initialState, action ) => { console.log( { message: `Toggling panel visibility.`, panel: action.panel, - }); + } ); return { ...state, - visiblePanel: state.visiblePanel === action.panel ? null : action.panel, + visiblePanel: + state.visiblePanel === action.panel ? null : action.panel, }; default: return state; diff --git a/src/stores/primary-sidebar/primary-sidebar-actions.js b/src/stores/primary-sidebar/primary-sidebar-actions.js index cfd195b..336f6a8 100644 --- a/src/stores/primary-sidebar/primary-sidebar-actions.js +++ b/src/stores/primary-sidebar/primary-sidebar-actions.js @@ -3,8 +3,6 @@ * * @type {Object} */ -const actions = { - -}; +const actions = {}; export default actions; diff --git a/webpack.config.js b/webpack.config.js index 7007b9b..aaaa743 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,17 +1,16 @@ -const defaults = require("@wordpress/scripts/config/webpack.config"); -const path = require("path"); - +const defaults = require( '@wordpress/scripts/config/webpack.config' ); +const path = require( 'path' ); module.exports = { ...defaults, entry: { - index: path.resolve(process.cwd(), "src", "index.js"), - render: path.resolve(process.cwd(), "src", "render.js"), - graphql: path.resolve(process.cwd(), "src", "graphql.js"), + index: path.resolve( process.cwd(), 'src', 'index.js' ), + render: path.resolve( process.cwd(), 'src', 'render.js' ), + graphql: path.resolve( process.cwd(), 'src', 'graphql.js' ), }, externals: { - react: "React", - "react-dom": "ReactDOM", - graphql: "graphql", + react: 'React', + 'react-dom': 'ReactDOM', + graphql: 'graphql', }, }; From 9ec994edf468417b9b5944fd7493b45726c505a8 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 4 Jun 2024 09:50:17 -0600 Subject: [PATCH 7/9] - attempting (and failing) to enqueue assets from the manifest.json --- .gitignore | 3 +- build/manifest.json | 203 ++++++++++++++ package-lock.json | 259 +++++++++++------- package.json | 5 +- .../third-party-plugin/third-party-plugin.php | 2 +- webpack.config.js | 38 ++- wpgraphql-ide.php | 165 +++++++++-- 7 files changed, 552 insertions(+), 123 deletions(-) create mode 100644 build/manifest.json diff --git a/.gitignore b/.gitignore index e1a8683..45b3a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,10 +58,11 @@ artifacts # build/release artifacts build/ +!build/manifest.json wpgraphql-ide/ wpgraphql-ide.zip /test-results/ /playwright-report/ /blob-report/ /playwright/.cache/ -/@wpgraphql/ \ No newline at end of file +/@wpgraphql/ diff --git a/build/manifest.json b/build/manifest.json new file mode 100644 index 0000000..e07ffe8 --- /dev/null +++ b/build/manifest.json @@ -0,0 +1,203 @@ +{ + "name": "wpgraphql-ide", + "version": "2.1.1", + "assets": { + "graphql-js": { + "path": "build/graphql.js", + "hash": "dc958cd6", + "chunkName": "graphql", + "originalFileName": "graphql.js" + }, + "graphql-php": { + "path": "build/graphql.asset.php", + "hash": "97bf8429", + "chunkName": "graphql", + "originalFileName": "graphql.php" + }, + "wpgraphql-ide-css": { + "path": "build/wpgraphql-ide.css", + "hash": "0d4eacd5", + "chunkName": "wpgraphql-ide", + "originalFileName": "wpgraphql-ide.css" + }, + "wpgraphql-ide-js": { + "path": "build/wpgraphql-ide.js", + "hash": "56cda257", + "chunkName": "wpgraphql-ide", + "originalFileName": "wpgraphql-ide.js" + }, + "wpgraphql-ide-php": { + "path": "build/wpgraphql-ide.asset.php", + "hash": "78a02b24", + "chunkName": "wpgraphql-ide", + "originalFileName": "wpgraphql-ide.php" + }, + "wpgraphql-ide-render-css": { + "path": "build/wpgraphql-ide-render.css", + "hash": "0b884f4c", + "chunkName": "wpgraphql-ide-render", + "originalFileName": "wpgraphql-ide-render.css" + }, + "wpgraphql-ide-render-js": { + "path": "build/wpgraphql-ide-render.js", + "hash": "c9a3143b", + "chunkName": "wpgraphql-ide-render", + "originalFileName": "wpgraphql-ide-render.js" + }, + "wpgraphql-ide-render-php": { + "path": "build/wpgraphql-ide-render.asset.php", + "hash": "475a8d07", + "chunkName": "wpgraphql-ide-render", + "originalFileName": "wpgraphql-ide-render.php" + }, + "338-js": { + "path": "build/338.js", + "hash": "8f4a66cb", + "chunkName": null, + "originalFileName": "338.js" + }, + "669-js": { + "path": "build/669.js", + "hash": "546a1967", + "chunkName": null, + "originalFileName": "669.js" + }, + "382-js": { + "path": "build/382.js", + "hash": "c55a03cf", + "chunkName": null, + "originalFileName": "382.js" + }, + "61-js": { + "path": "build/61.js", + "hash": "a1ccf8ec", + "chunkName": null, + "originalFileName": "61.js" + }, + "983-js": { + "path": "build/983.js", + "hash": "5beb7779", + "chunkName": null, + "originalFileName": "983.js" + }, + "148-js": { + "path": "build/148.js", + "hash": "d90ac49d", + "chunkName": null, + "originalFileName": "148.js" + }, + "951-js": { + "path": "build/951.js", + "hash": "3c3e8a07", + "chunkName": null, + "originalFileName": "951.js" + }, + "910-js": { + "path": "build/910.js", + "hash": "53d64e89", + "chunkName": null, + "originalFileName": "910.js" + }, + "113-js": { + "path": "build/113.js", + "hash": "ee7d6882", + "chunkName": null, + "originalFileName": "113.js" + }, + "924-js": { + "path": "build/924.js", + "hash": "e0fa696e", + "chunkName": null, + "originalFileName": "924.js" + }, + "391-js": { + "path": "build/391.js", + "hash": "acbff0f0", + "chunkName": null, + "originalFileName": "391.js" + }, + "277-js": { + "path": "build/277.js", + "hash": "5b6bf40c", + "chunkName": null, + "originalFileName": "277.js" + }, + "77-js": { + "path": "build/77.js", + "hash": "ce22e609", + "chunkName": null, + "originalFileName": "77.js" + }, + "528-js": { + "path": "build/528.js", + "hash": "513eea5d", + "chunkName": null, + "originalFileName": "528.js" + }, + "627-js": { + "path": "build/627.js", + "hash": "01d840ba", + "chunkName": null, + "originalFileName": "627.js" + }, + "385-js": { + "path": "build/385.js", + "hash": "dab78ca8", + "chunkName": null, + "originalFileName": "385.js" + }, + "420-js": { + "path": "build/420.js", + "hash": "d1a73220", + "chunkName": null, + "originalFileName": "420.js" + }, + "260-js": { + "path": "build/260.js", + "hash": "6557263d", + "chunkName": null, + "originalFileName": "260.js" + }, + "93-js": { + "path": "build/93.js", + "hash": "4097c1b5", + "chunkName": null, + "originalFileName": "93.js" + }, + "253-js": { + "path": "build/253.js", + "hash": "eb374587", + "chunkName": null, + "originalFileName": "253.js" + }, + "482-js": { + "path": "build/482.js", + "hash": "ac2d9c02", + "chunkName": null, + "originalFileName": "482.js" + }, + "271-js": { + "path": "build/271.js", + "hash": "3f44923c", + "chunkName": null, + "originalFileName": "271.js" + }, + "912-js": { + "path": "build/912.js", + "hash": "73182d91", + "chunkName": null, + "originalFileName": "912.js" + }, + "681-js": { + "path": "build/681.js", + "hash": "2f355ec7", + "chunkName": null, + "originalFileName": "681.js" + }, + "90-js": { + "path": "build/90.js", + "hash": "510f2676", + "originalFileName": "90.js" + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a30d775..b15be10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,9 @@ "graphql-ws": "^5.14.2", "lz-string": "^1.5.0", "react": "^18.2.0", - "vaul": "^0.9.0" + "vaul": "^0.9.0", + "webpack-manifest-plugin": "^5.0.0", + "webpack-nano": "^1.1.1" }, "devDependencies": { "@babel/preset-env": "^7.23.9", @@ -37,6 +39,7 @@ "chalk": "^5.3.0", "clsx": "^2.0.0", "concurrently": "^8.2.2", + "crypto": "^1.0.1", "docker-compose": "^0.24.6", "dotenv": "^16.4.4", "husky": "^9.0.11", @@ -4224,7 +4227,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -4238,7 +4240,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -4247,7 +4248,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -4256,7 +4256,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -4265,14 +4264,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -6215,7 +6212,6 @@ "version": "8.56.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.6.tgz", "integrity": "sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -6225,7 +6221,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -6348,8 +6343,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -6392,7 +6386,6 @@ "version": "20.11.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", - "devOptional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -6969,7 +6962,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -6978,26 +6970,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -7007,14 +6995,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -7026,7 +7012,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -7035,7 +7020,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -7043,14 +7027,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -7066,7 +7048,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -7079,7 +7060,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -7091,7 +7071,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -7105,7 +7084,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -8083,14 +8061,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abab": { "version": "2.0.6", @@ -8116,7 +8092,6 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -8138,7 +8113,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -8186,7 +8160,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8250,7 +8223,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -9166,7 +9138,6 @@ "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -9239,8 +9210,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/builtin-modules": { "version": "3.3.0", @@ -9427,7 +9397,6 @@ "version": "1.0.30001600", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -9640,7 +9609,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -10615,6 +10583,13 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.", + "dev": true + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -11636,8 +11611,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.716", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.716.tgz", - "integrity": "sha512-t/MXMzFKQC3UfMDpw7V5wdB/UAB8dWx4hEsy+fpPYJWW3gqh3u5T1uXp6vR+H6dGCPBxkRo+YBcapBLvbGQHRw==", - "dev": true + "integrity": "sha512-t/MXMzFKQC3UfMDpw7V5wdB/UAB8dWx4hEsy+fpPYJWW3gqh3u5T1uXp6vR+H6dGCPBxkRo+YBcapBLvbGQHRw==" }, "node_modules/emittery": { "version": "0.13.1", @@ -11696,7 +11670,6 @@ "version": "5.16.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -11895,8 +11868,7 @@ "node_modules/es-module-lexer": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.0.tgz", - "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==", - "dev": true + "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -12611,7 +12583,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -12624,7 +12595,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -12901,7 +12871,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -12913,7 +12882,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -12946,7 +12914,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -13256,8 +13223,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -14023,8 +13989,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.11", @@ -14766,7 +14731,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -17578,8 +17542,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -18285,7 +18248,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -18917,8 +18879,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -18987,7 +18948,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -18996,7 +18956,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -19310,8 +19269,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/netmask": { "version": "2.0.2", @@ -19391,8 +19349,7 @@ "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-package-data": { "version": "3.0.3", @@ -21494,7 +21451,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -21647,7 +21603,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -22219,7 +22174,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -22540,7 +22494,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -22658,7 +22611,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -23306,6 +23258,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -23987,7 +23944,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -24211,7 +24167,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -24289,7 +24244,6 @@ "version": "5.29.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", - "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -24307,7 +24261,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -24341,7 +24294,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -24354,14 +24306,12 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/terser/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -24370,7 +24320,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -24896,8 +24845,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -24973,7 +24921,6 @@ "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -25019,7 +24966,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -25332,7 +25278,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -25377,7 +25322,6 @@ "version": "5.91.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -25769,6 +25713,41 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack-manifest-plugin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-5.0.0.tgz", + "integrity": "sha512-8RQfMAdc5Uw3QbCQ/CBV/AXqOR8mt03B6GJmRbhWopE8GzRfEpn+k0ZuWywxW+5QZsffhmFDY1J6ohqJo+eMuw==", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -25830,11 +25809,105 @@ "node": ">=8" } }, + "node_modules/webpack-nano": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webpack-nano/-/webpack-nano-1.1.1.tgz", + "integrity": "sha512-3dypjHtWQylpgsYmaovsUgFmXmDBoArq8aNMvDjmhVRpaA8MQsYxMiXgsp09GYL3n5y+1PfscytrFW3IXknlIQ==", + "dependencies": { + "chalk": "^4.1.0", + "import-local": "^3.0.2", + "rechoir": "^0.7.0", + "yargs-parser": "^20.2.1" + }, + "bin": { + "wp": "bin/wp.js" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "webpack": ">=4.20.2" + } + }, + "node_modules/webpack-nano/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/webpack-nano/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/webpack-nano/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/webpack-nano/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/webpack-nano/node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/webpack-nano/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-nano/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } diff --git a/package.json b/package.json index 1022895..2aff061 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "chalk": "^5.3.0", "clsx": "^2.0.0", "concurrently": "^8.2.2", + "crypto": "^1.0.1", "docker-compose": "^0.24.6", "dotenv": "^16.4.4", "husky": "^9.0.11", @@ -63,7 +64,9 @@ "graphql-ws": "^5.14.2", "lz-string": "^1.5.0", "react": "^18.2.0", - "vaul": "^0.9.0" + "vaul": "^0.9.0", + "webpack-manifest-plugin": "^5.0.0", + "webpack-nano": "^1.1.1" }, "lint-staged": { "package.json": "sort-package-json" diff --git a/plugins/third-party-plugin/third-party-plugin.php b/plugins/third-party-plugin/third-party-plugin.php index 5172f26..a8db6b5 100644 --- a/plugins/third-party-plugin/third-party-plugin.php +++ b/plugins/third-party-plugin/third-party-plugin.php @@ -26,7 +26,7 @@ wp_enqueue_script( 'third-party-plugin', plugins_url( 'build/index.js', __FILE__ ), - array_merge( $asset_file['dependencies'], ['wpgraphql-ide'] ), + array_merge( $asset_file['dependencies'], ['wpgraphql-ide-js'] ), $asset_file['version'] ); diff --git a/webpack.config.js b/webpack.config.js index aaaa743..9d42aa4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,16 +1,50 @@ const defaults = require( '@wordpress/scripts/config/webpack.config' ); const path = require( 'path' ); +const { WebpackManifestPlugin } = require('webpack-manifest-plugin'); +const { createHash } = require('crypto'); +const packageJson = require('./package.json'); + +function sluggify(filename) { + return filename + .replace(/[^a-zA-Z0-9-]/g, ' ') // Remove all non-letter and non-dash characters + .replace(/\s+/g, '-') // Replace spaces with dashes + .toLowerCase(); +} module.exports = { ...defaults, entry: { - index: path.resolve( process.cwd(), 'src', 'index.js' ), - render: path.resolve( process.cwd(), 'src', 'render.js' ), graphql: path.resolve( process.cwd(), 'src', 'graphql.js' ), + "wpgraphql-ide": path.resolve( process.cwd(), 'src', 'index.js' ), + "wpgraphql-ide-render": path.resolve( process.cwd(), 'src', 'render.js' ), }, externals: { react: 'React', 'react-dom': 'ReactDOM', graphql: 'graphql', }, + plugins: [ + ...defaults.plugins, + new WebpackManifestPlugin({ + fileName: 'manifest.json', + publicPath: 'build/', + generate: (seed, files) => { + const manifest = {}; + manifest.name = packageJson.name; + manifest.version = packageJson.version; + manifest.assets = files.reduce((acc, file) => { + const hash = createHash('md5').update(file.path).digest('hex').substr(0, 8); + acc[ sluggify( file.name ) ] = { + path: file.path, + hash, + size: file.size, + chunkName: file.chunk ? file.chunk.name : null, + originalFileName: path.basename(file.name), + }; + return acc; + }, seed); + return manifest; + }, + }), + ], }; diff --git a/wpgraphql-ide.php b/wpgraphql-ide.php index d9ef1e9..d287f2e 100644 --- a/wpgraphql-ide.php +++ b/wpgraphql-ide.php @@ -223,7 +223,7 @@ function enqueue_graphql_ide_menu_icon_css(): void { /** * Enqueues the React application script and associated styles. */ -function enqueue_react_app_with_styles(): void { +function register_scripts(): void { if ( is_legacy_ide_page() ) { return; } @@ -244,27 +244,127 @@ function enqueue_react_app_with_styles(): void { } } - $asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/index.asset.php'; - $render_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/render.asset.php'; - $graphql_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/graphql.asset.php'; + $manifest_path = WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/manifest.json'; - $app_context = get_app_context(); + if ( ! file_exists( $manifest_path ) ) { + return; + } - wp_register_script( - 'graphql', - plugins_url( 'build/graphql.js', __FILE__ ), - $graphql_asset_file['dependencies'], - $graphql_asset_file['version'], - false - ); + $manifest = file_get_contents( $manifest_path ); + $manifest_contents = json_decode( $manifest, true ); - wp_enqueue_script( - 'wpgraphql-ide', - plugins_url( 'build/index.js', __FILE__ ), - array_merge( $asset_file['dependencies'], [ 'graphql' ] ), - $asset_file['version'], - false - ); + if ( empty( $manifest_contents ) || ! is_array( $manifest_contents ) ) { + return; + } + + $assets = $manifest_contents['assets'] ?? []; + + $registered = []; + + foreach ( $assets as $key => $asset ) { + + // if the asset['path'] does not end in .php or .css skip it + if ( ! preg_match( '/\.(php|css)$/', $asset['path'] ) ) { + continue; + } + + // $handle should be the key of the asset sluggified + $key = sanitize_title( $key ); + + // if the asset is a css file, enqueue it + if ( 'css' === pathinfo( $asset['path'], PATHINFO_EXTENSION ) ) { + wp_enqueue_style( + $key, + plugins_url( $asset['path'], __FILE__ ), + [], + $asset['hash'] + ); + + } + + + // if the asset is a php file, load the asset.php file and get the version and dependencies to enqueue + if ( 'php' === pathinfo( $asset['path'], PATHINFO_EXTENSION ) ) { + $asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . '/' . $asset['path']; + + $registered[] = $asset['chunkName'] . '-js'; + + wp_register_script( + $asset['chunkName'] . '-js', + plugins_url( '/build/' . $asset['chunkName'] . '.js', __FILE__ ), + array_merge( $asset_file['dependencies'] ), + $asset['hash'], + false + ); + +// wp_send_json( [ +// '$key' => $key, +// '$path' => untrailingslashit( plugins_url( '/build/' . $asset['chunkName'] . '.js', __FILE__ ) ), +// '$dependencies' => $asset_file['dependencies'], +// '$version' => $asset_file['version'], +// ]); + +// wp_send_json( [ +// '$asset_path' => $asset['path'], +// '$asset_file_path' => $asset_file, +// '$asset' => $asset, +// '$asset_file' => $asset_file, +//// '$key' => $key, +// 'path' => plugins_url( $asset['path'], __FILE__ ), +//// 'dependencies' => $asset_file['dependencies'], +//// 'version' => $asset_file['version'], +// ]); + + } + + + } + + +// wp_send_json( [ +// 'manifest' => json_decode( $manifest, true ), +// ] ); + +// +// $asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/index.asset.php'; +// $render_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/render.asset.php'; +// $graphql_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/graphql.asset.php'; +// + + +// wp_register_script( +// 'graphql', +// plugins_url( 'build/graphql.js', __FILE__ ), +// $graphql_asset_file['dependencies'], +// $graphql_asset_file['version'], +// false +// ); +// +// wp_enqueue_script( +// 'wpgraphql-ide', +// plugins_url( 'build/index.js', __FILE__ ), +// array_merge( $asset_file['dependencies'], [ 'graphql' ] ), +// $asset_file['version'], +// false +// ); +// + +// + +// +// wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $asset_file['version'] ); +// wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $asset_file['version'] ); +// +// // Avoid running custom styles through a build process for an improved developer experience. +// wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $asset_file['version'] ); +} + +add_action( 'init', __NAMESPACE__ . '\\register_scripts' ); + + +function enqueue_react_app_with_styles() { + + $app_context = get_app_context(); $localized_data = [ 'nonce' => wp_create_nonce( 'wp_rest' ), @@ -276,29 +376,44 @@ function enqueue_react_app_with_styles(): void { ]; wp_localize_script( - 'wpgraphql-ide', + 'wpgraphql-ide-js', 'WPGRAPHQL_IDE_DATA', $localized_data ); + $graphql_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/wpgraphql-ide-render.asset.php'; + + wp_enqueue_script( + 'graphql-js', + plugins_url( 'build/render.js', __FILE__ ), + array_merge( $graphql_asset_file['dependencies'] ), + $graphql_asset_file['version'], + false + ); +// // Extensions looking to extend GraphiQL can hook in here, // after the window object is established, but before the App renders do_action( 'wpgraphqlide_enqueue_script', $app_context ); + $render_asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/wpgraphql-ide-render.asset.php'; + wp_enqueue_script( - 'wpgraphql-ide-render', + 'wpgraphql-ide-render-js', plugins_url( 'build/render.js', __FILE__ ), - array_merge( $asset_file['dependencies'], [ 'wpgraphql-ide', 'graphql' ] ), + array_merge( $render_asset_file['dependencies'], [ 'wpgraphql-ide-js', 'graphql-js' ] ), $render_asset_file['version'], false ); - wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $asset_file['version'] ); - wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $render_asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $render_asset_file['version'] ); // Avoid running custom styles through a build process for an improved developer experience. - wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $render_asset_file['version'] ); + } + + add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' ); add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' ); From 3050f9c789ed05b84efdcede70bdc40a11c5f9af Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 4 Jun 2024 09:52:56 -0600 Subject: [PATCH 8/9] - updated css paths --- wpgraphql-ide.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpgraphql-ide.php b/wpgraphql-ide.php index d287f2e..52cd635 100644 --- a/wpgraphql-ide.php +++ b/wpgraphql-ide.php @@ -405,8 +405,8 @@ function enqueue_react_app_with_styles() { false ); - wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $render_asset_file['version'] ); - wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $render_asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/wpgraphql-ide.css', __FILE__ ), [], $render_asset_file['version'] ); + wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/wpgraphql-ide-render.css', __FILE__ ), [], $render_asset_file['version'] ); // Avoid running custom styles through a build process for an improved developer experience. wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $render_asset_file['version'] ); From e1049091de98100a83a584a9b90a25fbe3e12554 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 4 Jun 2024 10:00:24 -0600 Subject: [PATCH 9/9] - update handles --- src/index.js | 2 ++ src/render.js | 2 ++ wpgraphql-ide.php | 7 +++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index 630096d..8282a7f 100644 --- a/src/index.js +++ b/src/index.js @@ -34,6 +34,8 @@ window.WPGraphQLIDE = { ...accessFunctions, }; +console.log( `WPGraphQLIDE is ready` ); + window.dispatchEvent( new Event( 'WPGraphQLIDE_Window_Ready' ) ); // // // Dynamically import the GraphQL library and assign it to `window.WPGraphQLIDE.GraphQL` diff --git a/src/render.js b/src/render.js index 534efad..b3bbfdf 100644 --- a/src/render.js +++ b/src/render.js @@ -1,6 +1,8 @@ import { createRoot } from '@wordpress/element'; import AppWrapper from './components/AppWrapper'; +console.log( `render.js...` ); + window.addEventListener( 'WPGraphQLIDE_Window_Ready', function ( event ) { /** * Get our root element id from the localized script. diff --git a/wpgraphql-ide.php b/wpgraphql-ide.php index 52cd635..480080f 100644 --- a/wpgraphql-ide.php +++ b/wpgraphql-ide.php @@ -26,7 +26,7 @@ define( 'WPGRAPHQL_IDE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); // TEMPORARY TEST -require_once WPGRAPHQL_IDE_PLUGIN_DIR_PATH . '/plugins/third-party-plugin/third-party-plugin.php'; +// require_once WPGRAPHQL_IDE_PLUGIN_DIR_PATH . '/plugins/third-party-plugin/third-party-plugin.php'; /** * Generates the SVG logo for GraphQL. @@ -376,7 +376,7 @@ function enqueue_react_app_with_styles() { ]; wp_localize_script( - 'wpgraphql-ide-js', + 'wpgraphql-ide-render-js', 'WPGRAPHQL_IDE_DATA', $localized_data ); @@ -390,7 +390,7 @@ function enqueue_react_app_with_styles() { $graphql_asset_file['version'], false ); -// + // Extensions looking to extend GraphiQL can hook in here, // after the window object is established, but before the App renders do_action( 'wpgraphqlide_enqueue_script', $app_context ); @@ -413,7 +413,6 @@ function enqueue_react_app_with_styles() { } - add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' ); add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' );