Completed

This commit is contained in:
aet 2021-07-21 23:37:51 -04:00
parent 2c504997af
commit 4c8f3424ce
23 changed files with 602 additions and 34 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
node_modules node_modules
mochawesome-report mochawesome-report
snapshots.d.ts
lib

View File

@ -2,6 +2,6 @@
"$schema": "https://json.schemastore.org/mocharc", "$schema": "https://json.schemastore.org/mocharc",
"reporter": "mochawesome", "reporter": "mochawesome",
"extension": [".ts"], "extension": [".ts"],
"require": ["ts-node/register"], "require": ["./scripts/babel-register.js"],
"timeout": 10000 "timeout": 10000
} }

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# babel-decorators
Emit beautiful looking transpiled code for decorators like `tsc`.

View File

@ -1,13 +1,17 @@
{ {
"name": "babel-decorators", "name": "babel-decorators",
"version": "1.0.0", "version": "0.1.0",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "mocha test/**/*.ts" "test": "mocha test/**/*.ts",
"postinstall": "mkdir -p lib; cd test/snapshots && ls | sed \"s/.*/'&'/\" | paste -sd '|' | sed -e \"s/^/export type Snapshot = /\" - > ../snapshots.d.ts"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.8", "@babel/core": "^7.14.8",
"@babel/plugin-transform-modules-commonjs": "^7.14.5",
"@babel/preset-typescript": "^7.14.5",
"@babel/register": "^7.14.5",
"@babel/types": "^7.14.8", "@babel/types": "^7.14.8",
"@types/babel__core": "^7.1.15", "@types/babel__core": "^7.1.15",
"@types/chai": "^4.2.21", "@types/chai": "^4.2.21",
@ -20,5 +24,13 @@
"prettier": "^2.3.2", "prettier": "^2.3.2",
"ts-node": "^10.1.0", "ts-node": "^10.1.0",
"typescript": "^4.3.5" "typescript": "^4.3.5"
},
"prettier": {
"arrowParens": "avoid",
"tabWidth": 2,
"printWidth": 90,
"semi": false,
"singleQuote": false,
"trailingComma": "es5"
} }
} }

244
pnpm-lock.yaml generated
View File

