Skip to content

Commit

Permalink
👍 First impl
Browse files Browse the repository at this point in the history
  • Loading branch information
lambdalisue committed Jan 2, 2024
1 parent 35f5fd8 commit 8fd08b0
Show file tree
Hide file tree
Showing 18 changed files with 634 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/npm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: npm

env:
DENO_VERSION: 1.x
NODE_VERSION: 16.x

on:
push:
tags:
- "v*"

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: denoland/setup-deno@v1
with:
deno-version: ${{ env.DENO_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: "https://registry.npmjs.org"
- name: Build
run: deno task build-npm
- name: Publish
run: |
cd npm
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
55 changes: 55 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Test

env:
DENO_VERSION: 1.x
NODE_VERSION: 16.x

on:
schedule:
- cron: "0 7 * * 0"
push:
branches:
- main
pull_request:

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with:
deno-version: ${{ env.DENO_VERSION }}
- name: Format
run: |
deno fmt --check
- name: Lint
run: deno lint
- name: Type check
run: deno task check

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with:
deno-version: ${{ env.DENO_VERSION }}
- name: Test
run: |
deno task test
timeout-minutes: 5

build-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with:
deno-version: ${{ env.DENO_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: "https://registry.npmjs.org"
- name: Build
run: deno task build-npm
49 changes: 49 additions & 0 deletions .github/workflows/update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: update

on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:

jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with:
deno-version: 1.x
- name: Configure Git
run: |
git config user.name github-actions[bot]
git config user.email github-actions[bot]@users.noreply.github.com
- name: Update dependencies and commit changes
run: deno task -q upgrade:commit --summary ../title.txt --report ../body.md
- name: Check result
id: result
uses: andstor/file-existence-action@v2
with:
files: ../title.txt, ../body.md
- name: Read title.txt
id: title
if: steps.result.outputs.files_exists == 'true'
uses: juliangruber/read-file-action@v1
with:
path: ../title.txt
- name: Read body.md
id: body
if: steps.result.outputs.files_exists == 'true'
uses: juliangruber/read-file-action@v1
with:
path: ../body.md
- name: Create a pull request
if: steps.result.outputs.files_exists == 'true'
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.PA_TOKEN }}
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
branch: automation/update-dependencies
title: ${{ steps.title.outputs.content }}
body: ${{ steps.body.outputs.content }}
labels: automation
delete-branch: true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/npm
deno.lock
.coverage
25 changes: 25 additions & 0 deletions .gitmessage
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@


# Guide (v1.0)
#
# 👍 :+1: Apply changes.
#
# 🌿 :herb: Add or update things for tests.
# ☕ :coffee: Add or update things for developments.
# 📦 :package: Add or update dependencies.
# 📝 :memo: Add or update documentations.
#
# 🐛 :bug: Bugfixes.
# 💋 :kiss: Critical hotfixes.
# 🚿 :shower: Remove features, codes, or files.
#
# 🚀 :rocket: Improve performance.
# 💪 :muscle: Refactor codes.
# 💥 :boom: Breaking changes.
# 💩 :poop: Bad codes needs to be improved.
#
# How to use:
# git config commit.template .gitmessage
#
# Reference:
# https://github.com/lambdalisue/emojiprefix
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright 2023 Alisue <lambdalisue@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# errorutil

[![npm](http://img.shields.io/badge/available%20on-npm-lightgrey.svg?logo=npm&logoColor=white)](https://www.npmjs.com/package/errorutil)
[![deno land](http://img.shields.io/badge/available%20on-deno.land/x-lightgrey.svg?logo=deno)](https://deno.land/x/errorutil)
[![deno doc](https://doc.deno.land/badge.svg)](https://doc.deno.land/https/deno.land/x/errorutil/mod.ts)
[![Test](https://github.com/lambdalisue/deno-errorutil/workflows/Test/badge.svg)](https://github.com/lambdalisue/deno-errorutil/actions?query=workflow%3ATest)
[![npm version](https://badge.fury.io/js/errorutil.svg)](https://badge.fury.io/js/errorutil)

A utility pack for handling error.

[deno]: https://deno.land/

## License

The code follows MIT license written in [LICENSE](./LICENSE). Contributors need
to agree that any modifications sent in this repository follow the license.
11 changes: 11 additions & 0 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"lock": false,
"tasks": {
"build-npm": "deno run -A scripts/build_npm.ts $(git describe --tags --always --dirty)",
"test": "deno test -A --parallel --shuffle --doc --coverage=.coverage",
"check": "deno check ./**/*.ts",
"coverage": "deno coverage .coverage",
"upgrade": "deno run -q -A https://deno.land/x/molt@0.14.2/cli.ts ./**/*.ts",
"upgrade:commit": "deno task -q upgrade --commit --prefix :package: --pre-commit=fmt"
}
}
39 changes: 39 additions & 0 deletions error_object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
is,
PredicateType,
} from "https://deno.land/x/unknownutil@v3.11.0/mod.ts";

export const isErrorObject = is.ObjectOf({
proto: is.String,
name: is.String,
message: is.String,
stack: is.OptionalOf(is.String),
attributes: is.Record,
});

export type ErrorObject = PredicateType<typeof isErrorObject>;

/**
* Convert an error to an error object
*/
export function toErrorObject(err: Error): ErrorObject {
const { constructor, name, message, stack = undefined, ...rest } = err;
return {
proto: constructor.name,
name,
message,
stack,
attributes: rest,
};
}

/**
* Convert an error object to an error
*/
export function fromErrorObject(obj: ErrorObject): Error {
return Object.assign(new Error(obj.message), {
name: obj.name,
stack: obj.stack,
...obj.attributes,
});
}
71 changes: 71 additions & 0 deletions error_object_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {
assertEquals,
assertInstanceOf,
} from "https://deno.land/std@0.210.0/assert/mod.ts";
import { fromErrorObject, toErrorObject } from "./error_object.ts";

class CustomError extends Error {
foo: string;
bar: number;
constructor(message: string, foo: string, bar: number) {
super(message);
this.name = "ThisIsCustomError";
this.foo = foo;
this.bar = bar;
}
}

Deno.test("toErrorObject", async (t) => {
await t.step("Error", () => {
const err = new Error("error");
err.stack = "stack...";
const obj = toErrorObject(err);
assertEquals(obj, {
proto: "Error",
name: "Error",
message: "error",
stack: "stack...",
attributes: {},
});
});

await t.step("CustomError", () => {
const err = new CustomError("error", "foo", 10);
err.stack = "stack...";
const obj = toErrorObject(err);
assertEquals(obj, {
proto: "CustomError",
name: "ThisIsCustomError",
message: "error",
stack: "stack...",
attributes: {
foo: "foo",
bar: 10,
},
});
});
});

Deno.test("fromErrorObject", async (t) => {
await t.step("Error", () => {
const obj = toErrorObject(new Error("error"));
obj.stack = "stack...";
const err = fromErrorObject(obj);
assertInstanceOf(err, Error);
assertEquals(err.name, "Error");
assertEquals(err.message, "error");
assertEquals(err.stack, "stack...");
});

await t.step("CustomError", () => {
const obj = toErrorObject(new CustomError("error", "foo", 10));
obj.stack = "stack...";
const err = fromErrorObject(obj);
assertInstanceOf(err, Error);
assertEquals(err.name, "ThisIsCustomError");
assertEquals(err.message, "error");
assertEquals(err.stack, "stack...");
assertEquals((err as CustomError).foo, "foo");
assertEquals((err as CustomError).bar, 10);
});
});
5 changes: 5 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./error_object.ts";
export * from "./raise.ts";
export * from "./try_or.ts";
export * from "./unimplemented.ts";
export * from "./unreachable.ts";
14 changes: 14 additions & 0 deletions raise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Throw an error.
*
* This is function thus can be used as an expression.
*
* ```typescript
* import { raise } from "./raise.ts";
*
* const fn = () => raise(new Error("fail"));
* ```
*/
export function raise(err: unknown): never {
throw err;
}
6 changes: 6 additions & 0 deletions raise_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { assertThrows } from "https://deno.land/std@0.210.0/assert/mod.ts";
import { raise } from "./raise.ts";

Deno.test("raise", () => {
assertThrows(() => raise(new Error("error")), Error, "error");
});
38 changes: 38 additions & 0 deletions scripts/build_npm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { build, emptyDir } from "https://deno.land/x/dnt@0.39.0/mod.ts";

const name = "errorutil";
const version = Deno.args[0];
if (!version) {
throw new Error("No version argument is specified");
}
console.log("*".repeat(80));
console.log(`${name} ${version}`);
console.log("*".repeat(80));

await emptyDir("./npm");

await build({
typeCheck: false,
// XXX:
// snapshot tests doesn't work with dnt so we disable tests for now
// https://github.com/denoland/dnt/issues/254
test: false,
entryPoints: ["./mod.ts"],
outDir: "./npm",
shims: {
// see JS docs for overview and more options
deno: "dev",
},
package: {
// package.json properties
name,
version,
author: "Alisue <lambdalisue@gmail.com>",
license: "MIT",
repository: "https://github.com/lambdalisue/deno-errorutil",
},
});

// post build steps
Deno.copyFileSync("LICENSE", "npm/LICENSE");
Deno.copyFileSync("README.md", "npm/README.md");

0 comments on commit 8fd08b0

Please sign in to comment.