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

@jsarc/qust

v0.0.1-beta.1.2

Published

Qust est une bibliothèque TypeScript ultra-légère et performante pour la sérialisation et désérialisation d'objets en chaînes de requête (query strings). Elle offre une API simple et puissante pour manipuler les paramètres d'URL avec support des types com

Readme

@jsarc/qust

License TypeScript Browser Node.js Bundle Size

@jsarc/qust est une bibliothèque TypeScript ultra-légère et performante pour la sérialisation et désérialisation d'objets en chaînes de requête (query strings). Elle offre une API simple et puissante pour manipuler les paramètres d'URL avec support des types complexes, des tableaux, des objets imbriqués et des options avancées.

✨ Fonctionnalités

  • Sérialisation complète : Conversion d'objets JavaScript/TypeScript en query strings
  • Parsing intelligent : Reconstruction d'objets à partir de query strings
  • Support multi-format : Tableaux au format bracket, index, comma ou séparateur personnalisé
  • Objets imbriqués : Profondeur configurable pour les structures complexes
  • Filtrage avancé : Exclusion des valeurs nulles, chaînes vides ou selon vos critères
  • Encodage/décodage : Contrôle total sur l'encodage URI
  • Type-safe : Typage TypeScript complet avec génériques
  • Léger : Seulement ~3.5KB minifié
  • Universal : Compatible navigateur, Node.js, Deno, Bun, etc.

📦 Installation

Via npm/yarn/pnpm

npm install @jsarc/qust
# ou
yarn add @jsarc/qust
# ou
pnpm add @jsarc/qust

Importation directe (CDN)

<script src="@jsarc/qust/qust.all.js"></script>

🚀 Démarrage Rapide

TypeScript/ES Modules

import { qust, Qust } from '@jsarc/qust';

// Utilisation avec les fonctions utilitaires
const query = qust.stringify({ name: "John", age: 30 });
// → "?name=John&age=30"

const obj = qust.parse("?name=John&age=30");
// → { name: "John", age: 30 }

CommonJS

const { qust } = require('@jsarc/qust');

Navigateur (global)

<script src="@jsarc/qust/qust.all.js"></script>
<script>
  // Disponible globalement
  const query = qust.stringify({ name: "John", age: 30 });
  const obj = qust.parse(query);
</script>

📚 API Référence

Types

type Primitive = string | number | boolean | null | undefined;
type QueryValue = Primitive | Primitive[] | { [key: string]: QueryValue };
type QueryObject = { [key: string]: QueryValue };

interface QustOptions {
  arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'none';
  arraySeparator?: string;
  skipNull?: boolean;
  skipEmptyString?: boolean;
  encode?: boolean;
  decode?: boolean;
  depth?: number;
}

Classe Qust

Constructeur

new Qust(options?: QustOptions)

Crée une nouvelle instance avec des options personnalisées.

Méthodes

  • stringify(obj: QueryObject): string : Convertit un objet en query string
  • parse<T = QueryObject>(queryString: string): T : Convertit une query string en objet
  • setOptions(newOptions: Partial<QustOptions>): void : Met à jour les options
  • getOptions(): Required<QustOptions> : Retourne les options actuelles

Fonctions utilitaires globales

// stringify avec options par défaut
qust.stringify(obj: QueryObject, options?: QustOptions): string

// parse avec options par défaut
qust.parse<T = QueryObject>(queryString: string, options?: QustOptions): T

Options par défaut

const DEFAULT_OPTIONS = {
  arrayFormat: 'bracket',
  arraySeparator: ',',
  skipNull: true,
  skipEmptyString: false,
  encode: true,
  decode: true,
  depth: 10
};

🔧 Utilisation Détaillée

Format des tableaux

Qust supporte plusieurs formats pour les tableaux :

1. Format "bracket" (défaut)

const obj = { tags: ["js", "ts", "node"] };
qust.stringify(obj);
// → "?tags[]=js&tags[]=ts&tags[]=node"