@ -2,6 +2,9 @@ lockfileVersion: 5.3
specifiers: specifiers:
'@babel/core': ^7.14.8 '@babel/core': ^7.14.8
'@babel/plugin-transform-modules-commonjs': ^7.14.5
'@babel/preset-typescript': ^7.14.5
'@babel/register': ^7.14.5
'@babel/types': ^7.14.8 '@babel/types': ^7.14.8
'@types/babel__core': ^7.1.15 '@types/babel__core': ^7.1.15
'@types/chai': ^4.2.21 '@types/chai': ^4.2.21
@ -17,6 +20,9 @@ specifiers:
devDependencies: devDependencies:
'@babel/core': 7.14.8 '@babel/core': 7.14.8
'@babel/plugin-transform-modules-commonjs': 7.14.5_@babel+core@7.14.8
'@babel/preset-typescript': 7.14.5_@babel+core@7.14.8
'@babel/register': 7.14.5_@babel+core@7.14.8
'@babel/types': 7.14.8 '@babel/types': 7.14.8
'@types/babel__core': 7.1.15 '@types/babel__core': 7.1.15
'@types/chai': 4.2.21 '@types/chai': 4.2.21
@ -76,6 +82,13 @@ packages:
source-map: 0.5.7 source-map: 0.5.7
dev: true dev: true
/@babel/helper-annotate-as-pure/7.14.5:
resolution: {integrity: sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.14.8
dev: true
/@babel/helper-compilation-targets/7.14.5_@babel+core@7.14.8: /@babel/helper-compilation-targets/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==} resolution: {integrity: sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -89,6 +102,23 @@ packages:
semver: 6.3.0 semver: 6.3.0
dev: true dev: true
/@babel/helper-create-class-features-plugin/7.14.8_@babel+core@7.14.8:
resolution: {integrity: sha512-bpYvH8zJBWzeqi1o+co8qOrw+EXzQ/0c74gVmY205AWXy9nifHrOg77y+1zwxX5lXE7Icq4sPlSQ4O2kWBrteQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-annotate-as-pure': 7.14.5
'@babel/helper-function-name': 7.14.5
'@babel/helper-member-expression-to-functions': 7.14.7
'@babel/helper-optimise-call-expression': 7.14.5
'@babel/helper-replace-supers': 7.14.5
'@babel/helper-split-export-declaration': 7.14.5
transitivePeerDependencies:
- supports-color
dev: true
/@babel/helper-function-name/7.14.5: /@babel/helper-function-name/7.14.5:
resolution: {integrity: sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==} resolution: {integrity: sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -149,6 +179,11 @@ packages:
'@babel/types': 7.14.8 '@babel/types': 7.14.8
dev: true dev: true
/@babel/helper-plugin-utils/7.14.5:
resolution: {integrity: sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-replace-supers/7.14.5: /@babel/helper-replace-supers/7.14.5:
resolution: {integrity: sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==} resolution: {integrity: sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -211,6 +246,73 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/@babel/plugin-syntax-typescript/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-plugin-utils': 7.14.5
dev: true
/@babel/plugin-transform-modules-commonjs/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-module-transforms': 7.14.8
'@babel/helper-plugin-utils': 7.14.5
'@babel/helper-simple-access': 7.14.8
babel-plugin-dynamic-import-node: 2.3.3
transitivePeerDependencies:
- supports-color
dev: true
/@babel/plugin-transform-typescript/7.14.6_@babel+core@7.14.8:
resolution: {integrity: sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-create-class-features-plugin': 7.14.8_@babel+core@7.14.8
'@babel/helper-plugin-utils': 7.14.5
'@babel/plugin-syntax-typescript': 7.14.5_@babel+core@7.14.8
transitivePeerDependencies:
- supports-color
dev: true
/@babel/preset-typescript/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
'@babel/helper-plugin-utils': 7.14.5
'@babel/helper-validator-option': 7.14.5
'@babel/plugin-transform-typescript': 7.14.6_@babel+core@7.14.8
transitivePeerDependencies:
- supports-color
dev: true
/@babel/register/7.14.5_@babel+core@7.14.8:
resolution: {integrity: sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.14.8
clone-deep: 4.0.1
find-cache-dir: 2.1.0
make-dir: 2.1.0
pirates: 4.0.1
source-map-support: 0.5.19
dev: true
/@babel/template/7.14.5: /@babel/template/7.14.5:
resolution: {integrity: sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==} resolution: {integrity: sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -360,6 +462,12 @@ packages:
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
dev: true dev: true
/babel-plugin-dynamic-import-node/2.3.3:
resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==}
dependencies:
object.assign: 4.1.2
dev: true
/balanced-match/1.0.2: /balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: true dev: true
@ -403,6 +511,13 @@ packages:
resolution: {integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==} resolution: {integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==}
dev: true dev: true
/call-bind/1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies:
function-bind: 1.1.1
get-intrinsic: 1.1.1
dev: true
/camelcase/5.3.1: /camelcase/5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -481,6 +596,15 @@ packages:
wrap-ansi: 7.0.0 wrap-ansi: 7.0.0
dev: true dev: true
/clone-deep/4.0.1:
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
engines: {node: '>=6'}
dependencies:
is-plain-object: 2.0.4
kind-of: 6.0.3
shallow-clone: 3.0.1
dev: true
/color-convert/1.9.3: /color-convert/1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies: dependencies:
@ -506,6 +630,10 @@ packages:
resolution: {integrity: sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==} resolution: {integrity: sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==}
dev: true dev: true
/commondir/1.0.1:
resolution: {integrity: sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=}
dev: true
/concat-map/0.0.1: /concat-map/0.0.1:
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
dev: true dev: true
@ -566,6 +694,13 @@ packages:
type-detect: 4.0.8 type-detect: 4.0.8
dev: true dev: true
/define-properties/1.1.3:
resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==}
engines: {node: '>= 0.4'}
dependencies:
object-keys: 1.1.1
dev: true
/diff/4.0.2: /diff/4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'} engines: {node: '>=0.3.1'}
@ -614,6 +749,15 @@ packages:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
dev: true dev: true
/find-cache-dir/2.1.0:
resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==}
engines: {node: '>=6'}
dependencies:
commondir: 1.0.1
make-dir: 2.1.0
pkg-dir: 3.0.0
dev: true
/find-up/3.0.0: /find-up/3.0.0:
resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -658,6 +802,10 @@ packages:
resolution: {integrity: sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==} resolution: {integrity: sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==}
dev: true dev: true
/function-bind/1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/gensync/1.0.0-beta.2: /gensync/1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -672,6 +820,14 @@ packages:
resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=} resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=}
dev: true dev: true
/get-intrinsic/1.1.1:
resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
has-symbols: 1.0.2
dev: true
/glob-parent/5.1.2: /glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -714,6 +870,18 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/has-symbols/1.0.2:
resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==}
engines: {node: '>= 0.4'}
dev: true
/has/1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/he/1.2.0: /he/1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true hasBin: true
@ -769,6 +937,13 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/is-plain-object/2.0.4:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
engines: {node: '>=0.10.0'}
dependencies:
isobject: 3.0.1
dev: true
/is-unicode-supported/0.1.0: /is-unicode-supported/0.1.0:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -778,6 +953,11 @@ packages:
resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=}
dev: true dev: true
/isobject/3.0.1:
resolution: {integrity: sha1-TkMekrEalzFjaqH5yNHMvP2reN8=}
engines: {node: '>=0.10.0'}
dev: true
/js-tokens/4.0.0: /js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true dev: true
@ -813,6 +993,11 @@ packages:
graceful-fs: 4.2.6 graceful-fs: 4.2.6
dev: true dev: true
/kind-of/6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
dev: true
/locate-path/3.0.0: /locate-path/3.0.0:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -859,6 +1044,14 @@ packages:
js-tokens: 4.0.0 js-tokens: 4.0.0
dev: true dev: true
/make-dir/2.1.0:
resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
engines: {node: '>=6'}
dependencies:
pify: 4.0.1
semver: 5.7.1
dev: true
/make-error/1.3.6: /make-error/1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
dev: true dev: true
@ -955,6 +1148,11 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/node-modules-regexp/1.0.0:
resolution: {integrity: sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=}
engines: {node: '>=0.10.0'}
dev: true
/node-releases/1.1.73: /node-releases/1.1.73:
resolution: {integrity: sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==} resolution: {integrity: sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==}
dev: true dev: true
@ -969,6 +1167,21 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/object-keys/1.1.1:
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
engines: {node: '>= 0.4'}
dev: true
/object.assign/4.1.2:
resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
has-symbols: 1.0.2
object-keys: 1.1.1
dev: true
/once/1.4.0: /once/1.4.0:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies: dependencies:
@ -1037,6 +1250,25 @@ packages:
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
dev: true dev: true
/pify/4.0.1:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
dev: true
/pirates/4.0.1:
resolution: {integrity: sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==}
engines: {node: '>= 6'}
dependencies:
node-modules-regexp: 1.0.0
dev: true
/pkg-dir/3.0.0:
resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==}
engines: {node: '>=6'}
dependencies:
find-up: 3.0.0
dev: true
/prettier/2.3.2: /prettier/2.3.2:
resolution: {integrity: sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==} resolution: {integrity: sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
@ -1081,6 +1313,11 @@ packages:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: true dev: true
/semver/5.7.1:
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
hasBin: true
dev: true
/semver/6.3.0: /semver/6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
hasBin: true hasBin: true
@ -1096,6 +1333,13 @@ packages:
resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=}
dev: true dev: true
/shallow-clone/3.0.1:
resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
engines: {node: '>=8'}
dependencies:
kind-of: 6.0.3
dev: true
/source-map-support/0.5.19: /source-map-support/0.5.19:
resolution: {integrity: sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==} resolution: {integrity: sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==}
dependencies: dependencies:

