@materya/carbon
v2.2.0
Published
A collection of useful modules with a no-dependency, clean, tested and lightweight code philosophy.
Downloads
51
Readme
@materya/carbon
A collection of useful modules with a no-dependency, clean, tested and lightweight code philosophy.
Install
npm i @materya/carbon
TOC
Modules
fs
Module dedicated to explore and manipulate filesystem related operations.
find
up
Search a given file name
in the current directory cwd
and up the tree until it reaches the top. Will throw if no matching file is found.
import * as carbon from '@materya/carbon'
const rcFileName = '.rc.json'
const rcFilePath = carbon.find.up(process.cwd(), rcFileName)
crawl
list
Crawl from directory
, listing all files sorted until depth
is reached.
import * as carbon from '@materya/carbon'
const list = carbon.crawl.list(process.cwd(), 2)
/*
> list
[
'filename1.ext',
'filename2.ext',
'dir1/filename1.ext',
'dir1/filename2.ext',
'dir1/dir2/filename1.ext',
]
*/
tree
Crawl from directory
, sorting out files and directories in a tree-like object until depth
is reached.
import * as carbon from '@materya/carbon'
const tree = carbon.crawl.tree(process.cwd(), 2)
/*
> tree
{
files: ['filename.ext', 'filename.ext'],
directories: {
somedir: {
files: ['filename.ext', 'filename.ext'],
directories: {},
},
...
},
}
*/
trigger
Crawl from directory
, triggering action(name: string, path: string)
callback on each file found.
import * as carbon from '@materya/carbon'
const action: FileActionCallback = (name, path) => { /* do something */ }
carbon.crawl.trigger(process.cwd(), action)
env
Module dedicated to manage process.env
and access environment variables.
get
Get a given name
env variable. Will throw unless a defaultValue
is provided.
import * as carbon from '@materya/carbon'
const myEnv = carbon.env.get('MY_ENV', 42)
tools
Various utility methods to make life easier.
object
isObject
Based on numerous threads and propositions across the internet (mainly SO), this method aims to identify with the best accuracy and the least complexity if a given value is an "object" (ie. an associative array).
See all tests at ./test/tools/object.test.ts
import { tools } from '@materya/carbon'
tools.object.isObject({}) // true
tools.object.isObject([]) // false
tools.object.isObject(() => null) // false
tools.object.isObject((new Date())) // false
// ...
merge
Deep merge together nested arrays or maps.
NOTE: The later sources keys take precedence over the previous same ones if a "conflict" arise.
import * as carbon from '@materya/carbon'
const map1 = {
animals: {
cats: {
types: ['lion', 'tiger'],
props: {
run: true,
eat: true,
die: true,
},
},
cars: ['dodge', 'ford'],
},
}
const map2 = {
animals: {
cats: {
types: ['cheetah'],
props: {
fly: false,
die: false, // it is well known that cats have 9 lives and don't die.
},
},
},
cars: ['audi', 'bmw'],
}
const merged = carbon.tools.merge(map1, map2)
/*
> merged
{
animals: {
cats: {
types: ['lion', 'tiger', 'cheetah'],
props: {
run: true,
eat: true,
die: false,
fly: false,
},
},
cars: ['dodge', 'ford', 'audi', 'bmw'],
},
}
*/
pick
Extract specific keys from a given object and return a new one with only those keys.
import * as carbon from '@materya/carbon'
const obj = {
a: 'foo',
b: 42,
c: 'bar',
d: { obj: 'foobar' },
}
const partialObj = carbon.tools.pick(obj)('b', 'd')
/*
> partialObj
{
b: 42,
d: { obj: 'foobar' },
}
*/
exclude
Exclude specific keys from a given object and return a new one without those keys.
import * as carbon from '@materya/carbon'
const obj = {
a: 'foo',
b: 42,
c: 'bar',
d: { obj: 'foobar' },
}
const partialObj = carbon.tools.exclude(obj)('b', 'd')
/*
> partialObj
{
a: 'foo',
c: 'bar',
}
*/
Types
Carbon provides also a set of utility types.
ObjectLiteral
Since the standard type object
is hard to use and error prone, this general type aims to replace it.
See https://github.com/microsoft/TypeScript/issues/21732 for more details.
type ObjectLiteral = Record<keyof any, unknown>
CastIndexSignature<Type>
Workaround to fix an index signature issue with interfaces.
See https://github.com/microsoft/TypeScript/issues/15300 for more details.
interface Todo {
title: string;
description?: string;
completed: boolean;
}
type TypeWithGenericObject<T extends Record<string | number | symbol, unknown>> = T
let test1: TypeWithGenericObject<Todo> // Throw a ts(2344) error
let test2: TypeWithGenericObject<CastIndexSignature<Todo>> // Works
DeepPartial<Type>
Traverse a Type
extending an object to switch all the props as optionals, recursively.
interface Todo {
title: string;
description: string;
metadata: {
foo: {
bar: {
ber: string;
};
};
};
completed: boolean;
}
type DeepPartialTodo: DeepPartial<Todo>
// type DeepPartialTodo = {
// title?: string;
// description?: string;
// metadata?: {
// foo?: {
// bar?: {
// ber?: string;
// };
// };
// };
DeepRequired<Type>
Traverse a Type
extending an object to switch all the props as required, recursively.
interface Todo {
title?: string;
description?: string;
metadata?: {
foo?: {
bar?: {
ber?: string;
};
};
};
completed?: boolean;
}
type DeepRequiredTodo: DeepRequired<Todo>
// type DeepRequiredTodo = {
// title: string;
// description: string;
// metadata: {
// foo: {
// bar: {
// ber: string;
// };
// };
// };
Opaque<Alias, Type>
Type alias that makes a given standard Type
like string
unique by its Alias
name.
Similar and inspired by Flow https://flow.org/en/docs/types/opaque-types/
type UniqueString = Opaque<'UniqueString', string>
const uniqueString: UniqueString = 'foobar'
const nonUniqueString = 'foobar'
const f = (arg: UniqueString): UniqueString => arg
f(nonUniqueString) // ts(2345) error: Argument of type 'string' is not assignable to parameter of type 'UniqueString'
f(uniqueString) // Valid
const f2 = (arg: string): string => arg
f2(nonUniqueString) // Valid
f2(uniqueString) // Valid, still a string
OptionalProps<Type>
Constructs a set of properties type by extracting all the optional keys from Type
.
type Todo = {
title: string;
description?: string;
completed: boolean;
}
type TodoOptionalProps = OptionalProps<Todo>
// type TodoOptionalProps = "description"
RequiredProps<Type>
Constructs a set of properties type by extracting all the required keys from Type
.
type Todo = {
title: string;
description?: string;
completed: boolean;
}
type TodoRequiredProps = RequiredProps<Todo>
// type TodoRequiredProps = "title" | "completed"
SelectivePartial<Type, Keys>
Constructs a type by picking all properties from Type
and then switching Keys
as optionals.
type Todo = {
title: string;
description?: string;
completed: boolean;
createdAt: number;
assignee: string;
}
type PartialTodo = SelectivePartial<Todo, 'createdAt' | 'assignee'>
// type PartialTodo = {
// title: string; // Stays required
// description?: string;
// completed: boolean; // Stays required
// createdAt?: number;
// assignee?: string;
// }
SelectiveRequired<Type, Keys>
Constructs a type by picking all properties from Type
and then switching Keys
as required.
type Todo = {
title: string;
description?: string;
completed: boolean;
createdAt: number;
assignee?: string;
reviewer?: string;
}
type RequiredTodo = SelectiveRequired<Todo, 'assignee' | 'reviewer'>
// type RequiredTodo = {
// title: string;
// description?: string; // Stays optional
// completed: boolean;
// createdAt: number;
// assignee: string;
// reviewer: string;
// }
UnionPick<Type, Values>
Constructs a new type as a valid subset of a given union Type
by picking up all given Values
from it.
type FooBarBaz =
| 'foo'
| 'bar'
| 'baz'
// Valid Type
type FooBar = UnionPick<FooBarBaz, 'foo' | 'bar'>
// Invalid Type
type FooBer = UnionPick<FooBarBaz, 'foo' | 'ber'>
// ^^^^^^^^^^^^^
// Type '"foo" | "ber"' does not satisfy the constraint 'FooBarBaz'.
// Type '"ber"' is not assignable to type 'FooBarBaz'.ts(2344)