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

@cedric-pouilleux/galexjs

v0.1.1

Published

Deterministic procedural galaxy board — runs on Node, vanilla Three.js, and Vue/TresJS.

Readme

GalexJS

Génération procédurale déterministe d'un plateau galactique. Une lib, trois cibles :

  • Backend Node — pure data, ni Three, ni DOM.
  • Vanilla Three.js — factories impératives qui montent les couches dans un THREE.Group.
  • Vue 3 + TresJS — composable réactif + composant drop-in <GalaxyScene>.

Pour le même (seed, opts), la lib produit des Float32Array byte-à-byte identiques sur V8, SpiderMonkey et JavaScriptCore. Donc le serveur (Node) et le client (Chrome / Firefox / Safari) voient la même galaxie sans payload de structure sur le réseau — seules les actions joueur transitent.

Pourquoi déterministe

Les jeux multi avec carte massive partagent traditionnellement la map en envoyant un dump des positions / cubes / contenus à la connexion. Avec GalexJS le serveur dérive la map depuis (seed, opts) ; le client la dérive aussi côté navigateur, à partir du même seed reçu en plaintext. Tous les bytes sont identiques cross-engine, donc :

  • Pas de protocole de sync pour la structure du monde
  • Validation serveur sans recharger d'état (le serveur reconstruit le cube cible à la volée)
  • Anti-triche trivial : si le client envoie un (cube, star) qui n'existe pas sur le seed, le serveur le sait

La compatibilité cross-engine repose sur de la math transcendante bit-stable (detSin, detCos, detPow…) auditée par un linter statique + un test hash byte-à-byte exécuté en CI sur Chromium / Firefox / WebKit.

Installation

npm install @cedric-pouilleux/galexjs three
# Pour la cible Vue / TresJS :
npm install vue @tresjs/core

three, vue et @tresjs/core sont des peer dependencies. Vue et TresJS sont optionnelles (consommées uniquement par view-vue/).

Usage par cible

Backend Node — pure data

import { createGalaxyData } from '@cedric-pouilleux/galexjs/sim';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });

// Valider une action joueur sans charger d'état persistant.
const cube = galaxy.grid.get(action.cube.i, 0, action.cube.k);
if (!cube) return { ok: false, reason: 'cube does not exist' };
if (!cube.starIndices.includes(action.starIndex)) {
  return { ok: false, reason: 'star not in this cube' };
}
return { ok: true };

Vanilla Three — scène montée à la main

import * as THREE from 'three';
import { createGalaxyData, createGalaxyScene } from '@cedric-pouilleux/galexjs/core';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });
const view = createGalaxyScene(galaxy, { gasDensity: 1.0 });
scene.add(view.object3D);

// Per-frame controls :
view.setDimming(0.5);                              // dim global (close-up)
view.setGasDim(0.45);                              // dim gaz seul (plan view)
view.setHaloVisible(false);                        // halo doux (fog of war)
view.setCoreVisible(false);                        // noyau galactique (fog of war)
view.setOrthoSize(zoom);                           // sprite size en mode ortho
view.setClipping(true, normal, point);             // plan de clipping monde
view.setVisibilityField({ focals: [cube], range: 3 });  // brouillard multi-focal

Vue / TresJS — déclaratif

<script setup lang="ts">
import { TresCanvas } from '@tresjs/core';
import { createGalaxyData, GalaxyScene } from '@cedric-pouilleux/galexjs';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });
</script>

<template>
  <TresCanvas window-size clear-color="#04060b">
    <TresPerspectiveCamera :position="[0, 70, 70]" :look-at="[0, 0, 0]" make-default />
    <GalaxyScene :galaxy-data="galaxy" :gas-density="1.0" />
  </TresCanvas>
</template>

⚠️ Côté vite.config.ts, brancher la conf TresJS sinon <TresCanvas> est rendu comme un custom HTML element vide :

import { templateCompilerOptions } from '@tresjs/core';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue(templateCompilerOptions)],
});

Le sandbox

npm run dev lance le playground complet. Il sert d'exemple de référence : tout est composé à partir des primitives lib, aucun concept de jeu n'est codé dedans.

