CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jiti

Runtime TypeScript and ESM support for Node.js with seamless interoperability between ESM and CommonJS.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

global-registration.mddocs/

Global Registration and ESM Loader

Global ESM loader registration and native runtime mode for seamless TypeScript support across Node.js applications.

Capabilities

Global ESM Loader Registration

Register jiti as a global ESM loader to automatically handle TypeScript and JSX files across your entire Node.js application.

// Import for automatic global registration
import "jiti/register";

Usage Examples:

// Method 1: Import in your entry file
import "jiti/register";
import { config } from "./config.ts"; // Automatically works

console.log(config);
# Method 2: Use Node.js --import flag
node --import jiti/register index.js

# Method 3: Use via environment variable
NODE_OPTIONS="--import jiti/register" node index.js

Requirements:

  • Node.js version 20 or higher (for global hooks support)
  • ESM environment (type: "module" in package.json or .mjs files)

Native Runtime Mode

Lightweight mode that uses runtime's native import.meta.resolve and dynamic import() capabilities without transformation.

import { createJiti } from "jiti/native";

/**
 * Creates a native jiti instance with limited API surface
 * @param parentURL - Parent URL for resolution context
 * @param jitiOptions - Limited options for native mode
 * @returns Jiti instance with native-only capabilities
 */
function createJiti(parentURL?: string | URL, jitiOptions?: JitiOptions): NativeJiti;

interface NativeJiti {
  // ✅ Supported methods
  import<T>(id: string, opts?: JitiResolveOptions & { default?: true }): Promise<T>;
  esmResolve(id: string, opts?: string | JitiResolveOptions): string;
  
  // ❌ Unsupported methods (throw errors)
  (id: string): never; // Throws: "jiti() is not supported in native mode, use jiti.import() instead"
  transform(opts: TransformOptions): never; // Throws: "transform() is not supported in native mode"
  evalModule(source: string, options?: EvalModuleOptions): never; // Throws: "evalModule() is not supported in native mode"
  resolve: never; // Throws: "resolve() is not supported in native mode"
}

Usage Examples:

import { createJiti } from "jiti/native";

// Create native jiti instance
const jiti = createJiti(import.meta.url);

// Only import() and esmResolve() work in native mode
const module = await jiti.import("./config.js");
const resolved = jiti.esmResolve("./utils.js");

// These methods throw errors in native mode:
try {
  jiti.transform({ source: "code" }); // Throws: not supported in native mode
} catch (error) {
  console.error(error.message); // "`transform()` is not supported in native mode"
}

try {
  jiti.evalModule("code"); // Throws: not supported in native mode
} catch (error) {
  console.error(error.message); // "`evalModule()` is not supported in native mode"
}

try {
  jiti("./module"); // Throws: not supported in native mode
} catch (error) {
  console.error(error.message); // "`jiti()` is not supported in native mode, use `jiti.import()` instead"
}

ESM Loader Implementation

The global ESM loader provides automatic transformation for TypeScript and other supported file types through Node.js's module loading hooks.

Supported File Types:

  • .ts - TypeScript files
  • .tsx - TypeScript with JSX
  • .mts - TypeScript ES modules
  • .cts - TypeScript CommonJS modules
  • .js - JavaScript (conditionally transformed)
  • .json - JSON modules with proper ESM/CommonJS detection

Loader Features:

// ESM Loader Hooks (internal implementation)
export async function resolve(specifier: string, context: ResolveContext, nextResolve: Function): Promise<ResolveResult>;
export async function load(url: string, context: LoadContext, nextLoad: Function): Promise<LoadResult>;

Configuration via Environment Variables

Configure the global loader behavior using environment variables.

Environment Variables:

  • JITI_DEBUG - Enable debug logging for loader operations
  • JITI_JSX - Enable JSX transformation globally
  • JITI_FS_CACHE - Control filesystem caching for loader
  • JITI_SOURCE_MAPS - Enable source maps in loader transformations
  • JITI_MODULE_CACHE - Control module caching for loader
  • JITI_INTEROP_DEFAULT - Control default export interoperability
  • JITI_ALIAS - Set module aliases (JSON string)
  • JITI_NATIVE_MODULES - Native modules list (JSON string)
  • JITI_TRANSFORM_MODULES - Modules to transform (JSON string)
  • JITI_TRY_NATIVE - Try native import first

Usage Examples:

