@@ -4,29 +4,111 @@ const fs = require("fs/promises");
4
4
const path = require ( "path" ) ;
5
5
6
6
const toml = require ( "@iarna/toml" ) ;
7
+ const PackageJson = require ( "@npmcli/package-json" ) ;
7
8
const YAML = require ( "yaml" ) ;
8
- const sort = require ( "sort-package-json" ) ;
9
9
10
- function escapeRegExp ( string ) {
10
+ const cleanupCypressFiles = ( filesEntries ) =>
11
+ filesEntries . flatMap ( ( [ filePath , content ] ) => {
12
+ const newContent = content
13
+ . replace ( "npx ts-node" , "node" )
14
+ . replace ( "create-user.ts" , "create-user.js" )
15
+ . replace ( "delete-user.ts" , "delete-user.js" ) ;
16
+
17
+ return [ fs . writeFile ( filePath , newContent ) ] ;
18
+ } ) ;
19
+
20
+ const cleanupDeployWorkflow = ( deployWorkflow , deployWorkflowPath ) => {
21
+ delete deployWorkflow . jobs . typecheck ;
22
+ deployWorkflow . jobs . deploy . needs = deployWorkflow . jobs . deploy . needs . filter (
23
+ ( need ) => need !== "typecheck"
24
+ ) ;
25
+
26
+ return [ fs . writeFile ( deployWorkflowPath , YAML . stringify ( deployWorkflow ) ) ] ;
27
+ } ;
28
+
29
+ const cleanupVitestConfig = ( vitestConfig , vitestConfigPath ) => {
30
+ const newVitestConfig = vitestConfig . replace (
31
+ "setup-test-env.ts" ,
32
+ "setup-test-env.js"
33
+ ) ;
34
+
35
+ return [ fs . writeFile ( vitestConfigPath , newVitestConfig ) ] ;
36
+ } ;
37
+
38
+ const escapeRegExp = ( string ) =>
11
39
// $& means the whole matched string
12
- return string . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
13
- }
40
+ string . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
14
41
15
- function getRandomString ( length ) {
16
- return crypto . randomBytes ( length ) . toString ( "hex" ) ;
17
- }
42
+ const getRandomString = ( length ) => crypto . randomBytes ( length ) . toString ( "hex" ) ;
18
43
19
- async function main ( { rootDirectory, packageManager, isTypeScript } ) {
44
+ const readFileIfNotTypeScript = (
45
+ isTypeScript ,
46
+ filePath ,
47
+ parseFunction = ( result ) => result
48
+ ) =>
49
+ ( isTypeScript ? Promise . resolve ( ) : fs . readFile ( filePath , "utf-8" ) ) . then (
50
+ parseFunction
51
+ ) ;
52
+
53
+ const removeUnusedDependencies = ( dependencies , unusedDependencies ) =>
54
+ Object . fromEntries (
55
+ Object . entries ( dependencies ) . filter (
56
+ ( [ key ] ) => ! unusedDependencies . includes ( key )
57
+ )
58
+ ) ;
59
+
60
+ const updatePackageJson = ( { APP_NAME , isTypeScript, packageJson } ) => {
61
+ const {
62
+ devDependencies,
63
+ prisma : { seed : prismaSeed , ...prisma } ,
64
+ scripts : { typecheck, validate, ...scripts } ,
65
+ } = packageJson . content ;
66
+
67
+ packageJson . update ( {
68
+ name : APP_NAME ,
69
+ devDependencies : isTypeScript
70
+ ? devDependencies
71
+ : removeUnusedDependencies ( devDependencies , [
72
+ "ts-node" ,
73
+ "vite-tsconfig-paths" ,
74
+ ] ) ,
75
+ prisma : isTypeScript
76
+ ? prisma
77
+ : {
78
+ ...prisma ,
79
+ seed : prismaSeed
80
+ . replace ( "ts-node" , "node" )
81
+ . replace ( "seed.ts" , "seed.js" ) ,
82
+ } ,
83
+ scripts : isTypeScript
84
+ ? { ...scripts , typecheck, validate }
85
+ : { ...scripts , validate : validate . replace ( " typecheck" , "" ) } ,
86
+ } ) ;
87
+ } ;
88
+
89
+ const main = async ( { isTypeScript, packageManager, rootDirectory } ) => {
20
90
const README_PATH = path . join ( rootDirectory , "README.md" ) ;
21
91
const FLY_TOML_PATH = path . join ( rootDirectory , "fly.toml" ) ;
22
92
const EXAMPLE_ENV_PATH = path . join ( rootDirectory , ".env.example" ) ;
23
93
const ENV_PATH = path . join ( rootDirectory , ".env" ) ;
24
- const PACKAGE_JSON_PATH = path . join ( rootDirectory , "package.json" ) ;
25
- const DEPLOY_YAML_PATH = path . join (
94
+ const DEPLOY_WORKFLOW_PATH = path . join (
26
95
rootDirectory ,
27
- ".github/workflows/deploy.yml"
96
+ ".github" ,
97
+ "workflows" ,
98
+ "deploy.yml"
28
99
) ;
29
100
const DOCKERFILE_PATH = path . join ( rootDirectory , "Dockerfile" ) ;
101
+ const CYPRESS_SUPPORT_PATH = path . join ( rootDirectory , "cypress" , "support" ) ;
102
+ const CYPRESS_COMMANDS_PATH = path . join ( CYPRESS_SUPPORT_PATH , "commands.js" ) ; // We renamed this during `create-remix`
103
+ const CREATE_USER_COMMAND_PATH = path . join (
104
+ CYPRESS_SUPPORT_PATH ,
105
+ "create-user.js"
106
+ ) ; // We renamed this during `create-remix`
107
+ const DELETE_USER_COMMAND_PATH = path . join (
108
+ CYPRESS_SUPPORT_PATH ,
109
+ "delete-user.js"
110
+ ) ; // We renamed this during `create-remix`
111
+ const VITEST_CONFIG_PATH = path . join ( rootDirectory , "vitest.config.js" ) ; // We renamed this during `create-remix`
30
112
31
113
const REPLACER = "indie-stack-template" ;
32
114
@@ -37,15 +119,31 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
37
119
// get rid of anything that's not allowed in an app name
38
120
. replace ( / [ ^ a - z A - Z 0 - 9 - _ ] / g, "-" ) ;
39
121
40
- const [ prodContent , readme , env , packageJson , deployConfig , dockerfile ] =
41
- await Promise . all ( [
42
- fs . readFile ( FLY_TOML_PATH , "utf-8" ) ,
43
- fs . readFile ( README_PATH , "utf-8" ) ,
44
- fs . readFile ( EXAMPLE_ENV_PATH , "utf-8" ) ,
45
- fs . readFile ( PACKAGE_JSON_PATH , "utf-8" ) . then ( ( s ) => JSON . parse ( s ) ) ,
46
- fs . readFile ( DEPLOY_YAML_PATH , "utf-8" ) . then ( ( s ) => YAML . parse ( s ) ) ,
47
- fs . readFile ( DOCKERFILE_PATH , "utf-8" ) ,
48
- ] ) ;
122
+ const [
123
+ prodContent ,
124
+ readme ,
125
+ env ,
126
+ dockerfile ,
127
+ cypressCommands ,
128
+ createUserCommand ,
129
+ deleteUserCommand ,
130
+ deployWorkflow ,
131
+ vitestConfig ,
132
+ packageJson ,
133
+ ] = await Promise . all ( [
134
+ fs . readFile ( FLY_TOML_PATH , "utf-8" ) ,
135
+ fs . readFile ( README_PATH , "utf-8" ) ,
136
+ fs . readFile ( EXAMPLE_ENV_PATH , "utf-8" ) ,
137
+ fs . readFile ( DOCKERFILE_PATH , "utf-8" ) ,
138
+ readFileIfNotTypeScript ( isTypeScript , CYPRESS_COMMANDS_PATH ) ,
139
+ readFileIfNotTypeScript ( isTypeScript , CREATE_USER_COMMAND_PATH ) ,
140
+ readFileIfNotTypeScript ( isTypeScript , DELETE_USER_COMMAND_PATH ) ,
141
+ readFileIfNotTypeScript ( isTypeScript , DEPLOY_WORKFLOW_PATH , ( s ) =>
142
+ YAML . parse ( s )
143
+ ) ,
144
+ readFileIfNotTypeScript ( isTypeScript , VITEST_CONFIG_PATH ) ,
145
+ PackageJson . load ( rootDirectory ) ,
146
+ ] ) ;
49
147
50
148
const newEnv = env . replace (
51
149
/ ^ S E S S I O N _ S E C R E T = .* $ / m,
@@ -60,25 +158,6 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
60
158
APP_NAME
61
159
) ;
62
160
63
- let saveDeploy = null ;
64
- if ( ! isTypeScript ) {
65
- delete packageJson . scripts . typecheck ;
66
- packageJson . scripts . validate = packageJson . scripts . validate . replace (
67
- " typecheck" ,
68
- ""
69
- ) ;
70
-
71
- delete deployConfig . jobs . typecheck ;
72
- deployConfig . jobs . deploy . needs = deployConfig . jobs . deploy . needs . filter (
73
- ( n ) => n !== "typecheck"
74
- ) ;
75
- // only write the deploy config if it's changed
76
- saveDeploy = fs . writeFile ( DEPLOY_YAML_PATH , YAML . stringify ( deployConfig ) ) ;
77
- }
78
-
79
- const newPackageJson =
80
- JSON . stringify ( sort ( { ...packageJson , name : APP_NAME } ) , null , 2 ) + "\n" ;
81
-
82
161
const lockfile = {
83
162
npm : "package-lock.json" ,
84
163
yarn : "yarn.lock" ,
@@ -92,28 +171,49 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
92
171
)
93
172
: dockerfile ;
94
173
95
- await Promise . all ( [
174
+ updatePackageJson ( { APP_NAME , isTypeScript, packageJson } ) ;
175
+
176
+ const fileOperationPromises = [
96
177
fs . writeFile ( FLY_TOML_PATH , toml . stringify ( prodToml ) ) ,
97
178
fs . writeFile ( README_PATH , newReadme ) ,
98
179
fs . writeFile ( ENV_PATH , newEnv ) ,
99
- fs . writeFile ( PACKAGE_JSON_PATH , newPackageJson ) ,
100
180
fs . writeFile ( DOCKERFILE_PATH , newDockerfile ) ,
101
- saveDeploy ,
181
+ packageJson . save ( ) ,
102
182
fs . copyFile (
103
183
path . join ( rootDirectory , "remix.init" , "gitignore" ) ,
104
184
path . join ( rootDirectory , ".gitignore" )
105
185
) ,
106
- fs . rm ( path . join ( rootDirectory , ".github/ ISSUE_TEMPLATE" ) , {
186
+ fs . rm ( path . join ( rootDirectory , ".github" , " ISSUE_TEMPLATE") , {
107
187
recursive : true ,
108
188
} ) ,
109
- fs . rm ( path . join ( rootDirectory , ".github/PULL_REQUEST_TEMPLATE.md" ) ) ,
110
- ] ) ;
189
+ fs . rm ( path . join ( rootDirectory , ".github" , "PULL_REQUEST_TEMPLATE.md" ) ) ,
190
+ ] ;
191
+
192
+ if ( ! isTypeScript ) {
193
+ fileOperationPromises . push (
194
+ ...cleanupCypressFiles ( [
195
+ [ CYPRESS_COMMANDS_PATH , cypressCommands ] ,
196
+ [ CREATE_USER_COMMAND_PATH , createUserCommand ] ,
197
+ [ DELETE_USER_COMMAND_PATH , deleteUserCommand ] ,
198
+ ] )
199
+ ) ;
200
+
201
+ fileOperationPromises . push (
202
+ ...cleanupDeployWorkflow ( deployWorkflow , DEPLOY_WORKFLOW_PATH )
203
+ ) ;
111
204
112
- execSync ( `npm run setup` , { stdio : "inherit" , cwd : rootDirectory } ) ;
205
+ fileOperationPromises . push (
206
+ ...cleanupVitestConfig ( vitestConfig , VITEST_CONFIG_PATH )
207
+ ) ;
208
+ }
209
+
210
+ await Promise . all ( fileOperationPromises ) ;
211
+
212
+ execSync ( "npm run setup" , { cwd : rootDirectory , stdio : "inherit" } ) ;
113
213
114
214
execSync ( "npm run format -- --loglevel warn" , {
115
- stdio : "inherit" ,
116
215
cwd : rootDirectory ,
216
+ stdio : "inherit" ,
117
217
} ) ;
118
218
119
219
console . log (
@@ -122,6 +222,6 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
122
222
Start development with \`npm run dev\`
123
223
` . trim ( )
124
224
) ;
125
- }
225
+ } ;
126
226
127
227
module . exports = main ;
0 commit comments