Skip to content

Commit

Permalink
feat(ui): make paste as curl recognize graphql + graphql requests now…
Browse files Browse the repository at this point in the history
… show GQL instead POST in sidebar + beautify graphql
  • Loading branch information
kobenguyent authored Sep 14, 2024
1 parent 811b065 commit 2f3ee23
Show file tree
Hide file tree
Showing 11 changed files with 528 additions and 19 deletions.
440 changes: 432 additions & 8 deletions packages/ui/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"dedent": "^1.5.1",
"dexie": "^3.2.0",
"dexie-export-import": "^1.0.3",
"format-graphql": "^1.5.0",
"graphql-request": "^7.1.0",
"httpsnippet-browser": "github:flawiddsouza/httpsnippet-browser#ed12aba",
"insomnia-importers-browser": "github:flawiddsouza/insomnia-importers-browser",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/GraphQLSchemaFetcher.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default {
required: true
},
schemaAction: {
type: String,
type: [null, String],
required: true,
},
},
Expand Down
12 changes: 10 additions & 2 deletions packages/ui/src/components/RequestPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ import { marked } from 'marked'
import HttpMethodModal from '@/components/modals/HttpMethodModal.vue'
import GraphQLSchemaFetcher from '@/components/GraphQLSchemaFetcher.vue'
import GenerateCodeModal from '@/components/modals/GenerateCodeModal.vue'
import { formatSdl } from 'format-graphql'

const renderer = new marked.Renderer()

Expand Down Expand Up @@ -770,8 +771,10 @@ export default {
},
beautifyGraphQL() {
try {
const formattedJSON = jsonPrettify(this.graphql.variables, ' ')
this.$refs.jsonEditor.setValue(formattedJSON)
const formattedVarsJSON = jsonPrettify(this.graphql.variables, ' ')
const formattedGraphqlJSON = formatSdl(this.graphql.query)
this.$refs.jsonEditor.setValue(formattedVarsJSON)
this.$refs.graphqlEditor.setValue(formattedGraphqlJSON)
} catch {} // catch all json parsing errors and ignore them
},
showGraphQLDocs(value){
Expand All @@ -797,13 +800,18 @@ export default {
return false
}
const result = await convertCurlCommandToRestfoxCollection(content, this.activeWorkspace._id)

if(result.length) {
delete result[0].name
delete result[0]._id
delete result[0]._type
delete result[0].workspaceId
delete result[0].parentId
Object.assign(this.activeTab, result[0])

if(this.activeTab.body.mimeType === constants.MIME_TYPE.GRAPHQL) {
this.loadGraphql()
}
}

return true
Expand Down
6 changes: 5 additions & 1 deletion packages/ui/src/components/SidebarItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</div>
</template>
<template v-if="sidebarItem._type === 'request'">
<div class="sidebar-item-method" :class="`request-method--${sidebarItem.method}`">{{ getMethodShortName(sidebarItem.method) }}</div>
<div class="sidebar-item-method" :class="`request-method--${isGqlRequest(sidebarItem) ? 'GQL' : sidebarItem.method}`">{{ getMethodShortName(isGqlRequest(sidebarItem) ? 'GQL' : sidebarItem.method) }}</div>
</template>
<template v-if="sidebarItem._type === 'socket'">
<div class="sidebar-item-method" :class="`request-method--SOCK`">SOCK</div>
Expand Down Expand Up @@ -93,6 +93,7 @@ export default {
'DELETE': 'DEL',
'PATCH': 'PTCH',
'OPTIONS': 'OPT',
'GRAPHQL': 'GQL'
}
return methods[method] || method
Expand Down Expand Up @@ -166,6 +167,9 @@ export default {
cancelSidebarItemNameRename() {
delete this.$store.state.sidebarItemTemporaryName[this.sidebarItem._id]
this.showInputToRenameRequest = false
},
isGqlRequest(request) {
return request.body.mimeType === 'application/graphql'
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,14 @@ export async function convertCurlCommandToRestfoxCollection(curlCommand: string,

if('body' in insomniaExport[0]) {
if('text' in insomniaExport[0].body) {
// for some reason we get \\n instead of \n in the text field
insomniaExport[0].body.text = insomniaExport[0].body.text.replaceAll('\\n', '\n')
if (insomniaExport[0].body.mimeType !== constants.MIME_TYPE.GRAPHQL) {
// for some reason we get \\n instead of \n in the text field
insomniaExport[0].body.text = insomniaExport[0].body.text.replaceAll('\\n', '\n')
} else {
const parsedBody = JSON.parse(insomniaExport[0].body.text)
parsedBody.query = parsedBody.query.replaceAll('\\n', '\n')
insomniaExport[0].body.text = JSON.stringify(parsedBody)
}
}
}
return convertInsomniaExportToRestfoxCollection({ resources: insomniaExport }, workspaceId)
Expand Down Expand Up @@ -1762,3 +1768,4 @@ export function getEditorConfig(): EditorConfig {
export function jsonStringify(data: any, space: number = getEditorConfig().indentSize): any {
return JSON.stringify(data, null, space)
}

45 changes: 45 additions & 0 deletions packages/ui/src/parsers/curl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,49 @@ describe('curl', () => {
}
}])
})

it('Curl command - GQL request', () => {
const chromeCurlCmd = `curl 'https://app.argos-ci.com/graphql' \\
-H 'accept: */*' \\
-H 'accept-language: en-US,en;q=0.9,vi;q=0.8,de;q=0.7' \\
-H 'authorization: Bearer token' \\
-H 'content-type: application/json' \\
--data-raw $'{"operationName":"AccountBreadcrumb_account","variables":{"slug":"kobenguyent"},"query":"query AccountBreadcrumb_account($slug: String\u0021) {\\\\n account(slug: $slug) {\\\\n id\\\\n slug\\\\n name\\\\n avatar {\\\\n ...AccountAvatarFragment\\\\n __typename\\\\n }\\\\n ...AccountPlanChip_Account\\\\n __typename\\\\n }\\\\n}\\\\n\\\\nfragment AccountAvatarFragment on AccountAvatar {\\\\n url(size: 64)\\\\n color\\\\n initial\\\\n __typename\\\\n}\\\\n\\\\nfragment AccountPlanChip_Account on Account {\\\\n subscriptionStatus\\\\n plan {\\\\n id\\\\n displayName\\\\n __typename\\\\n }\\\\n __typename\\\\n}"}'`.trim()
const result = convert(chromeCurlCmd)

expect(result).toMatchObject([
{
'_id': '__REQ_1__',
'_type': 'request',
'authentication': {},
'body': {
'mimeType': 'application/graphql',
'text': '{"operationName":"AccountBreadcrumb_account","variables":{"slug":"kobenguyent"},"query":"query AccountBreadcrumb_account($slug: String!) {\\\\n account(slug: $slug) {\\\\n id\\\\n slug\\\\n name\\\\n avatar {\\\\n ...AccountAvatarFragment\\\\n __typename\\\\n }\\\\n ...AccountPlanChip_Account\\\\n __typename\\\\n }\\\\n}\\\\n\\\\nfragment AccountAvatarFragment on AccountAvatar {\\\\n url(size: 64)\\\\n color\\\\n initial\\\\n __typename\\\\n}\\\\n\\\\nfragment AccountPlanChip_Account on Account {\\\\n subscriptionStatus\\\\n plan {\\\\n id\\\\n displayName\\\\n __typename\\\\n }\\\\n __typename\\\\n}"}',
},
'headers': [
{
'name': 'accept',
'value': '*/*',
},
{
'name': 'accept-language',
'value': 'en-US,en;q=0.9,vi;q=0.8,de;q=0.7',
},
{
'name': 'authorization',
'value': 'Bearer token',
},
{
'name': 'content-type',
'value': 'application/json',
},
],
'method': 'POST',
'name': 'https://app.argos-ci.com/graphql',
'parameters': [],
'parentId': '__WORKSPACE_ID__',
'url': 'https://app.argos-ci.com/graphql',
},
])
})
})
22 changes: 18 additions & 4 deletions packages/ui/src/parsers/curl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { ControlOperator, parse, ParseEntry } from 'shell-quote'
import { Converter, ImportRequest, Parameter, PostData } from './curl.types'
import constants from '@/constants'

