1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.ADDON_NAME = void 0;
|
7 | const semver_1 = __importDefault(require("semver"));
|
8 | const child_process_1 = require("stagehand/lib/adapters/child-process");
|
9 | const ember_cli_entities_1 = require("./lib/utilities/ember-cli-entities");
|
10 | const fork_1 = __importDefault(require("./lib/utilities/fork"));
|
11 | const middleware_1 = __importDefault(require("./lib/typechecking/middleware"));
|
12 | const walk_sync_1 = __importDefault(require("walk-sync"));
|
13 | const fs_extra_1 = __importDefault(require("fs-extra"));
|
14 | const debug_1 = __importDefault(require("debug"));
|
15 | const debug = debug_1.default('ember-cli-typescript:addon');
|
16 | exports.ADDON_NAME = 'ember-cli-typescript';
|
17 | exports.default = ember_cli_entities_1.addon({
|
18 | name: exports.ADDON_NAME,
|
19 | included() {
|
20 | this._super.included.apply(this, arguments);
|
21 | this._checkDevelopment();
|
22 | this._checkAddonAppFiles();
|
23 | this._checkBabelVersion();
|
24 |
|
25 |
|
26 | if (this.parent === this.project) {
|
27 | this._getTypecheckWorker();
|
28 | this._checkInstallationLocation();
|
29 | this._checkEmberCLIVersion();
|
30 | }
|
31 | },
|
32 | includedCommands() {
|
33 | if (this.project.isEmberCLIAddon()) {
|
34 | return {
|
35 | 'ts:precompile': require('./lib/commands/precompile').default,
|
36 | 'ts:clean': require('./lib/commands/clean').default,
|
37 | };
|
38 | }
|
39 | },
|
40 | blueprintsPath() {
|
41 | return `${__dirname}/blueprints`;
|
42 | },
|
43 | serverMiddleware({ app, options }) {
|
44 | if (!options || !options.path) {
|
45 | debug('Installing typecheck server middleware');
|
46 | this._addTypecheckMiddleware(app);
|
47 | }
|
48 | else {
|
49 | debug('Skipping typecheck server middleware');
|
50 | }
|
51 | },
|
52 | testemMiddleware(app, options) {
|
53 | if (!options || !options.path) {
|
54 | debug('Installing typecheck testem middleware');
|
55 | this._addTypecheckMiddleware(app);
|
56 | }
|
57 | else {
|
58 | debug('Skipping typecheck testem middleware');
|
59 | }
|
60 | },
|
61 | async postBuild() {
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | let worker = await this._getTypecheckWorker();
|
69 | let { failed } = await worker.getStatus();
|
70 | if (failed) {
|
71 |
|
72 |
|
73 | throw new Error('Typechecking failed');
|
74 | }
|
75 | },
|
76 | setupPreprocessorRegistry(type, registry) {
|
77 | if (type !== 'parent')
|
78 | return;
|
79 |
|
80 |
|
81 |
|
82 | if (this.parent === this.project) {
|
83 | this._registerCollisionDetectionPreprocessor(registry);
|
84 | }
|
85 | },
|
86 | shouldIncludeChildAddon(addon) {
|
87 |
|
88 |
|
89 | return !['in-repo-a', 'in-repo-b'].includes(addon.name);
|
90 | },
|
91 | _registerCollisionDetectionPreprocessor(registry) {
|
92 | registry.add('js', {
|
93 | name: 'ember-cli-typescript-collision-check',
|
94 | toTree: (input, path) => {
|
95 | if (path !== '/')
|
96 | return input;
|
97 | let addon = this;
|
98 | let checked = false;
|
99 | let stew = require('broccoli-stew');
|
100 | return stew.afterBuild(input, function () {
|
101 | if (!checked) {
|
102 | checked = true;
|
103 | addon._checkForFileCollisions(this.inputPaths[0]);
|
104 | }
|
105 | });
|
106 | },
|
107 | });
|
108 | },
|
109 | _checkForFileCollisions(directory) {
|
110 | let walkSync = require('walk-sync');
|
111 | let files = new Set(walkSync(directory, ['**/*.{js,ts}']));
|
112 | let collisions = [];
|
113 | for (let file of files) {
|
114 | if (file.endsWith('.js') && files.has(file.replace(/\.js$/, '.ts'))) {
|
115 | collisions.push(file.replace(/\.js$/, '.{js,ts}'));
|
116 | }
|
117 | }
|
118 | if (collisions.length) {
|
119 | this.ui.writeWarnLine('Detected collisions between .js and .ts files of the same name. ' +
|
120 | 'This can result in nondeterministic build output; ' +
|
121 | 'see https://git.io/JvIwo for more information.\n - ' +
|
122 | collisions.join('\n - '));
|
123 | }
|
124 | },
|
125 | _checkBabelVersion() {
|
126 | let babel = this.parent.addons.find((addon) => addon.name === 'ember-cli-babel');
|
127 | let version = babel && babel.pkg.version;
|
128 | if (!babel || !(semver_1.default.gte(version, '7.17.0') && semver_1.default.lt(version, '8.0.0'))) {
|
129 | let versionString = babel ? `version ${babel.pkg.version}` : `no instance of ember-cli-babel`;
|
130 | this.ui.writeWarnLine(`ember-cli-typescript requires ember-cli-babel ^7.17.0, but you have ${versionString} installed; ` +
|
131 | 'your TypeScript files may not be transpiled correctly.');
|
132 | }
|
133 | },
|
134 | _checkEmberCLIVersion() {
|
135 | let cliPackage = this.project.require('ember-cli/package.json');
|
136 | if (semver_1.default.lt(cliPackage.version, '3.5.0')) {
|
137 | this.ui.writeWarnLine('ember-cli-typescript works best with ember-cli >= 3.5, which uses the system temporary directory ' +
|
138 | 'by default rather than a project-local one, minimizing file system events the TypeScript ' +
|
139 | 'compiler needs to keep track of.');
|
140 | }
|
141 | },
|
142 | _checkDevelopment() {
|
143 | if (this.isDevelopingAddon() && !process.env.CI && __filename.endsWith('.js')) {
|
144 | this.ui.writeWarnLine('ember-cli-typescript is in development but not being loaded from `.ts` sources — ' +
|
145 | 'do you have compiled artifacts lingering in `/js`?');
|
146 | }
|
147 | },
|
148 | _checkAddonAppFiles() {
|
149 |
|
150 | let isDevelopingAddon = !this.app && this.parent.isDevelopingAddon();
|
151 |
|
152 | let isRootAddon = this.parent.root === this.project.root;
|
153 |
|
154 | let appDir = `${this.parent.root}/app`;
|
155 | if (isDevelopingAddon && isRootAddon && fs_extra_1.default.existsSync(appDir)) {
|
156 | let tsFilesInApp = walk_sync_1.default(appDir, { globs: ['**/*.ts'] });
|
157 | if (tsFilesInApp.length) {
|
158 | this.ui.writeWarnLine(`found .ts files in ${appDir}\n` +
|
159 | "ember-cli-typescript only compiles files in an addon's `addon` folder; " +
|
160 | 'see https://github.com/typed-ember/ember-cli-typescript/issues/562');
|
161 | }
|
162 | }
|
163 | },
|
164 | _checkInstallationLocation() {
|
165 | if (this.project.isEmberCLIAddon() &&
|
166 | this.project.pkg.devDependencies &&
|
167 | this.project.pkg.devDependencies[this.name]) {
|
168 | this.ui.writeWarnLine('`ember-cli-typescript` should be included in your `dependencies`, not `devDependencies`');
|
169 | }
|
170 | },
|
171 | _addTypecheckMiddleware(app) {
|
172 | let workerPromise = this._getTypecheckWorker();
|
173 | let middleware = new middleware_1.default(this.project, workerPromise);
|
174 | middleware.register(app);
|
175 | },
|
176 | _typecheckWorker: undefined,
|
177 | _getTypecheckWorker() {
|
178 | if (!this._typecheckWorker) {
|
179 | this._typecheckWorker = this._forkTypecheckWorker();
|
180 | }
|
181 | return this._typecheckWorker;
|
182 | },
|
183 | async _forkTypecheckWorker() {
|
184 | let childProcess = fork_1.default(`${__dirname}/lib/typechecking/worker/launch`);
|
185 | let worker = await child_process_1.connect(childProcess);
|
186 | await worker.onTypecheck((status) => {
|
187 | for (let error of status.errors) {
|
188 | this.ui.writeLine(error);
|
189 | }
|
190 | });
|
191 | await worker.start(this.project.root);
|
192 | return worker;
|
193 | },
|
194 | });
|