Skip to content
Closed
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
48 changes: 42 additions & 6 deletions packages/pine/src/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,62 @@ export const validTaskValue = (val: any) => {
);
};

/**
* Bind `this` for task functions to parent object.
*
* @param {object} obj
* @param {function} fn
*
* @returns {object|boolean}
*/
const bindTask = (obj: PineFile, task: any): PineFile | boolean => {
if (!validTaskValue(task)) {
return false;
}

if (!isObject(task) || !task._) {
return { ...task, default: bindTask(task, task.default) };
}

return {
...task,
_: task._.bind(
new Proxy(obj, {
get(target: PineFile, handler: string) {
if (
isObject(target[handler]) &&
typeof target[handler]._ === 'function'
) {
return target[handler]._;
}
},
})
),
};
};

/**
* Resolve task function by name.
*
* @param {string} obj
* @param {object} obj
* @param {string} key
* @param {string} sep
*
* @returns {function|boolean}
* @returns {function|object|boolean}
*/
export const resolveTask = (obj: PineFile, key: string, sep = ':'): any => {
if (!key) {
return false;
}

const properties = (Array.isArray(key) ? key : key.split(sep)) as string[];
const task = properties.reduce((prev: any[], cur: string) => {
return prev[cur] || false;
}, obj as any) as any;
const task = properties.reduce<PineFile>(
(prev: PineFile, cur: string) =>
(bindTask(prev, prev[cur]) || {}) as PineFile,
obj
);

if (!isObject(task) && !validTaskValue(task)) {
if (!validTaskValue(task)) {
return false;
}

Expand Down
51 changes: 48 additions & 3 deletions packages/pine/test/task.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,29 @@ describe('task', () => {
i: () => true,
},
j: {
_: () => true,
default: () => true,
},
m: {
n: () => true,
default() {
return this.n();
},
o: {
p() {
return true;
},
q() {
return this.p();
},
},
},
r: {
s() {
return true;
},
t() {
return this.t();
},
},
});

Expand Down Expand Up @@ -48,7 +70,7 @@ describe('task', () => {
},
{
input: 'j',
type: 'function',
type: 'object',
output: true,
},
{
Expand All @@ -61,6 +83,26 @@ describe('task', () => {
type: 'boolean',
output: false,
},
{
input: 'm',
type: 'object',
output: true,
},
{
input: 'm:n',
type: 'function',
output: true,
},
{
input: 'm:o:q',
type: 'function',
output: true,
},
{
input: 'r:s',
type: 'function',
output: true,
},
{
input: undefined,
type: 'boolean',
Expand All @@ -71,7 +113,10 @@ describe('task', () => {
tests.forEach((test) => {
const output = resolveTask(tasks, test.input as any);
expect(typeof output).toBe(test.type);
expect(output ? output() : output).toBe(test.output);

const fn =
typeof output === 'object' && output.default ? output.default : output;
expect(typeof fn === 'function' ? fn() : output).toBe(test.output);
});
});

Expand Down