View File

@ -0,0 +1,5 @@
require("@babel/register")({
extensions: [".js", ".jsx", ".ts", ".tsx"],
presets: ["@babel/preset-typescript"],
plugins: ["@babel/plugin-transform-modules-commonjs"],
})

18
scripts/build.js Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env node
const fs = require("fs")
const { format } = require("prettier")
const babel = require("@babel/core")
// Main
const res = babel.transformFileSync("src/index.ts", {
presets: ["@babel/preset-typescript"],
plugins: ["@babel/plugin-transform-modules-commonjs"],
})
fs.writeFileSync("lib/index.js", format(res.code, { parser: "babel" }))
// package.json
const pkg = require("../package.json")
delete pkg.scripts
delete pkg.devDependencies
delete pkg.prettier
fs.writeFileSync("lib/package.json", JSON.stringify(pkg, null, 2))

View File

@ -1,6 +1,184 @@
import type * as babel from "@babel/core"; import type * as babel from "@babel/core"
import type * as t from "@babel/types"
export default ({ types: t }: typeof babel): babel.PluginObj => ({ interface State {
name: "tsc-dedent", getTSLib(): t.ImportSpecifier[]
visitor: {}, getParam(): t.Identifier
}); getDecorate(): t.Identifier
}
export default ({ types: t }: typeof babel): babel.PluginObj<State> => ({
name: "tsc-decorators",
visitor: {
Program: {
enter(path, state) {
const getTSLib = once(() => {
const specifiers: t.ImportSpecifier[] = []
const dec = t.importDeclaration(specifiers, t.stringLiteral("tslib"))
path.node.body.unshift(dec)
return specifiers
})
state.getTSLib = getTSLib
const createGet = (name: string) =>
once(() => {
const specifiers = getTSLib()
const localID = path.scope.hasBinding(name)
? path.scope.generateUidIdentifier(name)
: t.identifier(name)
specifiers.push(t.importSpecifier(localID, t.identifier(name)))
return localID
})
const getParam = createGet("__param")
const getDecorate = createGet("__decorate")
state.getParam = () => t.cloneNode(getParam())
state.getDecorate = () => t.cloneNode(getDecorate())
},
},
ClassDeclaration(path, state) {
const modifiers: (t.Expression | t.Statement)[] = []
const classDecorators: t.Expression[] = []
const prefixes: t.Statement[] = []
const classID = path.node.id
const isNamedExport = t.isExportNamedDeclaration(path.parent)
const isDefaultExport = t.isExportDefaultDeclaration(path.parent)
if (path.node.decorators) {
classDecorators.push(...path.node.decorators.map(d => d.expression))
path.node.decorators = []
}
for (const child of path.node.body.body) {
switch (child.type) {
case "ClassProperty":
if (!child.decorators) continue
modifiers.push(
t.callExpression(state.getDecorate(), [
t.arrayExpression(child.decorators.map(d => d.expression)),
t.memberExpression(classID, t.identifier("prototype")),
t.isIdentifier(child.key) ? t.stringLiteral(child.key.name) : child.key,
t.unaryExpression("void", t.numericLiteral(0)),
])
)
child.decorators = null
break
case "ClassMethod":
{
const list: t.Expression[] = []
if (child.decorators) {
list.push(...child.decorators.map(d => d.expression))
child.decorators = null
}
child.params.forEach((param, i) => {
pseudoAssert(!t.isTSParameterProperty(param))
if (!param.decorators?.length) return
list.push(
...param.decorators
.map(d => d.expression)
.map(e =>
t.callExpression(state.getParam(), [t.numericLiteral(i), e])
)
)
param.decorators = null
})
if (child.kind === "constructor") {
classDecorators.push(...list)
} else {
let key: t.Expression
if (child.computed) {
const newID = path.scope.generateUidIdentifier()
prefixes.push(
t.variableDeclaration("let", [t.variableDeclarator(newID)])
)
child.key = t.assignmentExpression("=", newID, child.key)
key = newID
} else if (t.isIdentifier(child.key)) {
key = t.stringLiteral(child.key.name)
} else {
key = child.key
}
modifiers.push(
t.callExpression(state.getDecorate(), [
t.arrayExpression(list),
t.memberExpression(classID, t.identifier("prototype")),
key,
t.nullLiteral(),
])
)
}
}
break
}
}
if (!classDecorators.length && !modifiers.length && !prefixes.length) return
const replacees: t.Statement[] = prefixes.slice()
if (classDecorators.length) {
replacees.push(
t.variableDeclaration("let", [
t.variableDeclarator(classID, { ...path.node, type: "ClassExpression" }),
])
)
modifiers.push(
t.assignmentExpression(
"=",
classID,
t.callExpression(state.getDecorate(), [
t.arrayExpression(classDecorators),
classID,
])
)
)
if (isNamedExport) {
modifiers.push(
t.exportNamedDeclaration(undefined, [t.exportSpecifier(classID, classID)])
)
} else if (isDefaultExport) {
modifiers.push(t.exportDefaultDeclaration(classID))
}
} else {
let node: t.Statement = path.node
if (isNamedExport) {
node = t.exportNamedDeclaration(node, [], null)
} else if (isDefaultExport) {
node = t.exportDefaultDeclaration(node)
}
replacees.push(node)
}
replacees.push(
...modifiers.map(e => (t.isStatement(e) ? e : t.expressionStatement(e)))
)
const replacementTarget = isNamedExport || isDefaultExport ? path.parentPath : path
replacementTarget.replaceWithMultiple(replacees)
},
},
})
function pseudoAssert(condition: any): asserts condition {}
const once = <T extends Function>(fn: T): T => {
let called = false
let cache: any
return function (this: any) {
if (called) {
return cache
} else {
cache = fn.apply(this, arguments)
called = true
return cache
}
} as any
}

