@antelopejs/interface-api-util 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -11
- package/dist/antelope.test.js +2 -1
- package/dist/antelope.test.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/rate-limit.js +1 -1
- package/dist/rate-limit.js.map +1 -1
- package/dist/tests/rate-limit.test.js +1 -1
- package/dist/tests/rate-limit.test.js.map +1 -1
- package/docs/1.introduction.md +30 -22
- package/docs/tsconfig.json +12 -0
- package/package.json +38 -24
- package/skills/api-util-interface/SKILL.md +26 -5
package/README.md
CHANGED
|
@@ -1,26 +1,93 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @antelopejs/interface-api-util
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<a href="https://www.npmjs.com/package/@antelopejs/interface-api-util"><img src="https://img.shields.io/npm/v/@antelopejs/interface-api-util?style=for-the-badge&labelColor=000000&color=000000"
|
|
5
|
-
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/
|
|
6
|
-
<a href="https://discord.gg/sjK28QHrA7"><img src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"
|
|
7
|
-
<a href="
|
|
4
|
+
<a href="https://www.npmjs.com/package/@antelopejs/interface-api-util"><img alt="npm" src="https://img.shields.io/npm/v/@antelopejs/interface-api-util?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
5
|
+
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/@antelopejs/interface-api-util?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
6
|
+
<a href="https://discord.gg/sjK28QHrA7"><img alt="Discord" src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"></a>
|
|
7
|
+
<a href="https://interfaces.antelopejs.com/docs/api-util"><img alt="Docs" src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000"></a>
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Request validation and rate limiting helpers for handlers written against [`@antelopejs/interface-api`](https://github.com/AntelopeJS/interface-api). Every failure becomes an `HTTPResult` error response.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## What it offers
|
|
13
|
+
|
|
14
|
+
- `assert(condition, code, message)` throws an `HTTPResult` when the condition is falsy and narrows its type when it holds.
|
|
15
|
+
- `assertValidation(body, validator)` runs a synchronous validator, such as a Zod `parse`, and turns a thrown error into a `400` response.
|
|
16
|
+
- `@RateLimit(limit, windowMs)` caps calls to a handler per client in a fixed window and answers `429` beyond it.
|
|
17
|
+
|
|
18
|
+
## Implementations
|
|
19
|
+
|
|
20
|
+
The helpers run in your module. They need the API interface served by a module:
|
|
21
|
+
|
|
22
|
+
| Module | Notes |
|
|
23
|
+
| ------------------------------------------------------ | --------------------------------------------------------------------------- |
|
|
24
|
+
| [`@antelopejs/api`](https://github.com/AntelopeJS/api) | Implements `@antelopejs/interface-api` and `@antelopejs/interface-api-util` |
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
Add the package to the module that declares routes:
|
|
13
29
|
|
|
14
30
|
```bash
|
|
15
|
-
|
|
31
|
+
pnpm add @antelopejs/interface-api-util
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then add an implementation of the API interface to the project:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ajs project modules add @antelopejs/api
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import {
|
|
44
|
+
Controller,
|
|
45
|
+
Get,
|
|
46
|
+
HTTPResult,
|
|
47
|
+
Parameter,
|
|
48
|
+
} from "@antelopejs/interface-api";
|
|
49
|
+
import { RateLimit, assert } from "@antelopejs/interface-api-util";
|
|
50
|
+
|
|
51
|
+
const BOOKS = new Map([["1", { title: "The Glass Meridian" }]]);
|
|
52
|
+
|
|
53
|
+
export class BookController extends Controller("/books") {
|
|
54
|
+
@Get(":id")
|
|
55
|
+
@RateLimit(100, 60_000)
|
|
56
|
+
async getBook(@Parameter("id") id: string) {
|
|
57
|
+
const book = BOOKS.get(id);
|
|
58
|
+
assert(book, 404, "Book not found");
|
|
59
|
+
return new HTTPResult(200, book);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
16
62
|
```
|
|
17
63
|
|
|
64
|
+
Place `@RateLimit` directly below the route decorator. Placed above it, `@RateLimit` throws when the class is defined.
|
|
65
|
+
|
|
18
66
|
## Documentation
|
|
19
67
|
|
|
20
|
-
|
|
68
|
+
- [Assertions, validation and rate limiting](./docs/1.introduction.md)
|
|
69
|
+
|
|
70
|
+
## Compatibility
|
|
71
|
+
|
|
72
|
+
Use with `@antelopejs/core` 1.x and the following peer dependencies:
|
|
21
73
|
|
|
22
|
-
-
|
|
74
|
+
<!-- docs-compat: ./package.json#peerDependencies -->
|
|
75
|
+
|
|
76
|
+
| Package | Range |
|
|
77
|
+
| ---------------------------- | ----------------- |
|
|
78
|
+
| `@antelopejs/interface-api` | `>=0.0.15 <1.0.0` |
|
|
79
|
+
| `@antelopejs/interface-core` | `>=0.2.4 <1.0.0` |
|
|
80
|
+
|
|
81
|
+
## Contributing
|
|
82
|
+
|
|
83
|
+
Read [CONTRIBUTING.md](./CONTRIBUTING.md) before you open a pull request. The local checks are:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pnpm install
|
|
87
|
+
pnpm lint
|
|
88
|
+
pnpm test
|
|
89
|
+
```
|
|
23
90
|
|
|
24
91
|
## License
|
|
25
92
|
|
|
26
|
-
|
|
93
|
+
[Apache-2.0](./LICENSE)
|
package/dist/antelope.test.js
CHANGED
|
@@ -9,10 +9,11 @@ exports.default = (0, config_1.defineConfig)({
|
|
|
9
9
|
source: {
|
|
10
10
|
type: "package",
|
|
11
11
|
package: "@antelopejs/api",
|
|
12
|
-
version: "1.
|
|
12
|
+
version: "1.3.0",
|
|
13
13
|
},
|
|
14
14
|
config: {
|
|
15
15
|
servers: [{ protocol: "http", host: "127.0.0.1", port: 5010 }],
|
|
16
|
+
publicBaseUrl: "http://127.0.0.1:5010",
|
|
16
17
|
},
|
|
17
18
|
},
|
|
18
19
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"antelope.test.js","sourceRoot":"","sources":["../src/antelope.test.ts"],"names":[],"mappings":";;AAAA,8DAAiE;AAEjE,kBAAe,IAAA,qBAAY,EAAC;IAC1B,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,iBAAiB;IAC9B,OAAO,EAAE;QACP,GAAG,EAAE;YACH,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,OAAO;aACjB;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"antelope.test.js","sourceRoot":"","sources":["../src/antelope.test.ts"],"names":[],"mappings":";;AAAA,8DAAiE;AAEjE,kBAAe,IAAA,qBAAY,EAAC;IAC1B,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,iBAAiB;IAC9B,OAAO,EAAE;QACP,GAAG,EAAE;YACH,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,OAAO;aACjB;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;gBAC9D,aAAa,EAAE,uBAAuB;aACvC;SACF;KACF;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,YAAY;KACrB;CACF,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -23,8 +23,9 @@ export * from "./rate-limit";
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function assert<T>(condition: T, code: number, message: string): asserts condition;
|
|
25
25
|
/**
|
|
26
|
-
* Executes
|
|
26
|
+
* Executes a synchronous validator on a body, converting thrown errors to HTTPResult.
|
|
27
27
|
* The validator should return a validated object on success and throw on failure.
|
|
28
|
+
* Promises are returned unchanged; asynchronous rejections are not converted.
|
|
28
29
|
*
|
|
29
30
|
* The error thrown by the validator may be altered by passing an error handler.
|
|
30
31
|
* The result of this error handler will be passed directly as the body of the HTTPResult.
|
package/dist/index.js
CHANGED
|
@@ -46,8 +46,9 @@ function assert(condition, code, message) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
* Executes
|
|
49
|
+
* Executes a synchronous validator on a body, converting thrown errors to HTTPResult.
|
|
50
50
|
* The validator should return a validated object on success and throw on failure.
|
|
51
|
+
* Promises are returned unchanged; asynchronous rejections are not converted.
|
|
51
52
|
*
|
|
52
53
|
* The error thrown by the validator may be altered by passing an error handler.
|
|
53
54
|
* The result of this error handler will be passed directly as the body of the HTTPResult.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AA0BA,wBAQC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AA0BA,wBAQC;AA2BD,4CAYC;AAzED,6DAAuD;AAEvD,+CAA6B;AAE7B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,MAAM,CACpB,SAAY,EACZ,IAAY,EACZ,OAAe;IAEf,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,0BAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,gBAAgB,CAC9B,IAAa,EACb,SAA+B,EAC/B,SAAqC,EACrC,IAAI,GAAG,GAAG;IAEV,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,0BAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
|
package/dist/rate-limit.js
CHANGED
|
@@ -4,9 +4,9 @@ exports.RateLimit = void 0;
|
|
|
4
4
|
exports.hitWindow = hitWindow;
|
|
5
5
|
exports.pruneExpired = pruneExpired;
|
|
6
6
|
exports.resolveKey = resolveKey;
|
|
7
|
-
const interface_api_1 = require("@antelopejs/interface-api");
|
|
8
7
|
const interface_core_1 = require("@antelopejs/interface-core");
|
|
9
8
|
const decorators_1 = require("@antelopejs/interface-core/decorators");
|
|
9
|
+
const interface_api_1 = require("@antelopejs/interface-api");
|
|
10
10
|
const TOO_MANY_REQUESTS = 429;
|
|
11
11
|
const DEFAULT_MESSAGE = "Too many requests";
|
|
12
12
|
const UNKNOWN_KEY = "unknown";
|
package/dist/rate-limit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":";;;AA6DA,8BAkBC;AAQD,oCAUC;AAQD,gCASC;AAlHD
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
16
|
-
const interface_api_1 = require("@antelopejs/interface-api");
|
|
17
16
|
const interface_core_1 = require("@antelopejs/interface-core");
|
|
17
|
+
const interface_api_1 = require("@antelopejs/interface-api");
|
|
18
18
|
const rate_limit_1 = require("../rate-limit");
|
|
19
19
|
const TOO_MANY_REQUESTS = 429;
|
|
20
20
|
const LIMIT = 2;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.test.js","sourceRoot":"","sources":["../../src/tests/rate-limit.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,8DAAqC;AACrC
|
|
1
|
+
{"version":3,"file":"rate-limit.test.js","sourceRoot":"","sources":["../../src/tests/rate-limit.test.ts"],"names":[],"mappings":"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"}
|
package/docs/1.introduction.md
CHANGED
|
@@ -17,14 +17,18 @@ npm install @antelopejs/interface-api-util
|
|
|
17
17
|
The `assert` function checks whether a condition is truthy. If the condition is falsy, it throws an `HTTPResult` with the specified HTTP status code and error message.
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
|
-
function assert<T>(
|
|
20
|
+
function assert<T>(
|
|
21
|
+
condition: T,
|
|
22
|
+
code: number,
|
|
23
|
+
message: string,
|
|
24
|
+
): asserts condition;
|
|
21
25
|
```
|
|
22
26
|
|
|
23
|
-
| Parameter | Type | Description
|
|
24
|
-
| ----------- | -------- |
|
|
25
|
-
| `condition` | `T` | The value to check (falsy values trigger the error)
|
|
26
|
-
| `code` | `number` | HTTP status code for the error response
|
|
27
|
-
| `message` | `string` | Error message included in the response body
|
|
27
|
+
| Parameter | Type | Description |
|
|
28
|
+
| ----------- | -------- | --------------------------------------------------- |
|
|
29
|
+
| `condition` | `T` | The value to check (falsy values trigger the error) |
|
|
30
|
+
| `code` | `number` | HTTP status code for the error response |
|
|
31
|
+
| `message` | `string` | Error message included in the response body |
|
|
28
32
|
|
|
29
33
|
The function uses TypeScript's `asserts` keyword, so the compiler narrows the type of `condition` to truthy after the call.
|
|
30
34
|
|
|
@@ -52,7 +56,11 @@ import { HTTPResult } from "@antelopejs/interface-api";
|
|
|
52
56
|
async function deletePost(postId: string, currentUserId: string) {
|
|
53
57
|
const post = await findPost(postId);
|
|
54
58
|
assert(post, 404, "Post not found");
|
|
55
|
-
assert(
|
|
59
|
+
assert(
|
|
60
|
+
post.authorId === currentUserId,
|
|
61
|
+
403,
|
|
62
|
+
"Not authorized to delete this post",
|
|
63
|
+
);
|
|
56
64
|
|
|
57
65
|
await removePost(postId);
|
|
58
66
|
return new HTTPResult(200, { deleted: true });
|
|
@@ -61,7 +69,7 @@ async function deletePost(postId: string, currentUserId: string) {
|
|
|
61
69
|
|
|
62
70
|
## `assertValidation`
|
|
63
71
|
|
|
64
|
-
The `assertValidation` function runs a validator on an input value. If the validator throws, `assertValidation` catches the error and throws an `HTTPResult` instead.
|
|
72
|
+
The `assertValidation` function runs a synchronous validator on an input value. If the validator throws, `assertValidation` catches the error and throws an `HTTPResult` instead. It does not await promises or convert asynchronous rejections; use a synchronous validator such as Zod's `parse`, not `parseAsync`.
|
|
65
73
|
|
|
66
74
|
```typescript
|
|
67
75
|
function assertValidation<T>(
|
|
@@ -72,12 +80,12 @@ function assertValidation<T>(
|
|
|
72
80
|
): T;
|
|
73
81
|
```
|
|
74
82
|
|
|
75
|
-
| Parameter | Type
|
|
76
|
-
| ----------- |
|
|
77
|
-
| `body` | `unknown`
|
|
78
|
-
| `validator` | `(body: unknown) => T`
|
|
79
|
-
| `errorFunc` | `(err: unknown) => unknown`
|
|
80
|
-
| `code` | `number`
|
|
83
|
+
| Parameter | Type | Default | Description |
|
|
84
|
+
| ----------- | --------------------------- | ------- | ------------------------------------------------------- |
|
|
85
|
+
| `body` | `unknown` | | The input value to validate |
|
|
86
|
+
| `validator` | `(body: unknown) => T` | | A function that returns the validated value or throws |
|
|
87
|
+
| `errorFunc` | `(err: unknown) => unknown` | | Optional error transformer for customizing the response |
|
|
88
|
+
| `code` | `number` | `400` | HTTP status code for the error response |
|
|
81
89
|
|
|
82
90
|
The function returns the validated value on success. On failure, it throws an `HTTPResult` whose body is either the result of `errorFunc` or the stringified error.
|
|
83
91
|
|
|
@@ -116,7 +124,7 @@ function validateAge(requestBody: unknown) {
|
|
|
116
124
|
schema.parse,
|
|
117
125
|
(err) => {
|
|
118
126
|
if (err instanceof z.ZodError) {
|
|
119
|
-
return { errors: err.
|
|
127
|
+
return { errors: err.issues.map((e) => e.message) };
|
|
120
128
|
}
|
|
121
129
|
return { errors: [String(err)] };
|
|
122
130
|
},
|
|
@@ -137,11 +145,11 @@ function RateLimit(
|
|
|
137
145
|
): MethodDecorator;
|
|
138
146
|
```
|
|
139
147
|
|
|
140
|
-
| Parameter | Type | Description
|
|
141
|
-
| ---------- | ------------------ |
|
|
142
|
-
| `limit` | `number` | Maximum number of requests allowed per window
|
|
143
|
-
| `windowMs` | `number` | Window duration in milliseconds
|
|
144
|
-
| `options` | `RateLimitOptions` | Optional custom key function and `429` response body
|
|
148
|
+
| Parameter | Type | Description |
|
|
149
|
+
| ---------- | ------------------ | ---------------------------------------------------- |
|
|
150
|
+
| `limit` | `number` | Maximum number of requests allowed per window |
|
|
151
|
+
| `windowMs` | `number` | Window duration in milliseconds |
|
|
152
|
+
| `options` | `RateLimitOptions` | Optional custom key function and `429` response body |
|
|
145
153
|
|
|
146
154
|
```typescript
|
|
147
155
|
interface RateLimitOptions {
|
|
@@ -171,12 +179,12 @@ class UsersController extends Controller("users") {
|
|
|
171
179
|
|
|
172
180
|
### Limit by a custom key
|
|
173
181
|
|
|
174
|
-
```
|
|
182
|
+
```ts docs-check
|
|
175
183
|
import { RateLimit } from "@antelopejs/interface-api-util";
|
|
176
184
|
import { Controller, Post, HTTPResult } from "@antelopejs/interface-api";
|
|
177
185
|
|
|
178
186
|
class AuthController extends Controller("auth") {
|
|
179
|
-
@Post("login")
|
|
187
|
+
@Post(":tenant/login")
|
|
180
188
|
@RateLimit(5, 60_000, {
|
|
181
189
|
key: (ctx) => ctx.routeParameters.tenant,
|
|
182
190
|
message: "Too many login attempts, slow down",
|
package/package.json
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-api-util",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "AntelopeJS
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "AntelopeJS helpers for API handlers: request assertions, input validation and rate limiting",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
7
|
-
"interface",
|
|
8
7
|
"api",
|
|
8
|
+
"interface",
|
|
9
|
+
"rate-limit",
|
|
9
10
|
"validation"
|
|
10
11
|
],
|
|
12
|
+
"homepage": "https://interfaces.antelopejs.com/docs/api-util",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/AntelopeJS/interface-api-util/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "Apache-2.0",
|
|
11
17
|
"repository": {
|
|
12
18
|
"type": "git",
|
|
13
19
|
"url": "git+https://github.com/AntelopeJS/interface-api-util.git"
|
|
14
20
|
},
|
|
15
|
-
"license": "Apache-2.0",
|
|
16
|
-
"packageManager": "pnpm@10.6.5",
|
|
17
|
-
"main": "dist/index.js",
|
|
18
|
-
"types": "dist/index.d.ts",
|
|
19
21
|
"files": [
|
|
20
22
|
"dist",
|
|
21
23
|
"docs",
|
|
22
24
|
"skills"
|
|
23
25
|
],
|
|
26
|
+
"main": "dist/index.js",
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
24
28
|
"exports": {
|
|
25
29
|
".": {
|
|
26
30
|
"types": "./dist/index.d.ts",
|
|
@@ -28,37 +32,47 @@
|
|
|
28
32
|
},
|
|
29
33
|
"./package.json": "./package.json"
|
|
30
34
|
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public",
|
|
37
|
+
"provenance": true
|
|
38
|
+
},
|
|
31
39
|
"scripts": {
|
|
32
40
|
"build": "rimraf dist && tsc",
|
|
33
|
-
"format": "
|
|
34
|
-
"lint:fix": "
|
|
35
|
-
"lint": "
|
|
41
|
+
"format": "oxfmt .",
|
|
42
|
+
"lint:fix": "oxlint --fix",
|
|
43
|
+
"lint": "oxlint",
|
|
36
44
|
"prepack": "pnpm run build",
|
|
37
45
|
"release": "pnpm run lint && pnpm run prepack && release-it",
|
|
38
|
-
"test": "pnpm run build && ajs module test ."
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"test": "src/antelope.test.ts",
|
|
42
|
-
"skills": [
|
|
43
|
-
"./skills"
|
|
44
|
-
]
|
|
46
|
+
"test": "pnpm run build && ajs module test .",
|
|
47
|
+
"format:check": "oxfmt --check .",
|
|
48
|
+
"knip": "knip"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
47
|
-
"@antelopejs/
|
|
48
|
-
"@antelopejs/interface-
|
|
49
|
-
"@
|
|
51
|
+
"@antelopejs/core": "^1.16.0",
|
|
52
|
+
"@antelopejs/interface-api": "^0.0.15",
|
|
53
|
+
"@antelopejs/interface-core": "^0.2.4",
|
|
54
|
+
"@antelopejs/tooling-configs": "^0.0.9",
|
|
50
55
|
"@types/mocha": "^10.0.10",
|
|
51
56
|
"@types/node": "^22.19.15",
|
|
57
|
+
"eslint-plugin-perfectionist": "^5.11.0",
|
|
58
|
+
"knip": "^6.34.0",
|
|
59
|
+
"oxfmt": "^0.66.0",
|
|
60
|
+
"oxlint": "1.81.0",
|
|
61
|
+
"oxlint-tsgolint": "^7.0.2001",
|
|
52
62
|
"release-it": "^19.2.4",
|
|
53
63
|
"release-it-changelogen": "^0.1.0",
|
|
54
64
|
"rimraf": "^6.1.3",
|
|
55
65
|
"typescript": "^5.9.3"
|
|
56
66
|
},
|
|
57
67
|
"peerDependencies": {
|
|
58
|
-
"@antelopejs/interface-api": ">=0.0.
|
|
59
|
-
"@antelopejs/interface-core": ">=0.
|
|
68
|
+
"@antelopejs/interface-api": ">=0.0.15 <1.0.0",
|
|
69
|
+
"@antelopejs/interface-core": ">=0.2.4 <1.0.0"
|
|
60
70
|
},
|
|
61
|
-
"
|
|
62
|
-
|
|
71
|
+
"packageManager": "pnpm@10.6.5",
|
|
72
|
+
"antelopeJs": {
|
|
73
|
+
"test": "src/antelope.test.ts",
|
|
74
|
+
"skills": [
|
|
75
|
+
"./skills"
|
|
76
|
+
]
|
|
63
77
|
}
|
|
64
78
|
}
|
|
@@ -18,7 +18,12 @@ as thrown `HTTPResult` values, which the API interface converts into HTTP respon
|
|
|
18
18
|
The package has a single export subpath (root only):
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
assert,
|
|
23
|
+
assertValidation,
|
|
24
|
+
RateLimit,
|
|
25
|
+
type RateLimitOptions,
|
|
26
|
+
} from "@antelopejs/interface-api-util";
|
|
22
27
|
```
|
|
23
28
|
|
|
24
29
|
`hitWindow`, `pruneExpired`, and `resolveKey` are also exported but marked `@internal` (rate-limit
|
|
@@ -27,11 +32,25 @@ plumbing, exposed for tests) — do not reach for them in application code.
|
|
|
27
32
|
## Usage
|
|
28
33
|
|
|
29
34
|
```ts
|
|
30
|
-
import {
|
|
31
|
-
|
|
35
|
+
import {
|
|
36
|
+
Controller,
|
|
37
|
+
Get,
|
|
38
|
+
Post,
|
|
39
|
+
HTTPResult,
|
|
40
|
+
Parameter,
|
|
41
|
+
RawBody,
|
|
42
|
+
} from "@antelopejs/interface-api";
|
|
43
|
+
import {
|
|
44
|
+
assert,
|
|
45
|
+
assertValidation,
|
|
46
|
+
RateLimit,
|
|
47
|
+
} from "@antelopejs/interface-api-util";
|
|
32
48
|
import * as z from "zod";
|
|
33
49
|
|
|
34
|
-
const createMemberSchema = z.object({
|
|
50
|
+
const createMemberSchema = z.object({
|
|
51
|
+
fullName: z.string().min(1),
|
|
52
|
+
email: z.string().email(),
|
|
53
|
+
});
|
|
35
54
|
|
|
36
55
|
class MembersController extends Controller("members") {
|
|
37
56
|
@Get(":id")
|
|
@@ -44,7 +63,9 @@ class MembersController extends Controller("members") {
|
|
|
44
63
|
|
|
45
64
|
@Post()
|
|
46
65
|
async create(@RawBody() body: Buffer) {
|
|
47
|
-
const { fullName, email } = assertValidation(body, (b) =>
|
|
66
|
+
const { fullName, email } = assertValidation(body, (b) =>
|
|
67
|
+
createMemberSchema.parse(JSON.parse((b as Buffer).toString())),
|
|
68
|
+
);
|
|
48
69
|
return new HTTPResult(201, await saveMember({ fullName, email }));
|
|
49
70
|
}
|
|
50
71
|
}
|