CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-expo-modules-core

The core infrastructure for Expo Modules architecture enabling seamless integration between React Native applications and native platform code.

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/

Expo Modules Core

Expo Modules Core provides the foundational infrastructure for the Expo Modules architecture, enabling seamless integration between React Native applications and native platform code. It offers a comprehensive set of APIs including native module proxies for cross-platform communication, event emitters for real-time event handling, shared objects and references for efficient memory management, and permission handling utilities for secure access control.

Package Information

  • Package Name: expo-modules-core
  • Package Type: npm
  • Language: TypeScript with native iOS and Android components
  • Installation: npm install expo-modules-core

Core Imports

import { 
  EventEmitter, 
  NativeModule, 
  SharedObject, 
  SharedRef,
  Platform,
  requireNativeModule,
  requireOptionalNativeModule,
  requireNativeViewManager,
  registerWebModule,
  uuid,
  reloadAppAsync,
  createSnapshotFriendlyRef,
  useReleasingSharedObject,
  createPermissionHook,
  CodedError,
  UnavailabilityError,
  PermissionStatus,
  type EventsMap,
  type PermissionResponse,
  type EventSubscription
} from "expo-modules-core";

For CommonJS:

const { 
  EventEmitter, 
  NativeModule, 
  requireNativeModule,
  requireOptionalNativeModule,
  Platform,
  uuid,
  reloadAppAsync,
  CodedError,
  UnavailabilityError,
  PermissionStatus
} = require("expo-modules-core");

Basic Usage

import { 
  EventEmitter, 
  requireNativeModule, 
  Platform,
  type EventSubscription 
} from "expo-modules-core";

// Create an event emitter for custom events
const emitter = new EventEmitter<{
  dataReceived: (data: string) => void;
  error: (error: Error) => void;
}>();

// Add event listeners
const subscription: EventSubscription = emitter.addListener("dataReceived", (data) => {
  console.log("Received:", data);
});

// Emit events
emitter.emit("dataReceived", "Hello from native!");

// Load a native module
try {
  const nativeModule = requireNativeModule("MyCustomModule");
  const result = await nativeModule.performOperation();
} catch (error) {
  console.log("Native module not available");
}

// Platform-specific code
const platformSpecificValue = Platform.select({
  ios: "iOS implementation",
  android: "Android implementation", 
  web: "Web implementation",
  default: "Fallback implementation"
});

// Clean up
subscription.remove();

Architecture

Expo Modules Core is built around several key architectural components:

  • Event System: Native-backed event emitters with full TypeScript support and automatic lifecycle management
  • Module Bridge: Direct access to native modules via JSI (JavaScript Interface) with fallback to bridge proxy
  • Shared Memory: Efficient memory sharing between JavaScript and native code via SharedObject and SharedRef
  • Platform Abstraction: Unified platform detection and environment utilities across iOS, Android, and web
  • Permission Management: React Hook-based permission system with standardized request/response patterns
  • Type Safety: Complete TypeScript integration with generic type preservation and native type definitions

Capabilities

Event Communication

Native-backed event system for real-time communication between JavaScript and native code, with full TypeScript support and automatic lifecycle management.

class EventEmitter<TEventsMap extends EventsMap = Record<never, never>> {
  addListener<EventName extends keyof TEventsMap>(
    eventName: EventName,
    listener: TEventsMap[EventName]
  ): EventSubscription;
  
  emit<EventName extends keyof TEventsMap>(
    eventName: EventName,
    ...args: Parameters<TEventsMap[EventName]>
  ): void;
}

interface EventSubscription {
  remove(): void;
}

Event Communication

Native Module Integration

Direct integration with native platform modules through JSI with automatic fallback to bridge proxy for backwards compatibility.

function requireNativeModule<ModuleType = any>(moduleName: string): ModuleType;
function requireOptionalNativeModule<ModuleType = any>(
  moduleName: string
): ModuleType | null;

class NativeModule<TEventsMap extends EventsMap = Record<never, never>>
  extends EventEmitter<TEventsMap> {
  ViewPrototypes?: { [viewName: string]: object };
}

Native Module Integration

Shared Memory Management

Efficient memory sharing between JavaScript and native code with manual memory management capabilities for performance-critical scenarios.

class SharedObject<TEventsMap extends EventsMap = Record<never, never>>
  extends EventEmitter<TEventsMap> {
  release(): void;
}

class SharedRef<
  TNativeRefType extends string = 'unknown',
  TEventsMap extends EventsMap = Record<never, never>
> extends SharedObject<TEventsMap> {
  nativeRefType: string;
}

Shared Memory Management

Platform Utilities

Cross-platform utilities for environment detection, platform-specific code execution, and browser capability checking.

interface Platform {
  OS: string;
  select: <T>(specifics: { [platform in PlatformSelectOSType]?: T }) => T;
  isDOMAvailable: boolean;
  canUseEventListeners: boolean;
  canUseViewport: boolean;
  isAsyncDebugging: boolean;
}

type PlatformSelectOSType = 'ios' | 'android' | 'web' | 'native' | 'electron' | 'default';

