CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rollup--pluginutils

A set of utility functions commonly used by Rollup plugins

Pending
Overview
Eval results
Files

code-generation.mddocs/

Code Generation

Utilities for generating valid JavaScript code, identifiers, and ES modules from data structures. These functions help create bundle-safe code and transform data into tree-shakable modules.

Capabilities

makeLegalIdentifier

Converts strings into valid JavaScript identifiers that are safe for use in bundles. Handles special characters, reserved words, and naming conflicts.

/**
 * Constructs a bundle-safe identifier from a string
 * Converts invalid characters and handles reserved words
 * @param str - The string to convert to a legal identifier
 * @returns A valid JavaScript identifier
 */
function makeLegalIdentifier(str: string): string;

Parameters:

  • str (string): The string to convert to a legal JavaScript identifier

Returns: A valid JavaScript identifier string

Transformation Rules:

  • Converts hyphens to camelCase: 'foo-bar''fooBar'
  • Replaces invalid characters with underscores
  • Prefixes with underscore if starts with number: '123abc''_123abc'
  • Handles reserved words: 'typeof''_typeof'
  • Returns '_' for empty strings

Usage Examples:

import { makeLegalIdentifier } from "@rollup/pluginutils";

// Basic transformations
makeLegalIdentifier('foo-bar'); // 'fooBar'
makeLegalIdentifier('my-component'); // 'myComponent'
makeLegalIdentifier('foo_bar'); // 'foo_bar' (already valid)

// Handle special characters
makeLegalIdentifier('foo@bar'); // 'foo_bar'
makeLegalIdentifier('foo.bar'); // 'foo_bar'
makeLegalIdentifier('foo bar'); // 'foo_bar'

// Reserved words and edge cases
makeLegalIdentifier('typeof'); // '_typeof'
makeLegalIdentifier('class'); // '_class'
makeLegalIdentifier('123abc'); // '_123abc'
makeLegalIdentifier(''); // '_'

// Use in code generation
export default function myPlugin() {
  return {
    generateBundle(options, bundle) {
      for (const [fileName, chunk] of Object.entries(bundle)) {
        if (chunk.type === 'chunk') {
          // Generate safe variable names from file names
          const varName = makeLegalIdentifier(
            fileName.replace(/\.[^.]+$/, '') // remove extension
          );
          
          // Use in generated code
          const wrapper = `
            const ${varName} = (function() {
              ${chunk.code}
              return exports;
            })();
          `;
          
          chunk.code = wrapper;
        }
      }
    }
  };
}

// Generate imports from module names
function generateImportName(moduleName) {
  // Convert scoped packages: '@rollup/plugin-utils' → 'rollupPluginUtils'
  const cleaned = moduleName.replace(/^@/, '').replace(/[^\w]/g, '-');
  return makeLegalIdentifier(cleaned);
}

generateImportName('@rollup/plugin-utils'); // 'rollupPluginUtils'
generateImportName('lodash-es'); // 'lodashEs'
generateImportName('my-library/sub-module'); // 'myLibrarySubModule'

dataToEsm

Transforms JavaScript objects into tree-shakable ES module source code. Generates both named exports and default exports with comprehensive formatting options.

/**
 * Transforms objects into tree-shakable ES Module imports
 * Generates both named and default exports with formatting options
 * @param data - An object to transform into an ES module
 * @param options - Configuration options for code generation
 * @returns Generated ES module source code
 */
function dataToEsm(data: unknown, options?: DataToEsmOptions): string;

interface DataToEsmOptions {
  compact?: boolean;
  includeArbitraryNames?: boolean;
  indent?: string;
  namedExports?: boolean;
  objectShorthand?: boolean;
  preferConst?: boolean;
}

Parameters:

  • data (unknown): The data to convert to ES module format
  • options (DataToEsmOptions, optional): Configuration options

DataToEsmOptions:

  • compact?: boolean - Minimize whitespace in generated code (default: false)
  • includeArbitraryNames?: boolean - Support non-identifier keys as named exports using arbitrary module namespace identifier names (default: false)
  • indent?: string - Indentation string for formatting (default: '\t')
  • namedExports?: boolean - Generate named exports for object properties (default: true)
  • objectShorthand?: boolean - Use ES6 object property shorthand syntax (default: true)
  • preferConst?: boolean - Use const instead of var for declarations (default: false)

Returns: Generated ES module source code as a string

Supported Data Types:

  • Objects with property values
  • Arrays with numeric indices
  • Primitive values (string, number, boolean)
  • Special values (Date, RegExp, BigInt, Symbol, Infinity, NaN, undefined)
  • Nested structures

Usage Examples:

import { dataToEsm } from "@rollup/pluginutils";

// Basic object transformation
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  debug: true
};

