npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mle-cli

v1.0.1

Published

Oracle MLE cli tool for development and testing. Run and test your JavaScript straight from the command line

Readme

terminal icon mle-cli

A fast, no-fuss CLI for Oracle’s Multilingual Engine (MLE). Use JavaScript in your Oracle database right from the terminal—no complex setup required.

At a glance

  • Run JavaScript in your Oracle database straight from the terminal
  • Interactive REPL
  • In-database test runner with readable results
  • ORDS endpoint scaffolding to expose REST using only JavaScript
  • Manage MLE objects (modules, environments)
  • Optional auto-bundling (TypeScript and npm dependencies)

🧠 Note: Under the hood mle-cli uses node-oracledb to connect to your database instance and execute generated queries.

Documentation

This README is the documentation for mle-cli. It covers installation, configuration, command usage, and examples.

For more detail on tests and REST endpoints, see:

Examples

Each command description in Available commands includes usage and examples.


Prerequisites

Before getting started, you'll need:

  1. An instance of Oracle 26ai that you can connect to
  2. A database user with the following privileges (granted individually or through the DB_DEVELOPER_ROLE role)
    • CREATE SESSION
    • EXECUTE DYNAMIC MLE
    • CREATE PROCEDURE
    • CREATE MLE
  3. A JavaScript runtime (Node.js) installed locally

The tool primarily supports connecting using TCP/IP, which should cover most use cases. For additional connection options, see the configuration section below.

If you don't have Node.js installed, you can download it from: https://nodejs.org/en/download

Installation

You can install mle-cli using npm by running one of the following commands:

Local installation (recommended for project-specific use):

npm install mle-cli

Local installation as a development dependency:

npm install --save-dev mle-cli

Global installation (for use from any directory):

npm install --global mle-cli

To update a local installation:

npm update mle-cli

To update a global installation:

npm update --global mle-cli

🧠 Note: For local installations, prefix the commands in this README with npx. So using it would look like this:

npx mle-cli run /path/to/file.js

Configuration

⚠️ WARNING ⚠️ Storing passwords in plaintext is not safe.

To connect to your database, mle-cli can assemble connection settings from several sources. For the same field, the effective priority is:

  1. --connect / -c
  2. A config file passed with --config / -f
  3. A config file found under $HOME/.mlecli
  4. Environment variables for any still-missing supported fields

A few details matter:

  • When --connect is present, config files are not loaded.
  • Environment variables only fill missing username, connectString, and walletLocation values. They do not override values already supplied by --connect or a config file.
  • The interactive password prompt is only used with --connect. Config files and environment variables are non-interactive.

For simple username/password logins, provide username and connectString. For wallets, access tokens, or other advanced node-oracledb connection attributes, use a config file.

Connection string on the command line

Use --connect (-c) for easy connect strings:

$ mle-cli -c 'scott@server:port/serviceName' run file.js
Please enter password: 

You can also add a privilege suffix such as AS SYSDBA:

$ mle-cli -c 'sys@server:port/serviceName as sysdba' repl
Please enter password:

Supported privilege suffixes are SYSASM, SYSBACKUP, SYSDBA, SYSDG, SYSKM, SYSOPER, SYSPRELIM, and SYSRAC.

Note: Do not include your password in the connect string. If you pass user/password@..., mle-cli ignores the embedded password and still prompts for it. When --connect is used, config files are skipped, so use a config file for walletLocation, accessToken, externalAuth, or other node-oracledb connection attributes.

Config files

mle-cli loads top-level connection attributes from JSON or JavaScript config files. Supported file types are .json, .js, .cjs, and .mjs.

Basic examples:

Username/password authentication also requires a password connection attribute. Config files do not trigger a password prompt. The examples omit credentials. For an interactive password prompt, use --connect.

JSON

{
    "username": "my_user",
    "connectString": "mydbmachine.example.com/orclpdb1"
}

JavaScript (ESM, config.mjs)

export default {
    username: "my_user",
    connectString: "mydbmachine.example.com/orclpdb1",
}

JavaScript (CJS, config.cjs)

module.exports = {
    username: "my_user",
    connectString: "mydbmachine.example.com/orclpdb1",
};

Since the tool accepts JavaScript source as a configuration option it is also possible to use configuration providers from node-oracledb.

