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

@stattus4/native-engine

v0.1.1

Published

Stattus4 engine com arquitetura Clean/Hexagonal e facade única para integração com SuperApp.

Readme

Corrigindo workflow

@stattus4/native-engine

Biblioteca nativa da Stattus4 para integração com o SuperAPP via uma única fachada (Engine), com suporte a gateway (TCP/BLE), pipeline de áudio, observabilidade e integração opcional com bridges nativas (TurboModule).

Este documento é a documentação funcional da biblioteca. Ele descreve a API pública e o comportamento atual do pacote @stattus4/native-engine.

Visão geral

A native-engine centraliza:

  • ciclo de vida da engine (start, stop, destroy)
  • conexão de gateway (connect, disconnect, sendGatewayCommand)
  • captura/reprodução de áudio e exportação de gravação
  • eventos de engine/gateway/áudio/protocolo
  • diagnósticos e métricas
  • fallback em memória quando bridges nativas não estão disponíveis

Suporte de plataforma (estado atual)

  • Engine (núcleo TypeScript): multiplataforma
  • factories TurboModule (createTurboNativeGatewayBridge, createTurboNativeAudioBridge): Android (retornam undefined fora de Android)
  • bridges customizadas (config.native): suportadas via interfaces públicas (NativeGatewayBridge, NativeAudioBridge)

Observação: o pacote contém código nativo iOS/Android, mas o auto-discovery de bridge TurboModule exportado hoje está habilitado apenas para Android.

Requisitos (recomendado)

  • Node.js >= 20 (validado no app example)
  • React Native (exemplo usa 0.83.0)
  • Android minSdkVersion 24 (conforme android/build.gradle)

Instalação no repositório

Este pacote está dentro do repositório stattus4-SuperAPP-lib em @stattus4/native-engine/.

cd @stattus4/native-engine
npm install

Para rodar o app de exemplo:

npm run example:android
# ou
npm run example:ios

Publicação pública no npm

O pacote está preparado para publicação pública no npm sob o escopo @stattus4.

Pré-requisitos:

  • conta npm com permissão para publicar no escopo @stattus4
  • autenticação no registry https://registry.npmjs.org/

Publicação:

cd @stattus4/native-engine
npm login
npm publish

O package.json define publishConfig.access = "public" e publishConfig.registry = "https://registry.npmjs.org/", então o primeiro publish do pacote escopado já sai como público no npm.

Publicação via GitHub Actions

O repositório agora possui o workflow .github/workflows/publish-native-engine.yml, que:

  • instala as dependências com npm ci
  • valida com npm run typecheck e npm run test:unit
  • publica @stattus4/native-engine no npm com o secret NPM_TOKEN

Antes de usar o workflow, configure em Settings > Secrets and variables > Actions um secret NPM_TOKEN com um token do npm que tenha permissão para publicar no escopo @stattus4.

Você pode disparar esse publish de duas formas:

  • manualmente em Actions > Publish @stattus4/native-engine to npm
  • automaticamente ao subir uma tag no formato native-engine-v*

Fluxo sugerido para release:

cd @stattus4/native-engine
npm version patch
git add package.json package-lock.json
git commit -m "chore: release 0.1.1"
git tag native-engine-v0.1.1
git push origin main --follow-tags

Instalação em outro projeto:

npm install @stattus4/native-engine

Depois disso, basta declarar a dependência normalmente no package.json do app:

{
  "dependencies": {
    "@stattus4/native-engine": "0.1.0"
  }
}

Início rápido

import {
  createEngine,
  createTurboNativeAudioBridge,
  createTurboNativeGatewayBridge,
  type Engine,
} from '@stattus4/native-engine';

const nativeGateway = createTurboNativeGatewayBridge();
const nativeAudio = createTurboNativeAudioBridge();

const engine: Engine = createEngine({
  appId: 'superapp',
  gateway: {
    mode: 'auto',
    port: 3000,
    reconnectOnFailure: true,
  },
  audio: {
    sampleRate: 16_000,
    channels: 1,
    bitsPerSample: 16,
    chunkSizeBytes: 320,
  },
  security: {
    enableEncryption: false,
    enableSigning: false,
  },
  protocol: {
    daqExpectedBytes: 160_000,
    streamIdleTimeoutMs: 4_000,
    getPermission: () => true,
    getProtocolVersion: () => 3,
    getAvailableFirmware: () => false,
  },
  retry: {
    maxAttempts: 3,
    baseDelayMs: 300,
    maxDelayMs: 2_000,
    jitter: 0.2,
  },
  timeout: {
    connectMs: 5_000,
    commandMs: 4_000,
    captureStartMs: 2_000,
  },
  observability: {
    level: 'info',
    enableMetrics: true,
    enableDiagnostics: true,
  },
  native: {
    ...(nativeGateway ? { gateway: nativeGateway } : {}),
    ...(nativeAudio ? { audio: nativeAudio } : {}),
  },
  // Em Android produção, você pode habilitar modo estrito:
  // capabilities: ANDROID_SUPERAPP_PRODUCTION_CAPABILITIES,
});

