elysia-autoload 0.0.1
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 +97 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +39 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +49 -0
- package/package.json +33 -0
package/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# elysia-autoload
|
2
|
+
|
3
|
+
Plugin for [Elysia](https://elysiajs.com/) which autoload all routes in directory
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
bun install elysia-autoload
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
## Register the plugin
|
14
|
+
|
15
|
+
```ts
|
16
|
+
import { Elysia } from "elysia";
|
17
|
+
import { autoload } from "elysia-autoload";
|
18
|
+
|
19
|
+
const app = new Elysia().use(autoload()).listen(3000);
|
20
|
+
|
21
|
+
export type ElysiaApp = typeof app;
|
22
|
+
```
|
23
|
+
|
24
|
+
## Create route
|
25
|
+
|
26
|
+
```ts
|
27
|
+
// routes/index.ts
|
28
|
+
import type { ElysiaApp } from "app";
|
29
|
+
|
30
|
+
export default (app: ElysiaApp) => app.get("/", { hello: "world" });
|
31
|
+
```
|
32
|
+
|
33
|
+
### Directory structure
|
34
|
+
|
35
|
+
Guide how `elysia-autoload` match routes
|
36
|
+
|
37
|
+
```
|
38
|
+
├── app.ts
|
39
|
+
├── routes
|
40
|
+
├── index.ts // index routes
|
41
|
+
├── posts
|
42
|
+
├── index.ts
|
43
|
+
└── [id].ts // dynamic params
|
44
|
+
├── likes
|
45
|
+
├── [...].ts
|
46
|
+
└── users.ts
|
47
|
+
└── package.json
|
48
|
+
```
|
49
|
+
|
50
|
+
- /routes/index.ts → /
|
51
|
+
- /routes/posts/index.ts → /posts
|
52
|
+
- /routes/posts/[id].ts → /posts/:id
|
53
|
+
- /routes/users.ts → /users
|
54
|
+
- /routes/likes/[...].ts → /likes/\*
|
55
|
+
|
56
|
+
## Options
|
57
|
+
|
58
|
+
| Key | Type | Default | Description |
|
59
|
+
| -------- | -------- | --------------------------- | ------------------------------------------------------------------- |
|
60
|
+
| pattern? | string | "\*\*_/\*_.{ts,js,mjs,cjs}" | [Glob patterns](<https://en.wikipedia.org/wiki/Glob_(programming)>) |
|
61
|
+
| dir? | string | "./routes" | The folder where routes are located |
|
62
|
+
| prefix? | string | | Prefix for routes |
|
63
|
+
| schema? | Function | | Handler for providing routes guard schema |
|
64
|
+
|
65
|
+
### Usage of schema handler
|
66
|
+
|
67
|
+
```ts
|
68
|
+
import swagger from "@elysiajs/swagger";
|
69
|
+
import Elysia from "elysia";
|
70
|
+
import { autoload } from "elysia-autoload";
|
71
|
+
|
72
|
+
const app = new Elysia()
|
73
|
+
.use(
|
74
|
+
autoload({
|
75
|
+
schema: ({ path, url }) => {
|
76
|
+
const tag = url.split("/").at(1)!;
|
77
|
+
|
78
|
+
return {
|
79
|
+
beforeHandle: ({ request }) => {
|
80
|
+
console.log(request.url);
|
81
|
+
},
|
82
|
+
detail: {
|
83
|
+
description: `Route autoloaded from ${path}`,
|
84
|
+
tags: [tag],
|
85
|
+
},
|
86
|
+
};
|
87
|
+
},
|
88
|
+
}),
|
89
|
+
)
|
90
|
+
.use(swagger());
|
91
|
+
|
92
|
+
export type ElysiaApp = typeof app;
|
93
|
+
|
94
|
+
app.listen(3001, console.log);
|
95
|
+
```
|
96
|
+
|
97
|
+
### Thanks [https://github.com/wobsoriano/elysia-autoroutes](elysia-autoroutes) for some ideas
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import Elysia from "elysia";
|
2
|
+
export interface AutoloadOptions {
|
3
|
+
pattern?: string;
|
4
|
+
dir?: string;
|
5
|
+
prefix?: string;
|
6
|
+
schema?: ({ path, url, }: {
|
7
|
+
path: string;
|
8
|
+
url: string;
|
9
|
+
}) => Parameters<InstanceType<typeof Elysia>["group"]>[1];
|
10
|
+
}
|
11
|
+
export declare function autoload({ pattern, dir, prefix, schema, }?: AutoloadOptions): Promise<Elysia<"", {
|
12
|
+
request: {};
|
13
|
+
store: {};
|
14
|
+
derive: {};
|
15
|
+
resolve: {};
|
16
|
+
}, {
|
17
|
+
type: {};
|
18
|
+
error: {};
|
19
|
+
}, {}, {}, {}, false>>;
|
package/dist/index.js
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.autoload = void 0;
|
4
|
+
const elysia_1 = require("elysia");
|
5
|
+
const node_fs_1 = require("node:fs");
|
6
|
+
const node_path_1 = require("node:path");
|
7
|
+
const utils_1 = require("./utils");
|
8
|
+
async function autoload({ pattern, dir, prefix, schema, } = {}) {
|
9
|
+
const directoryPath = (0, utils_1.getPath)(dir || "./routes");
|
10
|
+
if (!node_fs_1.default.existsSync(directoryPath))
|
11
|
+
throw new Error(`Directory ${directoryPath} doesn't exists`);
|
12
|
+
if (!node_fs_1.default.statSync(directoryPath).isDirectory())
|
13
|
+
throw new Error(`${directoryPath} isn't a directory`);
|
14
|
+
const app = new elysia_1.default({
|
15
|
+
name: "elysia-autoload",
|
16
|
+
seed: {
|
17
|
+
pattern,
|
18
|
+
dir,
|
19
|
+
},
|
20
|
+
});
|
21
|
+
const glob = new Bun.Glob(pattern || "**/*.{ts,js,mjs,cjs}");
|
22
|
+
const files = await Array.fromAsync(glob.scan({
|
23
|
+
cwd: directoryPath,
|
24
|
+
}));
|
25
|
+
for await (const path of (0, utils_1.sortByNestedParams)(files)) {
|
26
|
+
const file = await Promise.resolve(`${(0, node_path_1.join)(directoryPath, path)}`).then(s => require(s));
|
27
|
+
if (!file.default)
|
28
|
+
throw new Error(`${path} don't provide export default`);
|
29
|
+
const url = (0, utils_1.transformToUrl)(path);
|
30
|
+
const groupOptions = schema ? schema({ path, url }) : {};
|
31
|
+
// Типы свойства "body" несовместимы.
|
32
|
+
// Тип "string | TSchema | undefined" не может быть назначен для типа "TSchema | undefined".
|
33
|
+
// Тип "string" не может быть назначен для типа "TSchema".ts(2345)
|
34
|
+
// @ts-expect-error why....
|
35
|
+
app.group((prefix ?? "") + url, groupOptions, file.default);
|
36
|
+
}
|
37
|
+
return app;
|
38
|
+
}
|
39
|
+
exports.autoload = autoload;
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.sortByNestedParams = exports.transformToUrl = exports.getPath = void 0;
|
4
|
+
const node_path_1 = require("node:path");
|
5
|
+
function getPath(dir) {
|
6
|
+
if ((0, node_path_1.isAbsolute)(dir))
|
7
|
+
return dir;
|
8
|
+
if ((0, node_path_1.isAbsolute)(process.argv[1]))
|
9
|
+
return (0, node_path_1.join)(process.argv[1], "..", dir);
|
10
|
+
return (0, node_path_1.join)(process.cwd(), process.argv[1], "..", dir);
|
11
|
+
}
|
12
|
+
exports.getPath = getPath;
|
13
|
+
// Inspired by https://github.com/wobsoriano/elysia-autoroutes/blob/main/src/utils/transformPathToUrl.ts#L4C31-L4C31
|
14
|
+
function transformToUrl(path) {
|
15
|
+
const replacements = [
|
16
|
+
// Clean the url extensions
|
17
|
+
{ regex: /\.(ts|js|mjs|cjs)$/u, replacement: "" },
|
18
|
+
// Handle wild card based routes - users/[...id]/profile.ts -> users/*/profile
|
19
|
+
{ regex: /\[\.\.\..*\]/gu, replacement: "*" },
|
20
|
+
// Handle generic square bracket based routes - users/[id]/index.ts -> users/:id
|
21
|
+
{
|
22
|
+
regex: /\[(.*?)\]/gu,
|
23
|
+
replacement: (_, match) => `:${match}`,
|
24
|
+
},
|
25
|
+
// Handle the case when multiple parameters are present in one file
|
26
|
+
// users / [id] - [name].ts to users /: id -:name and users / [id] - [name] / [age].ts to users /: id -: name /: age
|
27
|
+
{ regex: /\]-\[/gu, replacement: "-:" },
|
28
|
+
{ regex: /\]\//gu, replacement: "/" },
|
29
|
+
{ regex: /\[/gu, replacement: "" },
|
30
|
+
{ regex: /\]/gu, replacement: "" },
|
31
|
+
// remove index from end of path
|
32
|
+
{ regex: /\/?index$/, replacement: "" },
|
33
|
+
];
|
34
|
+
let url = path;
|
35
|
+
for (const { regex, replacement } of replacements) {
|
36
|
+
url = url.replace(regex, replacement);
|
37
|
+
}
|
38
|
+
return "/" + url;
|
39
|
+
}
|
40
|
+
exports.transformToUrl = transformToUrl;
|
41
|
+
function getParamsCount(path) {
|
42
|
+
return path.match(/\[(.*?)\]/gu)?.length || 0;
|
43
|
+
}
|
44
|
+
// Is it necessary?..
|
45
|
+
// Sorts by the smallest parameters
|
46
|
+
function sortByNestedParams(routes) {
|
47
|
+
return routes.sort((a, b) => getParamsCount(a) - getParamsCount(b));
|
48
|
+
}
|
49
|
+
exports.sortByNestedParams = sortByNestedParams;
|
package/package.json
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"name": "elysia-autoload",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"author": "kravetsone",
|
5
|
+
"description": "Plugin for Elysia which autoload all routes in directory",
|
6
|
+
"keywords": [
|
7
|
+
"bun",
|
8
|
+
"elysia",
|
9
|
+
"autoimports",
|
10
|
+
"autoload",
|
11
|
+
"nextjs",
|
12
|
+
"filerouter",
|
13
|
+
"autoroutes"
|
14
|
+
],
|
15
|
+
"scripts": {
|
16
|
+
"prepublishOnly": "npm run lint:fix && tsc",
|
17
|
+
"lint": "eslint \"src/**/*.{ts,tsx,js,mjs,cjs}\"",
|
18
|
+
"lint:fix": "eslint \"src/**/*.{ts,tsx,js,mjs,cjs}\" --fix"
|
19
|
+
},
|
20
|
+
"devDependencies": {
|
21
|
+
"bun-types": "latest",
|
22
|
+
"eslint": "^8.41.0",
|
23
|
+
"eslint-kit": "^10.0.0",
|
24
|
+
"prettier": "^3.0.0"
|
25
|
+
},
|
26
|
+
"peerDependencies": {
|
27
|
+
"typescript": "^5.0.0",
|
28
|
+
"elysia": "^0.8.0"
|
29
|
+
},
|
30
|
+
"files": [
|
31
|
+
"dist"
|
32
|
+
]
|
33
|
+
}
|