@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,28 @@
1
+ import { ResourceMetadata, ScriptLibrary, VersionedScriptLibrary } from '../core/types';
2
+ import ResourceRepositoryBase from './resource';
3
+ declare class ScriptLibraryRepository extends ResourceRepositoryBase<ScriptLibrary> {
4
+ constructor();
5
+ find(slug: string): Promise<ScriptLibrary>;
6
+ private allFilesExist;
7
+ findSlugsNotAdded(): Promise<Array<string>>;
8
+ protected getSourceCodeFileName(scriptLibrary: ScriptLibrary): string;
9
+ protected getResourceDirectory(scriptLibrary: ScriptLibrary): string;
10
+ protected getResourcePath(scriptLibrary: ScriptLibrary): string;
11
+ protected resourceDirectoryName(scriptLibrary: ScriptLibrary): string;
12
+ protected removeFiles(scriptLibrary: ScriptLibrary): Promise<void>;
13
+ protected resourceToMetadata(scriptLibrary: ScriptLibrary): ResourceMetadata;
14
+ protected saveFiles(scriptLibrary: ScriptLibrary): Promise<void>;
15
+ private versionsDirectory;
16
+ private versionDirectory;
17
+ private versionPath;
18
+ versionHasChanges(scriptLibrary: ScriptLibrary, version: VersionedScriptLibrary): Promise<boolean>;
19
+ getLocalVersionTags(scriptLibrary: ScriptLibrary): string[];
20
+ versionExistsLocally(scriptLibrary: ScriptLibrary, tag: string): boolean;
21
+ removeVersion(scriptLibrary: ScriptLibrary, tag: string): void;
22
+ saveVersion(scriptLibrary: ScriptLibrary, version: VersionedScriptLibrary): Promise<void>;
23
+ metadataFromFiles(slug: string): Promise<ResourceMetadata>;
24
+ getVersions(scriptLibrary: ScriptLibrary): Promise<Array<VersionedScriptLibrary>>;
25
+ validSlug(slug: string): boolean;
26
+ slugFormatMessage(): string;
27
+ }
28
+ export default ScriptLibraryRepository;
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs-extra");
4
+ const path = require("node:path");
5
+ const color_1 = require("@oclif/color");
6
+ const cli_1 = require("../utils/cli");
7
+ const errors_1 = require("../core/errors");
8
+ const types_1 = require("../core/types");
9
+ const filenamify_1 = require("../utils/filenamify");
10
+ const file_utils_1 = require("../utils/file-utils");
11
+ const resource_1 = require("./resource");
12
+ const resource_checker_1 = require("../services/resource-checker");
13
+ class ScriptLibraryRepository extends resource_1.default {
14
+ constructor() {
15
+ super({
16
+ name: 'modules',
17
+ });
18
+ }
19
+ async find(slug) {
20
+ const { [this._repositoryName]: scriptLibraries } = await this.workspaceConfig.getActiveTeam();
21
+ const scriptLibraryMetadata = scriptLibraries[slug];
22
+ if (!scriptLibraryMetadata) {
23
+ throw new errors_1.LocalScriptLibraryNotFound(new Error('Script library not found on team metadata'), slug);
24
+ }
25
+ const sourceCodeFile = fs.readFileSync(this.getResourcePath(scriptLibraryMetadata));
26
+ try {
27
+ const sourceCode = sourceCodeFile.toString();
28
+ return new types_1.ScriptLibrary(scriptLibraryMetadata.id, scriptLibraryMetadata.name, sourceCode, scriptLibraryMetadata.programmingLanguage, scriptLibraryMetadata.resolvingTeamSlug);
29
+ }
30
+ catch (error) {
31
+ throw new errors_1.LocalScriptLibraryNotFound(error, slug);
32
+ }
33
+ }
34
+ allFilesExist(directory) {
35
+ const processDirectory = path.join(this._repositoryName, directory);
36
+ return fs.pathExistsSync(path.join(processDirectory, `${directory}.js`)) || fs.pathExistsSync(path.join(processDirectory, `${directory}.py`));
37
+ }
38
+ async findSlugsNotAdded() {
39
+ const slugsNotAdded = [];
40
+ for (const directory of fs.readdirSync(this._repositoryName)) {
41
+ if (!(await this.workspaceConfig.exists('modules', directory))) {
42
+ if (!this.validSlug(directory)) {
43
+ cli_1.default.log(color_1.default.yellow(`\n⚠️ local module directory '${directory}' doesn't have a valid format and will be ignored. ${this.slugFormatMessage()}`));
44
+ }
45
+ else if (!this.allFilesExist(directory)) {
46
+ cli_1.default.log(color_1.default.yellow(`\n⚠️ local module directory '${directory}' doesn't have all the required files and will be ignored.`));
47
+ }
48
+ else {
49
+ slugsNotAdded.push(directory);
50
+ }
51
+ }
52
+ }
53
+ return slugsNotAdded;
54
+ }
55
+ getSourceCodeFileName(scriptLibrary) {
56
+ return (0, filenamify_1.default)(scriptLibrary.name) + '.' + (scriptLibrary.programmingLanguage === 'PYTHON' ? `py` : `js`);
57
+ }
58
+ getResourceDirectory(scriptLibrary) {
59
+ return path.join(this._repositoryName, this.resourceDirectoryName(scriptLibrary));
60
+ }
61
+ getResourcePath(scriptLibrary) {
62
+ return path.join(this.getResourceDirectory(scriptLibrary), this.getSourceCodeFileName(scriptLibrary));
63
+ }
64
+ resourceDirectoryName(scriptLibrary) {
65
+ return (0, filenamify_1.default)(scriptLibrary.name);
66
+ }
67
+ async removeFiles(scriptLibrary) {
68
+ await new Promise((resolve, reject) => {
69
+ try {
70
+ fs.removeSync(this.getResourcePath(scriptLibrary));
71
+ this.removeDirectoryIfEmpty(this.getResourceDirectory(scriptLibrary));
72
+ resolve(true);
73
+ }
74
+ catch (error) {
75
+ reject(error);
76
+ }
77
+ });
78
+ }
79
+ resourceToMetadata(scriptLibrary) {
80
+ return {
81
+ id: scriptLibrary.id,
82
+ name: scriptLibrary.name,
83
+ slug: scriptLibrary.slug,
84
+ programmingLanguage: scriptLibrary.programmingLanguage,
85
+ ...(scriptLibrary.resolvingTeamSlug && { resolvingTeamSlug: scriptLibrary.resolvingTeamSlug }),
86
+ };
87
+ }
88
+ async saveFiles(scriptLibrary) {
89
+ (0, file_utils_1.outputFileSyncIfChanged)(this.getResourcePath(scriptLibrary), scriptLibrary.sourceCode || '', { readOnly: Boolean(scriptLibrary.resolvingTeamSlug) });
90
+ }
91
+ versionsDirectory(scriptLibrary) {
92
+ return path.join(this._repositoryName, this.resourceDirectoryName(scriptLibrary), 'versions');
93
+ }
94
+ versionDirectory(scriptLibrary, tag) {
95
+ return path.join(this.versionsDirectory(scriptLibrary), tag);
96
+ }
97
+ versionPath(scriptLibrary, tag) {
98
+ return path.join(this.versionDirectory(scriptLibrary, tag), this.getSourceCodeFileName(scriptLibrary));
99
+ }
100
+ async versionHasChanges(scriptLibrary, version) {
101
+ const versionPath = this.versionPath(scriptLibrary, version.tag);
102
+ if (!fs.pathExistsSync(versionPath)) {
103
+ return true;
104
+ }
105
+ const storedSourceCode = fs.readFileSync(versionPath).toString();
106
+ const storedVersion = new types_1.VersionedScriptLibrary(scriptLibrary.id, version.tag, storedSourceCode, scriptLibrary.programmingLanguage);
107
+ return !resource_checker_1.default.sameContent(storedVersion, version);
108
+ }
109
+ getLocalVersionTags(scriptLibrary) {
110
+ const versionsDir = this.versionsDirectory(scriptLibrary);
111
+ if (!fs.pathExistsSync(versionsDir))
112
+ return [];
113
+ return fs.readdirSync(versionsDir).filter((name) => this.validVersion(name));
114
+ }
115
+ versionExistsLocally(scriptLibrary, tag) {
116
+ return fs.pathExistsSync(this.versionDirectory(scriptLibrary, tag));
117
+ }
118
+ removeVersion(scriptLibrary, tag) {
119
+ fs.removeSync(this.versionDirectory(scriptLibrary, tag));
120
+ }
121
+ async saveVersion(scriptLibrary, version) {
122
+ const versionFilePath = path.join(this._repositoryName, this.resourceDirectoryName(scriptLibrary), 'versions', version.tag, this.getSourceCodeFileName(scriptLibrary));
123
+ fs.outputFileSync(versionFilePath, version.sourceCode || '');
124
+ fs.chmodSync(versionFilePath, 0o444);
125
+ }
126
+ async metadataFromFiles(slug) {
127
+ const resourceDirectory = path.join(this._repositoryName, slug);
128
+ const programmingLanguage = fs.existsSync(path.join(resourceDirectory, `${slug}.js`)) ? 'JAVASCRIPT' : 'PYTHON';
129
+ return {
130
+ name: slug,
131
+ slug: slug,
132
+ programmingLanguage,
133
+ contentHash: '',
134
+ };
135
+ }
136
+ async getVersions(scriptLibrary) {
137
+ const versionsDirectory = this.versionsDirectory(scriptLibrary);
138
+ if (!fs.pathExistsSync(versionsDirectory)) {
139
+ return [];
140
+ }
141
+ const versions = [];
142
+ for (const version of fs.readdirSync(versionsDirectory)) {
143
+ if (!this.validVersion(version)) {
144
+ cli_1.default.log(color_1.default.yellow(`\n⚠️ module version '${version}' doesn't have a valid format and will be ignored. ${this.versionFormatMessage()}`));
145
+ continue;
146
+ }
147
+ try {
148
+ const sourceCode = await fs.readFileSync(path.join(versionsDirectory, version, this.getSourceCodeFileName(scriptLibrary))).toString();
149
+ versions.push(new types_1.VersionedScriptLibrary(scriptLibrary.id, version, sourceCode, scriptLibrary.programmingLanguage));
150
+ }
151
+ catch {
152
+ cli_1.default.log(color_1.default.yellow(`\n⚠️ local version directory '${version}' doesn't have valid files and will be ignored.`));
153
+ }
154
+ }
155
+ return versions;
156
+ }
157
+ validSlug(slug) {
158
+ return /^[\w-.]*$/.test(slug);
159
+ }
160
+ slugFormatMessage() {
161
+ return 'Only letters, dashes and dots are allowed.';
162
+ }
163
+ }
164
+ exports.default = ScriptLibraryRepository;
@@ -0,0 +1,23 @@
1
+ import { RawTeamSettings, Team } from '../core/types';
2
+ import WorkspaceConfig from '../config/workspace';
3
+ /**
4
+ * Reads/writes the singleton team.json (timezone, error handler, inheritance) at the
5
+ * workspace root. Unlike collection resources this is not a ResourceRepositoryBase:
6
+ * there is exactly one team, so there is no slug-keyed collection to manage.
7
+ *
8
+ * team.json references the error-handler process by slug for portability; the cloud
9
+ * references it by id, so this repository resolves slug<->id against the tracked
10
+ * process metadata in .fcode/.
11
+ */
12
+ export default class TeamRepository {
13
+ protected workspaceConfig: WorkspaceConfig;
14
+ exists(): boolean;
15
+ find(): Promise<Team>;
16
+ save(team: Team): void;
17
+ /** Builds a Team from the cloud's raw settings, resolving the error-handler id to a slug. */
18
+ fromRaw(raw: RawTeamSettings): Promise<Team>;
19
+ resolveSlugToId(processSlug: string): Promise<string>;
20
+ resolveIdToSlug(processId: string): Promise<string>;
21
+ private parseErrorHandler;
22
+ private toFile;
23
+ }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs-extra");
4
+ const types_1 = require("../core/types");
5
+ const workspace_1 = require("../config/workspace");
6
+ const file_utils_1 = require("../utils/file-utils");
7
+ const TEAM_FILENAME = 'team.json';
8
+ /**
9
+ * Reads/writes the singleton team.json (timezone, error handler, inheritance) at the
10
+ * workspace root. Unlike collection resources this is not a ResourceRepositoryBase:
11
+ * there is exactly one team, so there is no slug-keyed collection to manage.
12
+ *
13
+ * team.json references the error-handler process by slug for portability; the cloud
14
+ * references it by id, so this repository resolves slug<->id against the tracked
15
+ * process metadata in .fcode/.
16
+ */
17
+ class TeamRepository {
18
+ constructor() {
19
+ this.workspaceConfig = new workspace_1.default();
20
+ }
21
+ exists() {
22
+ return fs.pathExistsSync(TEAM_FILENAME);
23
+ }
24
+ async find() {
25
+ const slug = await this.workspaceConfig.getActiveTeamSlug();
26
+ let raw = {};
27
+ try {
28
+ raw = fs.readJsonSync(TEAM_FILENAME) || {};
29
+ }
30
+ catch { }
31
+ const parentTeamSlugs = Array.isArray(raw.parentTeamSlugs) ? raw.parentTeamSlugs : [];
32
+ return new types_1.Team(slug, parentTeamSlugs, raw.zoneId, this.parseErrorHandler(raw.errorHandlerConfig));
33
+ }
34
+ save(team) {
35
+ (0, file_utils_1.outputFileSyncIfChanged)(TEAM_FILENAME, JSON.stringify(this.toFile(team), null, 2));
36
+ }
37
+ /** Builds a Team from the cloud's raw settings, resolving the error-handler id to a slug. */
38
+ async fromRaw(raw) {
39
+ let errorHandlerConfig;
40
+ if (raw.errorHandlerConfig?.processId) {
41
+ errorHandlerConfig = {
42
+ processSlug: await this.resolveIdToSlug(raw.errorHandlerConfig.processId),
43
+ tag: raw.errorHandlerConfig.tag ?? null,
44
+ };
45
+ }
46
+ return new types_1.Team(raw.slug, raw.parentTeamSlugs ?? [], raw.zoneId, errorHandlerConfig);
47
+ }
48
+ async resolveSlugToId(processSlug) {
49
+ const { processes } = await this.workspaceConfig.getActiveTeam();
50
+ return processes[processSlug]?.id ?? processSlug;
51
+ }
52
+ async resolveIdToSlug(processId) {
53
+ const { processes } = await this.workspaceConfig.getActiveTeam();
54
+ const match = Object.values(processes).find((process) => process.id === processId);
55
+ return match?.slug ?? processId;
56
+ }
57
+ parseErrorHandler(raw) {
58
+ if (!raw || !raw.processSlug) {
59
+ return undefined;
60
+ }
61
+ return { processSlug: raw.processSlug, tag: raw.tag ?? null };
62
+ }
63
+ toFile(team) {
64
+ const file = { parentTeamSlugs: team.parentTeamSlugs ?? [] };
65
+ if (team.zoneId !== undefined) {
66
+ file.zoneId = team.zoneId;
67
+ }
68
+ if (team.errorHandlerConfig !== undefined) {
69
+ file.errorHandlerConfig = team.errorHandlerConfig;
70
+ }
71
+ return file;
72
+ }
73
+ }
74
+ exports.default = TeamRepository;
@@ -0,0 +1,26 @@
1
+ import { AddResourceOptions, ResourceMetadata, Variable } from '../core/types';
2
+ import ResourceRepositoryBase from './resource';
3
+ export declare const DEFAULT_SENSITIVE_VALUE = "********";
4
+ declare class VariableRepository extends ResourceRepositoryBase<Variable> {
5
+ private filename;
6
+ private localFilename;
7
+ private filenameInitPromise;
8
+ constructor();
9
+ private ensureFilenamesInitialized;
10
+ findAll(): Promise<Variable[]>;
11
+ findAllForExecution(): Promise<Variable[]>;
12
+ find(slug: string): Promise<Variable>;
13
+ findSlugsNotAdded(): Promise<Array<string>>;
14
+ protected getResourcePath(_resource: Variable): string;
15
+ protected removeFiles(variable: Variable): Promise<void>;
16
+ protected resourceToMetadata(variable: Variable): ResourceMetadata;
17
+ protected saveFiles(variable: Variable): Promise<void>;
18
+ metadataFromFiles(slug: string, opts: AddResourceOptions): Promise<ResourceMetadata>;
19
+ private readVariablesMeta;
20
+ private writeVariablesMeta;
21
+ private filePath;
22
+ private readVariablesFromFile;
23
+ private valueToSave;
24
+ private writeRawVariables;
25
+ }
26
+ export default VariableRepository;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_SENSITIVE_VALUE = void 0;
4
+ const dotenv_1 = require("dotenv");
5
+ const fs = require("fs-extra");
6
+ const path = require("node:path");
7
+ const types_1 = require("../core/types");
8
+ const resource_1 = require("./resource");
9
+ const errors_1 = require("../core/errors");
10
+ const global_1 = require("../config/global");
11
+ const settings_1 = require("../config/settings");
12
+ const file_utils_1 = require("../utils/file-utils");
13
+ const env_utils_1 = require("../utils/env-utils");
14
+ exports.DEFAULT_SENSITIVE_VALUE = '********';
15
+ const VARIABLES_META_FILENAME = 'variables.meta.json';
16
+ class VariableRepository extends resource_1.default {
17
+ constructor() {
18
+ super({
19
+ name: 'variables',
20
+ });
21
+ this.filename = null;
22
+ this.localFilename = null;
23
+ this.filenameInitPromise = null;
24
+ }
25
+ async ensureFilenamesInitialized() {
26
+ if (this.filenameInitPromise) {
27
+ return this.filenameInitPromise;
28
+ }
29
+ this.filenameInitPromise = (async () => {
30
+ const globalConfig = new global_1.default();
31
+ this.filename = await globalConfig.getSetting(settings_1.SettingKeys.VARIABLES_FILE_NAME);
32
+ this.localFilename = await globalConfig.getSetting(settings_1.SettingKeys.LOCAL_VARIABLES_FILE_NAME);
33
+ })();
34
+ return this.filenameInitPromise;
35
+ }
36
+ async findAll() {
37
+ await this.ensureFilenamesInitialized();
38
+ const rawVariables = this.readVariablesFromFile();
39
+ const localOverrideKeys = new Set(Object.keys(this.readVariablesFromFile(true)));
40
+ const meta = this.readVariablesMeta();
41
+ const variables = [];
42
+ const { variables: localVariables } = await this.workspaceConfig.getActiveTeam();
43
+ for (const localVariableKey of Object.keys(localVariables)) {
44
+ const localVariable = localVariables[localVariableKey];
45
+ const isSensitive = meta[localVariable.key]?.isSensitive ?? false;
46
+ const variable = types_1.Variable.validate(new types_1.Variable(localVariable.id, localVariable.key, rawVariables[localVariable.key], isSensitive));
47
+ variable.overriddenLocally = localOverrideKeys.has(localVariable.key);
48
+ variables.push(variable);
49
+ }
50
+ return variables;
51
+ }
52
+ async findAllForExecution() {
53
+ await this.ensureFilenamesInitialized();
54
+ const rawVariables = this.readVariablesFromFile();
55
+ const localRawVariables = this.readVariablesFromFile(true);
56
+ const meta = this.readVariablesMeta();
57
+ const variables = [];
58
+ const { variables: localVariables } = await this.workspaceConfig.getActiveTeam();
59
+ for (const localVariableKey of Object.keys(localVariables)) {
60
+ const localVariable = localVariables[localVariableKey];
61
+ const value = localRawVariables[localVariable.key] || rawVariables[localVariable.key];
62
+ const isSensitive = meta[localVariable.key]?.isSensitive ?? false;
63
+ variables.push(types_1.Variable.validate(new types_1.Variable(localVariable.id, localVariable.key, value, isSensitive)));
64
+ }
65
+ return variables;
66
+ }
67
+ async find(slug) {
68
+ let variables = await this.findAll();
69
+ variables = variables.filter((v) => v.key === slug);
70
+ if (variables.length > 0) {
71
+ return variables[0];
72
+ }
73
+ throw new errors_1.LocalVariableNotFound(new Error('Variable not found on team metadata'), slug);
74
+ }
75
+ async findSlugsNotAdded() {
76
+ await this.ensureFilenamesInitialized();
77
+ const { variables: localVariables } = await this.workspaceConfig.getActiveTeam();
78
+ const slugsNotAdded = [];
79
+ for (const [key, _value] of Object.entries(this.readVariablesFromFile())) {
80
+ if (!localVariables[key]) {
81
+ slugsNotAdded.push(key);
82
+ }
83
+ }
84
+ return slugsNotAdded;
85
+ }
86
+ getResourcePath(_resource) {
87
+ throw new Error('Method not implemented.');
88
+ }
89
+ async removeFiles(variable) {
90
+ await this.ensureFilenamesInitialized();
91
+ let rawVariables = this.readVariablesFromFile();
92
+ delete rawVariables[variable.key];
93
+ this.writeRawVariables(rawVariables);
94
+ const meta = this.readVariablesMeta();
95
+ delete meta[variable.key];
96
+ this.writeVariablesMeta(meta);
97
+ }
98
+ resourceToMetadata(variable) {
99
+ return {
100
+ id: variable.id,
101
+ slug: variable.slug,
102
+ key: variable.key,
103
+ };
104
+ }
105
+ async saveFiles(variable) {
106
+ await this.ensureFilenamesInitialized();
107
+ let rawVariables = this.readVariablesFromFile();
108
+ rawVariables = Object.assign(rawVariables, { [variable.key]: this.valueToSave(variable) });
109
+ this.writeRawVariables(rawVariables);
110
+ const meta = this.readVariablesMeta();
111
+ meta[variable.key] = { isSensitive: variable.isSensitive };
112
+ this.writeVariablesMeta(meta);
113
+ }
114
+ async metadataFromFiles(slug, opts) {
115
+ const meta = this.readVariablesMeta();
116
+ const isSensitive = opts.variableSensitive || meta[slug]?.isSensitive || false;
117
+ meta[slug] = { isSensitive };
118
+ this.writeVariablesMeta(meta);
119
+ return {
120
+ slug,
121
+ key: slug,
122
+ contentHash: '',
123
+ };
124
+ }
125
+ readVariablesMeta() {
126
+ try {
127
+ return fs.readJsonSync(VARIABLES_META_FILENAME) || {};
128
+ }
129
+ catch {
130
+ return {};
131
+ }
132
+ }
133
+ writeVariablesMeta(meta) {
134
+ const sorted = Object.keys(meta)
135
+ .sort()
136
+ .reduce((acc, key) => {
137
+ acc[key] = meta[key];
138
+ return acc;
139
+ }, {});
140
+ (0, file_utils_1.outputFileSyncIfChanged)(VARIABLES_META_FILENAME, JSON.stringify(sorted, null, 2));
141
+ }
142
+ filePath(useLocalVersion = false) {
143
+ if (!this.filename || !this.localFilename) {
144
+ throw new Error('Filenames not initialized. Call ensureFilenamesInitialized() first.');
145
+ }
146
+ return path.join(useLocalVersion ? this.localFilename : this.filename);
147
+ }
148
+ readVariablesFromFile(useLocalVersion = false) {
149
+ try {
150
+ const result = (0, dotenv_1.parse)(fs.readFileSync(this.filePath(useLocalVersion), 'utf8')) || {};
151
+ for (const [key, value] of Object.entries(result)) {
152
+ result[key] = (0, env_utils_1.unescapeEnvValue)(value);
153
+ }
154
+ return result;
155
+ }
156
+ catch {
157
+ return {};
158
+ }
159
+ }
160
+ valueToSave(variable) {
161
+ if (!variable.value && variable.isSensitive) {
162
+ return exports.DEFAULT_SENSITIVE_VALUE;
163
+ }
164
+ return variable.value;
165
+ }
166
+ writeRawVariables(rawVariables) {
167
+ const envContent = Object.entries(rawVariables)
168
+ .sort((a, b) => a[0].localeCompare(b[0]))
169
+ .map(([key, value]) => `${key}=${(0, env_utils_1.escapeEnvValue)(value)}`)
170
+ .join('\n');
171
+ (0, file_utils_1.outputFileSyncIfChanged)(this.filePath(), envContent);
172
+ }
173
+ }
174
+ exports.default = VariableRepository;
@@ -0,0 +1,87 @@
1
+ const fs = require('node:fs')
2
+ const path = require('node:path')
3
+ const { execSync } = require('node:child_process')
4
+ const os = require('node:os')
5
+
6
+ const YC_COMMAND = process.env.YC_COMMAND ?? "fcode"
7
+
8
+ const file = process.argv[2]
9
+ if (!fs.existsSync(file)) {
10
+ console.error('File not found: ' + file)
11
+ process.exit(1)
12
+ }
13
+
14
+ function getVersion(relativePath) {
15
+ const parts = relativePath.split(path.sep)
16
+ if (parts.length == 5 && parts[2] == 'versions') {
17
+ return parts[3]
18
+ }
19
+ return null
20
+ }
21
+
22
+ const absolutePath = path.resolve(file)
23
+ if (!absolutePath.startsWith(process.cwd() + path.sep)) {
24
+ console.error('File outside of current directory: ' + file)
25
+ process.exit(1)
26
+ }
27
+ const relativePath = path.relative(process.cwd(), absolutePath)
28
+
29
+ if (!relativePath.endsWith('.js') || !relativePath.startsWith('processes' + path.sep)) {
30
+ console.error('You can only debug JavaScript processes, file not valid: ' + absolutePath)
31
+ process.exit(1)
32
+ }
33
+
34
+ let mainFilePath = ''
35
+ let dependenciesPath = ''
36
+ try {
37
+ version = getVersion(relativePath)
38
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'fcode-'))
39
+ const command = [YC_COMMAND, 'pre-debug', absolutePath, '-t', tempDir]
40
+ if (version) {
41
+ command.push('-v')
42
+ command.push(version)
43
+ }
44
+ console.log('Running command: ' + command.join(' '))
45
+
46
+ try {
47
+ execSync(command.join(' '), { encoding: 'utf-8', stdio: 'inherit' })
48
+ } catch (error) {
49
+ console.error('Command finished with exit code: ' + error.status)
50
+ process.exit(1)
51
+ }
52
+
53
+ const variablesFile = path.join(tempDir, 'METADATA')
54
+ if (!fs.existsSync(variablesFile)) {
55
+ console.error('Temporal directory not found')
56
+ process.exit(1)
57
+ }
58
+
59
+ const fileContent = fs.readFileSync(variablesFile, 'utf-8')
60
+ const lines = fileContent.split('\n')
61
+
62
+ for (const line of lines) {
63
+ if (line.includes('FCODE_EXECUTION_FILE')) {
64
+ mainFilePath = line.split('=')[1].trim()
65
+ }
66
+ if (line.includes('FCODE_DEPENDENCIES_PATH')) {
67
+ dependenciesPath = line.split('=')[1].trim()
68
+ }
69
+ }
70
+
71
+ if (!mainFilePath || !dependenciesPath) {
72
+ console.error('Failed creating process temporal files')
73
+ process.exit(1)
74
+ }
75
+ } catch (error) {
76
+ console.error('Error running command')
77
+ console.error(error)
78
+ process.exit(1)
79
+ }
80
+
81
+ const fileName = path.basename(mainFilePath).replace('.js', '')
82
+ const executionDir = path.dirname(path.resolve(mainFilePath))
83
+
84
+ const newPaths = [path.join(path.dirname(path.resolve(__filename)), 'libs', 'node'), path.join(dependenciesPath, 'node_modules'), process.cwd()]
85
+
86
+ process.env.NODE_PATH = [process.env.NODE_PATH, ...newPaths].join(':')
87
+ require(path.join(executionDir, fileName))
@@ -0,0 +1,81 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+ import tempfile
5
+
6
+
7
+ YC_COMMAND = os.environ.get("YC_COMMAND", "fcode")
8
+ file = sys.argv[1]
9
+ if not os.path.exists(file):
10
+ print("File not found: " + file)
11
+ exit(1)
12
+
13
+
14
+ def get_version(file):
15
+ parts = file.split(os.sep)
16
+ if len(parts) == 5 and parts[2] == "versions":
17
+ return parts[3]
18
+ return None
19
+
20
+
21
+ file = os.path.abspath(file)
22
+ if not file.startswith(os.getcwd() + os.sep):
23
+ print("File outside of current directory: " + file)
24
+ exit(1)
25
+ relative_file = file.replace(os.getcwd() + os.sep, "")
26
+ if not file.endswith(".py") or not relative_file.startswith("processes" + os.sep):
27
+ print("You can only debug python processes, file not valid: " + file)
28
+ exit(1)
29
+
30
+ main_file_path = ""
31
+ try:
32
+ version = get_version(file)
33
+ tempDir = tempfile.TemporaryDirectory()
34
+ command = [YC_COMMAND, "pre-debug", file, "-t", tempDir.name]
35
+ if version != None:
36
+ command.append("-v")
37
+ command.append(version)
38
+ print("Running command: " + " ".join(command))
39
+ result = subprocess.run(" ".join(command), shell=True, encoding="utf-8")
40
+ if result.returncode != 0:
41
+ print("Command finished with exit code: " + str(result.returncode))
42
+ exit(1)
43
+ variables_file = os.path.join(tempDir.name, "METADATA")
44
+ if not os.path.exists(variables_file):
45
+ print("Temporal directory not found")
46
+ exit(1)
47
+ with open(variables_file, "r") as f:
48
+ for line in f:
49
+ if "FCODE_EXECUTION_FILE" in line:
50
+ main_file_path = line.split("=")[1].strip()
51
+ if "FCODE_DEPENDENCIES_PATH" in line:
52
+ dependencies_path = line.split("=")[1].strip()
53
+ if "FCODE_TMP_PATH" in line:
54
+ os.environ["FCODE_RUNTIME_METADATA_PATH"] = os.path.join(
55
+ line.split("=")[1].strip(), "initialize_params.py"
56
+ )
57
+ if len(main_file_path) == 0 or len(dependencies_path) == 0:
58
+ print("Failed creating process temporal files")
59
+ exit(1)
60
+ except Exception as e:
61
+ print("Error running command")
62
+ print(e)
63
+ exit(1)
64
+
65
+ file_name = os.path.basename(main_file_path).replace(".py", "")
66
+ execution_dir = os.path.dirname(os.path.realpath(main_file_path))
67
+ tmp_dir_name = os.path.basename(execution_dir)
68
+ tmp_dir_parent = os.path.dirname(execution_dir)
69
+ library_path = os.path.join(
70
+ os.path.dirname(os.path.realpath(__file__)), "libs", "python"
71
+ )
72
+ sys.path.append(library_path)
73
+ sys.path.append(tmp_dir_parent)
74
+ sys.path.append(dependencies_path)
75
+ sys.path.append(os.getcwd())
76
+ print("## library_path: " + library_path)
77
+ print("## dependencies_path: " + dependencies_path)
78
+ print("## tmp_dir_parent: " + tmp_dir_parent)
79
+ print("## os.getcwd(): " + os.getcwd())
80
+ print("## importing: " + tmp_dir_name + "." + file_name)
81
+ __import__(tmp_dir_name + "." + file_name, fromlist=[tmp_dir_name])
@@ -0,0 +1 @@
1
+ module.exports = { fcode }