npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stray-react-di

v3.0.3

Published

Sistema unificado de gerenciamento de dependências para aplicações React com injeção inteligente de dependências, providers, components, services e hooks

Readme

stray-react-di

npm version TypeScript Build Status Coverage Status

Stray é um sistema unificado de gerenciamento de dependências para aplicações React com injeção inteligente de dependências, providers, components, services e hooks.

✨ Principais Características

  • 🎯 Arquitetura Unificada: Uma única classe StrayDependency para gerenciar providers, components, services, hooks e HOCs
  • 🔧 Detecção Automática de Tipos: Identifica automaticamente o tipo baseado em convenções de nomenclatura
  • 📦 TypeScript Nativo: Totalmente tipado com suporte completo ao TypeScript
  • 🚀 Injeção de Dependências: Sistema poderoso de DI com resolução automática
  • 🔄 Compatibilidade: Mantém compatibilidade com versões anteriores
  • Performance: Otimizado para aplicações React de alto desempenho
  • 🎨 Flexibilidade: Suporte a HOCs, renderização customizada e composição

📦 Instalação

npm install stray-react-di
yarn add stray-react-di
pnpm add stray-react-di

🚀 Início Rápido

Configuração Básica

import { StrayApp } from 'stray-react-di';
import React from 'react';

// Componentes de exemplo
const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  <div>{children}</div>
);

const Button: React.FC<{ title?: string }> = ({ title }) => (
  <button>{title || 'Click me'}</button>
);

class ApiService {
  constructor(private config: any) {}
  
  async getData() {
    return fetch(this.config.apiUrl);
  }
}

const useAuth = () => {
  return { user: null, login: () => {}, logout: () => {} };
};

// Criando a aplicação Stray
const app = new StrayApp();

// Configuração unificada
app
  .config('config', { 
    target: { apiUrl: 'https://api.example.com' }, 
    type: 'dependency' 
  })
  .provider('AuthProvider', { 
    target: AuthProvider, 
    props: { theme: 'dark' } 
  })
  .component('Button', { 
    target: Button, 
    route: '/',
    props: { title: 'Home Button' }
  })
  .service('ApiService', { 
    target: ApiService, 
    dependencies: ['config'] 
  })
  .hook('useAuth', { 
    target: useAuth 
  });

// Renderizar a aplicação
app.render().then(() => {
  console.log('Aplicação iniciada!');
});

Detecção Automática de Tipos

O Stray detecta automaticamente o tipo de dependência baseado em convenções:

// Detecção automática por nome
app.config('AuthProvider', { target: AuthProvider });     // → type: 'provider'
app.config('UserService', { target: UserService });       // → type: 'service'  
app.config('useAuth', { target: useAuth });               // → type: 'hook'
app.config('withAuth', { target: withAuthHoc });          // → type: 'hoc'
app.config('Button', { target: Button });                 // → type: 'component'

📚 Guias e Documentação

Métodos de Conveniência

const app = new StrayApp();

// Providers (para Context API)
app.provider('ThemeProvider', {
  target: ThemeProvider,
  props: { theme: 'dark' },
  position: 1 // Ordem de renderização
});

// Components (para roteamento)
app.component('HomePage', {
  target: HomePage,
  route: '/',
  props: { title: 'Welcome' }
});

// Services (injeção de dependência)
app.service('ApiService', {
  target: ApiService,
  dependencies: ['config', 'httpClient']
});

// Hooks (com dependências injetadas)
app.hook('useApi', {
  target: useApi,
  dependencies: ['ApiService']
});

// HOCs (Higher-Order Components)
app.hoc('withAuth', {
  target: withAuthHoc
});

// Dependências simples (valores, configurações)
app.dependency('config', {
  apiUrl: process.env.REACT_APP_API_URL,
  timeout: 5000
});

Sistema de Dependências

// 1. Configurar dependências
app.dependency('config', {
  apiUrl: 'https://api.example.com',
  timeout: 5000
});

// 2. Service que depende da configuração
class ApiService {
  constructor(private config: any) {}
  
  async request(endpoint: string) {
    const response = await fetch(`${this.config.apiUrl}${endpoint}`, {
      timeout: this.config.timeout
    });
    return response.json();
  }
}

app.service('ApiService', {
  target: ApiService,
  dependencies: ['config'] // Será injetado no construtor
});

// 3. Hook que depende do service
const useUsers = (apiService: ApiService) => {
  const [users, setUsers] = useState([]);
  
  useEffect(() => {
    apiService.request('/users').then(setUsers);
  }, []);
  
  return users;
};

