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

@theseed.dev/erifa

v1.2.0

Published

EriFa — Encrypted Request Integration for Applications. Chiffrement E2E transparent pour Express, Elysia, Fastify, Hono, Vue, React, Next.js, Nuxt, Angular.

Readme

Chiffrement E2E automatique et transparent entre ton frontend et ton backend.
Même API, zéro configuration, compatible avec tous les frameworks majeurs.

npm install @theseed.dev/erifa

Frameworks supportés

| Frontend | Backend | |---|---| | Vue 3 (axios · composable) | Express | | React / Vanilla JS (axios) | Elysia (Bun) | | Next.js (App Router / Pages) | Fastify | | Nuxt 3 | Hono | | Angular 15+ | — |


Démarrage rapide

1 — Déclarer la clé

Ajoute erifa.key dans le package.json de ton projet frontend :

{
  "erifa": {
    "key": "ta-cle-secrete-longue-et-aleatoire"
  }
}

La clé doit faire au minimum 16 caractères. Elle ne sera jamais exposée en clair dans le bundle.

2 — Brancher le script d'injection

Le script s'exécute avant le bundler à chaque dev et build.
Adapte selon ton bundler :

{
  "scripts": {
    "dev":   "node node_modules/@theseed.dev/erifa/scripts/inject-key.js && vite",
    "build": "node node_modules/@theseed.dev/erifa/scripts/inject-key.js && vite build"
  }
}

Remplace vite / vite build par next dev / next build, nuxt dev / nuxt build, etc.

3 — Ajouter au .gitignore

node_modules/@theseed.dev/erifa/src/injected-key.js

Backend

Express

const express = require("express");
const erifa   = require("@theseed.dev/erifa");

const app = express();
app.use(express.json());
app.use(erifa.middleware(process.env.ERIFA_SECRET));

app.post("/login", (req, res) => {
  // req.body est déchiffré automatiquement
  res.json({ token: "jwt..." }); // chiffré automatiquement
});

Elysia (Bun)

import { Elysia }  from "elysia";
import erifa       from "@theseed.dev/erifa";

const app = new Elysia()
  .use(erifa.elysia(process.env.ERIFA_SECRET!))
  .post("/login", ({ body }) => {
    // body déchiffré automatiquement
    return { token: "jwt..." }; // chiffré automatiquement
  })
  .listen(3000);

Fastify

const fastify = require("fastify")();
const erifa   = require("@theseed.dev/erifa");

fastify.register(erifa.fastify, { secretKey: process.env.ERIFA_SECRET });

fastify.post("/login", async (request) => {
  // request.body est déchiffré automatiquement
  return { token: "jwt..." }; // chiffré automatiquement
});

Hono

import { Hono } from "hono";
import erifa    from "@theseed.dev/erifa";

const app = new Hono();
app.use("*", erifa.hono(process.env.ERIFA_SECRET!));

app.post("/login", async (c) => {
  const body = await c.req.json(); // déchiffré automatiquement
  return c.json({ token: "jwt..." }); // chiffré automatiquement
});

Option excludeErrors (tous les backends)

Par défaut, toutes les réponses sont chiffrées (y compris 4xx/5xx).
Pour laisser passer les erreurs en clair :

erifa.middleware(SECRET, { excludeErrors: true }) // Express
erifa.elysia(SECRET, { excludeErrors: true })     // Elysia
erifa.fastify  → { secretKey: SECRET, excludeErrors: true } // Fastify (options register)
erifa.hono(SECRET, { excludeErrors: true })       // Hono

Frontend

Vue 3 — axios (recommandé)

Utilise erifa exactement comme axios. La clé est injectée automatiquement via le script de build.

// main.js
import erifa from "@theseed.dev/erifa";

// Optionnel — si la clé est injectée via window.__ERIFA_KEY__ (SSR)
erifa.init();
<!-- Login.vue -->
<script setup>
import erifa from "@theseed.dev/erifa";

async function login() {
  const { data } = await erifa.post("https://api.example.com/login", {
    username: "admin",
    password: "secret",
  });
  console.log(data.token);
}
</script>

