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 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
@@ -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;
@@ -0,0 +1,3 @@
1
+ export declare function getPath(dir: string): string;
2
+ export declare function transformToUrl(path: string): string;
3
+ export declare function sortByNestedParams(routes: string[]): string[];
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
+ }