@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,376 @@
1
+ import debugFn from 'debug';
2
+ import got from 'got';
3
+ import { StepError } from './step-error.js';
4
+ import { OVERRIDE_CACHE_BEHAVIOR, DELETE_CACHE_BEHAVIOR } from './../../constants/cache.js';
5
+
6
+ const debug = debugFn('cca:api');
7
+
8
+ /**
9
+ * Connect to Corva API
10
+ *
11
+ */
12
+ export class Api {
13
+ /**
14
+ * @type {import('got').Got}
15
+ */
16
+ #api;
17
+
18
+ constructor(envName, apiKey, authToken = null) {
19
+ const prefixUrl = `https://api${envName === 'production' ? '' : `.${envName}`}.corva.ai`;
20
+
21
+ this.#api = got.extend({
22
+ prefixUrl,
23
+ retry: { limit: 0 },
24
+ headers: {
25
+ 'Authorization': authToken ? `Bearer ${authToken}` : `API ${apiKey}`,
26
+ 'Content-Type': 'application/json',
27
+ 'Accept': 'application/json',
28
+ },
29
+ hooks: {
30
+ beforeRequest: [debug],
31
+ },
32
+ });
33
+ }
34
+
35
+ /**
36
+ * Get app by appKey
37
+ *
38
+ * @public
39
+ *
40
+ * @param {string} appKey
41
+ *
42
+ * @returns {object}
43
+ */
44
+ async getAppByKey(appKey) {
45
+ const { data } = await this.#api
46
+ .get('v2/apps', {
47
+ searchParams: { per_page: 2, search: appKey },
48
+ })
49
+ .json();
50
+
51
+ const app = data.find((app) => app.attributes.app_key === appKey);
52
+
53
+ if (!app) {
54
+ throw new StepError(
55
+ `App with key - ${appKey}, does not exist.\nThe key search is case-sensitive. You might need to update the app key in your app to exactly match the key.`,
56
+ );
57
+ }
58
+
59
+ return app;
60
+ }
61
+
62
+ /**
63
+ * Get app datasets
64
+ *
65
+ * @public
66
+ *
67
+ * @param {string} appId
68
+ *
69
+ * @returns {object}
70
+ */
71
+ async getAppDatasetsOperationWrite(appId) {
72
+ const { data } = await this.#api
73
+ .get(`v2/apps/${appId}/app_datasets?dataset_operation=write&fields[]=app_dataset.dataset_name`)
74
+ .json();
75
+
76
+ return data;
77
+ }
78
+
79
+ /**
80
+ * Get asset details
81
+ *
82
+ * @public
83
+ *
84
+ * @param {string} assetId
85
+ *
86
+ * @returns {Promise<object[]>}
87
+ */
88
+ async getAssetById(assetId) {
89
+ const { data } = await this.#api.get(`v2/assets/${assetId}`).json();
90
+
91
+ return data;
92
+ }
93
+
94
+ /**
95
+ * Get assets streams by ids
96
+ *
97
+ * @public
98
+ *
99
+ * @param {string[]} assetIds
100
+ * @param {string[]} segments
101
+ * @param {string[]} statuses
102
+ *
103
+ * @returns {Promise<object[]>}
104
+ */
105
+ async getStreamsByAssetIds(assetIds, segments, statuses = ['complete']) {
106
+ const searchParams = new URLSearchParams([
107
+ ...assetIds.map((assetId) => ['asset_id[]', assetId]),
108
+ ...segments.map((segment) => ['segment[]', segment]),
109
+ ...statuses.map((status) => ['status[]', status]),
110
+ ]);
111
+
112
+ return this.#api.get(`v1/app_streams`, { searchParams }).json();
113
+ }
114
+
115
+ /**
116
+ * Get all assets
117
+ *
118
+ * @public
119
+ *
120
+ * @param {string[]} statuses
121
+ * @param {number} companyId
122
+ * @param {number} perPage
123
+ *
124
+ * @returns {Promise<object[]>}
125
+ */
126
+ async getAllAssets(statuses = ['active'], companyId = null, perPage = 2000) {
127
+ const searchParams = [['per_page', perPage]];
128
+
129
+ if (companyId) {
130
+ searchParams.push(['company_id', companyId]);
131
+ }
132
+
133
+ if (statuses?.length) {
134
+ searchParams.push(...statuses.map((status) => ['status[]', status]));
135
+ }
136
+
137
+ const { data } = await this.#api.get(`v2/assets`, { searchParams: new URLSearchParams(searchParams) }).json();
138
+
139
+ return data;
140
+ }
141
+
142
+ /**
143
+ * Get wells data by asset id
144
+ *
145
+ * @public
146
+ *
147
+ * @param {string} assetId
148
+ *
149
+ * @returns {object[]}
150
+ */
151
+ async getWellByAssetId(assetId) {
152
+ const { wells } = await this.#api
153
+ .post('v2/assets/resolve', {
154
+ json: { assets: [assetId] },
155
+ })
156
+ .json();
157
+
158
+ if (!wells || !wells.length) {
159
+ throw new StepError(`Could not find wells by asset ID - ${assetId}`);
160
+ }
161
+
162
+ return wells;
163
+ }
164
+
165
+ /**
166
+ * Queue app run for create new task
167
+ *
168
+ * @public
169
+ *
170
+ * @param {string} appId
171
+ * @param {string} version
172
+ * @param {number} interval
173
+ * @param {string} wellId
174
+ * @param {string[]} appDatasetsNames
175
+ * @param {string} streamId
176
+ * @param {number} appConnectionId
177
+ *
178
+ * @returns {object}
179
+ */
180
+ async queueAppRun(appId, version, interval, wellId, appDatasetsNames, streamId, appConnectionId, cache) {
181
+ const json = {
182
+ cache_behavior: cache ? OVERRIDE_CACHE_BEHAVIOR : DELETE_CACHE_BEHAVIOR,
183
+ cache_override: cache,
184
+ app_run: {
185
+ app_stream_id: streamId,
186
+ well_id: wellId,
187
+ app_version: version,
188
+ datasets: appDatasetsNames,
189
+ settings: {
190
+ end: 0,
191
+ invokes: null,
192
+ records_per_event: 300,
193
+ start: 0,
194
+ },
195
+ },
196
+ app_connection_id: appConnectionId,
197
+ };
198
+
199
+ if (interval) {
200
+ json.app_run.settings.interval = interval;
201
+ }
202
+
203
+ const { data } = await this.#api.post(`v2/apps/${appId}/app_runs`, { json }).json();
204
+
205
+ return data;
206
+ }
207
+
208
+ /**
209
+ * Get all active(status - pending or in_progress or running) runs by app ID
210
+ *
211
+ * @public
212
+ *
213
+ * @param {string} appId
214
+ *
215
+ * @returns {object[]}
216
+ */
217
+ async getAppRuns(appId) {
218
+ const { data } = await this.#api
219
+ .get(`v2/apps/${appId}/app_runs?page=1&per_page=500&status[]=pending&status[]=in_progress&status[]=running`)
220
+ .json();
221
+
222
+ return data;
223
+ }
224
+
225
+ /**
226
+ * Upload packages
227
+ *
228
+ * @public
229
+ *
230
+ * @param {string} appKey
231
+ * @param {object} formData
232
+ *
233
+ * @returns
234
+ */
235
+ async uploadPackages(appKey, formData) {
236
+ const uploadURL = `v2/apps/${appKey}/packages/upload`;
237
+
238
+ try {
239
+ const { data } = await this.#api
240
+ .post(uploadURL, {
241
+ headers: formData.getHeaders(),
242
+ body: formData,
243
+ })
244
+ .json();
245
+
246
+ return {
247
+ id: data.id,
248
+ status: data.attributes.status,
249
+ isDeletedDueToLimit: data.attributes.deleted_due_to_limit,
250
+ };
251
+ } catch (e) {
252
+ throw new StepError(`${JSON.parse(e.response.body).message || ''} \nPOST: ${uploadURL} failed.`, { cause: e });
253
+ }
254
+ }
255
+
256
+ /**
257
+ * @param {string} appId
258
+ * @param {string} id
259
+ * @param {string} notes
260
+ *
261
+ * @returns { Promise<{id: number, status: string}>}
262
+ */
263
+ async addNotes(appId, id, notes) {
264
+ const { data } = await this.#api
265
+ .patch(`v2/apps/${appId}/packages/${id}`, {
266
+ json: { package: { notes } },
267
+ })
268
+ .json();
269
+
270
+ return {
271
+ id: data.id,
272
+ status: data.attributes.status,
273
+ };
274
+ }
275
+
276
+ /**
277
+ * @param {string} appId
278
+ * @param {string} uploadId
279
+ *
280
+ * @returns { Promise<{id: number, status: string, notes: string}>}
281
+ */
282
+ async checkApp(appId, uploadId) {
283
+ const { data } = await this.#api.get(`v2/apps/${appId}/packages/${uploadId}`).json();
284
+
285
+ return {
286
+ id: data.id,
287
+ status: data.attributes.status,
288
+ notes: data.attributes.notes ?? '',
289
+ };
290
+ }
291
+
292
+ /**
293
+ * @param {string} appId
294
+ * @param {string} uploadId
295
+ *
296
+ * @returns { Promise<void>}
297
+ */
298
+ deleteAppUpload(appId, uploadId) {
299
+ return this.#api.delete(`v2/apps/${appId}/packages/${uploadId}`).json();
300
+ }
301
+
302
+ /**
303
+ * @param {string} appId
304
+ * @param {string} id
305
+ *
306
+ * @returns { Promise<{id: number, status: string}>}
307
+ */
308
+ async publishApp(appId, id) {
309
+ console.log(`v2/apps/${appId}/packages/${id}`, {
310
+ json: { package: { status: 'published' } },
311
+ });
312
+
313
+ const { data } = await this.#api
314
+ .patch(`v2/apps/${appId}/packages/${id}`, {
315
+ json: { package: { status: 'published' } },
316
+ })
317
+ .json();
318
+
319
+ console.log('done');
320
+
321
+ return {
322
+ id: data.id,
323
+ status: data.attributes.status,
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Get app packages
329
+ *
330
+ * @param {string} appId
331
+ *
332
+ * @returns { Promise<object[]>}
333
+ */
334
+ async getAppPackages(appId) {
335
+ const { data } = await this.#api.get(`v2/apps/${appId}/packages`).json();
336
+
337
+ return data;
338
+ }
339
+
340
+ /**
341
+ * Connect app to the stream
342
+ *
343
+ * @public
344
+ *
345
+ * @param {string} appId
346
+ * @param {string} streamId
347
+ * @param {object} settings
348
+ * @param {string} status
349
+ *
350
+ * @returns { Promise<object> }
351
+ */
352
+ async connectAppToStream(appId, streamId, settings, status = 'active') {
353
+ const json = {
354
+ app_stream_id: streamId,
355
+ app_id: appId,
356
+ status,
357
+ settings,
358
+ scheduler_type: settings.scheduler_type,
359
+ };
360
+
361
+ return this.#api.post('v1/app_connections', { json }).json();
362
+ }
363
+
364
+ /**
365
+ * @param {string} appId
366
+ * @param {string} id
367
+ * @param {'DEV' | 'BETA' | 'PROD'} label
368
+ *
369
+ * @returns { Promise<{id: number, status: string}>}
370
+ */
371
+ async putLabel(appId, id, label) {
372
+ await this.#api.patch(`v2/apps/${appId}/packages/${id}`, {
373
+ json: { package: { label } },
374
+ });
375
+ }
376
+ }
@@ -0,0 +1,83 @@
1
+ import archiver from 'archiver';
2
+ import debugFn from 'debug';
3
+
4
+ const debug = debugFn('cca:zip');
5
+
6
+ import { createWriteStream, promises as fs } from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ export const createZipArchive = async (dirName, zipName, itemsToZip = []) => {
10
+ const filePath = path.resolve(dirName, zipName);
11
+ const archive = archiver.create('zip', {});
12
+ const output = createWriteStream(filePath);
13
+
14
+ // pipe archive data to the file
15
+ archive.pipe(output);
16
+
17
+ // eslint-disable-next-line no-async-promise-executor
18
+ await new Promise(async (resolve, reject) => {
19
+ output.once('close', resolve).once('end', function () {
20
+ debug('Data has been drained');
21
+ });
22
+
23
+ archive.on('warning', function (err) {
24
+ if (err.code === 'ENOENT') {
25
+ console.warn(err.message);
26
+
27
+ return;
28
+ }
29
+
30
+ throw err;
31
+ });
32
+
33
+ archive.once('error', reject);
34
+
35
+ const dataToZip = await getDataToZip(itemsToZip, dirName);
36
+
37
+ for (const item of dataToZip) {
38
+ if (item.isDir) {
39
+ debug(`Adding directory %s -> %s`, item.path, item.name);
40
+ archive.directory(item.path, item.name);
41
+
42
+ continue;
43
+ }
44
+
45
+ debug(`Adding file %s -> %s`, item.path, item.name);
46
+ archive.file(item.path, { name: item.name });
47
+ }
48
+
49
+ archive.finalize();
50
+ });
51
+
52
+ return archive.pointer();
53
+ };
54
+
55
+ const getDataToZip = async (itemsToZip, dirName) => {
56
+ const promises = itemsToZip.map(async (name) => {
57
+ const nameWasProvided = typeof name === 'string';
58
+ const filePath = nameWasProvided ? path.resolve(dirName, name) : name.path;
59
+ const fileName = nameWasProvided ? name : name.name;
60
+
61
+ const { exists, isDir } = await fs
62
+ .lstat(filePath)
63
+ .then((stat) => ({
64
+ exists: true,
65
+ isDir: stat.isDirectory(),
66
+ }))
67
+ .catch(() => {
68
+ debug(`%s location not exist, filtering it out`, filePath);
69
+
70
+ return { exists: false, isDir: false };
71
+ });
72
+
73
+ return {
74
+ name: fileName,
75
+ path: filePath,
76
+ exists,
77
+ isDir,
78
+ };
79
+ });
80
+ const allData = await Promise.all(promises);
81
+
82
+ return allData.filter((f) => f.exists);
83
+ };
@@ -0,0 +1,30 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import os from 'node:os';
3
+ import { resolve } from 'node:path';
4
+
5
+ import debugFn from 'debug';
6
+ import { StepError } from './step-error.js';
7
+
8
+ const debug = debugFn('cca:json');
9
+
10
+ export const loadJson = async (dirName, fileName) => {
11
+ const fullPath = resolve(dirName, fileName);
12
+
13
+ try {
14
+ debug('Loading file %s', fullPath);
15
+
16
+ const manifest = await fs.readFile(fullPath, 'utf8');
17
+
18
+ return JSON.parse(manifest);
19
+ } catch (e) {
20
+ if (e.code === 'ENOENT') {
21
+ throw new StepError(`${fileName} was not found in ${resolve(dirName)}`, { cause: e });
22
+ }
23
+
24
+ throw e;
25
+ }
26
+ };
27
+
28
+ export const saveJson = async (dirName, fileName, data) => {
29
+ return fs.writeFile(resolve(dirName, fileName), JSON.stringify(data, null, 2) + os.EOL);
30
+ };
@@ -0,0 +1,81 @@
1
+ import set from 'lodash/set.js';
2
+ import { APP_TYPES, APP_RUNTIMES } from '../../constants/cli.js';
3
+ import {
4
+ SCHEDULER_TYPE_DATA_TIME,
5
+ SCHEDULER_TYPE_DEPTH,
6
+ SCHEDULER_TYPE_NATURAL_TIME,
7
+ } from '../../constants/manifest.js';
8
+
9
+ const SCHEDULER_MAPPING = [SCHEDULER_TYPE_DATA_TIME, SCHEDULER_TYPE_DEPTH, SCHEDULER_TYPE_NATURAL_TIME].reduce(
10
+ (acc, type) => set(acc, type.value, type.name.toLowerCase().replace(/ /, '-')),
11
+ {},
12
+ );
13
+
14
+ const NODE_RUNTIMES = [APP_RUNTIMES.NODE16, APP_RUNTIMES.NODE18];
15
+
16
+ export class Manifest {
17
+ constructor(manifest) {
18
+ this.manifest = manifest;
19
+ }
20
+
21
+ get runtime() {
22
+ return this.manifest.settings.runtime;
23
+ }
24
+
25
+ get type() {
26
+ return this.manifest.application.type;
27
+ }
28
+
29
+ get subtype() {
30
+ if (this.isScheduler()) {
31
+ return SCHEDULER_MAPPING[this.manifest.settings.app.scheduler_type];
32
+ }
33
+
34
+ if (this.isStream()) {
35
+ return this.manifest.settings.app.log_type;
36
+ }
37
+
38
+ return '';
39
+ }
40
+
41
+ get templateName() {
42
+ return this.type + (this.isScheduler() || this.isStream() ? `_${this.subtype}` : '');
43
+ }
44
+
45
+ get name() {
46
+ return this.manifest.application.name;
47
+ }
48
+
49
+ get unix_name() {
50
+ // todo: npm scopes?
51
+ return this.manifest.application.key.replace(/\W+/gi, '_').toLowerCase();
52
+ }
53
+
54
+ get description() {
55
+ return this.manifest.application.description;
56
+ }
57
+
58
+ isNode() {
59
+ return NODE_RUNTIMES.includes(this.manifest.settings.runtime);
60
+ }
61
+
62
+ isUi() {
63
+ return this.manifest.application.type === APP_TYPES.UI;
64
+ }
65
+
66
+ isJs() {
67
+ return this.isUi() || this.isNode();
68
+ }
69
+
70
+ isPython() {
71
+ return this.manifest.settings.runtime.startsWith('python');
72
+ }
73
+
74
+ isScheduler() {
75
+ return this.manifest.application.type === APP_TYPES.SCHEDULER;
76
+ }
77
+
78
+ isStream() {
79
+ return this.manifest.application.type === APP_TYPES.STREAM;
80
+ }
81
+ }
@@ -0,0 +1,142 @@
1
+ import chalk from 'chalk';
2
+ import terminalLink from 'terminal-link';
3
+
4
+ import { logger } from '../../helpers/logger.js';
5
+
6
+ /**
7
+ * Console notification
8
+ *
9
+ */
10
+ export class Notification {
11
+ #prefixUrl;
12
+
13
+ constructor(envName) {
14
+ this.#prefixUrl = `https://app${envName === 'production' ? '.' : `.${envName}.`}corva.ai`;
15
+ }
16
+
17
+ /**
18
+ * Create link
19
+ *
20
+ * @private
21
+ *
22
+ * @param {string} title
23
+ * @param {string} url
24
+ *
25
+ * @returns {string}
26
+ */
27
+ _createLink(title, url) {
28
+ return this._addLinkDecoration(terminalLink(title, url));
29
+ }
30
+
31
+ /**
32
+ * Print to console line break
33
+ *
34
+ * @public
35
+ *
36
+ * @returns {void}
37
+ */
38
+ printLineBreak() {
39
+ logger.write('\n');
40
+ }
41
+
42
+ /**
43
+ * Print to console text
44
+ *
45
+ * @public
46
+ *
47
+ * @param {string} text
48
+ *
49
+ * @returns {void}
50
+ */
51
+ print(text) {
52
+ this.printLineBreak();
53
+ logger.write(text);
54
+ }
55
+
56
+ /**
57
+ * Add a link styles
58
+ *
59
+ * @private
60
+ *
61
+ * @param {string} context
62
+ *
63
+ * @returns {string}
64
+ */
65
+ _addLinkDecoration(context) {
66
+ return chalk.blue.underline(context);
67
+ }
68
+
69
+ /**
70
+ * Add an error styles
71
+ *
72
+ * @private
73
+ *
74
+ * @param {string} context
75
+ *
76
+ * @returns {string}
77
+ */
78
+ _addErrorDecoration(context) {
79
+ return chalk.red.bold(context);
80
+ }
81
+
82
+ /**
83
+ * Get stream link
84
+ *
85
+ * @public
86
+ *
87
+ * @param {string} title
88
+ * @param {string} streamId
89
+ *
90
+ * @returns {string}
91
+ */
92
+ getStreamLink(title, streamId) {
93
+ const streamUrl = `${this.#prefixUrl}/config/streams/${streamId}`;
94
+
95
+ return this._createLink(title, streamUrl);
96
+ }
97
+
98
+ /**
99
+ * Print stream link
100
+ *
101
+ * @public
102
+ *
103
+ * @param {string} title
104
+ * @param {string} streamId
105
+ *
106
+ * @returns {avoid}
107
+ */
108
+ printStreamLink(title, streamId) {
109
+ const link = this.getStreamLink(title, streamId);
110
+
111
+ this.print(link);
112
+ }
113
+
114
+ /**
115
+ * Get asset link
116
+ *
117
+ * @public
118
+ *
119
+ * @param {string} title
120
+ * @param {string} assetId
121
+ *
122
+ * @returns {string}
123
+ */
124
+ getAssetLink(title, assetId) {
125
+ const assetUrl = `${this.#prefixUrl}/assets/${assetId}`;
126
+
127
+ return this._createLink(title, assetUrl);
128
+ }
129
+
130
+ /**
131
+ * Print an error
132
+ *
133
+ * @public
134
+ *
135
+ * @param {string} error
136
+ *
137
+ * @returns {void}
138
+ */
139
+ printError(error) {
140
+ this.print(this._addErrorDecoration(error));
141
+ }
142
+ }
@@ -0,0 +1,10 @@
1
+ export class StepError extends Error {
2
+ cause;
3
+ name;
4
+
5
+ constructor(message, { cause } = {}) {
6
+ super(message);
7
+ this.name = 'StepError';
8
+ this.cause = cause;
9
+ }
10
+ }