@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.
Files changed (39) hide show
  1. package/README.md +236 -0
  2. package/assets/CLI-EnvironmentVariable.png +0 -0
  3. package/assets/EnvironmentVariable.png +0 -0
  4. package/assets/EnvironmentVariable1.png +0 -0
  5. package/files/ui-build.js +331 -0
  6. package/index.js +381 -0
  7. package/package.json +39 -0
  8. package/src/android.js +479 -0
  9. package/src/command.js +552 -0
  10. package/src/config.js +11 -0
  11. package/src/custom-logger/progress-bar.js +97 -0
  12. package/src/custom-logger/steps.js +117 -0
  13. package/src/custom-logger/task-logger.js +147 -0
  14. package/src/exec.js +73 -0
  15. package/src/expo-launcher.js +596 -0
  16. package/src/ios.js +517 -0
  17. package/src/logger.js +104 -0
  18. package/src/mobileprovision-parse/index.js +72 -0
  19. package/src/project-sync.service.js +390 -0
  20. package/src/requirements.js +250 -0
  21. package/src/utils.js +100 -0
  22. package/src/web-preview-launcher.js +548 -0
  23. package/src/zip.js +19 -0
  24. package/templates/embed/android/ReactNativeAppFragment.java +78 -0
  25. package/templates/embed/android/SplashScreenReactActivityLifecycleListener.kt +41 -0
  26. package/templates/embed/android/fragment_react_native_app.xml +14 -0
  27. package/templates/embed/ios/ReactNativeView.h +12 -0
  28. package/templates/embed/ios/ReactNativeView.m +59 -0
  29. package/templates/embed/ios/ReactNativeView.swift +53 -0
  30. package/templates/expo-camera-patch/useWebQRScanner.js +100 -0
  31. package/templates/ios-build-patch/podFIlePostInstall.js +72 -0
  32. package/templates/package/packageLock.json +14334 -0
  33. package/templates/wm-rn-runtime/App.js +479 -0
  34. package/templates/wm-rn-runtime/App.navigator.js +109 -0
  35. package/test.js +0 -0
  36. package/tools-site/index.html.template +17 -0
  37. package/tools-site/page_background.svg +99 -0
  38. package/tools-site/qrcode.js +614 -0
  39. 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
+ }