app.hook('useUsers', {
  target: useUsers,
  dependencies: ['ApiService'] // Será injetado como propriedade
});

// 4. Component que usa o hook
const UsersList: React.FC = () => {
  const users = app.getHook('useUsers')();
  
  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
};

app.component('UsersList', {
  target: UsersList,
  route: '/users'
});

HOCs (Higher-Order Components)

// 1. Definir HOC
const withLoading = (WrappedComponent: React.ComponentType) => {
  return (props: any) => {
    const [loading, setLoading] = useState(true);
    
    useEffect(() => {
      setTimeout(() => setLoading(false), 1000);
    }, []);
    
    if (loading) return <div>Loading...</div>;
    return <WrappedComponent {...props} />;
  };
};

app.hoc('withLoading', { target: withLoading });

// 2. Aplicar HOC a componente
app.component('UserProfile', {
  target: UserProfile,
  route: '/profile',
  hocs: ['withLoading'] // Aplicado automaticamente
});

Renderização Customizada

const customRenderCallback = (Component: React.ComponentType, props: any, children: React.ReactNode) => {
  return (
    <ErrorBoundary>
      <Component {...props}>
        {children}
      </Component>
    </ErrorBoundary>
  );
};

app.provider('ErrorProvider', {
  target: ErrorBoundaryProvider,
  renderCallback: customRenderCallback
});

🔧 API Completa

StrayApp

Métodos de Configuração

| Método | Descrição | Exemplo | |--------|-----------|---------| | config(name, config) | Configuração unificada | app.config('Button', { target: Button }) | | provider(name, config) | Configura provider | app.provider('Theme', { target: ThemeProvider }) | | component(name, config) | Configura componente | app.component('Home', { target: HomePage }) | | service(name, config) | Configura service | app.service('Api', { target: ApiService }) | | hook(name, config) | Configura hook | app.hook('useAuth', { target: useAuth }) | | hoc(name, config) | Configura HOC | app.hoc('withAuth', { target: withAuth }) | | dependency(name, value) | Configura valor simples | app.dependency('config', { api: 'url' }) |

Métodos de Consulta

| Método | Descrição | Retorno | |--------|-----------|---------| | getProviders() | Lista providers | IStrayDependency[] | | getComponents() | Lista componentes | IStrayDependency[] | | getServices() | Lista services | IStrayDependency[] | | getHooks() | Lista hooks | IStrayDependency[] | | getHocs() | Lista HOCs | IStrayDependency[] | | getService(name) | Obtém service instanciado | any | | getHook(name) | Obtém hook injetado | any | | has(name) | Verifica se existe | boolean | | getDependencyConfig(name) | Obtém configuração | IStrayDependency |

Métodos de Renderização

| Método | Descrição | |--------|-----------| | render(children?) | Renderiza aplicação | | createApp(children?) | Alias para render | | buildProvidersTree(children?) | Constrói árvore de providers | | buildRoutesTree() | Constrói rotas |

Métodos de Combinação

| Método | Descrição | |--------|-----------| | combine(otherApp, options?) | Combina com outra instância | | export(includeOnly?) | Exporta dependências | | import(exportedData, options?) | Importa dependências | | StrayApp.merge(app1, app2, options?) | Merge estático |

StrayDependencyConfig

interface StrayDependencyConfig<T = any> {
  name?: string;                    // Nome único
  target: DependencyTarget<T>;      // Componente/Service/Hook/etc
  type?: DependencyType;            // 'provider' | 'component' | 'service' | 'hook' | 'hoc' | 'dependency'
  dependencies?: string[];          // Array de dependências
  props?: DynamicProps<any>;        // Props estáticas ou função
  description?: string;             // Descrição
  route?: string;                   // Rota (para components)
  hocs?: string[];                  // HOCs a aplicar
  position?: number;                // Posição (para providers)
  renderCallback?: RenderCallback;  // Callback customizado
}

🎯 Exemplos Avançados

Aplicação Completa com Roteamento

import { StrayApp, quickSetup } from 'stray-react-di';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const app = quickSetup({
  providers: {
    'Router': { target: BrowserRouter },
    'AuthProvider': { target: AuthProvider },
    'ThemeProvider': { target: ThemeProvider, position: 1 }
  },
  
  services: {
    'ApiService': { target: ApiService, dependencies: ['config'] },
    'AuthService': { target: AuthService, dependencies: ['ApiService'] }
  },
  
  hooks: {
    'useAuth': { target: useAuth, dependencies: ['AuthService'] },
    'useTheme': { target: useTheme }
  },
  
  components: {
    'HomePage': { target: HomePage, route: '/' },
    'LoginPage': { target: LoginPage, route: '/login' },
    'ProfilePage': { target: ProfilePage, route: '/profile', hocs: ['withAuth'] }
  },
  
  dependencies: {
    'config': { 
      target: {
        apiUrl: process.env.REACT_APP_API_URL,
        appName: 'My App'
      }
    }
  }
});