qust.parse("?tags[]=js&tags[]=ts&tags[]=node");
// → { tags: ["js", "ts", "node"] }

2. Format "index"

const obj = { coords: [10, 20, 30] };
qust.stringify(obj, { arrayFormat: "index" });
// → "?coords[0]=10&coords[1]=20&coords[2]=30"

qust.parse("?coords[0]=10&coords[1]=20&coords[2]=30");
// → { coords: [10, 20, 30] }

3. Format "comma"

const obj = { values: [1, 2, 3] };
qust.stringify(obj, { arrayFormat: "comma" });
// → "?values=1,2,3"

qust.parse("?values=1,2,3", { arrayFormat: "comma" });
// → { values: [1, 2, 3] }

4. Format "separator"

const obj = { items: ["a", "b", "c"] };
qust.stringify(obj, { 
  arrayFormat: "separator",
  arraySeparator: "|" 
});
// → "?items=a&items=b&items=c"
// Chaque élément devient un paramètre distinct avec la même clé

5. Format "none"

const obj = { items: ["x", "y"] };
qust.stringify(obj, { arrayFormat: "none" });
// → "?items=x&items=y"
// Similaire à separator mais géré différemment en interne

Objets imbriqués

const obj = {
  user: {
    name: "Alice",
    settings: {
      theme: "dark",
      notifications: true
    }
  }
};

const query = qust.stringify(obj);
// → "?user[name]=Alice&user[settings][theme]=dark&user[settings][notifications]=true"

const parsed = qust.parse(query);
// → { user: { name: "Alice", settings: { theme: "dark", notifications: true } } }

Contrôle de la profondeur

// Limite la profondeur de sérialisation/désérialisation
const q = new Qust({ depth: 2 });

const obj = {
  a: { 
    b: {
      c: {  // Ce niveau sera ignoré (profondeur > 2)
        d: 10
      }
    }
  }
};

q.stringify(obj);
// Avertissement : "Qust: Profondeur maximale atteinte"

Filtrage des valeurs

const obj = {
  a: null,
  b: "",
  c: "value",
  d: 0,
  e: undefined
};

// Ignore null et chaînes vides
qust.stringify(obj, { 
  skipNull: true, 
  skipEmptyString: true 
});
// → "?c=value&d=0"

// Garde toutes les valeurs
qust.stringify(obj, { 
  skipNull: false, 
  skipEmptyString: false 
});
// → "?a=null&b=&c=value&d=0"

Contrôle de l'encodage

const obj = { city: "Paris & Lyon" };

// Avec encodage (défaut)
qust.stringify(obj);
// → "?city=Paris%20%26%20Lyon"

// Sans encodage
qust.stringify(obj, { encode: false });
// → "?city=Paris & Lyon"

// Parsing avec/sans décodage
qust.parse("?city=Paris%20%26%20Lyon", { decode: true });
// → { city: "Paris & Lyon" }

qust.parse("?city=Paris%20%26%20Lyon", { decode: false });
// → { city: "Paris%20%26%20Lyon" }

Types de données supportés

const obj = {
  string: "hello",
  number: 42,
  boolean: true,
  null: null,
  undefined: undefined,
  array: [1, 2, 3],
  nested: { key: "value" }
};

qust.stringify(obj);
// Les valeurs sont converties automatiquement :
// - boolean → "true"/"false"
// - number → chaîne numérique
// - null → "null"
// - undefined → "undefined"

qust.parse("?string=hello&number=42&boolean=true&null=null");
// → { string: "hello", number: 42, boolean: true, null: null }

🎯 Cas d'utilisation

1. Construction d'URLs

function buildSearchUrl(baseUrl: string, filters: any): string {
  const query = qust.stringify(filters);
  return `\${baseUrl}\${query}`;
}

const filters = {
  q: "laptop",
  category: "electronics",
  price: { min: 100, max: 1000 },
  brands: ["dell", "hp", "lenovo"],
  inStock: true
};

