@startupjs/cli 0.56.0-alpha.6 → 0.57.0-canary.0
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 +20 -12
- package/commands/build.js +13 -0
- package/commands/index.js +7 -0
- package/commands/pm/init-pm.js +30 -0
- package/commands/pm/pr.js +12 -0
- package/commands/pm/task.js +12 -0
- package/commands/pm/utils.js +8 -0
- package/commands/postinstall.js +17 -0
- package/commands/start-production.js +21 -0
- package/index.js +23 -669
- package/package.json +10 -18
- package/corepack.sh +0 -52
- package/link/index.js +0 -9
- package/link/log.js +0 -33
- package/link/path.js +0 -61
- package/link/postLinkAndroid.js +0 -15
- package/link/postLinkIOS.js +0 -8
- package/link/pushNotificationsLinker/AndroidLinker.js +0 -144
- package/link/pushNotificationsLinker/IosLinker.js +0 -137
- package/link/pushNotificationsLinker/constants.js +0 -114
- package/link/pushNotificationsLinker/index.js +0 -37
- package/link/stylesLinker.js +0 -47
package/index.js
CHANGED
|
@@ -1,682 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const CLI_VERSION = require('./package.json').version
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import url from 'url'
|
|
3
|
+
import { dirname, join } from 'path'
|
|
4
|
+
import { readFileSync } from 'fs'
|
|
5
|
+
import * as commands from './commands/index.js'
|
|
7
6
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
7
|
+
const __filename = url.fileURLToPath(import.meta.url)
|
|
8
|
+
const packageJson = JSON.parse(readFileSync(join(dirname(__filename), 'package.json')))
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
path.dirname(require.resolve('@startupjs/patches')),
|
|
15
|
-
'patches'
|
|
16
|
-
)
|
|
17
|
-
// patch-package requires the path to be relative
|
|
18
|
-
PATCHES_DIR = path.relative(process.cwd(), PATCHES_DIR)
|
|
19
|
-
} catch (err) {
|
|
20
|
-
console.error(err)
|
|
21
|
-
console.error('ERROR!!! Patches packages not found. Falling back to local patches folder')
|
|
22
|
-
PATCHES_DIR = './patches'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let PM_SCRIPTS_PATH
|
|
26
|
-
try {
|
|
27
|
-
PM_SCRIPTS_PATH = path.join(
|
|
28
|
-
path.dirname(require.resolve('@startupjs/pm')),
|
|
29
|
-
'scripts.sh'
|
|
30
|
-
)
|
|
31
|
-
} catch (err) {
|
|
32
|
-
console.error(err)
|
|
33
|
-
console.error('ERROR!!! @startupjs/pm package wasn\'t found.')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let PATCHES_GESTURE_HANDLER_DIR
|
|
37
|
-
try {
|
|
38
|
-
PATCHES_GESTURE_HANDLER_DIR = path.join(
|
|
39
|
-
path.dirname(require.resolve('@startupjs/patches')),
|
|
40
|
-
'patches_gestureHandler'
|
|
41
|
-
)
|
|
42
|
-
// patch-package requires the path to be relative
|
|
43
|
-
PATCHES_GESTURE_HANDLER_DIR = path.relative(process.cwd(), PATCHES_GESTURE_HANDLER_DIR)
|
|
44
|
-
} catch (err) {
|
|
45
|
-
console.error(err)
|
|
46
|
-
console.error('ERROR!!! Gesture handler patches not found.')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const LINK = !!process.env.LINK
|
|
50
|
-
const LOCAL_DIR = process.env.LOCAL_DIR || '.'
|
|
51
|
-
|
|
52
|
-
const DEPENDENCIES = [
|
|
53
|
-
// Install alpha version of startupjs when running the alpha of cli
|
|
54
|
-
`startupjs@${STARTUPJS_VERSION}`,
|
|
55
|
-
'react-native-svg@^14.0.0',
|
|
56
|
-
'nconf@^0.10.0',
|
|
57
|
-
'react',
|
|
58
|
-
'react-dom',
|
|
59
|
-
'axios@^0.26.0' // For making AJAX requests
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
const DEV_DEPENDENCIES = [
|
|
63
|
-
'eslint@latest',
|
|
64
|
-
'eslint-config-startupjs',
|
|
65
|
-
'husky@^4.3.0',
|
|
66
|
-
'lint-staged'
|
|
67
|
-
]
|
|
68
|
-
|
|
69
|
-
const REMOVE_DEPENDENCIES = [
|
|
70
|
-
'@babel/core',
|
|
71
|
-
'@babel/runtime',
|
|
72
|
-
'@react-native/eslint-config',
|
|
73
|
-
'metro-react-native-babel-preset'
|
|
74
|
-
]
|
|
75
|
-
|
|
76
|
-
const REMOVE_FILES = [
|
|
77
|
-
'.prettierrc.js',
|
|
78
|
-
'.eslintrc.js',
|
|
79
|
-
'.flowconfig',
|
|
80
|
-
'App.js',
|
|
81
|
-
'babel.config.js',
|
|
82
|
-
'metro.config.js'
|
|
83
|
-
]
|
|
84
|
-
|
|
85
|
-
const SCRIPTS_ORIG = {}
|
|
86
|
-
|
|
87
|
-
// Development
|
|
88
|
-
|
|
89
|
-
SCRIPTS_ORIG.start = ({ inspect } = {}) => oneLine(`
|
|
90
|
-
npx concurrently
|
|
91
|
-
"${SCRIPTS_ORIG.web}"
|
|
92
|
-
"${SCRIPTS_ORIG.server({ inspect })}"
|
|
93
|
-
`)
|
|
94
|
-
|
|
95
|
-
// Web
|
|
96
|
-
|
|
97
|
-
SCRIPTS_ORIG.web = oneLine(`
|
|
98
|
-
npx cross-env WEBPACK_DEV=1
|
|
99
|
-
npx webpack-dev-server --config webpack.web.config.cjs
|
|
100
|
-
`)
|
|
101
|
-
|
|
102
|
-
// Server
|
|
103
|
-
|
|
104
|
-
SCRIPTS_ORIG.server = ({ inspect } = {}) => oneLine(`
|
|
105
|
-
node
|
|
106
|
-
${inspect ? '--inspect' : ''}
|
|
107
|
-
--watch
|
|
108
|
-
--experimental-detect-module
|
|
109
|
-
server.js
|
|
110
|
-
`)
|
|
111
|
-
|
|
112
|
-
// Production
|
|
113
|
-
|
|
114
|
-
SCRIPTS_ORIG.build = ({ async } = {}) => oneLine(`
|
|
115
|
-
npx rimraf ./build &&
|
|
116
|
-
${async ? 'npx cross-env ASYNC=1' : ''}
|
|
117
|
-
npx webpack --config webpack.web.config.cjs
|
|
118
|
-
`)
|
|
119
|
-
|
|
120
|
-
SCRIPTS_ORIG.expoBuild = ({ async } = {}) => oneLine(`
|
|
121
|
-
npx expo export -p web
|
|
122
|
-
`)
|
|
123
|
-
|
|
124
|
-
SCRIPTS_ORIG.startProduction = oneLine(`
|
|
125
|
-
npx cross-env NODE_ENV=production
|
|
126
|
-
node --experimental-detect-module server.js
|
|
127
|
-
`)
|
|
128
|
-
|
|
129
|
-
SCRIPTS_ORIG.expoStartProduction = oneLine(`
|
|
130
|
-
npx cross-env NODE_ENV=production
|
|
131
|
-
node --experimental-detect-module --import='startupjs/nodeRegister' -e 'import("startupjs/startServer")'
|
|
132
|
-
`)
|
|
133
|
-
|
|
134
|
-
// Etc
|
|
135
|
-
|
|
136
|
-
SCRIPTS_ORIG.patchPackage = () => oneLine(`
|
|
137
|
-
npx patch-package --patch-dir ${PATCHES_DIR} && ${SCRIPTS_ORIG.patchGestureHandler()}
|
|
138
|
-
`)
|
|
139
|
-
|
|
140
|
-
SCRIPTS_ORIG.patchGestureHandler = () => PATCHES_GESTURE_HANDLER_DIR
|
|
141
|
-
? oneLine(`
|
|
142
|
-
(cat package.json | grep -q react-native-gesture-handler && npx patch-package --patch-dir ${PATCHES_GESTURE_HANDLER_DIR} || true)
|
|
143
|
-
`)
|
|
144
|
-
: 'true'
|
|
145
|
-
|
|
146
|
-
SCRIPTS_ORIG.postinstall = () => oneLine(`
|
|
147
|
-
${SCRIPTS_ORIG.patchPackage()}
|
|
148
|
-
`)
|
|
149
|
-
|
|
150
|
-
SCRIPTS_ORIG.testE2E = ({ inspect } = {}) => {
|
|
151
|
-
return oneLine(`
|
|
152
|
-
startupjs build --async && npx concurrently "startupjs start-production" "sleep 15s && npx playwright test $@" --kill-others --success first
|
|
153
|
-
`)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
SCRIPTS_ORIG.codegenTestE2E = ({ inspect } = {}) => {
|
|
157
|
-
return oneLine(`
|
|
158
|
-
startupjs build --async && npx concurrently "startupjs start-production" "npx playwright codegen $@"
|
|
159
|
-
`)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const SCRIPTS = {
|
|
163
|
-
start: 'startupjs start',
|
|
164
|
-
metro: 'react-native start --reset-cache',
|
|
165
|
-
web: 'startupjs web',
|
|
166
|
-
server: 'startupjs server',
|
|
167
|
-
postinstall: 'startupjs postinstall',
|
|
168
|
-
adb: 'adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:3010 tcp:3010',
|
|
169
|
-
'log-android-color': 'react-native log-android | ccze -m ansi -C -o nolookups',
|
|
170
|
-
'log-android': 'hash ccze 2>/dev/null && npm run log-android-color || (echo "WARNING! Falling back to plain logging. For colored logs install ccze - brew install ccze" && react-native log-android)',
|
|
171
|
-
android: 'react-native run-android && (npm run adb || true) && npm run log-android',
|
|
172
|
-
'android-release': 'react-native run-android --variant Release',
|
|
173
|
-
ios: 'react-native run-ios',
|
|
174
|
-
'ios-release': 'react-native run-ios --configuration Release',
|
|
175
|
-
build: 'startupjs build --async',
|
|
176
|
-
'start-production': 'startupjs start-production',
|
|
177
|
-
'test-e2e': 'startupjs test-e2e',
|
|
178
|
-
'codegen-test-e2e': 'startupjs codegen-test-e2e'
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const DEFAULT_TEMPLATE = 'ui'
|
|
182
|
-
const DEFAULT_YARN_VERSION = '4'
|
|
183
|
-
const TEMPLATES = {
|
|
184
|
-
simple: {
|
|
185
|
-
subTemplates: ['simple']
|
|
186
|
-
},
|
|
187
|
-
routing: {
|
|
188
|
-
subTemplates: ['simple', 'routing'],
|
|
189
|
-
packages: [
|
|
190
|
-
// === START APP PEER DEPS ===
|
|
191
|
-
'react-native-restart@^0.0.22'
|
|
192
|
-
// === END APP PEER DEPS ===
|
|
193
|
-
]
|
|
194
|
-
},
|
|
195
|
-
ui: {
|
|
196
|
-
subTemplates: ['simple', 'routing', 'ui'],
|
|
197
|
-
packages: [
|
|
198
|
-
// === START APP PEER DEPS ===
|
|
199
|
-
'react-native-restart@^0.0.22',
|
|
200
|
-
// === END APP PEER DEPS ===
|
|
10
|
+
const program = new Command()
|
|
11
|
+
.usage('<command> [options]')
|
|
12
|
+
.version(packageJson.version, '-v, --version', 'output the version of startupjs cli utility in this project')
|
|
201
13
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
'react-native-gesture-handler@^2.14.0',
|
|
206
|
-
'react-native-pager-view@^6.2.0'
|
|
207
|
-
// === END UI PEER DEPS ===
|
|
208
|
-
]
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
let templatesPath
|
|
213
|
-
|
|
214
|
-
// ----- init
|
|
215
|
-
|
|
216
|
-
commander
|
|
217
|
-
.command('init <projectName>')
|
|
218
|
-
.description('bootstrap a new startupjs application')
|
|
219
|
-
.option('--react-native <semver>', 'Use a particular semver of React Native as a template', 'latest')
|
|
220
|
-
.option('-t, --template <name>', 'Which startupjs template to use to bootstrap the project', DEFAULT_TEMPLATE)
|
|
221
|
-
.option('-y, --yarn <semver>', 'Use a particular semver of yarn', DEFAULT_YARN_VERSION)
|
|
222
|
-
.action(async (projectName, { reactNative, template, yarn }) => {
|
|
223
|
-
console.log('> run npx', projectName, { reactNative, template, yarn })
|
|
14
|
+
async function run () {
|
|
15
|
+
for (const command of Object.values(commands)) {
|
|
16
|
+
const { name, description, options = [], action } = command
|
|
224
17
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
await execa.command(
|
|
228
|
-
`${path.join(__dirname, 'corepack.sh')} ${yarn}`,
|
|
229
|
-
{ shell: true, stdio: 'inherit' }
|
|
230
|
-
)
|
|
231
|
-
} catch (e) {
|
|
232
|
-
throw Error('Setup corepack: ', e)
|
|
18
|
+
if (program.commands.find(cmd => cmd.name() === name)) {
|
|
19
|
+
throw new Error(`Attempted to override an already registered command: ${name}`)
|
|
233
20
|
}
|
|
234
21
|
|
|
235
|
-
const
|
|
22
|
+
const cmd = program.command(name)
|
|
23
|
+
if (description) cmd.description(description)
|
|
236
24
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
25
|
+
for (const option of options) {
|
|
26
|
+
const { name, description } = option
|
|
27
|
+
cmd.option(name, description)
|
|
240
28
|
}
|
|
241
29
|
|
|
242
|
-
|
|
243
|
-
await execa(
|
|
244
|
-
'mkdir',
|
|
245
|
-
['-p', LOCAL_DIR],
|
|
246
|
-
{ stdio: 'inherit' }
|
|
247
|
-
)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// init react-native application
|
|
251
|
-
await execa('npx', [
|
|
252
|
-
'--yes',
|
|
253
|
-
`react-native${'@' + reactNative}`,
|
|
254
|
-
'init',
|
|
255
|
-
'--skip-install',
|
|
256
|
-
projectName
|
|
257
|
-
].concat(['--version', reactNative]), {
|
|
258
|
-
cwd: path.join(process.cwd(), LOCAL_DIR),
|
|
259
|
-
stdio: 'inherit'
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
// specify yarn version
|
|
263
|
-
await execa('rm', ['-rf', 'node_modules'], {
|
|
264
|
-
cwd: projectPath,
|
|
265
|
-
stdio: 'inherit'
|
|
266
|
-
})
|
|
267
|
-
await execa('rm', ['-f', 'yarn.lock'], {
|
|
268
|
-
cwd: projectPath,
|
|
269
|
-
stdio: 'inherit'
|
|
270
|
-
})
|
|
271
|
-
await execa('corepack', ['use', `yarn@${yarn}`], {
|
|
272
|
-
cwd: projectPath,
|
|
273
|
-
stdio: 'inherit'
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
// remove extra files which are covered by startupjs core
|
|
277
|
-
if (REMOVE_FILES.length) {
|
|
278
|
-
await execa('rm', ['-f'].concat(REMOVE_FILES), {
|
|
279
|
-
cwd: projectPath,
|
|
280
|
-
stdio: 'inherit'
|
|
281
|
-
})
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
await execa('yarn', ['config', 'set', 'nodeLinker', 'node-modules'], {
|
|
285
|
-
cwd: projectPath,
|
|
286
|
-
stdio: 'inherit'
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
// remove extra dependencies which are covered by startupjs core
|
|
290
|
-
if (REMOVE_DEPENDENCIES.length) {
|
|
291
|
-
await execa('yarn', ['remove'].concat(REMOVE_DEPENDENCIES), {
|
|
292
|
-
cwd: projectPath,
|
|
293
|
-
stdio: 'inherit'
|
|
294
|
-
})
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// copy additional startupjs template files over react-native ones
|
|
298
|
-
console.log(`> Copy template '${template}'`)
|
|
299
|
-
for (const subTemplate of TEMPLATES[template].subTemplates) {
|
|
300
|
-
const subTemplatePath = path.join(templatesPath, subTemplate)
|
|
301
|
-
await recursivelyCopyFiles(subTemplatePath, projectPath)
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// install startupjs dependencies
|
|
305
|
-
await execa('yarn', ['add'].concat(DEPENDENCIES).concat(TEMPLATES[template].packages || []), {
|
|
306
|
-
cwd: projectPath,
|
|
307
|
-
stdio: 'inherit'
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
if (LINK) {
|
|
311
|
-
// TODO: Link startupjs packages. ref:
|
|
312
|
-
// https://stackoverflow.com/questions/48681642/yarn-workspaces-and-yarn-link
|
|
313
|
-
console.log('> TODO: Link startupjs packages for local install')
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (DEV_DEPENDENCIES.length) {
|
|
317
|
-
// install startupjs devDependencies
|
|
318
|
-
await execa('yarn', ['add', '-D'].concat(DEV_DEPENDENCIES), {
|
|
319
|
-
cwd: projectPath,
|
|
320
|
-
stdio: 'inherit'
|
|
321
|
-
})
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
console.log('> Update config.json')
|
|
325
|
-
updateConfigJson(projectPath, { projectName })
|
|
326
|
-
|
|
327
|
-
console.log('> Patch package.json')
|
|
328
|
-
patchPackageJson(projectPath)
|
|
329
|
-
|
|
330
|
-
console.log('> Add additional things to .gitignore')
|
|
331
|
-
appendGitignore(projectPath)
|
|
332
|
-
|
|
333
|
-
console.log('> Apply module patches from /patches/ folder')
|
|
334
|
-
await execa('yarn', ['postinstall'], {
|
|
335
|
-
cwd: projectPath,
|
|
336
|
-
stdio: 'inherit'
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
if (process.platform === 'darwin') {
|
|
340
|
-
await execa('pod', ['install'], {
|
|
341
|
-
cwd: path.join(projectPath, 'ios'),
|
|
342
|
-
stdio: 'inherit'
|
|
343
|
-
})
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (template === 'ui') {
|
|
347
|
-
await execa('startupjs', ['link'], {
|
|
348
|
-
cwd: projectPath,
|
|
349
|
-
stdio: 'inherit'
|
|
350
|
-
})
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
console.log(getSuccessInstructions(projectName))
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
// ----- init
|
|
357
|
-
|
|
358
|
-
commander
|
|
359
|
-
.command('start')
|
|
360
|
-
.description('Run "startupjs web" and "startupjs server" at the same time.')
|
|
361
|
-
.option('-i, --inspect', 'Use node --inspect')
|
|
362
|
-
.action(async (options) => {
|
|
363
|
-
await execa.command(
|
|
364
|
-
SCRIPTS_ORIG.start(options),
|
|
365
|
-
{ stdio: 'inherit', shell: true }
|
|
366
|
-
)
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
commander
|
|
370
|
-
.command('test-e2e')
|
|
371
|
-
.description('Run e2e tests')
|
|
372
|
-
.action(async (options) => {
|
|
373
|
-
await execa.command(
|
|
374
|
-
SCRIPTS_ORIG.testE2E(options),
|
|
375
|
-
{ stdio: 'inherit', shell: true }
|
|
376
|
-
)
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
commander
|
|
380
|
-
.command('codegen-test-e2e')
|
|
381
|
-
.description('Run codegen for e2e tests')
|
|
382
|
-
.action(async (options) => {
|
|
383
|
-
await execa.command(
|
|
384
|
-
SCRIPTS_ORIG.codegenTestE2E(options),
|
|
385
|
-
{ stdio: 'inherit', shell: true }
|
|
386
|
-
)
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
commander
|
|
390
|
-
.command('web')
|
|
391
|
-
.description('Compile (with webpack) and run web')
|
|
392
|
-
.action(async (options) => {
|
|
393
|
-
await execa.command(
|
|
394
|
-
SCRIPTS_ORIG.web,
|
|
395
|
-
{ stdio: 'inherit', shell: true }
|
|
396
|
-
)
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
commander
|
|
400
|
-
.command('server')
|
|
401
|
-
.description('Compile (with webpack) and run server')
|
|
402
|
-
.option('-i, --inspect', 'Use node --inspect')
|
|
403
|
-
.action(async (options) => {
|
|
404
|
-
await execa.command(
|
|
405
|
-
SCRIPTS_ORIG.server(options),
|
|
406
|
-
{ stdio: 'inherit', shell: true }
|
|
407
|
-
)
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
commander
|
|
411
|
-
.command('build')
|
|
412
|
-
.description('Build web bundles')
|
|
413
|
-
.option('-a, --async', 'Build with splitting code into async chunks loaded dynamically')
|
|
414
|
-
.action(async (options) => {
|
|
415
|
-
await execa.command(
|
|
416
|
-
isExpo() ? SCRIPTS_ORIG.expoBuild(options) : SCRIPTS_ORIG.build(options),
|
|
417
|
-
{ stdio: 'inherit', shell: true }
|
|
418
|
-
)
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
commander
|
|
422
|
-
.command('start-production')
|
|
423
|
-
.description('Start production')
|
|
424
|
-
.action(async (options) => {
|
|
425
|
-
await execa.command(
|
|
426
|
-
isExpo() ? SCRIPTS_ORIG.expoStartProduction : SCRIPTS_ORIG.startProduction,
|
|
427
|
-
{ stdio: 'inherit', shell: true }
|
|
428
|
-
)
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
commander
|
|
432
|
-
.command('patch-package')
|
|
433
|
-
.description('Apply required patches to libraries used by startupjs')
|
|
434
|
-
.action(async (options) => {
|
|
435
|
-
await execa.command(
|
|
436
|
-
SCRIPTS_ORIG.patchPackage(options),
|
|
437
|
-
{ stdio: 'inherit', shell: true }
|
|
438
|
-
)
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
commander
|
|
442
|
-
.command('link')
|
|
443
|
-
.description('Links files')
|
|
444
|
-
.action(async () => {
|
|
445
|
-
// this is important because ./link contains files that are initialized on require. Thus, 'glob' in ./linc/path does not work correctly when required in a header
|
|
446
|
-
const link = require('./link')
|
|
447
|
-
link()
|
|
448
|
-
})
|
|
449
|
-
|
|
450
|
-
commander
|
|
451
|
-
.command('android-link')
|
|
452
|
-
.description('Links android files')
|
|
453
|
-
.action(async () => {
|
|
454
|
-
console.warn('"startupjs android-link" is deprecated. Use "startupjs link" instead.')
|
|
455
|
-
// this is important because ./link contains files that are initialized on require. Thus, 'glob' in ./linc/path does not work correctly when required in a header
|
|
456
|
-
const link = require('./link')
|
|
457
|
-
link()
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
commander
|
|
461
|
-
.command('postinstall')
|
|
462
|
-
.description('Run startupjs postinstall scripts')
|
|
463
|
-
.action(async (options) => {
|
|
464
|
-
await execa.command(
|
|
465
|
-
SCRIPTS_ORIG.postinstall(options),
|
|
466
|
-
{ stdio: 'inherit', shell: true }
|
|
467
|
-
)
|
|
468
|
-
})
|
|
469
|
-
|
|
470
|
-
// ----- project management commands
|
|
471
|
-
|
|
472
|
-
commander
|
|
473
|
-
.command('init-pm')
|
|
474
|
-
.description('Create a new project on github from template')
|
|
475
|
-
.action(async () => {
|
|
476
|
-
await execa.command(`${PM_SCRIPTS_PATH} init-pm`, { shell: true, stdio: 'inherit' })
|
|
477
|
-
addPmScriptsToPackageJson() // add `yarn pm` and `yarn task` to package.json/scripts
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
commander
|
|
481
|
-
.command('task <issueNumber>')
|
|
482
|
-
.description('Create a task branch (or just switch to it if it already exists)')
|
|
483
|
-
.action(async (issueNumber) => {
|
|
484
|
-
await execa.command(`${PM_SCRIPTS_PATH} task ${issueNumber}`, { shell: true, stdio: 'inherit' })
|
|
485
|
-
})
|
|
486
|
-
|
|
487
|
-
commander
|
|
488
|
-
.command('pr [issueNumber]')
|
|
489
|
-
.description('Make PR for this task (or re-request review if it already exists)')
|
|
490
|
-
.action(async (issueNumber = '') => {
|
|
491
|
-
await execa.command(`${PM_SCRIPTS_PATH} pr ${issueNumber}`, { shell: true, stdio: 'inherit' })
|
|
492
|
-
})
|
|
493
|
-
|
|
494
|
-
// ----- helpers
|
|
495
|
-
|
|
496
|
-
async function recursivelyCopyFiles (sourcePath, targetPath) {
|
|
497
|
-
const fileNames = fs.readdirSync(sourcePath)
|
|
498
|
-
|
|
499
|
-
if (fileNames.length === 0) return
|
|
500
|
-
|
|
501
|
-
for (const fileName of fileNames) {
|
|
502
|
-
const filePath = path.join(sourcePath, fileName)
|
|
503
|
-
if (fs.lstatSync(filePath).isDirectory()) {
|
|
504
|
-
const subTargetPath = path.join(targetPath, fileName)
|
|
505
|
-
await execa(
|
|
506
|
-
'mkdir',
|
|
507
|
-
['-p', subTargetPath],
|
|
508
|
-
{ stdio: 'inherit' }
|
|
509
|
-
)
|
|
510
|
-
await recursivelyCopyFiles(filePath, subTargetPath)
|
|
511
|
-
} else {
|
|
512
|
-
await execa(
|
|
513
|
-
'cp',
|
|
514
|
-
[filePath, targetPath],
|
|
515
|
-
{ stdio: 'inherit' }
|
|
516
|
-
)
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
function patchPackageJson (projectPath) {
|
|
522
|
-
const packageJSONPath = path.join(projectPath, 'package.json')
|
|
523
|
-
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString())
|
|
524
|
-
|
|
525
|
-
delete packageJSON.scripts.test
|
|
526
|
-
delete packageJSON.devDependencies['babel-jest']
|
|
527
|
-
delete packageJSON.devDependencies['react-test-renderer']
|
|
528
|
-
delete packageJSON.devDependencies.jest
|
|
529
|
-
|
|
530
|
-
packageJSON.scripts = {
|
|
531
|
-
...packageJSON.scripts,
|
|
532
|
-
...SCRIPTS
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
packageJSON['lint-staged'] = {
|
|
536
|
-
'*.{js,jsx}': [
|
|
537
|
-
'eslint --fix',
|
|
538
|
-
'git add'
|
|
539
|
-
]
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
packageJSON.husky = {
|
|
543
|
-
hooks: {
|
|
544
|
-
'pre-commit': 'lint-staged'
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// FIXME: We can't use type=module now, because metro does not support ESM
|
|
549
|
-
// and does not provide ability to pass .cjs config.
|
|
550
|
-
// packageJSON.type = 'module'
|
|
551
|
-
packageJSON.sideEffects = ['*.css', '*.styl']
|
|
552
|
-
|
|
553
|
-
fs.writeFileSync(
|
|
554
|
-
packageJSONPath,
|
|
555
|
-
`${JSON.stringify(packageJSON, null, 2)}\n`
|
|
556
|
-
)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
function addPmScriptsToPackageJson () {
|
|
560
|
-
const projectPath = process.cwd()
|
|
561
|
-
const packageJSONPath = path.join(projectPath, 'package.json')
|
|
562
|
-
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString())
|
|
563
|
-
|
|
564
|
-
packageJSON.scripts = {
|
|
565
|
-
...packageJSON.scripts,
|
|
566
|
-
task: 'npx startupjs task',
|
|
567
|
-
pr: 'npx startupjs pr'
|
|
30
|
+
cmd.action(action)
|
|
568
31
|
}
|
|
569
32
|
|
|
570
|
-
|
|
571
|
-
packageJSONPath,
|
|
572
|
-
`${JSON.stringify(packageJSON, null, 2)}\n`
|
|
573
|
-
)
|
|
33
|
+
program.parse(process.argv)
|
|
574
34
|
}
|
|
575
35
|
|
|
576
|
-
|
|
577
|
-
const gitignorePath = path.join(projectPath, '.gitignore')
|
|
578
|
-
let gitignore = fs.readFileSync(gitignorePath).toString()
|
|
579
|
-
|
|
580
|
-
gitignore += `
|
|
581
|
-
# DB data
|
|
582
|
-
/data/
|
|
583
|
-
# Protection from accidentally commiting private npm keys to a public repo
|
|
584
|
-
.npmrc
|
|
585
|
-
# Mongo data when running in a docker dev container
|
|
586
|
-
/.mongo
|
|
587
|
-
# yarn
|
|
588
|
-
.yarn/
|
|
589
|
-
# sqlite
|
|
590
|
-
sqlite.db
|
|
591
|
-
`.replace(/\n\s+/g, '\n')
|
|
592
|
-
|
|
593
|
-
fs.writeFileSync(gitignorePath, gitignore)
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
function updateConfigJson (projectPath, options) {
|
|
597
|
-
const configJsonPath = path.join(projectPath, 'config.json')
|
|
598
|
-
let configJson = fs.readFileSync(configJsonPath).toString()
|
|
599
|
-
|
|
600
|
-
try {
|
|
601
|
-
const templateFn = template(configJson)
|
|
602
|
-
const sessionSecret = generateRandomString(32)
|
|
603
|
-
configJson = templateFn({ ...options, sessionSecret })
|
|
604
|
-
} catch (e) {
|
|
605
|
-
console.log(
|
|
606
|
-
'\x1b[31m' +
|
|
607
|
-
'config.json has not been updated, update it manually!' +
|
|
608
|
-
'\x1b[0m'
|
|
609
|
-
)
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
fs.writeFileSync(
|
|
613
|
-
configJsonPath,
|
|
614
|
-
configJson
|
|
615
|
-
)
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
function generateRandomString (length = 0) {
|
|
619
|
-
let result = ''
|
|
620
|
-
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
621
|
-
const charactersLength = characters.length
|
|
622
|
-
|
|
623
|
-
for (let i = 0; i < length; i++) {
|
|
624
|
-
result += characters.charAt(
|
|
625
|
-
Math.floor(
|
|
626
|
-
Math.random() * charactersLength
|
|
627
|
-
)
|
|
628
|
-
)
|
|
629
|
-
}
|
|
630
|
-
return result
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
function getSuccessInstructions (projectName) {
|
|
634
|
-
return `
|
|
635
|
-
StartupJS installation successful!
|
|
636
|
-
|
|
637
|
-
To use private packages, log in via yarn npm login.
|
|
638
|
-
|
|
639
|
-
INSTRUCTIONS
|
|
640
|
-
|
|
641
|
-
$ cd ${projectName}
|
|
642
|
-
|
|
643
|
-
Run each command in a separate terminal tab:
|
|
644
|
-
|
|
645
|
-
1. Start server:
|
|
646
|
-
|
|
647
|
-
$ yarn server
|
|
648
|
-
|
|
649
|
-
2. Start web:
|
|
650
|
-
|
|
651
|
-
$ yarn web
|
|
652
|
-
|
|
653
|
-
and go to http://localhost:3000
|
|
654
|
-
|
|
655
|
-
3. Start native:
|
|
656
|
-
|
|
657
|
-
$ yarn metro
|
|
658
|
-
$ yarn android
|
|
659
|
-
$ yarn ios
|
|
660
|
-
`
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// Replace all new lines with spaces to properly handle cli-commands
|
|
664
|
-
function oneLine (str) {
|
|
665
|
-
return str.replace(/\s+/g, ' ')
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
function isExpo (rootPath = process.cwd()) {
|
|
669
|
-
try {
|
|
670
|
-
const packageJson = fs.readFileSync(path.resolve(rootPath, './package.json'), 'utf8')
|
|
671
|
-
const { dependencies = {} } = JSON.parse(packageJson)
|
|
672
|
-
return Boolean(dependencies.expo)
|
|
673
|
-
} catch {
|
|
674
|
-
return false
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
exports.run = (options = {}) => {
|
|
679
|
-
if (!options.templatesPath) throw Error('templatesPath not found!')
|
|
680
|
-
templatesPath = options.templatesPath
|
|
681
|
-
commander.parse(process.argv)
|
|
682
|
-
}
|
|
36
|
+
export { run }
|