orpc-file-based-router 0.1.0 → 0.1.2

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  # orpc-file-based-router
2
2
 
3
- A plugin for [oRPC](https://orpc.unnoq.com) that automatically creates an oRPC router configuration based on your file
4
- structure, similar to Next.js, express-file-routing
3
+ A plugin for [oRPC](https://orpc.unnoq.com) that automatically generates an oRPC router configuration based on your file
4
+ structure, inspired by Next.js and express-file-routing approaches.
5
5
 
6
- ## Highlights
6
+ ## Highlights
7
7
 
8
- - 📁 **File-based structure**: Organize your API endpoints intuitively through your filesystem
9
- - 🔄 **Zero configuration**: Generate routes automatically based on your directory structure
10
- - ⚡️ **Development speed**: Eliminate boilerplate code and reduce maintenance overhead
11
- - 🔍 **Dynamic routing**: Support for path parameters using `{param}` syntax in file names
12
- - 📑 **Index handling**: Support for index routes via `index.ts` files
8
+ - 📁 **File-based Structure**: Organize your API endpoints intuitively through your filesystem
9
+ - 🔄 **Zero Configuration**: Generate routes automatically based on your directory structure
10
+ - ⚡️ **Development Speed**: Eliminate boilerplate code and reduce maintenance overhead
11
+ - 🔍 **Dynamic Routing**: Support for path parameters using `{param}` syntax in file names
12
+ - 📑 **Index Routes**: Support for index routes via `index.ts` files
13
13
 
14
14
  > ⚠️ **IMPORTANT:** At this time, the plugin's functionality is only guaranteed
15
15
  > in nodejs runtime
@@ -62,21 +62,35 @@ const router = await createRouter(routesDir);
62
62
  const handler = new RPCHandler(router);
63
63
 
64
64
  ```
65
- > **Note:** If your environment doesn't support top-level await, wrap your server startup code in an async function:
66
- > ```typescript
67
- > async function startServer() {
68
- > const router = await createRouter(routesDir);
69
- > const handler = new RPCHandler(router);
70
- > // ... start your server
71
- > }
72
- > startServer();
73
- > ```
65
+ > **Note:** If your environment doesn't support top-level await, just use `cachedRouter` for example in expressjs it could be:
66
+ ```typescript
67
+ import { RPCHandler } from "@orpc/server/node";
68
+ import { cachedRouter } from "orpc-file-based-router";
69
+
70
+ const routesDir = new URL("./routes", import.meta.url).pathname;
71
+ const router = cachedRouter(routesDir)
74
72
 
75
- ## Type-Safe Client Configuration (Optional)
73
+ app.use('/rpc{/*path}', async (req, res, next) => {
76
74
 
77
- If you plan to use [oRPC client](https://orpc.unnoq.com/docs/client/client-side), you can set up automatic configuration generation, which can be used for client typing.
75
+ const handler = new RPCHandler(await router.getRouter());
76
+
77
+ const { matched } = await handler.handle(req, res, {
78
+ prefix: '/rpc',
79
+ })
80
+
81
+ if (matched) {
82
+ return
83
+ }
84
+
85
+ next()
86
+ })
87
+ ```
78
88
 
79
- 1. Add the following code to your main server file (e.g., `server.ts` or `main.ts`) or anywhere else. This will automatically regenerate the router configuration each time your server starts:
89
+ ## 🔒 Type-Safe Client Configuration (Optional)
90
+
91
+ For users of the [oRPC client](https://orpc.unnoq.com/docs/client/client-side), we provide automatic configuration generation for enhanced type safety and improved developer experience.
92
+
93
+ 1. Add the following code to your main server file (e.g., `server.ts` or `main.ts`). This will automatically regenerate the router configuration each time your server starts:
80
94
 
81
95
  ```typescript
82
96
  import { generateRouter } from "orpc-file-based-router";
@@ -121,6 +135,16 @@ const client: RouterClient<typeof router> = createORPCClient(link)
121
135
 
122
136
  ```
123
137
 
124
- ## License
138
+ ## 🛠 Configuration Options
139
+
140
+ When using `generateRouter`, you can provide additional options to customize the output:
141
+
142
+ | Field | Type | Required | Default Value | Description |
143
+ |-------------------|----------|--------------|-----------------------|------------------------------------------------------------------------------------------------------------------------------|
144
+ | `importExtension` | string | false | `""`(No extension) | File extension to append to import statements in the generated router. Useful when your build setup requires specific extensions. <br>Example: `.js` → `import { me } from "./routes/auth/me.js"` |
145
+
146
+
147
+
148
+ ## 📄 License
125
149
 
126
- MIT
150
+ MIT License - feel free to use this in your own projects!
package/dist/index.cjs CHANGED
@@ -36,6 +36,17 @@ async function createRouter(routesDir) {
36
36
  return r.exports[e].route({ path: `${r.path}` });
37
37
  });
38
38
  }
39
+ async function cachedRouter(routesDir) {
40
+ let router = null;
41
+ return {
42
+ getRouter: async () => {
43
+ if (!router) {
44
+ router = await createRouter(routesDir);
45
+ }
46
+ return router;
47
+ }
48
+ };
49
+ }
39
50
  async function generateRouter(routesDir, outputFile, options) {
40
51
  const files = walkTree(
41
52
  routesDir
@@ -43,7 +54,7 @@ async function generateRouter(routesDir, outputFile, options) {
43
54
  const exports = await generateRoutes(files);
44
55
  const importPaths = exports.map((x) => path.relative(path.dirname(outputFile), routesDir).concat(x.path));
45
56
  const content = buildRouter(exports, (r, e) => {
46
- return `${e}.route({ path: '${r.path}' })`;
57
+ return `${e}.route({ path: '${r.path.replace(/\/{0,1}index$/, "")}' })`;
47
58
  });
48
59
  let routerContent = `// This file is auto-generated
49
60
 
@@ -120,5 +131,6 @@ async function generateRoutes(files) {
120
131
  return routes;
121
132
  }
122
133
 
134
+ exports.cachedRouter = cachedRouter;
123
135
  exports.createRouter = createRouter;
124
136
  exports.generateRouter = generateRouter;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,17 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
+ declare function cachedRouter(routesDir: string): Promise<{
3
+ getRouter: () => Promise<Router>;
4
+ }>;
2
5
  type GeneratorOptions = {
6
+ /**
7
+ * File extension to append to import statements in the generated router.
8
+ * Useful when your build setup requires specific extensions.
9
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
10
+ * @default "" (no extension)
11
+ */
3
12
  importExtension?: string;
4
13
  };
5
14
  declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
6
15
  type Router = Record<string, any>;
7
16
 
8
- export { createRouter, generateRouter };
17
+ export { cachedRouter, createRouter, generateRouter };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,17 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
+ declare function cachedRouter(routesDir: string): Promise<{
3
+ getRouter: () => Promise<Router>;
4
+ }>;
2
5
  type GeneratorOptions = {
6
+ /**
7
+ * File extension to append to import statements in the generated router.
8
+ * Useful when your build setup requires specific extensions.
9
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
10
+ * @default "" (no extension)
11
+ */
3
12
  importExtension?: string;
4
13
  };
5
14
  declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
6
15
  type Router = Record<string, any>;
7
16
 
8
- export { createRouter, generateRouter };
17
+ export { cachedRouter, createRouter, generateRouter };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,17 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
+ declare function cachedRouter(routesDir: string): Promise<{
3
+ getRouter: () => Promise<Router>;
4
+ }>;
2
5
  type GeneratorOptions = {
6
+ /**
7
+ * File extension to append to import statements in the generated router.
8
+ * Useful when your build setup requires specific extensions.
9
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
10
+ * @default "" (no extension)
11
+ */
3
12
  importExtension?: string;
4
13
  };
5
14
  declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
6
15
  type Router = Record<string, any>;
7
16
 
8
- export { createRouter, generateRouter };
17
+ export { cachedRouter, createRouter, generateRouter };
package/dist/index.mjs CHANGED
@@ -30,6 +30,17 @@ async function createRouter(routesDir) {
30
30
  return r.exports[e].route({ path: `${r.path}` });
31
31
  });
32
32
  }
33
+ async function cachedRouter(routesDir) {
34
+ let router = null;
35
+ return {
36
+ getRouter: async () => {
37
+ if (!router) {
38
+ router = await createRouter(routesDir);
39
+ }
40
+ return router;
41
+ }
42
+ };
43
+ }
33
44
  async function generateRouter(routesDir, outputFile, options) {
34
45
  const files = walkTree(
35
46
  routesDir
@@ -37,7 +48,7 @@ async function generateRouter(routesDir, outputFile, options) {
37
48
  const exports = await generateRoutes(files);
38
49
  const importPaths = exports.map((x) => relative(dirname(outputFile), routesDir).concat(x.path));
39
50
  const content = buildRouter(exports, (r, e) => {
40
- return `${e}.route({ path: '${r.path}' })`;
51
+ return `${e}.route({ path: '${r.path.replace(/\/{0,1}index$/, "")}' })`;
41
52
  });
42
53
  let routerContent = `// This file is auto-generated
43
54
 
@@ -114,4 +125,4 @@ async function generateRoutes(files) {
114
125
  return routes;
115
126
  }
116
127
 
117
- export { createRouter, generateRouter };
128
+ export { cachedRouter, createRouter, generateRouter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orpc-file-based-router",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "File-based router plugin for oRPC - automatically generate oRPC router from your file structure",
5
5
  "author": "zeeeeby",
6
6
  "license": "MIT",