Skip to content

Commit

Permalink
fix(ui): tag replacement bug (resolves #311)
Browse files Browse the repository at this point in the history
  • Loading branch information
flawiddsouza committed Feb 17, 2025
1 parent e25cf54 commit d38a4ae
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 41 deletions.
5 changes: 3 additions & 2 deletions packages/ui/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
import { ActionContext } from 'vuex'
import { version } from '../../electron/package.json'
import constants from '@/constants'
import { handleTags } from '@/utils/tag'
import { handleResponseTag } from '@/utils/tag'
import { handleTags } from '@/parsers/tag'

// From: https://stackoverflow.com/a/67802481/4932305
export function toTree(array: CollectionItem[]): CollectionItem[] {
Expand Down Expand Up @@ -101,7 +102,7 @@ export async function substituteEnvironmentVariables(
substitutedString = substitutedString.replaceAll(`{{ ${objectPath} }}`, objectPathValue)
})

substitutedString = await handleTags(substitutedString, tagTrigger, cacheId, noError)
substitutedString = await handleTags(handleResponseTag, substitutedString, tagTrigger, cacheId, noError)

return substitutedString
}
Expand Down
26 changes: 25 additions & 1 deletion packages/ui/src/parsers/tag.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test, expect } from 'vitest'
import { tagRegex, parseFunction, toFunctionString } from './tag'
import { tagRegex, parseFunction, toFunctionString, handleTags, ParsedResult } from './tag'

const sumInput = 'sum(a=1, b=2)'
const sumParsedResult = {
Expand Down Expand Up @@ -67,3 +67,27 @@ test('tagRegex', async() => {

expect(flattenedMatches).toEqual(expectedMatches)
})

test('handleTags: #311', async() => {
const input = `{
"a": "{% response(attribute='body', behavior='never', maxAge=60, request='JB-6w6Kp0YXPBU72__o2W', path='b64::YXJncy5h') %}",
"b": "{% response(attribute='body', behavior='never', maxAge=60, request='JB-6w6Kp0YXPBU72__o2W', path='b64::YXJncy5i') %}"
}`

const expectedOutput = `{
"a": "10",
"b": "20"
}`

const handleResponseTag = async(parsedResult: ParsedResult) => {
if (parsedResult.parameters.path === 'args.a') {
return '10'
}

if (parsedResult.parameters.path === 'args.b') {
return '20'
}
}

expect(await handleTags(handleResponseTag, input, false, undefined, true)).toEqual(expectedOutput)
})
39 changes: 39 additions & 0 deletions packages/ui/src/parsers/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,42 @@ export function toFunctionString(parsedResult: ParsedResult): string {
const paramsString = paramsArray.join(', ')
return `${functionName}(${paramsString})`
}

export async function handleTags(handleResponseTag: (...args: any) => Promise<string | undefined>, string: string, tagTrigger: boolean, cacheId: string | undefined, noError: boolean) {
const regex = tagRegex
let matches = [...string.matchAll(regex)]
// Reverse matches to avoid shifting indexes when replacing text - cause of issue #311
matches = matches.reverse()

for(const match of matches) {
const fullMatch = match[0]
const start = match.index!
const end = start + fullMatch.length

// console.log(`Match: ${fullMatch}, Start: ${start}, End: ${end}`)

const parsedTag = parseFunction(match[1], true)

let replacement = undefined

if (parsedTag.functionName === 'response') {
replacement = await handleResponseTag(parsedTag, tagTrigger, cacheId)
}

if (replacement === undefined) {
if (noError) {
replacement = '<no value found>'
} else {
const at = `${string.slice(0, start)}━>${parsedTag.functionName}(...)<━${string.slice(end)}`

throw new Error(`Could not resolve tag\n\n${toFunctionString(parsedTag)}\n\nat ${at}`, {
cause: 'display-error'
})
}
}

string = string.slice(0, start) + replacement + string.slice(end)
}

return string
}
39 changes: 1 addition & 38 deletions packages/ui/src/utils/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async function getResponseForRequest(
return latestResponse
}

async function handleResponseTag(parsedTag: tagParser.ParsedResult, tagTrigger: boolean, cacheId: string | undefined) {
export async function handleResponseTag(parsedTag: tagParser.ParsedResult, tagTrigger: boolean, cacheId: string | undefined) {
let returnValue = undefined

const cacheKey = cacheId + JSON.stringify(parsedTag)
Expand Down Expand Up @@ -124,40 +124,3 @@ async function handleResponseTag(parsedTag: tagParser.ParsedResult, tagTrigger:

return returnValue
}

export async function handleTags(string: string, tagTrigger: boolean, cacheId: string | undefined, noError: boolean) {
const regex = tagParser.tagRegex
const matches = [...string.matchAll(regex)]

for(const match of matches) {
const fullMatch = match[0]
const start = match.index!
const end = start + fullMatch.length

// console.log(`Match: ${fullMatch}, Start: ${start}, End: ${end}`)

const parsedTag = tagParser.parseFunction(match[1], true)

let replacement = undefined

if (parsedTag.functionName === 'response') {
replacement = await handleResponseTag(parsedTag, tagTrigger, cacheId)
}

if (replacement === undefined) {
if (noError) {
replacement = '<no value found>'
} else {
const at = `${string.slice(0, start)}━>${parsedTag.functionName}(...)<━${string.slice(end)}`

throw new Error(`Could not resolve tag\n\n${tagParser.toFunctionString(parsedTag)}\n\nat ${at}`, {
cause: 'display-error'
})
}
}

string = string.slice(0, start) + replacement + string.slice(end)
}

return string
}

0 comments on commit d38a4ae

Please sign in to comment.