Full connect descriptors are also supported

{
    "username": "my_user",
    "connectString": "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=mymachine.example.com)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))"
}

The CLI tool will automatically search these exact paths for configuration files:

  • $HOME/.mlecli/config.json
  • $HOME/.mlecli/config.js
  • $HOME/.mlecli/config.cjs
  • $HOME/.mlecli/config.mjs

No project-local config search is performed. If both JSON and JS configuration files are present in $HOME/.mlecli, mle-cli will prioritize the JSON configuration file.

🧠 Note: The CLI tool passes configuration values along to node-oracledb. This means that all options available in node-oracledb are also available to mle-cli. If your config includes accessToken, mle-cli automatically enables externalAuth. For more see the node-oracledb documentation.

Specifying a custom config file:

You can tell mle-cli the exact path of your configuration file to bypass the default $HOME/.mlecli search:

$ mle-cli --config path/to/config.json repl
>

Or use the short form:

$ mle-cli -f path/to/config.json repl
>

💡 Tip: Relative paths are resolved from your current working directory. You can place the --config flag anywhere in your command:

$ mle-cli run --config path/to/config.json hello.js
hello world

Environment variables

If username, connectString, or walletLocation are still missing after --connect or config-file processing, mle-cli will attempt to retrieve them from the following environment variables:

| Variable | Description | | --------------------- | -------------------------------------- | | MLECLI_USERNAME | Database username | | MLECLI_CONN_STRING | Connection string (host/service) | | MLECLI_WALLET_LOC | Path to wallet directory |

These variables are fallback values only; they do not override CLI or config-file values.

Note: Password values are intentionally not supported through environment variables.

Import maps

Some commands of this tool accept import maps. These are used to describe environments and the tools will create MLE environments based on the import map when these are given.

Example

$ mle-cli run --import-map example-map.json file-to-run.js

These import maps describe import names and the MLE module these map to.

Example

{
    "imports": {
        "my-imported-module": "MOD_NAME",
        "other-module": "OTHER_MODULE_NAME" 
    }
}

With --env, the command uses mappings from an existing MLE environment:

$ mle-cli run --env MY_ENV imports.js

Available commands

This section covers each command in detail, including the interactive REPL, test runner, and options for managing MLE objects. Use mle-cli <command> --help to see the options for a specific command.

$ mle-cli --help
Usage: mle-cli [options] [command]

Oracle MLE cli tool for development and testing. Run and test your JavaScript straight from the command line

Options:
  -V, --version             output the version number
  -f, --config <path>       path to configuration file for connection information.
  -c, --connect <info>      connection info as an easy connect string in the format {user}@{connect string}[ AS {privilege}].
  --debug                   run in debug mode.
  --experimental <feature>  enable the specified experimental feature (choices: "build")
  -h, --help                display help for command

Commands:
  run [options] <path>      Run the given js file with MLE.
  repl [options]            Start a Read-Eval-Print-Loop using MLE.
  create                    Create MLE objects.
  drop                      Drop MLE objects.
  list                      List MLE related database objects.
  test [options] [path]     Run your unit tests in the database using MLE.
  help [command]            display help for command

Environment variables supported:

  MLECLI_USERNAME - Database username (alternative to --connect or config)
  MLECLI_CONN_STRING - Database connect string (alternative to --connect or config)
  MLECLI_WALLET_LOC - Wallet location for connections (alternative to --connect or config)

If both CLI flags and environment variables are provided, flag values take precedence.

run

Usage: mle-cli run [options] <path>

The run command executes a local JavaScript file:

$ cat hello.js
console.log('hello world');

$ mle-cli run hello.js
hello world

If your code contains errors, mle-cli reports file paths and line numbers. In this example, errorstack.js contains:

function fail() {
    throw new Error('This is a useful error msg.');
}

fail();
$ mle-cli run errorstack.js
Error: This is a useful error msg.
  at fail errorstack.js (line: 2, column: 11)
  at errorstack.js (line: 5, column: 1)

MLE Environments

You can run your JS files in specific MLE environments. Please refer to the Import maps section to see how to do this.

Auto-bundling

Internally, mle-cli invokes esbuild on input files, with bundling enabled. Since, esbuild supports TypeScript type erasure this means that you can give TypeScript files to run with imports from other files or your node_modules and it will still work.

