Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
feat: parse method ISC field (#1539)
Browse files Browse the repository at this point in the history
* feat: parse `methods` ISC field

* fix: normalize methods

* refactor: name one differently, ambiguity is too much to handle for eslint

* fix: throw FunctionBundlingUserError
  • Loading branch information
Skn0tt committed Aug 24, 2023
1 parent 5f1e22c commit 836b6d5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/runtimes/node/in_source_config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Logger } from '../../../utils/logger.js'
import { nonNullable } from '../../../utils/non_nullable.js'
import { getRoutesFromPath, Route } from '../../../utils/routes.js'
import { RUNTIME } from '../../runtime.js'
import { NODE_BUNDLER } from '../bundlers/types.js'
import { createBindingsMethod } from '../parser/bindings.js'
import { getExports } from '../parser/exports.js'
import { getImports } from '../parser/imports.js'
Expand All @@ -21,6 +22,7 @@ export type ISCValues = {
routes?: Route[]
runtimeAPIVersion?: number
schedule?: string
methods?: string[]
}

interface FindISCDeclarationsOptions {
Expand Down Expand Up @@ -61,6 +63,29 @@ export const findISCDeclarationsInPath = async (
return findISCDeclarations(source, { functionName, featureFlags, logger })
}

/**
* Normalizes method names into arrays of uppercase strings.
* (e.g. "get" becomes ["GET"])
*/
const normalizeMethods = (input: unknown, name: string): string[] | undefined => {
const methods = Array.isArray(input) ? input : [input]

return methods.map((method) => {
if (typeof method !== 'string') {
throw new FunctionBundlingUserError(
`Could not parse method declaration of function '${name}'. Expecting HTTP Method, got ${method}`,
{
functionName: name,
runtime: RUNTIME.JAVASCRIPT,
bundler: NODE_BUNDLER.ESBUILD,
},
)
}

return method.toUpperCase()
})
}

export const findISCDeclarations = (
source: string,
{ functionName, featureFlags, logger }: FindISCDeclarationsOptions,
Expand Down Expand Up @@ -93,6 +118,10 @@ export const findISCDeclarations = (
config.schedule = configExport.schedule
}

if (configExport.method !== undefined) {
config.methods = normalizeMethods(configExport.method, functionName)
}

return config
}

Expand Down
10 changes: 10 additions & 0 deletions src/runtimes/node/parser/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const parseConfigExport = (node: Statement) => {
// - number
// - object
// - string
// - array of strings
const parseObject = (node: ObjectExpression) =>
node.properties.reduce((acc, property): Record<string, unknown> => {
if (property.type !== 'ObjectProperty' || property.key.type !== 'Identifier') {
Expand All @@ -156,6 +157,15 @@ const parseObject = (node: ObjectExpression) =>
}
}

if (property.value.type === 'ArrayExpression') {
return {
...acc,
[property.key.name]: property.value.elements.flatMap((element) =>
element?.type === 'StringLiteral' ? [element.value] : [],
),
}
}

if (property.value.type === 'ObjectExpression') {
return {
...acc,
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/runtimes/node/in_source_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,36 @@ describe('V2 API', () => {
})
})

describe('`method` property', () => {
test('Using an array', () => {
const source = `export default async () => {
return new Response("Hello!")
}
export const config = {
method: ["GET", "POST"]
}`

const { methods } = findISCDeclarations(source, options)

expect(methods).toEqual(['GET', 'POST'])
})

test('Using single method', () => {
const source = `export default async () => {
return new Response("Hello!")
}
export const config = {
method: "GET"
}`

const { methods } = findISCDeclarations(source, options)

expect(methods).toEqual(['GET'])
})
})

describe('`path` property', () => {
test('Missing a leading slash', () => {
expect.assertions(4)
Expand Down

1 comment on commit 836b6d5

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱ Benchmark results

  • largeDepsEsbuild: 2.8s
  • largeDepsNft: 8.9s
  • largeDepsZisi: 17.2s

Please sign in to comment.