Skip to content

Commit 25f3e2f

Browse files
committed
feat: add static analysis helper
1 parent 689b2ac commit 25f3e2f

File tree

10 files changed

+118
-0
lines changed

10 files changed

+118
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
background: true,
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
schedule: '@hourly',
9+
}

plugin/src/helpers/analysis.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import fs from 'fs'
2+
import { relative } from 'path'
3+
4+
import { extractExportedConstValue, UnsupportedValueError } from 'next/dist/build/analysis/extract-const-value'
5+
import { parseModule } from 'next/dist/build/analysis/parse-module'
6+
7+
export const extractConfigFromFile = async (apiFilePath: string): Promise<Record<string, unknown>> => {
8+
const fileContent = await fs.promises.readFile(apiFilePath, 'utf8')
9+
if (!fileContent.includes('config')) {
10+
return {}
11+
}
12+
const ast = await parseModule(apiFilePath, fileContent)
13+
try {
14+
return extractExportedConstValue(ast, 'config')
15+
} catch (error) {
16+
if (error instanceof UnsupportedValueError) {
17+
console.warn(`Unsupported config value in ${relative(process.cwd(), apiFilePath)}`)
18+
}
19+
return {}
20+
}
21+
}

test/analysis.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { extractConfigFromFile } from '../plugin/src/helpers/analysis'
2+
import { resolve } from 'path'
3+
describe('static source analysis', () => {
4+
it('should extract config values from a source file', async () => {
5+
const config = await extractConfigFromFile(resolve(__dirname, './fixtures/analysis/background.js'))
6+
expect(config).toEqual({
7+
background: true,
8+
})
9+
})
10+
it('should extract config values from a TypeScript source file', async () => {
11+
const config = await extractConfigFromFile(resolve(__dirname, './fixtures/analysis/background.ts'))
12+
expect(config).toEqual({
13+
background: true,
14+
})
15+
})
16+
it('should return an empty config if not defined', async () => {
17+
const config = await extractConfigFromFile(resolve(__dirname, './fixtures/analysis/missing.ts'))
18+
expect(config).toEqual({})
19+
})
20+
21+
it('should return an empty config if config is invalid', async () => {
22+
const config = await extractConfigFromFile(resolve(__dirname, './fixtures/analysis/invalid.ts'))
23+
expect(config).toEqual({})
24+
})
25+
26+
it('should extract schedule values from a source file', async () => {
27+
const config = await extractConfigFromFile(resolve(__dirname, './fixtures/analysis/scheduled.ts'))
28+
expect(config).toEqual({
29+
schedule: '@daily',
30+
})
31+
})
32+
})

test/fixtures/analysis/background.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
background: true,
9+
}

test/fixtures/analysis/background.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
background: true,
9+
}

test/fixtures/analysis/invalid.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
background() {
9+
return true
10+
},
11+
}

test/fixtures/analysis/scheduled.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
schedule: '@hourly',
9+
}

test/fixtures/analysis/scheduled.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default (req, res) => {
2+
res.setHeader('Content-Type', 'application/json')
3+
res.status(200)
4+
res.json({ message: 'hello world :)' })
5+
}
6+
7+
export const config = {
8+
schedule: '@daily',
9+
}

0 commit comments

Comments
 (0)