// Container DOM
const container = document.getElementById('root');
const appWithContainer = new StrayApp({ container });

// Combinar configurações
appWithContainer.combine(app);

// Iniciar aplicação
appWithContainer.createApp();

Micro-frontends com Stray

// App Principal
const mainApp = new StrayApp();
mainApp.provider('SharedProvider', { target: SharedContextProvider });

// Micro-frontend 1
const authModule = new StrayApp();
authModule
  .service('AuthService', { target: AuthService })
  .component('LoginForm', { target: LoginForm });

// Micro-frontend 2  
const dashboardModule = new StrayApp();
dashboardModule
  .component('Dashboard', { target: Dashboard })
  .hook('useDashboard', { target: useDashboard });

// Combinação
const combinedApp = StrayApp.merge(mainApp, authModule);
combinedApp.combine(dashboardModule, { prefix: 'dashboard_' });

combinedApp.createApp();

Sistema de Plugins

interface Plugin {
  name: string;
  dependencies: ExportedDependencies;
}

class PluginManager {
  constructor(private app: StrayApp) {}
  
  loadPlugin(plugin: Plugin) {
    console.log(`Loading plugin: ${plugin.name}`);
    this.app.import(plugin.dependencies);
  }
  
  unloadPlugin(pluginName: string) {
    // Implementar remoção de dependências
  }
}

const app = new StrayApp();
const pluginManager = new PluginManager(app);

// Plugin de autenticação
const authPlugin: Plugin = {
  name: 'auth',
  dependencies: authModule.export(['AuthService', 'LoginForm'])
};

pluginManager.loadPlugin(authPlugin);

🧪 Testes

Configuração de Testes

npm test              # Executar todos os testes
npm run test:watch    # Modo watch
npm run test:coverage # Com coverage

Testando com Stray

import { StrayApp } from 'stray-react-di';
import { render, screen } from '@testing-library/react';

describe('StrayApp Integration', () => {
  let app: StrayApp;

  beforeEach(() => {
    app = new StrayApp();
  });

  it('should resolve dependencies correctly', async () => {
    // Configurar
    app.dependency('config', { message: 'Hello World' });
    
    class TestService {
      constructor(private config: any) {}
      getMessage() { return this.config.message; }
    }
    
    app.service('TestService', {
      target: TestService,
      dependencies: ['config']
    });

    // Testar
    const service = app.getService('TestService');
    expect(service.getMessage()).toBe('Hello World');
  });

  it('should render component tree', async () => {
    const TestComponent = () => <div>Test</div>;
    
    app.component('TestComponent', {
      target: TestComponent,
      route: '/test'
    });

    const element = await app.buildRoutesTree();
    expect(element).toBeDefined();
  });
});

🔄 Migração v2 → v3

Mudanças Principais

  • Arquitetura Unificada: StrayDependency substitui classes separadas
  • TypeScript Nativo: Tipagem completa
  • Métodos Simplificados: config() como método principal
  • Detecção Automática: Tipos detectados por convenção
  • Compatibilidade: Aliases mantidos para código legado

Guia de Migração

// v2 (JavaScript)
const app = new StrayApp();
app.buildProvider('AuthProvider', AuthProviderConfig);
app.buildComponent('HomePage', HomePageConfig);

// v3 (TypeScript) - Recomendado
const app = new StrayApp();
app.provider('AuthProvider', { target: AuthProvider });
app.component('HomePage', { target: HomePage, route: '/' });

// v3 (Compatibilidade) - Funciona mas não recomendado
app.buildProvider('AuthProvider', AuthProviderConfig); // ← Ainda funciona
app.buildComponent('HomePage', HomePageConfig);         // ← Ainda funciona

📖 Recursos Adicionais

🤝 Contribuindo

Contribuições são bem-vindas! Por favor, leia nosso Guia de Contribuição.

Desenvolvimento Local

git clone https://github.com/teraprox/stray.git
cd stray
npm install
npm run dev
npm test

Scripts Disponíveis

npm run build         # Build de produção
npm run dev           # Desenvolvimento com watch
npm test              # Executar testes
npm run lint          # Linting
npm run format        # Formatação de código

