Repository: cmseaton42/task-easy
Branch: master
Commit: b960a6f10535
Files: 12
Total size: 22.9 KB
Directory structure:
gitextract_wedwjsnx/
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
└── src/
├── __snapshots__/
│ └── task-easy.spec.js.snap
├── index.d.ts
├── index.js
└── task-easy.spec.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintignore
================================================
node_modules/**
coverage/**
scripts/**
================================================
FILE: .eslintrc.js
================================================
module.exports = {
env: {
"jest/globals": true,
es6: true,
node: true
},
extends: ["eslint:recommended"],
parserOptions: {
ecmaVersion: 8,
sourceType: "module",
ecmaFeatures: {
jsx: true,
experimentalObjectRestSpread: true
}
},
rules: {
indent: ["error", 4],
"no-console": 0,
quotes: ["error", "double"],
semi: ["error", "always"],
"jest/no-disabled-tests": "warn",
"jest/no-focused-tests": "error",
"jest/no-identical-title": "error",
"jest/prefer-to-have-length": "warn",
"jest/valid-expect": "error"
},
plugins: ["jest"]
};
================================================
FILE: .gitignore
================================================
/node_modules/
# Ignore Jest Coverage Reports
/coverage
/assets
================================================
FILE: .npmignore
================================================
**/*.spec.js
/coverage
/assets
**/__snapshots__
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "node"
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/7cce00f2d081132a34c2
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always
================================================
FILE: LICENSE
================================================
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center"><img width="280" src="https://i.imgur.com/VwF0DyE.png" alt="Task Easy Logo"></p>
<div align="center">
<p><a href="https://www.npmjs.com/package/task-easy"><img src="https://img.shields.io/npm/v/task-easy.svg?style=flat-square" alt="npm" /></a>
<a href="https://github.com/cmseaton42/task-easy/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cmseaton42/task-easy.svg?style=flat-square" alt="license" /></a>
<img src="https://img.shields.io/travis/cmseaton42/task-easy.svg?style=flat-square" alt="Travis" />
<img src="https://img.shields.io/coveralls/github/cmseaton42/task-easy.svg?style=flat-square" alt="Coveralls github" />
<a href="https://github.com/cmseaton42/task-easy"><img src="https://img.shields.io/github/stars/cmseaton42/task-easy.svg?&style=social&logo=github&label=Stars" alt="GitHub stars" /></a>
</p>
</div>
# Task Easy - Promise Queue Made Easy ✅
A simple, customizable, and lightweight priority queue for promise based tasks.
> Now with types!!! Big thanks to [Emiliano Heyns](https://github.com/retorquere) :beers:
>
> - See below example for typescript version
## Getting Started
Install with npm
```
npm install task-easy --save
```
## How it Works
**TaskEasy** is built as an extension of a simple heap data structure. Tasks are queued by simply passing a task (function) to the `.schedule` method along with an array of arguments to be called as well as an object to describe the task's relative priority. The caller is returned a promise which will resolve once the scheduled task has ran. Priority determination is left up to the user via a function that accepts task priority object and returns a judgement.
### Usage
The usage of **TaskEasy** is best given by example so that is the route we will take.
In this example, we will be passing priority objects to the scheduler that will be marked by the following signature.
```js
{
// An integer representing priority,
// the higher the number the higher the priority
priority: Number,
// A timestamp to illustrate when the task
// was scheduled, used as a 'tie-breaker' for
// tasks of the same priority
timestamp: Date
}
```
> **NOTE**
>
> The priority object's signature that you want to queue your items with is 100% up to you. 😄
Now, let's create a function that will receive our priority objects and output a priority judgment so that _TaskEasy_ knows how to handle queued tasks. Our function will be passed two arguments (the priority objects of two scheduled tasks) and return a judgement indicating which task is of _higher_ priority. If we return `true`, then we are communicating to _TaskEasy_ that the first task is higher priority than the second task or vice versa
```js
// This function is passed to the TaskEasy contructor and will be used internally to determine tasks order.
const prioritize = (obj1, obj2) => {
return obj1.priority === obj2.priority
? obj1.timestamp.getTime() < obj2.timestamp.getTime() // Return true if task 1 is older than task 2
: obj1.priority > obj2.priority; // return true if task 1 is higher priority than task 2
};
```
Now, we can initialize a new _TaskEasy_ instance.
```js
const { TaskEasy } = require("task-easy");
const max_tasks = 200; // How many tasks will we allow to be queued at a time (defaults to 100)
const queue = new TaskEasy(prioritize, max_tasks);
```
Now, lets build an async function to demo the scheduler.
```js
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
```
> **NOTE**
>
> Scheduled tasks _MUST_ be functions that return _promises_. This works well with async functions or with ES2017 `ASYNC/AWAIT` functions.
Now, that we have a task to schedule, let's schedule some tasks. The `.schedule` method takes three arguments, the task to call, an array of arguments, and a priority object that is associated with the scheduled task. It will return a promise that will resolve or reject once the task has been ran.
```js
// .schedule accepts the task signature,
// an array or arguments, and a priority object
const task1 = queue
.schedule(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 1 ran..."));
const task2 = queue
.schedule(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 2 ran..."));
const task3 = queue
.schedule(delay, [100], { priority: 2, timestamp: new Date() })
.then(() => console.log("Task 3 ran..."));
const task4 = queue
.schedule(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 4 ran..."));
const task5 = queue
.schedule(delay, [100], { priority: 3, timestamp: new Date() })
.then(() => console.log("Task 5 ran..."));
// OUTPUT
// Task 1 ran...
// Task 5 ran...
// Task 3 ran...
// Task 2 ran...
// Task 4 ran...
```
> **NOTE**
>
> In the above example, `task1` resolved first as it once put onto the queue first and was immediately called as it was the only task on the queue at that time.
## Now with _Typescript_
```typescript
import { TaskEasy } from "task-easy";
// Define interface for priority
// objects to be used in the
// TaskEasy instance
interface IPriority {
priority: number;
timestamp: Date;
}
// Define delay function type
// -> Must extend Task<T>: (...args) => Promise<T>
type delayFn = (ms: number) => Promise<undefined>;
// Define delay function of type 'delayFn' defined above
const delay: delayFn = ms => new Promise(resolve => setTimeout(resolve, ms));
// Define priority function
// -> Must extend (obj1: T, obj2: T) =>
const prioritize = (obj1: IPriority, obj2: IPriority) => {
return obj1.priority === obj2.priority
? obj1.timestamp.getTime() < obj2.timestamp.getTime() // Return true if task 1 is older than task 2
: obj1.priority > obj2.priority; // return true if task 1 is higher priority than task 2
};
// Initialize new queue
const queue = new TaskEasy(prioritize); // equivalent of TaskEasy<IPriority>(prioritize) via type inference
// .schedule accepts the task signature,
// an array or arguments, and a priority object
// -> with type inference
const task1 = queue
.schedule(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 1 ran..."));
const task2 = queue
.schedule(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 2 ran..."));
// Definitely typed
const task3 = queue
.schedule<undefined, delayFn>(delay, [100], { priority: 2, timestamp: new Date() })
.then(() => console.log("Task 3 ran..."));
const task4 = queue
.schedule<undefined, delayFn>(delay, [100], { priority: 1, timestamp: new Date() })
.then(() => console.log("Task 4 ran..."));
const task5 = queue
.schedule<undefined, delayFn>(delay, [100], { priority: 3, timestamp: new Date() })
.then(() => console.log("Task 5 ran..."));
// OUTPUT
// Task 1 ran...
// Task 5 ran...
// Task 3 ran...
// Task 2 ran...
// Task 4 ran...
```
## Built With
- [NodeJS](https://nodejs.org/en/) - The Engine
- [javascript - ES2017](https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) - The Language
## Contributers
- **Canaan Seaton** - _Owner_ - [GitHub Profile](https://github.com/cmseaton42) - [Personal Website](http://www.canaanseaton.com/)
## License
This project is licensed under the MIT License - see the [LICENCE](https://github.com/cmseaton42/task-easy/blob/master/LICENSE) file for details
================================================
FILE: package.json
================================================
{
"name": "task-easy",
"version": "1.0.1",
"description": "A simple, customizable, and lightweight priority queue for promise based tasks.",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"scripts": {
"test": "npm run lint && jest && npm run test:coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"test:local": "npm run lint && jest && npm run test:coverage",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:detailed": "jest --verbose",
"test:update": "jest -u",
"lint": "./node_modules/.bin/eslint . --ext .js",
"lint:fix": "npm run lint -- --fix"
},
"keywords": [
"queue",
"task",
"worker",
"job",
"in-memory",
"priority",
"manager",
"utility",
"promise",
"Async"
],
"repository": {
"type": "git",
"url": "https://github.com/cmseaton42/task-easy"
},
"author": "Canaan Seaton",
"license": "MIT",
"devDependencies": {
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
"eslint-plugin-jest": "^23.4.0",
"jest": "^24.9.0"
}
}
================================================
FILE: src/__snapshots__/task-easy.spec.js.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Micro Worker Private Methods Reorder Method Produces Correct Output 1`] = `
Array [
Object {
"args": Array [
200,
],
"priority_obj": Object {
"value": 2,
},
"task": [Function],
},
Object {
"args": Array [
100,
],
"priority_obj": Object {
"value": 1,
},
"task": [Function],
},
Object {
"args": Array [
600,
],
"priority_obj": Object {
"value": 6,
},
"task": [Function],
},
Object {
"args": Array [
300,
],
"priority_obj": Object {
"value": 3,
},
"task": [Function],
},
Object {
"args": Array [
400,
],
"priority_obj": Object {
"value": 4,
},
"task": [Function],
},
Object {
"args": Array [
500,
],
"priority_obj": Object {
"value": 5,
},
"task": [Function],
},
Object {
"args": Array [
1400,
],
"priority_obj": Object {
"value": 14,
},
"task": [Function],
},
Object {
"args": Array [
700,
],
"priority_obj": Object {
"value": 7,
},
"task": [Function],
},
Object {
"args": Array [
800,
],
"priority_obj": Object {
"value": 8,
},
"task": [Function],
},
Object {
"args": Array [
900,
],
"priority_obj": Object {
"value": 9,
},
"task": [Function],
},
Object {
"args": Array [
1000,
],
"priority_obj": Object {
"value": 10,
},
"task": [Function],
},
Object {
"args": Array [
1100,
],
"priority_obj": Object {
"value": 11,
},
"task": [Function],
},
Object {
"args": Array [
1200,
],
"priority_obj": Object {
"value": 12,
},
"task": [Function],
},
Object {
"args": Array [
1300,
],
"priority_obj": Object {
"value": 13,
},
"task": [Function],
},
Object {
"args": Array [
0,
],
"priority_obj": Object {
"value": 0,
},
"task": [Function],
},
]
`;
================================================
FILE: src/index.d.ts
================================================
// Task Easy Class
export declare class TaskEasy<C> {
constructor(compare_func: (ob1: C, obj2: C) => boolean, max_queue_size?: number);
schedule<P, T extends TaskEasy.Task<P>>(task: T, args: TaskEasy.Arguments<T>, priority_obj: C): Promise<P>;
}
declare namespace TaskEasy {
// Extract argument types from passed function type
export type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] ? [] : [T];
// Generic task type, must return promise
export type Task<T> = (...args: any[]) => Promise<T>;
}
================================================
FILE: src/index.js
================================================
/**
* A simple in memory priority queue
*
* @class TaskEasy
* @param {Function} compare_func - Function to handle comparison objects passed to Scheduler
* @param {Number} [max_queue_size=100] Max number of tasks allowed in queue
*/
class TaskEasy {
constructor(compare_func, max_queue_size = 100) {
this.tasks = [];
this.taskRunning = false;
if (typeof compare_func !== "function")
throw new Error(
`Task Easy Comparison Function must be of Type <function> instead got ${typeof compare_func}`
);
if (typeof max_queue_size !== "number")
throw new Error(`Task Easy Max Queue Size must be of Type <Number> instead got ${typeof max_queue_size}`);
if (max_queue_size <= 0) throw new Error("Task Easy Max Queue Size must be greater than 0");
this.compare = compare_func;
this.max = max_queue_size;
}
/**
* Schedules a new "Task" to be Performed
*
* @param {function} task - task to schedule
* @param {Array} args - array of arguments to pass to task
* @param {object} priority_obj - object that will be passed to comparison handler provided in the constructor
* @returns
* @memberof TaskQueue
*/
schedule(task, args, priority_obj) {
if (typeof task !== "function")
throw new Error(`Scheduler Task must be of Type <function> instead got ${typeof task}`);
if (!Array.isArray(args)) throw new Error(`Scheduler args must be of Type <Array> instead got ${typeof args}`);
if (typeof priority_obj !== "object")
throw new Error(`Scheduler Task must be of Type <Object> instead got ${typeof priority_obj}`);
if (this.tasks.length >= this.max) throw new Error(`Micro Queue is already full at size of ${this.max}!!!`);
// return Promise to Caller
return new Promise((resolve, reject) => {
// Push Task to Queue
if (this.tasks.length === 0) {
this.tasks.unshift({ task, args, priority_obj, resolve, reject });
this._reorder(0);
this._next();
} else {
this.tasks.unshift({ task, args, priority_obj, resolve, reject });
this._reorder(0);
}
});
}
/**
* Swaps the tasks with the specified indexes
*
* @param {number} ix
* @param {number} iy
* @memberof TaskEasy
*/
_swap(ix, iy) {
const temp = this.tasks[ix];
this.tasks[ix] = this.tasks[iy];
this.tasks[iy] = temp;
}
/**
* Recursively Reorders from Seed Index Based on Outcome of Comparison Function
*
* @param {number} index
* @memberof TaskQueue
*/
_reorder(index) {
const { compare } = this;
const size = this.tasks.length;
const l = index * 2 + 1;
const r = index * 2 + 2;
let swap = index;
if (l < size && compare(this.tasks[l].priority_obj, this.tasks[swap].priority_obj)) swap = l;
if (r < size && compare(this.tasks[r].priority_obj, this.tasks[swap].priority_obj)) swap = r;
if (swap !== index) {
this._swap(swap, index);
this._reorder(swap);
}
}
/**
* Executes Highest Priority Task
*
* @memberof TaskQueue
*/
_runTask() {
this._swap(0, this.tasks.length - 1);
const job = this.tasks.pop();
const { task, args, resolve, reject } = job;
this._reorder(0);
this.taskRunning = true;
task(...args)
.then((...args) => {
resolve(...args);
this.taskRunning = false;
this._next();
})
.catch((...args) => {
reject(...args);
this.taskRunning = false;
this._next();
});
}
/**
* Executes Next Task in Queue if One Exists and One is Currently Running
*
* @memberof TaskQueue
*/
_next() {
if (this.tasks.length !== 0 && this.taskRunning === false) {
this._runTask();
}
}
}
module.exports = { TaskEasy };
================================================
FILE: src/task-easy.spec.js
================================================
const { TaskEasy } = require("./index");
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
describe("Micro Worker", () => {
describe("New Instance", () => {
it("Rejects Improper Constructor Arguments", () => {
const fn = (arg, max) => () => new TaskEasy(arg, max);
expect(fn()).toThrow();
expect(fn("hello", 6)).toThrow();
expect(fn({ a: 6 }, 6)).toThrow();
expect(fn(() => console.log("hello"), 0)).toThrow();
expect(fn(() => console.log("hello"), "string")).toThrow();
expect(fn(() => console.log("hello"), 6)).not.toThrow();
});
});
describe("Private Methods", () => {
let compare;
let arr;
let q;
beforeEach(() => {
arr = [];
compare = (obj1, obj2) => {
if (obj1.value === obj2.value) return obj1.id < obj2.id;
return obj1.value >= obj2.value;
};
for (let i = 0; i < 15; i++) {
arr.push({
task: delay,
args: [100 * i],
priority_obj: { value: i }
});
}
q = new TaskEasy(compare);
q.tasks = arr;
});
it("Reorder Method Produces Correct Output", () => {
q._reorder(0);
expect(q.tasks).toMatchSnapshot();
});
it("Runs Tasks on Push", async () => {
const delayReturn = ms =>
new Promise((resolve, reject) => {
if (typeof ms !== "number") reject("Bad Input");
else
setTimeout(() => {
resolve(ms);
}, ms);
});
const q = new TaskEasy(compare);
const p1 = q.schedule(delayReturn, [50], { value: 1 });
const p2 = q.schedule(delayReturn, [60], { value: 1 });
const p3 = q.schedule(delayReturn, [70], { value: 1 });
await expect(p1).resolves.toBe(50);
await expect(p2).resolves.toBe(60);
await expect(p3).resolves.toBe(70);
});
it("Runs Tasks on Priority", async () => {
const delayReturn = ms =>
new Promise((resolve, reject) => {
if (typeof ms !== "number") reject("Bad Input");
else
setTimeout(() => {
resolve(ms);
}, ms);
});
const q = new TaskEasy(compare);
const res = [];
const p1 = q.schedule(delayReturn, [100], { value: 1, id: 1 }).then(n => res.push(n));
const p2 = q.schedule(delayReturn, [110], { value: 1, id: 2 }).then(n => res.push(n));
const p3 = q.schedule(delayReturn, [120], { value: 2, id: 3 }).then(n => res.push(n));
const p4 = q.schedule(delayReturn, [130], { value: 3, id: 4 }).then(n => res.push(n));
const p5 = q.schedule(delayReturn, [140], { value: 1, id: 5 }).then(n => res.push(n));
const p6 = q
.schedule(delayReturn, ["hello"], { value: 0, id: 6 })
.then(n => res.push(n))
.catch(e => res.push(e));
const p7 = q.schedule(delayReturn, [90], { value: 4, id: 5 }).then(n => res.push(n));
const p8 = q.schedule(delayReturn, [70], { value: 2, id: 6 }).then(n => res.push(n));
const p9 = q.schedule(delayReturn, [105], { value: 1, id: 7 }).then(n => res.push(n));
const p10 = q
.schedule(delayReturn, [107], {
value: 2,
id: 8
})
.then(n => res.push(n));
const p11 = q
.schedule(delayReturn, [80], {
value: 5,
id: 9
})
.then(n => res.push(n));
await Promise.all([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11]);
expect(res).toEqual([100, 80, 90, 130, 120, 70, 107, 110, 140, 105, "Bad Input"]);
});
});
describe("Public Methods", () => {
let compare;
beforeEach(() => {
compare = (obj1, obj2) => {
if (obj1.value === obj2.value) return obj1.id < obj2.id;
return obj1.value >= obj2.value;
};
});
describe("Scheduler", () => {
it("It Rejects Bad Args", () => {
const q = new TaskEasy(compare);
const fn = (func, args, obj) => () => {
q.schedule(func, args, obj);
};
expect(fn(12, [12, 12], { test: 12 })).toThrow();
expect(fn("12", [12, 12], { test: 12 })).toThrow();
expect(fn(arg => console.log(arg), "hello", { test: 12 })).toThrow();
expect(fn(arg => console.log(arg), ["hello"], "test")).toThrow();
expect(fn(arg => console.log(arg), ["hello"], { test: 12 })).not.toThrow();
});
it("Throws if too many tasks queued", () => {
const q = new TaskEasy(compare, 10);
const fn = () => {
for (let i = 0; i < 15; i++) {
q.schedule(delay, [i * 10], { value: i, id: i });
}
};
expect(fn).toThrow();
});
});
});
});
gitextract_wedwjsnx/
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
└── src/
├── __snapshots__/
│ └── task-easy.spec.js.snap
├── index.d.ts
├── index.js
└── task-easy.spec.js
SYMBOL INDEX (10 symbols across 2 files)
FILE: src/index.d.ts
class TaskEasy (line 2) | class TaskEasy<C> {
type Arguments (line 9) | type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] ex...
type Task (line 12) | type Task<T> = (...args: any[]) => Promise<T>;
FILE: src/index.js
class TaskEasy (line 8) | class TaskEasy {
method constructor (line 9) | constructor(compare_func, max_queue_size = 100) {
method schedule (line 36) | schedule(task, args, priority_obj) {
method _swap (line 65) | _swap(ix, iy) {
method _reorder (line 77) | _reorder(index) {
method _runTask (line 100) | _runTask() {
method _next (line 128) | _next() {
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (25K chars).
[
{
"path": ".eslintignore",
"chars": 39,
"preview": "\nnode_modules/**\ncoverage/**\nscripts/**"
},
{
"path": ".eslintrc.js",
"chars": 711,
"preview": "module.exports = {\n env: {\n \"jest/globals\": true,\n es6: true,\n node: true\n },\n extends: [\""
},
{
"path": ".gitignore",
"chars": 65,
"preview": "/node_modules/\n\n# Ignore Jest Coverage Reports\n/coverage\n\n/assets"
},
{
"path": ".npmignore",
"chars": 47,
"preview": "**/*.spec.js\n/coverage\n/assets\n**/__snapshots__"
},
{
"path": ".travis.yml",
"chars": 351,
"preview": "language: node_js\nnode_js:\n - \"node\"\nnotifications:\n webhooks:\n urls:\n - https://webhooks.gitter.im/e/7cce00f2"
},
{
"path": "LICENSE",
"chars": 1043,
"preview": "Copyright (c) 2018\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and as"
},
{
"path": "README.md",
"chars": 7542,
"preview": "<p align=\"center\"><img width=\"280\" src=\"https://i.imgur.com/VwF0DyE.png\" alt=\"Task Easy Logo\"></p>\n\n<div align=\"center\">"
},
{
"path": "package.json",
"chars": 1233,
"preview": "{\n \"name\": \"task-easy\",\n \"version\": \"1.0.1\",\n \"description\": \"A simple, customizable, and lightweight priority "
},
{
"path": "src/__snapshots__/task-easy.spec.js.snap",
"chars": 2130,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Micro Worker Private Methods Reorder Method Produces Correct Output"
},
{
"path": "src/index.d.ts",
"chars": 555,
"preview": "// Task Easy Class\nexport declare class TaskEasy<C> {\n constructor(compare_func: (ob1: C, obj2: C) => boolean, max_qu"
},
{
"path": "src/index.js",
"chars": 4211,
"preview": "/**\n * A simple in memory priority queue\n *\n * @class TaskEasy\n * @param {Function} compare_func - Function to handle co"
},
{
"path": "src/task-easy.spec.js",
"chars": 5538,
"preview": "const { TaskEasy } = require(\"./index\");\n\nconst delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n\ndescribe"
}
]
About this extraction
This page contains the full source code of the cmseaton42/task-easy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (22.9 KB), approximately 6.2k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.