Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add inheritTasks to features #1523

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions src/actions/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,26 @@ export abstract class TasksMixin {
}
}

/**
* Get task sources property descriptors.
*/
getTaskSourcesPropertyDescriptors(this: BaseGeneratorImpl): any {
if (this.features.inheritTasks) {
const queueNames = Object.keys(this._queues);
let currentPrototype = Object.getPrototypeOf(this);
let propertyDescriptors = [];
while (currentPrototype) {
propertyDescriptors.unshift(...Object.entries(Object.getOwnPropertyDescriptors(currentPrototype)));
currentPrototype = Object.getPrototypeOf(currentPrototype);
}

propertyDescriptors = propertyDescriptors.filter(([name]) => queueNames.includes(name));
return Object.fromEntries(propertyDescriptors);
}

return Object.getOwnPropertyDescriptors(Object.getPrototypeOf(this));
}

/**
* Extract tasks from a priority.
*
Expand All @@ -161,10 +181,10 @@ export abstract class TasksMixin {

const { taskPrefix = this.features.taskPrefix ?? '' } = taskOptions;
const propertyName = `${taskPrefix}${name}`;
const property = Object.getOwnPropertyDescriptor(
taskOptions.taskOrigin || Object.getPrototypeOf(this),
propertyName,
);
const property = taskOptions.taskOrigin
? Object.getOwnPropertyDescriptor(taskOptions.taskOrigin, propertyName)
: this.getTaskSourcesPropertyDescriptors()[propertyName];

if (!property) return [];

const item: Task['method'] = property.value ?? property.get?.call(this);
Expand Down Expand Up @@ -218,7 +238,7 @@ export abstract class TasksMixin {
* Get task names.
*/
getTaskNames(this: BaseGeneratorImpl): string[] {
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
const methods = Object.keys(this.getTaskSourcesPropertyDescriptors());
let validMethods = methods.filter(method => methodIsValid(method));
const { taskPrefix } = this.features;

Expand Down
3 changes: 3 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ export type BaseFeatures = FeaturesApi & {

/** Custom priorities for more fine tuned workflows. */
customPriorities?: Priority[];

/** Inherit tasks from parent prototypes, implies tasksMatchingPriority */
inheritTasks?: boolean;
};

export type BaseOptions = OptionsApi & {
Expand Down
63 changes: 51 additions & 12 deletions test/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1889,18 +1889,21 @@ describe('Base', () => {
describe('getTaskNames', () => {
class TestGen extends Base {
constructor(args, options, features) {
const customPriorities = [{ priorityName: 'customPriority', before: 'prompting' }];
super(
args,
{
...options,
customPriorities: [
{
priorityName: 'customPriority',
before: 'prompting',
Array.isArray(args)
? options
: {
...options,
customPriorities,
},
],
},
features,
Array.isArray(args)
? {
...features,
customPriorities,
}
: features,
);
}

Expand All @@ -1920,12 +1923,48 @@ describe('Base', () => {
assert.deepStrictEqual(gen.getTaskNames(), ['anyMethod', 'default', 'customPriority']);
});

it('should return any public member when tasksMatchingPriority is true', async function () {
const Gen = helpers.createDummyGenerator(TestGen, {
it('should return any public member when tasksMatchingPriority is false', async function () {
const Gen = helpers.createDummyGenerator(class extends TestGen {}, {
default() {},
customPriority() {},
otherMethod() {},
});
assert.deepStrictEqual(new Gen({ env }).getTaskNames(), ['default', 'customPriority']);
assert.deepStrictEqual(new Gen({ env }).getTaskNames(), ['default', 'customPriority', 'otherMethod']);
});

it('should return only priorities tasks when tasksMatchingPriority is true', async function () {
const Gen = class extends TestGen {
constructor(args, options, features) {
super(args, options, { ...features, tasksMatchingPriority: true });
}

default() {}

customPriority() {}

otherMethod() {}
};

assert.deepStrictEqual(new Gen([], { env }).getTaskNames(), ['default', 'customPriority']);
});

it('should return only inherited tasks when inheritTasks is true', async function () {
const Gen = class extends TestGen {
constructor(args, options, features) {
super(args, options, { ...features, inheritTasks: true });
}

default() {}

initializing() {}
};

const gen = new Gen([], { env });
assert.deepStrictEqual(gen.getTaskNames(), ['default', 'customPriority', 'initializing']);
assert.strictEqual(
gen.getTaskSourcesPropertyDescriptors().default.value,
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(gen), 'default')!.value,
);
});
});
});
Loading