const moduleCode = dataToEsm(config, {
  compact: false,
  indent: '  ',
  preferConst: true,
  objectShorthand: true,
  namedExports: true
});

console.log(moduleCode);
/*
export const apiUrl = 'https://api.example.com';
export const timeout = 5000;
export const debug = true;
export default { apiUrl, timeout, debug };
*/

// Complex data with formatting options
const complexData = {
  users: ['alice', 'bob'],
  settings: {
    theme: 'dark',
    notifications: true
  },
  created: new Date('2023-01-01'),
  pattern: /^\w+$/,
  bigNumber: BigInt('9007199254740991')
};

const compactCode = dataToEsm(complexData, {
  compact: true,
  namedExports: true,
  includeArbitraryNames: false
});

// Use in plugin for configuration files
export default function configPlugin(options = {}) {
  return {
    resolveId(id) {
      if (id === 'virtual:config') {
        return id;
      }
    },
    
    load(id) {
      if (id === 'virtual:config') {
        // Convert plugin options to ES module
        return dataToEsm(options, {
          preferConst: true,
          objectShorthand: true,
          namedExports: true
        });
      }
    }
  };
}

// Handle non-identifier keys
const dataWithSpecialKeys = {
  'normal-key': 'value1',
  'special@key': 'value2',
  '123numeric': 'value3'
};

const codeWithArbitraryNames = dataToEsm(dataWithSpecialKeys, {
  includeArbitraryNames: true,
  namedExports: true
});

/*
export const normalKey = 'value1';
export { 'special@key' as specialKey };
export { '123numeric' as _123numeric };
export default { normalKey, 'special@key': specialKey, '123numeric': _123numeric };
*/

// Generate module from JSON file
export default function jsonPlugin() {
  return {
    transform(code, id) {
      if (id.endsWith('.json')) {
        const data = JSON.parse(code);
        
        // Convert JSON to tree-shakable ES module
        const esModule = dataToEsm(data, {
          preferConst: true,
          namedExports: true,
          objectShorthand: true
        });
        
        return { code: esModule };
      }
    }
  };
}

Common Patterns

Configuration Module Generation

import { dataToEsm, makeLegalIdentifier } from "@rollup/pluginutils";

export default function configPlugin(userConfig = {}) {
  const defaultConfig = {
    apiEndpoint: 'https://api.example.com',
    timeout: 5000,
    retries: 3,
    debug: false
  };
  
  const finalConfig = { ...defaultConfig, ...userConfig };
  
  return {
    resolveId(id) {
      if (id === 'virtual:app-config') return id;
    },
    
    load(id) {
      if (id === 'virtual:app-config') {
        // Generate tree-shakable config module
        return dataToEsm(finalConfig, {
          preferConst: true,
          namedExports: true,
          objectShorthand: true,
          compact: false
        });
      }
    }
  };
}

// Usage in application code:
// import { apiEndpoint, timeout } from 'virtual:app-config';

Dynamic Import Generation

import { makeLegalIdentifier, dataToEsm } from "@rollup/pluginutils";

export default function dynamicImportPlugin(options = {}) {
  const { modules = {} } = options;
  
  return {
    generateBundle() {
      // Generate loader module with dynamic imports
      const loaderCode = Object.entries(modules)
        .map(([key, modulePath]) => {
          const importName = makeLegalIdentifier(key);
          return `
export const ${importName} = () => import('${modulePath}');
          `.trim();
        })
        .join('\n');
      
      // Also generate static config
      const configModule = dataToEsm({
        availableModules: Object.keys(modules),
        moduleCount: Object.keys(modules).length
      });
      
      this.emitFile({
        type: 'asset',
        fileName: 'dynamic-loader.js',
        source: loaderCode
      });
      
      this.emitFile({
        type: 'asset',
        fileName: 'loader-config.js',
        source: configModule
      });
    }
  };
}

Safe Variable Generation

import { makeLegalIdentifier } from "@rollup/pluginutils";

export default function namespacePlugin(options = {}) {
  const { namespace = 'MyLibrary' } = options;
  
  return {
    generateBundle(options, bundle) {
      for (const [fileName, chunk] of Object.entries(bundle)) {
        if (chunk.type === 'chunk') {
          // Generate safe namespace from file name
          const safeName = makeLegalIdentifier(
            fileName.replace(/\.[^.]+$/, '') // remove extension
          );
          
          // Wrap exports in namespace
          const namespacedCode = `
(function(global) {
  'use strict';
  
  // Original code
  ${chunk.code}
  
  // Create namespace
  global.${namespace} = global.${namespace} || {};
  global.${namespace}.${safeName} = exports;
  
})(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this);
          `;
          
          chunk.code = namespacedCode;
        }
      }
    }
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-rollup--pluginutils

docs

ast-analysis.md

code-generation.md

file-processing.md

index.md

regex-utilities.md

tile.json