Platform Utilities

Permission Management

React Hook-based permission system with standardized request/response patterns and automatic lifecycle management.

enum PermissionStatus {
  GRANTED = 'granted',
  UNDETERMINED = 'undetermined', 
  DENIED = 'denied'
}

interface PermissionResponse {
  status: PermissionStatus;
  expires: PermissionExpiration;
  granted: boolean;
  canAskAgain: boolean;
}

function createPermissionHook<Permission extends PermissionResponse, Options extends object>(
  methods: PermissionHookMethods<Permission, Options>
): (options?: PermissionHookOptions<Options>) => 
  [Permission | null, () => Promise<Permission>, () => Promise<Permission>];

Permission Management

Native View Components

Integration system for React Native components backed by native view managers, with automatic prototype binding and lifecycle management.

function requireNativeViewManager<P>(
  moduleName: string,
  viewName?: string
): ComponentType<P>;

Native View Components

UUID Generation

Native-backed UUID generation with support for both random (v4) and deterministic (v5) UUID creation.

interface UUID {
  v4(): string;
  v5(name: string, namespace: string | number[]): string;
  namespace: typeof Uuidv5Namespace;
}

enum Uuidv5Namespace {
  dns = '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
  url = '6ba7b811-9dad-11d1-80b4-00c04fd430c8',
  oid = '6ba7b812-9dad-11d1-80b4-00c04fd430c8',
  x500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8'
}

UUID Generation

Error Handling

Standardized error classes with error codes for consistent error handling across Expo modules.

class CodedError extends Error {
  code: string;
  info?: any;
  constructor(code: string, message: string);
}

class UnavailabilityError extends CodedError {
  constructor(moduleName: string, propertyName: string);
}

Error Handling

App Utilities

Additional utility functions for application lifecycle management, app reloading, and React development helpers.

function reloadAppAsync(reason?: string): Promise<void>;
function createSnapshotFriendlyRef<T>(): RefObject<T | null>;

App Utilities

React Integration

React hooks and utilities for seamless integration with React components and automatic resource management.

function useReleasingSharedObject<TSharedObject extends SharedObject>(
  factory: () => TSharedObject,
  dependencies: DependencyList
): TSharedObject;

function createSnapshotFriendlyRef<T>(): RefObject<T | null>;

Shared Memory Management

Deprecated APIs

Legacy Event Emitter

Deprecated event emitter class for backward compatibility with older modules.

/**
 * @deprecated Use EventEmitter instead
 */
class LegacyEventEmitter {
  constructor(nativeModule: any);
  addListener<T>(eventName: string, listener: (event: T) => void): EventSubscription;
  removeAllListeners(eventName: string): void;
  removeSubscription(subscription: EventSubscription): void;
  emit(eventName: string, ...params: any[]): void;
}

Legacy Native Modules Proxy

Deprecated proxy object for accessing native modules.

/**
 * @deprecated Use requireNativeModule or requireOptionalNativeModule instead
 */
const NativeModulesProxy: Record<string, ProxyNativeModule>;

Global Types

// Core event system types
type EventsMap = Record<string, (...args: any[]) => void>;
type PermissionExpiration = 'never' | number;

// Typed array support
type TypedArray = IntBasedTypedArray | UintBasedTypedArray | FloatBasedTypedArray;
type IntBasedTypedArray = Int8Array | Int16Array | Int32Array;
type UintBasedTypedArray = Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;
type FloatBasedTypedArray = Float32Array | Float64Array;

// Platform types
type PlatformSelectOSType = 'ios' | 'android' | 'web' | 'native' | 'electron' | 'default';

// Legacy module proxy interface
interface ProxyNativeModule {
  addListener?(eventName: string): void;
  removeListeners?(count: number): void;
  [key: string]: any;
}

// React integration types
type ComponentType<P = {}> = React.ComponentType<P>;
interface RefObject<T> {
  readonly current: T | null;
}
type DependencyList = ReadonlyArray<any>;

// Permission system types
interface PermissionHookMethods<Permission extends PermissionResponse, Options = never> {
  requestMethod: (options?: Options) => Promise<Permission>;
  getMethod: (options?: Options) => Promise<Permission>;
}

interface PermissionHookOptions<Options extends object> extends Options {
  get?: boolean;
  request?: boolean;
}

// Global Expo namespace types
interface ViewConfig {
  validAttributes: Record<string, any>;
  directEventTypes: Record<string, { registrationName: string }>;
}

interface ExpoGlobal {
  modules: Record<string, any>;
  expoModulesCoreVersion?: { major: number; minor: number; patch: number };
  cacheDir?: string;
  documentsDir?: string;
  uuidv4(): string;
  uuidv5(name: string, namespace: string): string;
  getViewConfig(moduleName: string, viewName?: string): ViewConfig | null;
  reloadAppAsync(reason: string): Promise<void>;
}

declare global {
  const expo: ExpoGlobal;
}

docs

app-utilities.md

error-handling.md

event-communication.md

index.md

native-modules.md

native-views.md

permissions.md

platform-utilities.md

shared-memory.md

uuid-generation.md

tile.json