Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decoratorMetadata flag if enabled by tsconfig #32914

Merged
merged 12 commits into from Feb 6, 2022
1 change: 1 addition & 0 deletions .eslintignore
Expand Up @@ -26,6 +26,7 @@ packages/next-env/**/*.d.ts
packages/create-next-app/templates/**
test/integration/eslint/**
test/development/basic/legacy-decorators/**/*
test/production/emit-decorator-metadata/**/*.js
test-timings.json
packages/next-swc/crates/**
bench/nested-deps/pages/**
Expand Down
4 changes: 4 additions & 0 deletions packages/next/build/swc/options.js
Expand Up @@ -21,6 +21,9 @@ export function getBaseSWCOptions({
const enableDecorators = Boolean(
jsConfig?.compilerOptions?.experimentalDecorators
)
const emitDecoratorMetadata = Boolean(
jsConfig?.compilerOptions?.emitDecoratorMetadata
)
return {
jsc: {
...(resolvedBaseUrl && paths
Expand All @@ -47,6 +50,7 @@ export function getBaseSWCOptions({
}
: {}),
legacyDecorator: enableDecorators,
decoratorMetadata: emitDecoratorMetadata,
react: {
importSource: jsConfig?.compilerOptions?.jsxImportSource || 'react',
runtime: 'automatic',
Expand Down
6 changes: 6 additions & 0 deletions test/production/emit-decorator-metadata/app/jsconfig.json
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
@@ -0,0 +1,14 @@
import { createHandler, Get, Param } from '@storyofams/next-api-decorators'

class HelloHandler {
@Get('/:myParam')
// This fails due to library looking for Reflect.getMetadata("design:paramtypes", ...).
// Design:paramtypes is never emitted due to missing SWC flag.
async get(@Param('myParam') myParam) {
return {
myParam,
}
}
}

export default createHandler(HelloHandler)
26 changes: 26 additions & 0 deletions test/production/emit-decorator-metadata/app/pages/index.js
@@ -0,0 +1,26 @@
import React from 'react'
import 'reflect-metadata'
import { container, singleton } from 'tsyringe'

@singleton()
class HelloService {
getHello() {
return 'Hello, world!'
}
}

const helloService = container.resolve(HelloService)

export default function Home() {
const message = helloService.getHello()

return <p id="message">{message}</p>
}

export function getServerSideProps() {
return {
props: {
now: Date.now(),
},
}
}
47 changes: 47 additions & 0 deletions test/production/emit-decorator-metadata/index.test.ts
@@ -0,0 +1,47 @@
import { join } from 'path'
import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { BrowserInterface } from 'test/lib/browsers/base'
import { fetchViaHTTP } from 'next-test-utils'

describe('emitDecoratorMetadata SWC option', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
'jsconfig.json': new FileRef(join(__dirname, 'app/jsconfig.json')),
pages: new FileRef(join(__dirname, 'app/pages')),
},
dependencies: {
'@storyofams/next-api-decorators': '1.6.0',
'reflect-metadata': '0.1.13',
'path-to-regexp': '6.2.0',
tsyringe: '4.6.0',
},
})
})

afterAll(() => next.destroy())

it('should compile with emitDecoratorMetadata enabled', async () => {
let browser: BrowserInterface
try {
browser = await webdriver(next.appPort, '/')
const message = await browser.elementByCss('#message').text()

expect(message).toBe('Hello, world!')
} finally {
if (browser) {
await browser.close()
}
}
})

it('should compile with emitDecoratorMetadata enabled for API', async () => {
const res = await fetchViaHTTP(next.url, '/api/something')
expect(res.status).toBe(200)
expect(await res.json()).toEqual({ myParam: 'something' })
})
})