@corva/create-app 0.17.0-0 → 0.17.0-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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [0.17.0-1](https://github.com/corva-ai/create-corva-app/compare/v0.17.0-0...v0.17.0-1) (2021-12-03)
6
+
7
+
8
+ ### Features
9
+
10
+ * add scheduler type option ([e2d3d3d](https://github.com/corva-ai/create-corva-app/commit/e2d3d3dcc7154d841b3da342a36a7edfbc8488e4))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * diff app types, runtimes and templates ([7c52817](https://github.com/corva-ai/create-corva-app/commit/7c528173535b9a915372ec469df8043b3830e387))
16
+
5
17
  ## [0.17.0-0](https://github.com/corva-ai/create-corva-app/compare/v0.16.0-1...v0.17.0-0) (2021-11-23)
6
18
 
7
19
  ## [0.16.0-1](https://github.com/corva-ai/create-corva-app/compare/v0.16.0-0...v0.16.0-1) (2021-11-18)
@@ -0,0 +1,26 @@
1
+ const APP_RUNTIMES = {
2
+ UI: 'ui',
3
+ NODE12: 'nodejs12.x',
4
+ PYTHON3: 'python3.8',
5
+ };
6
+
7
+ const TEMPLATE_TYPES = {
8
+ UI: 'js',
9
+ UI_TS: 'ts',
10
+ NODE: 'node',
11
+ NODE_TYPESCRIPT: 'node-ts',
12
+ PYTHON: 'python',
13
+ };
14
+
15
+ const APP_TYPES = {
16
+ UI: 'ui',
17
+ SCHEDULER: 'scheduler',
18
+ STREAM: 'stream',
19
+ TASK: 'task',
20
+ };
21
+
22
+ module.exports = {
23
+ TEMPLATE_TYPES,
24
+ APP_RUNTIMES,
25
+ APP_TYPES,
26
+ };
@@ -1,3 +1,5 @@
1
+ const { APP_RUNTIMES, APP_TYPES, TEMPLATE_TYPES } = require('./cli');
2
+
1
3
  const defaultManifest = {
2
4
  format: 1,
3
5
  license: {
@@ -10,7 +12,7 @@ const defaultManifest = {
10
12
  authors: [],
11
13
  },
12
14
  application: {
13
- type: 'ui',
15
+ type: APP_TYPES.UI,
14
16
  key: 'app.key-goes-here',
15
17
  visibility: 'private',
16
18
  name: 'Name of My App',
@@ -68,16 +70,40 @@ const defaultDataAppPythonManifest = {
68
70
  };
69
71
 
70
72
  const defaultTimeSchedulerSettings = {
71
- scheduler_type: 'data_time',
72
73
  cron_string: '*/5 * * * *',
73
74
  };
74
75
 
75
76
  const defaultDepthSchedulerSettings = {
76
- scheduler_type: 'data_depth',
77
77
  depth_milestone: 1,
78
78
  };
79
79
 
80
- const MANIFEST_MANDATORY_KEYS = ['appType', 'appKey', 'appName', 'category', 'segments', 'runtime'];
80
+ const getManifestMandatoryKeys = (opts) => {
81
+ const keys = manifestOptions(opts.projectName).reduce((acc, option) => {
82
+ if (option.required) {
83
+ acc.push(option.name);
84
+ }
85
+
86
+ return acc;
87
+ }, []);
88
+
89
+ const { appType } = opts;
90
+
91
+ if (appType) {
92
+ if (appType !== APP_TYPES.UI) {
93
+ keys.push('runtime');
94
+ }
95
+
96
+ if (appType === APP_TYPES.SCHEDULER) {
97
+ keys.push('schedulerType');
98
+ }
99
+ }
100
+
101
+ return keys;
102
+ };
103
+
104
+ const SCHEDULER_TYPE_NATURAL_TIME = { name: 'Natural Time', value: 1 };
105
+ const SCHEDULER_TYPE_DATA_TIME = { name: 'Data Time', value: 2 };
106
+ const SCHEDULER_TYPE_DEPTH = { name: 'Date Depth', value: 4 };
81
107
 
82
108
  const manifestOptions = (projectName) => [
83
109
  { name: 'developerName', message: 'Enter the Developer Name', default: 'O&G Company' },
@@ -86,11 +112,36 @@ const manifestOptions = (projectName) => [
86
112
  type: 'rawlist',
87
113
  name: 'appType',
88
114
  message: 'Choose the App Type',
89
- default: 'ui',
90
- choices: ['ui', 'scheduler', 'stream', 'task'],
115
+ default: APP_TYPES.UI,
116
+ choices: Object.values(APP_TYPES),
117
+ required: true,
118
+ },
119
+ {
120
+ type: 'rawlist',
121
+ name: 'schedulerType',
122
+ message: 'Choose the scheduler type',
123
+ default: SCHEDULER_TYPE_NATURAL_TIME.name,
124
+ choices: [SCHEDULER_TYPE_NATURAL_TIME, SCHEDULER_TYPE_DATA_TIME, SCHEDULER_TYPE_DEPTH],
125
+ when: (answers) => answers.appType === APP_TYPES.SCHEDULER,
126
+ },
127
+ {
128
+ name: 'cronString',
129
+ message: 'Provide CRON string for the scheduler',
130
+ default: '*/5 * * * *',
131
+ when: (answers) => answers.appType === APP_TYPES.SCHEDULER,
132
+ },
133
+ {
134
+ name: 'appKey',
135
+ message: 'Enter the App Key',
136
+ default: 'app.key-goes-here',
137
+ required: true,
138
+ },
139
+ {
140
+ name: 'appName',
141
+ message: 'Enter the App Name',
142
+ default: projectName,
143
+ required: true,
91
144
  },
92
- { name: 'appKey', message: 'Enter the App Key', default: 'app.key-goes-here' },
93
- { name: 'appName', message: 'Enter the App Name', default: projectName },
94
145
  {
95
146
  name: 'description',
96
147
  message: 'Enter description',
@@ -101,20 +152,32 @@ const manifestOptions = (projectName) => [
101
152
  message: 'Enter summary',
102
153
  default: 'More information about this app goes here',
103
154
  },
104
- { name: 'category', message: 'Enter category', default: '' },
155
+ {
156
+ name: 'category',
157
+ message: 'Enter category',
158
+ default: '',
159
+ required: true,
160
+ },
105
161
  { name: 'website', message: 'Enter website', default: 'https://www.oandgexample.com/my-app/' },
106
162
  {
107
163
  type: 'rawlist',
108
164
  name: 'segments',
109
165
  message: 'Choose segments',
110
166
  choices: ['drilling', 'completion'],
167
+ required: true,
111
168
  },
112
169
  {
113
170
  type: 'rawlist',
114
171
  name: 'runtime',
115
172
  message: 'Choose runtime',
116
- choices: ['python3.8', 'nodejs12.x'],
117
- when: (answers) => answers.appType !== 'ui',
173
+ choices: (answers) => {
174
+ if (answers && answers.appType !== APP_TYPES.UI) {
175
+ return Object.values(APP_RUNTIMES).filter((value) => value !== APP_RUNTIMES.UI);
176
+ }
177
+
178
+ return Object.values(APP_RUNTIMES);
179
+ },
180
+ when: (answers) => answers.appType !== APP_TYPES.UI,
118
181
  },
119
182
  {
120
183
  type: 'rawlist',
@@ -122,7 +185,7 @@ const manifestOptions = (projectName) => [
122
185
  message: 'Please select the desired package manager',
123
186
  default: 'yarn',
124
187
  choices: ['yarn', 'npm'],
125
- when: (answers) => !answers.runtime || !answers.runtime.startsWith('python'),
188
+ when: (answers) => !answers.runtime || !answers.runtime.startsWith(TEMPLATE_TYPES.PYTHON),
126
189
  },
127
190
  {
128
191
  type: 'confirm',
@@ -130,14 +193,8 @@ const manifestOptions = (projectName) => [
130
193
  message: 'Would you like to use TypesScript?',
131
194
  default: false,
132
195
  when: (answers) =>
133
- (answers.runtime && answers.runtime.startsWith('nodejs')) || answers.appType === 'ui',
134
- },
135
- {
136
- type: 'rawlist',
137
- name: 'schedulerType',
138
- message: 'Choose schedulerType',
139
- choices: ['data_time', 'data_depth', 'natural_time'],
140
- when: (answers) => answers.appType === 'scheduler',
196
+ (answers.runtime && answers.runtime.startsWith(TEMPLATE_TYPES.NODE)) ||
197
+ answers.appType === APP_TYPES.UI,
141
198
  },
142
199
  ];
143
200
 
@@ -149,5 +206,8 @@ module.exports = {
149
206
  defaultTimeSchedulerSettings,
150
207
  defaultDepthSchedulerSettings,
151
208
  manifestOptions,
152
- MANIFEST_MANDATORY_KEYS,
209
+ getManifestMandatoryKeys,
210
+ SCHEDULER_TYPE_NATURAL_TIME,
211
+ SCHEDULER_TYPE_DATA_TIME,
212
+ SCHEDULER_TYPE_DEPTH,
153
213
  };
@@ -24,8 +24,8 @@ const dependencies = {
24
24
 
25
25
  const tsDependencies = {
26
26
  devDependencies: {
27
- "@tsconfig/create-react-app": "1.0.2",
28
- "@types/material-ui": "0.21.9",
27
+ '@tsconfig/create-react-app': '1.0.2',
28
+ '@types/material-ui': '0.21.9',
29
29
  '@types/react': '^17.0.22',
30
30
  '@types/react-dom': '^17.0.9',
31
31
  '@typescript-eslint/eslint-plugin': '^4.31.2',
@@ -1,7 +1,8 @@
1
+ const { APP_RUNTIMES, APP_TYPES, TEMPLATE_TYPES } = require('../constants/cli.js');
1
2
  const manifestConstants = require('../constants/manifest.js');
2
3
 
3
4
  function fillManifest(answers) {
4
- const runtime = answers.runtime || 'ui';
5
+ const runtime = answers.runtime || APP_RUNTIMES.UI;
5
6
 
6
7
  const defaultManifestProperties = _defaultManifestProperties({
7
8
  type: answers.appType,
@@ -33,7 +34,11 @@ function fillManifest(answers) {
33
34
  settings: {
34
35
  ...defaultManifestProperties.settings,
35
36
  runtime,
36
- ...defaultAppSettings({ type: answers.appType, schedulerType: answers.schedulerType }),
37
+ ...defaultAppSettings({
38
+ type: answers.appType,
39
+ schedulerType: answers.schedulerType,
40
+ cronString: answers.cronString,
41
+ }),
37
42
  },
38
43
  };
39
44
 
@@ -41,31 +46,32 @@ function fillManifest(answers) {
41
46
  }
42
47
 
43
48
  function _defaultManifestProperties({ type, runtime }) {
44
- if (type === 'ui') {
49
+ if (type === APP_TYPES.UI) {
45
50
  return manifestConstants.defaultUIAppManifest;
46
51
  }
47
52
 
48
- if (runtime.match(/python/)) {
53
+ if (runtime.startsWith(TEMPLATE_TYPES.PYTHON)) {
49
54
  return manifestConstants.defaultDataAppPythonManifest;
50
55
  }
51
56
 
52
57
  return manifestConstants.defaultDataAppNodeManifest;
53
58
  }
54
59
 
55
- function defaultAppSettings({ type, schedulerType }) {
60
+ function defaultAppSettings({ type, schedulerType, cronString }) {
56
61
  if (!schedulerType) {
57
62
  return {};
58
63
  }
59
64
 
60
65
  const schedulerAppSettings =
61
- schedulerType == 'data_depth'
66
+ schedulerType === manifestConstants.SCHEDULER_TYPE_DEPTH.value
62
67
  ? manifestConstants.defaultDepthSchedulerSettings
63
68
  : manifestConstants.defaultTimeSchedulerSettings;
64
69
 
65
70
  return {
66
71
  app: {
67
72
  ...schedulerAppSettings,
68
- scheduler_type: schedulerType || 'data_time',
73
+ scheduler_type: schedulerType,
74
+ cron_string: cronString,
69
75
  },
70
76
  };
71
77
  }
package/index.js CHANGED
@@ -23,6 +23,7 @@ const manifestConstants = require('./constants/manifest.js');
23
23
  const packageJson = require('./package.json');
24
24
  const { clear } = require('console');
25
25
  const spawn = require('cross-spawn');
26
+ const { APP_RUNTIMES, TEMPLATE_TYPES, APP_TYPES } = require('./constants/cli');
26
27
 
27
28
  const YARN_EXECUTABLE = 'yarn';
28
29
 
@@ -38,11 +39,6 @@ clear();
38
39
  let projectName;
39
40
  let program;
40
41
 
41
- const APP_TYPES = {
42
- UI: 'ui',
43
- NODE: 'node',
44
- };
45
-
46
42
  function startingMessage() {
47
43
  console.log(chalk.green(' Welcome to apps generator for:'));
48
44
  console.log(chalk.cyan(figlet.textSync('CORVA.AI', { horizontalLayout: 'full' })));
@@ -55,7 +51,7 @@ function checkNodeVersion() {
55
51
  console.log(
56
52
  chalk.red(
57
53
  `You are using Node ${process.version}.\n\n` +
58
- `Please update to Node 10 or higher for a better, fully supported experience.\n`
54
+ `Please update to Node 10 or higher for a better, fully supported experience.\n`
59
55
  )
60
56
  );
61
57
  // Fall back to latest supported react-scripts on Node 4
@@ -67,7 +63,7 @@ function checkOptions(opts) {
67
63
  let isValid = true;
68
64
  const values = {};
69
65
 
70
- manifestConstants.MANIFEST_MANDATORY_KEYS.forEach((key) => {
66
+ manifestConstants.getManifestMandatoryKeys(opts).forEach((key) => {
71
67
  if (!opts[key]) {
72
68
  isValid = false;
73
69
  }
@@ -99,8 +95,20 @@ async function initialChecks() {
99
95
  .choices(['npm', YARN_EXECUTABLE])
100
96
  );
101
97
 
102
- manifestConstants.MANIFEST_MANDATORY_KEYS.forEach((key) => {
103
- program.option(`--${key} [value]`);
98
+ manifestConstants.manifestOptions(projectName).forEach((value) => {
99
+ const option = new commander.Option(`--${value.name} [value]`, value.message);
100
+
101
+ if (value.choices) {
102
+ if (typeof value.choices === 'function') {
103
+ option.choices(value.choices());
104
+ } else {
105
+ option.choices(
106
+ value.choices.map((choice) => `${typeof choice === 'object' ? choice.value : choice}`)
107
+ );
108
+ }
109
+ }
110
+
111
+ program.addOption(option);
104
112
  });
105
113
 
106
114
  program.parse(process.argv);
@@ -109,11 +117,15 @@ async function initialChecks() {
109
117
 
110
118
  const opts = program.opts();
111
119
 
120
+ if (opts.schedulerType) {
121
+ opts.schedulerType = Number(opts.schedulerType);
122
+ }
123
+
112
124
  packageManager = opts.packageManager || packageManager;
113
125
  useTypescript = opts.useTypescript || useTypescript;
114
126
 
115
127
  if (opts.zip) {
116
- if (opts.zip === APP_TYPES.UI) {
128
+ if (opts.zip === APP_RUNTIMES.UI) {
117
129
  return uiScripts.zipAppSource(shouldUseYarn());
118
130
  }
119
131
 
@@ -137,7 +149,9 @@ async function initialChecks() {
137
149
 
138
150
  async function initPackage(manifest) {
139
151
  const appType = manifest.application.type;
140
- if (appType === APP_TYPES.UI) await ensureLatestVersion();
152
+ if (appType === APP_TYPES.UI) {
153
+ await ensureLatestVersion();
154
+ }
141
155
 
142
156
  const root = path.resolve(projectName);
143
157
 
@@ -153,17 +167,13 @@ async function initPackage(manifest) {
153
167
  // config for every possible version at this point, so just consolidate all versions of a runtime into a single
154
168
  // template directory.
155
169
  if (appType !== APP_TYPES.UI) {
156
- if (runtime.startsWith('python')) {
157
- runtime = 'python';
158
- } else if (runtime.startsWith('nodejs')) {
159
- runtime = 'node';
160
-
161
- if (useTypescript) {
162
- runtime += '-ts';
163
- }
170
+ if (runtime.startsWith(TEMPLATE_TYPES.PYTHON)) {
171
+ runtime = TEMPLATE_TYPES.PYTHON;
172
+ } else {
173
+ runtime = useTypescript ? TEMPLATE_TYPES.NODE_TYPESCRIPT : TEMPLATE_TYPES.NODE;
164
174
  }
165
- } else if (appType === APP_TYPES.UI) {
166
- runtime = useTypescript ? 'ts' : 'js';
175
+ } else {
176
+ runtime = useTypescript ? TEMPLATE_TYPES.UI_TS : TEMPLATE_TYPES.UI;
167
177
  }
168
178
 
169
179
  addTemplate(root, appType, runtime);
@@ -185,7 +195,7 @@ async function createApp(opts) {
185
195
  } else {
186
196
  console.log('Please fill your app Metadata');
187
197
 
188
- inquirer.prompt(manifestConstants.manifestOptions(projectName)).then((answers) => {
198
+ inquirer.prompt(manifestConstants.manifestOptions(projectName), opts).then((answers) => {
189
199
  packageManager = answers.packageManager || packageManager;
190
200
  useTypescript = answers.useTypescript || useTypescript;
191
201
 
@@ -222,15 +232,39 @@ function addTemplate(root, appType, runtime) {
222
232
  function configureApp(root, appType, runtime, manifest) {
223
233
  if (appType === APP_TYPES.UI) {
224
234
  addPackageJSON(root, manifest.application.name);
225
- } else if (runtime.startsWith(APP_TYPES.NODE)) {
235
+ } else if (runtime.startsWith(TEMPLATE_TYPES.NODE)) {
226
236
  updatePackageJSON(root, manifest.application.description, appType, runtime);
227
237
  }
238
+
239
+ if (runtime.startsWith(TEMPLATE_TYPES.PYTHON) && appType === APP_TYPES.SCHEDULER) {
240
+ patchSchedulerForPython(root, appType, runtime, manifest);
241
+ }
242
+ }
243
+
244
+ function patchSchedulerForPython(root, appType, runtime, manifest) {
245
+ const schedulerType = manifest.settings.app.scheduler_type;
246
+
247
+ if (schedulerType === manifestConstants.SCHEDULER_TYPE_DATA_TIME.value) {
248
+ return;
249
+ }
250
+
251
+ const templateFolder = path.resolve(__dirname, 'template', appType, runtime);
252
+ const originalType = 'ScheduledDataTimeEvent';
253
+ const replacementType =
254
+ schedulerType === manifestConstants.SCHEDULER_TYPE_DEPTH.value
255
+ ? 'ScheduledDepthEvent'
256
+ : 'ScheduledNaturalTimeEvent';
257
+ const patchedCode = fs
258
+ .readFileSync(path.join(templateFolder, 'lambda_function.py'), 'utf-8')
259
+ .replace(new RegExp(originalType, 'g'), replacementType);
260
+
261
+ fs.writeFileSync(path.join(root, 'lambda_function.py'), patchedCode);
228
262
  }
229
263
 
230
264
  function addPackageJSON(root, appName) {
231
265
  const devDependencies = {
232
266
  ...packageConstants.dependencies.devDependencies,
233
- ...(useTypescript && packageConstants.tsDependencies.devDependencies)
267
+ ...(useTypescript && packageConstants.tsDependencies.devDependencies),
234
268
  };
235
269
  const packageJson = {
236
270
  name: appName.replace(/\W/g, ''),
@@ -262,7 +296,7 @@ function updatePackageJSON(root, description, appType, runtime) {
262
296
 
263
297
  function installApp(appPath, appType, runtime) {
264
298
  switch (runtime) {
265
- case 'python': {
299
+ case TEMPLATE_TYPES.PYTHON: {
266
300
  break;
267
301
  }
268
302
  default: {
@@ -302,7 +336,7 @@ function installJsApp(appPath, appType) {
302
336
  console.log();
303
337
  console.log(`Success! Created ${projectName} at ${appPath}`);
304
338
 
305
- if (appType === APP_TYPES.UI) {
339
+ if (appType === APP_RUNTIMES.UI) {
306
340
  console.log('Inside that directory, you can run several commands:');
307
341
  helpCommands();
308
342
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corva/create-app",
3
- "version": "0.17.0-0",
3
+ "version": "0.17.0-1",
4
4
  "private": false,
5
5
  "description": "Create app to use it in CORVA.AI",
6
6
  "keywords": [
@@ -85,9 +85,12 @@ async function compressAppToZip(useYarn) {
85
85
  name: 'package.json',
86
86
  });
87
87
 
88
- ['manifest.json', 'config-overrides.js', 'tsconfig.json', useYarn ? 'yarn.lock' : 'package-lock.json'].forEach(
89
- (name) => archive.file(path.resolve(dirname, name), { name })
90
- );
88
+ [
89
+ 'manifest.json',
90
+ 'config-overrides.js',
91
+ 'tsconfig.json',
92
+ useYarn ? 'yarn.lock' : 'package-lock.json',
93
+ ].forEach((name) => archive.file(path.resolve(dirname, name), { name }));
91
94
 
92
95
  archive.directory(path.resolve(dirname, 'src'), 'src');
93
96