Skip to content

HonoluluHenk/typesafe-json-path

Repository files navigation

typesafe-json-path

Typesafe navigation in JSON data structures for typescrpt.

Contributors Forks Stargazers Issues MIT License

CI NPM

Table of Contents
  1. About The Project
  2. Usage
  3. Getting Started
  4. Changelog
  5. Roadmap
  6. Contributing
  7. License
  8. Contact
  9. Acknowledgments

About The Project

  • Ever had a JSON data structure that is implemented in more than one file? Translation-files anyone?
  • You wanted to access these values in a typesafe manner? I.e.: without resorting to string-keys?
  • You want refactoring support from your IDE when renaming properties?
  • You want compilation to fail if you mistyped a property name?

Read the examples in Usage to find out how!

(back to top)

Usage

Best shown by example:

Minimal example

import {TypesafeJsonPath} from '@honoluluhenk/typesafe-json-path';

const translationsRoot = {
  FOO: {
    BAR: {
      BAZ: 'Baz was here!',
      HELLO: 'Hello World',
    }
  }
};

const path = TypesafeJsonPath.init<typeof translationsRoot>();

// please note: this is not string but real property access!
const pathAsString = path.FOO.BAR.HELLO.$path.path;
// 'FOO.BAR.HELLO'
const value = path.FOO.BAR.HELLO.$path.get(translationsRoot);

console.log(value);
// 'Hello World'

(back to top)

Full example

The full power can be seen here: use a custom Resolver and go wild.

This example implements a translation service that is not access-by-string but fully typesafe!

import {type PathSegment, Resolver, TypesafeJsonPath} from '@honoluluhenk/typesafe-json-path';

const translationsRoot = {
  FOO: {
    BAR: {
      BAZ: 'Baz was here!',
      HELLO: 'Hello %s',
      RUCKSACK: 'Rucksack',
    },
  },
};
// some other translation
const translationsDE = {
  FOO: {
    BAR: {
      BAZ: 'Baz war hier!',
      HELLO: 'Hallo %s',
    },
  },
};

// your custom path resolver
class Translator<T extends object> extends Resolver<unknown, T> {
  constructor(
    path: ReadonlyArray<PathSegment>,
    private readonly myTranslateService: MyCustomTranslateService,
  ) {
    super(path);
  }

  translate(...args: unknown[]): string {
    // Delegate to some translation service.
    return this.myTranslateService.translate(this.path, args);
  }
}

// include all variants to have full refactoring support in your IDE
type TranslationType = typeof translationsRoot & typeof translationsDE;

// Now the real fun begins...
const translations = TypesafeJsonPath.init<TranslationType, Translator<any>>(
  path => new Translator(
    path,
    new MyCustomTranslateService(navigator.languages[0], {en: translationsRoot, de: translationsDE}),
  ),
);

// again: this is not string but real property access in a typesafe and refactoring-friendly way!
const text = translations.FOO.BAR.HELLO.$path.translate('Welt');
// internally, myTranslateService.translate() was called with the path-string 'FOO.BAR.HELLO'.
console.log(text);
// Assuming the user language was some german (de) locale:
// 'Hallo Welt'

(back to top)

Getting Started

Prerequisites

The implementation makes heavy use of the Proxy object.

As such, this lib can only be used if it is available.

Installation

This npm library is intended to be used in typescript projects where the

Just install the NPM package:

npm install @honoluluhenk/typesafe-json-path

(back to top)

Changelog

See releases

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Run tests/linting (npm run prepush)
  5. Push to the Branch (git push origin feature/AmazingFeature)
  6. Open a Pull Request

(back to top)

License

Distributed under the Lesser Gnu Public License 2.1 (LGPL-2.1) License. See LICENSE for more information.

(back to top)

Contact

Christoph Linder - post@christoph-linder.ch

Project Link: https://github.com/HonoluluHenk/typesafe-json-path

(back to top)