Internal CodeEngine utilities
npm install @code-engine/utilsCodeEngine utilities
======================================







This is a utility library that's used inside CodeEngine. It contains miscellaneous utility functions, some of which are experimental and may be removed or changed in the future.
> NOTE: This is an internal library that is only intended to be used by CodeEngine. Using it outside of CodeEngine is discouraged.
- File utilities
- Module utilities
- Iteration utilities
- Log utilities
File utilities
-------------------------------
File object.- info: - A FileInfo object. All fields are optional except for the path.
- pluginName: - (optional) The name of the plugin that's creating the file. This is used to create a unique source URL for the file. If not provided, it just defaults to "plugin".
``javascript
import { createFile } from "@code-engine/utils";
createFile({ path: "robots.txt" });
createFile({ path: "page.html", text: "
$3
This is the same as createFile(), except that it requires a change property to be set (to "created", "modified", or "deleted").`javascript
import { createChangedFile } from "@code-engine/utils";createChangedFile({ path: "robots.txt", change: "created" });
createChangedFile({ path: "page.html", text: "
Hello, world!
", change: "modified" });
`
$3
Normalizes a FileInfo object. For ease of use, the FileInfo interface is pretty loose and allows multiple different data types for most fields. This function returns a normalized FileInfo object where each field is a specific type.createFile() and createChangedFile().`javascript
import { normalizeFileInfo } from "@code-engine/utils";normalizeFileInfo({ path: "robots.txt" });
normalizeFileInfo({ path: "page.html", text: "
Hello, world!
" });
`Module utilities
-------------------------------
$3
Resolves the entry-file path of the specified JavaScript module, either from the specified path or a globally-installed NPM package.- moduleId: - The name or path of the module to resolve
- cwd - (optional) The directory to resolve from. Defaults to
process.cwd()`javascript
import { resolveModule } from "@code-engine/utils";resolveModule("lodash");
resolveModule("lodash", "/my/custom/path");
resolveModule("../node_modules/lodash");
resolveModule("../node_modules/lodash/lib/index.js");
`$3
Imports the specified JavaScript module, either from the specified path or a globally-installed NPM package.- moduleId: - The name or path of the module to resolve
- cwd - (optional) The directory to resolve from. Defaults to
process.cwd()`javascript
import { importModule } from "@code-engine/utils";importModule("lodash");
importModule("lodash", "/my/custom/path");
importModule("../node_modules/lodash");
importModule("../node_modules/lodash/lib/index.js");
`Iteration utilities
-------------------------------
$3
This class helps when running multiple async tasks concurrently. Given a concurrency limit, it tracks availability to run additional tasks.`javascript
import { ConcurrentTasks } from "@code-engine/utils";// Run up to 3 async tasks concurrently
let concurrentTasks = new ConcurrentTasks(3);
// Process a large list of files, 3 at a time
for await (let file of files) {
// Wait for one of the 3 task "slots" to become available
await concurrentTasks.waitForAvailability();
// Start an async task
let promise = processFile(file);
concurrentTasks.add(promise);
}
// Wait for any remainint tasks to complete
await concurrentTasks.waitForAll();
`
$3
Creates an async iterable that you can write values to.`javascript
import { IterableWriter } from "@code-engine/utils";// The writer.iterable property is the async iterable that gets written to
let writer = new IterableWriter();
// Write a value to the iterable, and wait for it to be read
await writer.write("Some value");
// Cause the iterable to throw an error on the next read
await writer.throw(new Error("Boom!"));
// Indicate that there are no more values, and wait for all existing values to be read.
await writer.end();
`
$3
Iterates over anything. This can be a single value, an array of values, an iterable, an async iterable, a Promise that returns one or more values. Literally anything.This function is used to allow CodeEngine plugins to return files however they want. They can return a single file, an array of files, an async iterator of files, a Promise of files, etc. If the plugin returns
undefined, then that's the same as returning an empty array (i.e. no files).`javascript
import { iterate } from "@code-engine/utils";// undefined is the same as an empty list
for await (let value of iterate(undefined)) {
console.log("This line will never be executed");
}
// Iterate over a single async value
let promise = Promise.resolve({ path: "some-file.txt" });
for await (let file of iterate(promise)) {
console.log(
Processing file: ${file.path});
}// Iterate over an array of values
let files = [
{ path: "file1.txt" },
{ path: "file2.txt" },
{ path: "file3.txt" },
];
for await (let file of iterate(files)) {
console.log(
Processing file: ${file.path});
}
`
$3
Iterates over an async iterable, always reading the specified number of values at a time. Values are yielded in first-available order.- iterable: - An async iterable
- concurrency: - The number of values to read simultaneously
`javascript
import { iterateParallel } from "@code-engine/utils";// Read 3 files at a time from disk. Some files may take longer to read than others.
// The loop iterates each file in first-available order.
for await (let file of iterateParallel(myAsyncFileReader, 3)) {
console.log(
Processing file: ${file.path});
}
`
$3
Joins multiple iterables into a single one that yields values in first-available order.- iterables: - The iterables (sync and/or async) to join together
`javascript
import { joinIterables } from "@code-engine/utils";let source1 = readFilesFrom("/my/first/directory");
let source2 = readFilesFrom("/my/second/directory");
let source3 = readFilesFrom("/my/third/directory");
// Read files from all three sources, and process them in first-available order
for await (let file of joinIterables(source1, source2, source3)) {
console.log(
Processing file: ${file.path});
}
`
$3
Splits an iterable into separate ones that each iterate a subset of the values. Each value in the original iterable will only be sent to ONE of the separate iterables. Values are sent in a first-come, first-serve order, so some iterables may receive more values than others.- iterable: - The iterable to split
- concurrency: - The number of separate iterables to create
`javascript
import { splitIterable } from "@code-engine/utils";// Split one async iterable into three
let [iterable1, iterable2, iterable3] = splitIterable(myAsyncIterable, 3);
`
$3
Debounces an async iterable, so all values that are yielded within a threshold are grouped together.- iterable: - An async iterable
- delay: - The amount of time, in milliseconds, to wait for additional values before yielding
`javascript
import { debounceIterable } from "@code-engine/utils";// Each iteration of this loop will wait at least 300ms.
// The values variable contains all values that were yielded since the previous iteration.
for await (let values of debounceIterable(myAsyncIterable, 300)) {
console.log(
${values.length} values were yielded);
}
`
$3
Iterates over all values in an async iterable, optionally multiple values at a time. The values are immediately discarded, so very little memory is consumed.- iterable: - An async iterable
- concurrency: - (optional) The number of values to read simultaneously. Defaults to 1.
`javascript
import { drainIterable } from "@code-engine/utils";// Iterate over all values, one at a time
await drainIterable(myAsyncIterable);
// Iterate over all values, three at a time
await drainIterable(myAsyncIterable, 3);
`Log utilities
-------------------------------
$3
This is just a convenience function that calls the corresponding method of the Logger object.Logger object- level: - A severity level, which determines which
Logger method to call. Can be "info", "log", "debug", "warn", "warning", or "error".- message: - The string or
Error object to log- data: (optional) A POJO with additional data to log
`javascript
import { log } from "@code-engine/utils";log(myLogger, "info", "This is an info message");
log(myLogger, "warning", "This is a warning!", { code: "LOW_MEMORY" });
log(myLogger, "error", new RangeError("Out of range!"));
`
$3
Creates a Logger that emits log messages via the given EventEmitter.EventEmitter to which logs are emitted- debug: - (Optional) A boolean that indicates whether debug messages should be emitted
`javascript
import { createLogEmitter } from "@code-engine/utils";
import { EventEmitter } from "events";let emitter = new EventEmitter();
let log = createLogEmitter(emitter, true);
log("This is a log message");
log.warn("This is a warning message");
`Contributing
--------------------------
Contributions, enhancements, and bug-fixes are welcome! Open an issue on GitHub and submit a pull request.
#### Building
To build the project locally on your computer:
1. __Clone this repo__
git clone https://github.com/CodeEngineOrg/code-engine-utils.git2. __Install dependencies__
npm install3. __Build the code__
npm run build4. __Run the tests__
npm test`License
--------------------------
@code-engine/utils is 100% free and open-source, under the MIT license. Use it however you want.
This package is Treeware. If you use it in production, then we ask that you buy the world a tree to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.
Big Thanks To
--------------------------
Thanks to these awesome companies for their support of Open Source developers ❤


