riser-bob 1.0.0 → 1.1.0
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/LICENSE +21 -27
- package/README.md +65 -200
- package/dist/application/riser-bob.d.ts +8 -1
- package/dist/cli.js +33 -4
- package/dist/errors/errors-messages.d.ts +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +71 -21
- package/dist/middleware/auth-middleware.d.ts +11 -3
- package/dist/middleware/logger-middleware.d.ts +3 -2
- package/dist/middleware/middleware-pipeline.d.ts +4 -2
- package/dist/routing/router.d.ts +3 -0
- package/dist/server/http-server.d.ts +3 -1
- package/dist/types/riser-bob-options.d.ts +3 -0
- package/dist/types/socket-io-integration.d.ts +7 -0
- package/dist/types/spong-request.d.ts +3 -4
- package/dist/validation/validator.d.ts +23 -2
- package/package.json +60 -58
package/LICENSE
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## 7. Disclaimer
|
|
24
|
-
RiserBob is provided "AS IS", without warranties of any kind, to the maximum extent permitted by applicable law.
|
|
25
|
-
|
|
26
|
-
## 8. Contact and Written Permission
|
|
27
|
-
Requests for permission to modify or redistribute RiserBob must be submitted to the copyright holder and approved in writing before the relevant activity takes place.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zen Allaham — RiserBob
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,231 +1,96 @@
|
|
|
1
|
-
|
|
1
|
+
<h1>
|
|
2
|
+
<img src="https://res.cloudinary.com/dgagbheuj/image/upload/v1792601028/riserbob/covers/keps4sy2lumzdx0ho23i.png" alt="RiserBob Logo" width="48" height="48" align="absmiddle" />
|
|
3
|
+
RiserBob
|
|
4
|
+
</h1>
|
|
2
5
|
|
|
3
|
-
A
|
|
6
|
+
A fun and fast framework powered by Bun and TypeScript, bringing simplicity and a fresh perspective to backend development.
|
|
7
|
+
Stay in the Sponge Zone!
|
|
4
8
|
|
|
5
|
-
> RiserBob is distributed under the [
|
|
9
|
+
> RiserBob is distributed under the [MIT License](#license).
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **Fast routing** with static and dynamic (`/users/:id`) routes, where static routes win over dynamic ones.
|
|
10
|
-
- **Middleware pipeline** with global and per-route middleware, executed in registration order.
|
|
11
|
-
- **Built-in auth middleware** for Bearer-token authentication with your own token verifier.
|
|
12
|
-
- **Validator** with a simple rule syntax (`required`, `string`, `email`, `min:18`, ...).
|
|
13
|
-
- **Response helpers** for JSON, status codes, headers, and redirects.
|
|
14
|
-
- **Consistent errors** through `HttpError` and a central error handler (`404`, `405` with the `Allow` header, `500`).
|
|
15
|
-
- **Fully tested** with Bun's test runner (unit and end-to-end tests).
|
|
11
|
+

|
|
16
12
|
|
|
17
|
-
##
|
|
13
|
+
## Features
|
|
18
14
|
|
|
19
|
-
-
|
|
15
|
+
- **Modular Structure** — Clean, reusable modules that keep your codebase easy to maintain.
|
|
16
|
+
- **Ready-to-Use Middleware** — Protect routes and handle common request workflows out of the box.
|
|
17
|
+
- **Blazing-Fast Performance** — Built for Bun and TypeScript, with a lightweight HTTP core.
|
|
18
|
+
- **Built-in Validation** — Validate incoming data with a simple, developer-friendly API.
|
|
19
|
+
- **Integrated CLI** — Generate whole modules in seconds.
|
|
20
|
+
- **Fun Sponge Zone** — Playful, SpongeBob-inspired messages and errors that make debugging enjoyable.
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
bun add riser-bob
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
> The examples below import from `riser-bob`. Adjust the import path if you install or reference the framework differently.
|
|
28
|
-
|
|
29
|
-
## Quick Start
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
import { RiserBob } from 'riser-bob'
|
|
33
|
-
|
|
34
|
-
const app = new RiserBob()
|
|
35
|
-
|
|
36
|
-
app.spongGet('/', async (spongReq, spongRes) => {
|
|
37
|
-
return spongRes.json({ message: 'Welcome to Bikini Bottom! 🍍' })
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
app.spongListen(3000, () => {
|
|
41
|
-
console.log('RiserBob is running on http://localhost:3000')
|
|
42
|
-
})
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Run it:
|
|
24
|
+
Requires [Bun](https://bun.sh) 1.3 or newer. There are two ways to start.
|
|
46
25
|
|
|
26
|
+
### 1. Starter template (recommended)
|
|
47
27
|
```bash
|
|
48
|
-
bun
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Routing
|
|
52
|
-
|
|
53
|
-
Register routes with the `Sponge` methods. Every method returns the app, so calls can be chained.
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
app.spongGet('/users', listUsers)
|
|
57
|
-
.spongPost('/users', createUser)
|
|
58
|
-
.spongPut('/users/:id', replaceUser)
|
|
59
|
-
.spongPatch('/users/:id', updateUser)
|
|
60
|
-
.spongDelete('/users/:id', deleteUser)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Paths must start with `/`, and registering the same method and path twice throws an error.
|
|
64
|
-
|
|
65
|
-
### Route parameters and query strings
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
app.spongGet('/users/:id', async (spongReq, spongRes) => {
|
|
69
|
-
const { id } = spongReq.params // decoded automatically
|
|
70
|
-
const page = spongReq.query.get('page') // URLSearchParams
|
|
71
|
-
|
|
72
|
-
return spongRes.json({ id, page })
|
|
73
|
-
})
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Reading the request body
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
app.spongPost('/users', async (spongReq, spongRes) => {
|
|
80
|
-
const body = await spongReq.json<{ name: string }>()
|
|
81
|
-
|
|
82
|
-
return spongRes.json({ created: body.name })
|
|
83
|
-
})
|
|
28
|
+
bun create riser-bob my-app
|
|
84
29
|
```
|
|
85
30
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## Middleware
|
|
89
|
-
|
|
90
|
-
A middleware receives the request and a `next` function. Return `next()` to continue, or return a `Response` to stop the chain.
|
|
31
|
+
The best choice if you want a ready-made, organized template to start your project with. It creates `src/index.ts`:
|
|
91
32
|
|
|
92
33
|
```ts
|
|
93
|
-
import
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
34
|
+
import { RiserBob } from "riser-bob";
|
|
35
|
+
import { UsersModule } from "./modules/users/users.module";
|
|
36
|
+
|
|
37
|
+
async function bootstrap() {
|
|
38
|
+
const bob = new RiserBob();
|
|
39
|
+
bob.spongGet("/", async (spongReq, spongRes) => {
|
|
40
|
+
return spongRes.json({
|
|
41
|
+
message: "Welcome to Bikini Bottom! 🍍",
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
new UsersModule().register(bob);
|
|
45
|
+
bob.spongListen(4000, () => {
|
|
46
|
+
console.log("🧽 RiserBob is running at http://localhost:4000 🍍");
|
|
47
|
+
});
|
|
98
48
|
}
|
|
99
49
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
> Global middleware is attached when a route is registered, so call `spongUse` **before** registering the routes it should apply to.
|
|
106
|
-
|
|
107
|
-
### Authentication
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
import { AuthMiddleware } from 'riser-bob'
|
|
111
|
-
|
|
112
|
-
const auth = new AuthMiddleware(async (token) => {
|
|
113
|
-
// Return the user for a valid token, or null for an invalid one.
|
|
114
|
-
return verifyMyToken(token)
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
app.spongGet(
|
|
118
|
-
'/me',
|
|
119
|
-
async (spongReq, spongRes) => {
|
|
120
|
-
return spongRes.json({ user: spongReq.user })
|
|
121
|
-
},
|
|
122
|
-
auth.middleware
|
|
123
|
-
)
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
The middleware reads the `Authorization: Bearer <token>` header. On success it sets `spongReq.user` and `spongReq.auth`. Otherwise it responds with `401` (`Unauthorized`, `Token is required`, or `Invalid or expired token`).
|
|
127
|
-
|
|
128
|
-
## Validation
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
import { Validator } from 'riser-bob'
|
|
132
|
-
|
|
133
|
-
const result = Validator.validate(
|
|
134
|
-
{ name: 'Zen', age: 17, email: 'zen@example.com' },
|
|
135
|
-
{
|
|
136
|
-
name: ['required', 'string'],
|
|
137
|
-
age: ['required', 'number', 'min:13'],
|
|
138
|
-
email: ['required', 'email']
|
|
139
|
-
}
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
if (!result.valid) {
|
|
143
|
-
console.log(result.errors) // { age: ['age must be at least 13'], ... }
|
|
144
|
-
}
|
|
50
|
+
bootstrap().catch((error: unknown) => {
|
|
51
|
+
console.error("[RiserBob] Failed to start application:", error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
145
54
|
```
|
|
146
55
|
|
|
147
|
-
|
|
148
|
-
| ------------------------------- | ------------------------------------------------------ |
|
|
149
|
-
| `required` | Value must be present and not empty. |
|
|
150
|
-
| `nullable` | `null` is allowed. Cannot be combined with `required`. |
|
|
151
|
-
| `string` / `number` / `boolean` | Type checks. Numbers must be finite. |
|
|
152
|
-
| `email` | Must be a valid email address. |
|
|
153
|
-
| `confirmed` | Must match the `<field>Confirmation` value. |
|
|
154
|
-
| `min:n` / `max:n` | Numeric limit for numbers, length limit for strings. |
|
|
155
|
-
| `minLength:n` / `maxLength:n` | String length limits (integers only). |
|
|
156
|
-
|
|
157
|
-
Fields without `required` are optional: missing values and empty strings are skipped.
|
|
158
|
-
|
|
159
|
-
## Responses and Errors
|
|
160
|
-
|
|
161
|
-
Handlers must return a `Response`. The `spongRes` helper builds one for you, and you can always return a standard `Response` instead.
|
|
56
|
+
Then the terminal shows:
|
|
162
57
|
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
|
|
58
|
+
```text
|
|
59
|
+
🧽 RiserBob — Project created successfully!
|
|
60
|
+
📁 Location: /path/to/my-app
|
|
61
|
+
|
|
62
|
+
Get started:
|
|
63
|
+
$ cd "my-app"
|
|
64
|
+
$ bun install
|
|
65
|
+
$ bun run dev
|
|
66
|
+
🍍 Happy coding in the Sponge Zone!
|
|
166
67
|
```
|
|
167
68
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
```ts
|
|
171
|
-
import { HttpError } from 'riser-bob'
|
|
69
|
+
### 2. Start from scratch
|
|
70
|
+
RiserBob doesn't force anything on you. Run `bun init`, then `bun add riser-bob`. Just remember that you'll need to build the server entry file yourself (like the one above).
|
|
172
71
|
|
|
173
|
-
|
|
174
|
-
throw new HttpError(403, 'Forbidden')
|
|
175
|
-
})
|
|
176
|
-
```
|
|
72
|
+
## Simple API, Powerful Structure
|
|
177
73
|
|
|
178
|
-
|
|
74
|
+
Every feature is a module of three focused files: a **controller** (the logic), a **router** (paths mapped to handlers) and a **module** that wires them together, so one call registers the whole feature: `new UsersModule().register(bob)`.
|
|
179
75
|
|
|
180
|
-
|
|
181
|
-
| ------------------------------ | ------------------------------------------------------- |
|
|
182
|
-
| No matching route | `404 Not Found` |
|
|
183
|
-
| Path exists, method does not | `405 Method Not Allowed` with an `Allow` header |
|
|
184
|
-
| Handler throws an `HttpError` | The error's status and message |
|
|
185
|
-
| Handler throws any other error | `500 Internal Server Error` (details are never exposed) |
|
|
186
|
-
| Handler returns no `Response` | `500` |
|
|
76
|
+
## CLI
|
|
187
77
|
|
|
188
|
-
|
|
78
|
+
Generate a complete module (`users.controller.ts`, `users.route.ts`, `users.module.ts`) with one command:
|
|
189
79
|
|
|
190
80
|
```bash
|
|
191
|
-
#
|
|
192
|
-
bun install
|
|
193
|
-
|
|
194
|
-
# Run all tests
|
|
195
|
-
bun test
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
```text
|
|
199
|
-
src/
|
|
200
|
-
application/ RiserBob application class
|
|
201
|
-
errors/ HttpError and ErrorHandler
|
|
202
|
-
http/ Response helpers
|
|
203
|
-
middleware/ Middleware pipeline and built-in middleware
|
|
204
|
-
routing/ Router
|
|
205
|
-
server/ HTTP server
|
|
206
|
-
types/ Shared types
|
|
207
|
-
validation/ Validator
|
|
208
|
-
test/
|
|
209
|
-
unit/ Unit tests
|
|
210
|
-
e2e/ End-to-end tests
|
|
81
|
+
bun run riser-bob g module users # `generate` also works
|
|
211
82
|
```
|
|
83
|
+
## Learn more
|
|
212
84
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
Contributions are welcome, but because RiserBob is proprietary, please read [CONTRIBUTING.md](CONTRIBUTING.md) first. It explains the contribution terms. Please also follow our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
216
|
-
|
|
217
|
-
## Security
|
|
218
|
-
|
|
219
|
-
Please report vulnerabilities privately. See [SECURITY.md](SECURITY.md) for details.
|
|
85
|
+
Docs and examples: **[riserbob.vercel.app](https://riserbob.vercel.app)**. Contributions are welcome ([CONTRIBUTING.md](CONTRIBUTING.md), [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)); report vulnerabilities privately ([SECURITY.md](SECURITY.md)).
|
|
220
86
|
|
|
221
87
|
## License
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
Copyright (c) 2026 RiserBob. All rights reserved.
|
|
88
|
+
RiserBob is released under the **MIT License**. See [LICENSE](LICENSE). Copyright (c) 2026 Zen Allaham — RiserBob
|
|
89
|
+
|
|
90
|
+
<p align="center">
|
|
91
|
+
<img
|
|
92
|
+
src="https://res.cloudinary.com/dgagbheuj/image/upload/v1792769341/ob3ejwt32h6dtfhxg1kh.png"
|
|
93
|
+
alt="RiserBob — Build APIs. Stay in the Sponge Zone."
|
|
94
|
+
width="100%"
|
|
95
|
+
/>
|
|
96
|
+
</p>
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { SpongHandler } from '../types/spong-handler';
|
|
2
2
|
import type { SpongRequest } from '../types/spong-request';
|
|
3
3
|
import type { SpongMiddleware } from '../types/spong-middleware';
|
|
4
|
+
import type { RiserBobOptions } from '../types/riser-bob-options';
|
|
5
|
+
import { Server as SocketIOServer } from 'socket.io';
|
|
6
|
+
import type { ServerOptions } from 'socket.io';
|
|
4
7
|
export declare class RiserBob {
|
|
5
8
|
private readonly router;
|
|
6
9
|
private readonly middlewares;
|
|
10
|
+
private readonly errorMessages;
|
|
11
|
+
private socketIO?;
|
|
12
|
+
constructor(options?: RiserBobOptions);
|
|
7
13
|
private register;
|
|
8
14
|
spongGet(path: string, handler: SpongHandler, ...middlewares: SpongMiddleware<SpongRequest>[]): this;
|
|
9
15
|
spongPost(path: string, handler: SpongHandler, ...middlewares: SpongMiddleware<SpongRequest>[]): this;
|
|
@@ -13,5 +19,6 @@ export declare class RiserBob {
|
|
|
13
19
|
spongHead(path: string, handler: SpongHandler, ...middlewares: SpongMiddleware<SpongRequest>[]): this;
|
|
14
20
|
spongOptions(path: string, handler: SpongHandler, ...middlewares: SpongMiddleware<SpongRequest>[]): this;
|
|
15
21
|
spongUse(middleware: SpongMiddleware<SpongRequest>): this;
|
|
16
|
-
|
|
22
|
+
spongSocketIO(options?: Partial<ServerOptions>): SocketIOServer;
|
|
23
|
+
spongListen(port?: number, callback?: () => void): Bun.Server<import("@socket.io/bun-engine").WebSocketData>;
|
|
17
24
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{mkdir as
|
|
3
|
+
import{mkdir as m,writeFile as y,unlink as R}from"fs/promises";import s from"path";function g(o){return o.split(/[-_\s]+/).filter(Boolean).map((e)=>e[0].toUpperCase()+e.slice(1).toLowerCase()).join("")}function C(o){return o.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[_\s]+/g,"-")}function x(o){if(o.endsWith("ies")&&o.length>3)return`${o.slice(0,-3)}y`;if(o.endsWith("s")&&!o.endsWith("ss"))return o.slice(0,-1);return o}function v(o){return/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(o)}async function f(o){if(!v(o))throw Error('Invalid module name. Use letters, numbers, "-" or "_", starting with a letter.');let e=C(o),r=g(e),p=x(e),i=g(p),a=s.resolve(process.cwd(),"src","modules",e),c={[`${e}.controller.ts`]:`import type { SpongHandler } from "riser-bob";
|
|
4
4
|
|
|
5
5
|
export class ${r}Controller {
|
|
6
6
|
readonly create: SpongHandler = async (spongReq, spongRes) => {
|
|
@@ -41,11 +41,15 @@ export class ${r}Router {
|
|
|
41
41
|
|
|
42
42
|
register(): void {
|
|
43
43
|
// Public routes
|
|
44
|
-
this.bob.spongPost("/api/${e}", this.controller.create);
|
|
45
44
|
this.bob.spongGet("/api/${e}", this.controller.findAll);
|
|
46
45
|
this.bob.spongGet("/api/${e}/:id", this.controller.findOne);
|
|
47
46
|
|
|
48
47
|
// Protected routes
|
|
48
|
+
this.bob.spongPost("/api/${e}",
|
|
49
|
+
this.controller.create,
|
|
50
|
+
this.authMiddleware.middleware,
|
|
51
|
+
);
|
|
52
|
+
|
|
49
53
|
this.bob.spongPut(
|
|
50
54
|
"/api/${e}/:id",
|
|
51
55
|
this.controller.update,
|
|
@@ -81,7 +85,32 @@ export class ${r}Module {
|
|
|
81
85
|
router.register();
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
|
-
`
|
|
88
|
+
`,[`schemas/${p}.schema.ts`]:`export class ${i}Schema {}
|
|
89
|
+
`,["rules/create.ts"]:`import type { ValidationSchema } from "riser-bob";
|
|
90
|
+
|
|
91
|
+
export const Create${i}Rule = {} satisfies ValidationSchema;
|
|
92
|
+
`,["rules/update.ts"]:`import { Create${i}Rule } from "./create";
|
|
93
|
+
|
|
94
|
+
export const Update${i}Rule = Create${i}Rule;
|
|
95
|
+
`,[`tests/${e}.controller.test.ts`]:`import { describe, expect, test } from "bun:test";
|
|
96
|
+
import { ${r}Controller } from "../${e}.controller";
|
|
97
|
+
|
|
98
|
+
describe("${r}Controller", () => {
|
|
99
|
+
const controller = new ${r}Controller();
|
|
100
|
+
|
|
101
|
+
test("should be defined", () => {
|
|
102
|
+
expect(controller).toBeDefined();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("should expose all route handlers", () => {
|
|
106
|
+
expect(typeof controller.create).toBe("function");
|
|
107
|
+
expect(typeof controller.findAll).toBe("function");
|
|
108
|
+
expect(typeof controller.findOne).toBe("function");
|
|
109
|
+
expect(typeof controller.update).toBe("function");
|
|
110
|
+
expect(typeof controller.delete).toBe("function");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
`};await m(a,{recursive:!0});for(let t of Object.keys(c)){let n=s.join(a,t);if(await Bun.file(n).exists())throw Error(`File "${s.relative(process.cwd(),n)}" already exists.`)}let u=[];try{for(let[t,n]of Object.entries(c)){let d=s.join(a,t);await m(s.dirname(d),{recursive:!0}),await y(d,n,{flag:"wx"}),u.push(d)}}catch(t){throw await Promise.all(u.map((n)=>R(n).catch(()=>{}))),t}console.log(""),console.log(`\uD83E\uDDFD Module "${e}" generated successfully!`),console.log(""),console.log(`\uD83D\uDCC1 ${s.relative(process.cwd(),a)}`),console.log("");for(let t of Object.keys(c))console.log(` \u2514\u2500\u2500 ${t}`)}var l=process.argv.slice(2),[h,O,b]=l;function w(){console.log(`
|
|
85
114
|
\uD83E\uDDFD RiserBob CLI
|
|
86
115
|
|
|
87
116
|
Usage:
|
|
@@ -92,4 +121,4 @@ Usage:
|
|
|
92
121
|
Commands:
|
|
93
122
|
g, generate Generate a component
|
|
94
123
|
--help Show this help message
|
|
95
|
-
`)}async function
|
|
124
|
+
`)}async function B(){if(l.length===0||l.includes("--help")||l.includes("-h")){w();return}if(l.includes("--version")||l.includes("-v")){console.log("RiserBob CLI"),console.log("Version is provided by the installed package.");return}if((h==="g"||h==="generate")&&O==="module"&&b){await f(b);return}console.error("\uD83E\uDDFD Oh, barnacles! Unknown command."),w(),process.exitCode=1}B().catch((o)=>{let e=o instanceof Error?o.message:"Something went wrong.";console.error(`\uD83C\uDF4D RiserBob CLI: ${e}`),process.exitCode=1});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class ErrorMessages {
|
|
2
|
+
private readonly funnyMode;
|
|
3
|
+
constructor(funnyMode?: boolean);
|
|
4
|
+
invalidPath(path: string): string;
|
|
5
|
+
handlerDidNotReturnResponse(): string;
|
|
6
|
+
requestFailed(): string;
|
|
7
|
+
nextCalledMultipleTimes(): string;
|
|
8
|
+
duplicateRoute(key: string): string;
|
|
9
|
+
methodNotAllowed(method: string, path: string, allowed: string[]): string;
|
|
10
|
+
routeNotFound(method: string, path: string): string;
|
|
11
|
+
handlerResponseMissing(method: string, path: string, received: string): string;
|
|
12
|
+
requestHandlingFailed(): string;
|
|
13
|
+
invalidValidationSchema(field: string): string;
|
|
14
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export type { SpongMethod } from './types/spong-method';
|
|
|
10
10
|
export type { SpongMiddleware } from './types/spong-middleware';
|
|
11
11
|
export type { SpongRequest } from './types/spong-request';
|
|
12
12
|
export type { SpongResponse } from './types/spong-response';
|
|
13
|
+
export type { SpongNext } from './types/spong-middleware';
|
|
13
14
|
export type { ValidationSchema } from './validation/validator';
|
|
14
15
|
export { Validator } from './validation/validator';
|