Skip to content

Commit c439b06

Browse files
committed
Rewrite addon main to register Babel plugins
1 parent 931f537 commit c439b06

File tree

8 files changed

+1195
-215
lines changed

8 files changed

+1195
-215
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module.exports = {
7373
rules: {
7474
// These are covered by tsc
7575
'no-undef': 'off',
76-
'no-unused-var': 'off'
76+
'no-unused-vars': 'off'
7777
}
7878
}
7979
],

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ const fs = require('fs');
66
// Otherwise, register ts-node if necessary and load from source.
77
if (fs.existsSync(`${__dirname}/js/addon.js`)) {
88
// eslint-disable-next-line node/no-missing-require
9-
module.exports = require('./js/addon');
9+
module.exports = require('./js/addon').default;
1010
} else {
1111
require('./register-ts-node');
1212

1313
// eslint-disable-next-line node/no-unpublished-require
14-
module.exports = require('./ts/addon');
14+
module.exports = require('./ts/addon').default;
1515
}

package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,22 @@
3535
"postpublish": "rimraf js"
3636
},
3737
"dependencies": {
38+
"@babel/plugin-proposal-class-properties": "^7.1.0",
39+
"@babel/plugin-transform-typescript": "^7.1.0",
3840
"broccoli-funnel": "^2.0.1",
3941
"broccoli-merge-trees": "^2.0.0",
4042
"broccoli-plugin": "^1.2.1",
4143
"broccoli-stew": "^1.4.0",
4244
"chokidar": "^2.0.3",
4345
"debug": "^3.1.0",
44-
"ember-cli-typescript-blueprints": "^1.0.0",
46+
"ember-cli-babel-plugin-helpers": "^1.0.0",
4547
"escape-string-regexp": "^1.0.5",
4648
"execa": "^0.9.0",
4749
"fs-extra": "^5.0.0",
4850
"glob": "^7.1.2",
4951
"resolve": "^1.5.0",
5052
"rsvp": "^4.8.1",
53+
"semver": "^5.5.1",
5154
"symlink-or-copy": "^1.1.8",
5255
"walk-sync": "^0.3.2"
5356
},
@@ -59,11 +62,12 @@
5962
"@types/ember-qunit": "^3.0.1",
6063
"@types/node": "^9.6.5",
6164
"@types/qunit": "^2.0.31",
65+
"@types/semver": "^5.5.0",
6266
"broccoli-asset-rev": "^2.7.0",
6367
"co": "^4.6.0",
6468
"ember-cli": "~3.5.0",
6569
"ember-cli-app-version": "^3.1.3",
66-
"ember-cli-babel": "^6.16.0",
70+
"ember-cli-babel": "^7.1.2",
6771
"ember-cli-blueprint-test-helpers": "^0.18.3",
6872
"ember-cli-dependency-checker": "^3.0.0",
6973
"ember-cli-eslint": "^4.2.3",
@@ -72,6 +76,7 @@
7276
"ember-cli-inject-live-reload": "^1.8.2",
7377
"ember-cli-release": "^0.2.9",
7478
"ember-cli-sri": "^2.1.1",
79+
"ember-cli-typescript-blueprints": "^1.0.0",
7580
"ember-cli-uglify": "^2.1.0",
7681
"ember-cli-update": "^0.14.0",
7782
"ember-disable-prototype-extensions": "^1.1.3",
@@ -108,13 +113,7 @@
108113
"ember-addon": {
109114
"configPath": "tests/dummy/config",
110115
"before": [
111-
"ember-cli-babel",
112-
"ember-qunit-decorators"
113-
],
114-
"after": [
115-
"ember-source",
116-
"ember-data",
117-
"ember-decorators"
116+
"ember-cli-babel"
118117
]
119118
},
120119
"prettier": {

ts/addon.js

Lines changed: 0 additions & 119 deletions
This file was deleted.

ts/addon.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import semver from 'semver';
2+
import { hasPlugin, addPlugin, AddPluginOptions } from 'ember-cli-babel-plugin-helpers';
3+
import Addon from 'ember-cli/lib/models/addon';
4+
import { addon } from './lib/utilities/ember-cli-entities';
5+
6+
export default addon({
7+
name: 'ember-cli-typescript',
8+
9+
included() {
10+
this._super.included.apply(this, arguments);
11+
this._checkDevelopment();
12+
this._checkBabelVersion();
13+
},
14+
15+
includedCommands() {
16+
if (this.project.isEmberCLIAddon()) {
17+
return {
18+
'ts:precompile': require('./lib/commands/precompile'),
19+
'ts:clean': require('./lib/commands/clean'),
20+
};
21+
}
22+
},
23+
24+
blueprintsPath() {
25+
return `${__dirname}/blueprints`;
26+
},
27+
28+
setupPreprocessorRegistry(type: string) {
29+
if (type !== 'parent') return;
30+
31+
// Normally this is the sort of logic that would live in `included()`, but
32+
// ember-cli-babel reads the configured extensions when setting up the
33+
// preprocessor registry, so we need to beat it to the punch.
34+
this._registerBabelExtension();
35+
36+
this._addPluginIfMissing('@babel/plugin-transform-typescript');
37+
this._addPluginIfMissing(
38+
'@babel/plugin-proposal-class-properties',
39+
{ loose: true },
40+
{
41+
// Needs to come after the decorators plugin, if present
42+
after: ['@babel/plugin-proposal-decorators'],
43+
}
44+
);
45+
},
46+
47+
shouldIncludeChildAddon(addon) {
48+
// For testing, we have dummy in-repo addons set up, but e-c-ts doesn't depend on them;
49+
// its dummy app does. Otherwise we'd have a circular dependency.
50+
return !['in-repo-a', 'in-repo-b'].includes(addon.name);
51+
},
52+
53+
_checkBabelVersion() {
54+
let babel = this.parent.addons.find(addon => addon.name === 'ember-cli-babel');
55+
if (!babel || !semver.satisfies(babel.pkg.version, '>=7.0.0-alpha.0 <8')) {
56+
let version = babel ? `version ${babel.pkg.version}` : `no instance of ember-cli-babel`;
57+
this.ui.writeWarnLine(
58+
`ember-cli-typescript requires ember-cli-babel@7, but you have ${version} installed; ` +
59+
'your TypeScript files may not be transpiled correctly.'
60+
);
61+
}
62+
},
63+
64+
_checkDevelopment() {
65+
if (this.isDevelopingAddon() && !process.env.CI && __filename.endsWith('.js')) {
66+
this.ui.writeWarnLine(
67+
'ember-cli-typescript is in development but not being loaded from `.ts` sources — ' +
68+
'do you have compiled artifacts lingering in `/js`?'
69+
);
70+
}
71+
},
72+
73+
_addPluginIfMissing(name: string, config?: unknown, constraints?: AddPluginOptions) {
74+
let target = this._getConfigurationTarget();
75+
76+
if (!hasPlugin(target, name)) {
77+
addPlugin(target, [require.resolve(name), config], constraints);
78+
}
79+
},
80+
81+
_getConfigurationTarget() {
82+
// If `this.app` isn't present, we know `this.parent` is an addon
83+
return this.app || (this.parent as Addon);
84+
},
85+
86+
_registerBabelExtension() {
87+
let target = this._getConfigurationTarget();
88+
let options: Record<string, any> = target.options || (target.options = {});
89+
let babelAddonOptions: Record<string, any> =
90+
options['ember-cli-babel'] || (options['ember-cli-babel'] = {});
91+
let extensions: string[] =
92+
babelAddonOptions.extensions || (babelAddonOptions.extensions = ['js']);
93+
94+
if (!extensions.includes('ts')) {
95+
extensions.push('ts');
96+
}
97+
},
98+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ExtendOptions, ExtendThisType } from 'core-object';
2+
import Addon from 'ember-cli/lib/models/addon';
3+
4+
/*
5+
* This module contains identity functions that accept and return config
6+
* hashes for various Ember CLI entities, ensuring that they're compatible
7+
* with the expected config signature and that any methods have the correct
8+
* `this` type.
9+
*/
10+
11+
/** Configuration for defining an Ember CLI addon */
12+
export function addon<T extends ExtendOptions<Addon>>(options: T & ExtendThisType<Addon, T>): T {
13+
return options;
14+
}

ts/tsconfig.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"noImplicitThis": true,
1111
"strictNullChecks": true,
1212
"strictPropertyInitialization": true,
13+
"noUnusedLocals": true,
14+
"noUnusedParameters": true,
1315
"outDir": "../js",
1416
"typeRoots": ["../node_modules/@types", "types"],
1517
"esModuleInterop": true

0 commit comments

Comments
 (0)