orpc-file-based-router 0.0.18 → 0.1.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 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
@@ -72,11 +72,11 @@ const handler = new RPCHandler(router);
72
72
  > startServer();
73
73
  > ```
74
74
 
75
- ## Type-Safe Client Configuration (Optional)
75
+ ## 🔒 Type-Safe Client Configuration (Optional)
76
76
 
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.
77
+ 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.
78
78
 
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:
79
+ 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
80
 
81
81
  ```typescript
82
82
  import { generateRouter } from "orpc-file-based-router";
@@ -121,6 +121,16 @@ const client: RouterClient<typeof router> = createORPCClient(link)
121
121
 
122
122
  ```
123
123
 
124
- ## License
124
+ ## 🛠 Configuration Options
125
125
 
126
- MIT
126
+ When using `generateRouter`, you can provide additional options to customize the output:
127
+
128
+ | Field | Type | Required | Default Value | Description |
129
+ |-------------------|----------|--------------|-----------------------|------------------------------------------------------------------------------------------------------------------------------|
130
+ | `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"` |
131
+
132
+
133
+
134
+ ## 📄 License
135
+
136
+ MIT License - feel free to use this in your own projects!
package/dist/index.cjs CHANGED
@@ -36,26 +36,27 @@ async function createRouter(routesDir) {
36
36
  return r.exports[e].route({ path: `${r.path}` });
37
37
  });
38
38
  }
