Skip to content

Commit 5479844

Browse files
committed
feat: init
1 parent cfa5272 commit 5479844

File tree

11 files changed

+391
-0
lines changed

11 files changed

+391
-0
lines changed

.github/workflows/release.yaml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
bump:
7+
description: "Bump Type"
8+
required: true
9+
type: choice
10+
options:
11+
- patch
12+
- minor
13+
- major
14+
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
publish:
21+
permissions:
22+
contents: write
23+
id-token: write
24+
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 15
27+
28+
steps:
29+
- name: Checkout Source Code
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Setup Bun
35+
uses: oven-sh/setup-bun@v1
36+
with:
37+
bun-version: latest
38+
39+
- name: Install Dependencies
40+
run: bun install --frozen-lockfile
41+
42+
- name: Set Git User
43+
run: |
44+
git config user.name "${GITHUB_ACTOR}"
45+
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
46+
47+
- name: Set NPM Config
48+
run: npm config set //registry.npmjs.org/:_authToken "${NPM_TOKEN}"
49+
env:
50+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
51+
52+
- name: Bump version
53+
run: bun run bump ${{ github.event.inputs.bump }}
54+
55+
- name: Build
56+
run: bun run build
57+
58+
- name: Publish
59+
run: npm publish --provenance --access public
60+
61+
- name: Commit
62+
run: git push --follow-tags

.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Dependency directories
2+
node_modules/
3+
4+
# Environment files
5+
.env
6+
.env.development.local
7+
.env.test.local
8+
.env.production.local
9+
.env.local
10+
11+
# Output files
12+
dist
13+
out
14+

README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# @microlib/try
2+
3+
Easily convert promises or lazy synchronous functions to result
4+
5+
### 🚀 Installation
6+
7+
```bash
8+
npm install @microlib/try
9+
```
10+
11+
```bash
12+
bun add @microlib/try
13+
```
14+
15+
### 📖 Usage
16+
17+
```ts
18+
import { Try } from "@microlib/try";
19+
20+
function myTaskSync() {
21+
if (Math.random() > 0.5) {
22+
throw new Error("Something went wrong");
23+
} else {
24+
return "Success";
25+
}
26+
}
27+
28+
function myTaskAsync() {
29+
return new Promise((resolve, reject) => {
30+
if (Math.random() > 0.5) {
31+
reject(new Error("Something went wrong"));
32+
} else {
33+
resolve("Success");
34+
}
35+
});
36+
}
37+
38+
const resultSync = Try(myTaskSync);
39+
const resultAsync = await Try(myTaskAsync);
40+
41+
console.log(resultSync);
42+
console.log(resultAsync);
43+
44+
/*
45+
46+
Output can be any of these:
47+
{ ok: true, value: "Success" }
48+
OR
49+
{ ok: false, error: Error: Something went wrong }
50+
51+
*/
52+
```
53+
54+
## 🍀 Show your Support
55+
56+
Give a ⭐️ if this project helped you!

bun.lockb

94.6 KB
Binary file not shown.

package.json

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"name": "@microlib/try",
3+
"version": "0.0.0",
4+
"description": "Easily convert promise to result",
5+
"keywords": [
6+
"promise",
7+
"try",
8+
"result"
9+
],
10+
"type": "module",
11+
"module": "src/index.ts",
12+
"main": "./dist/index.cjs",
13+
"types": "./dist/index.d.ts",
14+
"files": [
15+
"dist"
16+
],
17+
"scripts": {
18+
"build": "unbuild",
19+
"bump": "bun scripts/bump.ts",
20+
"release": "bun scripts/release.ts"
21+
},
22+
"devDependencies": {
23+
"@types/bun": "^1.1.11",
24+
"unbuild": "^2.0.0"
25+
},
26+
"peerDependencies": {
27+
"typescript": "^5.6.3"
28+
},
29+
"author": {
30+
"name": "tanishqmanuja",
31+
"url": "https://github.com/tanishqmanuja",
32+
"email": "[email protected]"
33+
},
34+
"repository": {
35+
"type": "git",
36+
"url": "git+https://github.com/microlib-js/try.git"
37+
},
38+
"exports": {
39+
".": {
40+
"require": "./dist/index.cjs",
41+
"import": "./dist/index.mjs",
42+
"types": "./dist/index.d.ts"
43+
},
44+
"./result": {
45+
"require": "./dist/result.cjs",
46+
"import": "./dist/result.mjs",
47+
"types": "./dist/result.d.ts"
48+
},
49+
"./utils": {
50+
"require": "./dist/utils.cjs",
51+
"import": "./dist/utils.mjs",
52+
"types": "./dist/utils.d.ts"
53+
},
54+
"./package.json": "./package.json"
55+
}
56+
}

scripts/bump.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { $ } from "bun";
2+
3+
const bump = process.argv[2];
4+
5+
if (!bump) {
6+
console.error("Missing bump");
7+
process.exit(1);
8+
}
9+
10+
if (!["patch", "minor", "major"].includes(bump)) {
11+
console.error("Invalid bump");
12+
process.exit(1);
13+
}
14+
15+
await $`npm version ${bump} -m "chore: bump version"`;

