Skip to content

Commit

Permalink
test: add ecosystem test for tupleson (#677)
Browse files Browse the repository at this point in the history
* test: add ecosystem test for tupleson

* docs: add tupleson and improve docs

* docs: add tupleson and improve docs
  • Loading branch information
belgattitude authored Oct 28, 2023
1 parent b697d66 commit 92343d2
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 54 deletions.
5 changes: 5 additions & 0 deletions .changeset/popular-avocados-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@httpx/exception': patch
---

Add tupleson tests and improve docs
12 changes: 12 additions & 0 deletions packages/exception/.size-limit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ module.exports = [
import: "{ fromJson }",
limit: "2000B",
},
{
name: "ESM ({ toJson })",
path: ["dist/serializer/index.mjs"],
import: "{ toJson }",
limit: "950B",
},
{
name: "ESM ({ fromJson, toJson })",
path: ["dist/serializer/index.mjs"],
import: "{ fromJson, toJson }",
limit: "2000B",
},
// ###################################################
// Commonjs full bundle
// ###################################################
Expand Down
183 changes: 130 additions & 53 deletions packages/exception/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,137 @@ yarn add @httpx/exception # via yarn
pnpm add @httpx/exception # via pnpm
```

## Documentation
## Bundle size

**👉 See full documentation on [https://belgattitude.github.io/httpx](https://belgattitude.github.io/httpx). 👈**
This library is best consumed in ESM, individual imports are tracked by a
size-limit action. In most situation the bundle size will be less than 1Kb.
That includes default messages :)

| Scenario | Size (esm -> min/gzip) |
| ------------------------------------------------ | ---------------------- |
| Import only one exception | ~ 400b |
| Import all exceptions or use createHttpException | < 1kb |
| All exceptions + typeguards + serializer | max 1.7kb |

## Usage

Basic usage below, but don't forget to check the
👉 full documentation on [https://belgattitude.github.io/httpx](https://belgattitude.github.io/httpx). 👈.
It includes serialization recipes, http422 with validation issues and more..

### Named

```typescript
import { HttpNotFound, HttpInternalServerError } from '@httpx/exception';

// 👉 1. Simple
const e404 = new HttpNotFound();

-> 🔥 e.statusCode === 404
-> 🔥 e.message inferred to be === "Not found"!

// 👉 2. Alternative custom message !
const e404 = new HttpNotFound("The graal is nowhere to be found");

// 👉 3. Custom params and (optional) context
const e500 = new HttpInternalServerError({
message: "Oups, this is on our side.",
url: "https://api.dev/gateway",
method: "POST",
errorId: 'track-me-in-the-logs',
code: 'custom internal code',
cause: new HttpGatewayTimeout({
code: "This Serverless Function has timed out",
errorId: "cdg1::h99k2-1664884491087-b41a2832f559",
}),
});
```

### Factory

```typescript
import { createHttpException } from '@httpx/exception';

// 👉 1. Simple
const e404 = createHttpException(404);
-> 🔥 e.statusCode === 404
-> 🔥 e.message inferred to be === "Not found"!

// 👉 2. Custom params and (optional) context

const e500 = createHttpException(500, {
message: "Oups, this is on our side.",
url: "https://api.dev/gateway",
method: "POST",
errorId: 'track-me-in-the-logs',
code: 'custom internal code',
cause: new HttpGatewayTimeout({
code: "This Serverless Function has timed out",
errorId: "cdg1::h99k2-1664884491087-b41a2832f559",
})
})
```

## Ecosystem

### Tupleson

Example with [tupleson](https://github.com/trpc/tupleson) serializer.

```typescript
import { createTson } from "tupleson";
import {
createHttpException,
HttpException,
HttpUnprocessableEntity,
} from "@httpx/exception";
import {
fromJson,
type SerializerError,
toJson,
} from "@httpx/exception/serializer";

const httpException: TsonType<HttpException | SerializerError, string> = {
deserialize: (v) => fromJson(v),
key: "HttpException",
serialize: (v) => toJson(v),
test: (v) => v instanceof HttpException,
};

const tson = createTson({
types: [httpException],
});

const obj = {
e422: new HttpUnprocessableEntity({
issues: [
{
message: "Invalid address",
path: ["addresses", 0, "line1"],
code: "empty_string",
},
],
}),
e404: createHttpException(404),
};

const serialized = tson.serialize(obj);
const deserialized = tson.deserialize(serialized);
expect(deserialized).toStrictEqual(obj);
```

## Serializer

Serialization

```typescript
import { fromJson, toJson } from "@httpx/exception/serializer";

const e = new HttpForbidden();

const json = toJson(e);
const deserialized = fromJson(json);
```

## Why ?

Expand Down Expand Up @@ -118,57 +246,6 @@ export const withApiErrorHandler = (params?: Params) => {

> Tip: @httpx/exception is small scoped by nature. The above example isn't to be taken "as is".
## Quick overview

Simple named exceptions:

```typescript
import {
HttpGatewayTimeout,
HttpInternalServerError,
HttpNotFound,
HttpServiceUnavailable,
} from "@httpx/exception";

throw new HttpNotFound(); // message = 'Not found', statusCode = 404

// Custom message
throw new HttpServiceUnavailable("Service temporarily unavailable");

// Custom context
throw new HttpInternalServerError({
message: "Oups, this is on our side.",
url: "https://api.dev/gateway",
code: "EXTERNAL_SERVICE_TIMEOUT",
cause: new HttpGatewayTimeout({
code: "This Serverless Function has timed out",
errorId: "cdg1::h99k2-1664884491087-b41a2832f559",
}),
});
```

By status code

```typescript
import { createHttpException } from "@httpx/exception";

const e404 = createHttpException(404);
const e500 = createHttpException(500, { message: "Server error" });
```

Serialization

```typescript
import { fromJson, toJson } from "@httpx/exception/serializer";

const e = new HttpForbidden();

const json = toJson(e);
const deserialized = fromJson(json);
```

More in the docs: [https://belgattitude.github.io/httpx](https://belgattitude.github.io/httpx)

## Support

Don't hesitate and open [an issue](https://github.com/belgattitude/httpx/issues).
Expand Down
2 changes: 1 addition & 1 deletion packages/exception/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"name": "Vanvelthem Sébastien",
"url": "https://github.com/belgattitude"
},
"homepage": "https://github.com/belgattitude/httpx",
"homepage": "https://belgattitude.github.io/httpx",
"repository": {
"type": "git",
"url": "https://github.com/belgattitude/httpx",
Expand Down
40 changes: 40 additions & 0 deletions packages/exception/test/specs/ecosystem.tupleson.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { TsonType } from 'tupleson';
import { createTson } from 'tupleson';
import {
createHttpException,
HttpException,
HttpUnprocessableEntity,
} from '../../src';
import { fromJson, type SerializerError, toJson } from '../../src/serializer';

describe('Ecosystem:tupleson', () => {
const httpException: TsonType<HttpException | SerializerError, string> = {
deserialize: (v) => fromJson(v),
key: 'HttpException',
serialize: (v) => toJson(v),
test: (v) => v instanceof HttpException,
};

const tson = createTson({
types: [httpException],
});

const obj = {
e422: new HttpUnprocessableEntity({
issues: [
{
message: 'Invalid address',
path: ['addresses', 0, 'line1'],
code: 'empty_string',
},
],
}),
e404: createHttpException(404),
};

it('should serialize/deserialize', () => {
const serialized = tson.serialize(obj);
const deserialized = tson.deserialize(serialized);
expect(deserialized).toStrictEqual(obj);
});
});

0 comments on commit 92343d2

Please sign in to comment.