react-fs-router 0.2.18 → 1.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 +35 -39
- package/genPath.js +91 -44
- package/index.js +18 -7
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# React-fs-router
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A cli library that watches a user-provided path for changes in files and folders and genarates two files to implement file-system based routing.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -16,42 +16,46 @@ npm install react-fs-router
|
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
-
The
|
|
19
|
+
The position of a file in the folder structure defines it's path. Files named index are treated as the root and default file in each folder.
|
|
20
|
+
You can define a dynamic route by placing the name of the file in brackets. ie: [id].js ==> :id
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
| Arguments | Result |
|
|
23
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| -i \| --input <directory> | Path to watch for changes. Required. |
|
|
25
|
+
| -o \| --output <output> | Optional argument that takes a path to place output files in. Defaults to the input directory. |
|
|
26
|
+
| -ext \| --extention <extention> | Optional argument to change the file extension of the output files. Defaults to .js . |
|
|
27
|
+
| -p \| --pageProperties [type] | Optional boolean argument to disable generating page_properties file. Defaults to false. |
|
|
28
|
+
| -b \| --build [type] | Optional boolean argument that tells the program to run once. Defaults to false. Intended for build commands. |
|
|
23
29
|
|
|
24
30
|
```JSON
|
|
25
31
|
"scripts": {
|
|
26
|
-
"rfr": "rfr -
|
|
32
|
+
"rfr": "rfr -d <path to pages folder>"
|
|
27
33
|
}
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
-b can be passed to tell the program to run only once. Intended to be used with the build script.
|
|
31
|
-
|
|
32
36
|
Run the development server
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
39
|
npm run start
|
|
36
40
|
```
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
Run react-fs-router
|
|
39
43
|
|
|
40
44
|
```bash
|
|
41
45
|
npm run rfr
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
The program will then generate two files one containing imports and exports of all the files inside the
|
|
48
|
+
The program will then generate two files one containing imports and exports of all the files inside the provided path and one containing an array of objects per each file. The properties in the mentioned object are as follows:
|
|
45
49
|
|
|
46
50
|
```javascript
|
|
47
|
-
|
|
48
|
-
component
|
|
49
|
-
name: //Name of the component mentioned in the file
|
|
50
|
-
icon: //Name of the icon mentioned in the file
|
|
51
|
-
index: //A number by which the objects in this array are sorted by
|
|
51
|
+
|
|
52
|
+
component: // Name of the default export of the file
|
|
53
|
+
name: // Name of the component mentioned in the file as // name: string
|
|
54
|
+
icon: // Name of the icon mentioned in the file as // icon: string
|
|
55
|
+
index: // A number by which the objects in this array are sorted by. mentioned in the file as // index: number
|
|
52
56
|
file: // The name of the file this object is for
|
|
53
|
-
path: // The path of this file in relation to its position in the folder structure.
|
|
54
|
-
|
|
57
|
+
path: // The path of this file in relation to its position in the folder structure. index files are always "/"
|
|
58
|
+
|
|
55
59
|
```
|
|
56
60
|
|
|
57
61
|
Name, icon and index can be written in each file and react-fs-router will read and place them in the output file.
|
|
@@ -62,21 +66,13 @@ Name, icon and index can be written in each file and react-fs-router will read a
|
|
|
62
66
|
// index: 0
|
|
63
67
|
```
|
|
64
68
|
|
|
65
|
-
To use with react-router:
|
|
69
|
+
To use the generated files with react-router:
|
|
66
70
|
|
|
67
71
|
```javascript xml react
|
|
68
|
-
// importing all of the files from the imports-exports file
|
|
69
|
-
import * as Pages from "src/config/route";
|
|
70
|
-
// importing the route objects
|
|
71
|
-
import { routes } from "src/config/routeConfigs";
|
|
72
|
-
|
|
73
|
-
import { Route, Switch } from "react-router-dom";
|
|
74
|
-
|
|
75
72
|
function App() {
|
|
76
73
|
const [pages, setPages] = useState();
|
|
77
74
|
|
|
78
75
|
useEffect(() => {
|
|
79
|
-
// calling the function to genarate routes.
|
|
80
76
|
setPages(renderConponents(Pages));
|
|
81
77
|
}, []);
|
|
82
78
|
|
|
@@ -106,7 +102,7 @@ function App() {
|
|
|
106
102
|
}
|
|
107
103
|
```
|
|
108
104
|
|
|
109
|
-
Place this component inside
|
|
105
|
+
Place this component inside BrowserRouter
|
|
110
106
|
|
|
111
107
|
```xml
|
|
112
108
|
<BrowserRouter>
|
|
@@ -117,14 +113,9 @@ Place this component inside <BrowserRouter>
|
|
|
117
113
|
## Using with Ant Pro Layout
|
|
118
114
|
|
|
119
115
|
The routes array generated by this library can be easily used with Ant designs pro layout component.
|
|
120
|
-
The following is an
|
|
116
|
+
The following is an example using an hoc:
|
|
121
117
|
|
|
122
118
|
```javascript xml
|
|
123
|
-
import { routes } from "../../config/routeConfigs";
|
|
124
|
-
import * as Icons from "@ant-design/icons";
|
|
125
|
-
import { Row } from "antd";
|
|
126
|
-
import ProLayout, { PageContainer } from "@ant-design/pro-layout";
|
|
127
|
-
import { Link } from "react-router-dom";
|
|
128
119
|
function Layout(Component) {
|
|
129
120
|
return class extends React.Component {
|
|
130
121
|
state = {
|
|
@@ -168,17 +159,22 @@ function Layout(Component) {
|
|
|
168
159
|
}
|
|
169
160
|
```
|
|
170
161
|
|
|
171
|
-
##
|
|
162
|
+
## Usage with Concurrently
|
|
172
163
|
|
|
173
|
-
|
|
174
|
-
2. Running this package with the start command is not recommended as it interferes with react script unless -b is passed to run the main function of the package once.
|
|
175
|
-
3. This library is a work in progress. Feel free to discuss your issues in the github page of the library.
|
|
164
|
+
You can use [concurrently](https://www.npmjs.com/package/concurrently) to run rfr with react at the same time.
|
|
176
165
|
|
|
177
|
-
|
|
166
|
+
```bash
|
|
167
|
+
npm install -g concurrently
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
concurrently --kill-others "npm run start" "npm run rfr"
|
|
172
|
+
```
|
|
178
173
|
|
|
179
|
-
|
|
174
|
+
## Caveats
|
|
180
175
|
|
|
181
|
-
|
|
176
|
+
1. Since all of the files are imported and re-exported, having two files with the same name as default export will cause an error.
|
|
177
|
+
2. Running this package along with the react start script is not recommended as it interferes with the react script. Consider using a package like concurrently for this purpose.
|
|
182
178
|
|
|
183
179
|
## License
|
|
184
180
|
|
package/genPath.js
CHANGED
|
@@ -4,12 +4,47 @@ const chokidar = require("chokidar");
|
|
|
4
4
|
|
|
5
5
|
let isNotThefirstTimeRunning = true;
|
|
6
6
|
|
|
7
|
-
const genPath = (
|
|
7
|
+
const genPath = (
|
|
8
|
+
page_directory,
|
|
9
|
+
configs_directory,
|
|
10
|
+
runOnce,
|
|
11
|
+
file_extention,
|
|
12
|
+
dont_output_fileProperties
|
|
13
|
+
) => {
|
|
14
|
+
//main function
|
|
8
15
|
const pathMaker = () => {
|
|
16
|
+
//parse parameters in path
|
|
17
|
+
const parsePageName = (fileName) => {
|
|
18
|
+
const isParam = fileName.includes("[") && fileName.includes("]");
|
|
19
|
+
|
|
20
|
+
const splitFileName = fileName.split("/");
|
|
21
|
+
if (splitFileName.length && isParam) {
|
|
22
|
+
const paramName = splitFileName[splitFileName.length - 1];
|
|
23
|
+
const paramNameWithoutExtention = paramName.split(".")[0];
|
|
24
|
+
const paramNameWithoutBraces = paramNameWithoutExtention
|
|
25
|
+
.replace("[", "")
|
|
26
|
+
.replace("]", "");
|
|
27
|
+
splitFileName[splitFileName.length - 1] = `:${paramNameWithoutBraces}`;
|
|
28
|
+
return splitFileName.join("/");
|
|
29
|
+
} else if (fileName === "index" && !isParam) return "";
|
|
30
|
+
else return fileName;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const parseFilePath = (filePath) => {
|
|
34
|
+
if (filePath.includes(":")) {
|
|
35
|
+
const splitPath = filePath.split("/");
|
|
36
|
+
const lastItemInPath = splitPath[splitPath.length - 1].replace(":", "");
|
|
37
|
+
splitPath[splitPath.length - 1] = `[${lastItemInPath}]`;
|
|
38
|
+
return splitPath.join("/");
|
|
39
|
+
} else return filePath;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//read page directory
|
|
9
43
|
const readDirectory = (directory, includeDirectory) => {
|
|
10
44
|
const pages = {};
|
|
11
45
|
const read = fs.readdirSync(directory);
|
|
12
|
-
read.
|
|
46
|
+
const readFiltered = read.filter((file) => !file.startsWith("_"));
|
|
47
|
+
readFiltered.forEach((page) => {
|
|
13
48
|
const name = page.split(".")[0];
|
|
14
49
|
if (page.includes(".")) {
|
|
15
50
|
pages[page.replace(".", "_")] = `${
|
|
@@ -21,6 +56,7 @@ const genPath = (page_directory, configs_directory, runOnce) => {
|
|
|
21
56
|
});
|
|
22
57
|
return pages;
|
|
23
58
|
};
|
|
59
|
+
|
|
24
60
|
const pages = readDirectory(page_directory);
|
|
25
61
|
|
|
26
62
|
const readFileProperties = (filepath) => {
|
|
@@ -77,8 +113,9 @@ const genPath = (page_directory, configs_directory, runOnce) => {
|
|
|
77
113
|
if (name) route.name = name;
|
|
78
114
|
if (icon) route.icon = icon;
|
|
79
115
|
if (index) route.index = index;
|
|
80
|
-
if (filepath) route.path = filepath;
|
|
116
|
+
if (filepath) route.path = parsePageName(filepath);
|
|
81
117
|
if (filename) route.file = filename.replace("_", ".");
|
|
118
|
+
|
|
82
119
|
return route;
|
|
83
120
|
};
|
|
84
121
|
|
|
@@ -106,23 +143,33 @@ const genPath = (page_directory, configs_directory, runOnce) => {
|
|
|
106
143
|
node?.component
|
|
107
144
|
? `import ${node.component} from "${
|
|
108
145
|
process.env.PWD + page_directory.replace(".", "")
|
|
109
|
-
}${node.path === "/" ? "" : node.path}";`
|
|
146
|
+
}${node.path === "/" ? "" : parseFilePath(node.path)}";`
|
|
110
147
|
: ""
|
|
111
148
|
)
|
|
112
149
|
.join("")} \n \n export{${routes
|
|
113
150
|
.map((node) => (node?.component ? `${node.component},` : ""))
|
|
114
151
|
.join("")}};`;
|
|
115
152
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
153
|
+
const parseFileExtention = (ext) => {
|
|
154
|
+
if (ext) {
|
|
155
|
+
if (ext.includes(".")) return ext;
|
|
156
|
+
else return "." + ext;
|
|
157
|
+
} else return ".js";
|
|
158
|
+
};
|
|
159
|
+
if (!dont_output_fileProperties) {
|
|
160
|
+
fs.writeFileSync(
|
|
161
|
+
(configs_directory || page_directory) +
|
|
162
|
+
`/_page-properties${parseFileExtention(file_extention)}`,
|
|
163
|
+
prettier.format(_config, { semi: false, parser: "babel" }),
|
|
164
|
+
(err) => {
|
|
165
|
+
if (err) return console.error(err);
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
123
169
|
|
|
124
170
|
fs.writeFileSync(
|
|
125
|
-
configs_directory +
|
|
171
|
+
(configs_directory || page_directory) +
|
|
172
|
+
`/_routes${parseFileExtention(file_extention)}`,
|
|
126
173
|
prettier.format(_routes, { semi: false, parser: "babel" }),
|
|
127
174
|
(err) => {
|
|
128
175
|
if (err) return console.error(err);
|
|
@@ -134,40 +181,40 @@ const genPath = (page_directory, configs_directory, runOnce) => {
|
|
|
134
181
|
pathMaker();
|
|
135
182
|
isNotThefirstTimeRunning = false;
|
|
136
183
|
}
|
|
184
|
+
|
|
137
185
|
const watcher = chokidar.watch(page_directory, {
|
|
138
|
-
ignored:
|
|
139
|
-
persistent:
|
|
186
|
+
ignored: /^\.|\_/,
|
|
187
|
+
persistent: !runOnce,
|
|
140
188
|
});
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
189
|
+
|
|
190
|
+
watcher
|
|
191
|
+
.on("add", function (path) {
|
|
192
|
+
try {
|
|
193
|
+
pathMaker();
|
|
194
|
+
} catch (e) {
|
|
195
|
+
console.log(e);
|
|
196
|
+
}
|
|
197
|
+
console.log("File", path, "has been added");
|
|
198
|
+
})
|
|
199
|
+
.on("change", function (path) {
|
|
200
|
+
try {
|
|
201
|
+
pathMaker();
|
|
202
|
+
} catch (e) {
|
|
203
|
+
console.log(e);
|
|
204
|
+
}
|
|
205
|
+
console.log("File", path, "has been changed");
|
|
206
|
+
})
|
|
207
|
+
.on("unlink", function (path) {
|
|
208
|
+
try {
|
|
209
|
+
pathMaker();
|
|
210
|
+
} catch (e) {
|
|
211
|
+
console.log(e);
|
|
212
|
+
}
|
|
213
|
+
console.log("File", path, "has been removed");
|
|
214
|
+
})
|
|
215
|
+
.on("error", function (error) {
|
|
216
|
+
console.error("Error happened", error);
|
|
217
|
+
});
|
|
171
218
|
};
|
|
172
219
|
|
|
173
220
|
module.exports = { genPath };
|
package/index.js
CHANGED
|
@@ -5,21 +5,32 @@ const { Command } = require("commander");
|
|
|
5
5
|
const { version, name } = require("./package.json");
|
|
6
6
|
|
|
7
7
|
const program = new Command();
|
|
8
|
+
|
|
8
9
|
program.storeOptionsAsProperties(name);
|
|
9
10
|
|
|
10
11
|
program.version(version, "-v --version", "Output the current version");
|
|
11
|
-
|
|
12
|
-
program.
|
|
13
|
-
program.
|
|
14
|
-
"-
|
|
15
|
-
"
|
|
12
|
+
program.requiredOption("-i,--input <directory>", "Path to your pages folder");
|
|
13
|
+
program.option("-o,--output <output>", "Path to store generated files");
|
|
14
|
+
program.option(
|
|
15
|
+
"-ext,--extention <extention>",
|
|
16
|
+
"extention on the generated files"
|
|
16
17
|
);
|
|
17
18
|
|
|
19
|
+
program.option(
|
|
20
|
+
"-p,--pageProperties [type]",
|
|
21
|
+
"Boolean option to disable genrating page properties file"
|
|
22
|
+
);
|
|
18
23
|
program.option(
|
|
19
24
|
"-b,--build [type]",
|
|
20
|
-
"
|
|
25
|
+
"Boolean Option to run the program once. Intended to be used with build commands."
|
|
21
26
|
);
|
|
22
27
|
|
|
23
28
|
program.parse();
|
|
24
29
|
|
|
25
|
-
genPath(
|
|
30
|
+
genPath(
|
|
31
|
+
program.input,
|
|
32
|
+
program.output,
|
|
33
|
+
program.build,
|
|
34
|
+
program.extention,
|
|
35
|
+
program.pageProperties
|
|
36
|
+
);
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-fs-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "File-system based routing for React.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"git repository": "https://github.com/Mehran9675/react-filesystem-routing",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "node ./index.js -
|
|
8
|
+
"test": "node ./index.js -i ./pages -ext ts",
|
|
9
9
|
"build": "npx -p typescript tsc"
|
|
10
10
|
},
|
|
11
11
|
"keywords": [
|
|
@@ -28,4 +28,8 @@
|
|
|
28
28
|
"typescript": "^4.4.4",
|
|
29
29
|
"prettier": "^2.4.1"
|
|
30
30
|
}
|
|
31
|
+
,"repository": {
|
|
32
|
+
"type":"git",
|
|
33
|
+
"url":"https://github.com/Mehran9675/react-filesystem-routing"
|
|
34
|
+
}
|
|
31
35
|
}
|