diff --git a/example/a.ts b/example/a.ts index 1ccdfedd..1aee4c87 100644 --- a/example/a.ts +++ b/example/a.ts @@ -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: [] + }) +) diff --git a/src/sucrose.ts b/src/sucrose.ts index 652c2b43..1886285d 100644 --- a/src/sucrose.ts +++ b/src/sucrose.ts @@ -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) => { @@ -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 = [] + // 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 + } } /** @@ -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 = ( @@ -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) @@ -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 @@ -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 && diff --git a/test/sucrose/retrieve-root-parameters.test.ts b/test/sucrose/retrieve-root-parameters.test.ts index ea1d63ac..b51ded7c 100644 --- a/test/sucrose/retrieve-root-parameters.test.ts +++ b/test/sucrose/retrieve-root-parameters.test.ts @@ -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 + }) }) }) diff --git a/test/sucrose/separate-function.test.ts b/test/sucrose/separate-function.test.ts index b462004c..96686b8b 100644 --- a/test/sucrose/separate-function.test.ts +++ b/test/sucrose/separate-function.test.ts @@ -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([ @@ -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 + } + ]) + }) })