ember-cli 7.1.0 → 7.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -25
- package/RELEASE.md +6 -5
- package/blueprints/http-mock/index.js +1 -1
- package/blueprints/http-proxy/index.js +1 -1
- package/docs/build/data.json +128 -1598
- package/lib/commands/generate.js +1 -1
- package/lib/models/command.js +1 -1
- package/lib/models/package-info-cache/package-info.js +1 -1
- package/lib/models/project.js +13 -5
- package/lib/tasks/generate-from-blueprint.js +1 -1
- package/lib/tasks/install-blueprint.js +4 -2
- package/lib/utilities/merge-blueprint-options.js +1 -1
- package/lib/utilities/version-utils.js +6 -1
- package/package.json +23 -14
- package/packages/addon-blueprint/files/README.md +10 -0
- package/packages/addon-blueprint/package.json +10 -2
- package/packages/app-blueprint/files/package.json +14 -14
- package/packages/app-blueprint/package.json +10 -2
- package/packages/blueprint-blueprint/files/blueprints/__name__/files/.gitkeep +0 -0
- package/packages/blueprint-blueprint/files/blueprints/__name__/index.js +16 -0
- package/packages/blueprint-blueprint/index.js +5 -0
- package/packages/blueprint-blueprint/package.json +13 -0
- package/{lib/models/blueprint.js → packages/blueprint-model/index.js} +19 -35
- package/packages/blueprint-model/node_modules/.bin/markdown-it +21 -0
- package/packages/blueprint-model/package.json +31 -0
- package/packages/blueprint-model/utilities/directory-for-package-name.js +31 -0
- package/packages/blueprint-model/utilities/edit-file-diff.js +64 -0
- package/packages/blueprint-model/utilities/experiments.js +63 -0
- package/packages/blueprint-model/utilities/file-info.js +170 -0
- package/packages/blueprint-model/utilities/open-editor.js +44 -0
- package/packages/blueprint-model/utilities/prepend-emoji.js +12 -0
- package/packages/blueprint-model/utilities/process-template.js +10 -0
- package/patches/ember-cli-blueprint-test-helpers.patch +15 -0
- package/tests/helpers/acceptance.js +6 -5
- package/tests/helpers/fixturify-project.js +29 -137
- package/tests/helpers/per-bundle-addon-cache.js +17 -23
- /package/{lib → packages/blueprint-model}/utilities/clean-remove.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/insert-into-file.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/is-addon.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/markdown-color.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/print-command.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/sequence.js +0 -0
- /package/{lib → packages/blueprint-model}/utilities/walk-up-path.js +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const util = require('util');
|
|
5
|
+
const { applyPatch, createPatch } = require('diff');
|
|
6
|
+
const quickTemp = require('quick-temp');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const SilentError = require('silent-error');
|
|
9
|
+
const openEditor = require('./open-editor');
|
|
10
|
+
const hash = require('promise.hash.helper');
|
|
11
|
+
|
|
12
|
+
const readFile = util.promisify(fs.readFile);
|
|
13
|
+
const writeFile = util.promisify(fs.writeFile);
|
|
14
|
+
|
|
15
|
+
class EditFileDiff {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.info = options.info;
|
|
18
|
+
|
|
19
|
+
quickTemp.makeOrRemake(this, 'tmpDifferenceDir');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
edit() {
|
|
23
|
+
return hash({
|
|
24
|
+
input: this.info.render(),
|
|
25
|
+
output: readFile(this.info.outputPath),
|
|
26
|
+
})
|
|
27
|
+
.then(this.invokeEditor.bind(this))
|
|
28
|
+
.then(this.applyPatch.bind(this))
|
|
29
|
+
.finally(this.cleanUp.bind(this));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
cleanUp() {
|
|
33
|
+
quickTemp.remove(this, 'tmpDifferenceDir');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
applyPatch(resultHash) {
|
|
37
|
+
return hash({
|
|
38
|
+
diffString: readFile(resultHash.diffPath),
|
|
39
|
+
currentString: readFile(resultHash.outputPath),
|
|
40
|
+
}).then((result) => {
|
|
41
|
+
let appliedDiff = applyPatch(result.currentString.toString(), result.diffString.toString());
|
|
42
|
+
|
|
43
|
+
if (!appliedDiff) {
|
|
44
|
+
let message = 'Patch was not cleanly applied.';
|
|
45
|
+
this.info.ui.writeLine(`${message} Please choose another action.`);
|
|
46
|
+
throw new SilentError(message);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return writeFile(resultHash.outputPath, appliedDiff);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
invokeEditor(result) {
|
|
54
|
+
let info = this.info;
|
|
55
|
+
let diff = createPatch(info.outputPath, result.output.toString(), result.input);
|
|
56
|
+
let diffPath = path.join(this.tmpDifferenceDir, 'currentDiff.diff');
|
|
57
|
+
|
|
58
|
+
return writeFile(diffPath, diff)
|
|
59
|
+
.then(() => openEditor(diffPath))
|
|
60
|
+
.then(() => ({ outputPath: info.outputPath, diffPath }));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = EditFileDiff;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { default: chalk } = require('chalk');
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
If you're here to remove the VITE experiment flag in favor of it being
|
|
7
|
+
permanently on, you can't do that until addressing
|
|
8
|
+
https://github.com/ember-cli/ember-cli/pull/10781#pullrequestreview-3230644293
|
|
9
|
+
|
|
10
|
+
A lot of test coverage would otherwise be lost, because valid tests are being
|
|
11
|
+
run only when the VITE experiment is off.
|
|
12
|
+
*/
|
|
13
|
+
const availableExperiments = Object.freeze(['EMBROIDER', 'CLASSIC', 'VITE']);
|
|
14
|
+
|
|
15
|
+
const deprecatedExperiments = Object.freeze([]);
|
|
16
|
+
const enabledExperiments = Object.freeze(['VITE']);
|
|
17
|
+
const deprecatedExperimentsDeprecationsIssued = [];
|
|
18
|
+
|
|
19
|
+
function isExperimentEnabled(experimentName) {
|
|
20
|
+
if (!availableExperiments.includes(experimentName)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (process.env.EMBER_CLI_ENABLE_ALL_EXPERIMENTS && deprecatedExperiments.includes(experimentName)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (process.env.EMBER_CLI_ENABLE_ALL_EXPERIMENTS) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (process.env.EMBER_CLI_CLASSIC && experimentName === 'EMBROIDER') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let experimentEnvironmentVariable = `EMBER_CLI_${experimentName}`;
|
|
37
|
+
let experimentValue = process.env[experimentEnvironmentVariable];
|
|
38
|
+
|
|
39
|
+
if (deprecatedExperiments.includes(experimentName)) {
|
|
40
|
+
let deprecationPreviouslyIssued = deprecatedExperimentsDeprecationsIssued.includes(experimentName);
|
|
41
|
+
let isSpecifiedByUser = experimentValue !== undefined;
|
|
42
|
+
|
|
43
|
+
if (!deprecationPreviouslyIssued && isSpecifiedByUser) {
|
|
44
|
+
console.warn(
|
|
45
|
+
chalk.yellow(`The ${experimentName} experiment in ember-cli has been deprecated and will be removed.`)
|
|
46
|
+
);
|
|
47
|
+
deprecatedExperimentsDeprecationsIssued.push(experimentName);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (enabledExperiments.includes(experimentName)) {
|
|
52
|
+
return experimentValue !== 'false';
|
|
53
|
+
} else {
|
|
54
|
+
return experimentValue !== undefined && experimentValue !== 'false';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
isExperimentEnabled,
|
|
60
|
+
|
|
61
|
+
// exported for testing purposes
|
|
62
|
+
_deprecatedExperimentsDeprecationsIssued: deprecatedExperimentsDeprecationsIssued,
|
|
63
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const util = require('util');
|
|
5
|
+
const { default: chalk } = require('chalk');
|
|
6
|
+
const EditFileDiff = require('./edit-file-diff');
|
|
7
|
+
const EOL = require('os').EOL;
|
|
8
|
+
const rxEOL = new RegExp(EOL, 'g');
|
|
9
|
+
const isBinaryFile = require('isbinaryfile').isBinaryFileSync;
|
|
10
|
+
const hash = require('promise.hash.helper');
|
|
11
|
+
const canEdit = require('./open-editor').canEdit;
|
|
12
|
+
const processTemplate = require('./process-template');
|
|
13
|
+
|
|
14
|
+
const readFile = util.promisify(fs.readFile);
|
|
15
|
+
const lstat = util.promisify(fs.stat);
|
|
16
|
+
|
|
17
|
+
function diffHighlight(line) {
|
|
18
|
+
if (line[0] === '+') {
|
|
19
|
+
return chalk.green(line);
|
|
20
|
+
} else if (line[0] === '-') {
|
|
21
|
+
return chalk.red(line);
|
|
22
|
+
} else if (/^@@/.test(line)) {
|
|
23
|
+
return chalk.cyan(line);
|
|
24
|
+
} else {
|
|
25
|
+
return line;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const NOOP = (_) => _;
|
|
30
|
+
class FileInfo {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
this.action = options.action;
|
|
33
|
+
this.outputBasePath = options.outputBasePath;
|
|
34
|
+
this.outputPath = options.outputPath;
|
|
35
|
+
this.displayPath = options.displayPath;
|
|
36
|
+
this.inputPath = options.inputPath;
|
|
37
|
+
this.templateVariables = options.templateVariables;
|
|
38
|
+
this.replacer = options.replacer || NOOP;
|
|
39
|
+
this.ui = options.ui;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
confirmOverwrite(path) {
|
|
43
|
+
let promptOptions = {
|
|
44
|
+
type: 'expand',
|
|
45
|
+
name: 'answer',
|
|
46
|
+
default: false,
|
|
47
|
+
message: `${chalk.red('Overwrite')} ${path}?`,
|
|
48
|
+
choices: [
|
|
49
|
+
{ key: 'y', name: 'Yes, overwrite', value: 'overwrite' },
|
|
50
|
+
{ key: 'n', name: 'No, skip', value: 'skip' },
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
let outputPathIsFile = false;
|
|
55
|
+
try {
|
|
56
|
+
outputPathIsFile = fs.statSync(this.outputPath).isFile();
|
|
57
|
+
} catch (err) {
|
|
58
|
+
/* ignore */
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let canDiff = !isBinaryFile(this.inputPath) && (!outputPathIsFile || !isBinaryFile(this.outputPath));
|
|
62
|
+
|
|
63
|
+
if (canDiff) {
|
|
64
|
+
promptOptions.choices.push({ key: 'd', name: 'Diff', value: 'diff' });
|
|
65
|
+
|
|
66
|
+
if (canEdit()) {
|
|
67
|
+
promptOptions.choices.push({ key: 'e', name: 'Edit', value: 'edit' });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return this.ui.prompt(promptOptions).then((response) => response.answer);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
displayDiff() {
|
|
75
|
+
let info = this,
|
|
76
|
+
{ createPatch } = require('diff');
|
|
77
|
+
return hash({
|
|
78
|
+
input: this.render(),
|
|
79
|
+
output: readFile(info.outputPath),
|
|
80
|
+
}).then((result) => {
|
|
81
|
+
let diff = createPatch(
|
|
82
|
+
info.outputPath,
|
|
83
|
+
result.output.toString().replace(rxEOL, '\n'),
|
|
84
|
+
result.input.replace(rxEOL, '\n')
|
|
85
|
+
);
|
|
86
|
+
let lines = diff.split('\n');
|
|
87
|
+
|
|
88
|
+
for (let i = 0; i < lines.length; i++) {
|
|
89
|
+
info.ui.write(diffHighlight(lines[i] + EOL));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async render() {
|
|
95
|
+
if (!this.rendered) {
|
|
96
|
+
let result = await this._render();
|
|
97
|
+
this.rendered = this.replacer(result, this);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return this.rendered;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
_render() {
|
|
104
|
+
let path = this.inputPath;
|
|
105
|
+
let context = this.templateVariables;
|
|
106
|
+
|
|
107
|
+
return readFile(path).then((content) =>
|
|
108
|
+
lstat(path).then((fileStat) => {
|
|
109
|
+
if (isBinaryFile(content, fileStat.size)) {
|
|
110
|
+
return content;
|
|
111
|
+
} else {
|
|
112
|
+
try {
|
|
113
|
+
return processTemplate(content.toString(), context);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
err.message += ` (Error in blueprint template: ${path})`;
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
checkForConflict() {
|
|
124
|
+
return this.render().then((input) => {
|
|
125
|
+
input = input.toString().replace(rxEOL, '\n');
|
|
126
|
+
|
|
127
|
+
return readFile(this.outputPath)
|
|
128
|
+
.then((output) => {
|
|
129
|
+
output = output.toString().replace(rxEOL, '\n');
|
|
130
|
+
|
|
131
|
+
return input === output ? 'identical' : 'confirm';
|
|
132
|
+
})
|
|
133
|
+
.catch((e) => {
|
|
134
|
+
if (e.code === 'ENOENT') {
|
|
135
|
+
return 'none';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
throw e;
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
confirmOverwriteTask() {
|
|
144
|
+
let info = this;
|
|
145
|
+
|
|
146
|
+
return function () {
|
|
147
|
+
function doConfirm() {
|
|
148
|
+
return info.confirmOverwrite(info.displayPath).then((action) => {
|
|
149
|
+
if (action === 'diff') {
|
|
150
|
+
return info.displayDiff().then(doConfirm);
|
|
151
|
+
} else if (action === 'edit') {
|
|
152
|
+
let editFileDiff = new EditFileDiff({ info });
|
|
153
|
+
return editFileDiff
|
|
154
|
+
.edit()
|
|
155
|
+
.then(() => (info.action = action))
|
|
156
|
+
.catch(() => doConfirm())
|
|
157
|
+
.then(() => info);
|
|
158
|
+
} else {
|
|
159
|
+
info.action = action;
|
|
160
|
+
return info;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return doConfirm();
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
module.exports = FileInfo;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const spawn = require('child_process').spawn;
|
|
4
|
+
|
|
5
|
+
function openEditor(file) {
|
|
6
|
+
if (!openEditor.canEdit()) {
|
|
7
|
+
throw new Error('EDITOR environment variable is not set');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!file) {
|
|
11
|
+
throw new Error('No `file` option provided');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let editorArgs = openEditor._env().EDITOR.split(' ');
|
|
15
|
+
let editor = editorArgs.shift();
|
|
16
|
+
const args = [file].concat(editorArgs);
|
|
17
|
+
let editProcess = openEditor._spawn(editor, args, { stdio: 'inherit' });
|
|
18
|
+
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
editProcess.on('close', (code) => {
|
|
21
|
+
if (code === 0) {
|
|
22
|
+
resolve();
|
|
23
|
+
} else {
|
|
24
|
+
reject(
|
|
25
|
+
new Error(`Spawn('${editor}', [${args.join(',')}]) exited with a non zero error status code: '${code}'`)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
openEditor.canEdit = function () {
|
|
33
|
+
return openEditor._env().EDITOR !== undefined;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
openEditor._env = function () {
|
|
37
|
+
return process.env;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
openEditor._spawn = function () {
|
|
41
|
+
return spawn.apply(this, arguments);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
module.exports = openEditor;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function supportEmoji() {
|
|
4
|
+
const hasEmojiTurnedOff = process.argv.indexOf('--no-emoji') > -1;
|
|
5
|
+
return process.stdout.isTTY && process.platform !== 'win32' && !hasEmojiTurnedOff;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const areEmojiSupported = supportEmoji();
|
|
9
|
+
|
|
10
|
+
module.exports = function prependEmoji(emoji, msg) {
|
|
11
|
+
return areEmojiSupported ? `${emoji} ${msg}` : msg;
|
|
12
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = function processTemplate(content, context) {
|
|
4
|
+
let options = {
|
|
5
|
+
evaluate: /<%([\s\S]+?)%>/g,
|
|
6
|
+
interpolate: /<%=([\s\S]+?)%>/g,
|
|
7
|
+
escape: /<%-([\s\S]+?)%>/g,
|
|
8
|
+
};
|
|
9
|
+
return require('lodash/template')(content, options)(context);
|
|
10
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
diff --git a/lib/helpers/setup.js b/lib/helpers/setup.js
|
|
2
|
+
index c337ec0020f46e0e9ed3f76b325c7d174168a900..29dfd7fb0acd5ae895d470b80be15bf1c8ff9a25 100644
|
|
3
|
+
--- a/lib/helpers/setup.js
|
|
4
|
+
+++ b/lib/helpers/setup.js
|
|
5
|
+
@@ -31,7 +31,9 @@ module.exports = function setupTestHooks(scope, options) {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (disabledTasks.length) {
|
|
9
|
+
- let Blueprint = requireFromCLI('lib/models/blueprint');
|
|
10
|
+
+ let Blueprint = require('@ember-tooling/blueprint-model', {
|
|
11
|
+
+ paths: [options.cliPath]
|
|
12
|
+
+ });
|
|
13
|
+
|
|
14
|
+
before(() => {
|
|
15
|
+
MockBlueprintTaskFor.disableTasks(Blueprint, disabledTasks);
|
|
@@ -139,11 +139,7 @@ async function createAndInstallTestTargets(projectName, options) {
|
|
|
139
139
|
|
|
140
140
|
let result = await applyCommand(command, projectName, '--skip-npm', `--directory=${outputDir.path}`);
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
preferLocal: true,
|
|
144
|
-
cwd: outputDir.path,
|
|
145
|
-
});
|
|
146
|
-
|
|
142
|
+
// we need to link these packages before we try to run pnpm install so it always uses the current version of ember-cli and the sub-packages
|
|
147
143
|
for (let pkg of [
|
|
148
144
|
'.',
|
|
149
145
|
'packages/blueprint-model',
|
|
@@ -157,6 +153,11 @@ async function createAndInstallTestTargets(projectName, options) {
|
|
|
157
153
|
});
|
|
158
154
|
}
|
|
159
155
|
|
|
156
|
+
await execa('pnpm', ['install', '--prefer-offline'], {
|
|
157
|
+
preferLocal: true,
|
|
158
|
+
cwd: outputDir.path,
|
|
159
|
+
});
|
|
160
|
+
|
|
160
161
|
return {
|
|
161
162
|
result,
|
|
162
163
|
cleanup: outputDir.cleanup,
|
|
@@ -4,9 +4,10 @@ const path = require('path');
|
|
|
4
4
|
const merge = require('lodash/merge');
|
|
5
5
|
// this is a test-only dependency
|
|
6
6
|
// eslint-disable-next-line n/no-unpublished-require
|
|
7
|
-
const FixturifyProject = require('fixturify-project');
|
|
7
|
+
const { Project: FixturifyProject } = require('fixturify-project');
|
|
8
8
|
const Project = require('../../lib/models/project');
|
|
9
9
|
const MockCLI = require('./mock-cli');
|
|
10
|
+
const { readFile } = require('fs/promises');
|
|
10
11
|
|
|
11
12
|
// used in these tests to ensure we are only
|
|
12
13
|
// operating on the addons added here
|
|
@@ -45,22 +46,9 @@ function getOptionsObjectWithCallbackFunction(defaultOptions, optionsOrCallback)
|
|
|
45
46
|
);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
// Essentially a copy of the function in node-fixturify-project, converted from TS to JS.
|
|
49
|
-
// We need this for use during toJSON().
|
|
50
|
-
function parseScoped(name) {
|
|
51
|
-
let matched = name.match(/(@[^@/]+)\/(.*)/);
|
|
52
|
-
if (matched) {
|
|
53
|
-
return {
|
|
54
|
-
scope: matched[1],
|
|
55
|
-
name: matched[2],
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
49
|
module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
62
|
-
|
|
63
|
-
super.
|
|
50
|
+
async write() {
|
|
51
|
+
await super.write(...arguments);
|
|
64
52
|
this._hasWritten = true;
|
|
65
53
|
}
|
|
66
54
|
|
|
@@ -68,26 +56,24 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
68
56
|
merge(this.files, filesObj);
|
|
69
57
|
}
|
|
70
58
|
|
|
71
|
-
buildProjectModel(ProjectClass = ProjectWithoutInternalAddons) {
|
|
59
|
+
async buildProjectModel(ProjectClass = ProjectWithoutInternalAddons) {
|
|
72
60
|
if (!this._hasWritten) {
|
|
73
|
-
this.
|
|
61
|
+
await this.write();
|
|
74
62
|
}
|
|
75
63
|
|
|
76
|
-
let pkg = JSON.parse(this.toJSON('package.json'));
|
|
77
64
|
let cli = new MockCLI();
|
|
78
|
-
let root = path.join(this.root, this.name);
|
|
79
65
|
|
|
80
|
-
return new ProjectClass(
|
|
66
|
+
return new ProjectClass(this.baseDir, this.pkg, cli.ui, cli);
|
|
81
67
|
}
|
|
82
68
|
|
|
83
|
-
buildProjectModelForInRepoAddon(addonName, ProjectClass = ProjectWithoutInternalAddons) {
|
|
69
|
+
async buildProjectModelForInRepoAddon(addonName, ProjectClass = ProjectWithoutInternalAddons) {
|
|
84
70
|
if (!this._hasWritten) {
|
|
85
|
-
this.
|
|
71
|
+
await this.write();
|
|
86
72
|
}
|
|
87
73
|
|
|
88
|
-
let
|
|
74
|
+
let root = path.join(this.baseDir, 'lib', addonName);
|
|
75
|
+
let pkg = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
|
89
76
|
let cli = new MockCLI();
|
|
90
|
-
let root = path.join(this.root, this.name, 'lib', addonName);
|
|
91
77
|
|
|
92
78
|
return new ProjectClass(root, pkg, cli.ui, cli);
|
|
93
79
|
}
|
|
@@ -105,31 +91,7 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
105
91
|
*/
|
|
106
92
|
addDependency(name, version, optionsOrCallback) {
|
|
107
93
|
const options = getOptionsObjectWithCallbackFunction(optionsOrCallback);
|
|
108
|
-
return super.addDependency(name, version, options.callback);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Add a 'reference' entry to this object's `dependencies` list. A 'reference' dependency is
|
|
113
|
-
* an entry in `dependencies` where the caller knows the dependency's source files are being
|
|
114
|
-
* created elsewhere in the project tree, so no source files should be created locally in
|
|
115
|
-
* `node_modules`, which is the standard FixturifyProject (and node-fixturify-project) behavior.
|
|
116
|
-
* We do this by adding the necessary reference to `dependencies` during `toJSON`.
|
|
117
|
-
*
|
|
118
|
-
* This is used when two addons wish to share a single definition on disk for a dependency (various parts of
|
|
119
|
-
* ember-cli optimize processing based on paths on disk.)
|
|
120
|
-
*
|
|
121
|
-
* Because there is no FixturifyProject being created, no callback is given as in other methods.
|
|
122
|
-
*
|
|
123
|
-
* @param {String} name name of the dependency
|
|
124
|
-
* @param {String} version version of the dependency, defaults to '*'. For our purposes, '*' means
|
|
125
|
-
* "whatever version was specified elsewhere."
|
|
126
|
-
*/
|
|
127
|
-
addReferenceDependency(name, version = '*') {
|
|
128
|
-
if (!this._referenceDependencies) {
|
|
129
|
-
this._referenceDependencies = {};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this._referenceDependencies[name] = version;
|
|
94
|
+
return super.addDependency(new this.constructor(name, version), options.callback);
|
|
133
95
|
}
|
|
134
96
|
|
|
135
97
|
/**
|
|
@@ -148,30 +110,6 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
148
110
|
return super.addDevDependency(name, version, options.callback);
|
|
149
111
|
}
|
|
150
112
|
|
|
151
|
-
/**
|
|
152
|
-
* Add a 'reference' entry to this object's `devDependencies` list. A 'reference' devDependency is
|
|
153
|
-
* an entry in `devDependencies` where the caller knows the dependency's source files are being
|
|
154
|
-
* created elsewhere in the project tree, so no source files should be created locally in
|
|
155
|
-
* `node_modules`, which is the standard FixturifyProject (and node-fixturify-project) behavior.
|
|
156
|
-
* We do this by adding the necessary reference to `devDependencies` during `toJSON`.
|
|
157
|
-
*
|
|
158
|
-
* This is used when two addons wish to share a single definition on disk for a devDependency
|
|
159
|
-
* (various parts of ember-cli optimize processing based on paths on disk.)
|
|
160
|
-
*
|
|
161
|
-
* Because there is no FixturifyProject being created, no callback is given as in other methods.
|
|
162
|
-
*
|
|
163
|
-
* @param {String} name name of the devDependency
|
|
164
|
-
* @param {String} version version of the devDependency, defaults to '*'. For our purposes, '*' means
|
|
165
|
-
* "whatever version was specified elsewhere."
|
|
166
|
-
*/
|
|
167
|
-
addReferenceDevDependency(name, version = '*') {
|
|
168
|
-
if (!this._referenceDevDependencies) {
|
|
169
|
-
this._referenceDevDependencies = {};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
this._referenceDevDependencies[name] = version;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
113
|
/**
|
|
176
114
|
* Add an addon to this object's `dependencies` list. The addon files will be written in
|
|
177
115
|
* this object's `node_modules/<addon_name>` directory when this object is written out.
|
|
@@ -274,15 +212,22 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
274
212
|
* a callback function while also specifying other properties.)
|
|
275
213
|
* @returns {FixturifyProject} the newly-created addon
|
|
276
214
|
*/
|
|
277
|
-
addInRepoAddon(name, version = '0.0.0', optionsOrCallback) {
|
|
215
|
+
async addInRepoAddon(name, version = '0.0.0', optionsOrCallback) {
|
|
278
216
|
const options = getOptionsObjectWithCallbackFunction({ allowCachingPerBundle: false }, optionsOrCallback);
|
|
279
217
|
|
|
280
|
-
|
|
281
|
-
prepareAddon(addon, options);
|
|
218
|
+
let inRepoAddon;
|
|
282
219
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
220
|
+
await new Promise((resolve) => {
|
|
221
|
+
inRepoAddon = new EmberCLIFixturifyProject(name, version, async (addon) => {
|
|
222
|
+
prepareAddon(addon, options);
|
|
223
|
+
|
|
224
|
+
if (typeof options.callback === 'function') {
|
|
225
|
+
await options.callback(addon);
|
|
226
|
+
resolve();
|
|
227
|
+
} else {
|
|
228
|
+
resolve();
|
|
229
|
+
}
|
|
230
|
+
});
|
|
286
231
|
});
|
|
287
232
|
|
|
288
233
|
// configure the current project to have an ember-addon configured at the
|
|
@@ -301,10 +246,9 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
301
246
|
|
|
302
247
|
addon.paths.push(addonPath);
|
|
303
248
|
|
|
304
|
-
|
|
249
|
+
inRepoAddon.baseDir = path.join(this.baseDir, addonRootDir, inRepoAddon.pkg.name);
|
|
305
250
|
|
|
306
|
-
|
|
307
|
-
Object.assign(this.files[addonRootDir], addonJSON);
|
|
251
|
+
await inRepoAddon.write();
|
|
308
252
|
return inRepoAddon;
|
|
309
253
|
}
|
|
310
254
|
|
|
@@ -322,12 +266,12 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
322
266
|
* @returns {FixturifyProject} the newly-created addon
|
|
323
267
|
*/
|
|
324
268
|
addInRepoEngine(name, version = '0.0.0', options = { allowCachingPerBundle: false, enableLazyLoading: false }) {
|
|
325
|
-
const callback = (engine) => {
|
|
269
|
+
const callback = async (engine) => {
|
|
326
270
|
engine.pkg.keywords.push('ember-engine');
|
|
327
271
|
|
|
328
272
|
// call original callback if it exists
|
|
329
273
|
if (typeof options.callback === 'function') {
|
|
330
|
-
options.callback(engine);
|
|
274
|
+
await options.callback(engine);
|
|
331
275
|
}
|
|
332
276
|
};
|
|
333
277
|
|
|
@@ -341,56 +285,4 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
|
|
|
341
285
|
|
|
342
286
|
return this.addInRepoAddon(name, version, { ...options, callback });
|
|
343
287
|
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Convert the object into a data structure suitable for passing to `fixturify`.
|
|
347
|
-
*
|
|
348
|
-
* @param {String} key optional key. If specified, the object will be run through toJSON, then the given
|
|
349
|
-
* property extracted and returned.
|
|
350
|
-
* @returns {Object} the `toJSON` value of the object (wrapped) or the toJSON value of the specified field
|
|
351
|
-
* (not wrapped.)
|
|
352
|
-
*/
|
|
353
|
-
toJSON(key) {
|
|
354
|
-
if (key) {
|
|
355
|
-
return super.toJSON(key);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
let jsonData = super.toJSON();
|
|
359
|
-
|
|
360
|
-
let scoped = parseScoped(this.name);
|
|
361
|
-
|
|
362
|
-
// Allowing for scoped names, get the object in the JSON structure that corresponds
|
|
363
|
-
// to this FixturifyProject.
|
|
364
|
-
let container = scoped ? jsonData[scoped.scope][scoped.name] : jsonData[this.name];
|
|
365
|
-
|
|
366
|
-
if (this._referenceDependencies || this._referenceDevDependencies) {
|
|
367
|
-
let pkg = JSON.parse(container['package.json']);
|
|
368
|
-
|
|
369
|
-
if (this._referenceDependencies) {
|
|
370
|
-
if (!pkg.dependencies) {
|
|
371
|
-
pkg.dependencies = {};
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
Object.assign(pkg.dependencies, this._referenceDependencies);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
if (this._referenceDevDependencies) {
|
|
378
|
-
if (!pkg.devDependencies) {
|
|
379
|
-
pkg.devDependencies = {};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
Object.assign(pkg.devDependencies, this._referenceDevDependencies);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
container['package.json'] = JSON.stringify(pkg, undefined, 2);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// an optimization to remove any node_modules declaration that has nothing in it,
|
|
389
|
-
// to avoid creating extra directories for no reason.
|
|
390
|
-
if (container['node_modules'] && Object.keys(container['node_modules']).length === 0) {
|
|
391
|
-
delete container['node_modules'];
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return jsonData;
|
|
395
|
-
}
|
|
396
288
|
};
|