const url = buildSearchUrl("/products", filters);
// → "/products?q=laptop&category=electronics&price[min]=100&price[max]=1000&brands[]=dell&brands[]=hp&brands[]=lenovo&inStock=true"

2. Récupération des paramètres d'URL

// Dans une application web
const currentQuery = (window as any).location.search;
const params = qust.parse(currentQuery);

// Utilisation avec React/Vue/Angular
function useQueryParams() {
  const [params, setParams] = useState(() => {
    return qust.parse((window as any).location.search);
  });

  const updateParams = (newParams: any) => {
    const query = qust.stringify({ ...params, ...newParams });
    (window as any).history.pushState({}, '', `?\${query}`);
    setParams(qust.parse(query));
  };

  return [params, updateParams];
}

3. Communication API

// Client-side
async function fetchWithParams(endpoint: string, params: any) {
  const query = qust.stringify(params);
  const response = await fetch(`\${endpoint}\${query}`);
  return response.json();
}

// Server-side (Node.js/Express)
app.get('/api/data', (req, res) => {
  const params = qust.parse(req.url);
  // Traiter les paramètres...
  res.json({ data: params });
});

4. Sauvegarde d'état

class FormState {
  private state: any = {};

  saveToUrl() {
    const query = qust.stringify(this.state, {
      skipEmptyString: true,
      skipNull: true
    });
    (window as any).location.hash = query;
  }

  loadFromUrl() {
    const query = (window as any).location.hash.substring(1);
    this.state = qust.parse(`?\${query}`) || {};
  }
}

🔧 Configuration Avancée

Instance personnalisée

// Création d'une instance avec configuration spécifique
const customQust = new Qust({
  arrayFormat: 'comma',
  skipNull: true,
  skipEmptyString: true,
  depth: 5
});

// Réutilisation avec la même configuration
const query1 = customQust.stringify(obj1);
const query2 = customQust.stringify(obj2);

// Modification dynamique
customQust.setOptions({ arrayFormat: 'index' });

Combinaison avec d'autres bibliothèques

import { qust } from '@jsarc/qust';
import {
    StringSchema,
    NumberSchema,
    BooleanSchema,
    DateSchema,
    EnumSchema,
    NotEnumSchema,
    ArraySchema,
    FileSchema,
    ObjectSchema,
    ChosenTypeSchema,
    AnyTypeSchema,
} from '@jsarc/jon';

const JON = {
    'String': StringSchema,
    'Number': NumberSchema,
    'Boolean': BooleanSchema,
    'Date': DateSchema,
    'Enum': EnumSchema,
    'NotEnum': NotEnumSchema,
    'Array': ArraySchema,
    'File': FileSchema,
    'Object': ObjectSchema,
    'ChosenType': ChosenTypeSchema,
    'AnyType': AnyTypeSchema,
}; // Pour la validation

// Validation avant sérialisation
const schema = new JON.Object('fr').struct({
  name: new JON.String('fr').required(),
  age: new JON.Number('fr').min(0).max(150),
  tags: new JON.Array('fr').types(new JON.String('fr'))
});

function safeStringify(obj: any) {
  const validation = schema.check(obj);
  if (validation.valid) {
    return qust.stringify(obj);
  }
  throw new Error(`Validation failed: \${validation.errors}`);
}

📋 Table des formats de tableaux

| Format | Exemple de sortie | Description | |--------|-------------------|-------------| | bracket | tags[]=a&tags[]=b | Format standard avec crochets vides | | index | tags[0]=a&tags[1]=b | Avec indices explicites | | comma | tags=a,b | Séparés par des virgules | | separator | tags=a&tags=b | Paramètres multiples avec même clé | | none | tags=a&tags=b | Similaire à separator, traitement interne différent |

🚨 Gestion des cas limites

Tableaux vides

qust.stringify({ items: [] });
// → "" (par défaut, les tableaux vides sont ignorés)

Valeurs spéciales

