@corva/create-app 0.0.0-73c49372

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 (193) hide show
  1. package/README.md +211 -0
  2. package/bin/cca.js +5 -0
  3. package/bin/create-corva-app.cjs +30 -0
  4. package/common/node/.env +15 -0
  5. package/common/node/.env.sample +26 -0
  6. package/common/node/gitignore +130 -0
  7. package/common/package.json +3 -0
  8. package/common/python/.env +5 -0
  9. package/common/python/.env.sample +7 -0
  10. package/common/python/Makefile +15 -0
  11. package/common/python/gitignore +161 -0
  12. package/common/python/requirements.txt +2 -0
  13. package/lib/commands/attach.js +28 -0
  14. package/lib/commands/create.js +463 -0
  15. package/lib/commands/release.js +52 -0
  16. package/lib/commands/rerun.js +34 -0
  17. package/lib/commands/zip.js +39 -0
  18. package/lib/constants/cache.js +5 -0
  19. package/lib/constants/cli.js +24 -0
  20. package/lib/constants/manifest.js +262 -0
  21. package/lib/constants/messages.js +15 -0
  22. package/lib/constants/package.js +269 -0
  23. package/lib/flow.js +53 -0
  24. package/lib/flows/attach.js +8 -0
  25. package/lib/flows/lib/api.js +376 -0
  26. package/lib/flows/lib/create-zip-archive.js +83 -0
  27. package/lib/flows/lib/json.js +30 -0
  28. package/lib/flows/lib/manifest.js +81 -0
  29. package/lib/flows/lib/notification.js +142 -0
  30. package/lib/flows/lib/step-error.js +10 -0
  31. package/lib/flows/lib/waitForMs.js +3 -0
  32. package/lib/flows/prepare.js +6 -0
  33. package/lib/flows/release.js +26 -0
  34. package/lib/flows/rerun.js +8 -0
  35. package/lib/flows/steps/attach/add-app-to-stream.js +23 -0
  36. package/lib/flows/steps/attach/get-all-live-assets.js +135 -0
  37. package/lib/flows/steps/attach/index.js +5 -0
  38. package/lib/flows/steps/attach/prepare-data.js +19 -0
  39. package/lib/flows/steps/prepare-load-app-files.js +12 -0
  40. package/lib/flows/steps/release/add-label.js +10 -0
  41. package/lib/flows/steps/release/add-notes.js +10 -0
  42. package/lib/flows/steps/release/get-config.js +41 -0
  43. package/lib/flows/steps/release/prepare-data.js +12 -0
  44. package/lib/flows/steps/release/publish.js +11 -0
  45. package/lib/flows/steps/release/remove-failed-upload.js +21 -0
  46. package/lib/flows/steps/release/upload-zip-to-corva.js +62 -0
  47. package/lib/flows/steps/release/wait-for-build.js +36 -0
  48. package/lib/flows/steps/rerun/create-task.js +77 -0
  49. package/lib/flows/steps/rerun/ensure-that-app-in-stream.js +68 -0
  50. package/lib/flows/steps/rerun/get-app-version.js +111 -0
  51. package/lib/flows/steps/rerun/prepare-data.js +162 -0
  52. package/lib/flows/steps/rerun/prepare-well-and-stream-data.js +188 -0
  53. package/lib/flows/steps/rerun/rerun.js +13 -0
  54. package/lib/flows/steps/zip-cleanup.js +17 -0
  55. package/lib/flows/steps/zip-create-archive.js +15 -0
  56. package/lib/flows/steps/zip-file-list-resolve.js +260 -0
  57. package/lib/flows/steps/zip-prepare.js +20 -0
  58. package/lib/flows/steps/zip.js +6 -0
  59. package/lib/flows/zip-simple.js +6 -0
  60. package/lib/flows/zip.js +7 -0
  61. package/lib/helpers/cli-version.js +114 -0
  62. package/lib/helpers/commands.js +13 -0
  63. package/lib/helpers/logger.js +35 -0
  64. package/lib/helpers/manifest.js +74 -0
  65. package/lib/helpers/resolve-app-runtime.js +128 -0
  66. package/lib/helpers/utils.js +91 -0
  67. package/lib/helpers/versioning.js +94 -0
  68. package/lib/main.js +68 -0
  69. package/lib/options/api-key.js +6 -0
  70. package/lib/options/app-key.js +6 -0
  71. package/lib/options/app-version.js +3 -0
  72. package/lib/options/bump-version.js +19 -0
  73. package/lib/options/cache.js +11 -0
  74. package/lib/options/env.js +3 -0
  75. package/lib/options/original-cwd.js +3 -0
  76. package/lib/options/silent.js +3 -0
  77. package/package.json +104 -0
  78. package/template_extensions/corva/.commitlintrc.json +6 -0
  79. package/template_extensions/corva/.github/pull_request_template.md +14 -0
  80. package/template_extensions/corva/.github/workflows/code-checks.yml +15 -0
  81. package/template_extensions/corva/.github/workflows/develop.yml +17 -0
  82. package/template_extensions/corva/.github/workflows/feat-fix-delete.yml +14 -0
  83. package/template_extensions/corva/.github/workflows/feat-fix.yml +23 -0
  84. package/template_extensions/corva/.github/workflows/release-fix-X.X.X.yml +16 -0
  85. package/template_extensions/corva/.github/workflows/validate-pr-title.yml +19 -0
  86. package/template_extensions/corva/.husky/commit-msg +5 -0
  87. package/template_extensions/corva/.husky/pre-commit +4 -0
  88. package/templates/scheduler_data-time/javascript/README.md +19 -0
  89. package/templates/scheduler_data-time/javascript/__tests__/processor.spec.js +15 -0
  90. package/templates/scheduler_data-time/javascript/index.js +15 -0
  91. package/templates/scheduler_data-time/python/README.md +31 -0
  92. package/templates/scheduler_data-time/python/lambda_function.py +7 -0
  93. package/templates/scheduler_data-time/python/test/__init__.py +0 -0
  94. package/templates/scheduler_data-time/python/test/app_test.py +10 -0
  95. package/templates/scheduler_data-time/typescript/README.md +25 -0
  96. package/templates/scheduler_data-time/typescript/__tests__/processor.spec.ts +15 -0
  97. package/templates/scheduler_data-time/typescript/index.ts +8 -0
  98. package/templates/scheduler_depth/javascript/README.md +19 -0
  99. package/templates/scheduler_depth/javascript/__tests__/processor.spec.js +17 -0
  100. package/templates/scheduler_depth/javascript/index.js +15 -0
  101. package/templates/scheduler_depth/python/README.md +31 -0
  102. package/templates/scheduler_depth/python/lambda_function.py +7 -0
  103. package/templates/scheduler_depth/python/test/__init__.py +0 -0
  104. package/templates/scheduler_depth/python/test/app_test.py +10 -0
  105. package/templates/scheduler_depth/typescript/README.md +25 -0
  106. package/templates/scheduler_depth/typescript/__tests__/processor.spec.ts +17 -0
  107. package/templates/scheduler_depth/typescript/index.ts +8 -0
  108. package/templates/scheduler_natural-time/javascript/README.md +19 -0
  109. package/templates/scheduler_natural-time/javascript/__tests__/processor.spec.js +15 -0
  110. package/templates/scheduler_natural-time/javascript/index.js +15 -0
  111. package/templates/scheduler_natural-time/python/README.md +31 -0
  112. package/templates/scheduler_natural-time/python/lambda_function.py +7 -0
  113. package/templates/scheduler_natural-time/python/test/__init__.py +0 -0
  114. package/templates/scheduler_natural-time/python/test/app_test.py +10 -0
  115. package/templates/scheduler_natural-time/typescript/README.md +25 -0
  116. package/templates/scheduler_natural-time/typescript/__tests__/processor.spec.ts +15 -0
  117. package/templates/scheduler_natural-time/typescript/index.ts +8 -0
  118. package/templates/stream_depth/javascript/README.md +19 -0
  119. package/templates/stream_depth/javascript/__tests__/processor.spec.js +20 -0
  120. package/templates/stream_depth/javascript/index.js +14 -0
  121. package/templates/stream_depth/python/README.md +31 -0
  122. package/templates/stream_depth/python/lambda_function.py +7 -0
  123. package/templates/stream_depth/python/test/__init__.py +0 -0
  124. package/templates/stream_depth/python/test/app_test.py +16 -0
  125. package/templates/stream_depth/typescript/README.md +25 -0
  126. package/templates/stream_depth/typescript/__tests__/processor.spec.ts +20 -0
  127. package/templates/stream_depth/typescript/index.ts +8 -0
  128. package/templates/stream_time/javascript/README.md +19 -0
  129. package/templates/stream_time/javascript/__tests__/processor.spec.js +14 -0
  130. package/templates/stream_time/javascript/index.js +14 -0
  131. package/templates/stream_time/python/README.md +31 -0
  132. package/templates/stream_time/python/lambda_function.py +7 -0
  133. package/templates/stream_time/python/test/__init__.py +0 -0
  134. package/templates/stream_time/python/test/app_test.py +16 -0
  135. package/templates/stream_time/typescript/README.md +25 -0
  136. package/templates/stream_time/typescript/__tests__/processor.spec.ts +14 -0
  137. package/templates/stream_time/typescript/index.ts +8 -0
  138. package/templates/task/javascript/README.md +19 -0
  139. package/templates/task/javascript/__tests__/processor.spec.js +16 -0
  140. package/templates/task/javascript/index.js +15 -0
  141. package/templates/task/python/README.md +31 -0
  142. package/templates/task/python/lambda_function.py +7 -0
  143. package/templates/task/python/test/__init__.py +0 -0
  144. package/templates/task/python/test/app_test.py +8 -0
  145. package/templates/task/typescript/README.md +25 -0
  146. package/templates/task/typescript/__tests__/processor.spec.ts +16 -0
  147. package/templates/task/typescript/index.ts +8 -0
  148. package/templates/ui/javascript/.eslintrc +11 -0
  149. package/templates/ui/javascript/.prettierrc +1 -0
  150. package/templates/ui/javascript/README.md +31 -0
  151. package/templates/ui/javascript/config/jest/babelTransform.js +16 -0
  152. package/templates/ui/javascript/config/jest/cssTransform.js +16 -0
  153. package/templates/ui/javascript/config/jest/fileTransform.js +48 -0
  154. package/templates/ui/javascript/config/jest/globalSetup.js +5 -0
  155. package/templates/ui/javascript/config/jest/setupTests.js +11 -0
  156. package/templates/ui/javascript/config-overrides.js +10 -0
  157. package/templates/ui/javascript/gitignore +27 -0
  158. package/templates/ui/javascript/src/App.completion.js +64 -0
  159. package/templates/ui/javascript/src/App.css +30 -0
  160. package/templates/ui/javascript/src/App.drilling.js +58 -0
  161. package/templates/ui/javascript/src/AppSettings.js +42 -0
  162. package/templates/ui/javascript/src/__mocks__/mockAppProps.js +590 -0
  163. package/templates/ui/javascript/src/__mocks__/mockAppSettingsProps.js +290 -0
  164. package/templates/ui/javascript/src/__tests__/App.test.js +21 -0
  165. package/templates/ui/javascript/src/__tests__/AppSettings.test.js +21 -0
  166. package/templates/ui/javascript/src/__tests__/TestsExample.test.js +37 -0
  167. package/templates/ui/javascript/src/assets/logo.svg +7 -0
  168. package/templates/ui/javascript/src/constants.js +3 -0
  169. package/templates/ui/javascript/src/index.js +7 -0
  170. package/templates/ui/typescript/.eslintrc +28 -0
  171. package/templates/ui/typescript/.prettierrc +1 -0
  172. package/templates/ui/typescript/README.md +31 -0
  173. package/templates/ui/typescript/config/jest/babelTransform.js +16 -0
  174. package/templates/ui/typescript/config/jest/cssTransform.js +16 -0
  175. package/templates/ui/typescript/config/jest/fileTransform.js +48 -0
  176. package/templates/ui/typescript/config/jest/globalSetup.js +5 -0
  177. package/templates/ui/typescript/config/jest/setupTests.js +11 -0
  178. package/templates/ui/typescript/config-overrides.js +10 -0
  179. package/templates/ui/typescript/gitignore +27 -0
  180. package/templates/ui/typescript/src/App.completion.tsx +66 -0
  181. package/templates/ui/typescript/src/App.css +30 -0
  182. package/templates/ui/typescript/src/App.drilling.tsx +60 -0
  183. package/templates/ui/typescript/src/AppSettings.tsx +38 -0
  184. package/templates/ui/typescript/src/__mocks__/mockAppProps.ts +590 -0
  185. package/templates/ui/typescript/src/__mocks__/mockAppSettingsProps.ts +290 -0
  186. package/templates/ui/typescript/src/__tests__/App.test.tsx +21 -0
  187. package/templates/ui/typescript/src/__tests__/AppSettings.test.tsx +21 -0
  188. package/templates/ui/typescript/src/__tests__/TestsExample.test.tsx +37 -0
  189. package/templates/ui/typescript/src/assets/logo.svg +7 -0
  190. package/templates/ui/typescript/src/constants.ts +3 -0
  191. package/templates/ui/typescript/src/custom.d.ts +9 -0
  192. package/templates/ui/typescript/src/index.js +7 -0
  193. package/templates/ui/typescript/tsconfig.json +8 -0
