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

module-import.mddocs/

Module Import and Resolution

Modern asynchronous module importing with TypeScript support and advanced resolution capabilities.

Capabilities

Asynchronous Import

Modern promise-based module importing with TypeScript and ESM compatibility.

/**
 * ESM import a module with additional TypeScript and ESM compatibility
 * @param id - Module identifier to import
 * @param opts - Optional resolve options and default export shortcut
 * @returns Promise resolving to module exports
 */
import<T = unknown>(
  id: string,
  opts?: JitiResolveOptions & { default?: true }
): Promise<T>;

Usage Examples:

import { createJiti } from "jiti";

const jiti = createJiti(import.meta.url);

// Import TypeScript module
const config = await jiti.import("./config.ts");

// Import with default export shortcut (mod?.default ?? mod)
const utils = await jiti.import("./utils.ts", { default: true });

// Import with specific type
interface UserConfig {
  apiKey: string;
  timeout: number;
}
const userConfig = await jiti.import<UserConfig>("./user-config.ts");

// Import JSON with type safety
const packageData = await jiti.import<{ version: string }>("./package.json");

// Import with resolve options
const module = await jiti.import("./module.ts", {
  conditions: ["import", "node"],
  try: true  // Don't throw on failure
});

ESM Resolution

Advanced module resolution with ESM import conditions and comprehensive options.

/**
 * Resolve module with ESM import conditions
 * @param id - Module identifier to resolve
 * @param opts - Resolution options or parent URL string
 * @returns Resolved module path or undefined if try option is used
 */
esmResolve(id: string, opts?: string | JitiResolveOptions): string;
esmResolve<T extends JitiResolveOptions = JitiResolveOptions>(
  id: string,
  opts?: T
): T["try"] extends true ? string | undefined : string;

Usage Examples:

const jiti = createJiti(import.meta.url);

// Basic resolution
const resolved = jiti.esmResolve("./config.ts");
console.log(resolved); // file:///path/to/config.ts

// Resolution with parent URL
const resolved = jiti.esmResolve("./utils", "/path/to/parent.js");

// Resolution with conditions
const resolved = jiti.esmResolve("package", {
  conditions: ["import", "node", "development"]
});

// Safe resolution that doesn't throw
const resolved = jiti.esmResolve("./maybe-missing", { try: true });
if (resolved) {
  console.log("Found:", resolved);
} else {
  console.log("Module not found");
}

// Resolution with specific parent URL
const resolved = jiti.esmResolve("./relative-module", {
  parentURL: "file:///specific/parent/dir/"
});

Resolution Options

Comprehensive options for controlling module resolution behavior.

interface JitiResolveOptions {
  /**
   * Export conditions to use during resolution
   * Common values: ["import", "require", "node", "browser", "development", "production"]
   */
  conditions?: string[];
  
  /**
   * Parent module URL for resolving relative imports
   */
  parentURL?: string | URL;
  
  /**
   * Don't throw on resolution failure, return undefined instead
   * @default false
   */
  try?: boolean;
}

Legacy Synchronous Import (Deprecated)

Synchronous CommonJS-style import functionality. Note: This API is deprecated and may be removed in future versions.

/**
 * @deprecated Prefer await jiti.import() for better compatibility
 * Synchronous module import similar to require()
 */
(id: string): any;

/**
 * @deprecated Prefer jiti.esmResolve() for better compatibility
 * Synchronous module resolution similar to require.resolve()
 */
resolve: {
  (id: string, options?: { paths?: string[] }): string;
  paths(request: string): string[] | null;
};

Migration Examples:

// ❌ Deprecated synchronous API
const config = jiti("./config.ts");
const resolved = jiti.resolve("./config.ts");

// ✅ Recommended asynchronous API
const config = await jiti.import("./config.ts");
const resolved = jiti.esmResolve("./config.ts");

Module Types and Interoperability

jiti provides seamless interoperability between ESM and CommonJS modules with smart default export handling.

Default Export Interoperability:

// TypeScript module with default export
// config.ts
export default { apiKey: "secret", timeout: 5000 };

// Import patterns
const config1 = await jiti.import("./config.ts"); // Full module object
const config2 = await jiti.import("./config.ts", { default: true }); // config2 === config1.default || config1

// Mixed exports module
// utils.ts
export const helper = () => "help";
export default { version: "1.0" };

const utils = await jiti.import("./utils.ts");
// utils = { helper: Function, default: { version: "1.0" } } + Proxy magic for interop
console.log(utils.helper()); // "help"
console.log(utils.version);  // "1.0" (thanks to interopDefault)

File Extension Handling:

jiti automatically handles various file extensions:

// All of these work automatically
await jiti.import("./config.ts");        // TypeScript
await jiti.import("./config.mts");       // TypeScript ESM
await jiti.import("./config.cts");       // TypeScript CommonJS
await jiti.import("./config.tsx");       // TypeScript + JSX
await jiti.import("./config.js");        // JavaScript
await jiti.import("./config.mjs");       // JavaScript ESM
await jiti.import("./config.cjs");       // JavaScript CommonJS
await jiti.import("./data.json");        // JSON

Error Handling

Comprehensive error handling for module import and resolution failures.

Import Error Handling:

try {
  const module = await jiti.import("./non-existent.ts");
} catch (error) {
  console.error("Import failed:", error.message);
  // Handle missing module
}

// Safe import with try option
const module = await jiti.import("./maybe-missing.ts", { try: true });
if (!module) {
  console.log("Module not found, using defaults");
}

Resolution Error Handling:

try {
  const resolved = jiti.esmResolve("./missing-module");
} catch (error) {
  console.error("Resolution failed:", error.message);
}

// Safe resolution
const resolved = jiti.esmResolve("./maybe-missing", { try: true });
if (!resolved) {
  console.log("Could not resolve module");
}

Advanced Usage Patterns

Dynamic Imports with Variables:

const configName = process.env.NODE_ENV || "development";
const config = await jiti.import(`./configs/${configName}.ts`);

// Conditional imports
const dbConfig = await jiti.import(
  process.env.NODE_ENV === "production" 
    ? "./db-prod.ts" 
    : "./db-dev.ts"
);

Plugin System with Dynamic Loading:

const pluginNames = ["auth", "logging", "cache"];
const plugins = await Promise.all(
  pluginNames.map(name => jiti.import(`./plugins/${name}.ts`))
);

// Type-safe plugin loading
interface Plugin {
  name: string;
  initialize: () => void;
}

const plugin = await jiti.import<Plugin>("./plugins/custom.ts");
plugin.initialize();

Alias Resolution:

// Create jiti with aliases
const jiti = createJiti(import.meta.url, {
  alias: {
    "@/*": "./src/*",
    "~/*": "./lib/*",
    "#components": "./src/components/index.ts"
  }
});

// Use aliases in imports
const utils = await jiti.import("@/utils/helpers.ts");
const lib = await jiti.import("~/common.ts");
const components = await jiti.import("#components");

docs

cli-tool.md

global-registration.md

index.md

instance-creation.md

module-import.md

transformation.md

tile.json