
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
@nkp/either
Advanced tools
@nkp/either
handles values of two possible types by wrapping the value in an Either<R, L>
.
Either<R, L>
is the union of Right<R>
and Left<L>
such that Either<R, L> = Right<R> | Left<L>
.
Either provides utility methods to help the flow and transformation of values between the left and right sides.
const input = '0.5';
const result: string =
// read the input
toNumber(input)
// if failed to parse, default to 50
.orElse(() => 50)
// must be less-than or equal-to 100
.flatMap((number) => number <= 100
? Either.right(number)
: Either.left(new Error('must be lte 100')))
// transform to percentage
.map(number => number * 100)
// transform to string
.map(percent => `the parsed value is: ${percent}%`)
// throw if on a failure path
.throwLeft()
// extract the value
.unwrap();
function toNumber(unknown: unknown): Either<number, string> {
switch (typeof unknown) {
case 'bigint': return Either.right(Number(unknown));
case 'number': return Either.right(unknown);
case 'string': {
const num = Number(unknown);
if (!Number.isFinite(num))
return Either.left('Failed to parse number: string value is not numeric');
return Either.right(num);
}
default: return Either.left(`Failed to parse number: unhandled type "${typeof unknown}""`);
}
}
npm install @nkp/either
yarn add @nkp/either
@nkp/either
targets CommonJS and ES modules. To utilise ES modules consider using a bundler like webpack
or rollup
.
import { Either, Right, Left } from '@nkp/either';
// Right<number>
const right: Right<number> = Either.right(5);
// Left<string>
const left: Left<string> = Either.left('hello');
// Either<number, Error> (Right)
const right: Either<number, Error> = Either.fromRight<number, Error>(5);
// Either<number, Error> (Left)
const left: Left<string> = Either.fromLeft(new Error('an unknown error occured'));
Maps both sides of the Either.
import { Either } from '@nkp/either';
const either: Either<number, string> = Either.fromRight<number. string>(5).
const bimapped: Either<string, Error> = either.bimap(
function onRight(rval: number) {
return `value is: ${rval}`;
},
function onLeft(lval: string) {
return new Error(lval);
},
)
Fire a callback on both sides of the Either.
import { Either } from '@nkp/either';
const either: Either<number, string> = Either.fromRight<number, string>(5).
const unaffected: Either<number, string> = either.bitap(
function onRight(rval: number) {
console.log(`right: ${rval}`);
},
function onLeft(lval: string) {
console.log(`left: ${rval}`);
},
)
either === unaffected; // true
Flatten the right-side of the Either.
import { Either } from '@nkp/either';
const either: Either<Either<boolean, number>, string> =
Either.fromRight<Either<boolean, number>, string>(Either.right(true)).
const flattened: Either<boolean, number | string> = either.flat();
Map the right-side of the Either and flatten the result.
import { Either } from '@nkp/either';
const either: Either<number, Error> = Either.fromRight<number, Error>(100).
const flattened: Either<number, Error> either.flatMap((number) => number > 100
? Either.left(new Error('value must be lte 100'))
: Either.right(number)
)
Map the left-side of the Either and flatten the result.
import { Either } from '@nkp/either';
class HttpError extends Error {
public readonly code: number;
constructor(message: string, code: number) {
super(message);
this.code = code;
}
}
const either: Either<number, HttpError> =
Either.fromLeft<string, HttpError>(new HttpError('Unauthenticated', 401)).
const flattened: Either<string, HttpError> either.flatMapLeft((error) => error.code === 401
? Either.right('recovered from unauthorised error :)')
: Either.left(error);
)
Is the Either a Left?
import { Either } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
if (either.isLeft()) {
either.value; // string
} else {
either.value; // number
}
Is the Either a Right?
import { Either } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
if (either.isRight()) {
either.value; // number
} else {
either.value; // string
}
Map the Either's right-side to a new value.
import { Either } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
const mapped: Either<string, string> = either.map(number => `value: ${number}`);
Map the Either's left-side to a new value.
import { Either } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
const mapped: Either<string, boolean> = either.mapLeft(lval => !!lval);
Map this Either insance to some value.
import { Either, Right } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
const mapped: boolean = either.mapSelf(self => self.isRight());
Map the the left-side of the Either into the right-side.
import { Either, Right } from '@nkp/either';
const either = Either.fromRight<number, string>(5);
const mapped: Right<number> = either.orElse(lval => Number(lval));
Fire a callback on the right-side of the Either.
import { Either } from '@nkp/either';
const either: Either<number, string> = Either.fromRight<number, string>(5).
const unaffected: Either<number, string> = either.tap((rval: number) => {
console.log(`right value is: ${rval}`);
});
either === unaffected; // true
Fire a callback on the left-side of the Either.
import { Either } from '@nkp/either';
const either: Either<number, string> = Either.fromRight<number, string>(5).
const unaffected: Either<number, string> = either.tapLeft((rval: string) => {
console.log(`left value is: ${rval}`);
});
either === unaffected; // true
Fire a callback on the Either instance.
import { Either } from '@nkp/either';
const either: Either<number, string> = Either.fromRight<number, string>(5).
const unaffected: Either<number, string> =
either.tapSelf((self: Either<number, sting>) => {
console.log(`the either is: ${self}`);
});
either === unaffected; // true
Throw on the left-side of the Either.
import { Either } from '@nkp/either';
const either: Either<number, Error> = Either.fromRight<number, Error>(5).
const afterThrow: Right<number> = either.throwLeft();
Throw on the right-side of the Either.
import { Either } from '@nkp/either';
const either: Either<Error, number> =
Either.fromRight<Error, number>(new Error('something went wrong')).
const afterThrow: Left<number> = either.throwRight();
Extract the right-side of the Either.
Throws if the Either is Left.
import { Either } from '@nkp/either';
const either: Either<number, boolean> =
Either.fromRight<number, boolean>(5).
const value: number = either.unwrap();
Extract the left-side of the Either.
Throws if the Either is Right.
import { Either } from '@nkp/either';
const either: Either<number, boolean> =
Either.fromRight<number, boolean>(5).
const value: boolean = either.unwrapLeft();
To a release a new version:
master
branch on GitHubnew release
on GitHub for the latest versionThis will trigger a GitHub action that tests and publishes the npm package.
FAQs
Either represents a value of one of two possible types
We found that @nkp/either demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.