@wavemaker-ai/wm-reactnative-cli 1.0.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 +236 -0
- package/assets/CLI-EnvironmentVariable.png +0 -0
- package/assets/EnvironmentVariable.png +0 -0
- package/assets/EnvironmentVariable1.png +0 -0
- package/files/ui-build.js +331 -0
- package/index.js +381 -0
- package/package.json +39 -0
- package/src/android.js +479 -0
- package/src/command.js +552 -0
- package/src/config.js +11 -0
- package/src/custom-logger/progress-bar.js +97 -0
- package/src/custom-logger/steps.js +117 -0
- package/src/custom-logger/task-logger.js +147 -0
- package/src/exec.js +73 -0
- package/src/expo-launcher.js +596 -0
- package/src/ios.js +517 -0
- package/src/logger.js +104 -0
- package/src/mobileprovision-parse/index.js +72 -0
- package/src/project-sync.service.js +390 -0
- package/src/requirements.js +250 -0
- package/src/utils.js +100 -0
- package/src/web-preview-launcher.js +548 -0
- package/src/zip.js +19 -0
- package/templates/embed/android/ReactNativeAppFragment.java +78 -0
- package/templates/embed/android/SplashScreenReactActivityLifecycleListener.kt +41 -0
- package/templates/embed/android/fragment_react_native_app.xml +14 -0
- package/templates/embed/ios/ReactNativeView.h +12 -0
- package/templates/embed/ios/ReactNativeView.m +59 -0
- package/templates/embed/ios/ReactNativeView.swift +53 -0
- package/templates/expo-camera-patch/useWebQRScanner.js +100 -0
- package/templates/ios-build-patch/podFIlePostInstall.js +72 -0
- package/templates/package/packageLock.json +14334 -0
- package/templates/wm-rn-runtime/App.js +479 -0
- package/templates/wm-rn-runtime/App.navigator.js +109 -0
- package/test.js +0 -0
- package/tools-site/index.html.template +17 -0
- package/tools-site/page_background.svg +99 -0
- package/tools-site/qrcode.js +614 -0
- package/tools-site/styles.css +39 -0
package/index.js
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
prepareProject,ejectProject, build, embed
|
|
5
|
+
} = require('./src/command');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const { LocalStorage } = require('node-localstorage');
|
|
8
|
+
const {
|
|
9
|
+
runExpo, runAndroid, runIos, sync, runESBuildWebPreview
|
|
10
|
+
} = require('./src/expo-launcher');
|
|
11
|
+
const { runWeb } = require('./src/web-preview-launcher');
|
|
12
|
+
const updateNotifier = require('update-notifier');
|
|
13
|
+
const pkg = require('./package.json');
|
|
14
|
+
const { canDoAndroidBuild, canDoIosBuild, showConfirmation } = require('./src/requirements');
|
|
15
|
+
updateNotifier({
|
|
16
|
+
pkg: pkg,
|
|
17
|
+
updateCheckInterval : 60 * 60 * 1000
|
|
18
|
+
}).notify({
|
|
19
|
+
defer: false
|
|
20
|
+
});
|
|
21
|
+
const prompt = require('prompt');
|
|
22
|
+
const logger = require('./src/logger');
|
|
23
|
+
const {calculateTotalSteps, androidBuildSteps, previewSteps} = require('./src/custom-logger/steps');
|
|
24
|
+
const {overallProgressBar} = require('./src/custom-logger/progress-bar')
|
|
25
|
+
const taskLogger = require('./src/custom-logger/task-logger').spinnerBar;
|
|
26
|
+
|
|
27
|
+
global.rootDir = process.env.WM_REACTNATIVE_CLI || `${os.homedir()}/.wm-reactnative-cli`;
|
|
28
|
+
global.localStorage = new LocalStorage(`${global.rootDir}/.store`);
|
|
29
|
+
global.WM_REPO_SCOPE = '@wavemaker';
|
|
30
|
+
// src is the web react native project zip
|
|
31
|
+
|
|
32
|
+
async function handleDeprecatedCommands(args) {
|
|
33
|
+
const syncCommand = `wm-reactnative sync ${args.previewUrl} ${args.clean ? '--clean' : ''} ${args.useProxy ? '--useProxy' : ''}`;
|
|
34
|
+
const response = await showConfirmation(
|
|
35
|
+
`Would you like to execute ${syncCommand} (yes/no) ?`
|
|
36
|
+
);
|
|
37
|
+
if (response !== 'y' && response !== 'yes') {
|
|
38
|
+
process.exit();
|
|
39
|
+
}
|
|
40
|
+
sync(args.previewUrl, args.clean, args.useProxy);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const args = require('yargs')
|
|
44
|
+
.command('build', 'build the project to generate android and ios folders', yargs => {
|
|
45
|
+
yargs.command('android [src] [options]', 'build for android', yargs => {
|
|
46
|
+
yargs.option('appId', {
|
|
47
|
+
alias: 'appId',
|
|
48
|
+
describe: 'unique application identifier',
|
|
49
|
+
type: 'string'
|
|
50
|
+
})
|
|
51
|
+
.option('aks', {
|
|
52
|
+
alias: 'aKeyStore',
|
|
53
|
+
describe: '(Android) path to keystore',
|
|
54
|
+
type: 'string'
|
|
55
|
+
})
|
|
56
|
+
.option('asp', {
|
|
57
|
+
alias: 'aStorePassword',
|
|
58
|
+
describe: '(Android) password to keystore',
|
|
59
|
+
type: 'string'
|
|
60
|
+
})
|
|
61
|
+
.option('aka', {
|
|
62
|
+
alias: 'aKeyAlias',
|
|
63
|
+
describe: '(Android) Alias name',
|
|
64
|
+
type: 'string'
|
|
65
|
+
})
|
|
66
|
+
.option('akp', {
|
|
67
|
+
alias: 'aKeyPassword',
|
|
68
|
+
describe: '(Android) password for key.',
|
|
69
|
+
type: 'string'
|
|
70
|
+
})
|
|
71
|
+
.option('p', {
|
|
72
|
+
alias: 'packageType',
|
|
73
|
+
describe: 'apk (or) bundle',
|
|
74
|
+
default: 'apk',
|
|
75
|
+
choices: ['apk', 'bundle']
|
|
76
|
+
})
|
|
77
|
+
.option('architecture', {
|
|
78
|
+
alias: 'arch',
|
|
79
|
+
describe: 'Specify the target architectures for the build (e.g., armeabi-v7a, arm64-v8a, x86, x86_64)',
|
|
80
|
+
type: 'array',
|
|
81
|
+
choices: ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'],
|
|
82
|
+
})
|
|
83
|
+
}, args => {
|
|
84
|
+
args.platform = 'android';
|
|
85
|
+
if(args.interactive){
|
|
86
|
+
overallProgressBar.enable();
|
|
87
|
+
// taskLogger.enableProgressBar();
|
|
88
|
+
}else{
|
|
89
|
+
overallProgressBar.disable();
|
|
90
|
+
// taskLogger.disableProgressBar();
|
|
91
|
+
}
|
|
92
|
+
global.verbose = args.verbose;
|
|
93
|
+
const totalCount = calculateTotalSteps(androidBuildSteps);
|
|
94
|
+
overallProgressBar.setTotal(totalCount);
|
|
95
|
+
build(args);
|
|
96
|
+
})
|
|
97
|
+
.command('ios [src] [options]', 'build for iOS', yargs => {
|
|
98
|
+
yargs.option('ic', {
|
|
99
|
+
alias: 'iCertificate',
|
|
100
|
+
describe: '(iOS) path of p12 certificate to use',
|
|
101
|
+
type: 'string'
|
|
102
|
+
})
|
|
103
|
+
.option('icp', {
|
|
104
|
+
alias: 'iCertificatePassword',
|
|
105
|
+
describe: '(iOS) password to unlock certificate',
|
|
106
|
+
type: 'string'
|
|
107
|
+
})
|
|
108
|
+
.option('ipf', {
|
|
109
|
+
alias: 'iProvisioningFile',
|
|
110
|
+
describe: '(iOS) path of the provisional profile to use',
|
|
111
|
+
type: 'string'
|
|
112
|
+
});
|
|
113
|
+
}, args => {
|
|
114
|
+
args.platform = 'ios';
|
|
115
|
+
if(args.interactive){
|
|
116
|
+
overallProgressBar.enable();
|
|
117
|
+
// taskLogger.enableProgressBar();
|
|
118
|
+
}else{
|
|
119
|
+
overallProgressBar.disable();
|
|
120
|
+
// taskLogger.disableProgressBar();
|
|
121
|
+
}
|
|
122
|
+
global.verbose = args.verbose;
|
|
123
|
+
const totalCount = calculateTotalSteps(androidBuildSteps);
|
|
124
|
+
overallProgressBar.setTotal(totalCount);
|
|
125
|
+
build(args)
|
|
126
|
+
})
|
|
127
|
+
yargs.positional('src', {
|
|
128
|
+
describe: 'path of rn project',
|
|
129
|
+
default: './',
|
|
130
|
+
type: 'string',
|
|
131
|
+
normalize: true
|
|
132
|
+
})
|
|
133
|
+
.option('dest', {
|
|
134
|
+
alias: 'dest',
|
|
135
|
+
describe: 'dest folder where the react native project will be extracted to',
|
|
136
|
+
type: 'string'
|
|
137
|
+
})
|
|
138
|
+
.option('bt', {
|
|
139
|
+
alias: 'buildType',
|
|
140
|
+
describe: 'development (or) debug (or) production (or) release',
|
|
141
|
+
default: 'debug',
|
|
142
|
+
coerce: (val) => {
|
|
143
|
+
if (val === 'development') {
|
|
144
|
+
return 'debug';
|
|
145
|
+
}
|
|
146
|
+
if (val === 'production') {
|
|
147
|
+
return 'release';
|
|
148
|
+
}
|
|
149
|
+
return val;
|
|
150
|
+
},
|
|
151
|
+
choices: ['development', 'debug', 'production', 'release']
|
|
152
|
+
})
|
|
153
|
+
.option('localrnruntimepath', {
|
|
154
|
+
alias: 'localrnruntimepath',
|
|
155
|
+
describe: 'local path pointing to the app-rn-runtime folder',
|
|
156
|
+
type: 'string'
|
|
157
|
+
})
|
|
158
|
+
.option('auto-eject', {
|
|
159
|
+
alias: 'autoEject',
|
|
160
|
+
describe: 'If set to true then project will be eject automatically without prompting any confirmations',
|
|
161
|
+
default: false,
|
|
162
|
+
type: 'boolean'
|
|
163
|
+
})
|
|
164
|
+
.option('verbose', {
|
|
165
|
+
describe: 'If set to true, then detailed logs will be displayed.',
|
|
166
|
+
default: false,
|
|
167
|
+
type: 'boolean'
|
|
168
|
+
})
|
|
169
|
+
.option('interactive', {
|
|
170
|
+
alias: 'i',
|
|
171
|
+
describe: 'if set true, progress bar will show',
|
|
172
|
+
default: false,
|
|
173
|
+
type: 'boolean'
|
|
174
|
+
});
|
|
175
|
+
})
|
|
176
|
+
.command('eject expo [src] [dest]',
|
|
177
|
+
'Removes Expo and generate pure react native project.',
|
|
178
|
+
yargs => {
|
|
179
|
+
yargs.positional('src', {
|
|
180
|
+
describe: 'path of React Native project',
|
|
181
|
+
default: './',
|
|
182
|
+
type: 'string',
|
|
183
|
+
normalize: true
|
|
184
|
+
})
|
|
185
|
+
.option('dest', {
|
|
186
|
+
alias: 'dest',
|
|
187
|
+
describe: 'dest folder where the react native project will be extracted to',
|
|
188
|
+
type: 'string'
|
|
189
|
+
})
|
|
190
|
+
},
|
|
191
|
+
(args) => {
|
|
192
|
+
ejectProject(args);
|
|
193
|
+
}).command(
|
|
194
|
+
'prepare expo [src] [dest]',
|
|
195
|
+
'Prepare Expo and generate RN native project.',
|
|
196
|
+
(yargs) => {
|
|
197
|
+
yargs
|
|
198
|
+
.positional('src', {
|
|
199
|
+
describe: 'path of React Native project',
|
|
200
|
+
default: './',
|
|
201
|
+
type: 'string',
|
|
202
|
+
normalize: true,
|
|
203
|
+
})
|
|
204
|
+
.option('dest', {
|
|
205
|
+
alias: 'dest',
|
|
206
|
+
describe:
|
|
207
|
+
'dest folder where the react native project will be extracted to',
|
|
208
|
+
type: 'string',
|
|
209
|
+
});
|
|
210
|
+
},
|
|
211
|
+
async (args) => {
|
|
212
|
+
prepareProject(args);
|
|
213
|
+
}
|
|
214
|
+
).command('embed', '',
|
|
215
|
+
yargs => {
|
|
216
|
+
yargs.command('android [src]',
|
|
217
|
+
'Embed React Native project with Native Android project',
|
|
218
|
+
yargs => {},
|
|
219
|
+
(args) => {
|
|
220
|
+
args.platform = 'android';
|
|
221
|
+
return embed(args);
|
|
222
|
+
}).command('ios [src]',
|
|
223
|
+
'Embed React Native project with Native iOS project.',
|
|
224
|
+
yargs => {},
|
|
225
|
+
(args) => {
|
|
226
|
+
args.platform = 'ios';
|
|
227
|
+
return embed(args);
|
|
228
|
+
}).positional('src', {
|
|
229
|
+
describe: 'path of React Native project',
|
|
230
|
+
default: './',
|
|
231
|
+
type: 'string',
|
|
232
|
+
normalize: true
|
|
233
|
+
})
|
|
234
|
+
.option('dest', {
|
|
235
|
+
alias: 'dest',
|
|
236
|
+
describe: 'dest folder where the react native project will be extracted to',
|
|
237
|
+
type: 'string'
|
|
238
|
+
})
|
|
239
|
+
.option('modulePath', {
|
|
240
|
+
alias: 'mp',
|
|
241
|
+
describe: 'path to the app module that needs to be embedded.',
|
|
242
|
+
type: 'string',
|
|
243
|
+
requiresArg: true
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
).command('run', '', (yargs) => {
|
|
247
|
+
yargs.command('expo <previewUrl>',
|
|
248
|
+
'Embed React Native project with Native Android project',
|
|
249
|
+
yargs => {
|
|
250
|
+
yargs.option('web', {
|
|
251
|
+
describe: 'If set to true then web will be started.',
|
|
252
|
+
default: false,
|
|
253
|
+
type: 'boolean'
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
async (args) => {
|
|
257
|
+
console.log(`Command run expo is no longer supported, instead use sync command`);
|
|
258
|
+
await handleDeprecatedCommands(args)
|
|
259
|
+
// if (args.clean) {
|
|
260
|
+
// localStorage.clear();
|
|
261
|
+
// }
|
|
262
|
+
// runExpo(args.previewUrl, args.web, args.clean)
|
|
263
|
+
}).command('web-preview <previewUrl>',
|
|
264
|
+
'launches React Native app in web browser.',
|
|
265
|
+
yargs => {
|
|
266
|
+
yargs.option('proxyHost', {
|
|
267
|
+
describe: 'If provided, this will be used as the host name to the proxy server. By default, ip address is used as host name.'
|
|
268
|
+
}).option('basePath', {
|
|
269
|
+
describe: 'Base Path at which the web preview has to be server.',
|
|
270
|
+
default: '/rn-bundle/',
|
|
271
|
+
})
|
|
272
|
+
.option('verbose', {
|
|
273
|
+
describe: 'If set to true, then detailed logs will be displayed.',
|
|
274
|
+
default: false,
|
|
275
|
+
type: 'boolean'
|
|
276
|
+
})
|
|
277
|
+
.option('interactive', {
|
|
278
|
+
alias: 'i',
|
|
279
|
+
describe: 'if set true, progress bar will show',
|
|
280
|
+
default: false,
|
|
281
|
+
type: 'boolean'
|
|
282
|
+
});
|
|
283
|
+
},
|
|
284
|
+
(args) => {
|
|
285
|
+
if (args.clean) {
|
|
286
|
+
localStorage.clear();
|
|
287
|
+
}
|
|
288
|
+
if(args.interactive){
|
|
289
|
+
overallProgressBar.enable();
|
|
290
|
+
// taskLogger.enableProgressBar();
|
|
291
|
+
}else{
|
|
292
|
+
overallProgressBar.disable();
|
|
293
|
+
// taskLogger.disableProgressBar();
|
|
294
|
+
}
|
|
295
|
+
global.verbose = args.verbose;
|
|
296
|
+
const totalCount = calculateTotalSteps(previewSteps);
|
|
297
|
+
const splits = args.previewUrl.split('#');
|
|
298
|
+
args.previewUrl = splits[0];
|
|
299
|
+
const authToken = splits[1];
|
|
300
|
+
if (args.esbuild) {
|
|
301
|
+
overallProgressBar.setTotal(totalCount-previewSteps[4].total);
|
|
302
|
+
runESBuildWebPreview(args.previewUrl, args.clean, authToken);
|
|
303
|
+
} else {
|
|
304
|
+
overallProgressBar.setTotal(totalCount);
|
|
305
|
+
runWeb(args.previewUrl, args.clean, authToken, args.proxyHost, args.basePath);
|
|
306
|
+
}
|
|
307
|
+
}).command('android <previewUrl>',
|
|
308
|
+
'launches React Native app in a Android device.',
|
|
309
|
+
yargs => {},
|
|
310
|
+
async (args) => {
|
|
311
|
+
console.log(`Command run android is no longer supported, instead use sync command`);
|
|
312
|
+
await handleDeprecatedCommands(args);
|
|
313
|
+
// if (args.clean) {
|
|
314
|
+
// localStorage.clear();
|
|
315
|
+
// }
|
|
316
|
+
// if (await canDoAndroidBuild()) {
|
|
317
|
+
// runAndroid(args.previewUrl, args.clean);
|
|
318
|
+
// }
|
|
319
|
+
}).command('ios <previewUrl>',
|
|
320
|
+
'launches React Native app in a iOS device.',
|
|
321
|
+
yargs => {},
|
|
322
|
+
async (args) => {
|
|
323
|
+
console.log(`Command run ios is no longer supported, instead use sync command`);
|
|
324
|
+
await handleDeprecatedCommands(args);
|
|
325
|
+
// if (args.clean) {
|
|
326
|
+
// localStorage.clear();
|
|
327
|
+
// }
|
|
328
|
+
// if (await canDoIosBuild()) {
|
|
329
|
+
// runIos(args.previewUrl, args.clean);
|
|
330
|
+
// }
|
|
331
|
+
}).positional('previewUrl', {
|
|
332
|
+
describe: 'Pereview Url of the React Native app.',
|
|
333
|
+
type: 'string'
|
|
334
|
+
}).option('clean', {
|
|
335
|
+
describe: 'If set to true then all existing folders are removed.',
|
|
336
|
+
default: false,
|
|
337
|
+
type: 'boolean'
|
|
338
|
+
});
|
|
339
|
+
})
|
|
340
|
+
.command('sync [previewUrl]', '', (yargs) => {
|
|
341
|
+
yargs.positional('previewUrl', {
|
|
342
|
+
describe: 'Pereview Url of the React Native app.',
|
|
343
|
+
type: 'string'
|
|
344
|
+
}).option('useProxy', {
|
|
345
|
+
describe: 'If set to true then all preview requests are routed through a internal proxy server.',
|
|
346
|
+
default: false,
|
|
347
|
+
type: 'boolean'
|
|
348
|
+
}).option('clean', {
|
|
349
|
+
describe: 'If set to true then all existing folders are removed.',
|
|
350
|
+
default: false,
|
|
351
|
+
type: 'boolean'
|
|
352
|
+
})
|
|
353
|
+
.option('verbose', {
|
|
354
|
+
describe: 'If set to true, then detailed logs will be displayed.',
|
|
355
|
+
default: false,
|
|
356
|
+
type: 'boolean'
|
|
357
|
+
})
|
|
358
|
+
.option('interactive', {
|
|
359
|
+
alias: 'i',
|
|
360
|
+
describe: 'if set true, progress bar will show',
|
|
361
|
+
default: false,
|
|
362
|
+
type: 'boolean'
|
|
363
|
+
});
|
|
364
|
+
}, (args) => {
|
|
365
|
+
if (args.clean) {
|
|
366
|
+
localStorage.clear();
|
|
367
|
+
}
|
|
368
|
+
if(args.interactive){
|
|
369
|
+
overallProgressBar.enable();
|
|
370
|
+
// taskLogger.enableProgressBar();
|
|
371
|
+
}else{
|
|
372
|
+
overallProgressBar.disable();
|
|
373
|
+
// taskLogger.disableProgressBar();
|
|
374
|
+
}
|
|
375
|
+
global.verbose = args.verbose;
|
|
376
|
+
const totalCount = calculateTotalSteps(previewSteps);
|
|
377
|
+
overallProgressBar.setTotal(totalCount);
|
|
378
|
+
sync(args.previewUrl, args.clean, args.useProxy);
|
|
379
|
+
})
|
|
380
|
+
.help('h')
|
|
381
|
+
.alias('h', 'help').argv;
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wavemaker-ai/wm-reactnative-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"wm-reactnative": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"axios": "^0.24.0",
|
|
16
|
+
"chalk": "^4.1.2",
|
|
17
|
+
"execa": "^4.0.3",
|
|
18
|
+
"express": "^4.18.1",
|
|
19
|
+
"extract-zip": "^2.0.1",
|
|
20
|
+
"fs-extra": "^9.0.1",
|
|
21
|
+
"htmlencode": "0.0.4",
|
|
22
|
+
"http-proxy": "^1.18.1",
|
|
23
|
+
"node-localstorage": "^2.2.1",
|
|
24
|
+
"open": "^8.4.0",
|
|
25
|
+
"plist": "^3.0.2",
|
|
26
|
+
"prompt": "^1.0.0",
|
|
27
|
+
"properties-reader": "^2.2.0",
|
|
28
|
+
"qs": "^6.10.3",
|
|
29
|
+
"request": "^2.88.2",
|
|
30
|
+
"rimraf": "^2.7.1",
|
|
31
|
+
"semver": "^7.3.2",
|
|
32
|
+
"shell-argument-escape": "^0.1.2",
|
|
33
|
+
"update-notifier": "^5.1.0",
|
|
34
|
+
"winston": "^3.3.3",
|
|
35
|
+
"xcode": "^3.0.1",
|
|
36
|
+
"yargs": "^15.4.0",
|
|
37
|
+
"yarn": "^1.22.10"
|
|
38
|
+
}
|
|
39
|
+
}
|