const unsubscribe = engine.onEvent((event) => {
  if (event.type === 'engine_error') {
    console.warn(event.error.code, event.error.message);
  }
});

(async () => {
  const started = await engine.start();
  if (!started.ok) return;

  const connected = await engine.connect();
  if (!connected.ok) return;

  const encoder = new TextEncoder();
  await engine.sendGatewayCommand({
    payload: encoder.encode('AT+INFO\r\n'),
  });

  const snapshot = engine.snapshot();
  console.log(snapshot.gatewayState, snapshot.audioState);

  const diagnostics = await engine.diagnostics();
  if (diagnostics.ok) {
    console.log(diagnostics.value);
  }

  await engine.disconnect();
  await engine.stop();
  unsubscribe();
  engine.destroy();
})();

Conceitos principais

1. Engine (fachada única)

A interface Engine concentra o uso público da biblioteca:

  • lifecycle: start, stop, destroy
  • gateway: connect, disconnect, sendGatewayCommand
  • áudio: startCapture, stopCapture, playAudioFile, exportação de gravações
  • observabilidade: onEvent, snapshot, diagnostics

2. Resultado padronizado (Result<T, EngineError>)

A API assíncrona retorna Result em vez de lançar exceções na maioria das operações:

  • sucesso: { ok: true, value }
  • erro: { ok: false, error }

Exceções ainda podem acontecer em createEngine(...) quando há configuração inválida ou exigência de capability não atendida (ex.: strictNative sem bridge nativa disponível).

3. Fallback automático

Se as bridges nativas não estiverem disponíveis e você não exigir modo estrito, a engine usa adapters em memória para gateway/áudio. Isso é útil para:

  • desenvolvimento local
  • testes unitários
  • execução em ambientes sem TurboModule

API pública (resumo)

Criação e exports principais

  • createEngine(config: EngineConfig): Engine
  • createTurboNativeGatewayBridge(): NativeGatewayBridge | undefined
  • createTurboNativeAudioBridge(): NativeAudioBridge | undefined
  • ANDROID_SUPERAPP_PRODUCTION_CAPABILITIES
  • EngineError, EngineErrorCode, engineError(...)
  • ok(...), err(...)

Métodos da Engine

  • start()
    • Inicializa a engine e publica engine_started.
  • stop()
    • Para captura de áudio, desconecta gateway e publica engine_stopped.
  • connect()
    • Conecta o gateway configurado (tcp/ble). Requer start() antes.
  • disconnect()
    • Desconecta o gateway atual.
  • sendGatewayCommand({ payload })
    • Envia bytes para o gateway.
  • startCapture({ mode? })
    • Inicia pipeline de áudio manualmente (play ou play_and_record).
  • stopCapture()
    • Para a captura/pipeline de áudio.
  • playAudioFile(wavAudio)
    • Reproduz um arquivo WAV via bridge de áudio nativa.
  • saveLastRecordingWav({ sink? })
    • Exporta a última gravação para WAV (e opcionalmente grava em sink.write(...)).
  • getLastRecordingPcm()
    • Retorna o PCM bruto da última gravação.
  • clearLastRecording()
    • Limpa buffers de gravação exportável.
  • snapshot()
    • Snapshot síncrono do estado de execução/gateway/áudio.
  • diagnostics()
    • Diagnóstico completo (capacidades, métricas, protocolo, gateway, áudio).
  • onEvent(listener)
    • Assina eventos da engine.
  • destroy()
    • Libera listeners/recursos internos. Chame no teardown da tela/processo.

Configuração (EngineConfig)

Campos obrigatórios

interface EngineConfig {
  appId: string;
  gateway: GatewayConfig;
  audio: AudioConfig;
  security: SecurityConfig;
  retry: RetryPolicy;
  timeout: TimeoutPolicy;
  observability: ObservabilityConfig;
  productScope?: EngineProductScopeConfig;
  protocol?: ProtocolConfig;
  capabilities?: EngineCapabilitiesConfig;
  native?: EngineNativeBridges;
}

Observação: createEngine() aplica defaults internos para productScope, protocol, retry e timeout, mas os tipos públicos exigem retry e timeout explicitamente.

gateway (GatewayConfig)

{
  mode: 'tcp' | 'ble' | 'auto';
  host?: string;
  port?: number;
  deviceName?: string;
  scanTimeoutMs?: number;
  reconnectDelayMs?: number;
  updateRateMs?: number;
  reconnectOnFailure: boolean;
  initialState?: GatewayState;
}

