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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@byu-oit/cartographer

v0.4.2

Published

The art or technique of making maps

Downloads

841

Readme

Introduction

This utility provides a helpful interface for converting Javascript objects into new forms.

Install

npm i @byu-oit/cartographer

Usage

Basic Usage

import { Cartographer } from '@byu-oit/cartographer'

// Configure the Cartographer how you want
const cartographer = new Cartographer().cpy('y', 'x')

// Get data that you want to be mapped
const sourceData1 = { x: '1' }
const sourceData2 = { x: '2' }

// use your configured Cartographer to map any number of sources
const result1 = cartographer.run(sourceData1)
// expected result: { y: '1' }
const result2 = cartographer.run(sourceData2)
// expected result: { y: '2' }

Documentation

Basic Functionality

  • set: sets the first parameter in the result object to the second parameter (This is static)
const cartographer = new Cartographer().set('To', 'Value')
// Output : { To: 'Value' }
  • cpy : sets the first parameter in the result object to the REFERENCE of the second parameter
const cartographer = new Cartographer().cpy('To', 'reference')
// Input : { reference: 'Value' }
// Output : { To: 'Value' }

Additional Functionality

Because a lot of data needs functionality more complex than just setting and copying we have added these additional features:

  • Conditions
  • Default Value
  • Transformers
  • Lookups / Dictionaries
  • Other Predefined Transformers (Pick & Select)
  • Using Cartographer to create Configuration Files

All of these features can be added to the basic set and cpy methods using options

import { Cartographer, Transformers } from '@byu-oit/cartographer'

const condtion = new Expression({ operands: [{ value: 1 }, { value: 1 }], operator: Operators.EQ })
const lookup = Transformers.Lookup({ dictionaryName: 'dictionaryName'})
const cartographer = new Cartographer().cpy('To', 'Value', {condtion: condtion, transformers: [lookup], defaultValue : "NO VALUE FOUND"})
// Lookup is a predefined transformer that uses dictionaries 

Conditions

We use the BYU poliblob package for all Condition Logic Visit Poliblob Repo

  • It should be noted that the Reference in the poliblob expressions can reference both the source and the result in the cartographer.
    • Source Reference Example:
      • const condition = new Condition().reference('path.in.source').equals(1).build()
    • Result Reference Example ($result):
      • const condtion = new Condition().reference('$result.path.in.result').equals(1).build()
      • $result must be used to access result
  • If the expression evaluates to true then the value is set otherwise it will not be set at all

Default Value

When the default value should be set:

  • If the reference is not found then it will set it to the default value
  • If the transformers return a null value

Transformers

Transformers are functions that you can register with the cartographer to call them in your configuration using an id. Your resolved reference or value will then be ran through the function updating the value that will be set.

  • If an array is given then the transformer will be run on each element in the array.
  • Your transformers must be registered with the Cartographer system.
  • The transformers are ran sequentially (order matters)
  • Transformers can access the Cartographer Object, Result, and Source if configured correctly.
export interface CartographerRunContext {
 source: unknown
 result: unknown
}

(this: Cartographer, value: unknown, options: Options, context?: CartographerRunContext): unknown

If you do not need to access the Cartographer Instance or the context then you do not need to specify those parameters in your function.

Here is a basic transformer that does not need access to the cartographer or the context

import { Static, Type } from '@sinclair/typebox'
import { TransformerRegistry } from '../../src/registry/index.js'
import * as System from '../../src/system/system.js'

export const Schema = Type.Object({
  incrementBy: Type.Number({ description: 'The amount numbers will be incremented by' })
}, {
  description: 'The increment transformer options'
})

export type Model = Static<typeof Schema>

export const Name = 'increment'

export const Func: TransformerRegistry.Transformer<Model> = function increment (value, { incrementBy }) {
  if (typeof value === 'number') {
    return value + incrementBy
  } else {
    return value
  }
}

Here is a contrived example of a transformer using context

export const Schema = Type.Object({
 path: Type.String({ description: 'The path in the result that you are looking for' })
}, {
 description: 'The resultSearch transformer options'
})

export type Model = Static<typeof Schema>

export const Name = 'result'

export const Func: TransformerRegistry.Transformer<Model> = function result (value, options, context) {
 if (context != null) {
  return get(context.result, options.path)
 }
}

