Skip to content

Commit

Permalink
Add decoratorMetadata flag if enabled by tsconfig (#32914)
Browse files Browse the repository at this point in the history
fixes #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 <22380829+ijjk@users.noreply.github.com>
  • Loading branch information
sannajammeh and ijjk committed Feb 6, 2022
1 parent 8039c6b commit e0c7794
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
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' })
})
})

0 comments on commit e0c7794

Please sign in to comment.