URL query encoder/decoder with a user configuration

Overview

@lfgroup/query-coder

URL query coder/decoder with configurable user pattern. It provides the most comfortable experience for encoding and decoding complex nested filter objects. Check out example for more info.

  1. Quickstart
  2. Advanced example
  3. Usage
    1. QueryCoder
      1. Encoding and decoding
      2. Decoding with a default value
    2. QueryHandler
      1. Ignoring required fields
      2. Defining value type
      3. Aliasing query values
      4. Encoding non-string values
      5. Accessing handlers outside of a coder
      6. Using handlers between different coders
      7. Excluding values from encoding

Quickstart

yarn add @lfgroup/query-coder

Query coder is designed to repeat an interface of provided object with QueryCoder, only replacing tree leaves with parser instances — QueryHandlers.

WIP

Advanced example

WIP

Imaging having a such interface for your querying filters:

type SearchGroupsFilter = {
  gameId?: "WorldOfWarcraft" | "WildRift" | "LostArk";
  gameMode?: GameMode;
  from?: Date;
  language?: Language;

  lostArk?: LostArkFilterInput;
  wildRift?: WildRiftFilterInput;
  wow?: WowFilterInput;
};

Let's take 1 example of this:

const filters: SearchGroupsFilter = {
  gameId: "WorldOfWarcraft",
  gameMode: GameMode.WowMythicPlus,
  language: Language.En,
  wow: {
    faction: WowFaction.Alliance,
    dungeon: WowDungeon.MistsOfTirnaScithe,
    minRioRating: 1400,
    region: WowRegion.Europe,
  },
};

Which should result in this:

const query =
  "game=wow&mode=mplus&language=en&faction=alliance&dungeon=mots&rating=1400&region=eu";

So we want to:

  • flatten nested filter object in a query string
  • rename certain keys (gameMode -> mode)
  • re-map certain values (WorldOfWarcraft -> wow)

With this lib, you can init QueryCoder and that's it! 🎉

import { QueryCoder, QueryHandler, Type } from "@lfg/query-coder";

// passing generic interface checks, whether node keys
// are the same as in provided interface
const query = new QueryCoder<SearchGroupsFilter>({
  gameId: new QueryHandler({
    query: "game",
    aliases: {
      WorldOfWarcraft: "wow",
      WildRift: "wr",
      LostArk: "la",
    },
  }),
  gameMode: new QueryHandler({ query: "mode" }),
  language: new QueryHandler({ query: "language" }),
  wow: {
    faction: new QueryHandler({
      query: "faction",
      /**
       * decodeCondition is Partial of generic
       * if decodeCondition is set, search query would be handled
       * with this handler only if decodeCondition matches query
       * For more info, check out section below
       */
      decodeCondition: { gameId: "WorldOfWarcraft" },
    }),
    dungeon: new QueryHandler({
      query: "dungeon",
      decodeCondition: { gameId: "WorldOfWarcraft" },
    }),
    minRioRating: new QueryHandler({
      query: "minRioRating",
      decodeCondition: { gameId: "WorldOfWarcraft" },
      /**
       * You should provide a primitive type, which is different from string
       * Otherwise, url query "foo=313" can result in an unexpected result
       */
      decodeType: Type.Number,
    }),
    region: new QueryHandler({
      query: "region",
      decodeCondition: { gameId: "WorldOfWarcraft" },
    }),
  },
});

query.encode(filters).toString(); // should result in query variable
query.decode(query); // should result in filters variable

Usage

1. QueryCoder

QueryCoder is a main instance you will use to encode and to decode your data. Typically, you should create coders at a global scope and provide a generic of an interface you are planing to encode/decode.

import { QueryCoder, QueryHandler } from "@lfg/query-coder";


interface ObjectToSerialize {
  foo: string;
  bar: {
    baz: string;
  };
}

const coder = new QueryCoder<ObjectToSerialize>({
  foo: new QueryHandler({ query: "foo_in_query" }),
  bar: {
    baz: new QueryHandler({ query: "baz_in_query" }),
  },
});

Encoding and decoding

Using a coder we've created above we can encode object to url query or decode query string to an object:

const object: ObjectToSerialize = {
  foo: 'value of foo',
  bar: {
    baz: 'bazz-value'
  },
};

// Encoding with .encode(T) method, which returns URLSearchParams
const urlSearchParams = coder.encode(object);
console.log(urlSearchParams.toString()); // foo_in_query=value%20of%20foo&baz_in_query=bazz-value

// Decoding with .decode(string) method, which returns T
const decodedObject = coder.decode(urlSearchParams.toString());
console.log(decodedObject); // same as var `object`

Decoding with a default value

Sometimes you may want to provide a default value for decoding proccess to fill required gaps of an interface. Providing default value will deep assign decoded object to default object, overwriting default value with decoded if any provided.

const query = `foo_in_query=url-value`


const defaultObj: ObjectToSerialize = {
  foo: "default",
  bar: {
    baz: "default",
  },
};

const decodedObj = coder.decode(query, { defaultValue: defaultObj });

console.log(decodedObj) // { foo: "url-value", bar: { baz: "default" } }

2. QueryHandler

QueryHandler is a handler for each node leaf of a codable object. It must include a name for a query key and provides additional options. You should mind that:

  • Only leaves, that have QueryHandler will be encoded/decoded
  • Values that are not strings should has decodeType param
interface ObjectToSerialize {
  foo: string;
  bar: {
    baz: string;
  };
}

