Skip to content

Commit e0c7794

Browse files
sannajammehijjk
andauthored
Add decoratorMetadata flag if enabled by tsconfig (vercel#32914)
fixes vercel#32913 Adds support for decorator metadata in SWC when enabled through ts/jsconfig. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `yarn lint` Co-authored-by: JJ Kasper <[email protected]>
1 parent 8039c6b commit e0c7794

File tree

6 files changed

+98
-0
lines changed

6 files changed

+98
-0
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ packages/next-env/**/*.d.ts
2626
packages/create-next-app/templates/**
2727
test/integration/eslint/**
2828
test/development/basic/legacy-decorators/**/*
29+
test/production/emit-decorator-metadata/**/*.js
2930
test-timings.json
3031
packages/next-swc/crates/**
3132
bench/nested-deps/pages/**

packages/next/build/swc/options.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export function getBaseSWCOptions({
2121
const enableDecorators = Boolean(
2222
jsConfig?.compilerOptions?.experimentalDecorators
2323
)
24+
const emitDecoratorMetadata = Boolean(
25+
jsConfig?.compilerOptions?.emitDecoratorMetadata
26+
)
2427
return {
2528
jsc: {
2629
...(resolvedBaseUrl && paths
@@ -47,6 +50,7 @@ export function getBaseSWCOptions({
4750
}
4851
: {}),
4952
legacyDecorator: enableDecorators,
53+
decoratorMetadata: emitDecoratorMetadata,
5054
react: {
5155
importSource: jsConfig?.compilerOptions?.jsxImportSource || 'react',
5256
runtime: 'automatic',
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"compilerOptions": {
3+
"experimentalDecorators": true,
4+
"emitDecoratorMetadata": true
5+
}
6+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { createHandler, Get, Param } from '@storyofams/next-api-decorators'
2+
3+
class HelloHandler {
4+
@Get('/:myParam')
5+
// This fails due to library looking for Reflect.getMetadata("design:paramtypes", ...).
6+
// Design:paramtypes is never emitted due to missing SWC flag.
7+
async get(@Param('myParam') myParam) {
8+
return {
9+
myParam,
10+
}
11+
}
12+
}
13+
14+
export default createHandler(HelloHandler)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react'
2+
import 'reflect-metadata'
3+
import { container, singleton } from 'tsyringe'
4+
5+
@singleton()
6+
class HelloService {
7+
getHello() {
8+
return 'Hello, world!'
9+
}
10+
}
11+
12+
const helloService = container.resolve(HelloService)
13+
14+
export default function Home() {
15+
const message = helloService.getHello()
16+
17+
return <p id="message">{message}</p>
18+
}
19+
20+
export function getServerSideProps() {
21+
return {
22+
props: {
23+
now: Date.now(),
24+
},
25+
}
26+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { join } from 'path'
2+
import webdriver from 'next-webdriver'
3+
import { createNext, FileRef } from 'e2e-utils'
4+
import { NextInstance } from 'test/lib/next-modes/base'
5+
import { BrowserInterface } from 'test/lib/browsers/base'
6+
import { fetchViaHTTP } from 'next-test-utils'
7+
8+
describe('emitDecoratorMetadata SWC option', () => {
9+
let next: NextInstance
10+
11+
beforeAll(async () => {
12+
next = await createNext({
13+
files: {
14+
'jsconfig.json': new FileRef(join(__dirname, 'app/jsconfig.json')),
15+
pages: new FileRef(join(__dirname, 'app/pages')),
16+
},
17+
dependencies: {
18+
'@storyofams/next-api-decorators': '1.6.0',
19+
'reflect-metadata': '0.1.13',
20+
'path-to-regexp': '6.2.0',
21+
tsyringe: '4.6.0',
22+
},
23+
})
24+
})
25+
26+
afterAll(() => next.destroy())
27+
28+
it('should compile with emitDecoratorMetadata enabled', async () => {
29+
let browser: BrowserInterface
30+
try {
31+
browser = await webdriver(next.appPort, '/')
32+
const message = await browser.elementByCss('#message').text()
33+
34+
expect(message).toBe('Hello, world!')
35+
} finally {
36+
if (browser) {
37+
await browser.close()
38+
}
39+
}
40+
})
41+
42+
it('should compile with emitDecoratorMetadata enabled for API', async () => {
43+
const res = await fetchViaHTTP(next.url, '/api/something')
44+
expect(res.status).toBe(200)
45+
expect(await res.json()).toEqual({ myParam: 'something' })
46+
})
47+
})

0 commit comments

Comments
 (0)