export const id = 'curl'
export const name = 'cURL'
Expand Down Expand Up @@ -169,7 +170,7 @@ const importCommand = (parseEntries: ParseEntry[]): ImportRequest => {
const contentTypeHeader = headers.find(
header => header.name.toLowerCase() === 'content-type',
)
const mimeType = contentTypeHeader
let mimeType = contentTypeHeader
? contentTypeHeader.value.split(';')[0]
: null

Expand All @@ -195,7 +196,7 @@ const importCommand = (parseEntries: ParseEntry[]): ImportRequest => {
})

/// /////// Body //////////
const body: PostData = mimeType ? { mimeType } : {}
let body: PostData = mimeType ? { mimeType } : {}
const bodyAsGET = getPairValue(pairsByName, false, ['G', 'get'])

if (dataParameters.length !== 0 && bodyAsGET) {
Expand All @@ -209,8 +210,20 @@ const importCommand = (parseEntries: ParseEntry[]): ImportRequest => {
}
})
} else if (dataParameters.length !== 0) {
body.text = dataParameters.map(parameter => `${parameter.name}${parameter.value}`).join('&')
body.mimeType = mimeType || ''
// check if it is the graphql
if(dataParameters[0].value && dataParameters[0].value.includes(`"query":`)) {
// Assuming GraphQL query is passed via --data or -d
const bodyData = dataParameters[0].value

mimeType = constants.MIME_TYPE.GRAPHQL
body = {
mimeType,
text: bodyData,
}
} else {
body.text = dataParameters.map (parameter => `${parameter.name}${parameter.value}`).join ('&')
body.mimeType = mimeType || ''
}
} else if (formDataParams.length) {
body.params = formDataParams
body.mimeType = mimeType || 'multipart/form-data'
Expand All @@ -227,6 +240,7 @@ const importCommand = (parseEntries: ParseEntry[]): ImportRequest => {
}

const count = requestCount++

return {
_id: `__REQ_${count}__`,
_type: 'request',
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/parsers/curl.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export interface PostData {
params?: Parameter[];
mimeType?: string;
text?: string;
query?: string;
variables?: any;
}

export interface QueryString extends Comment {
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ body {
color: var(--method-post) !important;
}

.request-method--GQL {
color: var(--method-post) !important;
}

.request-method--PUT {
color: var(--method-put) !important;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/tests/App_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Scenario('Add GraphQL requests', async() => {
for(let i = 1; i <= 5; i++) {
const requestName = `GraphQL Request ${i}`
I.createGraphQLRequest(requestName)
await I.isActiveSidebarItem(`POST${requestName}`)
await I.isActiveSidebarItem(`GQL${requestName}`)
await I.isActiveTab(`POST ${requestName}`)
}
})
Expand Down

0 comments on commit 2f3ee23

Please sign in to comment.