const coder = new QueryCoder<ObjectToSerialize>({
  foo: new QueryHandler({ query: "foo_in_query" }),
  bar: {
    baz: new QueryHandler({ query: "baz_in_query" }),
  },
});

Ignoring required fields

Refer decode default

Defining value type

Aliasing query values

Encoding non-string values

Accessing handlers outside of a coder

Using handlers between different coders

Excluding values from encoding

You might also like...

An event-driven architecture wrapper for Wechaty that applies the CQS principle by using separate Query and Command messages to retrieve and modify the bot state, respectively.

An event-driven architecture wrapper for Wechaty that applies the CQS principle by using separate Query and Command messages to retrieve and modify the bot state, respectively.

CQRS Wechaty An event-driven architecture wrapper for Wechaty that applies the CQS principle by using separate Query and Command messages to retrieve

Mar 23, 2022

Subgraph to query Doodles NFT tokens along with the traits and owners.

Doodles Subgraph API Subgraph to query Doodles NFT tokens along with the traits and owners. How to use the API Try it out here Example query: { toke

Sep 19, 2022

logseq custom.js and custom.css utilities : resize query table columns, hide namespaces...

logseq custom.js and custom.css utilities : resize query table columns, hide namespaces...

logseq-custom-files custom.js and custom.css utilities for Logseq. current version v20220331 query table view : add handles on the query table headers

Dec 7, 2022

On-chain query batcher for CosmWasm-enabled chains

multiquery On-chain query batcher for CosmWasm. Similar to SCB 10X's multicall contract, but supports any serializable query request, not limited to W

Dec 6, 2022

API and CLI tool to fetch and query Chome DevTools heap snapshots.

Puppeteer Heap Snapshot Capture heap snapshots and query the snapshot for objects matching a set of properties. Read more about it in this blog post.

Jan 3, 2023

A ts/js pkg to query the OnAir Airline Manager's API.

Typescript/Javascript package for querying the OnAir API A Typescript/Javascript wrapper around the OnAir Airline Manager's API. Installation npm i -s

Dec 15, 2022

A Node.js microservice to store and query time series data

Time series storage microservice This is a simple Node.js application which allows the storage and query of time series datasets in an InfluxDB 2.0 in

Apr 25, 2022

The Trino datasource allows to query and visualize Trino data from within Grafana.

Trino Grafana Data Source Plugin The Trino datasource allows to query and visualize Trino data from within Grafana. Getting started Drop this into Gra

Nov 3, 2022

A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.

Obsidian Media DB Plugin A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your va

Dec 21, 2022
Releases(v0.1.0)
  • v0.1.0(Mar 21, 2022)

    🎉 It lives! 🎉

    Basic features of query coder/decoder.

    Plans:

    • [ ] Add a test
    • [ ] Add transform function as decoding middleware
    • [ ] Think about returning URL object instead of string
    Source code(tar.gz)
    Source code(zip)
Owner
LF Group Inc.
Modern group & friend finder for gamers of all kinds.
LF Group Inc.
Web stream based jsonlines decoder/encoder

jsonlines-web Web stream based jsonlines decoder/encoder ✅ Deno ✅ browser ✅ Node.js This library supports JSON in the following formats: Line-delimite

ayame113 4 Nov 16, 2022
z-base-32 encoder & decoder

z32 z-base-32 encoder & decoder npm install z32 Usage const z32 = require('z32') const s = z32.encode('Hello, World!') console.log(s) // jb1sa5dxfo

Mathias Buus 7 Jun 19, 2022
Backend API Rest application for ShortLink, a URL shortening service where you enter a valid URL and get back an encoded URL

ShortLink - The Shortest URL (API) Sobre o Projeto | Como Usar | Importante! Sobre o projeto The Shortest URL é um projeto back-end de ShortLink, um s

Bruno Weber 2 Mar 22, 2022
A simple query builder, it will helps to develop DSL query for Elasticsearch

Elasticsearch Dynamic Query Builder A simple query builder, it will helps to develop DSL query for elasticsearch Installation You can start it from np

Hashemi Rafsan 4 Nov 20, 2022
TypeScript dotbim parser and encoder.

dotbim-ts Open-source TypeScript parser and encoder for dotbim file format. dotbim's website: https://dotbim.net/ Here you can find small manual for d

Baid 5 Aug 2, 2022
🔆🔎👀 Smart Contract Storage Viewer, DataType Guesser, Toolbox & Transaction Decoder

?? ?? ?? Smart Contract Storage HexViewer Demo Target - the target contract API Endpoint - your infura (or equivalent) api key Retrieves smart contrac

tintin 85 Nov 27, 2022
Piccloud is a full-stack (Angular & Spring Boot) online image clipboard that lets you share images over the internet by generating a unique URL. Others can access the image via this URL.

Piccloud Piccloud is a full-stack application built with Angular & Spring Boot. It is an online image clipboard that lets you share images over the in

Olayinka Atobiloye 3 Dec 15, 2022
High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.

lazysizes lazysizes is a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive images picture/srcset), ifra

Alexander Farkas 16.6k Jan 1, 2023
Examples of how to do query, style, dom, ajax, event etc like jQuery with plain javascript.

You (Might) Don't Need jQuery Frontend environments evolve rapidly nowadays and modern browsers have already implemented a great deal of DOM/BOM APIs

NEFE 20.3k Dec 24, 2022