@factorialco/fcode-cli 1.1.0

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 (234) hide show
  1. package/README.md +1021 -0
  2. package/bin/dev +17 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/run +7 -0
  5. package/bin/run.cmd +3 -0
  6. package/dist/commands/add.d.ts +6 -0
  7. package/dist/commands/add.js +22 -0
  8. package/dist/commands/clone.d.ts +26 -0
  9. package/dist/commands/clone.js +177 -0
  10. package/dist/commands/dependencies/add.d.ts +9 -0
  11. package/dist/commands/dependencies/add.js +13 -0
  12. package/dist/commands/dependencies/install.d.ts +14 -0
  13. package/dist/commands/dependencies/install.js +44 -0
  14. package/dist/commands/dependencies/pull.d.ts +12 -0
  15. package/dist/commands/dependencies/pull.js +14 -0
  16. package/dist/commands/dependencies/push.d.ts +12 -0
  17. package/dist/commands/dependencies/push.js +14 -0
  18. package/dist/commands/dependencies/reset.d.ts +9 -0
  19. package/dist/commands/dependencies/reset.js +13 -0
  20. package/dist/commands/dependencies/status.d.ts +9 -0
  21. package/dist/commands/dependencies/status.js +13 -0
  22. package/dist/commands/http.d.ts +22 -0
  23. package/dist/commands/http.js +272 -0
  24. package/dist/commands/login.d.ts +18 -0
  25. package/dist/commands/login.js +62 -0
  26. package/dist/commands/logout.d.ts +10 -0
  27. package/dist/commands/logout.js +34 -0
  28. package/dist/commands/modules/add.d.ts +9 -0
  29. package/dist/commands/modules/add.js +13 -0
  30. package/dist/commands/modules/pull.d.ts +13 -0
  31. package/dist/commands/modules/pull.js +43 -0
  32. package/dist/commands/modules/push.d.ts +13 -0
  33. package/dist/commands/modules/push.js +35 -0
  34. package/dist/commands/modules/remove.d.ts +9 -0
  35. package/dist/commands/modules/remove.js +19 -0
  36. package/dist/commands/modules/reset.d.ts +9 -0
  37. package/dist/commands/modules/reset.js +13 -0
  38. package/dist/commands/modules/status.d.ts +11 -0
  39. package/dist/commands/modules/status.js +40 -0
  40. package/dist/commands/pre-debug.d.ts +20 -0
  41. package/dist/commands/pre-debug.js +120 -0
  42. package/dist/commands/process-metadata.d.ts +18 -0
  43. package/dist/commands/process-metadata.js +63 -0
  44. package/dist/commands/processes/add.d.ts +9 -0
  45. package/dist/commands/processes/add.js +13 -0
  46. package/dist/commands/processes/install-dependencies.d.ts +14 -0
  47. package/dist/commands/processes/install-dependencies.js +30 -0
  48. package/dist/commands/processes/pull.d.ts +13 -0
  49. package/dist/commands/processes/pull.js +47 -0
  50. package/dist/commands/processes/push.d.ts +13 -0
  51. package/dist/commands/processes/push.js +39 -0
  52. package/dist/commands/processes/remove.d.ts +9 -0
  53. package/dist/commands/processes/remove.js +19 -0
  54. package/dist/commands/processes/reset.d.ts +9 -0
  55. package/dist/commands/processes/reset.js +13 -0
  56. package/dist/commands/processes/status.d.ts +11 -0
  57. package/dist/commands/processes/status.js +58 -0
  58. package/dist/commands/pull.d.ts +9 -0
  59. package/dist/commands/pull.js +32 -0
  60. package/dist/commands/push.d.ts +9 -0
  61. package/dist/commands/push.js +29 -0
  62. package/dist/commands/remote/add.d.ts +10 -0
  63. package/dist/commands/remote/add.js +32 -0
  64. package/dist/commands/remote/list.d.ts +7 -0
  65. package/dist/commands/remote/list.js +33 -0
  66. package/dist/commands/remote/set.d.ts +10 -0
  67. package/dist/commands/remote/set.js +28 -0
  68. package/dist/commands/reset.d.ts +6 -0
  69. package/dist/commands/reset.js +19 -0
  70. package/dist/commands/run.d.ts +16 -0
  71. package/dist/commands/run.js +56 -0
  72. package/dist/commands/runtime-env.d.ts +12 -0
  73. package/dist/commands/runtime-env.js +42 -0
  74. package/dist/commands/settings/get.d.ts +12 -0
  75. package/dist/commands/settings/get.js +67 -0
  76. package/dist/commands/settings/remove.d.ts +9 -0
  77. package/dist/commands/settings/remove.js +35 -0
  78. package/dist/commands/settings/set.d.ts +10 -0
  79. package/dist/commands/settings/set.js +39 -0
  80. package/dist/commands/setup-debug.d.ts +12 -0
  81. package/dist/commands/setup-debug.js +118 -0
  82. package/dist/commands/status.d.ts +6 -0
  83. package/dist/commands/status.js +22 -0
  84. package/dist/commands/team/pull.d.ts +8 -0
  85. package/dist/commands/team/pull.js +23 -0
  86. package/dist/commands/team/push.d.ts +11 -0
  87. package/dist/commands/team/push.js +41 -0
  88. package/dist/commands/team/status.d.ts +8 -0
  89. package/dist/commands/team/status.js +40 -0
  90. package/dist/commands/test/scaffold.d.ts +9 -0
  91. package/dist/commands/test/scaffold.js +61 -0
  92. package/dist/commands/test.d.ts +13 -0
  93. package/dist/commands/test.js +72 -0
  94. package/dist/commands/variables/add.d.ts +12 -0
  95. package/dist/commands/variables/add.js +21 -0
  96. package/dist/commands/variables/pull.d.ts +12 -0
  97. package/dist/commands/variables/pull.js +14 -0
  98. package/dist/commands/variables/push.d.ts +12 -0
  99. package/dist/commands/variables/push.js +14 -0
  100. package/dist/commands/variables/remove.d.ts +9 -0
  101. package/dist/commands/variables/remove.js +19 -0
  102. package/dist/commands/variables/reset.d.ts +9 -0
  103. package/dist/commands/variables/reset.js +13 -0
  104. package/dist/commands/variables/status.d.ts +12 -0
  105. package/dist/commands/variables/status.js +58 -0
  106. package/dist/config/global.d.ts +15 -0
  107. package/dist/config/global.js +77 -0
  108. package/dist/config/index.d.ts +14 -0
  109. package/dist/config/index.js +44 -0
  110. package/dist/config/remote.d.ts +15 -0
  111. package/dist/config/remote.js +60 -0
  112. package/dist/config/settings.d.ts +16 -0
  113. package/dist/config/settings.js +54 -0
  114. package/dist/config/workspace.d.ts +28 -0
  115. package/dist/config/workspace.js +158 -0
  116. package/dist/core/commands/api-client-command.d.ts +6 -0
  117. package/dist/core/commands/api-client-command.js +30 -0
  118. package/dist/core/commands/base-command.d.ts +11 -0
  119. package/dist/core/commands/base-command.js +61 -0
  120. package/dist/core/commands/dependency-command.d.ts +5 -0
  121. package/dist/core/commands/dependency-command.js +16 -0
  122. package/dist/core/commands/modules-command.d.ts +7 -0
  123. package/dist/core/commands/modules-command.js +18 -0
  124. package/dist/core/commands/processes-command.d.ts +8 -0
  125. package/dist/core/commands/processes-command.js +27 -0
  126. package/dist/core/commands/resource-command.d.ts +24 -0
  127. package/dist/core/commands/resource-command.js +92 -0
  128. package/dist/core/commands/variables-command.d.ts +5 -0
  129. package/dist/core/commands/variables-command.js +16 -0
  130. package/dist/core/dependencies/env-dependencies-command.d.ts +19 -0
  131. package/dist/core/dependencies/env-dependencies-command.js +70 -0
  132. package/dist/core/dependencies/env-process-dependencies-command.d.ts +15 -0
  133. package/dist/core/dependencies/env-process-dependencies-command.js +78 -0
  134. package/dist/core/dependencies/javascript-env-dependencies.d.ts +8 -0
  135. package/dist/core/dependencies/javascript-env-dependencies.js +77 -0
  136. package/dist/core/dependencies/python-env-dependencies.d.ts +9 -0
  137. package/dist/core/dependencies/python-env-dependencies.js +91 -0
  138. package/dist/core/errors.d.ts +55 -0
  139. package/dist/core/errors.js +144 -0
  140. package/dist/core/executors/execution-task.d.ts +29 -0
  141. package/dist/core/executors/execution-task.js +139 -0
  142. package/dist/core/executors/javascript-execution-task.d.ts +13 -0
  143. package/dist/core/executors/javascript-execution-task.js +618 -0
  144. package/dist/core/executors/python/context.d.ts +2 -0
  145. package/dist/core/executors/python/context.js +3 -0
  146. package/dist/core/executors/python/datastore.d.ts +2 -0
  147. package/dist/core/executors/python/datastore.js +4 -0
  148. package/dist/core/executors/python-execution-task.d.ts +11 -0
  149. package/dist/core/executors/python-execution-task.js +173 -0
  150. package/dist/core/executors/source-code-sanitizer.d.ts +4 -0
  151. package/dist/core/executors/source-code-sanitizer.js +45 -0
  152. package/dist/core/resource-merger.d.ts +14 -0
  153. package/dist/core/resource-merger.js +155 -0
  154. package/dist/core/resource-pusher.d.ts +12 -0
  155. package/dist/core/resource-pusher.js +133 -0
  156. package/dist/core/resource-repository.d.ts +8 -0
  157. package/dist/core/resource-repository.js +2 -0
  158. package/dist/core/types.d.ts +290 -0
  159. package/dist/core/types.js +238 -0
  160. package/dist/core/utils/dependencies.d.ts +5 -0
  161. package/dist/core/utils/dependencies.js +82 -0
  162. package/dist/core/utils/variables.d.ts +4 -0
  163. package/dist/core/utils/variables.js +10 -0
  164. package/dist/hooks/init/auth.d.ts +3 -0
  165. package/dist/hooks/init/auth.js +28 -0
  166. package/dist/hooks/init/update.d.ts +3 -0
  167. package/dist/hooks/init/update.js +42 -0
  168. package/dist/index.d.ts +1 -0
  169. package/dist/index.js +4 -0
  170. package/dist/repositories/process.d.ts +36 -0
  171. package/dist/repositories/process.js +339 -0
  172. package/dist/repositories/programming-language-manifest.d.ts +17 -0
  173. package/dist/repositories/programming-language-manifest.js +95 -0
  174. package/dist/repositories/resource.d.ts +29 -0
  175. package/dist/repositories/resource.js +79 -0
  176. package/dist/repositories/script-library.d.ts +28 -0
  177. package/dist/repositories/script-library.js +164 -0
  178. package/dist/repositories/team.d.ts +23 -0
  179. package/dist/repositories/team.js +74 -0
  180. package/dist/repositories/variable.d.ts +26 -0
  181. package/dist/repositories/variable.js +174 -0
  182. package/dist/runtime/executor.js +87 -0
  183. package/dist/runtime/executor.py +81 -0
  184. package/dist/runtime/libs/node/fcode/index.js +1 -0
  185. package/dist/runtime/libs/python/fcode/__init__.py +75 -0
  186. package/dist/runtime/libs/python/fcode/context.py +98 -0
  187. package/dist/runtime/libs/python/fcode/datastore.py +35 -0
  188. package/dist/runtime/libs/python/fcode/schedule.py +45 -0
  189. package/dist/runtime/libs/python/fcode/storage.py +271 -0
  190. package/dist/runtime/libs/python/fcode/variables.py +102 -0
  191. package/dist/services/auth-service.d.ts +12 -0
  192. package/dist/services/auth-service.js +114 -0
  193. package/dist/services/credential-prompter.d.ts +6 -0
  194. package/dist/services/credential-prompter.js +60 -0
  195. package/dist/services/fcode-graphql-client.d.ts +45 -0
  196. package/dist/services/fcode-graphql-client.js +721 -0
  197. package/dist/services/http-server.d.ts +3 -0
  198. package/dist/services/http-server.js +17 -0
  199. package/dist/services/oauth-browser-service.d.ts +9 -0
  200. package/dist/services/oauth-browser-service.js +164 -0
  201. package/dist/services/process-parameters-sampler.d.ts +2 -0
  202. package/dist/services/process-parameters-sampler.js +41 -0
  203. package/dist/services/process-runner.d.ts +22 -0
  204. package/dist/services/process-runner.js +97 -0
  205. package/dist/services/resource-checker.d.ts +8 -0
  206. package/dist/services/resource-checker.js +82 -0
  207. package/dist/services/test-runner.d.ts +17 -0
  208. package/dist/services/test-runner.js +228 -0
  209. package/dist/utils/canonical-hash.d.ts +9 -0
  210. package/dist/utils/canonical-hash.js +30 -0
  211. package/dist/utils/cli/index.d.ts +14 -0
  212. package/dist/utils/cli/index.js +50 -0
  213. package/dist/utils/cli/screen.d.ts +2 -0
  214. package/dist/utils/cli/screen.js +25 -0
  215. package/dist/utils/cli/styled/table.d.ts +23 -0
  216. package/dist/utils/cli/styled/table.js +272 -0
  217. package/dist/utils/colorize-resource.d.ts +1 -0
  218. package/dist/utils/colorize-resource.js +7 -0
  219. package/dist/utils/env-utils.d.ts +2 -0
  220. package/dist/utils/env-utils.js +16 -0
  221. package/dist/utils/file-utils.d.ts +11 -0
  222. package/dist/utils/file-utils.js +33 -0
  223. package/dist/utils/filenamify.d.ts +4 -0
  224. package/dist/utils/filenamify.js +73 -0
  225. package/dist/utils/gitignore.d.ts +17 -0
  226. package/dist/utils/gitignore.js +60 -0
  227. package/dist/utils/promise.d.ts +4 -0
  228. package/dist/utils/promise.js +38 -0
  229. package/dist/utils/url-utils.d.ts +2 -0
  230. package/dist/utils/url-utils.js +10 -0
  231. package/dist/utils/variable-warnings.d.ts +8 -0
  232. package/dist/utils/variable-warnings.js +38 -0
  233. package/oclif.manifest.json +1783 -0
  234. package/package.json +129 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const color_1 = require("@oclif/color");
