|
| 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 | +}); |
0 commit comments