elysia-autoload 1.0.1 → 1.2.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 +24 -3
- package/dist/index.d.ts +46 -13
- package/dist/index.js +46 -33
- package/package.json +46 -44
- package/dist/index.cjs +0 -176
- package/dist/index.d.cts +0 -47
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# elysia-autoload
|
2
2
|
|
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`](
|
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
5
|
**Currently, Eden types generation is broken!!**
|
6
6
|
|
@@ -153,9 +153,9 @@ Example of app with types code-generation you can see in [example](https://githu
|
|
153
153
|
|
154
154
|
**Currently, Eden types generation is broken!!**
|
155
155
|
|
156
|
-
### Bun build usage
|
156
|
+
### [Bun build](https://bun.sh/docs/bundler) usage
|
157
157
|
|
158
|
-
You can use this plugin with `Bun.build
|
158
|
+
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)!
|
159
159
|
|
160
160
|
```ts
|
161
161
|
// @filename: build.ts
|
@@ -163,6 +163,7 @@ import { autoload } from "esbuild-plugin-autoload"; // default import also suppo
|
|
163
163
|
|
164
164
|
await Bun.build({
|
165
165
|
entrypoints: ["src/index.ts"],
|
166
|
+
target: "bun",
|
166
167
|
outdir: "out",
|
167
168
|
plugins: [autoload()],
|
168
169
|
}).then(console.log);
|
@@ -170,6 +171,26 @@ await Bun.build({
|
|
170
171
|
|
171
172
|
Then, build it with `bun build.ts` and run with `bun out/index.ts`.
|
172
173
|
|
174
|
+
### [Bun compile](https://bun.sh/docs/bundler/executables) usage
|
175
|
+
|
176
|
+
You can bundle and then compile it into a [single executable binary file](https://bun.sh/docs/bundler/executables)
|
177
|
+
|
178
|
+
```ts
|
179
|
+
import { autoload } from "esbuild-plugin-autoload"; // default import also supported
|
180
|
+
|
181
|
+
await Bun.build({
|
182
|
+
entrypoints: ["src/index.ts"],
|
183
|
+
target: "bun",
|
184
|
+
outdir: "out",
|
185
|
+
plugins: [autoload()],
|
186
|
+
}).then(console.log);
|
187
|
+
|
188
|
+
await Bun.$`bun build --compile out/index.js`;
|
189
|
+
```
|
190
|
+
|
191
|
+
> [!WARNING]
|
192
|
+
> You cannot use it in `bun build --compile` mode without extra step ([Feature issue](https://github.com/oven-sh/bun/issues/11895))
|
193
|
+
|
173
194
|
[Read more](https://github.com/kravetsone/esbuild-plugin-autoload)
|
174
195
|
|
175
196
|
### Usage of schema handler
|
package/dist/index.d.ts
CHANGED
@@ -1,29 +1,61 @@
|
|
1
|
-
import Elysia, { RouteBase,
|
2
|
-
import { BaseMacro } from 'elysia/dist/types';
|
1
|
+
import Elysia, { RouteBase, LocalHook, InputSchema, RouteSchema, SingletonBase, BaseMacro, Elysia as Elysia$1 } from 'elysia';
|
3
2
|
|
4
|
-
type
|
5
|
-
|
6
|
-
|
3
|
+
type PathToObject<Path extends string, Type extends RouteBase> = Path extends `${infer Head}/${infer Rest}` ? Head extends "" ? PathToObject<Rest, Type> : {
|
4
|
+
[K in Head]: PathToObject<Rest, Type>;
|
5
|
+
} : {
|
6
|
+
[K in Path]: Type;
|
7
7
|
};
|
8
|
-
type
|
8
|
+
type RouteEndType = Record<string, {
|
9
|
+
body: any;
|
10
|
+
params: any;
|
11
|
+
query: any;
|
12
|
+
headers: any;
|
13
|
+
response: any;
|
14
|
+
}>;
|
15
|
+
type FlattenIndexRoutes<T> = T extends object ? {
|
16
|
+
[K in keyof T as K extends "index" ? T[K] extends RouteEndType ? never : K : K]: FlattenIndexRoutes<T[K]>;
|
17
|
+
} & (T extends {
|
18
|
+
index: infer I;
|
19
|
+
} ? I extends RouteEndType ? FlattenIndexRoutes<I> : {} : {}) : T;
|
20
|
+
type ElysiaWithBaseUrl<BaseUrl extends string, ElysiaType extends Elysia<any, any, any, any, any, any, any, any>> = 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
|
+
type SoftString<T extends string> = T | (string & {});
|
9
22
|
|
10
|
-
type
|
23
|
+
type SchemaHandler = ({ path, url, }: {
|
11
24
|
path: string;
|
12
25
|
url: string;
|
13
26
|
}) => LocalHook<InputSchema, RouteSchema, SingletonBase, Record<string, Error>, BaseMacro, "">;
|
14
|
-
interface
|
27
|
+
interface TypesOptions {
|
15
28
|
output?: string | string[];
|
16
29
|
typeName?: string;
|
17
30
|
useExport?: boolean;
|
18
31
|
}
|
19
|
-
interface
|
32
|
+
interface AutoloadOptions {
|
20
33
|
pattern?: string;
|
21
34
|
dir?: string;
|
22
35
|
prefix?: string;
|
23
|
-
schema?:
|
24
|
-
types?:
|
36
|
+
schema?: SchemaHandler;
|
37
|
+
types?: TypesOptions | true;
|
38
|
+
/**
|
39
|
+
* Throws an error if no matches are found.
|
40
|
+
* @default true
|
41
|
+
*/
|
42
|
+
failGlob?: boolean;
|
43
|
+
/**
|
44
|
+
* import a specific `export` from a file
|
45
|
+
* @example import first export
|
46
|
+
* ```ts
|
47
|
+
* import: (file) => Object.keys(file).at(0) || "default",
|
48
|
+
* ```
|
49
|
+
* @default "default"
|
50
|
+
*/
|
51
|
+
import?: SoftString<"default"> | ((file: any) => string);
|
52
|
+
/**
|
53
|
+
* Skip imports where needed `export` not defined
|
54
|
+
* @default false
|
55
|
+
*/
|
56
|
+
skipImportErrors?: boolean;
|
25
57
|
}
|
26
|
-
declare function autoload(options?:
|
58
|
+
declare function autoload(options?: AutoloadOptions): Promise<Elysia$1<string, false, {
|
27
59
|
decorator: {};
|
28
60
|
store: {};
|
29
61
|
derive: {};
|
@@ -34,6 +66,7 @@ declare function autoload(options?: IAutoloadOptions): Promise<Elysia$1<string,
|
|
34
66
|
}, {
|
35
67
|
schema: {};
|
36
68
|
macro: {};
|
69
|
+
macroFn: {};
|
37
70
|
}, {}, {
|
38
71
|
derive: {};
|
39
72
|
resolve: {};
|
@@ -44,4 +77,4 @@ declare function autoload(options?: IAutoloadOptions): Promise<Elysia$1<string,
|
|
44
77
|
schema: {};
|
45
78
|
}>>;
|
46
79
|
|
47
|
-
export { type ElysiaWithBaseUrl, type
|
80
|
+
export { type AutoloadOptions, type ElysiaWithBaseUrl, type SchemaHandler, type SoftString, type TypesOptions, autoload };
|
package/dist/index.js
CHANGED
@@ -1,12 +1,7 @@
|
|
1
|
-
|
2
|
-
import
|
3
|
-
import
|
4
|
-
import {
|
5
|
-
Elysia
|
6
|
-
} from "elysia";
|
1
|
+
import fs from 'node:fs';
|
2
|
+
import path from 'node:path';
|
3
|
+
import { Elysia } from 'elysia';
|
7
4
|
|
8
|
-
// src/utils.ts
|
9
|
-
import path from "node:path";
|
10
5
|
function getPath(dir) {
|
11
6
|
if (path.isAbsolute(dir))
|
12
7
|
return dir;
|
@@ -14,7 +9,7 @@ function getPath(dir) {
|
|
14
9
|
return path.join(process.argv[1], "..", dir);
|
15
10
|
return path.join(process.cwd(), process.argv[1], "..", dir);
|
16
11
|
}
|
17
|
-
function transformToUrl(
|
12
|
+
function transformToUrl(path2) {
|
18
13
|
const replacements = [
|
19
14
|
// Clean the url extensions
|
20
15
|
{ regex: /\.(ts|tsx|js|jsx|mjs|cjs)$/u, replacement: "" },
|
@@ -36,14 +31,14 @@ function transformToUrl(path3) {
|
|
36
31
|
// remove index from end of path
|
37
32
|
{ regex: /\/?index$/, replacement: "" }
|
38
33
|
];
|
39
|
-
let url =
|
34
|
+
let url = path2;
|
40
35
|
for (const { regex, replacement } of replacements) {
|
41
36
|
url = url.replace(regex, replacement);
|
42
37
|
}
|
43
38
|
return url;
|
44
39
|
}
|
45
|
-
function getParamsCount(
|
46
|
-
return
|
40
|
+
function getParamsCount(path2) {
|
41
|
+
return path2.match(/\[(.*?)\]/gu)?.length || 0;
|
47
42
|
}
|
48
43
|
function sortByNestedParams(routes) {
|
49
44
|
return routes.sort((a, b) => getParamsCount(a) - getParamsCount(b));
|
@@ -53,30 +48,30 @@ function fixSlashes(prefix) {
|
|
53
48
|
return prefix;
|
54
49
|
return prefix.slice(0, -1);
|
55
50
|
}
|
56
|
-
function addRelativeIfNotDot(
|
57
|
-
if (
|
58
|
-
return `./${
|
59
|
-
return
|
51
|
+
function addRelativeIfNotDot(path2) {
|
52
|
+
if (path2.at(0) !== ".")
|
53
|
+
return `./${path2}`;
|
54
|
+
return path2;
|
60
55
|
}
|
61
56
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
var TYPES_OBJECT_DEFAULT = {
|
57
|
+
const DIR_ROUTES_DEFAULT = "./routes";
|
58
|
+
const TYPES_OUTPUT_DEFAULT = "./routes-types.ts";
|
59
|
+
const TYPES_TYPENAME_DEFAULT = "Routes";
|
60
|
+
const TYPES_OBJECT_DEFAULT = {
|
67
61
|
output: [TYPES_OUTPUT_DEFAULT],
|
68
62
|
typeName: TYPES_TYPENAME_DEFAULT
|
69
63
|
};
|
70
64
|
async function autoload(options = {}) {
|
71
|
-
const fileSources = {};
|
72
65
|
const { pattern, prefix, schema } = options;
|
66
|
+
const failGlob = options.failGlob ?? true;
|
67
|
+
const getImportName = options?.import ?? "default";
|
73
68
|
const dir = options.dir ?? DIR_ROUTES_DEFAULT;
|
74
|
-
const types = options.types
|
69
|
+
const types = options.types ? options.types !== true ? {
|
75
70
|
...TYPES_OBJECT_DEFAULT,
|
76
71
|
...options.types,
|
77
72
|
// This code allows you to omit the output data or specify it as an string[] or string.
|
78
73
|
output: !options.types.output ? [TYPES_OUTPUT_DEFAULT] : Array.isArray(options.types.output) ? options.types.output : [options.types.output]
|
79
|
-
} : TYPES_OBJECT_DEFAULT;
|
74
|
+
} : TYPES_OBJECT_DEFAULT : false;
|
80
75
|
const directoryPath = getPath(dir);
|
81
76
|
if (!fs.existsSync(directoryPath))
|
82
77
|
throw new Error(`Directory ${directoryPath} doesn't exists`);
|
@@ -98,15 +93,34 @@ async function autoload(options = {}) {
|
|
98
93
|
cwd: directoryPath
|
99
94
|
})
|
100
95
|
);
|
96
|
+
if (failGlob && files.length === 0)
|
97
|
+
throw new Error(
|
98
|
+
`No matches found in ${directoryPath}. You can disable this error by setting the failGlob parameter to false in the options of autoload plugin`
|
99
|
+
);
|
101
100
|
const paths = [];
|
102
101
|
for await (const filePath of sortByNestedParams(files)) {
|
103
|
-
const fullPath =
|
102
|
+
const fullPath = path.join(directoryPath, filePath);
|
104
103
|
const file = await import(fullPath);
|
105
|
-
|
106
|
-
|
104
|
+
const importName = typeof getImportName === "string" ? getImportName : getImportName(file);
|
105
|
+
if (!file[importName] && options?.skipImportErrors)
|
106
|
+
continue;
|
107
|
+
if (!file[importName])
|
108
|
+
throw new Error(`${filePath} don't provide export ${importName}`);
|
107
109
|
const url = transformToUrl(filePath);
|
108
110
|
const groupOptions = schema ? schema({ path: filePath, url }) : {};
|
109
|
-
|
111
|
+
const importedValue = file[importName];
|
112
|
+
console.log(
|
113
|
+
importedValue.toString(),
|
114
|
+
importedValue.length,
|
115
|
+
typeof importedValue === "function" && !importedValue.length,
|
116
|
+
importedValue instanceof Elysia
|
117
|
+
);
|
118
|
+
if (typeof importedValue === "function" && importedValue.length)
|
119
|
+
plugin.group(url, groupOptions, importedValue);
|
120
|
+
if (typeof importedValue === "function" && !importedValue.length)
|
121
|
+
plugin.group(url, groupOptions, (app) => app.use(importedValue()));
|
122
|
+
if (importedValue instanceof Elysia)
|
123
|
+
plugin.group(url, groupOptions, (app) => app.use(importedValue));
|
110
124
|
if (types)
|
111
125
|
paths.push(fullPath.replace(directoryPath, ""));
|
112
126
|
}
|
@@ -115,8 +129,8 @@ async function autoload(options = {}) {
|
|
115
129
|
const outputAbsolutePath = getPath(outputPath);
|
116
130
|
const imports = paths.map(
|
117
131
|
(x, index) => `import type Route${index} from "${addRelativeIfNotDot(
|
118
|
-
|
119
|
-
|
132
|
+
path.relative(
|
133
|
+
path.dirname(outputAbsolutePath),
|
120
134
|
directoryPath + x.replace(".ts", "").replace(".tsx", "")
|
121
135
|
).replace(/\\/gu, "/")
|
122
136
|
)}";`
|
@@ -138,6 +152,5 @@ async function autoload(options = {}) {
|
|
138
152
|
}
|
139
153
|
return plugin;
|
140
154
|
}
|
141
|
-
|
142
|
-
|
143
|
-
};
|
155
|
+
|
156
|
+
export { autoload };
|
package/package.json
CHANGED
@@ -1,46 +1,48 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
2
|
+
"name": "elysia-autoload",
|
3
|
+
"version": "1.2.0",
|
4
|
+
"author": "kravetsone",
|
5
|
+
"type": "module",
|
6
|
+
"types": "./dist/index.d.ts",
|
7
|
+
"module": "./dist/index.js",
|
8
|
+
"exports": {
|
9
|
+
".": {
|
10
|
+
"types": "./dist/index.d.ts",
|
11
|
+
"import": "./dist/index.js"
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"description": "Plugin for Elysia which autoload all routes in directory and code-generate types for Eden with Bun.build support",
|
15
|
+
"homepage": "https://github.com/kravetsone/elysia-autoload",
|
16
|
+
"keywords": [
|
17
|
+
"bun",
|
18
|
+
"elysia",
|
19
|
+
"autoimports",
|
20
|
+
"autoload",
|
21
|
+
"nextjs",
|
22
|
+
"filerouter",
|
23
|
+
"autoroutes",
|
24
|
+
"eden",
|
25
|
+
"treaty",
|
26
|
+
"trpc",
|
27
|
+
"codegeneration"
|
28
|
+
],
|
29
|
+
"scripts": {
|
30
|
+
"prepublishOnly": "bun test && bunx pkgroll",
|
31
|
+
"lint": "bunx @biomejs/biome check src",
|
32
|
+
"lint:fix": "bun lint --apply",
|
33
|
+
"prepare": "bunx husky"
|
34
|
+
},
|
35
|
+
"files": ["dist"],
|
36
|
+
"devDependencies": {
|
37
|
+
"@biomejs/biome": "1.8.3",
|
38
|
+
"@elysiajs/eden": "^1.1.0",
|
39
|
+
"@elysiajs/swagger": "^1.1.0",
|
40
|
+
"@types/bun": "^1.1.6",
|
41
|
+
"elysia": "^1.1.2",
|
42
|
+
"pkgroll": "^2.1.1",
|
43
|
+
"typescript": "^5.5.3"
|
44
|
+
},
|
45
|
+
"peerDependencies": {
|
46
|
+
"elysia": "^1.1.0"
|
47
|
+
}
|
46
48
|
}
|
package/dist/index.cjs
DELETED
@@ -1,176 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __create = Object.create;
|
3
|
-
var __defProp = Object.defineProperty;
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
8
|
-
var __export = (target, all) => {
|
9
|
-
for (var name in all)
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
11
|
-
};
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
14
|
-
for (let key of __getOwnPropNames(from))
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
17
|
-
}
|
18
|
-
return to;
|
19
|
-
};
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
26
|
-
mod
|
27
|
-
));
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
29
|
-
|
30
|
-
// src/index.ts
|
31
|
-
var src_exports = {};
|
32
|
-
__export(src_exports, {
|
33
|
-
autoload: () => autoload
|
34
|
-
});
|
35
|
-
module.exports = __toCommonJS(src_exports);
|
36
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
37
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
38
|
-
var import_elysia = require("elysia");
|
39
|
-
|
40
|
-
// src/utils.ts
|
41
|
-
var import_node_path = __toESM(require("path"), 1);
|
42
|
-
function getPath(dir) {
|
43
|
-
if (import_node_path.default.isAbsolute(dir))
|
44
|
-
return dir;
|
45
|
-
if (import_node_path.default.isAbsolute(process.argv[1]))
|
46
|
-
return import_node_path.default.join(process.argv[1], "..", dir);
|
47
|
-
return import_node_path.default.join(process.cwd(), process.argv[1], "..", dir);
|
48
|
-
}
|
49
|
-
function transformToUrl(path3) {
|
50
|
-
const replacements = [
|
51
|
-
// Clean the url extensions
|
52
|
-
{ regex: /\.(ts|tsx|js|jsx|mjs|cjs)$/u, replacement: "" },
|
53
|
-
// Fix windows slashes
|
54
|
-
{ regex: /\\/gu, replacement: "/" },
|
55
|
-
// Handle wild card based routes - users/[...id]/profile.ts -> users/*/profile
|
56
|
-
{ regex: /\[\.\.\..*\]/gu, replacement: "*" },
|
57
|
-
// Handle generic square bracket based routes - users/[id]/index.ts -> users/:id
|
58
|
-
{
|
59
|
-
regex: /\[(.*?)\]/gu,
|
60
|
-
replacement: (_, match) => `:${match}`
|
61
|
-
},
|
62
|
-
// Handle the case when multiple parameters are present in one file
|
63
|
-
// users / [id] - [name].ts to users /: id -:name and users / [id] - [name] / [age].ts to users /: id -: name /: age
|
64
|
-
{ regex: /\]-\[/gu, replacement: "-:" },
|
65
|
-
{ regex: /\]\//gu, replacement: "/" },
|
66
|
-
{ regex: /\[/gu, replacement: "" },
|
67
|
-
{ regex: /\]/gu, replacement: "" },
|
68
|
-
// remove index from end of path
|
69
|
-
{ regex: /\/?index$/, replacement: "" }
|
70
|
-
];
|
71
|
-
let url = path3;
|
72
|
-
for (const { regex, replacement } of replacements) {
|
73
|
-
url = url.replace(regex, replacement);
|
74
|
-
}
|
75
|
-
return url;
|
76
|
-
}
|
77
|
-
function getParamsCount(path3) {
|
78
|
-
return path3.match(/\[(.*?)\]/gu)?.length || 0;
|
79
|
-
}
|
80
|
-
function sortByNestedParams(routes) {
|
81
|
-
return routes.sort((a, b) => getParamsCount(a) - getParamsCount(b));
|
82
|
-
}
|
83
|
-
function fixSlashes(prefix) {
|
84
|
-
if (!prefix?.endsWith("/"))
|
85
|
-
return prefix;
|
86
|
-
return prefix.slice(0, -1);
|
87
|
-
}
|
88
|
-
function addRelativeIfNotDot(path3) {
|
89
|
-
if (path3.at(0) !== ".")
|
90
|
-
return `./${path3}`;
|
91
|
-
return path3;
|
92
|
-
}
|
93
|
-
|
94
|
-
// src/index.ts
|
95
|
-
var DIR_ROUTES_DEFAULT = "./routes";
|
96
|
-
var TYPES_OUTPUT_DEFAULT = "./routes-types.ts";
|
97
|
-
var TYPES_TYPENAME_DEFAULT = "Routes";
|
98
|
-
var TYPES_OBJECT_DEFAULT = {
|
99
|
-
output: [TYPES_OUTPUT_DEFAULT],
|
100
|
-
typeName: TYPES_TYPENAME_DEFAULT
|
101
|
-
};
|
102
|
-
async function autoload(options = {}) {
|
103
|
-
const fileSources = {};
|
104
|
-
const { pattern, prefix, schema } = options;
|
105
|
-
const dir = options.dir ?? DIR_ROUTES_DEFAULT;
|
106
|
-
const types = options.types && options.types !== true ? {
|
107
|
-
...TYPES_OBJECT_DEFAULT,
|
108
|
-
...options.types,
|
109
|
-
// This code allows you to omit the output data or specify it as an string[] or string.
|
110
|
-
output: !options.types.output ? [TYPES_OUTPUT_DEFAULT] : Array.isArray(options.types.output) ? options.types.output : [options.types.output]
|
111
|
-
} : TYPES_OBJECT_DEFAULT;
|
112
|
-
const directoryPath = getPath(dir);
|
113
|
-
if (!import_node_fs.default.existsSync(directoryPath))
|
114
|
-
throw new Error(`Directory ${directoryPath} doesn't exists`);
|
115
|
-
if (!import_node_fs.default.statSync(directoryPath).isDirectory())
|
116
|
-
throw new Error(`${directoryPath} isn't a directory`);
|
117
|
-
const plugin = new import_elysia.Elysia({
|
118
|
-
name: "elysia-autoload",
|
119
|
-
prefix: fixSlashes(prefix),
|
120
|
-
seed: {
|
121
|
-
pattern,
|
122
|
-
dir,
|
123
|
-
prefix,
|
124
|
-
types
|
125
|
-
}
|
126
|
-
});
|
127
|
-
const glob = new Bun.Glob(pattern || "**/*.{ts,tsx,js,jsx,mjs,cjs}");
|
128
|
-
const files = await Array.fromAsync(
|
129
|
-
glob.scan({
|
130
|
-
cwd: directoryPath
|
131
|
-
})
|
132
|
-
);
|
133
|
-
const paths = [];
|
134
|
-
for await (const filePath of sortByNestedParams(files)) {
|
135
|
-
const fullPath = import_node_path2.default.join(directoryPath, filePath);
|
136
|
-
const file = await import(fullPath);
|
137
|
-
if (!file.default)
|
138
|
-
throw new Error(`${filePath} doesn't provide default export`);
|
139
|
-
const url = transformToUrl(filePath);
|
140
|
-
const groupOptions = schema ? schema({ path: filePath, url }) : {};
|
141
|
-
plugin.group(url, groupOptions, file.default);
|
142
|
-
if (types)
|
143
|
-
paths.push(fullPath.replace(directoryPath, ""));
|
144
|
-
}
|
145
|
-
if (types) {
|
146
|
-
for await (const outputPath of types.output) {
|
147
|
-
const outputAbsolutePath = getPath(outputPath);
|
148
|
-
const imports = paths.map(
|
149
|
-
(x, index) => `import type Route${index} from "${addRelativeIfNotDot(
|
150
|
-
import_node_path2.default.relative(
|
151
|
-
import_node_path2.default.dirname(outputAbsolutePath),
|
152
|
-
directoryPath + x.replace(".ts", "").replace(".tsx", "")
|
153
|
-
).replace(/\\/gu, "/")
|
154
|
-
)}";`
|
155
|
-
);
|
156
|
-
await Bun.write(
|
157
|
-
outputAbsolutePath,
|
158
|
-
[
|
159
|
-
`import type { ElysiaWithBaseUrl } from "elysia-autoload";`,
|
160
|
-
imports.join("\n"),
|
161
|
-
"",
|
162
|
-
!types.useExport ? "declare global {" : "",
|
163
|
-
` export type ${types.typeName} = ${paths.map(
|
164
|
-
(x, index) => `ElysiaWithBaseUrl<"${((prefix?.endsWith("/") ? prefix.slice(0, -1) : prefix) ?? "") + transformToUrl(x) || "/"}", ReturnType<typeof Route${index}>>`
|
165
|
-
).join("\n & ")}`,
|
166
|
-
!types.useExport ? "}" : ""
|
167
|
-
].join("\n")
|
168
|
-
);
|
169
|
-
}
|
170
|
-
}
|
171
|
-
return plugin;
|
172
|
-
}
|
173
|
-
// Annotate the CommonJS export names for ESM import in node:
|
174
|
-
0 && (module.exports = {
|
175
|
-
autoload
|
176
|
-
});
|
package/dist/index.d.cts
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
import Elysia, { RouteBase, Elysia as Elysia$1, LocalHook, InputSchema, RouteSchema, SingletonBase } from 'elysia';
|
2
|
-
import { BaseMacro } from 'elysia/dist/types';
|
3
|
-
|
4
|
-
type RemoveLastChar<T extends string> = T extends `${infer V}/` ? V : T;
|
5
|
-
type RoutesWithPrefix<Routes extends RouteBase, Prefix extends string> = {
|
6
|
-
[K in keyof Routes as `${Prefix}${RemoveLastChar<K & string>}`]: Routes[K];
|
7
|
-
};
|
8
|
-
type ElysiaWithBaseUrl<BaseUrl extends string, ElysiaType extends Elysia<any, any, any, any, any, any, any, any>> = 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, RoutesWithPrefix<Routes, BaseUrl>, Ephemeral, Volatile> : never;
|
9
|
-
|
10
|
-
type TSchemaHandler = ({ path, url, }: {
|
11
|
-
path: string;
|
12
|
-
url: string;
|
13
|
-
}) => LocalHook<InputSchema, RouteSchema, SingletonBase, Record<string, Error>, BaseMacro, "">;
|
14
|
-
interface ITypesOptions {
|
15
|
-
output?: string | string[];
|
16
|
-
typeName?: string;
|
17
|
-
useExport?: boolean;
|
18
|
-
}
|
19
|
-
interface IAutoloadOptions {
|
20
|
-
pattern?: string;
|
21
|
-
dir?: string;
|
22
|
-
prefix?: string;
|
23
|
-
schema?: TSchemaHandler;
|
24
|
-
types?: ITypesOptions | true;
|
25
|
-
}
|
26
|
-
declare function autoload(options?: IAutoloadOptions): Promise<Elysia$1<string, false, {
|
27
|
-
decorator: {};
|
28
|
-
store: {};
|
29
|
-
derive: {};
|
30
|
-
resolve: {};
|
31
|
-
}, {
|
32
|
-
type: {};
|
33
|
-
error: {};
|
34
|
-
}, {
|
35
|
-
schema: {};
|
36
|
-
macro: {};
|
37
|
-
}, {}, {
|
38
|
-
derive: {};
|
39
|
-
resolve: {};
|
40
|
-
schema: {};
|
41
|
-
}, {
|
42
|
-
derive: {};
|
43
|
-
resolve: {};
|
44
|
-
schema: {};
|
45
|
-
}>>;
|
46
|
-
|
47
|
-
export { type ElysiaWithBaseUrl, type IAutoloadOptions, type ITypesOptions, autoload };
|