@corva/create-app 0.0.0-2576df8

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 (204) hide show
  1. package/README.md +218 -0
  2. package/bin/cca.js +5 -0
  3. package/bin/create-corva-app.cjs +25 -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 +58 -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 +35 -0
  20. package/lib/constants/manifest.js +263 -0
  21. package/lib/constants/messages.js +15 -0
  22. package/lib/constants/package.js +288 -0
  23. package/lib/flow.js +53 -0
  24. package/lib/flows/attach.js +8 -0
  25. package/lib/flows/lib/api.js +385 -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 +136 -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 +266 -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 +150 -0
  62. package/lib/helpers/commands.js +13 -0
  63. package/lib/helpers/logger.js +35 -0
  64. package/lib/helpers/manifest.js +82 -0
  65. package/lib/helpers/resolve-app-runtime.js +132 -0
  66. package/lib/helpers/utils.js +97 -0
  67. package/lib/helpers/versioning.js +94 -0
  68. package/lib/main.js +64 -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 +1 -0
  78. package/template_extensions/corva/.commitlintrc.json +6 -0
  79. package/template_extensions/corva/.eslintrc +32 -0
  80. package/template_extensions/corva/.github/pull_request_template.md +14 -0
  81. package/template_extensions/corva/.github/workflows/code-checks.yml +15 -0
  82. package/template_extensions/corva/.github/workflows/develop.yml +19 -0
  83. package/template_extensions/corva/.github/workflows/feat-fix-delete.yml +14 -0
  84. package/template_extensions/corva/.github/workflows/feat-fix.yml +23 -0
  85. package/template_extensions/corva/.github/workflows/release-fix-X.X.X.yml +16 -0
  86. package/template_extensions/corva/.github/workflows/validate-pr-title.yml +19 -0
  87. package/template_extensions/corva/.husky/commit-msg +5 -0
  88. package/template_extensions/corva/.husky/pre-commit +4 -0
  89. package/template_extensions/corva/.release-please-manifest.json +3 -0
  90. package/template_extensions/corva/release-please-config.json +10 -0
  91. package/templates/scheduler_data-time/javascript/README.md +19 -0
  92. package/templates/scheduler_data-time/javascript/__tests__/processor.spec.js +15 -0
  93. package/templates/scheduler_data-time/javascript/index.js +15 -0
  94. package/templates/scheduler_data-time/python/README.md +31 -0
  95. package/templates/scheduler_data-time/python/lambda_function.py +7 -0
  96. package/templates/scheduler_data-time/python/test/__init__.py +0 -0
  97. package/templates/scheduler_data-time/python/test/app_test.py +10 -0
  98. package/templates/scheduler_data-time/typescript/README.md +25 -0
  99. package/templates/scheduler_data-time/typescript/__tests__/processor.spec.ts +15 -0
  100. package/templates/scheduler_data-time/typescript/index.ts +8 -0
  101. package/templates/scheduler_depth/javascript/README.md +19 -0
  102. package/templates/scheduler_depth/javascript/__tests__/processor.spec.js +17 -0
  103. package/templates/scheduler_depth/javascript/index.js +15 -0
  104. package/templates/scheduler_depth/python/README.md +31 -0
  105. package/templates/scheduler_depth/python/lambda_function.py +7 -0
  106. package/templates/scheduler_depth/python/test/__init__.py +0 -0
  107. package/templates/scheduler_depth/python/test/app_test.py +10 -0
  108. package/templates/scheduler_depth/typescript/README.md +25 -0
  109. package/templates/scheduler_depth/typescript/__tests__/processor.spec.ts +17 -0
  110. package/templates/scheduler_depth/typescript/index.ts +8 -0
  111. package/templates/scheduler_natural-time/javascript/README.md +19 -0
  112. package/templates/scheduler_natural-time/javascript/__tests__/processor.spec.js +15 -0
  113. package/templates/scheduler_natural-time/javascript/index.js +15 -0
  114. package/templates/scheduler_natural-time/python/README.md +31 -0
  115. package/templates/scheduler_natural-time/python/lambda_function.py +7 -0
  116. package/templates/scheduler_natural-time/python/test/__init__.py +0 -0
  117. package/templates/scheduler_natural-time/python/test/app_test.py +10 -0
  118. package/templates/scheduler_natural-time/typescript/README.md +25 -0
  119. package/templates/scheduler_natural-time/typescript/__tests__/processor.spec.ts +15 -0
  120. package/templates/scheduler_natural-time/typescript/index.ts +8 -0
  121. package/templates/stream_depth/javascript/README.md +19 -0
  122. package/templates/stream_depth/javascript/__tests__/processor.spec.js +20 -0
  123. package/templates/stream_depth/javascript/index.js +14 -0
  124. package/templates/stream_depth/python/README.md +31 -0
  125. package/templates/stream_depth/python/lambda_function.py +7 -0
  126. package/templates/stream_depth/python/test/__init__.py +0 -0
  127. package/templates/stream_depth/python/test/app_test.py +16 -0
  128. package/templates/stream_depth/typescript/README.md +25 -0
  129. package/templates/stream_depth/typescript/__tests__/processor.spec.ts +20 -0
  130. package/templates/stream_depth/typescript/index.ts +8 -0
  131. package/templates/stream_time/javascript/README.md +19 -0
  132. package/templates/stream_time/javascript/__tests__/processor.spec.js +14 -0
  133. package/templates/stream_time/javascript/index.js +14 -0
  134. package/templates/stream_time/python/README.md +31 -0
  135. package/templates/stream_time/python/lambda_function.py +7 -0
  136. package/templates/stream_time/python/test/__init__.py +0 -0
  137. package/templates/stream_time/python/test/app_test.py +16 -0
  138. package/templates/stream_time/typescript/README.md +25 -0
  139. package/templates/stream_time/typescript/__tests__/processor.spec.ts +14 -0
  140. package/templates/stream_time/typescript/index.ts +8 -0
  141. package/templates/task/javascript/README.md +19 -0
  142. package/templates/task/javascript/__tests__/processor.spec.js +16 -0
  143. package/templates/task/javascript/index.js +15 -0
  144. package/templates/task/python/README.md +31 -0
  145. package/templates/task/python/lambda_function.py +7 -0
  146. package/templates/task/python/test/__init__.py +0 -0
  147. package/templates/task/python/test/app_test.py +8 -0
  148. package/templates/task/typescript/README.md +25 -0
  149. package/templates/task/typescript/__tests__/processor.spec.ts +16 -0
  150. package/templates/task/typescript/index.ts +8 -0
  151. package/templates/ui/javascript/.codex/config.toml +3 -0
  152. package/templates/ui/javascript/.cursor/mcp.json +8 -0
  153. package/templates/ui/javascript/.eslintrc +11 -0
  154. package/templates/ui/javascript/.mcp.json +8 -0
  155. package/templates/ui/javascript/.prettierrc +1 -0
  156. package/templates/ui/javascript/AGENTS.md +304 -0
  157. package/templates/ui/javascript/CLAUDE.md +1 -0
  158. package/templates/ui/javascript/README.md +31 -0
  159. package/templates/ui/javascript/config/jest/babelTransform.js +16 -0
  160. package/templates/ui/javascript/config/jest/cssTransform.js +16 -0
  161. package/templates/ui/javascript/config/jest/fileTransform.js +48 -0
  162. package/templates/ui/javascript/config/jest/globalSetup.js +5 -0
  163. package/templates/ui/javascript/config/jest/setupTests.js +30 -0
  164. package/templates/ui/javascript/config-overrides.js +10 -0
  165. package/templates/ui/javascript/gitignore +27 -0
  166. package/templates/ui/javascript/src/App.completion.js +52 -0
  167. package/templates/ui/javascript/src/App.drilling.js +49 -0
  168. package/templates/ui/javascript/src/App.scss +17 -0
  169. package/templates/ui/javascript/src/AppSettings.js +28 -0
  170. package/templates/ui/javascript/src/__tests__/App.test.js +26 -0
  171. package/templates/ui/javascript/src/__tests__/AppSettings.test.js +28 -0
  172. package/templates/ui/javascript/src/__tests__/TestsExample.test.js +37 -0
  173. package/templates/ui/javascript/src/assets/logo.svg +7 -0
  174. package/templates/ui/javascript/src/constants.js +3 -0
  175. package/templates/ui/javascript/src/index.js +8 -0
  176. package/templates/ui/typescript/.codex/config.toml +3 -0
  177. package/templates/ui/typescript/.cursor/mcp.json +8 -0
  178. package/templates/ui/typescript/.eslintrc +28 -0
  179. package/templates/ui/typescript/.mcp.json +8 -0
  180. package/templates/ui/typescript/.prettierrc +1 -0
  181. package/templates/ui/typescript/AGENTS.md +344 -0
  182. package/templates/ui/typescript/CLAUDE.md +1 -0
  183. package/templates/ui/typescript/README.md +31 -0
  184. package/templates/ui/typescript/config/jest/babelTransform.js +16 -0
  185. package/templates/ui/typescript/config/jest/cssTransform.js +16 -0
  186. package/templates/ui/typescript/config/jest/fileTransform.js +48 -0
  187. package/templates/ui/typescript/config/jest/globalSetup.js +5 -0
  188. package/templates/ui/typescript/config/jest/setupTests.js +30 -0
  189. package/templates/ui/typescript/config-overrides.js +10 -0
  190. package/templates/ui/typescript/gitignore +27 -0
  191. package/templates/ui/typescript/src/App.completion.tsx +52 -0
  192. package/templates/ui/typescript/src/App.drilling.tsx +49 -0
  193. package/templates/ui/typescript/src/App.scss +17 -0
  194. package/templates/ui/typescript/src/AppSettings.tsx +28 -0
  195. package/templates/ui/typescript/src/__mocks__/mockData.ts +22 -0
  196. package/templates/ui/typescript/src/__tests__/App.test.tsx +27 -0
  197. package/templates/ui/typescript/src/__tests__/AppSettings.test.tsx +28 -0
  198. package/templates/ui/typescript/src/__tests__/TestsExample.test.tsx +37 -0
  199. package/templates/ui/typescript/src/assets/logo.svg +7 -0
  200. package/templates/ui/typescript/src/constants.ts +3 -0
  201. package/templates/ui/typescript/src/custom.d.ts +19 -0
  202. package/templates/ui/typescript/src/index.js +8 -0
  203. package/templates/ui/typescript/src/types.ts +3 -0
  204. package/templates/ui/typescript/tsconfig.json +7 -0
