Skip to content

Commit 060dbbf

Browse files
author
Kelly Selden
committed
add blueprint initialization and addon installation
1 parent 1994814 commit 060dbbf

40 files changed

Lines changed: 972 additions & 24 deletions

bin/commands/init.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
const args = require('../../src/args');
4+
const init = require('../../src/init');
5+
6+
module.exports.command = 'init';
7+
8+
module.exports.describe = 'initialize a blueprint';
9+
10+
module.exports.builder = {
11+
blueprint: args['blueprint'],
12+
to: args['to'],
13+
resolveConflicts: args['resolve-conflicts'],
14+
reset: args['reset']
15+
};
16+
17+
module.exports.handler = async function handler(argv) {
18+
let blueprint = argv['blueprint'];
19+
let to = argv['to'];
20+
let resolveConflicts = argv['resolve-conflicts'];
21+
let reset = argv['reset'];
22+
23+
try {
24+
let message = await init({
25+
blueprint,
26+
to,
27+
resolveConflicts,
28+
reset,
29+
wasRunAsExecutable: true
30+
});
31+
if (message) {
32+
console.log(message);
33+
}
34+
} catch (err) {
35+
console.error(err);
36+
}
37+
};

bin/commands/install.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
const install = require('../../src/install');
4+
5+
module.exports.command = 'install <addon>';
6+
7+
module.exports.describe = 'install an addon';
8+
9+
module.exports.handler = async function handler(argv) {
10+
let addon = argv['addon'];
11+
12+
try {
13+
let message = await install({
14+
addon
15+
});
16+
if (message) {
17+
console.log(message);
18+
}
19+
} catch (err) {
20+
console.error(err);
21+
}
22+
};