View File

@ -1,34 +1,53 @@
import { describe, it } from "mocha"; import { readFileSync } from "fs"
import { expect } from "chai"; import { describe, it } from "mocha"
import { transform } from "@babel/core"; import { resolve } from "path"
import { format } from "prettier"; import { expect } from "chai"
import plugin from "../src/index"; import { transform } from "@babel/core"
import { format } from "prettier"
import type { Snapshot } from "./snapshots"
import plugin from "../src/index"
const javascript = (code: TemplateStringsArray) => const canonize = (code: string) =>
transform(code[0], { format(code, { parser: "babel" }).trim().split("\n").filter(Boolean).join("\n")
const equal = (name: Snapshot) => {
const folder = resolve(__dirname, "snapshots", name)
const actual = readFileSync(resolve(folder, "input.txt"), "utf-8")
const expected = readFileSync(resolve(folder, "output.txt"), "utf-8")
const transformed = transform(actual, {
parserOpts: { parserOpts: {
plugins: ["decorators-legacy", "typescript"], plugins: ["decorators-legacy", "typescript"],
}, },
babelrc: false,
configFile: false,
plugins: [plugin], plugins: [plugin],
})!.code!; })!.code!
expect(canonize(transformed)).to.deep.equal(canonize(expected))
}
const canonize = (code: string) => format(code, { parser: "babel" }).trim(); describe("tsc-decorator", () => {
it("works with property decorators", () => {
equal("properties")
})
const equal = (actual: string, expected: string) => { it("works with method decorators", () => {
actual = canonize(actual); equal("methods")
expected = canonize(expected); })
expect(actual).to.deep.equal(expected);
};
describe("", () => { it("works with parameter decorators", () => {
it("should do nothing", () => { equal("params")
equal( })
javascript`
class A {} // https://github.com/babel/babel/issues/13591
`, it.skip("works with computed property keys", () => {
/* javascript */ ` equal("computedProperties")
class A {} })
`
); it("works with class/consrtuctor decorators", () => {
}); equal("constructor")
}); })
it("does not interfere with export declarations", () => {
equal("exports")
})
})

View File

@ -0,0 +1 @@
*

View File

@ -0,0 +1,4 @@
class A {
@decorator
[Symbol.iterator]() {}
}

View File

@ -0,0 +1,5 @@
let _a;
class A {
[_a = Symbol.iterator]() { }
}
__decorate([decorator], A.prototype, _a, null);

View File

@ -0,0 +1,4 @@
@classDecorator
class A {
@prop string: string;
}

View File

@ -0,0 +1,8 @@
import { __decorate } from "tslib";
let A = class A {
string: string;
}
__decorate([prop], A.prototype, "string", void 0);
A = __decorate([classDecorator], A);

View File

@ -0,0 +1,9 @@
export class NormalDecorated {
@prop a: string
}
@classDecorator
export class ClassDecorated {}
@classDecorator
export default class DefaultExport {}

View File

@ -0,0 +1,15 @@
import { __decorate } from "tslib";
export class NormalDecorated {
a: string;
}
__decorate([prop], NormalDecorated.prototype, "a", void 0);
let ClassDecorated = class ClassDecorated {};
ClassDecorated = __decorate([classDecorator], ClassDecorated);
export { ClassDecorated };
let DefaultExport = class DefaultExport {};
DefaultExport = __decorate([classDecorator], DefaultExport);
export default DefaultExport;

View File

@ -0,0 +1,3 @@
class A {
@dec method(): string {}
}

View File

@ -0,0 +1,7 @@
import { __decorate } from "tslib";
class A {
method(): string {}
}
__decorate([dec], A.prototype, "method", null);

View File

@ -0,0 +1,6 @@
import { __decorate } from "tslib"
class A {
method1(skipped: string, @Arg() b: string) {}
method2(@Arg() a: string, @Arg() b: string) {}
}

View File

@ -0,0 +1,10 @@
import { __param, __decorate as _decorate } from "tslib";
import { __decorate } from "tslib";
class A {
method1(skipped: string, b: string) {}
method2(a: string, b: string) {}
}
_decorate([__param(1, Arg())], A.prototype, "method1", null);
_decorate([__param(0, Arg()), __param(1, Arg())], A.prototype, "method2", null);

View File

@ -0,0 +1,4 @@
class A {
@dec prop: string
@dec @dec2 prop2: string
}

View File

@ -0,0 +1,9 @@
import { __decorate } from "tslib"
class A {
prop: string;
prop2: string;
}
__decorate([dec], A.prototype, "prop", void 0);
__decorate([dec, dec2], A.prototype, "prop2", void 0);

View File

@ -1,5 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true,
"checkJs": false,
"strict": true, "strict": true,
"noEmit": true "noEmit": true
} }