@@ -0,0 +1,463 @@
1
+ import { dirname, join, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { clear } from 'node:console';
4
+ import os from 'node:os';
5
+ import { existsSync } from 'node:fs';
6
+
7
+ import { Command, Option } from 'commander';
8
+ import spawn from 'cross-spawn';
9
+ import chalk from 'chalk';
10
+ import fs from 'fs-extra';
11
+ import figlet from 'figlet';
12
+ import _ from 'lodash/fp.js';
13
+ import inquirer from 'inquirer';
14
+
15
+ import { originalCwdOption } from '../options/original-cwd.js';
16
+ import { ensureBumpVersion, ensureLatestVersion } from '../helpers/cli-version.js';
17
+ import { logger } from '../helpers/logger.js';
18
+ import { IS_WINDOWS, resolveAppRuntime } from '../helpers/resolve-app-runtime.js';
19
+ import { tryGitCommit, tryGitInit } from '../helpers/versioning.js';
20
+ import { addUiAppFile, copyFolderRecursiveSync, getExcludedFiles, putVariablesInEnvFile } from '../helpers/utils.js';
21
+ import { getDefaultsForPackageJson } from '../constants/package.js';
22
+ import { getRealWorkingDir } from '../helpers/commands.js';
23
+ import { Manifest } from '../flows/lib/manifest.js';
24
+ import { fillManifest } from '../helpers/manifest.js';
25
+ import { getManifestMandatoryKeys, manifestOptions } from '../constants/manifest.js';
26
+ import { StepError } from '../flows/lib/step-error.js';
27
+
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = dirname(__filename);
30
+
31
+ const WRITE_TO_JSON_OPTS = {
32
+ spaces: 2,
33
+ EOL: os.EOL,
34
+ };
35
+
36
+ export const createCommand = new Command('create')
37
+ .description('Create a new app')
38
+ .argument('[project-directory]', 'project directory to work with', process.argv[process.argv.length - 1])
39
+ .addOption(originalCwdOption);
40
+
41
+ manifestOptions().forEach((value) => {
42
+ const type = value.commaSeparated ? 'string' : typeof value.default;
43
+ const cliType = type === 'undefined' ? (value.choices ? ' [string]' : '') : ` [${type}]`;
44
+ const alias = value.alias ? `-${value.alias}, ` : '';
45
+ const optionString = `${alias}--${value.name}${cliType}`;
46
+
47
+ const option = new Option(optionString, value.message);
48
+
49
+ if (value.choices) {
50
+ if (typeof value.choices === 'function') {
51
+ option.choices(value.choices());
52
+ } else {
53
+ option.choices(value.choices.map((choice) => `${typeof choice === 'object' ? choice.value : choice}`));
54
+ }
55
+ }
56
+
57
+ if (type === 'number') {
58
+ option.argParser(Number);
59
+ } else if (value.commaSeparated) {
60
+ option.argParser((str) => str.split(',').map((s) => s.trim()));
61
+ }
62
+
63
+ if (type !== 'undefined') {
64
+ option.default(value.default);
65
+ }
66
+
67
+ createCommand.addOption(option);
68
+ });
69
+
70
+ createCommand.version(fs.readJSONSync(join(__dirname, '../../package.json')).version);
71
+
72
+ createCommand.action(async (dirName, options) => {
73
+ if (options.zip || options.release) {
74
+ options.bumpVersion = await ensureBumpVersion(options.bumpVersion);
75
+ }
76
+
77
+ startingMessage();
78
+
79
+ // NOTE: Default action
80
+ await createApp(dirName, options);
81
+ });
82
+
83
+ /**
84
+ *
85
+ * @param {import('./flows/lib/manifest').Manifest} manifest
86
+ */
87
+ const getEnvManagementLink = (manifest) => {
88
+ if (manifest.isJs()) {
89
+ if (IS_WINDOWS) {
90
+ return 'https://github.com/coreybutler/nvm-windows';
91
+ }
92
+
93
+ return 'https://github.com/nvm-sh/nvm';
94
+ }
95
+
96
+ if (IS_WINDOWS) {
97
+ return 'https://docs.python.org/3/using/windows.html#using-python-on-windows';
98
+ }
99
+
100
+ return 'https://github.com/pyenv/pyenv';
101
+ };
102
+
103
+ async function initPackage(projectName, opts) {
104
+ const manifest = new Manifest(fillManifest(opts));
105
+ const runtime = resolveAppRuntime(opts);
106
+
107
+ if (!(await runtime.isRuntimeAvailable())) {
108
+ throw new StepError(
109
+ `You need ${runtime.environment} version ${runtime.version} to use "${opts.runtime}" runtime. ` +
110
+ `Please install it manually or proceed to ${chalk.green(getEnvManagementLink(manifest))} ` +
111
+ `to install a node version manager`,
112
+ );
113
+ }
114
+
115
+ if (manifest.isUi()) {
116
+ await ensureLatestVersion();
117
+ }
118
+
119
+ const root = getRealWorkingDir(projectName, opts);
120
+
121
+ logger.log(`Creating a new Corva app in ${chalk.green(root)}.`);
122
+
123
+ await fs.ensureDir(root);
124
+
125
+ if ((await fs.readdir(root)).length) {
126
+ const shouldCleanup = await inquirer
127
+ .prompt([
128
+ {
129
+ message: `Directory "${root}" is not empty. Clean it to proceed?`,
130
+ name: 'cleanup',
131
+ type: 'confirm',
132
+ },
133
+ ])
134
+ .then(_.get('cleanup'));
135
+
136
+ if (shouldCleanup) {
137
+ await fs.emptyDir(root);
138
+ } else {
139
+ throw new StepError(`Directory is not empty: ${root}`);
140
+ }
141
+ }
142
+
143
+ await fs.writeJSON(join(root, 'manifest.json'), manifest.manifest, WRITE_TO_JSON_OPTS);
144
+
145
+ await addTemplate(root, manifest, runtime, opts);
146
+ await configureApp(root, manifest, runtime, opts);
147
+
148
+ if (opts.gitInit) {
149
+ if (!tryGitInit(root)) {
150
+ logger.log('Already in a git repository. Skipping git initialization.');
151
+ }
152
+ }
153
+
154
+ opts.dependenciesInstall && (await installDependencies(root, manifest, runtime));
155
+
156
+ if (opts.gitInit) {
157
+ if (tryGitCommit(root)) {
158
+ logger.log();
159
+ logger.log('Created git commit');
160
+ }
161
+ }
162
+
163
+ logger.log();
164
+ logger.log(`Success! Created ${chalk.green(manifest.name)} at ${chalk.yellow(root)}`);
165
+
166
+ helpCommands(manifest, runtime);
167
+
168
+ logger.log();
169
+ }
170
+
171
+ async function createApp(dirName, opts) {
172
+ const { isValid, values } = checkOptions(opts);
173
+
174
+ if (isValid) {
175
+ Object.keys(values).forEach((key) => {
176
+ logger.log(`${key} : ${values[key]}`);
177
+ });
178
+
179
+ return initPackage(dirName, opts);
180
+ }
181
+
182
+ console.log('Please fill your app Metadata');
183
+
184
+ const answers = await inquirer.prompt(manifestOptions(dirName), opts);
185
+
186
+ return initPackage(dirName, answers);
187
+ }
188
+
189
+ /**
190
+ *
191
+ * @param {string} root
192
+ * @param {import('./flows/lib/manifest').Manifest} manifest
193
+ * @param {*} runtime
194
+ * @param {*} opts
195
+ */
196
+ async function addTemplate(root, manifest, runtime, opts) {
197
+ logger.log(chalk.green('Copying app template...'));
198
+ logger.log();
199
+
200
+ const cliRoot = resolve(__dirname, '..', '..');
201
+
202
+ const templateFolder = join(cliRoot, 'templates', manifest.templateName, runtime.language);
203
+
204
+ const excludeFiles = getExcludedFiles(manifest);
205
+
206
+ copyFolderRecursiveSync(templateFolder, root, excludeFiles);
207
+
208
+ if (manifest.isNode()) {
209
+ copyFolderRecursiveSync(join(cliRoot, 'common', 'node'), root);
210
+ }
211
+
212
+ if (manifest.isPython()) {
213
+ copyFolderRecursiveSync(join(cliRoot, 'common', 'python'), root);
214
+ }
215
+
216
+ if (!manifest.isUi()) {
217
+ await putVariablesInEnvFile(root, manifest);
218
+ }
219
+
220
+ // We can't have .gitignore file in our templates.
221
+ // It's missing when @corva/create-app is installed.
222
+ // That's why we manually rename gitignore to .gitignore after copying template
223
+ const targetGitignore = join(root, '.gitignore');
224
+
225
+ fs.renameSync(join(root, 'gitignore'), targetGitignore);
226
+
227
+ if (runtime.language === 'typescript' && manifest.isNode()) {
228
+ await fs.appendFile(targetGitignore, '\n**/*.js\n');
229
+ }
230
+
231
+ logger.log(chalk.green('Done: copying app template!'));
232
+
233
+ try {
234
+ if (Array.isArray(opts?.extensions) && opts.extensions.length) {
235
+ opts.extensions.forEach((extension) => {
236
+ const extPath = join(cliRoot, 'template_extensions', extension);
237
+
238
+ if (fs.existsSync(extPath)) {
239
+ copyFolderRecursiveSync(extPath, root);
240
+ }
241
+ });
242
+
243
+ logger.log(chalk.green('Done: applying app extensions!'));
244
+ }
245
+ } catch (e) {
246
+ logger.log(chalk.red('Error: applying app extensions!'));
247
+ logger.log(e);
248
+ }
249
+
250
+ if (manifest.isUi()) {
251
+ addUiAppFile(templateFolder, root, runtime, manifest, opts);
252
+ }
253
+ }
254
+
255
+ /**
256
+ *
257
+ * @param {string} root
258
+ * @param {import('./flows/lib/manifest').Manifest} manifest
259
+ * @param {*} runtime
260
+ * @param {*} opts
261
+ */
262
+ async function configureApp(root, manifest, runtime, opts) {
263
+ if (manifest.isJs()) {
264
+ await addNvmRc(root, manifest, runtime);
265
+ await addPackageJSON(root, manifest, runtime, opts);
266
+ }
267
+
268
+ if (manifest.isNode()) {
269
+ await addTsConfigs(root, manifest, runtime);
270
+ }
271
+
272
+ if (manifest.isPython()) {
273
+ await addPythonConfigs(root, manifest, runtime);
274
+ }
275
+ }
276
+
277
+ const addNvmRc = async (root, manifest, runtime) => {
278
+ await fs.outputFile(join(root, '.nvmrc'), `${runtime.semver}\n`);
279
+ };
280
+
281
+ /**
282
+ *
283
+ * @param {string} root
284
+ * @param {Manifest} manifest
285
+ * @param {import('../helpers/resolve-app-runtime.js').Runtime} runtime
286
+ */
287
+ const addPythonConfigs = async (root, manifest, runtime) => {
288
+ await fs.writeFile(resolve(root, '.python-version'), `${runtime.version}\n`);
289
+ await fs.writeFile(resolve(root, '.python-virtualenv'), `${manifest.unix_name}\n`);
290
+ };
291
+
292
+ const addTsConfigs = (root, manifest, runtime) => {
293
+ if (runtime.language !== 'typescript') {
294
+ return;
295
+ }
296
+
297
+ return Promise.all([
298
+ fs.writeJson(
299
+ resolve(root, 'tsconfig.json'),
300
+ {
301
+ extends: `@tsconfig/node${runtime.version}/tsconfig.json`,
302
+ compilerOptions: {
303
+ inlineSourceMap: true,
304
+ strict: false,
305
+ outDir: 'dist',
306
+ },
307
+ },
308
+ WRITE_TO_JSON_OPTS,
309
+ ),
310
+ fs.writeJson(
311
+ resolve(root, 'tsconfig.build.json'),
312
+ {
313
+ extends: './tsconfig.json',
314
+ include: ['lib/**/*.ts', 'index.ts'],
315
+ exclude: ['node_modules', '**/*.spec.ts'],
316
+ },
317
+ WRITE_TO_JSON_OPTS,
318
+ ),
319
+ ]);
320
+ };
321
+
322
+ /**
323
+ *
324
+ * @param {string} root
325
+ * @param {import('./flows/lib/manifest').Manifest} manifest
326
+ */
327
+ function addPackageJSON(root, manifest, runtime, opts) {
328
+ const {
329
+ version,
330
+ description,
331
+ scripts,
332
+ dependencies,
333
+ devDependencies,
334
+ main,
335
+ license = 'UNLICENSED',
336
+ private: isPrivate = true,
337
+ ...rest
338
+ } = getDefaultsForPackageJson(manifest, runtime, opts);
339
+
340
+ const packageJson = {
341
+ name: manifest.unix_name,
342
+ version,
343
+ description: manifest.description || description,
344
+ main,
345
+ private: isPrivate,
346
+ license,
347
+ engines: {
348
+ node: `^${runtime.version}`,
349
+ [runtime.packageManager]: '*',
350
+ },
351
+ scripts,
352
+ dependencies,
353
+ devDependencies,
354
+ ...rest,
355
+ };
356
+
357
+ return fs.writeJSON(join(root, 'package.json'), packageJson, WRITE_TO_JSON_OPTS);
358
+ }
359
+
360
+ /**
361
+ * @param {string} root
362
+ * @param {import('./flows/lib/manifest').Manifest} manifest
363
+ * @param {import('./helpers/resolve-app-runtime.js').Runtime} runtime
364
+ * @returns {Promise<void>}
365
+ * @throws {Error}
366
+ * @throws {import('child_process').ExecException}
367
+ * @throws {import('child_process').SpawnSyncReturns<Buffer>}
368
+ */
369
+ async function installDependencies(root, manifest, runtime) {
370
+ const command = manifest.isJs() ? runtime.packageManager : 'make';
371
+
372
+ if (IS_WINDOWS && !manifest.isJs()) {
373
+ logger.log();
374
+ logger.log(`⚠️ ${chalk.yellow('Please install project dependencies manually')}`);
375
+
376
+ return;
377
+ }
378
+
379
+ const args = ['install'];
380
+ const opts = { stdio: ['inherit', 'inherit', 'pipe'], cwd: root };
381
+
382
+ if (process.env.CI && command === 'yarn') {
383
+ args.push('--cache-folder=".yarn-cache"');
384
+ }
385
+
386
+ logger.log(chalk.yellow(`Installing template dependencies using ${runtime.packageManager}...`));
387
+
388
+ const nvmOpts = {
389
+ shell: true,
390
+ ...opts,
391
+ };
392
+
393
+ const proc =
394
+ manifest.isJs() && existsSync(`${os.homedir()}/.nvm/nvm.sh`)
395
+ ? spawn.sync(`\\. ${os.homedir()}/.nvm/nvm.sh && nvm i && ${command} ${args.join(' ')}`, nvmOpts)
396
+ : spawn.sync(command, args, opts);
397
+
398
+ if (proc.stderr) {
399
+ const error = proc.stderr
400
+ .toString('utf8')
401
+ .split('\n')
402
+ // NOTE: filter out warnings caused by @corva/ui peer dependencies
403
+ .filter((line) => !line.includes('@corva/ui'))
404
+ .join('\n');
405
+
406
+ console.log(error);
407
+ }
408
+
409
+ if (proc.status !== 0) {
410
+ console.error(`\`${command} ${args.join(' ')}\` failed`);
411
+
412
+ return;
413
+ }
414
+
415
+ logger.log(chalk.green('Successfull project install'));
416
+ }
417
+
418
+ async function helpCommands(manifest, { packageManager: displayedCommand }) {
419
+ if (!manifest.isUi()) {
420
+ return;
421
+ }
422
+
423
+ const useYarn = displayedCommand === 'yarn';
424
+
425
+ logger.log('Inside that directory, you can run several commands:');
426
+ logger.log();
427
+ logger.log(chalk.cyan(` ${displayedCommand} start`));
428
+ logger.log(' Starts the development server.');
429
+ logger.log();
430
+ logger.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`));
431
+ logger.log(' Bundles the app into static files for production.');
432
+ logger.log();
433
+ logger.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}zip`));
434
+ logger.log(' Bundles the app into ZIP file in app root directory');
435
+ logger.log();
436
+ logger.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}release`));
437
+ logger.log(' Uploads the app ZIP to Corva');
438
+ logger.log();
439
+ }
440
+
441
+ function startingMessage() {
442
+ clear();
443
+ console.log(chalk.green(' Welcome to apps generator for:'));
444
+ console.log(chalk.cyan(figlet.textSync('CORVA.AI', { horizontalLayout: 'full' })));
445
+ }
446
+
447
+ function checkOptions(opts) {
448
+ let isValid = true;
449
+ const values = {};
450
+
451
+ getManifestMandatoryKeys(opts).forEach((key) => {
452
+ if (!opts[key]) {
453
+ isValid = false;
454
+ }
455
+
456
+ values[key] = opts[key];
457
+ });
458
+
459
+ return {
460
+ isValid,
461
+ values,
462
+ };
463
+ }
@@ -0,0 +1,58 @@
1
+ import chalk from 'chalk';
2
+ import { Command, Option } from 'commander';
3
+ import { runFlow } from '../flow.js';
4
+ import { RELEASE_FLOW } from '../flows/release.js';
5
+ import { getRealWorkingDir } from '../helpers/commands.js';
6
+ import { apiKeyOption } from '../options/api-key.js';
7
+ import { bumpVersionOption } from '../options/bump-version.js';
8
+ import { envOption } from '../options/env.js';
9
+ import { originalCwdOption } from '../options/original-cwd.js';
10
+ import { silentOption } from '../options/silent.js';
11
+ import { ensureBumpVersion } from '../helpers/cli-version.js';
12
+ import { ERROR_ICON } from '../constants/messages.js';
13
+ import { appKeyOption } from '../options/app-key.js';
14
+
15
+ export const releaseCommand = new Command('release')
16
+ .description('Release app')
17
+ .argument('<project-directory>', 'Project directory to work with')
18
+ .argument('[patterns...]', 'Additional patterns to zip', [])
19
+ .addOption(bumpVersionOption)
20
+ .addOption(new Option('--ignored-files [string...]', 'Patterns to skip zip').default([]))
21
+ .addOption(silentOption)
22
+ .addOption(envOption)
23
+ .addOption(apiKeyOption)
24
+ .addOption(appKeyOption)
25
+ .addOption(originalCwdOption)
26
+ .addOption(new Option('--notes [string]', 'Add custom notes to published app'))
27
+ .addOption(new Option('--label [string]', 'Put a label on the release').choices(['DEV', 'BETA', 'PROD']))
28
+ .addOption(new Option('--remove-on-fail [boolean]', 'Remove release if it fails during deployment').default(false))
29
+ .addOption(
30
+ new Option('--remove-on-success [boolean]', 'App package (.zip) will not be deleted after upload').default(true),
31
+ )
32
+ .addOption(
33
+ new Option(
34
+ '--remove-existing [boolean]',
35
+ 'If package version is already taken - remove the previously published package and upload a new one',
36
+ ).default(false),
37
+ )
38
+ // .addOption(new Option('--zip-file-name [string]', 'Prebuilt zip file name in dir'))
39
+ .addOption(new Option('--author [string]', 'Author name for the audit'))
40
+ .action(async (dirName, patterns, options) => {
41
+ // if author is present in CLI, save it to process.env
42
+ if (options.author) {
43
+ process.env.githubUsername = options.author;
44
+ }
45
+
46
+ options.bumpVersion = await ensureBumpVersion(options.bumpVersion);
47
+
48
+ await runFlow(RELEASE_FLOW, {
49
+ dirName: getRealWorkingDir(dirName, options),
50
+ patterns,
51
+ options,
52
+ });
53
+ })
54
+ .showHelpAfterError()
55
+ .showSuggestionAfterError(true)
56
+ .configureOutput({
57
+ outputError: (str, write) => write(chalk.red(`${ERROR_ICON} ${str}`)),
58
+ });
@@ -0,0 +1,34 @@
1
+ import chalk from 'chalk';
2
+ import { Command, Option } from 'commander';
3
+ import { ERROR_ICON } from '../constants/messages.js';
4
+ import { runFlow } from '../flow.js';
5
+ import { RERUN_FLOW } from '../flows/rerun.js';
6
+ import { getRealWorkingDir } from '../helpers/commands.js';
7
+ import { apiKeyOption } from '../options/api-key.js';
8
+ import { appVersion } from '../options/app-version.js';
9
+ import { envOption } from '../options/env.js';
10
+ import { originalCwdOption } from '../options/original-cwd.js';
11
+ import { silentOption } from '../options/silent.js';
12
+ import { cacheOption } from '../options/cache.js';
13
+
14
+ export const rerunCommand = new Command('rerun')
15
+ .description('Rerun app')
16
+ .argument('<project-directory>', 'Project directory to work with')
17
+ .addOption(apiKeyOption)
18
+ .addOption(envOption)
19
+ .addOption(silentOption)
20
+ .addOption(cacheOption)
21
+ .addOption(appVersion)
22
+ .addOption(new Option('--assets [assets...]', 'Assets IDs list', []).conflicts('companyId'))
23
+ .addOption(new Option('--company-id [number]', 'Company ID', []))
24
+ .addOption(new Option('--interval [number]', 'Interval for scheduler apps (exp. 1200)'))
25
+ .addOption(new Option('--force-stream-log-type [string]', 'Force stream log type').choices(['time', 'depth']))
26
+ .addOption(originalCwdOption)
27
+ .action(async (dirName, options) => {
28
+ await runFlow(RERUN_FLOW, { dirName: getRealWorkingDir(dirName, options), options });
29
+ })
30
+ .showHelpAfterError()
31
+ .showSuggestionAfterError(true)
32
+ .configureOutput({
33
+ outputError: (str, write) => write(chalk.red(`${ERROR_ICON} ${str}`)),
34
+ });
@@ -0,0 +1,39 @@
1
+ import chalk from 'chalk';
2
+ import { Command, Option } from 'commander';
3
+ import _ from 'lodash/fp.js';
4
+
5
+ import { runFlow } from '../flow.js';
6
+ import { ZIP_FLOW } from '../flows/zip.js';
7
+ import { getRealWorkingDir, silencer } from '../helpers/commands.js';
8
+ import { bumpVersionOption } from '../options/bump-version.js';
9
+ import { originalCwdOption } from '../options/original-cwd.js';
10
+ import { silentOption } from '../options/silent.js';
11
+ import { ensureBumpVersion } from '../helpers/cli-version.js';
12
+ import { ERROR_ICON } from '../constants/messages.js';
13
+
14
+ export const zipCommand = new Command('zip')
15
+ .description('Bundle app')
16
+ .argument('<project-directory>', 'Project directory to work with')
17
+ .argument('[patterns...]', 'Additional patterns to zip', [])
18
+ .addOption(bumpVersionOption)
19
+ .addOption(new Option('--ignored-files [ignoredFiles...]', 'Patterns to skip zip', []))
20
+ .addOption(originalCwdOption)
21
+ .addOption(silentOption)
22
+ .action(
23
+ silencer(async (dirName, patterns, options) => {
24
+ options.bumpVersion = await ensureBumpVersion(options.bumpVersion);
25
+
26
+ console.log(getRealWorkingDir(dirName, options), options);
27
+
28
+ return runFlow(ZIP_FLOW, {
29
+ dirName: getRealWorkingDir(dirName, options),
30
+ patterns,
31
+ options,
32
+ }).then(_.get('zipFileName'));
33
+ }),
34
+ )
35
+ .showHelpAfterError()
36
+ .showSuggestionAfterError(true)
37
+ .configureOutput({
38
+ outputError: (str, write) => write(chalk.red(`${ERROR_ICON} ${str}`)),
39
+ });
@@ -0,0 +1,5 @@
1
+ export const DELETE_CACHE_BEHAVIOR = 'delete';
2
+
3
+ export const OVERRIDE_CACHE_BEHAVIOR = 'override';
4
+
5
+ export const KEEP_CACHE_BEHAVIOR = 'keep';
@@ -0,0 +1,35 @@
1
+ export const APP_RUNTIMES = {
2
+ UI: 'ui',
3
+ // NODE12: 'nodejs12.x',
4
+ // NODE14: 'nodejs14.x',
5
+ // NODE16: 'nodejs16.x',
6
+ NODE18: 'nodejs18.x',
7
+ NODE20: 'nodejs20.x',
8
+ NODE22: 'nodejs22.x',
9
+ NODE24: 'nodejs24.x',
10
+ // PYTHON3_8: 'python3.8',
11
+ // PYTHON3_9: 'python3.9',
12
+ // PYTHON3_10: 'python3.10',
13
+ PYTHON3_11: 'python3.11',
14
+ PYTHON3_12: 'python3.12',
15
+ PYTHON3_13: 'python3.13',
16
+ };
17
+
18
+ export const TEMPLATE_TYPES = {
19
+ UI: 'js',
20
+ UI_TS: 'ts',
21
+ NODE: 'node',
22
+ NODE_TYPESCRIPT: 'node-ts',
23
+ PYTHON: 'python',
24
+ };
25
+
26
+ export const APP_TYPES = {
27
+ UI: 'ui',
28
+ SCHEDULER: 'scheduler',
29
+ STREAM: 'stream',
30
+ TASK: 'task',
31
+ };
32
+
33
+ export const APP_EXTENSIONS = {
34
+ CORVA: 'corva',
35
+ };