Skip to content

Commit

Permalink
release
Browse files Browse the repository at this point in the history
  • Loading branch information
cevr committed Dec 29, 2023
1 parent 4beafce commit de60db5
Show file tree
Hide file tree
Showing 16 changed files with 708 additions and 844 deletions.
5 changes: 5 additions & 0 deletions .changeset/new-apes-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ftld": major
---

make some adjustments for more tree shakability, release it finally since its stable
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -786,20 +786,22 @@ It handles `Task`, `Result`, `Option`, and even `Promise` types. It always retur
```ts
import { Do, Task, Result, UnwrapNoneError, UnknownError } from "ftld";

// without Do
// without Do you get nesting hell
function doSomething(): SyncTask<UnknownError, unknown> {
return Task.from(() => {
//...
})
.flatMap(() => {
//...
})
.flatMap(() => {
//...
})
.flatMap(() => {
}).flatMap(() => {
//...
return Task.from().flatMap(() => {
//...
return Task.flatMap(() => {
//...
return Task.from().flatMap(() => {
//...
});
});
});
});
}

// if there are any async computations, it will return an Async Task
Expand Down Expand Up @@ -862,7 +864,11 @@ async function calculateNum(): Promise<number>;

function doSomething(): AsyncTask<SomeError | AnotherError, number> {
return Do(function* ($) {
const a = yield* $(calculateNum(), () => new SomeError());
const a = yield* $(
calculateNum(),
(e) => new SomeError() // <-- notice how the error can be mapped over
//^-- the error type is inferred initially as UnknownError which captures the initial error in a value `.error`
);

// can quickly override the error type for any type
const b = yield* $(
Expand Down Expand Up @@ -899,7 +905,6 @@ const objMap = Collection.map(obj, (n) => n + 1);
const listReduce = Collection.reduce(list, (acc, n) => acc + n, 0); // 15
const objReduce = Collection.reduce(obj, (acc, n) => acc + n, 0); // 15


const listFilter = Collection.filter(list, (n) => n % 2 === 0); // [2, 4]
const objFilter = Collection.filter(obj, (n) => n % 2 === 0); // { a: Option.None(), b: Option.Some(2), c: Option.None(), d: Option.Some(4), e: Option.None() }

Expand Down
11 changes: 6 additions & 5 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@
"test:coverage": "vitest run --coverage && open coverage/index.html"
},
"devDependencies": {
"concurrently": "^8.2.0",
"tsup": "^7.1.0",
"typescript": "^5.1.5",
"undici": "^5.22.1",
"vitest": "^0.32.2"
"@vitest/coverage-v8": "^1.1.0",
"concurrently": "^8.2.2",
"tsup": "^8.0.1",
"typescript": "^5.3.3",
"undici": "^6.2.1",
"vitest": "^1.1.0"
},
"files": [
"dist"
Expand Down
17 changes: 7 additions & 10 deletions lib/src/internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@ export type UnwrapError<E> = [E] extends [never]
? UnwrapError<E>
: UnknownError;

export const _value = Symbol.for("_value");
export const _tag = Symbol.for("_tag");

export const TAGS = {
Some: "Some",
None: "None",
Ok: "Ok",
Err: "Err",
Task: "Task",
};
export const _value = Symbol.for("ftld/_value");
export const _tag = Symbol.for("ftld/_tag");
export const SOME = Symbol.for("fltd/Some");
export const NONE = Symbol.for("fltd/None");
export const OK = Symbol.for("fltd/Ok");
export const ERR = Symbol.for("fltd/Err");
export const TASK = Symbol.for("fltd/Task");
6 changes: 3 additions & 3 deletions lib/src/option.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { _value, _tag, TAGS } from "./internals.js";
import { _value, _tag, SOME, NONE } from "./internals.js";
import type { Result } from "./result.js";
import { UnwrapNoneError, identity, isResult } from "./utils.js";

Expand All @@ -8,7 +8,7 @@ type OptionMatcher<A, B, C> = {
} & {};

export class Some<A> {
readonly [_tag] = TAGS.Some;
readonly [_tag] = SOME;
private readonly [_value]: A;
private constructor(value: A) {
this[_value] = value;
Expand Down Expand Up @@ -73,7 +73,7 @@ export class Some<A> {
}

export class None<A> {
readonly [_tag] = TAGS.None;
readonly [_tag] = NONE;
private constructor() {}

/**
Expand Down
29 changes: 14 additions & 15 deletions lib/src/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,27 +497,26 @@ describe.concurrent("Result", () => {
error: "error 2",
},
});
});
it("should settle a Ok result", () => {
const result = Result.Ok(42);

it("should settle a Ok result", () => {
const result = Result.Ok(42);

const settled = result.settle();
const settled = result.settle();

expect(settled).toEqual({
type: "Ok",
value: 42,
});
expect(settled).toEqual({
type: "Ok",
value: 42,
});
});

it("should settle an Err result", () => {
const result = Result.Err("error");
it("should settle an Err result", () => {
const result = Result.Err("error");

const settled = result.settle();
const settled = result.settle();

expect(settled).toEqual({
type: "Err",
error: "error",
});
expect(settled).toEqual({
type: "Err",
error: "error",
});
});
});
Expand Down
6 changes: 3 additions & 3 deletions lib/src/result.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { _value, _tag, TAGS } from "./internals.js";
import { _value, _tag, OK, ERR } from "./internals.js";
import { UnknownError, identity, isOption } from "./utils.js";
import type { Option } from "./option.js";

Expand All @@ -8,7 +8,7 @@ type ResultMatcher<E, A, B, C> = {
} & {};

export class Ok<E, A> {
readonly [_tag] = TAGS.Ok;
readonly [_tag] = OK;
private readonly [_value]: A;
private constructor(value: A) {
this[_value] = value;
Expand Down Expand Up @@ -119,7 +119,7 @@ export class Ok<E, A> {
}

export class Err<E, A> {
readonly [_tag] = TAGS.Err;
readonly [_tag] = ERR;
private readonly [_value]: E;

private constructor(value: E) {
Expand Down
18 changes: 11 additions & 7 deletions lib/src/task.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,13 @@ describe.concurrent("Task", () => {

it("should correctly construct from an option", async () => {
const value = 42;
const error = new Error("An error occurred");

const option = Option.Some(value);
const task = Task.from(
() => option,
() => error
);
const task = Task.from(() => option);
const result = task.run();
expect(result.isOk()).toBeTruthy();
expect(result.unwrap()).toEqual(value);
expectTypeOf(task).toEqualTypeOf<SyncTask<UnwrapNoneError, number>>();
});

it("should correctly infer return type from all possible values", async () => {
Expand Down Expand Up @@ -1926,11 +1924,17 @@ describe.concurrent("Task", () => {
});

it("should be reusable", async () => {
const task = Task.from(async () => 1);
const task = Task.sleep(100).flatMap(() =>
Task.from(async () => Date.now())
);

const res = task.run();
expect(res).toBeInstanceOf(Promise);
await res;
let x = await res;
let y = await res;
let z = await task.run();
expect(task.run()).toBeInstanceOf(Promise);
expect(x).toEqual(y);
expect(x).not.toEqual(z);
});
});
4 changes: 2 additions & 2 deletions lib/src/task.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Compute, UnwrapError, UnwrapValue } from "./internals.js";
import { isPromise, _tag, TAGS } from "./internals.js";
import { isPromise, _tag, TASK } from "./internals.js";
import {
isOption,
isResult,
Expand Down Expand Up @@ -284,7 +284,7 @@ export type SyncTask<E, A> = {
};

class _Task {
readonly [_tag] = TAGS.Task;
readonly [_tag] = TASK;
private attempts = {
retry: 0,
repeat: 0,
Expand Down
8 changes: 4 additions & 4 deletions lib/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TAGS, _tag } from "./internals.js";
import { ERR, NONE, OK, SOME, TASK, _tag } from "./internals.js";
import type { Option } from "./option.js";
import type { Result } from "./result.js";
import type { Task } from "./task.js";
Expand All @@ -21,7 +21,7 @@ export function isResult<E, A>(value: unknown): value is Result<E, A> {
!!value &&
typeof value === "object" &&
_tag in value &&
(value[_tag] === TAGS.Ok || value[_tag] === TAGS.Err)
(value[_tag] === OK || value[_tag] === ERR)
);
}

Expand All @@ -30,7 +30,7 @@ export function isOption<A>(value: unknown): value is Option<A> {
!!value &&
typeof value === "object" &&
_tag in value &&
(value[_tag] === TAGS.Some || value[_tag] === TAGS.None)
(value[_tag] === SOME || value[_tag] === NONE)
);
}

Expand All @@ -39,7 +39,7 @@ export function isTask<E, A>(value: unknown): value is Task<E, A> {
!!value &&
typeof value === "object" &&
_tag in value &&
value[_tag] === TAGS.Task
value[_tag] === TASK
);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"outDir": "dist/esm",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"module": "NodeNext",
"lib": ["ESNext", "DOM"],
"types": ["vitest/globals"],
"moduleResolution": "NodeNext",
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@vitest/coverage-c8": "^0.32.2",
"vitest": "^0.32.2"
"@changesets/cli": "^2.27.1"
}
}
Loading

0 comments on commit de60db5

Please sign in to comment.