📄 Licença

MIT © TeraPROX Development Team

🙏 Agradecimentos

  • React team pela excelente biblioteca
  • TypeScript team pelo sistema de tipos
  • Jest team pela ferramenta de testes
  • Comunidade open source

🌟 Star no GitHub📦 NPM Package📖 Documentação

Feito com ❤️ por TeraPROX Development Team

🏗️ Estrutura da Pasta

stray/
├── index.js                    # Ponto de entrada principal
├── core/                      # Módulos principais
│   ├── StrayApp.js           # Classe principal do sistema
│   └── DependencyMapping.js  # Sistema de mapeamento e resolução de dependências
├── examples/                  # Exemplos práticos de uso
│   ├── StrayAppUsage.js      # Exemplos básicos de configuração
│   └── StrayAppIntelligentProps.js # Exemplos de props inteligentes
├── docs/                      # Documentação detalhada
│   ├── StrayAppConfigDependency.js     # Documentação de configuração
│   ├── StrayAppIntelligentProps.js     # Documentação de props inteligentes
│   └── INTELLIGENT_PROPS_FINAL_SUMMARY.js # Resumo final da implementação
└── tests/                     # Testes do sistema
    ├── StrayAppConfigTests.js   # Testes de configuração
    └── StrayAppFinalTest.js     # Testes finais integrados

🚀 Características Principais

1. Sistema de Props Inteligente

  • Detecção automática de dependências baseada no retorno das funções props
  • Suporte a formatos JSON (objetos) e Array (strings)
  • Carregamento automático de serviços conforme necessidade

2. Mapeamento Isolado de Serviços

  • DEPENDENCY_MAPPING: Para componentes e providers
  • SERVICES_MAPPING: Para serviços isolados
  • Resolução automática e inteligente de dependências

3. Flexibilidade de Configuração

  • Configuração manual tradicional via configDependency
  • Configuração automática via props inteligentes
  • Suporte a dependências condicionais e dinâmicas

📖 Como Usar

Importação Básica

import StrayApp from './stray';
// ou
import { StrayApp, DEPENDENCY_MAPPING, SERVICES_MAPPING } from './stray';

Configuração Rápida

import { createStrayApp } from './stray';

const strayApp = createStrayApp({
  dependencies: {
    'UserService': () => import('./services/UserService'),
    'ApiService': () => import('./services/ApiService')
  }
});

Props Inteligentes (Recomendado)

const MyComponent = strayApp.loadProvider('MyProvider', () => ({
  userService: null,     // Será carregado automaticamente
  apiService: null,      // Será carregado automaticamente
  localData: { ready: true }  // Valor local, não é dependência
}));

🔄 Migração de Código Existente

Se você estava usando o Stray antes da reorganização, apenas atualize os imports:

Antes:

import StrayApp from './config/StrayApp';
import { DEPENDENCY_MAPPING } from './config/DependencyMapping';

Depois:

import StrayApp from './stray';
import { DEPENDENCY_MAPPING } from './stray';

🧪 Execução dos Testes

Para executar os testes do sistema Stray:

# Executar testes específicos do Stray
node src/stray/tests/StrayAppFinalTest.js

# Executar testes de configuração
node src/stray/tests/StrayAppConfigTests.js

📚 Documentação Detalhada

🛠️ Exemplos Práticos

🎯 Benefícios

  1. Desacoplamento: Separação clara entre componentes, serviços e dependências
  2. Automação: Redução significativa de código boilerplate
  3. Inteligência: Detecção automática de dependências sem configuração manual
  4. Flexibilidade: Suporte a múltiplos padrões de configuração
  5. Manutenibilidade: Código mais limpo e fácil de manter
  6. Performance: Carregamento lazy de dependências quando necessário

🔧 Arquitetura

O Stray utiliza uma arquitetura em camadas:

  1. Core Layer (StrayApp.js): Gerenciamento principal e orquestração
  2. Mapping Layer (DependencyMapping.js): Resolução e análise de dependências
  3. Intelligence Layer: Sistema de props inteligentes e detecção automática
  4. Service Layer: Isolamento e carregamento de serviços

⚡ Performance

  • Lazy Loading: Serviços são carregados apenas quando necessário
  • Caching: Dependências resolvidas são cacheadas para reutilização
  • Smart Detection: Algoritmo otimizado para detecção de dependências
  • Minimal Overhead: Impacto mínimo na performance da aplicação

Desenvolvido pela equipe TeraPROX - Versão 1.0.0