Unfortunately, MLE doesn't support source maps so the original source locations will not map back and forth (e.g. in error stacks). For this reason this feature is behind the experimental build flag.

import { PackageURL } from 'packageurl-js';
 
function doThing(url: string) {
    const purl = PackageURL.fromString(url);
    console.log(purl.name);
    console.log(purl.namespace);
    console.log(purl.type);
    console.log(purl.version);
}
 
doThing('pkg:maven/org.springframework.integration/[email protected]');
$ mle-cli --experimental build run purl.ts

Output

spring-integration-jms
org.springframework.integration
maven
5.5.5

How it works

The run command reads the contents of the provided file and creates an MLE module[^1]. Then an environment that maps the newly created MLE module is created. Afterwards we force the evaluation of the module by importing it using DBMS_MLE. The output streams (stdout/stderr) are captured in a CLOB along with any exception information if there is any (message and stack trace). In the end the module is dropped and the client formats and prints the result of the evaluation.

This approach enables several advanced features:

  1. Top-level await support:
console.log(await Promise.resolve('a value'));
  1. Static ESM imports: This example assumes MY_MODULE and MY_ENV exist as described under create. The local file imports.js contains:
import { sayHello } from 'my-module';

console.log(sayHello());
$ mle-cli run --env MY_ENV imports.js
hello world

[^1]: To create an MLE module it first creates a "holder" PL/SQL package with a BLOB variable and a function that returns the value of the variable. Then the variable is written with the contents of the file. The MLE module is created by selecting the function, which returns the BLOB. Finally the "holder" package is dropped.


repl

Usage: mle-cli repl [--env <name>]

REPL (Read-Eval-Print-Loop) provides an interactive shell where you can type JavaScript commands and see results immediately:

$ mle-cli repl
> 2 + 2
4
> .exit

Multi-line input is also supported:

$ mle-cli repl
> console.log(`
... My multi-line string.
... Has a second line
... `);

My multi-line string.
Has a second line

> function f1() {
...   console.log('Hello World');
... }
> f1();
Hello World

Your command history is saved at $HOME/.mle_repl_history. You can navigate through previous commands using the up and down arrow keys or use reverse-i-search to find specific commands.

Special commands:

  • .exit - Exit the REPL
  • .editor - Enter editor mode for multi-line input
  • .save path/to/file - Save the current REPL session to a file
  • .load path/to/file - Load commands from a file into the current session

🟡 The following special commands are NOT currently supported:

  • .break
  • .clear

Working with async code and imports

Unlike the run command, the REPL doesn't support top-level await. To use async features, wrap your code in an immediately-executed async function:

$ mle-cli repl
> (async () => {
... console.log(await Promise.resolve('hello')); 
... })();
hello

> .exit

For importing modules, use dynamic imports:

$ mle-cli repl 
> (async () => {
... const { fetch } = await import('mle-js-fetch');
... fetch('http://example.org');
... })();

💡 Tip: To make imported symbols available for later use in the REPL session, assign them to the global object:

> (async () => {
... const { fetch } = await import('mle-js-fetch');
... globalThis.fetch = fetch;
... })();
> fetch('http://example.org');

For modules with many exports:

> (async () => Object.assign(globalThis, await import('mle-js-fetch')))();
> fetch('http://example.org');

How it works

The CLI uses REPLServer from node:repl to provide the interactive interface.

When the server is started, a standalone connection to the database is created along with a DBMS_MLE context. The handle to that context is sent back to the client and used later.

The custom evaluator provides multiline input buffering (using node to detect when a unit is complete) and the executor. When a complete code unit is detected it is sent to the database for execution using DBMS_MLE. The output streams (stdout/stderr) are captured in CLOBs and sent back to the client along with exception information (if one occured).


create

You can create MLE objects directly from the command line. This command has multiple subcommands, one for each object type.

module

Usage: mle-cli create module <path> --name <name> [--no-replace]

The module subcommand installs a local JavaScript file as an MLE module in the database. The specified name is case sensitive.

In this example, source.js contains:

export function sayHello() {
    return 'hello world';
}

The following command installs source.js as MY_MODULE:

$ mle-cli create module ./source.js --name MY_MODULE

