or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-embroider--addon-shim

Make v2 addons work in non-Embroider apps by providing compatibility shim that transforms v2 addon structure into v1-compatible format.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@embroider/addon-shim@1.10.x

To install, run

npx @tessl/cli install tessl/npm-embroider--addon-shim@1.10.0

index.mddocs/

@embroider/addon-shim

@embroider/addon-shim provides a compatibility shim that enables Ember.js v2 addons to work in classic (non-Embroider) applications. The shim transforms v2 addon structure into v1-compatible format, handling module resolution, asset bundling, and build pipeline integration without requiring users to migrate to Embroider.

Package Information

  • Package Name: @embroider/addon-shim
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @embroider/addon-shim

Core Imports

const { addonV1Shim } = require("@embroider/addon-shim");

For TypeScript (type imports only):

import type { ShimOptions, AddonInstance } from "@embroider/addon-shim";
const { addonV1Shim } = require("@embroider/addon-shim");

Basic Usage

// Create an addon-main.js file in your v2 addon
const { addonV1Shim } = require('@embroider/addon-shim');
module.exports = addonV1Shim(__dirname);

With configuration options:

const { addonV1Shim } = require('@embroider/addon-shim');

module.exports = addonV1Shim(__dirname, {
  disabled(options) {
    // Conditionally disable shim functionality
    let welcomeConfig = options['ember-welcome-page'] || {};
    return process.env.EMBER_ENV === 'production' && !welcomeConfig.enabled;
  },
  autoImportCompat: {
    customizeMeta(meta) {
      // Customize ember-auto-import metadata
      return meta;
    }
  }
});

Architecture

The addon shim operates as a bridge between v2 and v1 addon architectures:

  • V1 Compatibility Layer: Implements v1 addon lifecycle hooks (included, treeForApp, treeForPublic, etc.)
  • Asset Management: Maps v2 app-js and public-assets configurations to v1 Broccoli trees
  • Auto-Import Integration: Manages registration with ember-auto-import for proper module resolution
  • Development Detection: Automatically detects development vs production environments
  • Conditional Functionality: Supports runtime disabling of shim features based on configuration

Capabilities

Main Shim Function

Creates a v1-compatible addon instance from a v2 addon directory and optional configuration.

/**
 * Creates a v1-compatible addon instance from a v2 addon
 * @param directory - The directory path of the v2 addon
 * @param options - Optional configuration for the shim
 * @returns A v1 addon instance object with lifecycle hooks
 */
function addonV1Shim(directory: string, options?: ShimOptions): AddonInstance;

interface AddonInstance {
  /** The name of the addon from package.json */
  name: string;
  /** Package information from package.json */
  pkg: PackageInfo;
  /** Parent addon instance or project */
  parent: AddonInstance | Project;
  /** Project instance (root project) */
  project: Project;
  /** App instance (if directly under app) */
  app?: AppInstance;
  /** Broccoli tree generator function */
  treeGenerator: (dir: string) => BroccoliTree;
  /** V1 addon lifecycle hook for initialization and registration */
  included(this: AddonInstance, ...args: unknown[]): void;
  /** V1 addon hook for providing app-js files to the consuming application */
  treeForApp(this: AddonInstance): BroccoliTree | undefined;
  /** V1 addon hook for addon files (always returns undefined for shim) */
  treeForAddon(): undefined;
  /** V1 addon hook for public assets to be served by the application */
  treeForPublic(this: AddonInstance): BroccoliTree | undefined;
  /** V1 addon hook for cache key generation for Broccoli trees */
  cacheKeyForTree(this: AddonInstance, treeType: string): string;
  /** V1 addon hook to determine if addon is under development */
  isDevelopingAddon(this: AddonInstance): boolean;
  /** Legacy method for v2 addon registration (backward compatibility) */
  registerV2Addon(this: AddonInstance, name: string, root: string): void;
  /** Find the host app instance */
  _findHost(): AppInstance;
  /** Super method for calling parent implementation */
  _super: { included: { apply: (context: any, args: unknown[]) => void } };
}

Configuration Options

Optional configuration interface for customizing shim behavior.

