elysia-autoload 1.2.1 → 1.4.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/README.md +10 -9
- package/dist/index.d.ts +10 -11
- package/dist/index.js +11 -12
- package/package.json +9 -10
package/README.md
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
Plugin for [Elysia](https://elysiajs.com/) which autoload all routes in directory and code-generate types for [Eden](https://elysiajs.com/eden/overview.html) with [`Bun.build`](#bun-build-usage) support!
|
4
4
|
|
5
|
-
**Currently, Eden types generation is broken!!**
|
6
|
-
|
7
5
|
## Installation
|
8
6
|
|
9
7
|
### Start new project with [create-elysiajs](https://github.com/kravetsone/create-elysiajs)
|
@@ -65,6 +63,9 @@ Guide how `elysia-autoload` match routes
|
|
65
63
|
└──index.ts
|
66
64
|
├── frontend
|
67
65
|
└──index.tsx // usage of tsx extension
|
66
|
+
├── events
|
67
|
+
└──(post).ts // post and get will not be in the link
|
68
|
+
└──(get).ts
|
68
69
|
└── users.ts
|
69
70
|
└── package.json
|
70
71
|
```
|
@@ -76,6 +77,8 @@ Guide how `elysia-autoload` match routes
|
|
76
77
|
- /routes/likes/[...].ts → /likes/\*
|
77
78
|
- /routes/domains/@[...]/index.ts → /domains/@\*
|
78
79
|
- /routes/frontend/index.tsx → /frontend
|
80
|
+
- /routes/events/(post).ts → /events
|
81
|
+
- /routes/events/(get).ts → /events
|
79
82
|
|
80
83
|
## Options
|
81
84
|
|
@@ -119,14 +122,14 @@ export type ElysiaApp = typeof app;
|
|
119
122
|
```ts
|
120
123
|
// client.ts
|
121
124
|
|
122
|
-
import {
|
125
|
+
import { treaty } from "@elysiajs/eden";
|
123
126
|
|
124
127
|
// Routes are a global type so you don't need to import it.
|
125
128
|
|
126
|
-
const app =
|
129
|
+
const app = treaty<Routes>("http://localhost:3002");
|
127
130
|
|
128
131
|
const { data } = await app.test["some-path-param"].get({
|
129
|
-
|
132
|
+
query: {
|
130
133
|
key: 2,
|
131
134
|
},
|
132
135
|
});
|
@@ -144,15 +147,13 @@ import type Route0 from "./routes/index";
|
|
144
147
|
import type Route1 from "./routes/test/[some]/index";
|
145
148
|
|
146
149
|
declare global {
|
147
|
-
export type Routes = ElysiaWithBaseUrl<"/api",
|
148
|
-
ElysiaWithBaseUrl<"/api/test/:some",
|
150
|
+
export type Routes = ElysiaWithBaseUrl<"/api", typeof Route0> &
|
151
|
+
ElysiaWithBaseUrl<"/api/test/:some", typeof Route1>;
|
149
152
|
}
|
150
153
|
```
|
151
154
|
|
152
155
|
Example of app with types code-generation you can see in [example](https://github.com/kravetsone/elysia-autoload/tree/main/example)
|
153
156
|
|
154
|
-
**Currently, Eden types generation is broken!!**
|
155
|
-
|
156
157
|
### [Bun build](https://bun.sh/docs/bundler) usage
|
157
158
|
|
158
159
|
You can use this plugin with [`Bun.build`](https://bun.sh/docs/bundler), thanks to [esbuild-plugin-autoload](https://github.com/kravetsone/esbuild-plugin-autoload)!
|
package/dist/index.d.ts
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
-
import Elysia, { RouteBase, LocalHook, InputSchema,
|
1
|
+
import Elysia, { RouteBase, RouteSchema, AnyElysia, LocalHook, InputSchema, SingletonBase, BaseMacro, Elysia as Elysia$1 } from 'elysia';
|
2
2
|
|
3
3
|
type PathToObject<Path extends string, Type extends RouteBase> = Path extends `${infer Head}/${infer Rest}` ? Head extends "" ? PathToObject<Rest, Type> : {
|
4
4
|
[K in Head]: PathToObject<Rest, Type>;
|
5
5
|
} : {
|
6
6
|
[K in Path]: Type;
|
7
7
|
};
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
}>;
|
8
|
+
declare namespace ElysiaMatch {
|
9
|
+
type RouteEnd = Record<string, RouteSchema>;
|
10
|
+
type Fx = (...args: any[]) => AnyElysia;
|
11
|
+
type All = AnyElysia | Fx;
|
12
|
+
type Extract<T extends All> = T extends Fx ? ReturnType<T> : T;
|
13
|
+
}
|
15
14
|
type FlattenIndexRoutes<T> = T extends object ? {
|
16
|
-
[K in keyof T as K extends "index" ? T[K] extends
|
15
|
+
[K in keyof T as K extends "index" ? T[K] extends ElysiaMatch.RouteEnd ? never : K : K]: FlattenIndexRoutes<T[K]>;
|
17
16
|
} & (T extends {
|
18
17
|
index: infer I;
|
19
|
-
} ? I extends
|
20
|
-
type ElysiaWithBaseUrl<BaseUrl extends string, ElysiaType extends
|
18
|
+
} ? I extends ElysiaMatch.RouteEnd ? FlattenIndexRoutes<I> : T : T) : T;
|
19
|
+
type ElysiaWithBaseUrl<BaseUrl extends string, ElysiaType extends ElysiaMatch.All> = ElysiaMatch.Extract<ElysiaType> extends Elysia<infer BasePath, infer Scoped, infer Singleton, infer Definitions, infer Metadata, infer Routes, infer Ephemeral, infer Volatile> ? Elysia<BasePath, Scoped, Singleton, Definitions, Metadata, FlattenIndexRoutes<PathToObject<BaseUrl, Routes>>, Ephemeral, Volatile> : never;
|
21
20
|
type SoftString<T extends string> = T | (string & {});
|
22
21
|
|
23
22
|
type SchemaHandler = ({ path, url, }: {
|
package/dist/index.js
CHANGED
@@ -3,8 +3,7 @@ import path from 'node:path';
|
|
3
3
|
import { Elysia } from 'elysia';
|
4
4
|
|
5
5
|
function getPath(dir) {
|
6
|
-
if (path.isAbsolute(dir))
|
7
|
-
return dir;
|
6
|
+
if (path.isAbsolute(dir)) return dir;
|
8
7
|
if (path.isAbsolute(process.argv[1]))
|
9
8
|
return path.join(process.argv[1], "..", dir);
|
10
9
|
return path.join(process.cwd(), process.argv[1], "..", dir);
|
@@ -22,6 +21,10 @@ function transformToUrl(path2) {
|
|
22
21
|
regex: /\[(.*?)\]/gu,
|
23
22
|
replacement: (_, match) => `:${match}`
|
24
23
|
},
|
24
|
+
{
|
25
|
+
regex: /\/?\((.*)\)/,
|
26
|
+
replacement: ""
|
27
|
+
},
|
25
28
|
// Handle the case when multiple parameters are present in one file
|
26
29
|
// users / [id] - [name].ts to users /: id -:name and users / [id] - [name] / [age].ts to users /: id -: name /: age
|
27
30
|
{ regex: /\]-\[/gu, replacement: "-:" },
|
@@ -44,13 +47,11 @@ function sortByNestedParams(routes) {
|
|
44
47
|
return routes.sort((a, b) => getParamsCount(a) - getParamsCount(b));
|
45
48
|
}
|
46
49
|
function fixSlashes(prefix) {
|
47
|
-
if (!prefix?.endsWith("/"))
|
48
|
-
return prefix;
|
50
|
+
if (!prefix?.endsWith("/")) return prefix;
|
49
51
|
return prefix.slice(0, -1);
|
50
52
|
}
|
51
53
|
function addRelativeIfNotDot(path2) {
|
52
|
-
if (path2.at(0) !== ".")
|
53
|
-
return `./${path2}`;
|
54
|
+
if (path2.at(0) !== ".") return `./${path2}`;
|
54
55
|
return path2;
|
55
56
|
}
|
56
57
|
|
@@ -102,8 +103,7 @@ async function autoload(options = {}) {
|
|
102
103
|
const fullPath = path.join(directoryPath, filePath);
|
103
104
|
const file = await import(fullPath);
|
104
105
|
const importName = typeof getImportName === "string" ? getImportName : getImportName(file);
|
105
|
-
if (!file[importName] && options?.skipImportErrors)
|
106
|
-
continue;
|
106
|
+
if (!file[importName] && options?.skipImportErrors) continue;
|
107
107
|
if (!file[importName])
|
108
108
|
throw new Error(`${filePath} don't provide export ${importName}`);
|
109
109
|
const url = transformToUrl(filePath);
|
@@ -115,14 +115,13 @@ async function autoload(options = {}) {
|
|
115
115
|
plugin.group(url, groupOptions, (app) => app.use(importedValue()));
|
116
116
|
if (importedValue instanceof Elysia)
|
117
117
|
plugin.group(url, groupOptions, (app) => app.use(importedValue));
|
118
|
-
if (types)
|
119
|
-
paths.push(fullPath.replace(directoryPath, ""));
|
118
|
+
if (types) paths.push([fullPath.replace(directoryPath, ""), importName]);
|
120
119
|
}
|
121
120
|
if (types) {
|
122
121
|
for await (const outputPath of types.output) {
|
123
122
|
const outputAbsolutePath = getPath(outputPath);
|
124
123
|
const imports = paths.map(
|
125
|
-
(x, index) => `import type Route${index} from "${addRelativeIfNotDot(
|
124
|
+
([x, exportName], index) => `import type ${exportName === "default" ? `Route${index}` : `{ ${exportName} as Route${index} }`} from "${addRelativeIfNotDot(
|
126
125
|
path.relative(
|
127
126
|
path.dirname(outputAbsolutePath),
|
128
127
|
directoryPath + x.replace(".ts", "").replace(".tsx", "")
|
@@ -137,7 +136,7 @@ async function autoload(options = {}) {
|
|
137
136
|
"",
|
138
137
|
!types.useExport ? "declare global {" : "",
|
139
138
|
` export type ${types.typeName} = ${paths.map(
|
140
|
-
(x, index) => `ElysiaWithBaseUrl<"${((prefix?.endsWith("/") ? prefix.slice(0, -1) : prefix) ?? "") + transformToUrl(x) || "/"}",
|
139
|
+
([x], index) => `ElysiaWithBaseUrl<"${((prefix?.endsWith("/") ? prefix.slice(0, -1) : prefix) ?? "") + transformToUrl(x) || "/"}", typeof Route${index}>`
|
141
140
|
).join("\n & ")}`,
|
142
141
|
!types.useExport ? "}" : ""
|
143
142
|
].join("\n")
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "elysia-autoload",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.4.0",
|
4
4
|
"author": "kravetsone",
|
5
5
|
"type": "module",
|
6
6
|
"types": "./dist/index.d.ts",
|
@@ -29,18 +29,17 @@
|
|
29
29
|
"scripts": {
|
30
30
|
"prepublishOnly": "bun test && bunx pkgroll",
|
31
31
|
"lint": "bunx @biomejs/biome check src",
|
32
|
-
"lint:fix": "bun lint --apply"
|
33
|
-
"prepare": "bunx husky"
|
32
|
+
"lint:fix": "bun lint --apply"
|
34
33
|
},
|
35
34
|
"files": ["dist"],
|
36
35
|
"devDependencies": {
|
37
|
-
"@biomejs/biome": "1.
|
38
|
-
"@elysiajs/eden": "^1.1.
|
39
|
-
"@elysiajs/swagger": "^1.1.
|
40
|
-
"@types/bun": "^1.1.
|
41
|
-
"elysia": "^1.1.
|
42
|
-
"pkgroll": "^2.
|
43
|
-
"typescript": "^5.
|
36
|
+
"@biomejs/biome": "1.9.2",
|
37
|
+
"@elysiajs/eden": "^1.1.3",
|
38
|
+
"@elysiajs/swagger": "^1.1.1",
|
39
|
+
"@types/bun": "^1.1.9",
|
40
|
+
"elysia": "^1.1.13",
|
41
|
+
"pkgroll": "^2.5.0",
|
42
|
+
"typescript": "^5.6.2"
|
44
43
|
},
|
45
44
|
"peerDependencies": {
|
46
45
|
"elysia": "^1.1.0"
|