By default, the command replaces an existing module with the same name. With --no-replace, the command fails if the module already exists.

$ mle-cli create module ./source.js --name MY_MODULE --no-replace

For the same source in source.ts, the command enables auto-bundling:

$ mle-cli --experimental build create module ./source.ts --name MY_MODULE

env

Usage: mle-cli create env <path> --name <name> [--no-replace]

The env subcommand creates an MLE environment from an import map. The environment name is case sensitive. This example assumes MY_MODULE already exists and my-env.json contains the following import map:

{
    "imports": {
        "my-module": "MY_MODULE"
    }
}

Example:

$ mle-cli create env --name MY_ENV ./my-env.json

By default, the command replaces an existing environment. Use --no-replace to fail if the name already exists.

ords

Usage: mle-cli create ords <path> --name <name> [--env <name> | --import-map <path>] [--print]

The ords subcommand installs a JavaScript file that exports ORDS handlers. It creates the MLE module, an MLE environment, and the ORDS modules, templates, and handlers. The CLI also installs its bundled mle-cli/ords runtime library. This command requires ORDS in the database and a REST-enabled schema.

In this example, hello-ords.js exports the following handler:

import { ords } from 'mle-cli/ords';

export const getHello = ords.get('/hello', (req, resp) => {
    resp.json({ message: 'Hello, ORDS!' });
});

The following command installs the endpoint:

$ mle-cli create ords hello-ords.js --name HELLO_ORDS

With --print, the command prints the generated ORDS SQL:

$ mle-cli create ords hello-ords.js --name HELLO_ORDS --print

--print still connects to the database and creates or replaces MLE objects. It skips execution of the generated ORDS SQL. For handler definitions, see the ORDS Endpoint Library Guide.


drop

You can drop MLE objects directly from the command line. This command has multiple subcommands, one for each object type.

module

Usage: mle-cli drop module <name>

Drops the module with the given name. Please note that names are case sensitive.

$ mle-cli drop module MY_MODULE

env

Usage: mle-cli drop env <name>

Drops the environment with the given name. Please note that names are case sensitive.

$ mle-cli drop env MY_ENV

list

You can list MLE objects in the schema of your user.

modules

Usage: mle-cli list modules

List MLE modules. Example output for two modules:

$ mle-cli list modules
MODULE_NAME  VERSION  TYPE  
-----------  -------  ----
MOD1         1.3.2    TEXT  
MOD2         0.2.3    TEXT

envs

Usage: mle-cli list envs

List MLE environments. Example output for an environment with two import mappings:

$ mle-cli list envs
Environment: TEST_ENV
  mod-1 -> MOD1
  mod-2 -> MOD2

test

Usage: mle-cli test [options] [path]

mle-cli test runs both test cases and assertions inside Oracle Database, using MLE. Tests can import MLE modules and execute SQL through the built-in session object. The CLI handles that execution and reports the results in your terminal.

The test runner accepts a test file or searches a directory recursively. With no path, it searches the current directory. It discovers *.test.js, *.test.mjs, *.test.ts, and *.test.mts files. TypeScript files require --experimental build. The command returns a non-zero exit status for failed tests or load errors.

In this example, test/example.test.js contains one test:

import { test, expect } from 'mle-cli/test';

test('addition', () => {
    expect.equal(2 + 2, 4);
});

The following command runs all tests under test inside the database:

$ mle-cli test ./test

The output includes the test result and an overall summary:

Test "addition" - passed
...
Suite summary: 1 passed, 0 failed, 0 skipped.

For a single test file:

$ mle-cli test ./test/example.test.js

Without a path, the command searches the current directory:

$ mle-cli test

Output

/Users/myuser/Development/mle-project/test/example1.test.js
--------------------------------------------------------------------------------
Test "My first test" - passed
Test "My failing test" - failed
    AssertionError: Expected value to be true, but evaluated to false.
        at expect.true (mle-cli/test:169:13)
        at example1.test.js:8:12
        at TestContext.execute (mle-cli/test:112:21)
        at async RootContext.execute (mle-cli/test:22:41)
Suite: "First suite"
    Test "My first test" - passed
    Test "My failing test" - failed
        AssertionError: Expected value to be true, but evaluated to false.
            at expect.true (mle-cli/test:169:13)
            at example1.test.js:17:16
            at TestContext.execute (mle-cli/test:112:21)
            at async SuiteContext.execute (mle-cli/test:69:38)
            at async RootContext.execute (mle-cli/test:22:41)