interface ShimOptions {
  /** 
   * Function to conditionally disable shim functionality
   * @param options - Parent options from consuming app or addon
   * @returns true to disable shim features, false to enable
   */
  disabled?: (options: any) => boolean;

  /** Configuration for ember-auto-import integration */
  autoImportCompat?: {
    /**
     * Customize the ember-addon metadata used by ember-auto-import
     * @param meta - Original addon metadata from package.json
     * @returns Modified addon metadata
     */
    customizeMeta?: (meta: AddonMeta) => AddonMeta;
  };
}

interface AddonMeta {
  /** Version of the ember-addon format (must be 2) */
  version: 2;
  /** Type of addon */
  type: "addon";
  /** Main entry point for the addon */
  main?: string;
  /** Order index for controlling addon loading order */
  "order-index"?: number;
  /** Whether this addon is a lazy engine */
  "lazy-engine"?: boolean;
  /** Indicates this addon was auto-upgraded from v1 format */
  "auto-upgraded"?: true;
  /** App-js mapping for JavaScript files to be included in the app */
  "app-js"?: Record<string, string>;
  /** FastBoot-specific JavaScript files */
  "fastboot-js"?: Record<string, string>;
  /** Modules that should be implicitly imported */
  "implicit-modules"?: string[];
  /** Scripts that should be implicitly included */
  "implicit-scripts"?: string[];
  /** Styles that should be implicitly included */
  "implicit-styles"?: string[];
  /** Test modules that should be implicitly imported */
  "implicit-test-modules"?: string[];
  /** Test scripts that should be implicitly included */
  "implicit-test-scripts"?: string[];
  /** Test styles that should be implicitly included */
  "implicit-test-styles"?: string[];
  /** Public assets mapping for static files */
  "public-assets"?: Record<string, string>;
  /** Package name remapping for dependencies */
  "renamed-packages"?: Record<string, string>;
  /** Module name remapping for imports */
  "renamed-modules"?: Record<string, string>;
}

Types

/** Broccoli tree type representing a file tree structure */
type BroccoliTree = any;

/** Validation result for ember-auto-import presence and version */
type AutoImportInfo = 
  | { present: false }
  | { present: true; version: string; satisfiesV2: false }
  | { present: true; version: string; satisfiesV2: true; instance: EAI2Instance };

interface EAI2Instance {
  /** Root directory of the ember-auto-import addon */
  root: string;
  /** Register a v2 addon with ember-auto-import */
  registerV2Addon(name: string, root: string): void;
  /** Get the current ember-auto-import leader (v2.10.0+) */
  leader?(): {
    registerV2Addon(name: string, root: string, options?: ShimOptions['autoImportCompat']): void;
  };
}

/** Additional types */
interface Project {
  /** Root directory of the project */
  root: string;
  /** Project addons */
  addons: AddonInstance[];
}

interface AppInstance {
  /** App project */
  project: Project;
}

interface PackageInfo {
  /** Package name */
  name: string;
  /** Package version */
  version: string;
  /** Package dependencies */
  dependencies?: Record<string, string>;
  /** Package devDependencies */
  devDependencies?: Record<string, string>;
  /** Ember addon metadata */
  "ember-addon"?: AddonMeta | { version?: 1; main?: string; };
}

Error Handling

The shim performs validation and throws errors for common misconfigurations:

  • Invalid v2 metadata: Throws if package.json doesn't contain valid ember-addon.version: 2
  • Missing ember-auto-import: Throws if parent v1 addon doesn't have ember-auto-import dependency
  • Incompatible ember-auto-import version: Throws if ember-auto-import version is < 2.0.0

Example error messages:

"did not find valid v2 addon metadata in <package-name>"
"<parent-name> needs to depend on ember-auto-import in order to use <addon-name>"
"<parent-name> has ember-auto-import <version> which is not new enough to use <addon-name>. It needs to upgrade to >=2.0"

Compatibility Requirements

  • Ember.js: v3.13 or above
  • Ember CLI: v2.13 or above
  • Node.js: v12, v14, or v16+ (as per package.json engines)
  • ember-auto-import: v2.0.0 or above (required by consuming v1 addons)