CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-config-universe

Shared ESLint configs for internal Expo projects providing multiple presets for different environments.

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

extension-utilities.mddocs/

Extension Utilities

Utility functions and constants for computing platform-specific file extensions used internally by ESLint Config Universe. These utilities are primarily for advanced customization and understanding how the configurations handle React Native and Expo platform-specific files.

Capabilities

Extension Constants

Pre-defined arrays of file extensions for different languages and platforms.

const { jsExtensions, tsExtensions, platformSubextensions } = require('eslint-config-universe/shared/extensions');

// JavaScript file extensions
jsExtensions: ['.js', '.jsx']

// TypeScript file extensions  
tsExtensions: ['.ts', '.tsx', '.d.ts']

// Platform-specific sub-extensions for React Native/Expo
platformSubextensions: ['.android', '.ios', '.web', '.native']

Extension Computation Function

Function that computes all possible file extension combinations for Expo and React Native projects.

const { computeExpoExtensions } = require('eslint-config-universe/shared/extensions');

/**
 * Computes all possible Expo file extensions by combining base extensions 
 * with platform sub-extensions and optional .expo prefix
 * @param baseExtensions - Array of base file extensions (e.g., ['.js', '.ts'])
 * @param platformSubextensions - Array of platform-specific extensions (e.g., ['.android', '.ios'])
 * @returns Array of all computed extension combinations
 */
function computeExpoExtensions(baseExtensions: string[], platformSubextensions: string[]): string[];

Usage Examples:

const { 
  jsExtensions,
  tsExtensions, 
  platformSubextensions,
  computeExpoExtensions
} = require('eslint-config-universe/shared/extensions');

// Get all JavaScript extensions
console.log(jsExtensions);
// Output: ['.js', '.jsx']

// Get all TypeScript extensions
console.log(tsExtensions);
// Output: ['.ts', '.tsx', '.d.ts']

// Get platform sub-extensions
console.log(platformSubextensions);
// Output: ['.android', '.ios', '.web', '.native']

// Compute all possible extensions for JavaScript
const jsExpoExtensions = computeExpoExtensions(jsExtensions, platformSubextensions);
console.log(jsExpoExtensions);
// Output: [
//   '.js', '.jsx',                    // Base extensions
//   '.android.js', '.android.jsx',    // Android-specific
//   '.ios.js', '.ios.jsx',           // iOS-specific
//   '.web.js', '.web.jsx',           // Web-specific
//   '.native.js', '.native.jsx',     // Native-specific
//   '.expo.js', '.expo.jsx',         // Expo base
//   '.expo.android.js', '.expo.android.jsx', // Expo + Android
//   '.expo.ios.js', '.expo.ios.jsx', // Expo + iOS
//   '.expo.web.js', '.expo.web.jsx', // Expo + Web
//   '.expo.native.js', '.expo.native.jsx' // Expo + Native
// ]

// Compute all possible extensions for both JS and TS
const allExtensions = computeExpoExtensions(
  [...jsExtensions, ...tsExtensions],
  platformSubextensions
);
console.log(allExtensions.length); // 30 different extension combinations

Extension Resolution Logic

The computeExpoExtensions function uses the following algorithm:

// Simplified implementation logic
function computeExpoExtensions(baseExtensions, platformSubextensions) {
  const expoExtensions = [];
  
  // For each expo prefix (.expo or none)
  for (const expo of ['.expo', '']) {
    // For each platform (or none)
    for (const platform of [...platformSubextensions, '']) {
      // For each base extension
      for (const base of baseExtensions) {
        // Combine: [expo][platform][base]
        expoExtensions.push(`${expo}${platform}${base}`);
      }
    }
  }
  
  return expoExtensions;
}

Platform-Specific File Resolution

Understanding how React Native and Expo resolve platform-specific files:

Resolution Priority

React Native resolves files in the following order:

  1. Platform-specific with exact match: Component.ios.js
  2. Platform-specific with native fallback: Component.native.js
  3. Platform-agnostic: Component.js

Expo Extensions

Expo adds an additional layer with .expo prefix:

  1. Expo + platform-specific: Component.expo.ios.js
  2. Expo platform-agnostic: Component.expo.js
  3. Standard React Native resolution continues...

Common Patterns

// File resolution examples:

// For iOS build of Expo app:
// 1. Button.expo.ios.tsx    (Expo iOS-specific TypeScript)
// 2. Button.ios.tsx         (iOS-specific TypeScript)
// 3. Button.native.tsx      (Native-specific TypeScript)
// 4. Button.expo.tsx        (Expo-specific TypeScript)
// 5. Button.tsx             (Generic TypeScript)

// For web build of Expo app:
// 1. Button.expo.web.tsx    (Expo web-specific)
// 2. Button.web.tsx         (Web-specific)
// 3. Button.expo.tsx        (Expo-specific)
// 4. Button.tsx             (Generic)

// For Android React Native app (no Expo):
// 1. Button.android.tsx     (Android-specific)
// 2. Button.native.tsx      (Native-specific)
// 3. Button.tsx             (Generic)

Custom Configuration Usage

Using extension utilities for custom ESLint configurations:

// Custom ESLint config using extension utilities
const { computeExpoExtensions, jsExtensions, tsExtensions } = require('eslint-config-universe/shared/extensions');

const customPlatforms = ['.mobile', '.desktop', '.tablet'];
const allExtensions = computeExpoExtensions(
  [...jsExtensions, ...tsExtensions],
  customPlatforms
);

module.exports = {
  extends: ['universe'],
  settings: {
    'import/extensions': allExtensions,
    'import/resolver': {
      node: { extensions: allExtensions }
    }
  },
  overrides: [
    {
      files: ['**/*.mobile.*'],
      rules: {
        // Mobile-specific rules
        'no-console': 'error'
      }
    },
    {
      files: ['**/*.desktop.*'],
      env: { electron: true },
      rules: {
        // Desktop-specific rules
        'node/no-unsupported-features/node-builtins': 'off'
      }
    }
  ]
};

Internal Usage

These utilities are used internally by the universe configurations:

Native Configuration Usage

// From native.js
const { computeExpoExtensions, jsExtensions, tsExtensions, platformSubextensions } = require('./shared/extensions');

const allExtensions = computeExpoExtensions(
  [...jsExtensions, ...tsExtensions],
  platformSubextensions
);

// Used in import resolver settings
settings: {
  'import/extensions': allExtensions,
  'import/resolver': {
    node: { extensions: allExtensions }
  }
}

Core Configuration Usage

// From shared/core.js
const { jsExtensions } = require('./extensions');

// Used for basic import resolution
settings: {
  'import/extensions': jsExtensions,
  'import/resolver': {
    node: { extensions: jsExtensions }
  }
}

Flat Configuration Support

Extension utilities work identically in both traditional and flat configurations:

// Flat config usage
const { computeExpoExtensions, jsExtensions, tsExtensions, platformSubextensions } = require('eslint-config-universe/flat/shared/extensions');

// Same API, same functionality
const allExtensions = computeExpoExtensions(
  [...jsExtensions, ...tsExtensions], 
  platformSubextensions
);

Note: The flat configuration versions are located in flat/shared/extensions.js but provide identical functionality to the traditional configuration versions.

Install with Tessl CLI

npx tessl i tessl/npm-eslint-config-universe

docs

basic-config.md

extension-utilities.md

index.md

native-config.md

node-config.md

typescript-analysis.md

web-config.md

tile.json