@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,68 @@
1
+ import chalk from 'chalk';
2
+
3
+ import { logger } from '../../../helpers/logger.js';
4
+
5
+ export const ENSURE_APP_IN_STREAM_TASK_STEP = {
6
+ message: 'Ensure that app in the stream...',
7
+ /**
8
+ *
9
+ * @param {object} context
10
+ */
11
+ fn: async (context) => {
12
+ const { mappedAssetsToStreams, app, api, manifest, corvaUrl } = context;
13
+
14
+ await Promise.all(
15
+ [...mappedAssetsToStreams].map(([assetId, stream]) => {
16
+ return ensureAppIsInTheStream(assetId, stream, app.id, api, manifest, corvaUrl);
17
+ }),
18
+ );
19
+
20
+ return context;
21
+ },
22
+ };
23
+
24
+ /**
25
+ * Ensure if the app is in the stream, if no, add app to the stream
26
+ *
27
+ * @param {string} assetId
28
+ * @param {object} stream
29
+ * @param {string} appId
30
+ * @param {import('../lib/api').Api} api
31
+ * @param {object} manifest
32
+ * @param {string} corvaUrl
33
+ *
34
+ * @returns {void}
35
+ */
36
+ const ensureAppIsInTheStream = async (assetId, stream, appId, api, manifest, corvaUrl) => {
37
+ const connectedApps = stream.app_connections.filter((connection) => connection.app_id === parseInt(appId));
38
+
39
+ if (connectedApps.length) {
40
+ if (connectedApps.length > 1) {
41
+ logger.write(
42
+ `\n\n${chalk.black.underline.bold(
43
+ `Attention, this app connected to the stream more than once: ${corvaUrl}/config/streams/${stream.id}, Asset ID: ${assetId}. Logic will make a rerun per each app`,
44
+ )}`,
45
+ );
46
+
47
+ return;
48
+ }
49
+
50
+ logger.write(
51
+ `\n\n${chalk.black.underline.bold(
52
+ `App has been already connected to the stream: ${corvaUrl}/config/streams/${stream.id}, Asset ID: ${assetId}`,
53
+ )}`,
54
+ );
55
+
56
+ return;
57
+ }
58
+
59
+ const newConnection = await api.connectAppToStream(appId, stream.id, manifest.manifest.settings.app);
60
+
61
+ stream.app_connections.push(newConnection);
62
+
63
+ logger.write(
64
+ `\n\n${chalk.black.underline.bold(
65
+ `Added app to the stream: ${corvaUrl}/config/streams/${stream.id} App: ${corvaUrl}/config/streams/${stream.id}/apps/${newConnection.id}, Asset ID: ${assetId}`,
66
+ )}`,
67
+ );
68
+ };
@@ -0,0 +1,111 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+
4
+ import { logger } from '../../../helpers/logger.js';
5
+ import { StepError } from '../../lib/step-error.js';
6
+
7
+ export const GET_APP_VERSION_TASK_STEP = {
8
+ message: 'Get app version...',
9
+ /**
10
+ *
11
+ * @param {object} context
12
+ */
13
+ fn: async (context) => {
14
+ const { app, options, api } = context;
15
+ const { appVersion } = options;
16
+
17
+ const currentAppVersion = await getAppVersion(app.id, appVersion, api);
18
+
19
+ return {
20
+ ...context,
21
+ version: currentAppVersion,
22
+ };
23
+ },
24
+ };
25
+
26
+ /**
27
+ * CLI prompt question - Please choose the app version (optional).
28
+ *
29
+ * @param {string} appId
30
+ * @param {string} optionAppVersion
31
+ * @param {import('../lib/api').Api} api
32
+ *
33
+ * @returns {Promise<{number}>}
34
+ */
35
+ const getAppVersion = async (appId, optionAppVersion, api) => {
36
+ logger.write('\n Checking app versions...');
37
+
38
+ const appPackages = await api.getAppPackages(appId);
39
+
40
+ if (!appPackages.length) {
41
+ throw new StepError('No app versions found');
42
+ }
43
+
44
+ const confirmUseVersionMessage = (version) => {
45
+ logger.write(`\n\n${chalk.black.underline.bold(`Use app version - ${chalk.green(version)}`)}`);
46
+ };
47
+
48
+ // try to get version from CLI option
49
+ if (optionAppVersion) {
50
+ const currentAppPackageByOption = appPackages.find(
51
+ (appPackage) => appPackage.attributes.version === optionAppVersion,
52
+ );
53
+
54
+ if (currentAppPackageByOption) {
55
+ const version = currentAppPackageByOption.attributes.version;
56
+
57
+ confirmUseVersionMessage(version);
58
+
59
+ return version;
60
+ }
61
+
62
+ logger.write(`\n\n${chalk.black.underline.bold(`Could not find app version - ${chalk.green(optionAppVersion)}`)}`);
63
+ }
64
+
65
+ // if there is only on version, use it.
66
+ if (appPackages.length === 1) {
67
+ const version = appPackages[0].attributes.version;
68
+
69
+ confirmUseVersionMessage(version);
70
+
71
+ return version;
72
+ }
73
+
74
+ // if there are several versions, show versions list to user
75
+ const choices = appPackages.map((appPackage) => {
76
+ const parts = [];
77
+ const { notes, label, version } = appPackage.attributes;
78
+
79
+ if (label) {
80
+ parts.push(label);
81
+ }
82
+
83
+ if (notes) {
84
+ parts.push(notes);
85
+ }
86
+
87
+ if (version) {
88
+ parts.push(version);
89
+ }
90
+
91
+ return {
92
+ value: appPackage.attributes.version,
93
+ name: parts.join(' '),
94
+ };
95
+ });
96
+
97
+ logger.log('\n');
98
+
99
+ return inquirer
100
+ .prompt([
101
+ {
102
+ message: 'Please choose the app version?',
103
+ name: 'option',
104
+ type: 'list',
105
+ choices,
106
+ },
107
+ ])
108
+ .then((answers) => {
109
+ return answers.option;
110
+ });
111
+ };
@@ -0,0 +1,162 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import _ from 'lodash';
4
+ import { logger } from '../../../helpers/logger.js';
5
+ import { StepError } from '../../lib/step-error.js';
6
+
7
+ const MAX_ASSET_IDS_COUNT = 300;
8
+
9
+ export const PREPARE_DATA_TASK_STEP = {
10
+ message: 'Preparing and checking data...',
11
+ fn: async (context) => {
12
+ const { manifest, options, api, CORVA_API_ENV } = context;
13
+ let { assets, interval, companyId } = options;
14
+
15
+ if (companyId) {
16
+ assets = await getAssetsByCompanyId(companyId, api);
17
+ }
18
+
19
+ assets = _.uniq(assets);
20
+
21
+ if (assets.length > MAX_ASSET_IDS_COUNT) {
22
+ throw new StepError(`Please no more than ${MAX_ASSET_IDS_COUNT} asset ids!`);
23
+ }
24
+
25
+ if (!['scheduler', 'stream'].includes(manifest.manifest.application.type)) {
26
+ throw new StepError('Rerun command supports only "scheduler" or "stream" apps');
27
+ }
28
+
29
+ if (!(await promptAreYouSure())) {
30
+ throw new StepError('Command stopped');
31
+ }
32
+
33
+ const app = await api.getAppByKey(manifest.manifest.application.key);
34
+ const appDatasets = await api.getAppDatasetsOperationWrite(app.id);
35
+ const appDatasetsNames = appDatasets.map((dataset) => dataset.attributes.dataset_name);
36
+
37
+ const existingAppRuns = await getExistAppRuns(app.id, assets, appDatasetsNames, api);
38
+
39
+ if (existingAppRuns.size) {
40
+ for (const appRunAssetId of existingAppRuns.keys()) {
41
+ // remove asset ID if similar rerun already exists
42
+ assets = assets.filter((assetId) => appRunAssetId !== assetId);
43
+
44
+ const run = existingAppRuns.get(appRunAssetId);
45
+
46
+ logger.write(
47
+ `\n\n${chalk.yellow.bold(
48
+ `A similar rerun with ID ${run.id}, for asset ID ${appRunAssetId} - already exists. Will be skipped!`,
49
+ )}`,
50
+ );
51
+ }
52
+ }
53
+
54
+ const corvaUrl = `https://app${CORVA_API_ENV === 'production' ? '.' : `.${CORVA_API_ENV}.`}corva.ai`;
55
+
56
+ return {
57
+ assets,
58
+ corvaUrl,
59
+ app,
60
+ options,
61
+ manifest,
62
+ appDatasetsNames,
63
+ interval: getInterval(manifest.manifest, interval),
64
+ };
65
+ },
66
+ };
67
+
68
+ /**
69
+ * CLI prompt question - Are you sure you want to do this?
70
+ *
71
+ * @returns
72
+ */
73
+ const promptAreYouSure = async () => {
74
+ logger.log('\n');
75
+
76
+ const answers = await inquirer.prompt([
77
+ {
78
+ message:
79
+ 'This command will create an additional load on the server, which may take a long time. \n Are you sure you want to do this?',
80
+ name: 'option',
81
+ type: 'list',
82
+ choices: [
83
+ { value: true, name: 'Yes' },
84
+ { value: false, name: 'No' },
85
+ ],
86
+ default: false,
87
+ },
88
+ ]);
89
+
90
+ return answers.option;
91
+ };
92
+
93
+ /**
94
+ * Get all suitable assets for rerun by company ID
95
+ *
96
+ * @param {number} comanyId
97
+ * @param {object} api
98
+ *
99
+ * @returns {number[]}
100
+ */
101
+ const getAssetsByCompanyId = async (companyId, api) => {
102
+ logger.write('\n Try to find all suitable assets by Company ID...');
103
+
104
+ const assets = await api.getAllAssets(['complete', 'idle', 'paused', 'unknown'], companyId);
105
+
106
+ logger.write(`\n\n Found ${chalk.yellow.bold(assets.length)} assets, for the company ID ${companyId}!`);
107
+
108
+ return assets.map((asset) => asset.id);
109
+ };
110
+
111
+ /**
112
+ * Check if current runs already exist
113
+ *
114
+ * @param {string} appId
115
+ * @param {string[]} assets
116
+ * @param {string[]} appDatasetsNames
117
+ * @param {object} api
118
+ *
119
+ * @returns {map}
120
+ */
121
+ const getExistAppRuns = async (appId, assets, appDatasetsNames, api) => {
122
+ const appRuns = new Map();
123
+ const existingAppRuns = await api.getAppRuns(appId);
124
+
125
+ // go through all assets ids
126
+ for (const assetId of assets) {
127
+ const runsForCurrentAsset = existingAppRuns.filter((run) => run.attributes.well_asset_id === assetId);
128
+
129
+ // go through all existing runs for current asset ID
130
+ for (const run of runsForCurrentAsset) {
131
+ const currentAppDatasetsNames = run.attributes.app_run_datasets.map((dataset) => dataset.name);
132
+
133
+ // if datasets names matched for the same asset ID - then run already exist
134
+ if (appDatasetsNames.sort().toString() === currentAppDatasetsNames.sort().toString()) {
135
+ appRuns.set(assetId, run);
136
+ }
137
+ }
138
+ }
139
+
140
+ return appRuns;
141
+ };
142
+
143
+ /**
144
+ * Get interval
145
+ *
146
+ * @param {object} manifest
147
+ * @param {number} intervalOption
148
+ *
149
+ * @returns {number | null}
150
+ */
151
+ const getInterval = (manifest, intervalOption) => {
152
+ if (manifest.application.type !== 'scheduler') {
153
+ return null;
154
+ }
155
+
156
+ const DEFAULT_INTERVAL = 3600;
157
+ const interval = intervalOption || DEFAULT_INTERVAL;
158
+
159
+ logger.write(`\n\n${chalk.black.underline.bold(`Use interval - ${chalk.green(interval)}`)}`);
160
+
161
+ return parseInt(interval);
162
+ };
@@ -0,0 +1,188 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+
4
+ import { logger } from '../../../helpers/logger.js';
5
+
6
+ export const PREPARE_WELL_AND_STREAM_TASK_STEP = {
7
+ message: 'Prepare well and stream data...',
8
+ /**
9
+ *
10
+ * @param {object} context
11
+ */
12
+ fn: async (context) => {
13
+ let { assets } = context;
14
+ const {
15
+ api,
16
+ manifest,
17
+ options: { forceStreamLogType },
18
+ } = context;
19
+
20
+ const { mappedAssetsToWells, mappedAssetsToStreams, assetsToDelete } = await prepareWellAndStreamData(
21
+ assets,
22
+ api,
23
+ manifest,
24
+ forceStreamLogType,
25
+ );
26
+
27
+ if (assetsToDelete.length) {
28
+ // remove asset ID if could not found stream or well
29
+ assets = assets.filter((assetId) => !assetsToDelete.includes(assetId));
30
+ }
31
+
32
+ return {
33
+ ...context,
34
+ assets,
35
+ mappedAssetsToStreams,
36
+ mappedAssetsToWells,
37
+ };
38
+ },
39
+ };
40
+
41
+ /**
42
+ * CLI prompt question - Please choose the stream
43
+ *
44
+ * @param {object[]} streams
45
+ * @param {('time'|'depth')} [forceStreamLogType]
46
+ *
47
+ * @returns {Promise<object>}
48
+ */
49
+ const getStreamWithPrompt = async (streams, forceStreamLogType) => {
50
+ const _streams = forceStreamLogType ? streams.filter((stream) => stream.log_type === forceStreamLogType) : streams;
51
+
52
+ const choices = _streams.map((stream) => {
53
+ return {
54
+ value: stream,
55
+ name: `${stream.name} (${stream.log_type})`,
56
+ };
57
+ });
58
+
59
+ if (!choices.length) {
60
+ throw new Error('No completed streams');
61
+ }
62
+
63
+ if (choices.length === 1) {
64
+ const [stream] = choices;
65
+
66
+ logger.write(`\n\n${chalk.black.underline.bold(`Process stream - ${chalk.green(stream.name)}`)}`);
67
+
68
+ return stream.value;
69
+ }
70
+
71
+ logger.log('\n');
72
+
73
+ return inquirer
74
+ .prompt([
75
+ {
76
+ message: 'Please choose stream?',
77
+ name: 'option',
78
+ type: 'list',
79
+ choices,
80
+ },
81
+ ])
82
+ .then((answers) => answers.option);
83
+ };
84
+
85
+ /**
86
+ * CLI prompt question - Please choose the well
87
+ *
88
+ * @param {object[]} wells
89
+ * @param {import('../lib/api').Api} api
90
+ *
91
+ * @returns {Promise<object>}
92
+ */
93
+ const getWellWithPrompt = async (wells, api) => {
94
+ const choices = await Promise.all(
95
+ wells.map(async (well) => {
96
+ const assetDetails = await api.getAssetById(well.data.attributes.asset_id);
97
+
98
+ well.data.name = assetDetails.attributes.name;
99
+
100
+ return {
101
+ value: well.data,
102
+ name: well.data.name,
103
+ };
104
+ }),
105
+ );
106
+
107
+ if (!choices.length) {
108
+ throw new Error('No wells found');
109
+ }
110
+
111
+ if (choices.length === 1) {
112
+ const [well] = choices;
113
+
114
+ logger.write(`\n\n${chalk.black.underline.bold(`Process well - ${chalk.green(well.name)}`)}`);
115
+
116
+ return well.value;
117
+ }
118
+
119
+ logger.log('\n');
120
+
121
+ return inquirer
122
+ .prompt([
123
+ {
124
+ message: 'Please choose the well?',
125
+ name: 'option',
126
+ type: 'list',
127
+ choices,
128
+ },
129
+ ])
130
+ .then((answers) => answers.option);
131
+ };
132
+
133
+ /**
134
+ * Get stream and well data for assets
135
+ *
136
+ * @param {string[]} assets
137
+ * @param {import('../lib/api').Api} api
138
+ * @param {object} manifest
139
+ * @param {('time'|'depth')} [forceStreamLogType]
140
+ *
141
+ * @returns {Promise<object>}
142
+ */
143
+ const prepareWellAndStreamData = async (assets, api, manifest, forceStreamLogType) => {
144
+ const mappedAssetsToWells = new Map();
145
+ const mappedAssetsToStreams = new Map();
146
+ const assetsToDelete = [];
147
+
148
+ for (const assetId of assets) {
149
+ try {
150
+ logger.write(`\n\n${chalk.black.underline.bold(`Process asset ID - ${chalk.green(assetId)}`)}`);
151
+
152
+ logger.write('\n Loading wells...');
153
+
154
+ const wells = await api.getWellByAssetId(assetId);
155
+ const well = await getWellWithPrompt(wells, api);
156
+
157
+ mappedAssetsToWells.set(well.attributes.asset_id, well);
158
+
159
+ logger.write('\n Loading streams...');
160
+
161
+ const streams = await api.getStreamsByAssetIds([assetId], manifest.manifest.application.segments);
162
+
163
+ if (!streams || !streams.length) {
164
+ throw new Error(`Could not found streams in Complete status for the asset ID - ${assetId}`);
165
+ }
166
+
167
+ const stream = await getStreamWithPrompt(streams, forceStreamLogType);
168
+
169
+ mappedAssetsToStreams.set(stream.asset_id, stream);
170
+ } catch (e) {
171
+ logger.write(
172
+ `\n\n${chalk.red.underline.bold(`Skipped the asset ID - ${assetId}, an error occurred: ${e.message}`)}`,
173
+ );
174
+
175
+ assetsToDelete.push(assetId);
176
+
177
+ if (mappedAssetsToWells.has(assetId)) mappedAssetsToWells.delete(assetId);
178
+
179
+ if (mappedAssetsToStreams.has(assetId)) mappedAssetsToStreams.delete(assetId);
180
+ }
181
+ }
182
+
183
+ return {
184
+ mappedAssetsToWells,
185
+ mappedAssetsToStreams,
186
+ assetsToDelete,
187
+ };
188
+ };
@@ -0,0 +1,13 @@
1
+ import { CREATE_TASK_STEP } from './create-task.js';
2
+ import { PREPARE_DATA_TASK_STEP } from './prepare-data.js';
3
+ import { GET_APP_VERSION_TASK_STEP } from './get-app-version.js';
4
+ import { ENSURE_APP_IN_STREAM_TASK_STEP } from './ensure-that-app-in-stream.js';
5
+ import { PREPARE_WELL_AND_STREAM_TASK_STEP } from './prepare-well-and-stream-data.js';
6
+
7
+ export const RERUN_STEPS = [
8
+ PREPARE_DATA_TASK_STEP,
9
+ GET_APP_VERSION_TASK_STEP,
10
+ PREPARE_WELL_AND_STREAM_TASK_STEP,
11
+ ENSURE_APP_IN_STREAM_TASK_STEP,
12
+ CREATE_TASK_STEP,
13
+ ];
@@ -0,0 +1,17 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+
4
+ import debugFn from 'debug';
5
+
6
+ const debug = debugFn('cca:flow:zip:cleanup');
7
+
8
+ export const CLEANUP_STEP = {
9
+ message: 'Removing temporary files...',
10
+ fn: async ({ itemsToRemove, dirName }) => {
11
+ for (const item of itemsToRemove) {
12
+ debug('Removing %s', item);
13
+
14
+ await fs.unlink(resolve(dirName, item));
15
+ }
16
+ },
17
+ };
@@ -0,0 +1,15 @@
1
+ import debugFn from 'debug';
2
+ import { createZipArchive } from '../lib/create-zip-archive.js';
3
+
4
+ const debug = debugFn('cca:flow:zip:archive');
5
+
6
+ export const CREATE_ARCHIVE_STEP = {
7
+ message: 'Creating archive...',
8
+ fn: async ({ itemsToZip, zipFileName, dirName }) => {
9
+ debug(`Zipping %d items to %s`, itemsToZip.length, zipFileName);
10
+
11
+ const bytes = await createZipArchive(dirName, zipFileName, itemsToZip);
12
+
13
+ debug(`Created %s with %d items (%d bytes)`, zipFileName, itemsToZip.length, bytes);
14
+ },
15
+ };