Skip to content

Programmatic API

James Messinger edited this page Mar 10, 2020 · 11 revisions

CodeEngine

In addition to the CLI, CodeEngine can also be imported as a Node module and run programmatically. It exports a CodeEngine class, which manages plugins, worker threads, events, runs, and watching functionality.

Table of Contents

CodeEngine class

This is the programmatic interface to CodeEngine. Multiple CodeEngine instances can co-exist in the same process. Each instance manages its own plugins, worker threads, events, runs, and watches.

const { CodeEngine } = require("code-engine");

// Create a new CodeEngine instance with the default config
let engine = new CodeEngine();

try {
  // Add some plugins
  await engine.use(plugin1, plugin2, plugin3);

  // Clean the destination directory
  await engine.clean();

  // Run CodeEngine
  let summary = await engine.run();

  // Show the results
  console.log(`${summary.output.fileCount} files were created`);
}
finally {
  // Safely dispose the instance
  await engine.dispose();
}

CodeEngine constructor

The constructor accepts an optional Config object.

const { CodeEngine } = require("code-engine");

// Create a new CodeEngine instance with a custom config
let engine = new CodeEngine({
  concurrency: 20,
  watchDelay: 1000,
  debug: true,
});
Config setting Type Default Description
cwd string process.cwd() The directory used to resolve all relative paths.
concurrency number The number of CPU cores available The number of worker threads that CodeEngine should use to process files.
dev boolean false, unless the NODE_ENV environment variable is set to "development" Indicates whether CodeEngine should run in local development mode. When true, many plugins will generate files that are un-minified, un-obfuscated, and may contain references to localhost.
debug boolean false, unless the DEBUG environment variable is set to a non-empty value Indicates whether CodeEngine is running in debug mode, which enables additional logging and error stack traces.

Static members

CodeEngine.instances

This static class property is an array of all CodeEngine instances that have been created and not yet disposed. You can call dispose() on a single instance to dispose it, or CodeEngine.disposeAll() to dispose all instances.

const { CodeEngine } = require("code-engine");

let engine1 = new CodeEngine();
let engine2 = new CodeEngine();
let engine3 = new CodeEngine();

console.log(`There are ${CodeEngine.instances.length} CodeEngine instances`);

CodeEngine.disposeAll()

This static class method disposes all CodeEngine instances (see dispose()). After calling this method, the existing CodeEngine instance are no longer usable.

const { CodeEngine } = require("code-engine");

let engine1 = new CodeEngine();
let engine2 = new CodeEngine();
let engine3 = new CodeEngine();

// Dispose all three instances
await CodeEngine.disposeAll();

Properties

CodeEngine.cwd

The directory used to resolve all relative paths. Defaults to process.cwd().

const { CodeEngine } = require("code-engine");

let engine = new CodeEngine();
console.log(`CodeEngine is running in ${engine.cwd}`);

CodeEngine.concurrency

The number of worker threads that CodeEngine is using to process files. Defaults to the number of CPU cores available.

const { CodeEngine } = require("code-engine");

let engine = new CodeEngine();
console.log(`CodeEngine has ${engine.concurrency} worker threads`);

CodeEngine.dev

Indicates whether CodeEngine is running in local development mode. When true, many plugins will generate files that are un-minified, un-obfuscated, and may contain references to localhost.

Defaults to false, unless the NODE_ENV environment variable is set to "development".

const { CodeEngine } = require("code-engine");

let engine = new CodeEngine();

if (engine.dev) {
  console.log(`CodeEngine is running in local development mode`);
}
else {
  console.log(`CodeEngine is running in production mode`);
}

CodeEngine.debug

Indicates whether CodeEngine is running in debug mode, which enables additional logging and error stack traces.

Defaults to false, unless the DEBUG environment variable is set to a non-empty value.

const { CodeEngine } = require("code-engine");

let engine = new CodeEngine();

if (engine.debug) {
  console.log(`CodeEngine is running in debug mode`);
}
else {
  console.log(`CodeEngine is running in normal mode`);
}

CodeEngine.disposed

Indicates whether the dispose() method has been called. Once disposed, a CodeEngine instance is no longer usable.

const { CodeEngine } = require("code-engine");

let engine = new CodeEngine();
console.log(engine.disposed);     // false

await engine.dispose();
console.log(engine.disposed);     // true

Methods

CodeEngine.use(...plugins)

Adds one or more CodeEngine plugins.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

// Add a single plugin
await engine.use(somePlugin);

// Add multiple plugins
await engine.use(plugin1, plugin2, plugin3);

CodeEngine.clean()

Deletes any previous output from the destination(s).

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

// Add some plugins
await engine.use(plugin1, plugin2, plugin3);

// Clean the destination(s)
await engine.clean();

CodeEngine.run()

Runs all source files through the plugin pipeline. Returns a Summary object with information about the run.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

// Add some plugins
await engine.use(plugin1, plugin2, plugin3);

// Run CodeEngine
let summary = await engine.run();

// Show the results
console.log(`${summary.output.fileCount} files were created`);

CodeEngine.watch([delay])

Watches source files for changes and runs them again whenever changes are detected.

  • delay - (optional) The amount of time (in milliseconds) to wait after a file change is detected before starting a new run. This allows multiple files that are changed together to all be re-built together. Defaults to 300ms.