Regras de resolução quando mode: 'auto':

  • se host ou port estiver definido: usa tcp
  • senão, se deviceName estiver definido: tenta ble quando houver bridge nativa de gateway; caso contrário, cai para tcp
  • caso contrário: usa tcp

audio (AudioConfig)

{
  sampleRate: number;
  channels: number;
  bitsPerSample: number;
  chunkSizeBytes: number;
}

Configura o pipeline de áudio (captura/reprodução) e também influencia defaults de gravação/DAQ.

security (SecurityConfig)

{
  enableEncryption: boolean;
  enableSigning: boolean;
}

Esses flags fazem parte do contrato público da engine e da configuração de produto. No estado atual da API pública, eles são principalmente declarativos (a fachada Engine não expõe operações de criptografia/assinatura diretamente).

protocol (ProtocolConfig)

A engine processa comandos/eventos de protocolo sobre payloads de gateway (especialmente no fluxo TCP/AT). Campos relevantes:

  • daqExpectedBytes
  • trackExpectedBytes
  • streamIdleTimeoutMs
  • requestsEnabled / getPermission
  • protocolVersion / getProtocolVersion
  • firmwareAvailable / getAvailableFirmware

Comandos AT reconhecidos no runtime atual (via parser interno):

  • AT+START
  • AT+DAQ
  • AT+DAQPOS
  • AT+STREAM
  • AT+INFO
  • AT+UPDATE
  • AT+DEVICE
  • AT+ALARM
  • AT+HBEAT
  • AT+UTRACK

observability (ObservabilityConfig)

{
  level: 'debug' | 'info' | 'warn' | 'error' | 'silent';
  enableMetrics: boolean;
  enableDiagnostics: boolean;
}
  • enableMetrics: habilita coleta de métricas e eventos metric_observed
  • enableDiagnostics: habilita engine.diagnostics()

productScope (EngineProductScopeConfig)

Metadata de produto exposta em diagnostics():

  • fota: 'deferred' | 'partial' | 'ready'
  • gps: 'deferred' | 'partial' | 'ready'
  • security: 'deferred' | 'partial' | 'ready'

Default:

{
  fota: 'deferred',
  gps: 'deferred',
  security: 'deferred',
}

capabilities (EngineCapabilitiesConfig)

Controla fallback/uso de bridges nativas:

  • forceFallback
  • allowNativeGateway
  • allowNativeAudio
  • allowSecureStore
  • requireNativeGateway
  • requireNativeAudio
  • strictNative (atalho para exigir gateway + áudio nativos)

Preset exportado para Android produção:

ANDROID_SUPERAPP_PRODUCTION_CAPABILITIES
// => { forceFallback: false, allowNativeGateway: true, allowNativeAudio: true, strictNative: true }

Bridges nativas (config.native)

Você pode injetar bridges customizadas para adaptar a engine ao host/plataforma:

  • native.gateway?: NativeGatewayBridge
  • native.audio?: NativeAudioBridge

Interface NativeGatewayBridge (resumo)

Métodos principais:

  • configure?(config)
  • connect()
  • disconnect()
  • send(payload)
  • onData(listener)
  • onDisconnect(listener)

Métodos opcionais para richer TCP lifecycle:

  • closeClient?()
  • onClientConnected?(listener)
  • onClientDisconnected?(listener)

Interface NativeAudioBridge (resumo)

  • startCapture(config)
  • stopCapture()
  • playFrame?(frame, config)
  • playWav?(payload)
  • getPlaybackHeadPosition?()

Factories TurboModule (Android)

  • createTurboNativeGatewayBridge()
  • createTurboNativeAudioBridge()

As factories tentam localizar o TurboModule NativeEngine e retornam undefined quando não disponível (ou fora de Android).

Gateway: modos tcp e ble

TCP

  • A engine atua com um servidor TCP (via bridge nativa) e recebe dados do cliente (sensor/dispositivo).
  • Eventos de cliente (gateway_client_connected, gateway_client_disconnected) e estado de servidor (gateway_transport_state_changed) são emitidos quando suportados pela bridge.
  • Erro de bind de porta (EADDRINUSE) é normalizado para EngineErrorCode.GATEWAY_PORT_IN_USE.

BLE

  • O modo BLE usa gateway.deviceName e os parâmetros de scan/reconnect/update.
  • O comportamento exato depende da NativeGatewayBridge fornecida.
  • Na bridge TurboModule Android atual, comandos enviados pela engine são mapeados para solicitações de bateria/GPS no runtime BLE.

Áudio e gravação

Captura manual

await engine.startCapture({ mode: 'play_and_record' });
await engine.stopCapture();

Modos:

  • play
  • play_and_record (default da captura)

Pipeline automático por protocolo