| Geste / mode | Effet | |---|---| | Clic gauche dans le vide + drag | Rotation orbite | | Clic droit + drag | Rotation orbite (alternative) | | Clic gauche sur un cube + drag | Sélection rectangulaire multi-cubes (cf. RectSelection) | | Clic court sur un cube | Close-up sur le cube | | Relâcher d'un rectangle | Close-up sur tous les cubes contenus dans le rectangle (champ d'étoiles fusionné) | | Molette | Zoom | | Esc | Sortir du close-up | | Espace (en mode mesure) | Cadre sur le trajet courant — dim tout le reste (cf. MeasureTool / Focus trajet) | | Toggle « Brouillard de guerre » | Active le visibility-field multi-focal + masque halo + noyau galactique | | Toggle « Vue plateau 2D » | Bascule en caméra orthographique vue de dessus | | Toggle « Mesurer une distance » | Active le MeasureTool — cube↔cube en orbite, étoile↔étoile en close-up | | Panneau « Génération » | Régénère la galaxie avec d'autres options (count, bras, étalement, gaz, …) |

La galaxie reste toujours centrée (enablePan = false sur les OrbitControls) — le pan est désactivé exprès pour éviter qu'elle dérive hors champ.

Architecture

core/           # Pure data, déterministe, sans Three
  GalaxyData      # Pipeline principal seed → buffers + grid
  CubeGrid        # Indexation spatiale + raycast Amanatides & Woo
  Astronomy       # Conversion world units ↔ années-lumière
  Random          # mulberry32 + dérivation de subseeds par label
  DetMath         # Math transcendantes bit-stables (sin, cos, log, exp, pow)
  Visibility      # Helper de calcul de fog of war

view/           # Vanilla Three — couches visuelles
  GalaxyScene     # Compose tout (stars + halo + gaz + bulbe), expose les contrôles
  CubeMarker      # Marqueur cube pour le concept "joueur" / "flotte" du client
  GridHelper      # Wireframes (occupied lines, visibility tiers)
  closeup/        # Sous-buffer + shader haute fidélité pour la vue rapprochée
  effects/        # Halo, nébuleuses, arm glow, gas streaks, inner ring, center dust

view-vue/       # Vue + TresJS
  composables/    # useGalaxyView (réactif), useGalaxyLayers (déclaratif)
  components/     # <GalaxyScene> drop-in

playground/     # Sandbox de démo (consomme les briques ci-dessus)
  Main.ts, Cameras, Picker, RectSelection, MeasureTool, Fog, PlanView, Closeup…

tools/          # CLI utilitaires
  CheckDeterminism  # Lint statique : interdit Math.sin/cos/etc dans core/
  server-example    # Exemple de validation serveur Node

docs/           # VitePress

Garanties

  • Déterminisme cross-engine : audité par tools/CheckDeterminism.ts (lint statique sur core/) + tests Node + Playwright sur Chromium / Firefox / WebKit.
  • TypeScript strict : tout le repo passe vue-tsc --noEmit.
  • Domaine jeu hors lib : aucun identifiant player / team / fleet / fog of war dans core/, view/, view-vue/. Les primitives sont neutres ; le client jeu compose ses concepts par-dessus (cf. primitives/).
  • Vocabulaire de plateau : cube, grid, world, marker, highlight, selection, hover, visibility, focal, range, closeup, plan view.

Scripts

npm run dev               # Playground vanilla Three
npm run example:server    # Exemple backend Node (validation déterministe)
npm run build             # Build de production (Vite)
npm test                  # typecheck strict + lint déterminisme + 72 tests
npm run test:cross        # Hash determinism sur Chromium / Firefox / WebKit
npm run docs:dev          # Site VitePress en hot-reload
npm run docs:build        # Build statique des docs

Documentation

Trois entry points publiés

| Import | Surface | Dépendances runtime | |---|---|---| | @cedric-pouilleux/galexjs/sim | Données pures déterministes (génération, grid, RNG, math bit-stable, visibilité, pathfinding) | aucune | | @cedric-pouilleux/galexjs/core | /sim + couche Three.js (scène, layers, effets, closeup, paths) | three | | @cedric-pouilleux/galexjs | /core + composables Vue + composant <GalaxyScene> | three, vue, @tresjs/core |

Publication

npm run build         # vite build (JS) + vue-tsc (.d.ts) + assemblage dist/package.json
npm run publish:dist  # npm publish ./dist

Le package.json source omet volontairement le champ exports pour que les imports relatifs continuent de résoudre vers la source pendant le dev. C'est le script scripts/prepare-dist.mjs qui écrit un dist/package.json publish-ready avec la map d'exports complète.

Licence

Tous droits réservés — voir le fichier LICENSE. Le package est publié sur npm pour faciliter la distribution, mais aucune licence d'usage n'est accordée par défaut.