const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

// Add some plugins
await engine.use(plugin1, plugin2, plugin3);

// Run ALL files
await engine.run();

// Start watching for changes and do partial runs
engine.watch();

engine.on("start", ({ changedFiles }) => {
  console.log(`${changedFiles.length} files were changed. Rebuilding...`);
});

engine.on("finish", ({ output }}) => {
  console.log(`${output.fileCount} files were created.`);
});

CodeEngine.dispose()

Releases system resources that are held by a CodeEngine instance. Once dispose() is called, the CodeEngine instance is no longer usable.

const { CodeEngine } = require("code-engine");

// Create a CodeEngine instance
let engine = new CodeEngine();

try {
  // Add some plugins
  await engine.use(plugin1, plugin2, plugin3);

  // Run CodeEngine
  await engine.run();
}
finally {
  // Safely dispose the instance
  await engine.dispose();
}

Logging Methods

CodeEngine.log(message_or_error, [data])

Logs a message or an error. This method is just a shortcut for log.info() or log.error().

  • message_or_error - If a message string is passed, then this method will call log.info(). If an Error object is passed, then this method will call log.error()

  • data - (Optional) An object with any additional data you want to add to the log

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.log("This is a log message");

engine.log("This is a log message with data", { foo: 42, bar: true });

engine.log(new Error("This is an error log"));

engine.log(new Error("This is an error log with data"), { foo: 42, bar: true });

CodeEngine.log.info(message, [data])

Logs an informative message. Unlike debug messages, info messages are always logged.

  • message - The message text

  • data - (Optional) An object with any additional data you want to add to the log

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.log.info("This is a log message");

engine.log.info("This is a log message with data", { foo: 42, bar: true });

CodeEngine.log.debug(message, [data])

Logs a debug message if CodeEngine is running in debug mode. When CodeEngine is running in normal mode, these messages will be ignored.

  • message - The message text

  • data - (Optional) An object with any additional data you want to add to the log

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.log.debug("This is a log message");

engine.log.debug("This is a log message with data", { foo: 42, bar: true });

CodeEngine.log.warn(message_or_error, [data])

Logs a warning message. This will not prevent CodeEngine from running or finishing its task. It just lets the user know that something is possibly wrong.

  • message_or_error - The warning message. If it's an Error object, then the error's message property will be used, and the error object will be added to the data object.

  • data - (Optional) An object with any additional data you want to add to the log

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.log.warn("This is a warning");

engine.log.warn("This is a warning with data", { foo: 42, bar: true });

engine.log(new Error("This is a warning"));

engine.log(new Error("This is a warning with data"), { foo: 42, bar: true });

CodeEngine.log.error(message_or_error, [data])

Logs an error message. This will not prevent CodeEngine from running or finishing its task. It just lets the user know that errors were encountered. This is typically preferred rather than throwing an error, which will cause CodeEngine to abort what it's doing.

  • message_or_error - The error message. If it's an Error object, then the error's message property will be used, and the error object will be added to the data object.

  • data - (Optional) An object with any additional data you want to add to the log

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.log.warn("This is an error message");

engine.log.warn("This is an error message with data", { foo: 42, bar: true });

engine.log(new Error("This is an error"));

engine.log(new Error("This is an error with data"), { foo: 42, bar: true });

Events

"error" event

This event is fired whenever an unhandled error occurs. If you don't handle this event, then Node.js will automatically terminate the process.

NOTE: When an unhandled error occurs, the CodeEngine instance, or one of its plugins, or one of its worker threads may be left in an invalid or unusable state. For this reason, we recommend that you dispose the CodeEngine instance and stop using it.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.on("error", (error) => {
  console.error("An unhandled error occurred:", error);
  engine.dispose();
});

"log" event

This event is fired whenever CodeEngine or a plugin calls any logging method. The event includes the message that was logged, the severity level, the error (if any), and any other data that was provided.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.on("log", ({ level, message, error, ...data }) => {
  if (level === "error" || level === "warning") {
    console.error(message, error, data);
  }
  else {
    console.log(message, data);
  }
});

"start" event

This event is fired whenever a new run starts — whether it's a full or partial run. It receives a Run object, which has information about the run.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.on("start", (run) => {
  if (run.full) {
    if (run.dev) {
      console.log("Starting a full run in dev mode.");
    }
    else {
      console.log("Starting a full run in production mode.");
    }
  }
  else {
    console.log(`Starting a partial run of ${run.changedFiles.length} files.`);
  }
});

"finish" event

This event is fired when a run completes. It receives a Summary object with the results of the run.

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

engine.on("finish", (summary) => {
  console.log(`Built ${summary.output.fileCount} files in ${summary.time.elapsed} milliseconds.`);
});

"change" event

This event is fired whenever CodeEngine or one of its plugins detects that a source file has changed. It receives a File object with a change property that indicates the type of change ("created", "modified", or "deleted").

const { CodeEngine } = require("code-engine");
let engine = new CodeEngine();

// Watch source files for changes
engine.watch();

engine.on("change", (file) => {
  console.log(`${file.path} was ${file.change}`);   // ex: "www/index.html was modified"
});
Clone this wiki locally