Vue 3 — composable useErifa()

Idéal en Composition API : ajoute un état réactif loading / error automatique.

<script setup>
import erifa from "@theseed.dev/erifa";

const api = erifa.vue({
  baseURL: "https://api.example.com",
  key: import.meta.env.VITE_ERIFA_KEY, // si tu ne passes pas par le script d'injection
});

async function login() {
  const { data } = await api.post("/login", { username, password });
}
</script>

<template>
  <p v-if="api.loading.value">Connexion en cours…</p>
  <p v-if="api.error.value" class="error">{{ api.error.value.message }}</p>
</template>

React / Vanilla JS

// lib/api.js
import erifa from "@theseed.dev/erifa";

export const api = erifa.create({ baseURL: "https://api.example.com" });
// LoginForm.jsx
import { api } from "../lib/api";

async function handleSubmit(e) {
  const { data } = await api.post("/login", { username, password });
  console.log(data.token);
}

Next.js — App Router

Utilise le client fetch natif d'erifa, adapté au fonctionnement de Next.js App Router.

// lib/api.ts
import erifa from "@theseed.dev/erifa";

const api = erifa.fetch({
  baseURL: "https://api.example.com",
  key: process.env.NEXT_PUBLIC_ERIFA_KEY,
});

export default api;
// app/login/page.tsx (Client Component)
"use client";
import api from "@/lib/api";

export default function LoginPage() {
  async function handleSubmit(formData: FormData) {
    const { data } = await api.post("/login", {
      username: formData.get("username"),
      password: formData.get("password"),
    });
    console.log(data.token);
  }

  return <form action={handleSubmit}>...</form>;
}

Next.js App Router côté serveur : passe la clé via process.env.ERIFA_SECRET (non-NEXT_PUBLIC_).
Le chiffrement se fait alors entre le serveur Next.js et ton API backend.

Nuxt 3

// plugins/erifa.ts
import erifa from "@theseed.dev/erifa";

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig();

  const api = erifa.fetch({
    baseURL: config.public.apiBase,
    key: config.public.erifaKey,
  });

  return { provide: { erifa: api } };
});
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiBase:  "https://api.example.com",
      erifaKey: process.env.NUXT_PUBLIC_ERIFA_KEY,
    },
  },
});
<!-- pages/login.vue -->
<script setup>
const { $erifa } = useNuxtApp();

async function login() {
  const { data } = await $erifa.post("/login", { username, password });
}
</script>

Angular 15+

Erifa s'intègre via un functional interceptor. Copie ce fichier dans ton projet :

// src/app/erifa.interceptor.ts
import { HttpInterceptorFn, HttpResponse } from "@angular/common/http";
import { map } from "rxjs/operators";
import erifa from "@theseed.dev/erifa";

// Initialise la clé une seule fois au démarrage
erifa.setKey(import.meta.env["NG_APP_ERIFA_KEY"] ?? "");

export const erifaInterceptor: HttpInterceptorFn = (req, next) => {
  // Chiffrement du body sortant
  if (req.body !== null && req.body !== undefined) {
    const encrypted = erifa.encrypt(req.body);
    req = req.clone({ body: { payload: encrypted } });
  }

  // Déchiffrement de la réponse entrante
  return next(req).pipe(
    map((event) => {
      if (event instanceof HttpResponse && event.body?.payload) {
        const decrypted = erifa.decrypt(event.body.payload);
        return decrypted !== null ? event.clone({ body: decrypted }) : event;
      }
      return event;
    })
  );
};

Enregistre l'interceptor dans app.config.ts :

// src/app/app.config.ts
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { erifaInterceptor } from "./erifa.interceptor";

export const appConfig = {
  providers: [
    provideHttpClient(withInterceptors([erifaInterceptor])),
  ],
};

C'est tout. Toutes tes requêtes HttpClient sont maintenant chiffrées automatiquement.


Injection de clé

Il existe trois façons d'injecter la clé côté frontend :

1. Script de build (recommandé — clé obfusquée dans le bundle)

