Skip to content

Commit

Permalink
🎉 feat: strict retrieveRootParamters
Browse files Browse the repository at this point in the history
  • Loading branch information
SaltyAom committed Jul 17, 2024
1 parent e12c04e commit 3b3fbcd
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 86 deletions.
48 changes: 32 additions & 16 deletions example/a.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
import { Elysia, t } from '../src'
import { retrieveRootParamters, sucrose } from '../src/sucrose'

new Elysia()
.get(
'/',
({ error }) => {
const hello = false
// const parameter = '({ hello: { a }, path })'
// const result = retrieveRootParamters(parameter)

if (!hello) {
return error(400)
}
// console.log(result)

return { example: 'Hello' }
console.log(
sucrose({
handler: function ({ query }) {
query.a
},
{
response: {
200: t.Object({ example: t.String() })
}
}
)
.listen(8080)
afterHandle: [],
beforeHandle: [],
error: [
function a({
query,
query: { a, c: d },
headers: { hello },
...rest
}) {
query.b
rest.query.e
},
({ query: { f } }) => {}
],
mapResponse: [],
onResponse: [],
parse: [],
request: [],
start: [],
stop: [],
trace: [],
transform: []
})
)
98 changes: 62 additions & 36 deletions src/sucrose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,30 @@ export const bracketPairRangeReverse = (
return [start, end + 1]
}

const removeColonAlias = (parameter: string) => {
while (true) {
const start = parameter.indexOf(':')
if (start === -1) break

let end = parameter.indexOf(',', start)
if (end === -1) end = parameter.indexOf('}', start) - 1
if (end === 0) end = parameter.length

parameter = parameter.slice(0, start) + parameter.slice(end)
}

return parameter
}

/**
* Retrieve only root paramters of a function
*
* @example
* ```typescript
* retrieveRootParameters('({ hello: { world: { a } }, elysia })') // => 'hello elysia'
* retrieveRootParameters('({ hello: { world: { a } }, elysia })') // => {
* parameters: ['hello', 'elysia'],
* hasParenthesis: true
* }
* ```
*/
export const retrieveRootParamters = (parameter: string) => {
Expand All @@ -197,23 +215,32 @@ export const retrieveRootParamters = (parameter: string) => {
// Remove {} from parameter
if (parameter.charCodeAt(0) === 123) {
hasParenthesis = true
// ! Do not trim space because there could be a case of non space ({query})
parameter = parameter.slice(1, -1)
}

parameter = parameter.trim()
parameter = parameter.replace(/( |\t|\n)/g, '').trim()
let parameters = <string[]>[]

// Object destructuring
while (true) {
const [start, end] = bracketPairRange(parameter)
// eslint-disable-next-line prefer-const
let [start, end] = bracketPairRange(parameter)
if (start === -1) break

parameter = parameter.slice(0, start - 2) + parameter.slice(end + 1)
// Remove colon from object structuring cast
parameters.push(parameter.slice(0, start - 1))
if (parameter.charCodeAt(end) === 44) end++
parameter = parameter.slice(end)
}

const result = parameter.replace(/:/g, '').trim()
parameter = removeColonAlias(parameter)

if (hasParenthesis) return '{ ' + result + ' }'
return result
if (parameter) parameters = parameters.concat(parameter.split(','))

return {
hasParenthesis,
parameters
}
}

/**
Expand All @@ -225,22 +252,22 @@ export const findParameterReference = (
parameter: string,
inference: Sucrose.Inference
) => {
const root = retrieveRootParamters(parameter)
const { parameters, hasParenthesis } = retrieveRootParamters(parameter)

// Check if root is an object destructuring
if (root.charCodeAt(0) === 123) {
if (!inference.query && root.includes('query')) inference.query = true
if (!inference.headers && root.includes('headers'))
inference.headers = true
if (!inference.body && root.includes('body')) inference.body = true
if (!inference.cookie && root.includes('cookie'))
inference.cookie = true
if (!inference.set && root.includes('set')) inference.set = true
if (!inference.server && root.includes('server'))
inference.server = true
}

return root
if (!inference.query && parameters.includes('query')) inference.query = true
if (!inference.headers && parameters.includes('headers'))
inference.headers = true
if (!inference.body && parameters.includes('body')) inference.body = true
if (!inference.cookie && parameters.includes('cookie'))
inference.cookie = true
if (!inference.set && parameters.includes('set')) inference.set = true
if (!inference.server && parameters.includes('server'))
inference.server = true

if (hasParenthesis) return `{ ${parameters.join(', ')} }`

return parameters.join(', ')
}

const findEndIndex = (
Expand Down Expand Up @@ -328,7 +355,7 @@ export const findAlias = (type: string, body: string, depth = 0) => {
if (variable === '}') {
const [start, end] = bracketPairRangeReverse(part)

aliases.push(content.slice(start, end))
aliases.push(removeColonAlias(content.slice(start, end)))

content = content.slice(index + 3 + type.length)

Expand Down Expand Up @@ -398,27 +425,29 @@ export const inferBodyReference = (
code.includes(alias + '["' + type + '"]') ||
code.includes(alias + "['" + type + "']")

for (let alias of aliases) {
for (const alias of aliases) {
if (!alias) continue

// Scan object destructured property
if (alias.charCodeAt(0) === 123) {
alias = retrieveRootParamters(alias)
const parameters = retrieveRootParamters(alias).parameters

if (!inference.query && alias.includes('query'))
if (!inference.query && parameters.includes('query'))
inference.query = true

if (!inference.headers && alias.includes('headers'))
if (!inference.headers && parameters.includes('headers'))
inference.headers = true

if (!inference.body && alias.includes('body')) inference.body = true
if (!inference.body && parameters.includes('body'))
inference.body = true

if (!inference.cookie && alias.includes('cookie'))
if (!inference.cookie && parameters.includes('cookie'))
inference.cookie = true

if (!inference.set && alias.includes('set')) inference.set = true
if (!inference.set && parameters.includes('set'))
inference.set = true

if (!inference.query && alias.includes('server'))
if (!inference.query && parameters.includes('server'))
inference.server = true

continue
Expand Down Expand Up @@ -569,11 +598,8 @@ export const sucrose = (
const aliases = findAlias(mainParameter, body)
aliases.splice(0, -1, mainParameter)

for (const alias of aliases)
if (isContextPassToFunction(mainParameter, body, inference))
break

inferBodyReference(body, aliases, inference)
if (!isContextPassToFunction(mainParameter, body, inference))
inferBodyReference(body, aliases, inference)

if (
!inference.query &&
Expand Down
83 changes: 50 additions & 33 deletions test/sucrose/retrieve-root-parameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,66 +5,83 @@ describe('retrieve root parameter', () => {
it('return an empty string when given an empty string', () => {
const parameter = ''
const result = retrieveRootParamters(parameter)
expect(result).toEqual('')
expect(result).toEqual({
parameters: [],
hasParenthesis: false
})
})

it('return the same string when there are no brackets in the string', () => {
const parameter = 'hello world'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('hello world')
})
// Doesn't make sense as JavaScript will panic
// it('return the same string when there are no brackets in the string', () => {
// const parameter = 'hello world'
// const result = retrieveRootParamters(parameter)
// expect(result).toEqual({
// parameters: ['hello world'],
// hasParenthesis: false
// })
// })

it('remove brackets and their contents when they are at the root level', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
expect(result).toEqual({
parameters: ['hello', 'elysia'],
hasParenthesis: true
})
})

it('return an empty string when given only brackets', () => {
const parameter = '()'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('')
expect(result).toEqual({
parameters: [],
hasParenthesis: false
})
})

it('return an empty string when given only one bracket', () => {
const parameter = '('
const result = retrieveRootParamters(parameter)
expect(result).toEqual('')
expect(result).toEqual({
parameters: [],
hasParenthesis: false
})
})

it('return even if bracket is unbalanced', () => {
const parameter = '({ hello: { world: { a } })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello }')
})
// Doesn't make sense as JavaScript will panic
// it('return even if bracket is unbalanced', () => {
// const parameter = '({ hello: { world: { a } })'
// const result = retrieveRootParamters(parameter)
// expect(result).toEqual({
// parameters: ['hello'],
// hasParenthesis: true
// })
// })

it('return the root parameters when given a string with spaces between brackets', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
})

it('return the root parameters when given a string with spaces between brackets and curly braces', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
expect(result).toEqual({
parameters: ['hello', 'elysia'],
hasParenthesis: true
})
})

it('return the root parameters when given a string with spaces between brackets and parentheses', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
it('return parameter on minified bracket', () => {
const parameter = '({ hello, path })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
expect(result).toEqual({
parameters: ['hello', 'path'],
hasParenthesis: true
})
})

it('return the root parameters when given a string with spaces between brackets, curly braces, and parentheses', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
})

it('return the root parameters when given a string with spaces between brackets, curly braces, parentheses, and other characters', () => {
const parameter = '({ hello: { world: { a } }, elysia })'
it('handle tab and new line', () => {
const parameter = '({ hello: { world: { a } }, \nelysia, \teden })'
const result = retrieveRootParamters(parameter)
expect(result).toEqual('{ hello elysia }')
expect(result).toEqual({
parameters: ['hello', 'elysia', 'eden'],
hasParenthesis: true
})
})
})
14 changes: 13 additions & 1 deletion test/sucrose/separate-function.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe('Sucrose: separateFunction', () => {
])
})

it('separate minify arrow param', () => {
it('separate minifed arrow param', () => {
const arrowParam = `({ sucrose, amber })=>{return "sucrose"}`

expect(separateFunction(arrowParam.toString())).toEqual([
Expand All @@ -94,4 +94,16 @@ describe('Sucrose: separateFunction', () => {
}
])
})

it('separate minified arrow without whitespace in the beginning', () => {
const arrowParam = `({sucrose, amber })=>{return "sucrose"}`

expect(separateFunction(arrowParam.toString())).toEqual([
'{sucrose, amber }',
'{return "sucrose"}',
{
isArrowReturn: false
}
])
})
})

0 comments on commit 3b3fbcd

Please sign in to comment.