CtrlK
BlogDocsLog inGet started
Tessl Logo

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.

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

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)

docs

index.md

tile.json