A engine também controla o áudio automaticamente em ciclos de protocolo:

  • estado de protocolo daq -> inicia pipeline em play_and_record
  • estado de protocolo stream -> inicia pipeline em play
  • estado idle/error -> desliga pipeline

Exportação da última gravação

  • saveLastRecordingWav() retorna WAV (Uint8Array)
  • getLastRecordingPcm() retorna PCM bruto (Uint8Array)
  • clearLastRecording() limpa buffers exportáveis

Se não houver gravação disponível, a engine retorna AUDIO_RECORDING_UNAVAILABLE.

Você também pode persistir a exportação via sink:

await engine.saveLastRecordingWav({
  sink: {
    write(payload) {
      // salvar em arquivo / upload / persistência
    },
  },
});

Eventos (engine.onEvent(...))

A engine publica eventos tipados (EngineEvent). Principais grupos:

Lifecycle da engine

  • engine_started
  • engine_stopped
  • engine_error

Gateway

  • gateway_state_changed
  • gateway_transport_state_changed
  • gateway_client_connected
  • gateway_client_disconnected
  • gateway_data_received
  • gateway_data_sent

Áudio

  • audio_state_changed
  • audio_frame_captured

Observabilidade

  • metric_observed

Protocolo

  • fluidcore_protocol_event

Observação: o nome do evento/tipo público (fluidcore_protocol_event, FluidCoreProtocolEvent) é mantido por compatibilidade da API atual. Ele representa os eventos de protocolo processados pela engine.

Campos úteis em fluidcore_protocol_event:

  • message
  • state
  • command?
  • payload?
  • device?
  • clientId?
  • sessionId?
  • progress?

Snapshot e diagnósticos

snapshot()

Leitura síncrona e leve do estado atual:

  • running
  • gatewayState
  • audioState
  • connectedAt
  • gateway (client count, active client, timestamps de atividade, estado do servidor)

diagnostics()

Retorna um snapshot estendido (EngineDiagnostics) com:

  • capabilities (fallback, nativeGateway, nativeAudio, secureStore)
  • productScope
  • gateway (bytes, reconnectAttempts, lastError, cliente ativo)
  • protocol (estado, último comando, último payload de device, metadados do device)
  • audio (frames, dropped, bytes)
  • metrics

Se observability.enableDiagnostics === false, retorna erro com EngineErrorCode.CAPABILITY_UNAVAILABLE.

Códigos de erro públicos (EngineErrorCode)

Lista atual:

  • INVALID_ARGUMENT
  • NOT_READY
  • ALREADY_RUNNING
  • TIMEOUT
  • PERMISSION_DENIED
  • CAPABILITY_UNAVAILABLE
  • GATEWAY_PORT_IN_USE
  • GATEWAY_CONNECT_FAILED
  • GATEWAY_DISCONNECTED
  • GATEWAY_SEND_FAILED
  • AUDIO_START_FAILED
  • AUDIO_STOP_FAILED
  • AUDIO_PLAYBACK_FAILED
  • AUDIO_RECORDING_UNAVAILABLE
  • AUDIO_EXPORT_FAILED
  • STORAGE_FAILED
  • SECURITY_FAILED
  • INTERNAL_ERROR

Boas práticas de uso

  • Chame start() antes de connect().
  • Sempre faça teardown com disconnect()/stop() e destroy().
  • Use strictNative em produção Android quando a bridge nativa for obrigatória.
  • Em desenvolvimento/testes, permita fallback para acelerar validação.
  • Assine engine_error via onEvent para telemetria e troubleshooting.

Troubleshooting

connect() falha com GATEWAY_PORT_IN_USE

A porta TCP já está em uso. Troque gateway.port ou encerre o processo que está ocupando a porta.

createEngine(...) lança erro de capability nativa

Exemplo comum:

  • Native gateway bridge is required but unavailable

Isso ocorre quando strictNative / requireNativeGateway / requireNativeAudio está ativo e a bridge correspondente não foi encontrada/injetada.

connect() retorna NOT_READY

engine.start() não foi chamado antes de engine.connect().

diagnostics() indisponível

Verifique observability.enableDiagnostics. Quando false, a engine retorna CAPABILITY_UNAVAILABLE.

Desenvolvimento da biblioteca

Dentro de @stattus4/native-engine/:

npm install
npm run typecheck
npm run lint
npm run test:unit

Testes Android (dependem de ambiente Android configurado):

npm run test:android:native
npm run test:android:e2e

Exemplo de integração

O app de exemplo em example/ demonstra:

  • criação da engine
  • uso das factories TurboModule
  • fluxo de ações (start, connect, envio de comando, captura, diagnósticos)
  • renderização de snapshot() e stream de eventos

Arquivo principal: example/src/App.tsx.

Licença

MIT. Veja LICENSE.