Skip to content

Commit

Permalink
Added refactor query functionality.
Browse files Browse the repository at this point in the history
Closes #745.
  • Loading branch information
imolorhe committed Dec 21, 2019
1 parent 0273393 commit c302e1c
Show file tree
Hide file tree
Showing 9 changed files with 490 additions and 13 deletions.
8 changes: 8 additions & 0 deletions src/app/actions/query/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const PRETTIFY_QUERY = 'PRETTIFY_QUERY';
export const COMPRESS_QUERY = 'COMPRESS_QUERY';
export const COPY_AS_CURL = 'COPY_AS_CURL';
export const CONVERT_TO_NAMED_QUERY = 'CONVERT_TO_NAMED_QUERY';
export const REFACTOR_QUERY = 'REFACTOR_QUERY';

export const SEND_QUERY_REQUEST = 'SEND_QUERY_REQUEST';
export const CANCEL_QUERY_REQUEST = 'CANCEL_QUERY_REQUEST';
Expand Down Expand Up @@ -115,6 +116,12 @@ export class ConvertToNamedQueryAction implements Action {
constructor(public windowId: string, public payload?: any) {}
}

export class RefactorQueryAction implements Action {
readonly type = REFACTOR_QUERY;

constructor(public windowId: string, public payload?: any) {}
}

export class SendQueryRequestAction implements Action {
readonly type = SEND_QUERY_REQUEST;

Expand Down Expand Up @@ -211,6 +218,7 @@ export type Action =
| CompressQueryAction
| CopyAsCurlAction
| ConvertToNamedQueryAction
| RefactorQueryAction
| SendQueryRequestAction
| SetSelectedOperationAction
| StartSubscriptionAction
Expand Down
8 changes: 8 additions & 0 deletions src/app/containers/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@
{{ 'CONVERT_TO_NAMED_QUERY_BUTTON' | translate }}
</div>
</a>
<a class="submenu-item" (click)="refactorQuery()" attr.aria-label="{{ 'REFACTOR_QUERY_BUTTON' | translate }}">
<div class="submenu-item-icon">
<app-icon name="disc"></app-icon>
</div>
<div class="submenu-item-label">
{{ 'REFACTOR_QUERY_BUTTON' | translate }}
</div>
</a>
</div>
</div>
<div class="side-menu-divider"></div>
Expand Down
4 changes: 4 additions & 0 deletions src/app/containers/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ export class AppComponent implements OnDestroy {
this.store.dispatch(new queryActions.ConvertToNamedQueryAction(this.activeWindowId));
}

refactorQuery() {
this.store.dispatch(new queryActions.RefactorQueryAction(this.activeWindowId));
}

toggleHeader(isOpen: boolean) {
this.store.dispatch(new dialogsActions.ToggleHeaderDialogAction(this.activeWindowId));
}
Expand Down
34 changes: 34 additions & 0 deletions src/app/effects/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as fromRoot from '../reducers';

import { Action as allActions } from '../actions';
import * as queryActions from '../actions/query/query';
import * as variablesActions from '../actions/variables/variables';
import * as layoutActions from '../actions/layout/layout';
import * as gqlSchemaActions from '../actions/gql-schema/gql-schema';
import * as dbActions from '../actions/db/db';
Expand Down Expand Up @@ -707,6 +708,39 @@ export class QueryEffects {
}),
);

@Effect()
refactorQuery$: Observable<Action> = this.actions$
.pipe(
ofType(queryActions.REFACTOR_QUERY),
withLatestFrom(this.store, (action: queryActions.Action, state: fromRoot.State) => {
return { data: state.windows[action.windowId], windowId: action.windowId, action };
}),
switchMap(res => {
try {
if (res.data.query.query && res.data.schema.schema) {
const refactorResult = this.gqlService.refactorQuery(res.data.query.query, res.data.schema.schema);
if (refactorResult && refactorResult.query) {
try {
this.store.dispatch(new variablesActions.UpdateVariablesAction(JSON.stringify({
...JSON.parse(res.data.variables.variables),
...refactorResult.variables,
}, null, 2), res.windowId));
} catch (err) {
this.notifyService.warning('Looks like your variables are not formatted properly');
return observableEmpty();
}
return observableOf(new queryActions.SetQueryAction(refactorResult.query, res.windowId));
}
}
} catch (err) {
debug.log(err);
this.notifyService.error('Your query does not appear to be valid. Please check it.');
}

return observableEmpty();
}),
);

@Effect()
showDonationAlert$: Observable<Action> = this.actions$
.pipe(
Expand Down
2 changes: 2 additions & 0 deletions src/app/interfaces/shared.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export interface IDictionary<V = any> {
[ key: string ]: V;
}

export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
2 changes: 2 additions & 0 deletions src/app/modules/icons/icons.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Copy,
Cpu,
Camera,
Disc,
Download,
Edit,
Eye,
Expand Down Expand Up @@ -68,6 +69,7 @@ const icons = {
Copy,
Cpu,
Camera,
Disc,
Download,
Edit,
Eye,
Expand Down
42 changes: 29 additions & 13 deletions src/app/services/gql/gql.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ import * as fromVariables from '../../reducers/variables/variables';
import { fillAllFields } from './fillFields';
import { setByDotNotation } from 'app/utils';
import { Token } from 'codemirror';
import { IDictionary, Omit } from 'app/interfaces/shared';
import {
refactorFieldsWithFragmentSpread,
generateTypeUsageEntries,
generateFragmentRefactorMap,
addFragmentDefinitionFromRefactorMap,
refactorArgumentsToVariables,
} from './helpers';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

interface SendRequestOptions {
query: string;
Expand Down Expand Up @@ -377,17 +384,6 @@ export class GqlService {
return parsedQuery.definitions
.filter((def): def is OperationDefinitionNode =>
!!(def.kind === 'OperationDefinition' && def.name && def.name.value));
// TODO: Figure out if this map is required
// .map((def: OperationDefinitionNode, i) => {
// if (def.kind === 'OperationDefinition') {
// // Make sure all operations have names
// if (!def.name || !def.name.value) {
// def.name = def.name || {};
// def.name.value = '#' + i.toString();
// }
// }
// return def;
// });
}

return [];
Expand Down Expand Up @@ -501,11 +497,31 @@ export class GqlService {
return print(edited);
}

refactorQuery(query: string, schema: GraphQLSchema) {

if (!query || !schema) {
return;
}
const ast = this.parseQuery(query);
const typeUsageEntries = generateTypeUsageEntries(ast, schema);

const fragmentRefactorMap = generateFragmentRefactorMap(typeUsageEntries);
const stripped = refactorFieldsWithFragmentSpread(ast, fragmentRefactorMap, schema);
const documentWithFragments = addFragmentDefinitionFromRefactorMap(stripped, fragmentRefactorMap, schema);
const argumentRefactorResult = refactorArgumentsToVariables(documentWithFragments, schema);

// debug.log('REFACTOR', ast, edited, fragmentRefactorMap, print(argumentRefactorResult.document), argumentRefactorResult.variables);
return {
query: print(argumentRefactorResult.document),
variables: argumentRefactorResult.variables,
};
}

/**
* Return the Schema Definition Language of the provided schema
* @param schema
*/
async getSDL(schema: any) {
async getSDL(schema: GraphQLSchema) {
if (this.isSchema(schema)) {
return this.prettify(printSchema(schema));
}
Expand Down
Loading

0 comments on commit c302e1c

Please sign in to comment.