{
  "scripts": {
    "dev":   "node node_modules/@theseed.dev/erifa/scripts/inject-key.js && vite"
  },
  "erifa": { "key": "ma-cle-secrete" }
}

2. Variable d'environnement (Next.js, Nuxt, Angular)

erifa.setKey(process.env.NEXT_PUBLIC_ERIFA_KEY);
// ou
erifa.init({ key: process.env.VITE_ERIFA_KEY });

3. Injection HTML côté serveur (SSR)

<!-- Injecté dynamiquement par le serveur avant de servir le HTML -->
<script>window.__ERIFA_KEY__ = "{{ ERIFA_SECRET }}";</script>
// main.js — lit window.__ERIFA_KEY__ si présent
erifa.init();

API de référence

Client commun (erifa, erifa.create(), erifa.fetch(), erifa.vue())

Tous les clients exposent la même interface :

| Méthode | Signature | |---|---| | get(url, opts?) | Promise<{ data, status, ok }> | | post(url, data, opts?) | Promise<{ data, status, ok }> | | put(url, data, opts?) | Promise<{ data, status, ok }> | | patch(url, data, opts?) | Promise<{ data, status, ok }> | | delete(url, opts?) | Promise<{ data, status, ok }> | | setKey(key) | void |

erifa.encrypt(data) / erifa.decrypt(payload)

Expose les primitives crypto avec la clé courante — utile pour les intégrations custom (Angular, etc.).

const payload  = erifa.encrypt({ secret: "42" });    // → "U2FsdGVk....<hmac>"
const original = erifa.decrypt(payload);              // → { secret: "42" }

erifa.init(options?)

Lit window.__ERIFA_KEY__ ou accepte { key } en option. À appeler au démarrage de l'app.

erifa.setKey(key)

Définit la clé manuellement (échange initial, OIDC, variables d'environnement runtime…).


Format des échanges

// Requête chiffrée par erifa
POST /login
{ "payload": "U2FsdGVkX1+...<ciphertext>.<hmac_sha256_hex>" }

// Réponse chiffrée par le middleware
{ "payload": "U2FsdGVkX1+...<ciphertext>.<hmac_sha256_hex>" }
  • Algorithme : AES via crypto-js (IV + salt aléatoires par chiffrement)
  • Intégrité : HMAC-SHA256 — tout payload altéré est rejeté avant déchiffrement

Mécanisme d'injection de clé — Technique

Vue d'ensemble

[Build time]                             [Runtime]
package.json → inject-key.js → injected-key.js → reconstruct() → SECRET_KEY
    (clé brute)   (script)    (clé obfusquée)     (src/index.js)

Le script scripts/inject-key.js :

  1. Lit la clé depuis package.json (champ erifa.key)
  2. Découpe la séquence en chunks de taille variable (2–8 bytes)
  3. Génère un salt aléatoire par chunk et XOR chaque byte : obfuscated = keyByte ^ salt
  4. Mélange les chunks (Fisher-Yates) — chacun garde son index d'origine
  5. Écrit src/injected-key.js avec la structure obfusquée

Au runtime, _0xReconstruct() re-trie par index, applique le XOR inverse et retourne un Uint8Array.
La clé n'existe sous forme de string qu'au moment de l'affectation à SECRET_KEY.


Avertissements

Toute clé présente dans un bundle navigateur peut être récupérée. L'obfuscation par XOR/chunking n'est pas du chiffrement.

Ce module protège contre :

  • ✅ L'interception réseau (MITM) quand HTTPS n'est pas disponible
  • ✅ L'analyse de trafic (payloads opaques)
  • ✅ Le scraping naïf des sources bundlées

Ce module ne protège pas contre :

  • ❌ Un attaquant avec accès à la machine (DevTools, memory snapshot)
  • ❌ Un bundle décompilé par un reverse engineer déterminé

Pour une sécurité réelle : combine erifa avec HTTPS, des tokens JWT à durée limitée, et une validation stricte côté serveur.


⚠️ Breaking change 1.0.x → 1.1.0 : format du payload modifié (ajout HMAC). Les deux côtés doivent être en 1.1.x ou 1.2.x.