@getsoren/create-boilerplate-vite-react-ts 2.7.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.
Potentially problematic release.
This version of @getsoren/create-boilerplate-vite-react-ts might be problematic. Click here for more details.
- package/.eslintignore +2 -0
- package/.eslintrc.json +6 -0
- package/.github/pull_request_template.md +2 -0
- package/.github/workflows/release.yml +66 -0
- package/.husky/pre-commit +8 -0
- package/CHANGELOG.md +6 -0
- package/README.md +97 -0
- package/bin/create-app.cjs +269 -0
- package/bun.lockb +0 -0
- package/index.html +13 -0
- package/index.tsx +9 -0
- package/package.json +64 -0
- package/public/.readme.md +1 -0
- package/public/favicon.ico +0 -0
- package/src/App.test.tsx +10 -0
- package/src/App.tsx +3 -0
- package/src/assets/.readme.md +1 -0
- package/src/components/.readme.md +4 -0
- package/src/components/DataDisplay/.readme.md +1 -0
- package/src/components/Feedback/.readme.md +1 -0
- package/src/components/Inputs/.readme.md +1 -0
- package/src/components/Layout/.readme.md +1 -0
- package/src/components/Navigation/.readme.md +1 -0
- package/src/components/Surfaces/.readme.md +1 -0
- package/src/components/Utils/.readme.md +1 -0
- package/src/components/Utils/Router.tsx +17 -0
- package/src/constants/.readme.md +3 -0
- package/src/constants/routes.ts +6 -0
- package/src/context/.readme.md +3 -0
- package/src/features/.readme.md +12 -0
- package/src/hooks/.readme.md +1 -0
- package/src/locales/.readme.md +1 -0
- package/src/locales/en.ts +3 -0
- package/src/locales/fr.ts +3 -0
- package/src/pages/.readme.md +6 -0
- package/src/pages/Contact.tsx +12 -0
- package/src/pages/Home.tsx +12 -0
- package/src/services/.readme.md +3 -0
- package/src/stores/.readme.md +2 -0
- package/src/test.config.ts +4 -0
- package/src/types/.readme.md +2 -0
- package/src/types/dependencies.d.ts +8 -0
- package/src/types/i18next.d.ts +10 -0
- package/src/types/vite-env.d.ts +1 -0
- package/src/utils/.readme.md +2 -0
- package/tsconfig.json +46 -0
- package/tsconfig.node.json +15 -0
- package/vite.config.ts +19 -0
package/.eslintignore
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: 🚀 Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: 🛎️ Checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
|
|
22
|
+
- name: 🐰 Setup Bun
|
|
23
|
+
uses: oven-sh/setup-bun@v1
|
|
24
|
+
|
|
25
|
+
- name: 📦 Install dependencies
|
|
26
|
+
run: bun install
|
|
27
|
+
|
|
28
|
+
- name: 🧑 Configure Git identity
|
|
29
|
+
run: |
|
|
30
|
+
git config --local user.name "github-actions[bot]"
|
|
31
|
+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
32
|
+
|
|
33
|
+
- name: 🏷️ Bump version & generate changelog
|
|
34
|
+
id: bump
|
|
35
|
+
run: |
|
|
36
|
+
PREV_VERSION=$(jq -r .version package.json)
|
|
37
|
+
bun run release
|
|
38
|
+
NEW_VERSION=$(jq -r .version package.json)
|
|
39
|
+
echo "prev_version=$PREV_VERSION" >> $GITHUB_OUTPUT
|
|
40
|
+
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
41
|
+
|
|
42
|
+
- name: 🚀 Push changes and tags
|
|
43
|
+
if: steps.bump.outputs.prev_version != steps.bump.outputs.new_version
|
|
44
|
+
run: |
|
|
45
|
+
git push origin HEAD:${{ github.ref }}
|
|
46
|
+
git push --tags
|
|
47
|
+
|
|
48
|
+
- name: 🏗️ Build
|
|
49
|
+
if: steps.bump.outputs.prev_version != steps.bump.outputs.new_version
|
|
50
|
+
run: bun run build
|
|
51
|
+
|
|
52
|
+
- name: 📝 Create GitHub Release
|
|
53
|
+
if: steps.bump.outputs.prev_version != steps.bump.outputs.new_version
|
|
54
|
+
run: gh release create "${{ steps.bump.outputs.new_version }}" -F CHANGELOG.md
|
|
55
|
+
env:
|
|
56
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
57
|
+
|
|
58
|
+
- name: 🔐 Setup npm auth
|
|
59
|
+
if: steps.bump.outputs.prev_version != steps.bump.outputs.new_version
|
|
60
|
+
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc
|
|
61
|
+
|
|
62
|
+
- name: 📤 Publish to npm
|
|
63
|
+
if: steps.bump.outputs.prev_version != steps.bump.outputs.new_version
|
|
64
|
+
env:
|
|
65
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|
|
66
|
+
run: npm publish --access public
|
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @getsoren/create-boilerplate-vite-react-ts
|
|
2
|
+
|
|
3
|
+
> Create quickly a skeleton of `Vite React TypeScript`
|
|
4
|
+
application with amazing configuration.
|
|
5
|
+
|
|
6
|
+
- [Quick Start](#Quick-Start)
|
|
7
|
+
- [Optional params](#Optional-params)
|
|
8
|
+
- [Files structure](#Files-structure)
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
**bun:**
|
|
13
|
+
```bash
|
|
14
|
+
bun create @getsoren/boilerplate-vite-react-ts YOUR_APP_NAME
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**npm:**
|
|
18
|
+
```bash
|
|
19
|
+
npm create @getsoren/boilerplate-vite-react-ts YOUR_APP_NAME
|
|
20
|
+
```
|
|
21
|
+
**yarn**:
|
|
22
|
+
```bash
|
|
23
|
+
yarn create @getsoren/boilerplate-vite-react-ts YOUR_APP_NAME
|
|
24
|
+
```
|
|
25
|
+
**pnpm**:
|
|
26
|
+
```bash
|
|
27
|
+
pnpm create @getsoren/boilerplate-vite-react-ts YOUR_APP_NAME
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> Note: `npm create @scope/foo` is equivalent to `npm init @scope/foo`, which resolves to the package `@scope/create-foo`.
|
|
31
|
+
|
|
32
|
+
## Optional params
|
|
33
|
+
|
|
34
|
+
You can add some params to install and configure automatically
|
|
35
|
+
some popular libraries.
|
|
36
|
+
|
|
37
|
+
| Name | Description | Documentation |
|
|
38
|
+
|----------------|------------------------------|-------------------------------------------------|
|
|
39
|
+
| `axios` | Install axios library | [axios](https://axios-http.com/fr/docs/intro) |
|
|
40
|
+
| `i18next` | Install i18next library | [i18next](https://www.i18next.com) |
|
|
41
|
+
| `react-query` | Install react query library | [react-query](https://react-query.tanstack.com) |
|
|
42
|
+
| `react-router` | Install react router library | [react-router](https://reactrouter.com) |
|
|
43
|
+
<br>
|
|
44
|
+
example:
|
|
45
|
+
|
|
46
|
+
```console
|
|
47
|
+
npm create @getsoren/boilerplate-vite-react-ts YOUR_APP_NAME --axios --i18next
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Files structure
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
├── .husky
|
|
54
|
+
pre-commit
|
|
55
|
+
├── public
|
|
56
|
+
favicon.ico
|
|
57
|
+
└── src
|
|
58
|
+
└── assets
|
|
59
|
+
└── components
|
|
60
|
+
└── DataDisplay
|
|
61
|
+
└── Feedback
|
|
62
|
+
└── Inputs
|
|
63
|
+
└── Layout
|
|
64
|
+
└── Navigation
|
|
65
|
+
└── Surfaces
|
|
66
|
+
└── Utils
|
|
67
|
+
Router.tsx (optional if react-router is installed)
|
|
68
|
+
└── constants
|
|
69
|
+
routes.ts (optional if react-router is installed)
|
|
70
|
+
└── context
|
|
71
|
+
└── features
|
|
72
|
+
└── hooks
|
|
73
|
+
└── locales
|
|
74
|
+
└── pages
|
|
75
|
+
Contact.tsx (optional if react-router is installed)
|
|
76
|
+
Home.tsx (optional if react-router is installed)
|
|
77
|
+
└── services
|
|
78
|
+
└── stores
|
|
79
|
+
└── types
|
|
80
|
+
i18next.d.ts (optional if i18next is installed)
|
|
81
|
+
vite-env.d.ts
|
|
82
|
+
└── utils
|
|
83
|
+
App.test.tsx
|
|
84
|
+
App.tsx
|
|
85
|
+
test.config.ts
|
|
86
|
+
.eslintignore
|
|
87
|
+
.eslintrc.json
|
|
88
|
+
.gitignore
|
|
89
|
+
index.html
|
|
90
|
+
index.tsx
|
|
91
|
+
package.json
|
|
92
|
+
README.md
|
|
93
|
+
tsconfig.json
|
|
94
|
+
tsconfig.node.json
|
|
95
|
+
vite.config.ts
|
|
96
|
+
[yarn.lock|pnpm-lock.yaml|package-lock.json|bun.lockb]
|
|
97
|
+
```
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const yargs = require("yargs")
|
|
3
|
+
const {join} = require("path");
|
|
4
|
+
const {execSync} = require("child_process");
|
|
5
|
+
const {mkdirSync, rmSync, openSync, writeFileSync, close, writeSync, appendFileSync} = require("fs");
|
|
6
|
+
const packageJson = require("../package.json");
|
|
7
|
+
const eslintrcJson = require("../.eslintrc.json");
|
|
8
|
+
|
|
9
|
+
const ENCODED_FILE = "utf8";
|
|
10
|
+
|
|
11
|
+
const PROJECT_NAME = process.argv[2];
|
|
12
|
+
const CURRENT_PATH = process.cwd();
|
|
13
|
+
const PROJECT_PATH = join(CURRENT_PATH, PROJECT_NAME);
|
|
14
|
+
const REPOSITORY_URL = packageJson.repository.url;
|
|
15
|
+
const PACKAGE_INFO = pkgFromUserAgent(process.env.npm_config_user_agent);
|
|
16
|
+
|
|
17
|
+
const PACKAGE_MANAGER = PACKAGE_INFO ? PACKAGE_INFO : "npm";
|
|
18
|
+
|
|
19
|
+
// Optional parameters
|
|
20
|
+
const AXIOS_PARAM = "axios";
|
|
21
|
+
const I18NEXT_PARAM = "i18next";
|
|
22
|
+
const REACT_QUERY_PARAM = "react-query";
|
|
23
|
+
const REACT_ROUTER_PARAM = "react-router";
|
|
24
|
+
|
|
25
|
+
if (process.argv.length < 3) {
|
|
26
|
+
console.log("\x1b[31m", "You have to provide name to your app.");
|
|
27
|
+
console.log("For example: ");
|
|
28
|
+
console.log(PACKAGE_MANAGER + " create boilerplate-vite-react-ts YOUR_APP_NAME", "\x1b[0m");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
mkdirSync(PROJECT_PATH);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (error?.code === "EEXIST") {
|
|
36
|
+
console.log(`The file ${PROJECT_NAME} already exist in the current directory, please give it another name.`);
|
|
37
|
+
} else {
|
|
38
|
+
console.log(error);
|
|
39
|
+
}
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function pkgFromUserAgent(userAgent) {
|
|
44
|
+
if (!userAgent) return undefined;
|
|
45
|
+
const pkgSpec = userAgent.split(' ')[0];
|
|
46
|
+
return pkgSpec.split('/')[0];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const buildPackageJson = ({packageJson, argv}) => {
|
|
50
|
+
// Filters package.json
|
|
51
|
+
const {
|
|
52
|
+
bin,
|
|
53
|
+
keywords,
|
|
54
|
+
homepage,
|
|
55
|
+
repository,
|
|
56
|
+
bugs,
|
|
57
|
+
version,
|
|
58
|
+
description,
|
|
59
|
+
...packageJsonFilter
|
|
60
|
+
} = packageJson;
|
|
61
|
+
|
|
62
|
+
// Filters dependencies
|
|
63
|
+
const {
|
|
64
|
+
yargs,
|
|
65
|
+
[!argv?.[AXIOS_PARAM] && "axios"]: axiosRemoved,
|
|
66
|
+
[!argv?.[I18NEXT_PARAM] && "i18next"]: i18nextRemoved,
|
|
67
|
+
[!argv?.[I18NEXT_PARAM] && "react-i18next"]: reactI18nextRemoved,
|
|
68
|
+
[!argv?.[I18NEXT_PARAM] && "i18next-browser-languagedetector"]: i18nextBrowserLanguageDetectorRemoved,
|
|
69
|
+
[!argv?.[REACT_QUERY_PARAM] && "@tanstack/react-query"]: reactQueryRemoved,
|
|
70
|
+
...dependenciesFilter
|
|
71
|
+
} = packageJson.dependencies;
|
|
72
|
+
|
|
73
|
+
// Filters scripts
|
|
74
|
+
const {
|
|
75
|
+
create,
|
|
76
|
+
...scriptFilter
|
|
77
|
+
} = packageJson.scripts
|
|
78
|
+
|
|
79
|
+
const newPackage = {
|
|
80
|
+
...packageJsonFilter,
|
|
81
|
+
name: argv._[0],
|
|
82
|
+
license: "UNLICENSED",
|
|
83
|
+
dependencies: {
|
|
84
|
+
...dependenciesFilter,
|
|
85
|
+
},
|
|
86
|
+
scripts: {
|
|
87
|
+
...scriptFilter,
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
writeFileSync(`${process.cwd()}/package.json`, JSON.stringify(newPackage, null, 2), ENCODED_FILE);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const buildEslintJson = (eslintrcJson) => {
|
|
95
|
+
const {rules, ...eslintrcJsonFilter} = eslintrcJson
|
|
96
|
+
|
|
97
|
+
writeFileSync(`${process.cwd()}/.eslintrc.json`, JSON.stringify(eslintrcJsonFilter, null, 2), ENCODED_FILE);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const buildSetupTest = () => {
|
|
101
|
+
|
|
102
|
+
if (yargs.argv?.[I18NEXT_PARAM]) {
|
|
103
|
+
const data = `\n` +
|
|
104
|
+
`// Mock translation` + `\n` +
|
|
105
|
+
`vi.mock("react-i18next", async () => {` + `\n` +
|
|
106
|
+
` const actual: any = await vi.importActual("react-i18next");` + `\n` +
|
|
107
|
+
` return {` + `\n` +
|
|
108
|
+
` ...actual,` + `\n` +
|
|
109
|
+
` useTranslation: () => ({` + `\n` +
|
|
110
|
+
` i18n: {` + `\n` +
|
|
111
|
+
` changeLanguage: () => new Promise(() => {}),` + `\n` +
|
|
112
|
+
` },` + `\n` +
|
|
113
|
+
` t: (str: string) => str,` + `\n` +
|
|
114
|
+
` }),` + `\n` +
|
|
115
|
+
` };` + `\n` +
|
|
116
|
+
`});`;
|
|
117
|
+
|
|
118
|
+
appendFileSync("src/test.config.ts", data);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
const removeUselessFiles = () => {
|
|
124
|
+
execSync("npx rimraf ./.git");
|
|
125
|
+
rmSync(join(PROJECT_PATH, ".github"), {recursive: true});
|
|
126
|
+
rmSync(join(PROJECT_PATH, ".circleci"), {recursive: true});
|
|
127
|
+
rmSync(join(PROJECT_PATH, "bin"), {recursive: true});
|
|
128
|
+
rmSync(join(PROJECT_PATH, "CHANGELOG.md"), {recursive: true});
|
|
129
|
+
rmSync(join(PROJECT_PATH, "src/types/dependencies.d.ts"), {recursive: true});
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
// Remove i18next files
|
|
133
|
+
if (!yargs.argv?.[I18NEXT_PARAM]) {
|
|
134
|
+
rmSync(join(PROJECT_PATH, "src/locales/en.ts"), {recursive: true});
|
|
135
|
+
rmSync(join(PROJECT_PATH, "src/locales/fr.ts"), {recursive: true});
|
|
136
|
+
rmSync(join(PROJECT_PATH, "src/types/i18next.d.ts"), {recursive: true});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Remove react router dom files
|
|
140
|
+
if (!yargs.argv?.[REACT_ROUTER_PARAM]) {
|
|
141
|
+
rmSync(join(PROJECT_PATH, "src/components/Utils/Router.tsx"), {recursive: true});
|
|
142
|
+
rmSync(join(PROJECT_PATH, "src/constants/routes.ts"), {recursive: true});
|
|
143
|
+
rmSync(join(PROJECT_PATH, "src/pages/Contact.tsx"), {recursive: true});
|
|
144
|
+
rmSync(join(PROJECT_PATH, "src/pages/Home.tsx"), {recursive: true});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const getAppData = () => {
|
|
149
|
+
let data = [];
|
|
150
|
+
const children = yargs.argv?.[REACT_ROUTER_PARAM] ? "<Router />" : `<h1>${packageJson.name}</h1>`;
|
|
151
|
+
|
|
152
|
+
if (yargs.argv?.[REACT_QUERY_PARAM]) {
|
|
153
|
+
data.push(`import { QueryClientProvider } from "@tanstack/react-query";\n`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (yargs.argv?.[REACT_ROUTER_PARAM]) {
|
|
157
|
+
data.push(`import Router from "@/components/Utils/Router";\n`)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (yargs.argv?.[REACT_QUERY_PARAM]) {
|
|
161
|
+
data.push(`import reactQueryConfig from "@/config/reactQuery.config";\n`)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (yargs.argv?.[AXIOS_PARAM]) {
|
|
165
|
+
data.push(`import "@/config/axios.config";\n`)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (yargs.argv?.[I18NEXT_PARAM]) {
|
|
169
|
+
data.push(`import "@/config/i18next.config";\n`)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (yargs.argv?.[REACT_QUERY_PARAM]) {
|
|
173
|
+
data.push(
|
|
174
|
+
`\nconst App = () => (` +
|
|
175
|
+
`\n <QueryClientProvider client={reactQueryConfig}>` +
|
|
176
|
+
`\n ${children}` +
|
|
177
|
+
`\n </QueryClientProvider>` +
|
|
178
|
+
`\n);`
|
|
179
|
+
)
|
|
180
|
+
} else {
|
|
181
|
+
const breakLine = data.length === 0 ? "" : "\n";
|
|
182
|
+
data.push(`${breakLine}const App = () => ${children};`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
data.push(`\n\nexport default App;`)
|
|
186
|
+
|
|
187
|
+
return data.join("") + "\n";
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const buildAppFile = () => {
|
|
191
|
+
const file = "src/App.tsx";
|
|
192
|
+
const fd = openSync(file, "w+");
|
|
193
|
+
const data = getAppData();
|
|
194
|
+
const buffer = Buffer.from(data);
|
|
195
|
+
|
|
196
|
+
writeSync(fd, buffer, 0, buffer.length, 0); //write new data
|
|
197
|
+
close(fd);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const installDependencies = () => {
|
|
201
|
+
const installDependencyCommand = PACKAGE_MANAGER === "npm" ? "install" : "add";
|
|
202
|
+
|
|
203
|
+
execSync(`${PACKAGE_MANAGER} install`);
|
|
204
|
+
|
|
205
|
+
if (yargs.argv?.[AXIOS_PARAM]) {
|
|
206
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} axios`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (yargs.argv?.[I18NEXT_PARAM]) {
|
|
210
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} i18next`);
|
|
211
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} react-i18next`);
|
|
212
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} i18next-browser-languagedetector`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (yargs.argv?.[REACT_QUERY_PARAM]) {
|
|
216
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} @tanstack/react-query`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (yargs.argv?.[REACT_ROUTER_PARAM]) {
|
|
220
|
+
execSync(`${PACKAGE_MANAGER} ${installDependencyCommand} react-router-dom`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Remove lock file before install, user don't need it
|
|
224
|
+
rmSync(join(PROJECT_PATH, "bun.lockb"), {recursive: true});
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const main = async () => {
|
|
228
|
+
try {
|
|
229
|
+
// Clear npx cache
|
|
230
|
+
console.log("\n\x1b[36m%s\x1b[0m", "Clear npx cache...");
|
|
231
|
+
execSync("rm -rf ~/.npm/_npx");
|
|
232
|
+
|
|
233
|
+
// Download files
|
|
234
|
+
console.log("\x1b[36m%s\x1b[0m", "Downloading files...");
|
|
235
|
+
execSync(`git clone --depth 1 ${REPOSITORY_URL} ${PROJECT_PATH}`);
|
|
236
|
+
|
|
237
|
+
// Change directory
|
|
238
|
+
process.chdir(PROJECT_PATH);
|
|
239
|
+
|
|
240
|
+
// Create package.json & .eslintrc.json
|
|
241
|
+
console.log("\x1b[36m%s\x1b[0m", "Create package.json & .eslintrc.json...");
|
|
242
|
+
buildPackageJson({packageJson, argv: yargs.argv});
|
|
243
|
+
|
|
244
|
+
// Install dependencies
|
|
245
|
+
console.log("\x1b[36m%s\x1b[0m", "Installing dependencies...");
|
|
246
|
+
installDependencies();
|
|
247
|
+
|
|
248
|
+
// Generate Files.tsx
|
|
249
|
+
console.log("\x1b[36m%s\x1b[0m", "Generate Files...");
|
|
250
|
+
buildAppFile();
|
|
251
|
+
buildEslintJson(eslintrcJson);
|
|
252
|
+
buildSetupTest();
|
|
253
|
+
|
|
254
|
+
// Remove useless files
|
|
255
|
+
console.log("\x1b[36m%s\x1b[0m", "Clean up unused file...");
|
|
256
|
+
removeUselessFiles();
|
|
257
|
+
|
|
258
|
+
// Create empty README.md
|
|
259
|
+
console.log("\x1b[36m%s\x1b[0m", "Create empty README.md...");
|
|
260
|
+
openSync("README.md", "w");
|
|
261
|
+
|
|
262
|
+
// Done
|
|
263
|
+
console.log("\x1b[32m%s\x1b[0m", "Your application is ready, enjoy to use !");
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.log(error);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
main().then();
|
package/bun.lockb
ADDED
|
Binary file
|
package/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Vite + React + TS</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/index.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/index.tsx
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@getsoren/create-boilerplate-vite-react-ts",
|
|
3
|
+
"description": "Start a Vite React TypeScript project in few second !",
|
|
4
|
+
"private": false,
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"version": "2.7.1",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"author": "Mickaël Austoni",
|
|
9
|
+
"homepage": "https://github.com/getsoren/create-boilerplate-vite-react-ts#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/getsoren/create-boilerplate-vite-react-ts.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/getsoren/create-boilerplate-vite-react-ts/issues"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"create-boilerplate-vite-react-ts": "bin/create-app.cjs"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "vite",
|
|
22
|
+
"build": "tsc && vite build",
|
|
23
|
+
"create": "node bin/create-app.cjs dist --axios --i18next --react-query --react-router",
|
|
24
|
+
"lint": "eslint . --max-warnings=0 && tsc --noEmit",
|
|
25
|
+
"preview": "vite preview",
|
|
26
|
+
"test": "yarn lint && vitest",
|
|
27
|
+
"prepare": "husky install",
|
|
28
|
+
"release": "commit-and-tag-version"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"react": "^18.2.0",
|
|
32
|
+
"react-dom": "^18.2.0",
|
|
33
|
+
"yargs": "^17.7.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
37
|
+
"@testing-library/react": "^14.0.0",
|
|
38
|
+
"@testing-library/user-event": "^14.4.3",
|
|
39
|
+
"@types/react": "^18.2.14",
|
|
40
|
+
"@types/react-dom": "^18.2.6",
|
|
41
|
+
"@vitejs/plugin-react": "^3.1.0",
|
|
42
|
+
"@getsoren/eslint-config-react-soren": "^1.14.0",
|
|
43
|
+
"husky": "^8.0.3",
|
|
44
|
+
"jsdom": "^22.1.0",
|
|
45
|
+
"typescript": "^4.9.5",
|
|
46
|
+
"vite": "^4.3.9",
|
|
47
|
+
"vitest": "^0.32.2",
|
|
48
|
+
"commit-and-tag-version": "^12.6.0"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"react",
|
|
52
|
+
"react create app",
|
|
53
|
+
"vite create app",
|
|
54
|
+
"react router",
|
|
55
|
+
"i18next",
|
|
56
|
+
"react-query",
|
|
57
|
+
"javascript",
|
|
58
|
+
"typescript"
|
|
59
|
+
],
|
|
60
|
+
"commit-and-tag-version": {
|
|
61
|
+
"releaseCommitMessageFormat": "chore(release): {{currentTag}} [skip ci]",
|
|
62
|
+
"tagPrefix": ""
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_Public folder_**
|
|
Binary file
|
package/src/App.test.tsx
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render } from "@testing-library/react";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import App from "@/App";
|
|
4
|
+
|
|
5
|
+
test("render <App />", () => {
|
|
6
|
+
const { getByText } = render(<App />);
|
|
7
|
+
const title = getByText("create-boilerplate-vite-react-ts");
|
|
8
|
+
|
|
9
|
+
expect(title).toBeInTheDocument();
|
|
10
|
+
});
|
package/src/App.tsx
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains assets files like images, fonts, ..._**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all data display components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all feedback components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all inputs components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all layouts components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all navigation components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all surfaces components_**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains all utils components_**
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from "react-router-dom";
|
|
2
|
+
import ROUTES from "@/constants/routes";
|
|
3
|
+
import Contact from "@/pages/Contact";
|
|
4
|
+
import Home from "@/pages/Home";
|
|
5
|
+
|
|
6
|
+
const router = createBrowserRouter(
|
|
7
|
+
createRoutesFromElements(
|
|
8
|
+
<>
|
|
9
|
+
<Route path={ROUTES.home} element={<Home />} />
|
|
10
|
+
<Route path={ROUTES.contact} element={<Contact />} />
|
|
11
|
+
</>,
|
|
12
|
+
),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const Router = () => <RouterProvider router={router} />;
|
|
16
|
+
|
|
17
|
+
export default Router;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
**_This directory contains reusable Feature Components.
|
|
2
|
+
A Feature Component is a concept inspired by Redux in which
|
|
3
|
+
all logic required for a feature is co-located to a single directory.
|
|
4
|
+
A Feature Component is often composed of many other components,
|
|
5
|
+
either local or shared. The same is true for all resources:
|
|
6
|
+
utils, types, hooks, and so on._**
|
|
7
|
+
|
|
8
|
+
**_Feature Components often include side effects._**
|
|
9
|
+
|
|
10
|
+
**_f using Redux, and interacts with the Store,
|
|
11
|
+
the Feature Component will include a slice file
|
|
12
|
+
that defines the “slice” of the Redux Store the feature represents._**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains reusable React Hooks._**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
**_This directory contains translation files._**
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
**_This directory contains Page Components.
|
|
2
|
+
Each Page Component is associated with a route.
|
|
3
|
+
Page Components compose the content of a page by importing
|
|
4
|
+
Components and Feature Components. A Page Component
|
|
5
|
+
should rarely include side effects, and should instead
|
|
6
|
+
delegate side effects to Feature Components_**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import ROUTES from "@/constants/routes";
|
|
3
|
+
|
|
4
|
+
const Contact = () => (
|
|
5
|
+
<>
|
|
6
|
+
<h1>create-boilerplate-vite-react-ts</h1>
|
|
7
|
+
<h2>Contact</h2>
|
|
8
|
+
<Link to={ROUTES.home}>Go to home</Link>
|
|
9
|
+
</>
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export default Contact;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import ROUTES from "@/constants/routes";
|
|
3
|
+
|
|
4
|
+
const Home = () => (
|
|
5
|
+
<>
|
|
6
|
+
<h1>create-boilerplate-vite-react-ts</h1>
|
|
7
|
+
<h2>Home</h2>
|
|
8
|
+
<Link to={ROUTES.contact}>Go to contact</Link>
|
|
9
|
+
</>
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export default Home;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This resolves the issue of typescript
|
|
2
|
+
// not recognizing the types of the dependencies
|
|
3
|
+
declare module "@tanstack/react-query";
|
|
4
|
+
declare module "axios";
|
|
5
|
+
declare module "i18next";
|
|
6
|
+
declare module "i18next-browser-languagedetector";
|
|
7
|
+
declare module "react-i18next";
|
|
8
|
+
declare module "react-router-dom";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": [
|
|
7
|
+
"DOM",
|
|
8
|
+
"DOM.Iterable",
|
|
9
|
+
"ESNext"
|
|
10
|
+
],
|
|
11
|
+
"allowJs": false,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"esModuleInterop": false,
|
|
14
|
+
"allowSyntheticDefaultImports": true,
|
|
15
|
+
"strict": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"module": "ESNext",
|
|
18
|
+
"moduleResolution": "Node",
|
|
19
|
+
"resolveJsonModule": true,
|
|
20
|
+
"isolatedModules": true,
|
|
21
|
+
"importsNotUsedAsValues": "error",
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"noEmit": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"jsx": "react-jsx",
|
|
26
|
+
"paths": {
|
|
27
|
+
"@/*": [
|
|
28
|
+
"src/*"
|
|
29
|
+
],
|
|
30
|
+
"~/*": [
|
|
31
|
+
"./*"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"types": [
|
|
35
|
+
"vitest/globals"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"include": [
|
|
39
|
+
"src"
|
|
40
|
+
],
|
|
41
|
+
"references": [
|
|
42
|
+
{
|
|
43
|
+
"path": "./tsconfig.node.json"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"composite": true,
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"allowSyntheticDefaultImports": true,
|
|
7
|
+
"resolveJsonModule": true
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"package.json"
|
|
11
|
+
],
|
|
12
|
+
"include": [
|
|
13
|
+
"vite.config.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import { defineConfig } from "vitest/config";
|
|
4
|
+
|
|
5
|
+
// https://vitejs.dev/config/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [react()],
|
|
8
|
+
resolve: {
|
|
9
|
+
alias: [
|
|
10
|
+
{ find: "@", replacement: resolve(__dirname, "src") },
|
|
11
|
+
{ find: "~", replacement: resolve(__dirname) },
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
test: {
|
|
15
|
+
environment: "jsdom",
|
|
16
|
+
globals: true,
|
|
17
|
+
setupFiles: "src/test.config.ts",
|
|
18
|
+
},
|
|
19
|
+
});
|