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

@lifeready/core

v9.0.8

Published

Note that the following only applies to the new API.

Readme

Key Crypt API

Note that the following only applies to the new API.

General design principles

  • Use typing as much as possible
  • Use auto inferred type where possible. This makes refactoring easier. Also less likely to cause errors because auto type inference usually resolves to the most strict type.
  • Provide utilities to remove boiler plates where possible. Should consider even small and simple boiler plates to improve the ability to refactor, reduce bugs, and maintain consistency.
  • Consistent naming convention
  • Prefer composition over inheritance. Generally allow for more flexibility in combining primitive functions. Coding style is more functional which makes it easier to reason and debug.

KC specific design

  • Provide data in a form that's close to the graphql input and results such that the user of the lib can experiment in the online graphql explorer to test out queries and mutations and expect the results to be the same.
    • Original data from API is always retained
    • Processed data (eg. decrypted, JSON parsed) are names with consistent suffix, eg.
      • cipherMeta (encrypted string) -> cipherMetaClear (decrypted string) -> cipherMetaClearJson (decrypted string JSON parsed)
      • plainMeta (plain string) -> plainMetaJson (plain string JSON parsed)
  • Allow optional efficiency improvements. eg, the encryption keys can be optionally provide for mutations. If not provided, the mutation will make additional queries to fetch the keys.
  • Allow future refactoring to make KC client independent of Angular.
  • Transparent encryption and decryption of data where possible
  • Most queries should be defined out side of KC-client because the business logic dictate which fields to select.
    • Except for certain instances where decrypting the data requires keys not managed within the key graph, eg. the key exchange function use a raw key string from OOB, so it contains functions to fetch and decrypt the data.
  • gqlTyped only has generic type on the return of the query or mutation, not on the input variable. Usually the LrMutation are created in a function, which has explit input types. The function will also do other preparation for the mutation, so the input type is not just the input variables. Because the end user does not need to interact with the gql mutation, it doesn't need an input variable type.
  • Use string enum instead of string constant union types because sometime you need to drop to JS and string typos becomes easy.
  • Return LrMutation where possible so that the user can choose how to compose the mutations. Unfortunately that's not always possible if subsequent steps depend on previous mutations. But these instances are rare.

Good to know

  • JSON.stringify(void 0) returns undefined so no need for this: input JSON.stringify(input)
  • When using mergeMap,concatMap, switchMap you can just return a promise.

Future

  • Being able to cancel apollo requests would be nice. Let's wait for support from apollo on that.

Convention

  • Suffixes
    • Option is user to group variables together.
    • Input is graphql mutation variable
    • Mutation is a graphql mutation
    • Query is a graphql query
  • When a graphql mutation wants to clear a field, pass in undefined or null as the variable value. If you want to prove that the user cleared the field, you can use empty string, which will get encrypted. And all encryption has a timestamp it can be verified to be cleared by the user at a certain time.
  • The return type of mutations should not use xxxNode types because the mutation performs a specific selection of fields in the result. The return type should be customised to include only those fields.
  • Use gqlTyped instead of gql and co-locate the interface for the result just above the query definition. Example
export interface CancelKeyExchangeMutation {
  cancelKeyExchange: {
    keyExchange: {
      id: ID;
    };
  };
}
export const CancelKeyExchangeMutation = gqlTyped<CancelKeyExchangeMutation>`
mutation CancelKeyExchangeMutation($input: CancelKeyExchangeInput!) {
  cancelKeyExchange(input: $input) {
    keyExchange {
      id
    }
  }
}
`;

Notice the name of the interface and the query is the same. The name CancelKeyExchangeMutation should always be repeated 4 times: as the interface name, the query variable name, the gqlTyped generic type, and the mutation name.