const Config = { transformer: Func, args: Schema }

Transformers must be registered to the Cartographer using this system call of the Cartographer

import { Transformer } from '@byu-oit/cartographer/system'

Transformer<typeof Schema>(Name, { transformer: Func, args: Schema })

Lookups / Dictionaries

Mapping values to corresponding values is a very common task and because of this we have add functionality to have lookups and dictionaries in the cartographer

  • Dictionaries are registered similar to how transformers are registered
  • You define the id of the dictionary in the system call and then use that value in your configuration to have values looked up
const numberDictionary: DictionaryRegistry.Dictionary<string, number> = new Map<string, number>([
 ['one', 1],
 ['two', 2]
])
System.Dictionary('stringToNumber', numberDictionary)

const source = {
    y: 'one'
}
const lookup = Transformers.Lookup({ dictionaryName: 'stringToNumber'})
const cartographer = new Cartographer().cpy('x', 'y', { transformers: [lookup] })
result = cartographer.run(source)
// result = { x: 1 }

Parameters:

  • dictionaryName : The name of the dictionary that has been registered with the cartographer
  • throwErr : If true this transformer will throw and error if it does not find a value in the mapping
  • defaultValue : The value that will be set if it is not found in the map.
    • If this value is not set then the transformer will return the original value
  • reference : The path of an object to return from the lookup
    • If your dictionary is a dictionary of objects then you can use the reference to return a property from that object

Other Predefined Transformers (Pick & Select)

Pick

// source = {x: { a: 'one', b: 'two' } }
const cartographer = new Cartographer().trf('y', 'x', Transformers.Pick({ properties: ['a'] }))
// { y : { a : 'one' } }

Given an object this transformer will return the specified properties from that object

Parameters:

  • properties : an array of strings of all the properties that you want to be returned

Select

// source = {x: { a: { b: 'two' } } }
const cartographer = new Cartographer().trf('y', 'x', Transformers.Select({ path: 'a.b' }))
// { y : 'two' }

Given a path this transformer will return the value at the given path. If it does not find a value then it will return the default value.

Parameters:

  • path : a string of the path of the value that you want returned
  • defaultValue : the value that you want returned if the path value resolves to undefined

Using Cartographer to create Configuration Files

One of the main features of the Cartographer is that it can be converted completely to and from JSON. The toJson method serializes the configuration to be stored or transferred statically (e.g. exposing the cartographer via API or storing configurations in a database). Additionally, the from constructor validates the configuration, or throws and error if the configuration could not be parsed.

  • Once you configure the cartographer instance how you want then you can call toJson and it will convert that cartographer instance to a json object
  • Using that json object you can create a new instance of your cartographer with the same configurations using the from method
const cartographer = new Cartographer()
const configuration = cartographer.toJson()
const newCartographer = Cartographer.from(JSON.parse(configuration))

Global Settings

const cartographer = new Cartographer({
  transformers: [
    Transformers.Lookup({ dictionaryName: 'stringToNumber', reference: 'value' })
  ]
})
// Every operation that is ran with this cartographer object will now add this transformer

you can set global transformations and conditions that are run on everything.

  • Condition:
    • If both a global condition and a local condition are set then both must be true for the value to be set
  • Transformer:
    • Global transformers are ran in order after the local transformers have finished

Helper Methods

The methods below are used as shortcuts

  • trf
  • trl
  • toObject
  • toJson
  • from

trl

trl : shorthand for writing a cpy that has a lookup

trl (to: string, from: string, dictionary: string, options?: SetOptions & Omit<LookupOptions, 'dictionaryName'>) => this

const cartographer = new Cartographer()
        .trl('to', 'from', 'spanishToEnglish', { throwErr: true, defaultValue: null })

trf

trf : shorthand for writing a cpy with transformers attached to it.

trf (to: string, from: string, ...transformers: TransformerModel[]): => this

const cartographer = new Cartographer().trf('to', 'from', Transformers.Pick({ properties: ['value'] }))

toObject

toObject : Returns the cartographer as an object

toObject (): => ConfigurationModel

const cartographer = new Cartographer().toObject()

toJson

toJson : Returns the cartographer as a string

toJson (): => string

const cartographer = new Cartographer().toJson()

from

from : Returns the cartographer as a string

from (config : unknown): => Cartographer

const cartographer = new Cartographer().from(configuration)