scripts/release.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { $ } from "bun";
2+
3+
import { version } from "../package.json";
4+
5+
const WORKFLOW_ID = "release.yaml";
6+
7+
const bump = process.argv[2] ?? "patch";
8+
9+
if (!bump) {
10+
console.error("Missing bump");
11+
process.exit(1);
12+
}
13+
14+
if (!["patch", "minor", "major"].includes(bump)) {
15+
console.error("Invalid bump");
16+
process.exit(1);
17+
}
18+
19+
const { owner, repo } = await $`git config --get remote.origin.url`
20+
.quiet()
21+
.text()
22+
.then((url) => {
23+
const [owner, repo] = url.split("/").slice(-2);
24+
if (!owner || !repo) {
25+
throw new Error("Cannot find owner or repo");
26+
}
27+
return {
28+
owner,
29+
repo: repo.replace(".git", "").trim(),
30+
};
31+
});
32+
33+
console.log(`Current Version: ${version}`);
34+
console.log(`Bump Type: ${bump}`);
35+
console.log(`Repo: ${owner}/${repo}`);
36+
37+
console.log("\nDispatching workflow...");
38+
39+
await $`gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
40+
/repos/${owner}/${repo}/actions/workflows/${WORKFLOW_ID}/dispatches -f "ref=main" -f "inputs[bump]=${bump}"`
41+
.quiet()
42+
.then(() => {
43+
console.log("Dispatched!");
44+
process.exit(0);
45+
})
46+
.catch((e) => {
47+
console.log(e);
48+
process.exit(1);
49+
});

src/index.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
isResultError,
3+
isResultOk,
4+
resultError,
5+
resultOf,
6+
resultOk,
7+
type Result,
8+
} from "./result";
9+
import { isError, isPromise } from "./utils";
10+
11+
export function trySync<T>(fn: () => T): Result<T> {
12+
try {
13+
const value = fn();
14+
return resultOk(value);
15+
} catch (e) {
16+
const error = isError(e) ? e : new Error(String(e));
17+
return resultError(error);
18+
}
19+
}
20+
21+
type MaybePromise<T> = T | Promise<T>;
22+
export function tryAsync<T>(fn: () => MaybePromise<T>): Promise<Result<T>> {
23+
try {
24+
const value = fn();
25+
if (isPromise(value)) {
26+
return value
27+
.then((v) => resultOk(v))
28+
.catch((e) => resultError(isError(e) ? e : new Error(String(e))));
29+
}
30+
31+
return Promise.resolve(resultOk(value));
32+
} catch (e) {
33+
const error = isError(e) ? e : new Error(String(e));
34+
return Promise.reject(resultError(error));
35+
}
36+
}
37+
38+
export const Try = Object.assign(resultOf, {
39+
sync: trySync,
40+
async: tryAsync,
41+
isOk: isResultOk,
42+
isError: isResultError,
43+
});

src/result.ts

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { isPromise, isError } from "./utils";
2+
3+
export type ResultOk<T> = {
4+
ok: true;
5+
value: T;
6+
};
7+
8+
export type ResultError<E extends Error = Error> = {
9+
ok: false;
10+
error: E;
11+
};
12+
13+
export type Result<T, E extends Error = Error> = ResultOk<T> | ResultError<E>;
14+
15+
export function resultOk<T>(value: T): ResultOk<T> {
16+
return {
17+
ok: true,
18+
value,
19+
};
20+
}
21+
22+
export function resultError<E extends Error = Error>(error: E): ResultError<E> {
23+
return {
24+
ok: false,
25+
error,
26+
};
27+
}
28+
29+
export function isResultOk<T>(result: Result<T>): result is ResultOk<T> {
30+
return result.ok;
31+
}
32+
33+
export function isResultError<E extends Error = Error>(
34+
result: Result<unknown, E>
35+
): result is ResultError<E> {
36+
return !result.ok;
37+
}
38+
39+
export function resultOf<T>(fn: () => Promise<T>): Promise<Result<T>>;
40+
export function resultOf<T>(fn: () => T): Result<T>;
41+
export function resultOf<T>(
42+
fn: () => Promise<T> | T
43+
): Result<T> | Promise<Result<T>> {
44+
try {
45+
const value = fn();
46+
if (isPromise(value)) {
47+
return value
48+
.then((v) => resultOk(v))
49+
.catch((e) => resultError(isError(e) ? e : new Error(String(e))));
50+
}
51+
52+
return resultOk(value);
53+
} catch (e) {
54+
const error = isError(e) ? e : new Error(String(e));
55+
return resultError(error);
56+
}
57+
}

src/utils.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const toStr = Function.bind.call(
2+
Function.call as typeof Function.prototype.toString,
3+
Object.prototype.toString
4+
);
5+
6+
export function isError(err: unknown): err is Error {
7+
return !!err && toStr(err) === "[object Error]";
8+
}
9+
10+
export function isPromise(value: unknown): value is Promise<unknown> {
11+
return !!value && toStr(value) === "[object Promise]";
12+
}

0 commit comments

Comments
 (0)