qust.stringify({ 
  special: "a&b=c?d#e",
  spaces: "hello world",
  unicode: "🎉"
});
// → "?special=a%26b%3Dc%3Fd%23e&spaces=hello%20world&unicode=%F0%9F%8E%89"
// Tout est correctement encodé

Conflits de clés

// Gestion automatique des structures complexes
const obj = {
  "user[name]": "direct",  // Clé avec crochets
  user: { name: "nested" } // Objet imbriqué
};

qust.stringify(obj);
// Les deux sont correctement gérés

🔬 Performance

Qust est optimisé pour la performance :

  • Algorithmes récursifs optimisés avec contrôle de profondeur
  • Encodage/décodage sélectif pour éviter les opérations inutiles
  • Gestion mémoire efficace avec réutilisation d'objets
  • Parsing streaming pour les grandes chaînes
// Benchmark approximatif (sur Node.js v18)
const largeObj = {
  users: Array(1000).fill(0).map((_, i) => ({ 
    id: i, 
    name: `User\${i}`,
    data: { nested: { value: i * 2 } }
  }))
};

console.time('stringify');
const query = qust.stringify(largeObj);
console.timeEnd('stringify'); // ~50ms

console.time('parse');
const parsed = qust.parse(query);
console.timeEnd('parse'); // ~30ms

🔧 Build et Développement

Structure du projet

@jsarc/qust/
├── qust.all.js
├── qust.all.min.js
├── index.d.ts
├── index.js
├── index.min.d.ts
├── index.min.js
├── package.json
├── tsconfig.json
└── README.md

📋 Compatibilité

Navigateurs Supportés

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+
  • Opera 47+
  • iOS Safari 12+
  • Android Chrome 60+

Environnements

  • Node.js 18+
  • Deno 1.30+
  • Bun 1.0+
  • React Native
  • Electron
  • Cloudflare Workers
  • Vercel Edge Functions

Dépendances

  • Aucune dépendance externe : Qust est entièrement autonome
  • TypeScript : Support natif (types inclus)
  • ES6+ : Utilise les fonctionnalités modernes JavaScript

🛡️ Meilleures Pratiques

Sécurité

  1. Toujours encoder par défaut : Protège contre les injections
  2. Valider les entrées : Avant de parser des données non fiables
  3. Limiter la profondeur : Éviter les attaques par récursion
  4. Utiliser skipEmptyString : Pour les formulaires web
// Configuration sécurisée par défaut
const secureQust = new Qust({
  encode: true,        // Toujours encoder
  depth: 10,          // Limite raisonnable
  skipNull: true,     // Ignorer les valeurs nulles
  skipEmptyString: true // Ignorer les champs vides
});

Performance

  1. Réutiliser les instances : Pour éviter la recréation d'options
  2. Choisir le bon format : "comma" pour les grands tableaux
  3. Filtrer tôt : skipNull/skipEmptyString réduit la charge
  4. Éviter la sur-sérialisation : Ne pas sérialiser inutilement

Maintenance

  1. Documenter les schémas : Utiliser TypeScript pour la documentation
  2. Tests unitaires : Couvrir les cas d'utilisation
  3. Versionner les APIs : Changements de format d'arrayFormat
  4. Logging en dev : Activer les avertissements de profondeur

📄 Licence

MIT License - Voir le fichier LICENSE pour plus de détails.

Copyright (c) 2024 INICODE

Permission est accordée, gratuitement, à toute personne obtenant une copie de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter dans le Logiciel sans restriction, y compris sans limitation les droits d'utilisation, de copie, de modification, de fusion, de publication, de distribution, de sous-licence et/ou de vente de copies du Logiciel, et de permettre aux personnes à qui le Logiciel est fourni de le faire, sous réserve des conditions suivantes :

🐛 Signaler un Bug

Envoyez nous un mail à l'adresse [email protected] pour :

  • Signaler un bug
  • Proposer une amélioration
  • Poser une question

@jsarc/qust - La solution ultime pour la manipulation de query strings en TypeScript.

Développé par l'équipe INICODE