39
- async function generateRouter(routesDir, outputFile) {
39
+ async function generateRouter(routesDir, outputFile, options) {
40
40
  const files = walkTree(
41
41
  routesDir
42
42
  );
43
43
  const exports = await generateRoutes(files);
44
44
  const importPaths = exports.map((x) => path.relative(path.dirname(outputFile), routesDir).concat(x.path));
45
45
  const content = buildRouter(exports, (r, e) => {
46
- return `${e}.route({ path: '${r.path}' })`;
46
+ return `${e}.route({ path: '${r.path.replace(/\/{0,1}index$/, "")}' })`;
47
47
  });
48
48
  let routerContent = `// This file is auto-generated
49
49
 
50
50
  `;
51
- routerContent += importPaths.map((x, i) => `import { ${Object.keys(exports[i].exports).join(", ")} } from "./${x}"`).join("\n");
51
+ const extension = options?.importExtension || "";
52
+ routerContent += importPaths.map((x, i) => `import { ${Object.keys(exports[i].exports).join(", ")} } from "./${x}${extension}"`).join("\n");
52
53
  routerContent += "\n\nexport const router = ";
53
54
  routerContent += JSON.stringify(content, null, 2).replace(/"/g, "").replace(/(\s*)([a-zA-Z0-9]+-[a-zA-Z0-9-]+):/g, '$1"$2":');
54
55
  node_fs.writeFileSync(path.join(outputFile), routerContent);
55
56
  }
56
57
  function buildRoutePath(parsedFile) {
57
58
  const directory = parsedFile.dir === parsedFile.root ? "" : parsedFile.dir;
58
- const name = parsedFile.name.startsWith("index") ? parsedFile.name.replace("index", "") : `/${parsedFile.name}`;
59
+ const name = `/${parsedFile.name}`;
59
60
  return directory + name;
60
61
  }
61
62
  function buildRouter(routes, mapper) {
package/dist/index.d.cts CHANGED
@@ -1,5 +1,14 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
- declare function generateRouter(routesDir: string, outputFile: string): Promise<void>;
2
+ type GeneratorOptions = {
3
+ /**
4
+ * File extension to append to import statements in the generated router.
5
+ * Useful when your build setup requires specific extensions.
6
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
7
+ * @default "" (no extension)
8
+ */
9
+ importExtension?: string;
10
+ };
11
+ declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
3
12
  type Router = Record<string, any>;
4
13
 
5
14
  export { createRouter, generateRouter };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,14 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
- declare function generateRouter(routesDir: string, outputFile: string): Promise<void>;
2
+ type GeneratorOptions = {
3
+ /**
4
+ * File extension to append to import statements in the generated router.
5
+ * Useful when your build setup requires specific extensions.
6
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
7
+ * @default "" (no extension)
8
+ */
9
+ importExtension?: string;
10
+ };
11
+ declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
3
12
  type Router = Record<string, any>;
4
13
 
5
14
  export { createRouter, generateRouter };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,14 @@
1
1
  declare function createRouter(routesDir: string): Promise<Router>;
2
- declare function generateRouter(routesDir: string, outputFile: string): Promise<void>;
2
+ type GeneratorOptions = {
3
+ /**
4
+ * File extension to append to import statements in the generated router.
5
+ * Useful when your build setup requires specific extensions.
6
+ * @example ".js" will generate imports like: import { me } from "./routes/auth/me.js"
7
+ * @default "" (no extension)
8
+ */
9
+ importExtension?: string;
10
+ };
11
+ declare function generateRouter(routesDir: string, outputFile: string, options?: GeneratorOptions): Promise<void>;
3
12
  type Router = Record<string, any>;
4
13
 
5
14
  export { createRouter, generateRouter };
package/dist/index.mjs CHANGED
@@ -30,26 +30,27 @@ async function createRouter(routesDir) {
30
30
  return r.exports[e].route({ path: `${r.path}` });
31
31
  });
32
32
  }
33
- async function generateRouter(routesDir, outputFile) {
33
+ async function generateRouter(routesDir, outputFile, options) {
34
34
  const files = walkTree(
35
35
  routesDir
36
36
  );
37
37
  const exports = await generateRoutes(files);
38
38
  const importPaths = exports.map((x) => relative(dirname(outputFile), routesDir).concat(x.path));
39
39
  const content = buildRouter(exports, (r, e) => {
40
- return `${e}.route({ path: '${r.path}' })`;
40
+ return `${e}.route({ path: '${r.path.replace(/\/{0,1}index$/, "")}' })`;
41
41
  });
42
42
  let routerContent = `// This file is auto-generated
43
43
 
44
44
  `;
45
- routerContent += importPaths.map((x, i) => `import { ${Object.keys(exports[i].exports).join(", ")} } from "./${x}"`).join("\n");
45
+ const extension = options?.importExtension || "";
46
+ routerContent += importPaths.map((x, i) => `import { ${Object.keys(exports[i].exports).join(", ")} } from "./${x}${extension}"`).join("\n");
46
47
  routerContent += "\n\nexport const router = ";
47
48
  routerContent += JSON.stringify(content, null, 2).replace(/"/g, "").replace(/(\s*)([a-zA-Z0-9]+-[a-zA-Z0-9-]+):/g, '$1"$2":');
48
49
  writeFileSync(join(outputFile), routerContent);
49
50
  }
50
51
  function buildRoutePath(parsedFile) {
51
52
  const directory = parsedFile.dir === parsedFile.root ? "" : parsedFile.dir;
52
- const name = parsedFile.name.startsWith("index") ? parsedFile.name.replace("index", "") : `/${parsedFile.name}`;
53
+ const name = `/${parsedFile.name}`;
53
54
  return directory + name;
54
55
  }
55
56
  function buildRouter(routes, mapper) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orpc-file-based-router",
3
- "version": "0.0.18",
3
+ "version": "0.1.1",
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",
@@ -30,7 +30,8 @@
30
30
  ],
31
31
  "scripts": {
32
32
  "build": "npm run type-check && unbuild",
33
- "type-check": "tsc --noEmit"
33
+ "type-check": "tsc --noEmit",
34
+ "playground": "tsx playground/src/generator.ts"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@orpc/client": "^1.8.5",
@@ -40,4 +41,4 @@
40
41
  "vitest": "^3.2.4",
41
42
  "zod": "^4.1.3"
42
43
  }
43
- }
44
+ }