18h
v3.1.3
Published
A Next.js style dynamic API router for Koa-based APIs.
Downloads
206
Readme
npm install 18h
mkdir routes
import { join } from "path";
import { router } from "18h";
router({
routesFolder: join(__dirname, "routes"),
port: 8000,
hostname: "localhost",
});
const logRequest = async (context, next) => {
console.log(context);
await next();
};
router({
// ...
middleware: [logRequest],
});
Example
Assuming you provided a folder called
routes
as theroutesFolder
when creating your router object, creating a file atroutes/index.ts
it will allow consumers to interact with that endpoint at thehttp://localhost/
URL.Creating a file called
routes/example.ts
will allow consumers to interact with that endpoint at thehttp://localhost/example
URL.Creating a file called
routes/example/index.ts
will produce the same result as mentioned above.
Note
Placing square brackets
[]
around the entire name of a folder or file in the routes folder will allow for route parameters to be accepted through that endpoint.
/a/[b]/c
would become the endpoint path/a/:b/c
.
The following file structure would generate the corresponding API endpoint structure.
package.json
package-lock.json
node_modules/
src/
├── index.ts
└── routes/
├── index.ts
├── feed/
│ └── index.ts
├── user/
│ ├── delete.ts
│ ├── index.ts
│ └── settings/
│ ├── private.ts
│ └── name.ts
├── users/
│ └── [userId]/
│ ├── block.ts
│ ├── index.ts
│ └── follow.ts
└── posts/
├── create.ts
├── delete.ts
├── index.ts
├── like.ts
└── share.ts
tsconfig.json
/
/feed
/user/
/user/delete
/user/settings
/user/settings/private
/user/settings/name
/users/:userId
/users/:userId/block
/users/:userId/follow
/posts
/posts/create
/posts/delete
/posts/like
/posts/share
// src/routes/users/[userId]/block
import { route, method, validation } from "18h";
export default route<{ userId: string }>({
get: method({
/** If you are accepting a body, you must
* define whether it can be `"form"`,
* `"json"`, or both. */
// accepts: ["json", "form"],
/** Validation, request, and response schema
* definition is done in one swoop. Uses "zod"
* library under the hood. */
schema: {
request: validation.null(),
response: validation.object({
userId: validation.string(),
}),
},
/** Optional middleware, `pre` will occur
* before the hanler, while `post` will happen
* after. */
middleware: {
pre: [],
post: [],
},
async handler(context) {
console.log(context.params.userId); // :userId sourced from URL.
console.log(context.request.body); // null
return {
status: 200,
headers: {
"x-custom-header": "true",
},
body: {
userId: "some_id",
},
};
},
}),
});
We can create a simple endpoint that just responds with the node package version of the current project we're in. The endpoint will work on all HTTP methods, not just GET
, but we could change it to do that by changing all occurances of all
to get
.
import { route, method, validation } from "18h";
const { npm_package_version: version } = process.env;
export default route({
all: method({
schema: {
request: validation.null(),
response: validation.object({
version: validation.string().optional(),
}),
},
async handler() {
return { body: { version } };
},
}),
});