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 CHANGED
@@ -1,27 +1,21 @@
1
- # RiserBob Proprietary License
2
-
3
- Copyright (c) 2026 RiserBob. All rights reserved.
4
-
5
- ## 1. Ownership
6
- RiserBob and its original source code, documentation, and associated materials are protected by applicable intellectual property laws. All rights not expressly granted under this license are reserved by the copyright holder.
7
-
8
- ## 2. Permission to Use
9
- Subject to the terms of this license, users are granted permission to use the official, unmodified version of RiserBob in their own applications and projects.
10
-
11
- ## 3. Modification Restrictions
12
- No person or entity may modify, adapt, alter, or create derivative versions of the RiserBob framework without prior written permission from the copyright holder.
13
-
14
- ## 4. Distribution Restrictions
15
- Redistribution, resale, sublicensing, or publication of RiserBob or any modified version of the framework is prohibited unless expressly authorized in writing by the copyright holder.
16
-
17
- ## 5. Independent Applications
18
- Users retain ownership of their independently developed application code, subject to any third-party rights and applicable law. Using RiserBob does not, by itself, transfer ownership of an application's independent code to the copyright holder.
19
-
20
- ## 6. No Implied Permission
21
- No permission is granted beyond the rights expressly stated in this license. Any exception must be approved in writing by the copyright holder.
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
- # 🧽 RiserBob
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 lightweight, fun, and fully tested HTTP framework for [Bun](https://bun.sh), with a built-in router, middleware pipeline, request validation, and consistent error handling.
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 [RiserBob Proprietary License](#license). Please read it before using the framework.
9
+ > RiserBob is distributed under the [MIT License](#license).
6
10
 
7
- ## Features
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
+ ![RiserBob](https://res.cloudinary.com/dgagbheuj/image/upload/v1792927501/qlflwqvq6xqgxnbn0puk.png)
16
12
 
17
- ## Requirements
13
+ ## Features
18
14
 
19
- - [Bun](https://bun.sh) 1.3 or newer
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
- ```bash
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 run index.ts
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
- `spongReq` also exposes `method`, `path`, `url`, `headers`, `text()`, and the original `request`.
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 type { SpongMiddleware, SpongRequest } from 'riser-bob'
94
-
95
- const logger: SpongMiddleware<SpongRequest> = async (spongReq, next) => {
96
- console.log(`${spongReq.method} ${spongReq.path}`)
97
- return next()
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
- app.spongUse(logger) // global middleware
101
-
102
- app.spongGet('/admin', handler, adminOnly) // route-specific middleware
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
- | Rule | Description |
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
- ```ts
164
- app.spongGet('/ok', async (spongReq, spongRes) => spongRes.json({ ok: true }))
165
- app.spongGet('/raw', async () => new Response('plain text'))
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
- To fail with a specific status, throw an `HttpError`:
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
- app.spongGet('/secret', async () => {
174
- throw new HttpError(403, 'Forbidden')
175
- })
176
- ```
72
+ ## Simple API, Powerful Structure
177
73
 
178
- RiserBob handles the common cases for you:
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
- | Situation | Response |
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
- ## Development
78
+ Generate a complete module (`users.controller.ts`, `users.route.ts`, `users.module.ts`) with one command:
189
79
 
190
80
  ```bash
191
- # Install dependencies
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
- ## Contributing
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
- RiserBob is released under the **RiserBob Proprietary License**. In short:
224
-
225
- - You may use the official, unmodified version of RiserBob in your own applications and projects.
226
- - You may **not** modify, redistribute, resell, or sublicense the framework without prior written permission.
227
- - You keep full ownership of the application code you write with RiserBob.
228
-
229
- See the [LICENSE](LICENSE) file for the full terms.
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
- spongListen(port?: number, callback?: () => void): Bun.Server<undefined>;
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 b,writeFile as f}from"fs/promises";import i from"path";function h(o){return o.split(/[-_\s]+/).filter(Boolean).map((e)=>e[0].toUpperCase()+e.slice(1).toLowerCase()).join("")}function w(o){return o.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[_\s]+/g,"-")}function y(o){return/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(o)}async function p(o){if(!y(o))throw Error('Invalid module name. Use letters, numbers, "-" or "_", starting with a letter.');let e=w(o),r=h(e),l=i.resolve(process.cwd(),"src","modules",e),c={[`${e}.controller.ts`]:`import type { SpongHandler } from "riser-bob";
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
- `};await b(l,{recursive:!0});for(let t of Object.keys(c)){let n=i.join(l,t);if(await Bun.file(n).exists())throw Error(`File "${i.relative(process.cwd(),n)}" already exists.`)}let d=[];try{for(let[t,n]of Object.entries(c)){let a=i.join(l,t);await f(a,n,{flag:"wx"}),d.push(a)}}catch(t){let{unlink:n}=await import("fs/promises");throw await Promise.all(d.map((a)=>n(a).catch(()=>{}))),t}console.log(`\uD83E\uDDFD Module "${e}" generated successfully!`),console.log(`\uD83D\uDCC1 ${i.relative(process.cwd(),l)}`);for(let t of Object.keys(c))console.log(` \u2514\u2500\u2500 ${t}`)}var s=process.argv.slice(2),[m,v,g]=s;function u(){console.log(`
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 R(){if(s.length===0||s.includes("--help")||s.includes("-h")){u();return}if(s.includes("--version")||s.includes("-v")){console.log("RiserBob CLI"),console.log("Version is provided by the installed package.");return}if((m==="g"||m==="generate")&&v==="module"&&g){await p(g);return}console.error("\uD83E\uDDFD Oh, barnacles! Unknown command."),u(),process.exitCode=1}R().catch((o)=>{let e=o instanceof Error?o.message:"Something went wrong.";console.error(`\uD83C\uDF4D RiserBob CLI: ${e}`),process.exitCode=1});
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';