4
+ const node_child_process_1 = require("node:child_process");
5
+ const global_1 = require("../../config/global");
6
+ const settings_1 = require("../../config/settings");
7
+ const VERSION_CHECK_INTERVAL = 1000 * 60 * 60 * 6;
8
+ const updateNotifier = async function ({ config, id }) {
9
+ const globalConfig = new global_1.default();
10
+ const disableUpdateNotifier = process.env.FCODE_DISABLE_UPDATE_NOTIFIER === 'true' ||
11
+ (await globalConfig.getSetting(settings_1.SettingKeys.DISABLE_UPDATE_NOTIFIER)) === 'true';
12
+ if (disableUpdateNotifier) {
13
+ return;
14
+ }
15
+ const versionCheckTime = (await globalConfig.get('versionCheckTime')) || 0;
16
+ const now = Date.now();
17
+ if (now - versionCheckTime > VERSION_CHECK_INTERVAL || id === '--version') {
18
+ try {
19
+ const lastestVersion = (0, node_child_process_1.execSync)('npm show @factorialco/fcode-cli version', { stdio: 'pipe' }).toString().trim();
20
+ await globalConfig.set('versionCheckTime', now);
21
+ if (config.version !== lastestVersion) {
22
+ console.log(`
23
+ ${color_1.default.cyan(`__ __ _____ _
24
+ \\ \\ / / / ____| | |
25
+ \\ \\_/ /__ _ __ | | ___ __| | ___
26
+ \\ / _ \\ '_ \\| | / _ \\ / _\` |/ _ \\
27
+ | | __/ |_) | |___| (_) | (_| | __/
28
+ |_|\\___| .__/ \\_____\\___/ \\__,_|\\___|
29
+ | |
30
+ |_|`)}
31
+
32
+ Update available ${color_1.default.red(config.version)} → ${color_1.default.greenBright(lastestVersion)}
33
+ Run ${color_1.default.bold('`npm i -g @factorialco/fcode-cli`')} to update
34
+ `);
35
+ }
36
+ }
37
+ catch {
38
+ console.log(`⚠️ ${color_1.default.red(' There was an error while attempting to check for updates.')}\n`);
39
+ }
40
+ }
41
+ };
42
+ exports.default = updateNotifier;
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var core_1 = require("@oclif/core");
4
+ Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
@@ -0,0 +1,36 @@
1
+ import { Process, ResourceMetadata, VersionedProcess } from '../core/types';
2
+ import ResourceRepositoryBase from './resource';
3
+ declare class ProcessRepository extends ResourceRepositoryBase<Process> {
4
+ constructor();
5
+ protected buildResourcePath(process: Process, filename: string, version?: string): string;
6
+ protected resourceDirectoryName(process: Process): string;
7
+ protected getSourceCodeFileName(programmingLanguage: string): string;
8
+ findAll(): Promise<Array<Process>>;
9
+ private allFilesExist;
10
+ private mandatoryFilesExist;
11
+ ensureAllFilesExist(processSlug: string): void;
12
+ findSlugsNotAdded(): Promise<Array<string>>;
13
+ find(processSlug: string, version?: string): Promise<Process>;
14
+ private readMetadataFile;
15
+ private buildMetadata;
16
+ findParameters(processSlug: string): Promise<any>;
17
+ getLastFileModifiedDate(process: Process, filename: string): Promise<Date>;
18
+ protected getResourcePath(process: Process): string;
19
+ protected removeFiles(process: Process): Promise<void>;
20
+ protected resourceToMetadata(process: Process): ResourceMetadata;
21
+ metadataFromFiles(slug: string): Promise<ResourceMetadata>;
22
+ protected saveFiles(process: Process): Promise<void>;
23
+ private versionsDirectory;
24
+ private versionDirectory;
25
+ versionHasChanges(process: Process, version: VersionedProcess): Promise<boolean>;
26
+ getLocalVersionTags(process: Process): string[];
27
+ versionExistsLocally(process: Process, tag: string): boolean;
28
+ removeVersion(process: Process, tag: string): void;
29
+ saveVersion(process: Process, version: VersionedProcess): Promise<void>;
30
+ getVersions(process: Process): Promise<Array<VersionedProcess>>;
31
+ private dependenciesFile;
32
+ getProcessFullPath(processSlug: string, version?: string): Promise<string>;
33
+ private getProcessMetadata;
34
+ private processHash;
35
+ }
36
+ export default ProcessRepository;
@@ -0,0 +1,339 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs-extra");
4
+ const crypto = require("node:crypto");
5
+ const path = require("node:path");
6
+ const color_1 = require("@oclif/color");
7
+ const cli_1 = require("../utils/cli");
8
+ const errors_1 = require("../core/errors");
9
+ const types_1 = require("../core/types");
10
+ const process_parameters_sampler_1 = require("../services/process-parameters-sampler");
11
+ const filenamify_1 = require("../utils/filenamify");
12
+ const file_utils_1 = require("../utils/file-utils");
13
+ const resource_1 = require("./resource");
14
+ const resource_checker_1 = require("../services/resource-checker");
15
+ const dependencies_1 = require("../core/utils/dependencies");
16
+ const PROGRAMMING_LANGUAGE_DEPENDENCIES_FILE_NAME = {
17
+ JAVASCRIPT: 'package.json',
18
+ PYTHON: 'requirements.txt',
19
+ };
20
+ class ProcessRepository extends resource_1.default {
21
+ constructor() {
22
+ super({
23
+ name: 'processes',
24
+ });
25
+ }
26
+ buildResourcePath(process, filename, version) {
27
+ let directory = this.resourceDirectoryName(process);
28
+ if (version) {
29
+ directory = path.join(directory, 'versions', version);
30
+ }
31
+ return path.join(this._repositoryName, directory, filename);
32
+ }
33
+ resourceDirectoryName(process) {
34
+ return (0, filenamify_1.default)(process.slug);
35
+ }
36
+ getSourceCodeFileName(programmingLanguage) {
37
+ return programmingLanguage === 'PYTHON' ? 'main.py' : 'index.js';
38
+ }
39
+ async findAll() {
40
+ const { processes } = await this.workspaceConfig.getActiveTeam();
41
+ const existProcesses = await Object.keys(processes).reduce((promise, processSlug) => promise.then(async (existNames) => {
42
+ const exists = await this.exists(processSlug);
43
+ if (exists) {
44
+ return [...existNames, processSlug];
45
+ }
46
+ return existNames;
47
+ }), Promise.resolve([]));
48
+ const localProcesses = Promise.all(existProcesses.map((processSlug) => this.find(processSlug)));
49
+ return localProcesses;
50
+ }
51
+ allFilesExist(processSlug, version) {
52
+ const processDirectory = path.join(this._repositoryName, processSlug, version ? 'versions' : '', version || '');
53
+ const existsSourceCode = fs.pathExistsSync(path.join(processDirectory, 'index.js')) || fs.pathExistsSync(path.join(processDirectory, 'main.py'));
54
+ const existsReadme = fs.pathExistsSync(path.join(processDirectory, 'README.md'));
55
+ const existsParametersSchema = fs.pathExistsSync(path.join(processDirectory, 'parametersSchema.json'));
56
+ const existsMetadata = fs.pathExistsSync(path.join(processDirectory, 'metadata.json'));
57
+ return existsSourceCode && existsReadme && existsMetadata && existsParametersSchema;
58
+ }
59
+ mandatoryFilesExist(processSlug, version) {
60
+ const processDirectory = path.join(this._repositoryName, processSlug, version ? 'versions' : '', version || '');
61
+ const existsSourceCode = fs.pathExistsSync(path.join(processDirectory, 'index.js')) || fs.pathExistsSync(path.join(processDirectory, 'main.py'));
62
+ return existsSourceCode;
63
+ }
64
+ ensureAllFilesExist(processSlug) {
65
+ const processDirectory = path.join(this._repositoryName, processSlug);
66
+ const existsReadme = fs.pathExistsSync(path.join(processDirectory, 'README.md'));
67
+ const existsParametersSchema = fs.pathExistsSync(path.join(processDirectory, 'parametersSchema.json'));
68
+ const existsMetadata = fs.pathExistsSync(path.join(processDirectory, 'metadata.json'));
69
+ if (!existsReadme) {
70
+ cli_1.cli.log(color_1.default.green(`ℹ️ local process directory '${processSlug}' doesn't have a README.md file and will be created.`));
71
+ fs.writeFileSync(path.join(processDirectory, 'README.md'), '');
72
+ }
73
+ if (!existsParametersSchema) {
74
+ cli_1.cli.log(color_1.default.green(`ℹ️ local process directory '${processSlug}' doesn't have a parametersSchema.json file and will be created.`));
75
+ fs.writeFileSync(path.join(processDirectory, 'parametersSchema.json'), '{}');
76
+ }
77
+ if (!existsMetadata) {
78
+ cli_1.cli.log(color_1.default.green(`ℹ️ local process directory '${processSlug}' doesn't have a metadata.json file and will be created.`));
79
+ fs.writeFileSync(path.join(processDirectory, 'metadata.json'), JSON.stringify({ name: processSlug, tags: [] }, null, 2));
80
+ }
81
+ }
82
+ async findSlugsNotAdded() {
83
+ const slugsNotAdded = [];
84
+ for (const directory of fs.readdirSync(this._repositoryName)) {
85
+ if (!(await this.workspaceConfig.exists('processes', directory))) {
86
+ if (!this.validSlug(directory)) {
87
+ cli_1.cli.log(color_1.default.yellow(`\n⚠️ local process directory '${directory}' doesn't have a valid format and will be ignored. ${this.slugFormatMessage()}`));
88
+ }
89
+ else if (!this.mandatoryFilesExist(directory)) {
90
+ cli_1.cli.log(color_1.default.yellow(`\n⚠️ local process directory '${directory}' doesn't have all the required files and will be ignored.`));
91
+ }
92
+ else {
93
+ slugsNotAdded.push(directory);
94
+ }
95
+ }
96
+ }
97
+ return slugsNotAdded;
98
+ }
99
+ async find(processSlug, version) {
100
+ const processMetadata = await this.getProcessMetadata(processSlug);
101
+ if (!processMetadata) {
102
+ throw new errors_1.LocalProcessNotFound(new Error('Process not found on team metadata'), processSlug);
103
+ }
104
+ const readProcessFile = (filename) => fs.readFileSync(this.buildResourcePath(processMetadata, filename, version));
105
+ try {
106
+ const sourceCodeFile = await readProcessFile(this.getSourceCodeFileName(processMetadata.script.programmingLanguage));
107
+ const sourceCode = sourceCodeFile.toString();
108
+ let readme = '';
109
+ try {
110
+ readme = (await readProcessFile('README.md')).toString();
111
+ }
112
+ catch { }
113
+ const metadata = this.readMetadataFile(processMetadata, processSlug, version);
114
+ let parametersSchema = {};
115
+ try {
116
+ parametersSchema = fs.readJsonSync(this.buildResourcePath(processMetadata, 'parametersSchema.json', version));
117
+ }
118
+ catch { }
119
+ const dependenciesFile = this.dependenciesFile(processMetadata);
120
+ const isDependenciesFilePresent = fs.existsSync(dependenciesFile);
121
+ const manifest = isDependenciesFilePresent
122
+ ? { dependencies: (0, dependencies_1.dependenciesFromFile)(processMetadata.script.programmingLanguage, fs.readFileSync(dependenciesFile).toString()) }
123
+ : null;
124
+ return new types_1.Process(processMetadata.id, processMetadata.slug, { parametersSchema, programmingLanguage: processMetadata.script.programmingLanguage, sourceCode }, readme, manifest, { dependencies: { scopedToProcess: isDependenciesFilePresent } }, metadata, processMetadata.resolvingTeamSlug);
125
+ }
126
+ catch {
127
+ throw new Error(`Process ${processSlug} not found!`);
128
+ }
129
+ }
130
+ readMetadataFile(processMetadata, processSlug, version) {
131
+ try {
132
+ const raw = fs.readJsonSync(this.buildResourcePath(processMetadata, 'metadata.json', version));
133
+ return {
134
+ name: raw.name ?? processSlug,
135
+ description: raw.description,
136
+ tags: Array.isArray(raw.tags) ? raw.tags : [],
137
+ webhook: raw.webhook,
138
+ form: raw.form,
139
+ visibility: raw.visibility,
140
+ };
141
+ }
142
+ catch (error) {
143
+ if (error instanceof SyntaxError) {
144
+ cli_1.cli.log(color_1.default.yellow(`\n⚠️ local process directory '${processSlug}' doesn't have a valid metadata.json file.`));
145
+ }
146
+ return { name: processSlug, tags: [] };
147
+ }
148
+ }
149
+ buildMetadata(process) {
150
+ const metadata = { name: process.name, tags: process.tags ?? [] };
151
+ if (process.description !== undefined) {
152
+ metadata.description = process.description;
153
+ }
154
+ if (process.webhook !== undefined) {
155
+ metadata.webhook = process.webhook;
156
+ }
157
+ if (process.form !== undefined) {
158
+ metadata.form = process.form;
159
+ }
160
+ if (process.visibility !== undefined) {
161
+ metadata.visibility = process.visibility;
162
+ }
163
+ return metadata;
164
+ }
165
+ async findParameters(processSlug) {
166
+ const processMetadata = await this.getProcessMetadata(processSlug);
167
+ if (!processMetadata) {
168
+ throw new errors_1.LocalProcessNotFound(new Error('Process not found on team metadata'), processSlug);
169
+ }
170
+ let parameters = {};
171
+ try {
172
+ parameters = fs.readJsonSync(this.buildResourcePath(processMetadata, 'parameters.json'));
173
+ }
174
+ catch { }
175
+ return parameters;
176
+ }
177
+ async getLastFileModifiedDate(process, filename) {
178
+ return new Promise((resolve, reject) => {
179
+ fs.stat(this.buildResourcePath(process, filename), (error, stats) => {
180
+ if (error) {
181
+ reject(error);
182
+ }
183
+ else {
184
+ resolve(stats.mtime);
185
+ }
186
+ });
187
+ });
188
+ }
189
+ getResourcePath(process) {
190
+ throw new Error('Method not implemented.');
191
+ }
192
+ async removeFiles(process) {
193
+ await new Promise((resolve, reject) => {
194
+ try {
195
+ const processDirectory = path.join(this._repositoryName, this.resourceDirectoryName(process));
196
+ fs.removeSync(path.join(processDirectory, this.getSourceCodeFileName(process.script.programmingLanguage)));
197
+ fs.removeSync(path.join(processDirectory, 'README.md'));
198
+ fs.removeSync(path.join(processDirectory, 'metadata.json'));
199
+ fs.removeSync(path.join(processDirectory, 'parametersSchema.json'));
200
+ fs.removeSync(path.join(processDirectory, 'parameters.json'));
201
+ fs.removeSync(this.dependenciesFile(process));
202
+ const versionsDirectory = this.versionsDirectory(process);
203
+ if (fs.existsSync(versionsDirectory)) {
204
+ fs.removeSync(versionsDirectory);
205
+ }
206
+ this.removeDirectoryIfEmpty(processDirectory);
207
+ resolve(true);
208
+ }
209
+ catch (error) {
210
+ reject(error);
211
+ }
212
+ });
213
+ }
214
+ resourceToMetadata(process) {
215
+ return {
216
+ id: process.id,
217
+ slug: process.slug,
218
+ script: {
219
+ programmingLanguage: process.script.programmingLanguage,
220
+ },
221
+ ...(process.resolvingTeamSlug && { resolvingTeamSlug: process.resolvingTeamSlug }),
222
+ };
223
+ }
224
+ async metadataFromFiles(slug) {
225
+ const resourceDirectory = path.join(this._repositoryName, slug);
226
+ const programmingLanguage = fs.existsSync(path.join(resourceDirectory, 'index.js')) ? 'JAVASCRIPT' : 'PYTHON';
227
+ return {
228
+ slug,
229
+ script: {
230
+ programmingLanguage,
231
+ },
232
+ contentHash: '',
233
+ };
234
+ }
235
+ async saveFiles(process) {
236
+ const readOnly = Boolean(process.resolvingTeamSlug);
237
+ (0, file_utils_1.outputFileSyncIfChanged)(this.buildResourcePath(process, this.getSourceCodeFileName(process.script.programmingLanguage)), process.script.sourceCode || '', {
238
+ readOnly,
239
+ });
240
+ (0, file_utils_1.outputFileSyncIfChanged)(this.buildResourcePath(process, 'README.md'), process.readme || '', { readOnly });
241
+ (0, file_utils_1.outputFileSyncIfChanged)(this.buildResourcePath(process, 'metadata.json'), JSON.stringify(this.buildMetadata(process), null, 2), { readOnly });
242
+ (0, file_utils_1.outputFileSyncIfChanged)(this.buildResourcePath(process, 'parametersSchema.json'), JSON.stringify(process.script.parametersSchema, null, 2), { readOnly });
243
+ const parametersFilePath = this.buildResourcePath(process, 'parameters.json');
244
+ if (!fs.existsSync(parametersFilePath)) {
245
+ const parameters = (0, process_parameters_sampler_1.generateParametersSample)(process);
246
+ fs.outputFileSync(parametersFilePath, JSON.stringify(parameters, null, 2));
247
+ }
248
+ if (process.settings.dependencies.scopedToProcess) {
249
+ (0, file_utils_1.outputFileSyncIfChanged)(this.dependenciesFile(process), (0, dependencies_1.dependenciesToFile)(process.script.programmingLanguage, process.manifest?.dependencies), {
250
+ readOnly,
251
+ });
252
+ }
253
+ }
254
+ versionsDirectory(process) {
255
+ return path.join(this._repositoryName, this.resourceDirectoryName(process), 'versions');
256
+ }
257
+ versionDirectory(process, tag) {
258
+ return path.join(this.versionsDirectory(process), tag);
259
+ }
260
+ async versionHasChanges(process, version) {
261
+ const versionPath = this.versionDirectory(process, version.tag);
262
+ if (!fs.pathExistsSync(versionPath) || !this.allFilesExist(process.slug, version.tag)) {
263
+ return true;
264
+ }
265
+ const storedSourceCode = fs.readFileSync(path.join(versionPath, this.getSourceCodeFileName(process.script.programmingLanguage))).toString();
266
+ const storedReadme = fs.readFileSync(path.join(versionPath, 'README.md')).toString();
267
+ const storedParametersSchema = fs.readJsonSync(path.join(versionPath, 'parametersSchema.json'));
268
+ const storedVersion = new types_1.VersionedProcess(process.id, version.tag, { parametersSchema: storedParametersSchema, programmingLanguage: process.script.programmingLanguage, sourceCode: storedSourceCode }, storedReadme);
269
+ return !resource_checker_1.default.sameContent(storedVersion, version);
270
+ }
271
+ getLocalVersionTags(process) {
272
+ const versionsDir = this.versionsDirectory(process);
273
+ if (!fs.pathExistsSync(versionsDir))
274
+ return [];
275
+ return fs.readdirSync(versionsDir).filter((name) => this.validVersion(name));
276
+ }
277
+ versionExistsLocally(process, tag) {
278
+ return fs.pathExistsSync(this.versionDirectory(process, tag));
279
+ }
280
+ removeVersion(process, tag) {
281
+ fs.removeSync(this.versionDirectory(process, tag));
282
+ }
283
+ async saveVersion(process, version) {
284
+ const versionPath = this.versionDirectory(process, version.tag);
285
+ const sourceCodeFile = path.join(versionPath, this.getSourceCodeFileName(process.script.programmingLanguage));
286
+ const readmeFile = path.join(versionPath, 'README.md');
287
+ const parametersSchemaFile = path.join(versionPath, 'parametersSchema.json');
288
+ fs.outputFileSync(sourceCodeFile, version.script.sourceCode || '');
289
+ fs.outputFileSync(readmeFile, version.readme || '');
290
+ fs.writeJsonSync(parametersSchemaFile, version.script.parametersSchema, { spaces: 2 });
291
+ fs.chmodSync(sourceCodeFile, 0o444);
292
+ fs.chmodSync(readmeFile, 0o444);
293
+ fs.chmodSync(parametersSchemaFile, 0o444);
294
+ }
295
+ async getVersions(process) {
296
+ const versionsDirectory = this.versionsDirectory(process);
297
+ if (!fs.pathExistsSync(versionsDirectory)) {
298
+ return [];
299
+ }
300
+ const versions = [];
301
+ for (const version of fs.readdirSync(versionsDirectory)) {
302
+ if (!this.validVersion(version)) {
303
+ cli_1.cli.log(color_1.default.yellow(`\n⚠️ process version '${version}' doesn't have a valid format and will be ignored. ${this.versionFormatMessage()}`));
304
+ continue;
305
+ }
306
+ try {
307
+ const sourceCode = await fs
308
+ .readFileSync(path.join(versionsDirectory, version, this.getSourceCodeFileName(process.script.programmingLanguage)))
309
+ .toString();
310
+ const readme = await fs.readFileSync(path.join(versionsDirectory, version, 'README.md')).toString();
311
+ const parametersSchema = await fs.readJsonSync(path.join(versionsDirectory, version, 'parametersSchema.json'));
312
+ versions.push(new types_1.VersionedProcess(process.id, version, {
313
+ parametersSchema: parametersSchema,
314
+ programmingLanguage: process.script.programmingLanguage,
315
+ sourceCode: sourceCode,
316
+ }, readme));
317
+ }
318
+ catch {
319
+ cli_1.cli.log(color_1.default.yellow(`\n⚠️ local version directory '${version}' doesn't have valid files and will be ignored.`));
320
+ }
321
+ }
322
+ return versions;
323
+ }
324
+ dependenciesFile(process) {
325
+ return path.join(this._repositoryName, this.resourceDirectoryName(process), PROGRAMMING_LANGUAGE_DEPENDENCIES_FILE_NAME[process.script.programmingLanguage]);
326
+ }
327
+ async getProcessFullPath(processSlug, version) {
328
+ const process = await this.find(processSlug, version);
329
+ return this.buildResourcePath(process, this.getSourceCodeFileName(process.script.programmingLanguage), version);
330
+ }
331
+ async getProcessMetadata(processSlug) {
332
+ const { processes } = await this.workspaceConfig.getActiveTeam();
333
+ return Object.values(processes).find((process) => process.slug === processSlug || this.processHash(process.slug) === processSlug);
334
+ }
335
+ processHash(processSlug) {
336
+ return crypto.createHash('sha1').update(processSlug).digest('hex');
337
+ }
338
+ }
339
+ exports.default = ProcessRepository;
@@ -0,0 +1,17 @@
1
+ import { ResourceMetadata, ProgrammingLanguageManifest } from '../core/types';
2
+ import ResourceRepositoryBase from './resource';
3
+ declare class ProgrammingLanguageManifestRepository extends ResourceRepositoryBase<ProgrammingLanguageManifest> {
4
+ constructor();
5
+ find(slug: string): Promise<ProgrammingLanguageManifest>;
6
+ protected getSourceCodeFileName(programmingLanguageManifest: ProgrammingLanguageManifest): string;
7
+ protected getResourceDirectory(programmingLanguageManifest: ProgrammingLanguageManifest): string;
8
+ protected getResourcePath(programmingLanguageManifest: ProgrammingLanguageManifest): string;
9
+ protected removeFiles(programmingLanguageManifest: ProgrammingLanguageManifest): Promise<void>;
10
+ protected resourceToMetadata(programmingLanguageManifest: ProgrammingLanguageManifest): ResourceMetadata;
11
+ protected saveFiles(programmingLanguageManifest: ProgrammingLanguageManifest): Promise<void>;
12
+ metadataFromFiles(slug: string): Promise<ResourceMetadata>;
13
+ validSlug(slug: string): boolean;
14
+ slugFormatMessage(): string;
15
+ findSlugsNotAdded(): Promise<Array<string>>;
16
+ }
17
+ export default ProgrammingLanguageManifestRepository;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs-extra");
4
+ const path = require("node:path");
5
+ const errors_1 = require("../core/errors");
6
+ const types_1 = require("../core/types");
7
+ const resource_1 = require("./resource");
8
+ const dependencies_1 = require("../core/utils/dependencies");
9
+ const file_utils_1 = require("../utils/file-utils");
10
+ class ProgrammingLanguageManifestRepository extends resource_1.default {
11
+ constructor() {
12
+ super({
13
+ name: 'dependencies',
14
+ });
15
+ }
16
+ async find(slug) {
17
+ const { [this._repositoryName]: programmingLanguageManifests } = await this.workspaceConfig.getActiveTeam();
18
+ const programmingLanguageManifest = programmingLanguageManifests[slug];
19
+ if (!programmingLanguageManifest) {
20
+ throw new errors_1.LocalProgrammingLanguageManifestNotFound(new Error('Programming Language Manifest not found on team metadata'), slug);
21
+ }
22
+ const sourceCodeFileContent = fs.readFileSync(this.getResourcePath(programmingLanguageManifest));
23
+ try {
24
+ return new types_1.ProgrammingLanguageManifest(programmingLanguageManifest.id, programmingLanguageManifest.slug, programmingLanguageManifest.programmingLanguage, (0, dependencies_1.dependenciesFromFile)(programmingLanguageManifest.programmingLanguage, sourceCodeFileContent.toString()));
25
+ }
26
+ catch (error) {
27
+ throw new errors_1.LocalProgrammingLanguageManifestNotFound(error, slug);
28
+ }
29
+ }
30
+ getSourceCodeFileName(programmingLanguageManifest) {
31
+ return programmingLanguageManifest.programmingLanguage === 'JAVASCRIPT' ? 'package.json' : 'requirements.txt';
32
+ }
33
+ getResourceDirectory(programmingLanguageManifest) {
34
+ return this._repositoryName;
35
+ }
36
+ getResourcePath(programmingLanguageManifest) {
37
+ return path.join(this.getResourceDirectory(programmingLanguageManifest), this.getSourceCodeFileName(programmingLanguageManifest));
38
+ }
39
+ async removeFiles(programmingLanguageManifest) {
40
+ await new Promise((resolve, reject) => {
41
+ try {
42
+ fs.removeSync(this.getResourcePath(programmingLanguageManifest));
43
+ this.removeDirectoryIfEmpty(this.getResourceDirectory(programmingLanguageManifest));
44
+ resolve(true);
45
+ }
46
+ catch (error) {
47
+ reject(error);
48
+ }
49
+ });
50
+ }
51
+ resourceToMetadata(programmingLanguageManifest) {
52
+ return {
53
+ id: programmingLanguageManifest.id,
54
+ slug: programmingLanguageManifest.programmingLanguage,
55
+ programmingLanguage: programmingLanguageManifest.programmingLanguage,
56
+ };
57
+ }
58
+ async saveFiles(programmingLanguageManifest) {
59
+ (0, file_utils_1.outputFileSyncIfChanged)(this.getResourcePath(programmingLanguageManifest), (0, dependencies_1.dependenciesToFile)(programmingLanguageManifest.programmingLanguage, programmingLanguageManifest.dependencies));
60
+ }
61
+ async metadataFromFiles(slug) {
62
+ if (slug === 'JAVASCRIPT') {
63
+ return {
64
+ id: 'javascript',
65
+ programmingLanguage: 'JAVASCRIPT',
66
+ slug: 'JAVASCRIPT',
67
+ };
68
+ }
69
+ if (slug === 'PYTHON') {
70
+ return {
71
+ id: 'python',
72
+ programmingLanguage: 'PYTHON',
73
+ slug: 'PYTHON',
74
+ };
75
+ }
76
+ throw new Error('Invalid slug');
77
+ }
78
+ validSlug(slug) {
79
+ return slug === 'JAVASCRIPT' || slug === 'PYTHON';
80
+ }
81
+ slugFormatMessage() {
82
+ return 'Only JAVASCRIPT or PYTHON are allowed.';
83
+ }
84
+ async findSlugsNotAdded() {
85
+ const slugsNotAdded = [];
86
+ if (!(await this.workspaceConfig.exists('dependencies', 'JAVASCRIPT')) && fs.existsSync(path.join(this._repositoryName, 'package.json'))) {
87
+ slugsNotAdded.push('JAVASCRIPT');
88
+ }
89
+ if (!(await this.workspaceConfig.exists('dependencies', 'PYTHON')) && fs.existsSync(path.join(this._repositoryName, 'requirements.txt'))) {
90
+ slugsNotAdded.push('PYTHON');
91
+ }
92
+ return slugsNotAdded;
93
+ }
94
+ }
95
+ exports.default = ProgrammingLanguageManifestRepository;
@@ -0,0 +1,29 @@
1
+ import type { AddResourceOptions, Resource, ResourceMetadata, ResourceRepositoryOptions } from '../core/types';
2
+ import WorkspaceConfig from '../config/workspace';
3
+ import ResourceRepository from '../core/resource-repository';
4
+ export declare abstract class ResourceRepositoryBase<R extends Resource> implements ResourceRepository<R> {
5
+ protected workspaceConfig: WorkspaceConfig;
6
+ _repositoryName: string;
7
+ constructor({ name }: ResourceRepositoryOptions);
8
+ exists(slug: string): Promise<boolean>;
9
+ findAll(): Promise<Array<R>>;
10
+ remove(slug: string): Promise<void>;
11
+ save(resource: R): Promise<R>;
12
+ saveAll(resources: R[]): Promise<R[]>;
13
+ saveMetadata(resource: R): Promise<R>;
14
+ existsMetadata(slug: string): Promise<boolean>;
15
+ removeMetadata(slug: string): Promise<void>;
16
+ validSlug(slug: string): boolean;
17
+ slugFormatMessage(): string;
18
+ validVersion(tag: string): boolean;
19
+ versionFormatMessage(): string;
20
+ abstract find(slug: string): Promise<R>;
21
+ abstract findSlugsNotAdded(): Promise<Array<string>>;
22
+ abstract metadataFromFiles(slug: string, opts?: AddResourceOptions): Promise<ResourceMetadata>;
23
+ protected abstract getResourcePath(resource: R): string;
24
+ protected abstract removeFiles(resource: R): Promise<void>;
25
+ protected abstract resourceToMetadata(resource: R): ResourceMetadata;
26
+ protected abstract saveFiles(resource: R): Promise<void>;
27
+ protected removeDirectoryIfEmpty(directoryPath: string): void;
28
+ }
29
+ export default ResourceRepositoryBase;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResourceRepositoryBase = void 0;
4
+ const fs = require("fs-extra");
5
+ const workspace_1 = require("../config/workspace");
6
+ const promise_1 = require("../utils/promise");
7
+ class ResourceRepositoryBase {
8
+ constructor({ name }) {
9
+ this.workspaceConfig = new workspace_1.default();
10
+ this._repositoryName = name;
11
+ }
12
+ async exists(slug) {
13
+ try {
14
+ await this.find(slug);
15
+ return true;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ async findAll() {
22
+ const { [this._repositoryName]: resources } = await this.workspaceConfig.getActiveTeam();
23
+ // eslint-disable-next-line unicorn/no-array-reduce
24
+ const existResources = await Object.keys(resources).reduce((promise, slug) => promise.then(async (existIds) => {
25
+ const exists = await this.exists(slug);
26
+ if (exists) {
27
+ return [...existIds, slug];
28
+ }
29
+ return existIds;
30
+ }), Promise.resolve([]));
31
+ return Promise.all(existResources.map((slug) => this.find(slug)));
32
+ }
33
+ async remove(slug) {
34
+ const localResource = await this.find(slug);
35
+ await this.removeFiles(localResource);
36
+ await this.workspaceConfig.remove(this._repositoryName, slug);
37
+ }
38
+ async save(resource) {
39
+ await this.saveFiles(resource);
40
+ await this.saveMetadata(resource);
41
+ return resource;
42
+ }
43
+ async saveAll(resources) {
44
+ await (0, promise_1.chainedPromises)(resources, async (resource) => this.save(resource));
45
+ return resources;
46
+ }
47
+ async saveMetadata(resource) {
48
+ const team = await this.workspaceConfig.getActiveTeam();
49
+ const resourceMetadata = this.resourceToMetadata(resource);
50
+ resourceMetadata.contentHash = resource.contentHash;
51
+ await this.workspaceConfig.add(this._repositoryName, resourceMetadata);
52
+ return resource;
53
+ }
54
+ async existsMetadata(slug) {
55
+ return await this.workspaceConfig.exists(this._repositoryName, slug);
56
+ }
57
+ async removeMetadata(slug) {
58
+ await this.workspaceConfig.remove(this._repositoryName, slug);
59
+ }
60
+ validSlug(slug) {
61
+ return /^[a-z][a-z0-9-]*[a-z0-9]$/.test(slug);
62
+ }
63
+ slugFormatMessage() {
64
+ return 'It must start with a lowercase letter, followed by lowercase letters, numbers, or hyphens, and end with a lowercase letter or number.';
65
+ }
66
+ validVersion(tag) {
67
+ return /^[a-z0-9][a-z0-9.-]*$/.test(tag);
68
+ }
69
+ versionFormatMessage() {
70
+ return "It must start with a number or a letter in lowercase and then use numbers, letters, '-' or '.'";
71
+ }
72
+ removeDirectoryIfEmpty(directoryPath) {
73
+ if (fs.existsSync(directoryPath) && fs.readdirSync(directoryPath).length === 0) {
74
+ fs.removeSync(directoryPath);
75
+ }
76
+ }
77
+ }
78
+ exports.ResourceRepositoryBase = ResourceRepositoryBase;
79
+ exports.default = ResourceRepositoryBase;