Skip to content

vbrajon/cutjs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cut JS

A shortcut utility JS library for rapidly interacting with objects, dates, and functions.

// Normal use
import { map } from "cut"
map({ a: 1 }, (v) => v + 1) //= {"a":2}

// Proxy use, access .data or .error
import cut from "cut"
cut({ a: 1 }).map((v) => v + 1).data //= {"a":2}
cut({ a: 1 }).x.y.error //= new Error()

// Prototype use, call directly on the object
import "cut?window+prototype"
({ a: 1 }).map((v) => v + 1) //= {"a":2}

// Format a Date
new Date("2000").format("YYYY-QQ") //= "2000-Q1"
new Date("2000").format("day, month, year", "en") //= "January 1, 2000"
new Date("2000T00:00").format("long, short", "ja") //= "2000年1月1日 0:00"

// Format a String
"hello_world".format() //= "Hello World"
"hello_world".format("camel") //= "helloWorld"
"{}_{}".format(["hello", "world"]) //= "hello_world"

// Format a Number
0.30000000000000004.format() //= "0.3"
0.111.format("+0.##%") //= "+11.1%"
123456.789.format(2) //= "120k"
123456.789.format(".") //= "123,457"
123456.789.format("CNÂ¥") //= "CNÂ¥123,456.79"

// Parse a Date
new Date("2000T00:00").parse("tomorrow") //= new Date("2000-01-02T00:00:00+01:00")
new Date("2000T00:00").parse("yesterday at 3pm") //= new Date("1999-12-31T15:00:00+01:00")
new Date("2000T00:00").parse("in one hour, two minutes and thirty-four seconds") //= new Date("2000-01-01T01:02:34+01:00")
new Date("2000T00:00").parse("6:30pm in three days") //= new Date("2000-01-04T18:30:00+01:00")

// Manipulate a Date
new Date("2000").plus("1 month").end("month").format("YYYY-MM-DD hh:mm") //= "2000-02-29 23:59"
new Date("2000").minus({ years: 1, months: 2 }).plus("1 year, 2 months").toISOString().slice(0, 10) //= "2000-01-01"

// Manipulate an Object or Array
const users = [
  { name: "John", age: 30, city: "London" },
  { name: "Jane", age: 14, city: "New York" },
  { name: "Jean", age: 35, city: "Paris" },
]
const usersByCity = users.sort("-age").group("city") //~ {"Paris":[{"name":"Jean","age":35...}
const avgAgeByCity = usersByCity.map((g) => g.mean("age")) //~ {"Paris":35...}

// Add a Function
cut(Array, "transpose", (arr) => arr[0].map((_, i) => arr.map((row) => row[i])))

// Add a shortcut
cut("shortcut", "transpose", (fn, arr) => {
  if (arr.some((row) => row.length !== arr[0].length)) throw new Error("Not a matrix")
  return fn(arr)
})

// Add an alias
cut(Array, "swap", cut.Array.transpose)

// And use it
const matrix = [[1, 2, 3], [4, 5, 6]]
matrix.swap() //= [[1,4],[2,5],[3,6]]
const invalid = [[1], [2, 3]]
invalid.transpose() //! Error: Not a matrix

Functions

  • Generic: is, equal, access, transform
  • Object: keys, values, entries, fromEntries, map, reduce, filter, find, findIndex
  • Array: map, reduce, filter, find, findIndex, sort, group, unique, min, max, sum, mean, median
  • Function: decorate, promisify, partial, memoize, every, wait, debounce, throttle
  • String: words, format
  • Number: duration, format
  • Date: relative, getWeek, getQuarter, getLastDate, getTimezone, setTimezone, parse, format, modify, plus, minus, start, end
  • RegExp: escape, replace, plus, minus

Development

bun i @js-temporal/polyfill lodash-es
bun test --watch --coverage

Principles

  1. Shortcuts: Easy extension for input or error handling through decorators.
    // The "sort" function has a shortcut to handle different input types and convert them to the proper input
    const users = await fetch("https://jsonplaceholder.typicode.com/users")
    sort(users, "name") // accepts a string to sort by the property
    sort(users, "-address.city") // accepts a string with "-" to sort in descending order and "." to access nested properties
    sort(users, (v) => v.name) // accepts a function of length 1
    sort(users, ["-address.city", (v) => v.name]) // accepts an array for multi-sorting
  2. Simplicity: Few core functions, easy to use and understand.
    // Object: map, reduce, filter, find (and other equivalent Array functions)
    // Array: sort, group, unique, min, max, sum, mean, median
    // String: format
    // Number: format
    // Date: format, parse, plus, minus, start, end
  3. Combination: Functions with the same name are combined into a single function that handles multiple types.
    // The "format" function is defined for String, Number, and Date
    format("hello world", "capitalize") //= "Hello world"
    format(123456.789, "$") //= "$123,456.79"
    format(new Date("2000"), "YYYY") //= "2000"
  4. Powerful: Few core functions that cover most use cases, removing the need for additional libraries like Lodash, Date-fns, or numfmt.

Roadmap

  • Blog Post / Hacker News / Product Hunt
  • CODE: Iterator or AsyncIterator
  • CODE: Additional Fn (forEach, findIndex, findLastIndex, some, every, flat, flatMap, reduceRight, concat, slice)
  • CODE: Typescript / TSDoc
  • DOC: per function, from Markdown or TSDoc, like motion.dev or sugarjs.com
  • DOC: button for Source Code + size / Gzip size
  • DOC: Monaco Editor or Github.dev like
  • DOC: Collaboration / Multiplayer / CTRL-S to PR
  • EXPERIMENT: LSP for test runner
  • EXPERIMENT: Fuzzy tests
  • EXPERIMENT: Security tests
  • EXPERIMENT: Composition / Distribution with AI as a Shadcn or v0 registry

About

🔪 Shortcut Utils

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published