# Enable JSX and debug mode globally
JITI_JSX=1 JITI_DEBUG=1 node --import jiti/register app.js

# Disable caching for development
JITI_FS_CACHE=false node --import jiti/register dev-server.js

Advanced Registration Patterns

Conditional Registration:

// Only register in development
if (process.env.NODE_ENV === "development") {
  await import("jiti/register");
}

// Import your TypeScript modules after registration
const { devUtils } = await import("./dev-utils.ts");

Application-Wide TypeScript Support:

// main.ts - Entry point with global registration
import "jiti/register";

// Now all imports in your app automatically support TypeScript
import { config } from "./config/app.ts";
import { routes } from "./routes/index.ts";
import { middleware } from "./middleware/auth.ts";

async function startApp() {
  const server = (await import("./server.ts")).default;
  server.start();
}

startApp();

Library Development:

// Enable TypeScript for your library's development
// lib/index.ts
export { LibraryClass } from "./core.ts";
export type { LibraryOptions } from "./types.ts";

// During development, use jiti for testing
// test/setup.ts
import "jiti/register";
import { test } from "./lib/index.ts"; // Uses TypeScript directly

Native Mode Limitations and Benefits

Benefits of Native Mode:

  • Extremely lightweight - no Babel dependencies
  • Faster startup time
  • Uses runtime's native capabilities
  • Better compatibility with modern Node.js features

Limitations:

  • No TypeScript transformation (only .js, .mjs, .cjs files)
  • No JSX support
  • No custom syntax transformations
  • Limited error handling compared to full jiti

When to Use Native Mode:

// ✅ Good for native mode - JavaScript only
const jiti = createJiti("jiti/native");
await jiti.import("./config.js");
await jiti.import("./utils.mjs");

// ❌ Not suitable for native mode - needs transformation
await jiti.import("./config.ts"); // TypeScript
await jiti.import("./component.tsx"); // JSX

Integration with Build Tools

Development vs Production:

// Development: Use global registration for TypeScript
if (process.env.NODE_ENV === "development") {
  await import("jiti/register");
  const { devConfig } = await import("./config.dev.ts");
} else {
  // Production: Use compiled JavaScript
  const { prodConfig } = await import("./config.prod.js");
}

Testing Setup:

// vitest.config.js or jest.config.js
export default {
  setupFilesAfterEnv: ["jiti/register"],
  // Now test files can import TypeScript directly
};

Development Scripts:

{
  "scripts": {
    "dev": "node --import jiti/register src/dev-server.ts",
    "test": "NODE_OPTIONS='--import jiti/register' vitest",
    "debug": "JITI_DEBUG=1 node --import jiti/register --inspect src/index.ts"
  }
}

Error Handling and Debugging

Loader Error Handling:

The ESM loader provides detailed error information for transformation failures:

// If a TypeScript file has syntax errors, the loader will provide:
// - File location with line/column numbers
// - Syntax error details
// - Code frame showing the problematic code

try {
  await import("./broken-syntax.ts");
} catch (error) {
  console.error("TypeScript compilation failed:");
  console.error(error.message);
  console.error(error.location); // File:line:column
}

Debug Mode:

# Enable debug logging to see loader operations
JITI_DEBUG=1 node --import jiti/register app.ts

Output shows:

  • File resolution details
  • Transformation decisions
  • Cache hit/miss information
  • Performance timings

Compatibility and Runtime Support

Node.js Version Requirements:

  • Global registration: Node.js 20+ (requires module hooks)
  • Native mode: Node.js 18+ (requires import.meta.resolve)
  • Full jiti mode: Node.js 16+

Runtime Detection:

// jiti automatically detects runtime capabilities
const jiti = createJiti(import.meta.url, {
  tryNative: true // Try native import first, fallback to transformation
});

// In Bun, this automatically uses native capabilities
// In Node.js, this uses transformation when needed
const module = await jiti.import("./file.ts");

Cross-Platform Support:

// Works across different JavaScript runtimes
import { createJiti } from "jiti/native";

// Deno support
const jiti = createJiti(import.meta.url);
const module = await jiti.import("./config.ts");

// Bun support with enhanced native capabilities
const jiti = createJiti(import.meta.url, {
  tryNative: true // Bun has excellent native TypeScript support
});

docs

cli-tool.md

global-registration.md

index.md

instance-creation.md

module-import.md

transformation.md

tile.json