src/get-project-options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module.exports = async function getProjectOptions({
3030
dependencies,
3131
devDependencies
3232
}, blueprint) {
33-
if (blueprint.name !== 'ember-cli') {
33+
if (blueprint && blueprint.name !== 'ember-cli') {
3434
return ['blueprint'];
3535
}
3636

src/get-start-and-end-commands.js

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const path = require('path');
44
const fs = require('fs-extra');
5+
const run = require('./run');
56
const utils = require('./utils');
67

78
const nodeModulesIgnore = `
@@ -23,7 +24,7 @@ module.exports = function getStartAndEndCommands({
2324
options += ' --yarn';
2425
}
2526

26-
if (!projectOptions.includes('welcome') && !projectOptions.includes('blueprint')) {
27+
if (!projectOptions.includes('welcome') && startBlueprint && startBlueprint.name === 'ember-cli') {
2728
options += ' --no-welcome';
2829
}
2930

@@ -40,14 +41,14 @@ module.exports = function getStartAndEndCommands({
4041
return {
4142
projectName,
4243
projectOptions,
43-
...projectOptions.includes('blueprint') ? {} : {
44+
...endBlueprint.name === 'ember-cli' ? {
4445
packageName: 'ember-cli',
4546
commandName: 'ember',
4647
// `createProjectFromCache` no longer works with custom blueprints.
4748
// It would look for an `ember-cli` version with the same version
4849
// as the blueprint.
4950
createProjectFromCache: createProjectFromCache(command)
50-
},
51+
} : {},
5152
createProjectFromRemote: createProjectFromRemote(command),
5253
startOptions: {
5354
packageVersion: startVersion,
@@ -86,16 +87,36 @@ function createProjectFromRemote(command) {
8687
options
8788
}) {
8889
return async function createProject(cwd) {
89-
if (options.blueprint.name !== 'ember-cli') {
90-
await utils.npx(`ember-cli ${command} -b ${options.blueprint.path}`, { cwd });
91-
// await utils.npx(`-p github:ember-cli/ember-cli#cfb9780 ember ${command} -b ${options.blueprint.name}@${options.packageVersion}`, { cwd });
92-
93-
await module.exports.appendNodeModulesIgnore({
90+
if (options.blueprint) {
91+
if (options.blueprint.name !== 'ember-cli') {
92+
await utils.npx(`ember-cli ${command} -b ${options.blueprint.path}`, { cwd });
93+
// await utils.npx(`-p github:ember-cli/ember-cli#cfb9780 ember ${command} -b ${options.blueprint.name}@${options.packageVersion}`, { cwd });
94+
95+
// This means it's not a full app blueprint, but a default blueprint of an addon.
96+
// There may be a faster way to detect this.
97+
let files = await utils.readdir(path.join(cwd, options.projectName));
98+
if (!files.length) {
99+
await module.exports.installAddonBlueprint({
100+
cwd,
101+
projectName: options.projectName,
102+
command,
103+
blueprintPath: options.blueprint.path
104+
});
105+
}
106+
107+
await module.exports.appendNodeModulesIgnore({
108+
cwd,
109+
projectName: options.projectName
110+
});
111+
} else {
112+
await utils.npx(`-p ember-cli@${options.packageVersion} ember ${command}`, { cwd });
113+
}
114+
} else {
115+
// We are doing a blueprint init, and need an empty first commit.
116+
await module.exports.createEmptyCommit({
94117
cwd,
95118
projectName: options.projectName
96119
});
97-
} else {
98-
await utils.npx(`-p ember-cli@${options.packageVersion} ember ${command}`, { cwd });
99120
}
100121

101122
return postCreateProject({
@@ -115,6 +136,35 @@ function postCreateProject({
115136
return path.join(cwd, projectName);
116137
}
117138

139+
module.exports.installAddonBlueprint = async function installAddonBlueprint({
140+
cwd,
141+
projectName,
142+
command,
143+
blueprintPath
144+
}) {
145+
await fs.remove(path.join(cwd, projectName));
146+
147+
await utils.npx(`ember-cli ${command}`, { cwd });
148+
149+
await run('npm install', { cwd: path.join(cwd, projectName) });
150+
151+
await utils.npx(`--no-install ember install ${blueprintPath}`, { cwd: path.join(cwd, projectName) });
152+
153+
await fs.remove(path.join(cwd, projectName, 'package-lock.json'));
154+
};
155+
156+
module.exports.createEmptyCommit = async function createEmptyCommit({
157+
cwd,
158+
projectName
159+
}) {
160+
await fs.mkdir(path.join(cwd, projectName));
161+
await fs.writeFile(path.join(cwd, projectName, 'package.json'), '{}');
162+
await appendNodeModulesIgnore({
163+
cwd,
164+
projectName
165+
});
166+
};
167+
118168
async function appendNodeModulesIgnore({
119169
cwd,
120170
projectName

src/index.js

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ const boilerplateUpdate = require('boilerplate-update');
1313
const getStartAndEndCommands = require('./get-start-and-end-commands');
1414
const parseBlueprint = require('./parse-blueprint');
1515
const downloadBlueprint = require('./download-blueprint');
16+
const loadBlueprintFile = require('./load-blueprint-file');
1617
const loadSafeBlueprintFile = require('./load-safe-blueprint-file');
1718
const saveBlueprint = require('./save-blueprint');
19+
const saveDefaultBlueprint = require('./save-default-blueprint');
1820

1921
module.exports = async function emberCliUpdate({
2022
blueprint: _blueprint,
@@ -35,20 +37,31 @@ module.exports = async function emberCliUpdate({
3537

3638
let cwd = process.cwd();
3739

40+
let emberCliUpdateJson = await loadSafeBlueprintFile(cwd);
41+
3842
let blueprint;
3943

4044
if (_blueprint) {
41-
if (!from) {
42-
throw new Error('A custom blueprint cannot detect --from. You must supply it.');
45+
blueprint = await parseBlueprint(_blueprint);
46+
47+
if (from) {
48+
blueprint.version = from;
49+
} else {
50+
let { blueprints } = emberCliUpdateJson;
51+
let existingBlueprint = blueprints.find(b => b.name === _blueprint);
52+
if (existingBlueprint) {
53+
blueprint.location = existingBlueprint.location;
54+
blueprint.version = existingBlueprint.version;
55+
}
4356
}
4457

45-
blueprint = await parseBlueprint(_blueprint);
46-
blueprint.version = from;
58+
if (!blueprint.version) {
59+
throw new Error('A custom blueprint cannot detect --from. You must supply it.');
60+
}
4761
} else {
48-
let { blueprints } = await loadSafeBlueprintFile(cwd);
62+
let { blueprints } = emberCliUpdateJson;
4963

50-
let completeBlueprints = blueprints.filter(blueprint => !blueprint.isPartial);
51-
if (!completeBlueprints.length) {
64+
if (!blueprints.length) {
5265
blueprints.splice(0, 0, defaultBlueprint);
5366
}
5467

@@ -64,10 +77,10 @@ module.exports = async function emberCliUpdate({
6477
} else {
6578
blueprint = blueprints[0];
6679
}
80+
}
6781

68-
if (blueprint.location) {
69-
blueprint.url = (await parseBlueprint(blueprint.location)).url;
70-
}
82+
if (blueprint && !blueprint.url && blueprint.location) {
83+
blueprint.url = (await parseBlueprint(blueprint.location)).url;
7184
}
7285

7386
let isCustomBlueprint = blueprint.name !== defaultBlueprint.name;
@@ -146,18 +159,38 @@ module.exports = async function emberCliUpdate({
146159
wasRunAsExecutable
147160
})).promise;
148161

149-
let { blueprints } = await loadSafeBlueprintFile(cwd);
162+
if (_blueprint) {
163+
let emberCliUpdateJson = await loadBlueprintFile(cwd);
150164

151-
let existingBlueprint = blueprints.find(b => b.name === blueprint.name);
165+
if (!emberCliUpdateJson && blueprint.name !== defaultBlueprint.name) {
166+
await saveDefaultBlueprint({
167+
cwd,
168+
defaultBlueprint
169+
});
170+
}
152171

153-
if (existingBlueprint) {
154172
await saveBlueprint({
155173
cwd,
156174
name: blueprint.name,
175+
location: blueprint.location,
157176
version: endVersion
158177
});
159178

160179
await run('git add ember-cli-update.json');
180+
} else {
181+
let { blueprints } = await loadSafeBlueprintFile(cwd);
182+
183+
let existingBlueprint = blueprints.find(b => b.name === blueprint.name);
184+
185+
if (existingBlueprint) {
186+
await saveBlueprint({
187+
cwd,
188+
name: blueprint.name,
189+
version: endVersion
190+
});
191+
192+
await run('git add ember-cli-update.json');
193+
}
161194
}
162195

163196
return result;

src/init.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
const run = require('./run');
4+
const getRemoteUrl = require('./get-remote-url');
5+
const boilerplateUpdate = require('boilerplate-update');
6+
const getStartAndEndCommands = require('./get-start-and-end-commands');
7+
const parseBlueprint = require('./parse-blueprint');
8+
const downloadBlueprint = require('./download-blueprint');
9+
const saveBlueprint = require('./save-blueprint');
10+
11+
module.exports = async function init({
12+
blueprint,
13+
to,
14+
resolveConflicts,
15+
reset,
16+
wasRunAsExecutable
17+
}) {
18+
let defaultBlueprint = {
19+
name: 'ember-cli'
20+
};
21+
22+
let cwd = process.cwd();
23+
24+
let parsedBlueprint;
25+
if (blueprint) {
26+
parsedBlueprint = await parseBlueprint(blueprint);
27+
} else {
28+
parsedBlueprint = defaultBlueprint;
29+
}
30+
parseBlueprint.version = to;
31+
32+
let downloadedBlueprint = await downloadBlueprint(parsedBlueprint.name, parsedBlueprint.url, parseBlueprint.version);
33+
34+
let result = await (await boilerplateUpdate({
35+
projectOptions: ['blueprint'],
36+
remoteUrl: ({ projectOptions }) => getRemoteUrl(projectOptions),
37+
endVersion: downloadedBlueprint.version,
38+
resolveConflicts,
39+
reset,
40+
createCustomDiff: true,
41+
customDiffOptions: ({
42+
packageJson,
43+
projectOptions,
44+
endVersion
45+
}) => getStartAndEndCommands({
46+
packageJson,
47+
projectOptions,
48+
endVersion,
49+
endBlueprint: downloadedBlueprint
50+
}),
51+
ignoredFiles: ['ember-cli-update.json'],
52+
wasRunAsExecutable
53+
})).promise;
54+
55+
await saveBlueprint({
56+
cwd,
57+
name: downloadedBlueprint.name,
58+
location: parsedBlueprint.location,
59+
version: downloadedBlueprint.version
60+
});
61+
62+
await run('git add ember-cli-update.json');
63+
64+
return result;
65+
};

src/install.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
const utils = require('./utils');
4+
const parseBlueprint = require('./parse-blueprint');
5+
const downloadBlueprint = require('./download-blueprint');
6+
const saveBlueprint = require('./save-blueprint');
7+
const loadBlueprintFile = require('./load-blueprint-file');
8+
const saveDefaultBlueprint = require('./save-default-blueprint');
9+
10+
const toDefault = require('./args').to.default;
11+
12+
module.exports = async function install({
13+
addon
14+
}) {
15+
let defaultBlueprint = {
16+
name: 'ember-cli'
17+
};
18+
19+
let cwd = process.cwd();
20+
21+
await utils.npx(`--no-install ember install ${addon}`);
22+
23+
let parsedBlueprint = await parseBlueprint(addon);
24+
let downloadedBlueprint = await downloadBlueprint(parsedBlueprint.name, parsedBlueprint.url, toDefault);
25+
26+
let emberCliUpdateJson = await loadBlueprintFile(cwd);
27+
28+
if (!emberCliUpdateJson && downloadedBlueprint.name !== defaultBlueprint.name) {
29+
await saveDefaultBlueprint({
30+
cwd,
31+
defaultBlueprint
32+
});
33+
}
34+
35+
await saveBlueprint({
36+
cwd,
37+
name: downloadedBlueprint.name,
38+
location: parsedBlueprint.location,
39+
version: downloadedBlueprint.version
40+
// isPartial: true
41+
});
42+
};

0 commit comments

Comments
 (0)