@@ -0,0 +1,260 @@
1
+ import chalk from 'chalk';
2
+ import Glob from 'glob';
3
+ import isGlob from 'is-glob';
4
+ import _ from 'lodash/fp.js';
5
+ import { promises as fs } from 'node:fs';
6
+ import { resolve } from 'node:path';
7
+ import { promisify } from 'node:util';
8
+ import { getIncreasedVersion } from '../../helpers/cli-version.js';
9
+ import { generateRandomString } from '../../helpers/utils.js';
10
+ import { loadJson } from '../lib/json.js';
11
+ import { StepError } from '../lib/step-error.js';
12
+
13
+ const glob = promisify(Glob);
14
+
15
+ import debugFn from 'debug';
16
+
17
+ const debug = debugFn('cca:flow:zip:resolve');
18
+
19
+ const uniqueValues = (array) => Array.from(new Set(array));
20
+
21
+ export const FILE_LIST_RESOLVE_STEP = {
22
+ message: 'Resolving files list...',
23
+ fn: async (context) => {
24
+ const { patterns, manifest, dirName, options } = context;
25
+ const files = await transformPatternsIntoFileNames(dirName, patterns, options.ignoredFiles);
26
+
27
+ if (manifest.isUi()) {
28
+ return resolveDataToZipUiApp(files, context);
29
+ }
30
+
31
+ if (manifest.isNode()) {
32
+ return resolveDataForZipNodeJsApp(files, context);
33
+ }
34
+
35
+ if (manifest.isPython()) {
36
+ return resolveDataForZipPythonApp(files, context);
37
+ }
38
+
39
+ throw new StepError(`Unsupported runtime: ${manifest.runtime}`);
40
+ },
41
+ };
42
+
43
+ const transformPatternsIntoFileNames = async (dirName, patterns, ignoredFiles = []) => {
44
+ const filesFromPatterns = [];
45
+
46
+ for (const pattern of patterns) {
47
+ if (pattern.includes('node_modules')) {
48
+ debug('Invalid file pattern', pattern);
49
+
50
+ continue;
51
+ }
52
+
53
+ if (!isGlob(pattern, { strict: false })) {
54
+ filesFromPatterns.push(pattern);
55
+
56
+ continue;
57
+ }
58
+
59
+ const files = await glob(pattern, {
60
+ cwd: dirName,
61
+ ignore: ['**/node_modules', ...ignoredFiles],
62
+ nodir: true,
63
+ });
64
+
65
+ filesFromPatterns.push(...files);
66
+ }
67
+
68
+ return filesFromPatterns;
69
+ };
70
+
71
+ /**
72
+ *
73
+ * @param {string[]} itemsToZip
74
+ * @param {object} param1
75
+ * @param {import('../lib/manifest').Manifest} param1.manifest
76
+ * @returns
77
+ */
78
+ const resolveDataToZipUiApp = async (itemsToZip = [], { options, pkg, dirName, manifest, appKey }) => {
79
+ const version = await getIncreasedVersion(pkg.version, options);
80
+ const randomSuffix = generateRandomString(); // Random suffix is needed to not cause a conflict when we call 2 parallel commands at the same time.
81
+ const zipFileName = `${manifest.unix_name}-${version}-${randomSuffix}.zip`;
82
+ const itemsToSave = [];
83
+ const shouldUpdateVersion = version !== pkg.version;
84
+
85
+ if (shouldUpdateVersion) {
86
+ pkg.version = version;
87
+
88
+ itemsToSave.push({
89
+ name: 'package.json',
90
+ content: pkg,
91
+ message: chalk(
92
+ `\n${chalk.yellow`NOTE`}: Version of your app was updated to ${version} (package.json), please don't lower it.`,
93
+ ),
94
+ });
95
+ }
96
+
97
+ const tmpPackageForSourceName = `packageForSource_${randomSuffix}.json`;
98
+
99
+ itemsToSave.push({
100
+ name: tmpPackageForSourceName,
101
+ content: _.set(
102
+ 'scripts',
103
+ {
104
+ build: 'webpack --config=./config-overrides.js --mode production',
105
+ },
106
+ pkg,
107
+ ),
108
+ });
109
+
110
+ const itemsToRemove = [tmpPackageForSourceName];
111
+
112
+ itemsToZip.push(
113
+ 'manifest.json',
114
+ 'config-overrides.js',
115
+ 'tsconfig.json',
116
+ '.npmrc',
117
+ '.nvmrc',
118
+ 'yarn.lock',
119
+ {
120
+ path: resolve(dirName, tmpPackageForSourceName),
121
+ name: 'package.json',
122
+ },
123
+ ...(await transformPatternsIntoFileNames(dirName, ['src/**/*'], options.ignoredFiles)),
124
+ );
125
+
126
+ if (options.appKey) {
127
+ /**
128
+ * Both manifest.json appKey in zip and the provided
129
+ * appKey param should match. That's why we set it for cases when appKey option
130
+ * is specified to override the one from manifest.json
131
+ */
132
+
133
+ const tmpManifestForSourceName = `manifestForSource_${randomSuffix}.json`;
134
+
135
+ itemsToSave.push({
136
+ name: tmpManifestForSourceName,
137
+ content: _.set('application.key', appKey, manifest.manifest),
138
+ });
139
+
140
+ itemsToRemove.push(tmpManifestForSourceName);
141
+
142
+ itemsToZip.push({
143
+ path: resolve(dirName, tmpManifestForSourceName),
144
+ name: 'manifest.json',
145
+ });
146
+ }
147
+
148
+ return {
149
+ zipFileName,
150
+ itemsToZip,
151
+ itemsToSave,
152
+ itemsToRemove,
153
+ };
154
+ };
155
+
156
+ /**
157
+ *
158
+ * @param {string[]} itemsToZip
159
+ * @param {object} param1
160
+ * @param {import('../lib/manifest').Manifest} param1.manifest
161
+ * @returns
162
+ */
163
+ const resolveDataForZipNodeJsApp = async (itemsToZip = [], { options, pkg, dirName, manifest }) => {
164
+ const version = await getIncreasedVersion(pkg.version, options);
165
+ const zipFileName = `${manifest.unix_name}-${version}.zip`;
166
+ const itemsToSave = [];
167
+ const shouldUpdateVersion = version !== pkg.version;
168
+
169
+ if (shouldUpdateVersion) {
170
+ pkg.version = version;
171
+
172
+ itemsToSave.push({
173
+ name: 'package.json',
174
+ content: pkg,
175
+ message: chalk(
176
+ `\n${chalk.yellow`NOTE`}: Version of your app was updated to ${version} (package.json), please don't lower it.`,
177
+ ),
178
+ });
179
+ }
180
+
181
+ const packageDirContent = await fs.readdir(dirName);
182
+ const shouldPushDefaultSrc = !itemsToZip.length;
183
+
184
+ itemsToZip.push('config', 'manifest.json', 'package.json', '.nvmrc', '.npmrc', '.eslintrc.js');
185
+
186
+ if (packageDirContent.includes('package-lock.json')) {
187
+ itemsToZip.push('package-lock.json');
188
+
189
+ if (shouldUpdateVersion) {
190
+ itemsToSave.push({
191
+ name: 'package-lock.json',
192
+ content: _.set('version', version, await loadJson(dirName, 'package-lock.json')),
193
+ });
194
+ }
195
+ } else if (packageDirContent.includes('yarn.lock')) {
196
+ itemsToZip.push('yarn.lock');
197
+ } else {
198
+ throw new StepError(`No lock file found in ${dirName}`);
199
+ }
200
+
201
+ const defaultSrcWithoutExtensions = '+(__tests__|src|lib)/**/*.';
202
+
203
+ if (packageDirContent.includes('tsconfig.json')) {
204
+ itemsToZip.push('tsconfig.json', 'tsconfig.build.json');
205
+
206
+ if (shouldPushDefaultSrc) {
207
+ itemsToZip.push(
208
+ 'index.ts',
209
+ ...(await glob(`${defaultSrcWithoutExtensions}ts`, {
210
+ cwd: dirName,
211
+ ignore: options.ignoredFiles,
212
+ })),
213
+ );
214
+ }
215
+ } else if (shouldPushDefaultSrc) {
216
+ itemsToZip.push(
217
+ 'index.js',
218
+ ...(await glob(`${defaultSrcWithoutExtensions}js`, {
219
+ cwd: dirName,
220
+ ignore: options.ignoredFiles,
221
+ })),
222
+ );
223
+ }
224
+
225
+ return {
226
+ zipFileName,
227
+ itemsToZip: uniqueValues(itemsToZip),
228
+ itemsToSave,
229
+ itemsToRemove: [],
230
+ };
231
+ };
232
+
233
+ /**
234
+ *
235
+ * @param {string[]} itemsToZip
236
+ * @param {object} param1
237
+ * @param {import('../lib/manifest').Manifest} param1.manifest
238
+ * @returns
239
+ */
240
+ const resolveDataForZipPythonApp = async (itemsToZip = [], { manifest, dirName, options }) => {
241
+ const zipFileName = `${manifest.unix_name}.zip`;
242
+
243
+ if (!itemsToZip.length) {
244
+ itemsToZip.push(
245
+ ...(await glob('**/*.py', {
246
+ cwd: dirName,
247
+ ignore: [...(options.ignoredFiles || []), 'venv/**/*'],
248
+ })),
249
+ );
250
+ }
251
+
252
+ itemsToZip.push('manifest.json', 'requirements.txt');
253
+
254
+ return {
255
+ zipFileName,
256
+ itemsToZip: uniqueValues(itemsToZip),
257
+ itemsToSave: [],
258
+ itemsToRemove: [],
259
+ };
260
+ };
@@ -0,0 +1,20 @@
1
+ import { logger } from '../../helpers/logger.js';
2
+ import { saveJson } from '../lib/json.js';
3
+
4
+ import debugFn from 'debug';
5
+
6
+ const debug = debugFn('cca:flow:zip:prepare');
7
+
8
+ export const PREPARE_FILES_BEFORE_ZIP_STEP = {
9
+ message: 'Preparing...',
10
+ fn: async ({ itemsToSave, dirName }) => {
11
+ for (const item of itemsToSave) {
12
+ debug(`Updating %s`, item.name);
13
+ await saveJson(dirName, item.name, item.content);
14
+
15
+ if (item.message) {
16
+ logger.write(item.message);
17
+ }
18
+ }
19
+ },
20
+ };
@@ -0,0 +1,6 @@
1
+ import { CLEANUP_STEP } from './zip-cleanup.js';
2
+ import { CREATE_ARCHIVE_STEP } from './zip-create-archive.js';
3
+ import { FILE_LIST_RESOLVE_STEP } from './zip-file-list-resolve.js';
4
+ import { PREPARE_FILES_BEFORE_ZIP_STEP } from './zip-prepare.js';
5
+
6
+ export const ZIP_STEPS = [FILE_LIST_RESOLVE_STEP, PREPARE_FILES_BEFORE_ZIP_STEP, CREATE_ARCHIVE_STEP, CLEANUP_STEP];
@@ -0,0 +1,6 @@
1
+ import { ZIP_STEPS } from './steps/zip.js';
2
+
3
+ export const ZIP_SIMPLE_FLOW = {
4
+ name: 'zip (simple)',
5
+ steps: ZIP_STEPS,
6
+ };
@@ -0,0 +1,7 @@
1
+ import { PREPARE_FLOW } from './prepare.js';
2
+ import { ZIP_STEPS } from './steps/zip.js';
3
+
4
+ export const ZIP_FLOW = {
5
+ name: 'zip',
6
+ steps: [PREPARE_FLOW, ...ZIP_STEPS],
7
+ };
@@ -0,0 +1,114 @@
1
+ import NpmApi from 'npm-api';
2
+ import chalk from 'chalk';
3
+ import semver from 'semver';
4
+ import inquirer from 'inquirer';
5
+ import { join } from 'path';
6
+ import * as url from 'url';
7
+
8
+ import { logger } from './logger.js';
9
+ import fs from 'fs-extra';
10
+
11
+ const npm = new NpmApi();
12
+
13
+ const error = chalk.bold.red;
14
+ const warning = chalk.hex('#FFA500'); // Orange
15
+ const code = chalk.cyan;
16
+ const asterisks = '****************************************************************';
17
+
18
+ const getCurrentVersion = async () =>
19
+ (await fs.readJSON(join(url.fileURLToPath(new URL('.', import.meta.url)), '../../package.json'))).version;
20
+ const getLatestVersion = async () => npm.repo('@corva/create-app').prop('version');
21
+
22
+ // NOTE: Stop process and show error if version is outdated
23
+ export async function ensureLatestVersion() {
24
+ const currentVersion = await getCurrentVersion();
25
+ const latestVersion = await getLatestVersion();
26
+
27
+ const isCurrentVersionOutdated = semver.gt(latestVersion, currentVersion);
28
+
29
+ if (isCurrentVersionOutdated) {
30
+ console.log(error(asterisks));
31
+ console.log(error`
32
+ Your version of the @corva/create-app is outdated.
33
+ There is a new version available ({green.bold ${latestVersion}}).
34
+ Please update the @corva/create-app with the following command:
35
+
36
+ ${code('npm i -g @corva/create-app@latest')}
37
+
38
+ `);
39
+ console.log(error(asterisks));
40
+ process.exit(0);
41
+ }
42
+ }
43
+
44
+ // NOTE: Show user-friendly warning if version is outdated
45
+ export async function warnIfOutdated() {
46
+ logger.write('Checking for updates...\n');
47
+
48
+ const currentVersion = await getCurrentVersion();
49
+ const latestVersion = await getLatestVersion();
50
+
51
+ const isCurrentVersionOutdated = semver.gt(latestVersion, currentVersion);
52
+
53
+ if (isCurrentVersionOutdated) {
54
+ console.log(warning(asterisks));
55
+ console.log(warning`
56
+ There is a new version available ({green.bold ${latestVersion}}).
57
+ You can update the CLI version with the following command:
58
+
59
+ ${code`npm i -g @corva/create-app@latest`}
60
+
61
+ `);
62
+ console.log(warning(asterisks));
63
+ } else {
64
+ logger.write(' ✅ \n');
65
+ }
66
+ }
67
+
68
+ const PROMPT_MESSAGE = `Bumping package version:
69
+ ${chalk.bold` Please select one of the options below:`}
70
+ `;
71
+
72
+ export const ensureBumpVersion = async (bumpVersion) => {
73
+ if (bumpVersion) {
74
+ return bumpVersion;
75
+ }
76
+
77
+ const { option, custom } = await inquirer.prompt([
78
+ {
79
+ message: PROMPT_MESSAGE,
80
+ name: 'option',
81
+ type: 'list',
82
+ choices: [
83
+ { value: 'major', name: 'major (x+1.y.z)' },
84
+ { value: 'minor', name: 'minor (x.y+1.z)' },
85
+ { value: 'patch', name: 'patch (x.y.z+1)' },
86
+ new inquirer.Separator(),
87
+ { value: 'custom', name: 'Enter a custom version' },
88
+ { value: 'skip', name: 'Skip version bump' },
89
+ ],
90
+ default: 'patch',
91
+ },
92
+ {
93
+ message: 'Enter custom version',
94
+ name: 'custom',
95
+ when: (answers) => answers.option === 'custom',
96
+ type: 'input',
97
+ validate: (input) => (semver.valid(input) ? true : 'Invalid semver version'),
98
+ },
99
+ ]);
100
+
101
+ return option === 'custom' ? custom : option;
102
+ };
103
+
104
+ export async function getIncreasedVersion(version, { bumpVersion: releaseTypeOrNewVersion }) {
105
+ if (releaseTypeOrNewVersion === 'skip') {
106
+ return version;
107
+ }
108
+
109
+ if (semver.valid(releaseTypeOrNewVersion)) {
110
+ return releaseTypeOrNewVersion;
111
+ }
112
+
113
+ return semver.inc(version, releaseTypeOrNewVersion);
114
+ }
@@ -0,0 +1,13 @@
1
+ import { resolve } from 'node:path';
2
+
3
+ export const silencer =
4
+ (handler) =>
5
+ async (...args) => {
6
+ const result = await handler(...args);
7
+
8
+ if (args[args.length - 2].silent && result) {
9
+ console.log(result);
10
+ }
11
+ };
12
+
13
+ export const getRealWorkingDir = (relativePath, options) => resolve(options.originalCwd, relativePath);
@@ -0,0 +1,35 @@
1
+ export class Logger {
2
+ constructor() {
3
+ this.isSilent = process.argv.includes('--silent');
4
+ }
5
+
6
+ write(str) {
7
+ if (this.isSilent) {
8
+ return;
9
+ }
10
+
11
+ if (str === undefined) {
12
+ process.stdout.write();
13
+
14
+ return;
15
+ }
16
+
17
+ process.stdout.write(str);
18
+ }
19
+
20
+ log(str) {
21
+ if (this.isSilent) {
22
+ return;
23
+ }
24
+
25
+ if (str === undefined) {
26
+ console.log();
27
+
28
+ return;
29
+ }
30
+
31
+ console.log(str);
32
+ }
33
+ }
34
+
35
+ export const logger = new Logger();
@@ -0,0 +1,74 @@
1
+ import { APP_RUNTIMES, APP_TYPES, TEMPLATE_TYPES } from '../constants/cli.js';
2
+ import * as manifestConstants from '../constants/manifest.js';
3
+
4
+ export function fillManifest(answers) {
5
+ const runtime = answers.runtime || APP_RUNTIMES.UI;
6
+
7
+ const defaultManifestProperties = _defaultManifestProperties({
8
+ type: answers.appType,
9
+ // fallback to UI
10
+ runtime,
11
+ });
12
+
13
+ const manifest = {
14
+ ...manifestConstants.defaultManifest,
15
+ ...defaultManifestProperties,
16
+ developer: {
17
+ ...manifestConstants.defaultManifest.developer,
18
+ ...defaultManifestProperties.developer,
19
+ name: answers.developerName,
20
+ identifier: answers.developerIdentifier,
21
+ },
22
+ application: {
23
+ ...manifestConstants.defaultManifest.application,
24
+ ...defaultManifestProperties.application,
25
+ key: answers.appKey,
26
+ name: answers.appName,
27
+ type: answers.appType,
28
+ description: answers.description,
29
+ summary: answers.summary,
30
+ category: answers.category,
31
+ website: answers.website,
32
+ segments: [answers.segments],
33
+ },
34
+ settings: {
35
+ ...defaultManifestProperties.settings,
36
+ runtime,
37
+ app: defaultAppSettings(answers),
38
+ },
39
+ };
40
+
41
+ return manifest;
42
+ }
43
+
44
+ function _defaultManifestProperties({ type, runtime }) {
45
+ if (type === APP_TYPES.UI) {
46
+ return manifestConstants.defaultUIAppManifest;
47
+ }
48
+
49
+ if (runtime.startsWith(TEMPLATE_TYPES.PYTHON)) {
50
+ return manifestConstants.defaultDataAppPythonManifest;
51
+ }
52
+
53
+ return manifestConstants.defaultDataAppNodeManifest;
54
+ }
55
+
56
+ function defaultAppSettings({ appType, schedulerType, cronString, depthMilestone, logType }) {
57
+ if (!schedulerType || appType !== APP_TYPES.SCHEDULER) {
58
+ return {
59
+ log_type: logType,
60
+ };
61
+ }
62
+
63
+ if (schedulerType === manifestConstants.SCHEDULER_TYPE_DEPTH.value) {
64
+ return {
65
+ scheduler_type: schedulerType,
66
+ depth_milestone: depthMilestone || 1,
67
+ };
68
+ }
69
+
70
+ return {
71
+ scheduler_type: schedulerType,
72
+ cron_string: cronString || '*/5 * * * *',
73
+ };
74
+ }
@@ -0,0 +1,128 @@
1
+ import debugFn from 'debug';
2
+ import { APP_TYPES } from '../constants/cli.js';
3
+
4
+ const debug = debugFn('cca:resolve-app-runtime');
5
+
6
+ import spawn from 'cross-spawn';
7
+ import { promises as fs } from 'fs';
8
+ import os from 'os';
9
+ import semver from 'semver';
10
+
11
+ /**
12
+ *
13
+ * @param {string} command
14
+ * @param {string} version
15
+ * @returns {Promise<boolean>}
16
+ */
17
+ const checkCliVersion = async (command, version) =>
18
+ new Promise((resolve) => {
19
+ const child = spawn(command, ['--version']);
20
+
21
+ let data = '';
22
+
23
+ child.stderr.on('data', (buffer) => {
24
+ data += buffer;
25
+ });
26
+
27
+ child.stdout.on('data', (buffer) => {
28
+ data += buffer;
29
+ });
30
+
31
+ child.once('close', (code) => {
32
+ if (code !== 0) {
33
+ debug(`Command ${command} exited with code ${code}`);
34
+ debug('Output:', data.toString());
35
+
36
+ return resolve(false);
37
+ }
38
+
39
+ debug(`%s version output: %s`, command, data.toString());
40
+
41
+ resolve(semver.satisfies(semver.coerce(data.toString('utf-8')), version));
42
+ });
43
+ });
44
+
45
+ const checkNodeVersion = (version) => async () => {
46
+ try {
47
+ await fs.access(`${os.homedir()}/.nvm/nvm.sh`);
48
+
49
+ debug('nvm is installed');
50
+
51
+ return true;
52
+ } catch (e) {
53
+ debug(e);
54
+ debug('nvm is not installed, checking node version');
55
+
56
+ return checkCliVersion('node', version);
57
+ }
58
+ };
59
+
60
+ export const IS_WINDOWS = process.platform === 'win32';
61
+
62
+ const semverVersionsMapping = {
63
+ node: {
64
+ 16: '16.19.0',
65
+ 18: '18.13.0',
66
+ },
67
+ python: {
68
+ '3.8': '3.8.16',
69
+ '3.9': '3.9.16',
70
+ '3.10': '3.10.9',
71
+ '3.11': '3.11.1',
72
+ },
73
+ };
74
+
75
+ /**
76
+ * @typedef {Object} Runtime
77
+ * @property {string} language
78
+ * @property {boolean} isRuntimeAvailable
79
+ * @property {string} packageManager
80
+ * @property {string} version
81
+ * @property {string} semver
82
+ */
83
+ export const resolveAppRuntime = (opts) => {
84
+ if (opts.appType === APP_TYPES.UI) {
85
+ const version = '18';
86
+
87
+ return {
88
+ language: opts.useTypescript ? 'typescript' : 'javascript',
89
+ isRuntimeAvailable: checkNodeVersion(version),
90
+ packageManager: opts.packageManager,
91
+ version,
92
+ semver: semverVersionsMapping.node[version],
93
+ };
94
+ }
95
+
96
+ if (opts.runtime.startsWith('node')) {
97
+ const version = /nodejs(\d{2})\.x/.exec(opts.runtime)[1];
98
+
99
+ return {
100
+ language: opts.useTypescript ? 'typescript' : 'javascript',
101
+ isRuntimeAvailable: checkNodeVersion(version),
102
+ packageManager: opts.packageManager,
103
+ version,
104
+ semver: semverVersionsMapping.node[version],
105
+ };
106
+ }
107
+
108
+ const version = /python(\d\.\d+)/.exec(opts.runtime)[1];
109
+
110
+ return {
111
+ language: 'python',
112
+ isRuntimeAvailable: async () => {
113
+ if (!IS_WINDOWS) {
114
+ return checkCliVersion(`python3`, version);
115
+ }
116
+
117
+ return (
118
+ (await checkCliVersion(`py -${version}`, version)) ||
119
+ (await checkCliVersion('python', version)) ||
120
+ (await checkCliVersion('python3', version))
121
+ );
122
+ },
123
+
124
+ packageManager: 'pip',
125
+ version,
126
+ semver: semverVersionsMapping.python[version],
127
+ };
128
+ };