Skip to content

Commit

Permalink
Merge 266e6e2 into 26b85bd
Browse files Browse the repository at this point in the history
  • Loading branch information
mshima committed Jan 22, 2020
2 parents 26b85bd + 266e6e2 commit 565f65e
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 1 deletion.
103 changes: 102 additions & 1 deletion lib/index.js
Expand Up @@ -14,6 +14,8 @@ const runAsync = require('run-async');
const through = require('through2');
const FileEditor = require('mem-fs-editor');
const debug = require('debug')('yeoman:generator');
const SubQueue = require('grouped-queue/lib/subqueue');

const Conflicter = require('./util/conflicter');
const Storage = require('./util/storage');
const promptSuggestion = require('./util/prompt-suggestion');
Expand Down Expand Up @@ -61,6 +63,19 @@ const methodIsValid = function(name) {
* };
*/
class Generator extends EventEmitter {
static get queues() {
return [
'initializing',
'prompting',
'configuring',
'default',
'writing',
'conflicts',
'install',
'end'
];
}

constructor(args, options) {
super();

Expand Down Expand Up @@ -161,6 +176,92 @@ class Generator extends EventEmitter {

// Ensure source/destination path, can be configured from subclasses
this.sourceRoot(path.join(path.dirname(this.resolved), 'templates'));

// Queues map: generator's queue name => grouped-queue's queue name (custom name)
this._queues = {};

// Add original queues.
Generator.queues.forEach(queue => {
this._queues[queue] = queue;
});

// Add custom queues
if (Array.isArray(this.options.customQueues)) {
const customQueues = this.options.customQueues;

// Sort customQueues, a referenced custom queue must be added before the one that reference it.
customQueues.sort((a, b) => {
if (a.name === b.before) {
return -1;
}

if (b.name === a.before) {
return 1;
}

return 0;
});

// Register at _queues and calculate options
customQueues.forEach(customQueue => {
if (this._queues[customQueue.name]) {
// Queue already registered
return;
}

const queueName = `${this.options.namespace}#${customQueue.name}`;
debug(`Registering custom queue ${queueName}`);
this._queues[customQueue.name] = queueName;
customQueue.queueName = queueName;
customQueue.beforeQueue = this._queues[customQueue.before];
});

// Add queue to runLoop
customQueues.forEach(customQueue => {
const queueName = customQueue.queueName;
if (this.env.runLoop.queueNames.includes(queueName)) {
return;
}

// Backwards compatibilitiy with grouped-queue < 1.0.0
if (!this.env.runLoop.addSubQueue) {
this.env.runLoop.addSubQueue = function(name, before) {
if (this.__queues__[name]) {
// Sub-queue already exists
return;
}

if (!before) {
// Add at last place.
this.__queues__[name] = new SubQueue();
this.queueNames.push(name);
return;
}

if (!this.__queues__[before] || _.indexOf(this.queueNames, before) === -1) {
throw new Error('sub-queue ' + before + ' not found');
}

const current = this.__queues__;
const currentNames = Object.keys(current);
// Recreate the queue with new order.
this.__queues__ = {};
currentNames.forEach(currentName => {
if (currentName === before) {
this.__queues__[name] = new SubQueue();
}

this.__queues__[currentName] = current[currentName];
});

// Recreate queueNames
this.queueNames = Object.keys(this.__queues__);
};
}

this.env.runLoop.addSubQueue(queueName, customQueue.beforeQueue);
});
}
}

/*
Expand Down Expand Up @@ -494,7 +595,7 @@ class Generator extends EventEmitter {
);
const item = property.value ? property.value : property.get.call(self);

const queueName = self.env.runLoop.queueNames.indexOf(name) === -1 ? null : name;
const queueName = self._queues[name];

// Name points to a function; run it!
if (typeof item === 'function') {
Expand Down
99 changes: 99 additions & 0 deletions test/base.js
Expand Up @@ -1241,4 +1241,103 @@ describe('Base', () => {
});
});
});

describe('Custom queues', () => {
beforeEach(function() {
this.TestGenerator = class extends Base {
constructor(args, options) {
super(args, {
...options,
customQueues: [
{
name: 'prePrompting1',
before: 'prompting'
},
{
name: 'preConfiguring1',
before: 'preConfiguring2'
},
{
name: 'preConfiguring2',
before: 'configuring'
},
{
name: 'afterEnd'
}
]
});
}
};
});

it('run custom queues in correct order', function() {
const prePrompting1 = sinon.spy();
const preConfiguring1 = sinon.spy();
const preConfiguring2 = sinon.spy();
const afterEnd = sinon.spy();

const initializing = sinon.spy();
const prompting = sinon.spy();
const configuring = sinon.spy();
const end = sinon.spy();

_.extend(this.TestGenerator.prototype, {
prePrompting1,
preConfiguring1,
preConfiguring2,
afterEnd,
initializing,
prompting,
configuring,
end,
assert: function() {
assert.deepStrictEqual(this._queues, {
initializing: 'initializing',
prePrompting1: 'dummy#prePrompting1',
prompting: 'prompting',
preConfiguring1: 'dummy#preConfiguring1',
preConfiguring2: 'dummy#preConfiguring2',
configuring: 'configuring',
default: 'default',
writing: 'writing',
conflicts: 'conflicts',
install: 'install',
end: 'end',
afterEnd: 'dummy#afterEnd'
});
assert.deepStrictEqual(this.env.runLoop.queueNames, [
'initializing',
'dummy#prePrompting1',
'prompting',
'dummy#preConfiguring1',
'dummy#preConfiguring2',
'configuring',
'default',
'writing',
'conflicts',
'install',
'end',
'dummy#afterEnd'
]);
}
});

this.testGen = new this.TestGenerator([], {
resolved: 'generator-ember/all/index.js',
namespace: 'dummy',
env: this.env,
'skip-install': true
});

return this.testGen.run().then(() => {
initializing.calledBefore(prePrompting1);
prePrompting1.calledBefore(prompting);
prompting.calledBefore(preConfiguring1);
preConfiguring1.calledBefore(preConfiguring2);
preConfiguring2.calledBefore(configuring);
configuring.calledBefore(end);
end.calledBefore(afterEnd);
});
});
});
});

0 comments on commit 565f65e

Please sign in to comment.