File summary: 2 passed, 2 failed, 0 skipped. (~2 ms)
--------------------------------------------------------------------------------

/Users/myuser/Development/mle-project/test/some-test-suite/example2.test.js
--------------------------------------------------------------------------------
Suite: "My module"
    Test "My first test" - failed
        AssertionError: Expected "2" to be equal to "3".
            at expect.equal (mle-cli/test:179:13)
            at example2.test.js:5:16
            at TestContext.execute (mle-cli/test:112:21)
            at async SuiteContext.execute (mle-cli/test:69:38)
            at async RootContext.execute (mle-cli/test:22:41)
    Test "My failing test" - passed

File summary: 1 passed, 1 failed, 0 skipped. (~0 ms)
--------------------------------------------------------------------------------

================================================================================
                 Suite summary: 3 passed, 3 failed, 0 skipped.
================================================================================

Searching a specific directory:

$ mle-cli test ./test/some-test-suite

Output

/Users/myuser/Development/mle-project/test/some-test-suite/example2.test.js
--------------------------------------------------------------------------------
Suite: "My module"
        AssertionError: Expected "2" to be equal to "3".
            at expect.equal (mle-cli/test:179:13)
            at example2.test.js:5:16
            at TestContext.execute (mle-cli/test:112:21)
            at async SuiteContext.execute (mle-cli/test:69:38)
            at async RootContext.execute (mle-cli/test:22:41)
    Test "My first test" - failed
    Test "My failing test" - passed

File summary: 1 passed, 1 failed, 0 skipped. (~1 ms)
--------------------------------------------------------------------------------

================================================================================
                 Suite summary: 1 passed, 1 failed, 0 skipped.
================================================================================

If the path is a single file, then only that file will be executed:

$ mle-cli test ./test/example1.test.js

Output

/Users/myuser/Development/mle-project/test/example1.test.js
--------------------------------------------------------------------------------
Test "My first test" - passed
    AssertionError: Expected value to be true, but evaluated to false.
        at expect.true (mle-cli/test:169:13)
        at example1.test.js:8:12
        at TestContext.execute (mle-cli/test:112:21)
        at async RootContext.execute (mle-cli/test:22:41)
Test "My failing test" - failed
Suite: "First suite"
    Test "My first test" - passed
        AssertionError: Expected value to be true, but evaluated to false.
            at expect.true (mle-cli/test:169:13)
            at example1.test.js:17:16
            at TestContext.execute (mle-cli/test:112:21)
            at async SuiteContext.execute (mle-cli/test:69:38)
            at async RootContext.execute (mle-cli/test:22:41)
    Test "My failing test" - failed

File summary: 2 passed, 2 failed, 0 skipped. (~2 ms)
--------------------------------------------------------------------------------

This tool includes a unit testing library called 'mle-cli/test'. It provides all the functionality you need to run and write your tests. While it's designed to work smoothly with the test runner, it's entirely optional. If you want to use a different library see the docs on using a custom unit test library.

For guidance on writing tests with 'mle-cli/test', see the API documentation.

MLE Environments

You can run your test files in specific MLE environments. Please refer to the Import maps section to see how to do this.

How it works

We use a local file system search algorithm to discover all eligible test files. At the start, we also read the contents of the bundled unit test library and create an MLE module for it. For each test file found, we:

  1. Read its contents.
  2. Create an MLE module for the test file.
  3. Set up an MLE environment that includes both the unit test library module and the test file module.
  4. Create a DBMS_MLE context and import the test module, which triggers its evaluation.

The test library exports result counts and timing through MLE bindings. The CLI retrieves these results and the captured output to print summaries. After execution, the CLI removes the temporary modules and environments.


Help

Missing a feature? Something not working? Please open an issue in our repository.

Contributing

This project welcomes contributions from the community. Before submitting a pull request, please review our contribution guide.

Security

Please consult the security guide for our responsible security vulnerability disclosure process.

License

Copyright (c) 2026, Oracle and/or its affiliates.

Released under the Universal Permissive License v1.0 as shown at https://oss.oracle.com/licenses/upl/.