farseer-cli 1.0.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 (120) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +741 -0
  3. package/dist/commands/app.d.ts +2 -0
  4. package/dist/commands/app.js +349 -0
  5. package/dist/commands/app.js.map +7 -0
  6. package/dist/commands/apps.d.ts +2 -0
  7. package/dist/commands/apps.js +111 -0
  8. package/dist/commands/apps.js.map +7 -0
  9. package/dist/commands/checkout.d.ts +2 -0
  10. package/dist/commands/checkout.js +166 -0
  11. package/dist/commands/checkout.js.map +7 -0
  12. package/dist/commands/config.d.ts +2 -0
  13. package/dist/commands/config.js +139 -0
  14. package/dist/commands/config.js.map +7 -0
  15. package/dist/commands/diff.d.ts +2 -0
  16. package/dist/commands/diff.js +183 -0
  17. package/dist/commands/diff.js.map +7 -0
  18. package/dist/commands/files.js +99 -0
  19. package/dist/commands/files.js.map +7 -0
  20. package/dist/commands/install.d.ts +2 -0
  21. package/dist/commands/install.js +79 -0
  22. package/dist/commands/install.js.map +7 -0
  23. package/dist/commands/list.d.ts +2 -0
  24. package/dist/commands/list.js +92 -0
  25. package/dist/commands/list.js.map +7 -0
  26. package/dist/commands/login.d.ts +2 -0
  27. package/dist/commands/login.js +134 -0
  28. package/dist/commands/login.js.map +7 -0
  29. package/dist/commands/logout.d.ts +2 -0
  30. package/dist/commands/logout.js +59 -0
  31. package/dist/commands/logout.js.map +7 -0
  32. package/dist/commands/mcp-server.d.ts +8 -0
  33. package/dist/commands/mcp-server.js +41 -0
  34. package/dist/commands/mcp-server.js.map +7 -0
  35. package/dist/commands/model.d.ts +2 -0
  36. package/dist/commands/model.js +189 -0
  37. package/dist/commands/model.js.map +7 -0
  38. package/dist/commands/pull.d.ts +2 -0
  39. package/dist/commands/pull.js +287 -0
  40. package/dist/commands/pull.js.map +7 -0
  41. package/dist/commands/push.d.ts +2 -0
  42. package/dist/commands/push.js +251 -0
  43. package/dist/commands/push.js.map +7 -0
  44. package/dist/commands/run.d.ts +2 -0
  45. package/dist/commands/run.js +246 -0
  46. package/dist/commands/run.js.map +7 -0
  47. package/dist/commands/setup.d.ts +2 -0
  48. package/dist/commands/setup.js +137 -0
  49. package/dist/commands/status.d.ts +2 -0
  50. package/dist/commands/status.js +145 -0
  51. package/dist/commands/status.js.map +7 -0
  52. package/dist/commands/unsetup.d.ts +2 -0
  53. package/dist/commands/unsetup.js +122 -0
  54. package/dist/commands/whoami.d.ts +2 -0
  55. package/dist/commands/whoami.js +63 -0
  56. package/dist/commands/whoami.js.map +7 -0
  57. package/dist/index.d.ts +2 -0
  58. package/dist/index.js +135 -0
  59. package/dist/index.js.map +7 -0
  60. package/dist/mcp/index.d.ts +7 -0
  61. package/dist/mcp/index.js +35 -0
  62. package/dist/mcp/index.js.map +7 -0
  63. package/dist/mcp/prompts/workflows.d.ts +7 -0
  64. package/dist/mcp/prompts/workflows.js +374 -0
  65. package/dist/mcp/prompts/workflows.js.map +7 -0
  66. package/dist/mcp/resources/documentation.d.ts +8 -0
  67. package/dist/mcp/resources/documentation.js +167 -0
  68. package/dist/mcp/resources/documentation.js.map +7 -0
  69. package/dist/mcp/server.d.ts +7 -0
  70. package/dist/mcp/server.js +49 -0
  71. package/dist/mcp/server.js.map +7 -0
  72. package/dist/mcp/tools/appTools.d.ts +7 -0
  73. package/dist/mcp/tools/appTools.js +377 -0
  74. package/dist/mcp/tools/appTools.js.map +7 -0
  75. package/dist/mcp/tools/authTools.d.ts +7 -0
  76. package/dist/mcp/tools/authTools.js +158 -0
  77. package/dist/mcp/tools/authTools.js.map +7 -0
  78. package/dist/mcp/tools/modelTools.d.ts +7 -0
  79. package/dist/mcp/tools/modelTools.js +331 -0
  80. package/dist/mcp/tools/modelTools.js.map +7 -0
  81. package/dist/mcp/tools/runTools.d.ts +7 -0
  82. package/dist/mcp/tools/runTools.js +231 -0
  83. package/dist/mcp/tools/runTools.js.map +7 -0
  84. package/dist/mcp/tools/syncTools.d.ts +7 -0
  85. package/dist/mcp/tools/syncTools.js +382 -0
  86. package/dist/mcp/tools/syncTools.js.map +7 -0
  87. package/dist/mcp/utils/helpers.d.ts +69 -0
  88. package/dist/mcp/utils/helpers.js +113 -0
  89. package/dist/mcp/utils/helpers.js.map +7 -0
  90. package/dist/services/appSyncService.d.ts +75 -0
  91. package/dist/services/appSyncService.js +370 -0
  92. package/dist/services/appSyncService.js.map +7 -0
  93. package/dist/services/configService.d.ts +39 -0
  94. package/dist/services/configService.js +196 -0
  95. package/dist/services/configService.js.map +7 -0
  96. package/dist/services/farseerApi.d.ts +166 -0
  97. package/dist/services/farseerApi.js +378 -0
  98. package/dist/services/farseerApi.js.map +7 -0
  99. package/dist/services/farseerFactory.d.ts +88 -0
  100. package/dist/services/farseerFactory.js +179 -0
  101. package/dist/services/farseerFactory.js.map +7 -0
  102. package/dist/services/farseerService.d.ts +96 -0
  103. package/dist/services/farseerService.js +614 -0
  104. package/dist/services/farseerService.js.map +7 -0
  105. package/dist/services/gitService.d.ts +31 -0
  106. package/dist/services/gitService.js +134 -0
  107. package/dist/services/gitService.js.map +7 -0
  108. package/dist/services/syncService.d.ts +44 -0
  109. package/dist/services/syncService.js +320 -0
  110. package/dist/services/syncService.js.map +7 -0
  111. package/dist/utils/constants.d.ts +7 -0
  112. package/dist/utils/constants.js +46 -0
  113. package/dist/utils/constants.js.map +7 -0
  114. package/dist/utils/helpers.d.ts +69 -0
  115. package/dist/utils/helpers.js +413 -0
  116. package/dist/utils/helpers.js.map +7 -0
  117. package/dist/utils/logger.d.ts +14 -0
  118. package/dist/utils/logger.js +76 -0
  119. package/dist/utils/logger.js.map +7 -0
  120. package/package.json +62 -0
@@ -0,0 +1,251 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var push_exports = {};
29
+ __export(push_exports, {
30
+ registerPushCommand: () => registerPushCommand
31
+ });
32
+ module.exports = __toCommonJS(push_exports);
33
+ var import_chalk = __toESM(require("chalk"));
34
+ var import_inquirer = __toESM(require("inquirer"));
35
+ var import_logger = require("../utils/logger");
36
+ var import_farseerFactory = require("../services/farseerFactory");
37
+ var import_syncService = require("../services/syncService");
38
+ var import_appSyncService = require("../services/appSyncService");
39
+ var import_gitService = require("../services/gitService");
40
+ var import_helpers = require("../utils/helpers");
41
+ var import_constants = require("../utils/constants");
42
+ var fs = __toESM(require("fs"));
43
+ function registerPushCommand(program) {
44
+ program.command("push [arg1] [arg2]").description("Push local files to Farseer instance\n\nUsage: push <org> <tenant> OR push <tenant> (if org is known)").option("--git", "Enable git operations (commit & push) - internal use only").option("-m, --message <message>", "Commit message (required when using --git)").option("--force", "Force push even if remote has changes").action(async (arg1, arg2, options) => {
45
+ const { organisation, tenant } = (0, import_helpers.resolveTenantWithOrgMapping)(arg1, arg2);
46
+ const clientResult = await (0, import_farseerFactory.getFarseerClientWithFallback)(organisation, tenant);
47
+ if (!clientResult) {
48
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
49
+ process.exit(1);
50
+ }
51
+ const filesDir = (0, import_helpers.getTenantFilesDir)(tenant);
52
+ if (!fs.existsSync(filesDir)) {
53
+ import_logger.logger.error(`Local folder not found: apps/${tenant}/files/`);
54
+ import_logger.logger.dim('Run "farseer pull <tenant>" first to initialize the folder.');
55
+ process.exit(1);
56
+ }
57
+ const inRemotejobsRepo = (0, import_helpers.isInRemotejobsRepo)();
58
+ const gitDisabledByEnv = !!process.env.FARSEER_NO_GIT;
59
+ const gitEnabled = options.git === true && inRemotejobsRepo && !gitDisabledByEnv;
60
+ if (options.git === true && !inRemotejobsRepo) {
61
+ import_logger.logger.error("Git operations are only available in remotejobs repository.");
62
+ process.exit(1);
63
+ }
64
+ if (gitEnabled && !options.message) {
65
+ import_logger.logger.error("Commit message is required when using git.");
66
+ import_logger.logger.dim('Use: farseer push <tenant> --git -m "Your message"');
67
+ process.exit(1);
68
+ }
69
+ const gitService = new import_gitService.GitService();
70
+ const syncService = new import_syncService.SyncService(tenant, clientResult.client);
71
+ if (gitEnabled) {
72
+ import_logger.logger.info("Pulling latest changes from git...");
73
+ const gitPullResult = await gitService.pull();
74
+ if (!gitPullResult.success) {
75
+ import_logger.logger.error("Git pull failed.");
76
+ import_logger.logger.dim(gitPullResult.message);
77
+ process.exit(1);
78
+ }
79
+ import_logger.logger.dim(gitPullResult.message);
80
+ }
81
+ if (!options.force) {
82
+ import_logger.logger.info("Checking for remote changes...");
83
+ const hasRemoteChanges = await syncService.checkRemoteChanges();
84
+ if (hasRemoteChanges) {
85
+ import_logger.logger.error("Remote has changes that are not synced locally.");
86
+ import_logger.logger.dim(`Run 'farseer pull ${tenant}' first, then try pushing again.`);
87
+ import_logger.logger.dim("Or use --force to push anyway (will overwrite remote changes).");
88
+ process.exit(1);
89
+ }
90
+ import_logger.logger.dim("Remote is in sync.");
91
+ }
92
+ const status = await syncService.getStatus();
93
+ const filesToPush = [
94
+ ...status.modifiedLocally,
95
+ ...status.onlyLocal
96
+ ];
97
+ const filesToDelete = status.modifiedRemotely.filter(
98
+ (f) => !fs.existsSync(`${filesDir}/${f}`)
99
+ );
100
+ let appStatus = { newLocal: [], modified: [], newRemote: [], synced: [] };
101
+ const appSyncService = new import_appSyncService.AppSyncService(tenant, clientResult.client);
102
+ appStatus = await appSyncService.getStatus();
103
+ const hasFileChanges = filesToPush.length > 0 || filesToDelete.length > 0;
104
+ const hasAppChanges = appStatus.newLocal.length > 0 || appStatus.modified.length > 0;
105
+ if (!hasFileChanges && !hasAppChanges) {
106
+ import_logger.logger.success("Nothing to push. Everything is in sync.");
107
+ return;
108
+ }
109
+ console.log();
110
+ import_logger.logger.header("Changes to push:");
111
+ if (filesToPush.length > 0) {
112
+ for (const file of filesToPush) {
113
+ const isNew = status.onlyLocal.includes(file);
114
+ if (isNew) {
115
+ console.log(import_chalk.default.green(` + ${file}`));
116
+ } else {
117
+ console.log(import_chalk.default.yellow(` M ${file}`));
118
+ }
119
+ }
120
+ }
121
+ if (filesToDelete.length > 0) {
122
+ for (const file of filesToDelete) {
123
+ console.log(import_chalk.default.red(` - ${file}`));
124
+ }
125
+ }
126
+ if (appStatus.newLocal.length > 0) {
127
+ console.log(import_chalk.default.green("New apps:"));
128
+ for (const app of appStatus.newLocal) {
129
+ console.log(import_chalk.default.green(` + ${app}`));
130
+ }
131
+ }
132
+ if (appStatus.modified.length > 0) {
133
+ console.log(import_chalk.default.yellow("Modified apps:"));
134
+ for (const app of appStatus.modified) {
135
+ console.log(import_chalk.default.yellow(` ~ ${app}`));
136
+ }
137
+ }
138
+ console.log();
139
+ const totalChanges = filesToPush.length + filesToDelete.length + appStatus.newLocal.length + appStatus.modified.length;
140
+ const confirm = await import_inquirer.default.prompt([
141
+ {
142
+ type: "confirm",
143
+ name: "proceed",
144
+ message: `Push ${totalChanges} change(s) to ${tenant}?`,
145
+ default: true
146
+ }
147
+ ]);
148
+ if (!confirm.proceed) {
149
+ import_logger.logger.info("Push cancelled.");
150
+ return;
151
+ }
152
+ await (0, import_farseerFactory.ensureFreshToken)(clientResult.client);
153
+ try {
154
+ let result = { uploaded: [], updated: [], deleted: [], unchanged: [] };
155
+ if (hasFileChanges) {
156
+ import_logger.logger.info(`Pushing files to ${tenant}...`);
157
+ result = await syncService.push();
158
+ console.log();
159
+ if (result.uploaded.length > 0) {
160
+ console.log(import_chalk.default.green("Uploaded files (new):"));
161
+ for (const file of result.uploaded) {
162
+ console.log(import_chalk.default.green(` + ${file}`));
163
+ }
164
+ console.log();
165
+ }
166
+ if (result.updated.length > 0) {
167
+ console.log(import_chalk.default.yellow("Updated files:"));
168
+ for (const file of result.updated) {
169
+ console.log(import_chalk.default.yellow(` M ${file}`));
170
+ }
171
+ console.log();
172
+ }
173
+ if (result.deleted.length > 0) {
174
+ console.log(import_chalk.default.red("Deleted files:"));
175
+ for (const file of result.deleted) {
176
+ console.log(import_chalk.default.red(` - ${file}`));
177
+ }
178
+ console.log();
179
+ }
180
+ }
181
+ let appResult = { created: [], updated: [], deleted: [], unchanged: [] };
182
+ if (hasAppChanges) {
183
+ import_logger.logger.info(`Pushing apps to ${tenant}...`);
184
+ appResult = await appSyncService.push();
185
+ if (appResult.created.length > 0) {
186
+ console.log(import_chalk.default.green("Created apps:"));
187
+ for (const app of appResult.created) {
188
+ console.log(import_chalk.default.green(` + ${app}`));
189
+ }
190
+ console.log();
191
+ }
192
+ if (appResult.updated.length > 0) {
193
+ console.log(import_chalk.default.yellow("Updated apps:"));
194
+ for (const app of appResult.updated) {
195
+ console.log(import_chalk.default.yellow(` ~ ${app}`));
196
+ }
197
+ console.log();
198
+ }
199
+ if (appResult.deleted.length > 0) {
200
+ console.log(import_chalk.default.red("Deleted apps:"));
201
+ for (const app of appResult.deleted) {
202
+ console.log(import_chalk.default.red(` - ${app}`));
203
+ }
204
+ console.log();
205
+ }
206
+ }
207
+ if (gitEnabled) {
208
+ import_logger.logger.info("Committing changes to git...");
209
+ const appsPath = `apps/${tenant}`;
210
+ await gitService.add([appsPath]);
211
+ const commitMessage = `[${tenant}] ${options.message}
212
+
213
+ Files: +${result.uploaded.length} ~${result.updated.length} -${result.deleted.length}
214
+ Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}
215
+
216
+ \u{1F916} Generated with Farseer CLI`;
217
+ const commitResult = await gitService.commit(commitMessage, import_constants.CLI_GIT_AUTHOR);
218
+ if (commitResult.success) {
219
+ import_logger.logger.dim(`Committed: ${commitResult.commitHash}`);
220
+ import_logger.logger.info("Pushing to git remote...");
221
+ const pushResult = await gitService.push();
222
+ if (pushResult.success) {
223
+ import_logger.logger.dim(pushResult.message);
224
+ } else {
225
+ import_logger.logger.warning("Failed to push to git remote.");
226
+ import_logger.logger.dim(pushResult.message);
227
+ import_logger.logger.dim("You may need to push manually.");
228
+ }
229
+ } else {
230
+ import_logger.logger.warning("Failed to commit changes.");
231
+ import_logger.logger.dim(commitResult.message);
232
+ }
233
+ }
234
+ console.log();
235
+ import_logger.logger.success("Push complete!");
236
+ import_logger.logger.dim(`Files: +${result.uploaded.length} ~${result.updated.length} -${result.deleted.length}`);
237
+ import_logger.logger.dim(`Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}`);
238
+ } catch (error) {
239
+ import_logger.logger.error("Push failed.");
240
+ if (error instanceof Error) {
241
+ import_logger.logger.dim(error.message);
242
+ }
243
+ process.exit(1);
244
+ }
245
+ });
246
+ }
247
+ // Annotate the CommonJS export names for ESM import in node:
248
+ 0 && (module.exports = {
249
+ registerPushCommand
250
+ });
251
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/push.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport inquirer from 'inquirer';\nimport { logger } from '../utils/logger';\nimport { getFarseerClientWithFallback, showLoginPrompt, ensureFreshToken } from '../services/farseerFactory';\nimport { SyncService } from '../services/syncService';\nimport { AppSyncService } from '../services/appSyncService';\nimport { GitService } from '../services/gitService';\nimport { getTenantFilesDir, resolveTenantWithOrgMapping, isInRemotejobsRepo } from '../utils/helpers';\nimport { CLI_GIT_AUTHOR } from '../utils/constants';\nimport * as fs from 'fs';\n\nexport function registerPushCommand(program: Command): void {\n program\n .command('push [arg1] [arg2]')\n .description('Push local files to Farseer instance\\n\\nUsage: push <org> <tenant> OR push <tenant> (if org is known)')\n .option('--git', 'Enable git operations (commit & push) - internal use only')\n .option('-m, --message <message>', 'Commit message (required when using --git)')\n .option('--force', 'Force push even if remote has changes')\n .action(async (arg1, arg2, options) => {\n const { organisation, tenant } = resolveTenantWithOrgMapping(arg1, arg2);\n const clientResult = await getFarseerClientWithFallback(organisation, tenant);\n\n if (!clientResult) {\n showLoginPrompt(tenant);\n process.exit(1);\n }\n\n const filesDir = getTenantFilesDir(tenant);\n\n if (!fs.existsSync(filesDir)) {\n logger.error(`Local folder not found: apps/${tenant}/files/`);\n logger.dim('Run \"farseer pull <tenant>\" first to initialize the folder.');\n process.exit(1);\n }\n\n // Git operations are opt-in with --git flag (internal developer feature)\n const inRemotejobsRepo = isInRemotejobsRepo();\n const gitDisabledByEnv = !!process.env.FARSEER_NO_GIT;\n\n // Git enabled ONLY if:\n // 1. User explicitly requested it (--git flag)\n // 2. We're in remotejobs repo (safety check)\n // 3. FARSEER_NO_GIT env var is not set\n const gitEnabled = options.git === true && inRemotejobsRepo && !gitDisabledByEnv;\n\n // Show error if --git requested but not in remotejobs repo\n if (options.git === true && !inRemotejobsRepo) {\n logger.error('Git operations are only available in remotejobs repository.');\n process.exit(1);\n }\n\n // Validate message is provided when using git\n if (gitEnabled && !options.message) {\n logger.error('Commit message is required when using git.');\n logger.dim('Use: farseer push <tenant> --git -m \"Your message\"');\n process.exit(1);\n }\n\n const gitService = new GitService();\n const syncService = new SyncService(tenant, clientResult.client);\n\n // Step 1: Git pull to ensure we're up to date\n if (gitEnabled) {\n logger.info('Pulling latest changes from git...');\n const gitPullResult = await gitService.pull();\n\n if (!gitPullResult.success) {\n logger.error('Git pull failed.');\n logger.dim(gitPullResult.message);\n process.exit(1);\n }\n\n logger.dim(gitPullResult.message);\n }\n\n // Step 2: Check if remote has unpulled changes\n if (!options.force) {\n logger.info('Checking for remote changes...');\n\n const hasRemoteChanges = await syncService.checkRemoteChanges();\n\n if (hasRemoteChanges) {\n logger.error('Remote has changes that are not synced locally.');\n logger.dim(`Run 'farseer pull ${tenant}' first, then try pushing again.`);\n logger.dim('Or use --force to push anyway (will overwrite remote changes).');\n process.exit(1);\n }\n\n logger.dim('Remote is in sync.');\n }\n\n // Step 3: Show what will be pushed\n const status = await syncService.getStatus();\n\n const filesToPush = [\n ...status.modifiedLocally,\n ...status.onlyLocal,\n ];\n\n const filesToDelete = status.modifiedRemotely.filter((f) =>\n !fs.existsSync(`${filesDir}/${f}`)\n );\n\n // Check app changes too (works with both JWT and API key)\n let appStatus = { newLocal: [] as string[], modified: [] as string[], newRemote: [] as string[], synced: [] as string[] };\n const appSyncService = new AppSyncService(tenant, clientResult.client);\n appStatus = await appSyncService.getStatus();\n\n const hasFileChanges = filesToPush.length > 0 || filesToDelete.length > 0;\n const hasAppChanges = appStatus.newLocal.length > 0 || appStatus.modified.length > 0;\n\n if (!hasFileChanges && !hasAppChanges) {\n logger.success('Nothing to push. Everything is in sync.');\n return;\n }\n\n console.log();\n logger.header('Changes to push:');\n\n if (filesToPush.length > 0) {\n for (const file of filesToPush) {\n const isNew = status.onlyLocal.includes(file);\n if (isNew) {\n console.log(chalk.green(` + ${file}`));\n } else {\n console.log(chalk.yellow(` M ${file}`));\n }\n }\n }\n\n if (filesToDelete.length > 0) {\n for (const file of filesToDelete) {\n console.log(chalk.red(` - ${file}`));\n }\n }\n\n // Show app changes\n if (appStatus.newLocal.length > 0) {\n console.log(chalk.green('New apps:'));\n for (const app of appStatus.newLocal) {\n console.log(chalk.green(` + ${app}`));\n }\n }\n\n if (appStatus.modified.length > 0) {\n console.log(chalk.yellow('Modified apps:'));\n for (const app of appStatus.modified) {\n console.log(chalk.yellow(` ~ ${app}`));\n }\n }\n\n console.log();\n\n const totalChanges = filesToPush.length + filesToDelete.length + appStatus.newLocal.length + appStatus.modified.length;\n\n // Step 4: Confirm push\n const confirm = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'proceed',\n message: `Push ${totalChanges} change(s) to ${tenant}?`,\n default: true,\n },\n ]);\n\n if (!confirm.proceed) {\n logger.info('Push cancelled.');\n return;\n }\n\n // Ensure token is fresh before push operations (may have expired during user input)\n await ensureFreshToken(clientResult.client);\n\n try {\n // Step 5: Push files only if there are file changes\n let result = { uploaded: [] as string[], updated: [] as string[], deleted: [] as string[], unchanged: [] as string[] };\n\n if (hasFileChanges) {\n logger.info(`Pushing files to ${tenant}...`);\n result = await syncService.push();\n\n console.log();\n\n if (result.uploaded.length > 0) {\n console.log(chalk.green('Uploaded files (new):'));\n for (const file of result.uploaded) {\n console.log(chalk.green(` + ${file}`));\n }\n console.log();\n }\n\n if (result.updated.length > 0) {\n console.log(chalk.yellow('Updated files:'));\n for (const file of result.updated) {\n console.log(chalk.yellow(` M ${file}`));\n }\n console.log();\n }\n\n if (result.deleted.length > 0) {\n console.log(chalk.red('Deleted files:'));\n for (const file of result.deleted) {\n console.log(chalk.red(` - ${file}`));\n }\n console.log();\n }\n }\n\n // Step 6: Push apps only if there are app changes\n let appResult = { created: [] as string[], updated: [] as string[], deleted: [] as string[], unchanged: [] as string[] };\n\n if (hasAppChanges) {\n logger.info(`Pushing apps to ${tenant}...`);\n appResult = await appSyncService.push();\n\n if (appResult.created.length > 0) {\n console.log(chalk.green('Created apps:'));\n for (const app of appResult.created) {\n console.log(chalk.green(` + ${app}`));\n }\n console.log();\n }\n\n if (appResult.updated.length > 0) {\n console.log(chalk.yellow('Updated apps:'));\n for (const app of appResult.updated) {\n console.log(chalk.yellow(` ~ ${app}`));\n }\n console.log();\n }\n\n if (appResult.deleted.length > 0) {\n console.log(chalk.red('Deleted apps:'));\n for (const app of appResult.deleted) {\n console.log(chalk.red(` - ${app}`));\n }\n console.log();\n }\n }\n\n // Step 7: Git commit & push\n if (gitEnabled) {\n logger.info('Committing changes to git...');\n\n const appsPath = `apps/${tenant}`;\n await gitService.add([appsPath]);\n\n const commitMessage = `[${tenant}] ${options.message}\n\nFiles: +${result.uploaded.length} ~${result.updated.length} -${result.deleted.length}\nApps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}\n\n\uD83E\uDD16 Generated with Farseer CLI`;\n\n const commitResult = await gitService.commit(commitMessage, CLI_GIT_AUTHOR);\n\n if (commitResult.success) {\n logger.dim(`Committed: ${commitResult.commitHash}`);\n\n logger.info('Pushing to git remote...');\n const pushResult = await gitService.push();\n\n if (pushResult.success) {\n logger.dim(pushResult.message);\n } else {\n logger.warning('Failed to push to git remote.');\n logger.dim(pushResult.message);\n logger.dim('You may need to push manually.');\n }\n } else {\n logger.warning('Failed to commit changes.');\n logger.dim(commitResult.message);\n }\n }\n\n console.log();\n logger.success('Push complete!');\n logger.dim(`Files: +${result.uploaded.length} ~${result.updated.length} -${result.deleted.length}`);\n logger.dim(`Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}`);\n } catch (error) {\n logger.error('Push failed.');\n if (error instanceof Error) {\n logger.dim(error.message);\n }\n process.exit(1);\n }\n });\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAkB;AAClB,sBAAqB;AACrB,oBAAuB;AACvB,4BAAgF;AAChF,yBAA4B;AAC5B,4BAA+B;AAC/B,wBAA2B;AAC3B,qBAAmF;AACnF,uBAA+B;AAC/B,SAAoB;AAEb,SAAS,oBAAoB,SAAwB;AACxD,UACK,QAAQ,oBAAoB,EAC5B,YAAY,uGAAuG,EACnH,OAAO,SAAS,2DAA2D,EAC3E,OAAO,2BAA2B,4CAA4C,EAC9E,OAAO,WAAW,uCAAuC,EACzD,OAAO,OAAO,MAAM,MAAM,YAAY;AACnC,UAAM,EAAE,cAAc,OAAO,QAAI,4CAA4B,MAAM,IAAI;AACvE,UAAM,eAAe,UAAM,oDAA6B,cAAc,MAAM;AAE5E,QAAI,CAAC,cAAc;AACf,iDAAgB,MAAM;AACtB,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,eAAW,kCAAkB,MAAM;AAEzC,QAAI,CAAC,GAAG,WAAW,QAAQ,GAAG;AAC1B,2BAAO,MAAM,gCAAgC,MAAM,SAAS;AAC5D,2BAAO,IAAI,6DAA6D;AACxE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAGA,UAAM,uBAAmB,mCAAmB;AAC5C,UAAM,mBAAmB,CAAC,CAAC,QAAQ,IAAI;AAMvC,UAAM,aAAa,QAAQ,QAAQ,QAAQ,oBAAoB,CAAC;AAGhE,QAAI,QAAQ,QAAQ,QAAQ,CAAC,kBAAkB;AAC3C,2BAAO,MAAM,6DAA6D;AAC1E,cAAQ,KAAK,CAAC;AAAA,IAClB;AAGA,QAAI,cAAc,CAAC,QAAQ,SAAS;AAChC,2BAAO,MAAM,4CAA4C;AACzD,2BAAO,IAAI,oDAAoD;AAC/D,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,aAAa,IAAI,6BAAW;AAClC,UAAM,cAAc,IAAI,+BAAY,QAAQ,aAAa,MAAM;AAG/D,QAAI,YAAY;AACZ,2BAAO,KAAK,oCAAoC;AAChD,YAAM,gBAAgB,MAAM,WAAW,KAAK;AAE5C,UAAI,CAAC,cAAc,SAAS;AACxB,6BAAO,MAAM,kBAAkB;AAC/B,6BAAO,IAAI,cAAc,OAAO;AAChC,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,2BAAO,IAAI,cAAc,OAAO;AAAA,IACpC;AAGA,QAAI,CAAC,QAAQ,OAAO;AAChB,2BAAO,KAAK,gCAAgC;AAE5C,YAAM,mBAAmB,MAAM,YAAY,mBAAmB;AAE9D,UAAI,kBAAkB;AAClB,6BAAO,MAAM,iDAAiD;AAC9D,6BAAO,IAAI,qBAAqB,MAAM,kCAAkC;AACxE,6BAAO,IAAI,gEAAgE;AAC3E,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,2BAAO,IAAI,oBAAoB;AAAA,IACnC;AAGA,UAAM,SAAS,MAAM,YAAY,UAAU;AAE3C,UAAM,cAAc;AAAA,MAChB,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,IACd;AAEA,UAAM,gBAAgB,OAAO,iBAAiB;AAAA,MAAO,CAAC,MAClD,CAAC,GAAG,WAAW,GAAG,QAAQ,IAAI,CAAC,EAAE;AAAA,IACrC;AAGA,QAAI,YAAY,EAAE,UAAU,CAAC,GAAe,UAAU,CAAC,GAAe,WAAW,CAAC,GAAe,QAAQ,CAAC,EAAc;AACxH,UAAM,iBAAiB,IAAI,qCAAe,QAAQ,aAAa,MAAM;AACrE,gBAAY,MAAM,eAAe,UAAU;AAE3C,UAAM,iBAAiB,YAAY,SAAS,KAAK,cAAc,SAAS;AACxE,UAAM,gBAAgB,UAAU,SAAS,SAAS,KAAK,UAAU,SAAS,SAAS;AAEnF,QAAI,CAAC,kBAAkB,CAAC,eAAe;AACnC,2BAAO,QAAQ,yCAAyC;AACxD;AAAA,IACJ;AAEA,YAAQ,IAAI;AACZ,yBAAO,OAAO,kBAAkB;AAEhC,QAAI,YAAY,SAAS,GAAG;AACxB,iBAAW,QAAQ,aAAa;AAC5B,cAAM,QAAQ,OAAO,UAAU,SAAS,IAAI;AAC5C,YAAI,OAAO;AACP,kBAAQ,IAAI,aAAAA,QAAM,MAAM,OAAO,IAAI,EAAE,CAAC;AAAA,QAC1C,OAAO;AACH,kBAAQ,IAAI,aAAAA,QAAM,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,QAC3C;AAAA,MACJ;AAAA,IACJ;AAEA,QAAI,cAAc,SAAS,GAAG;AAC1B,iBAAW,QAAQ,eAAe;AAC9B,gBAAQ,IAAI,aAAAA,QAAM,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,MACxC;AAAA,IACJ;AAGA,QAAI,UAAU,SAAS,SAAS,GAAG;AAC/B,cAAQ,IAAI,aAAAA,QAAM,MAAM,WAAW,CAAC;AACpC,iBAAW,OAAO,UAAU,UAAU;AAClC,gBAAQ,IAAI,aAAAA,QAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AAAA,MACzC;AAAA,IACJ;AAEA,QAAI,UAAU,SAAS,SAAS,GAAG;AAC/B,cAAQ,IAAI,aAAAA,QAAM,OAAO,gBAAgB,CAAC;AAC1C,iBAAW,OAAO,UAAU,UAAU;AAClC,gBAAQ,IAAI,aAAAA,QAAM,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,MAC1C;AAAA,IACJ;AAEA,YAAQ,IAAI;AAEZ,UAAM,eAAe,YAAY,SAAS,cAAc,SAAS,UAAU,SAAS,SAAS,UAAU,SAAS;AAGhH,UAAM,UAAU,MAAM,gBAAAC,QAAS,OAAO;AAAA,MAClC;AAAA,QACI,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ,YAAY,iBAAiB,MAAM;AAAA,QACpD,SAAS;AAAA,MACb;AAAA,IACJ,CAAC;AAED,QAAI,CAAC,QAAQ,SAAS;AAClB,2BAAO,KAAK,iBAAiB;AAC7B;AAAA,IACJ;AAGA,cAAM,wCAAiB,aAAa,MAAM;AAE1C,QAAI;AAEA,UAAI,SAAS,EAAE,UAAU,CAAC,GAAe,SAAS,CAAC,GAAe,SAAS,CAAC,GAAe,WAAW,CAAC,EAAc;AAErH,UAAI,gBAAgB;AAChB,6BAAO,KAAK,oBAAoB,MAAM,KAAK;AAC3C,iBAAS,MAAM,YAAY,KAAK;AAEhC,gBAAQ,IAAI;AAEZ,YAAI,OAAO,SAAS,SAAS,GAAG;AAC5B,kBAAQ,IAAI,aAAAD,QAAM,MAAM,uBAAuB,CAAC;AAChD,qBAAW,QAAQ,OAAO,UAAU;AAChC,oBAAQ,IAAI,aAAAA,QAAM,MAAM,OAAO,IAAI,EAAE,CAAC;AAAA,UAC1C;AACA,kBAAQ,IAAI;AAAA,QAChB;AAEA,YAAI,OAAO,QAAQ,SAAS,GAAG;AAC3B,kBAAQ,IAAI,aAAAA,QAAM,OAAO,gBAAgB,CAAC;AAC1C,qBAAW,QAAQ,OAAO,SAAS;AAC/B,oBAAQ,IAAI,aAAAA,QAAM,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,UAC3C;AACA,kBAAQ,IAAI;AAAA,QAChB;AAEA,YAAI,OAAO,QAAQ,SAAS,GAAG;AAC3B,kBAAQ,IAAI,aAAAA,QAAM,IAAI,gBAAgB,CAAC;AACvC,qBAAW,QAAQ,OAAO,SAAS;AAC/B,oBAAQ,IAAI,aAAAA,QAAM,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,UACxC;AACA,kBAAQ,IAAI;AAAA,QAChB;AAAA,MACJ;AAGA,UAAI,YAAY,EAAE,SAAS,CAAC,GAAe,SAAS,CAAC,GAAe,SAAS,CAAC,GAAe,WAAW,CAAC,EAAc;AAEvH,UAAI,eAAe;AACf,6BAAO,KAAK,mBAAmB,MAAM,KAAK;AAC1C,oBAAY,MAAM,eAAe,KAAK;AAEtC,YAAI,UAAU,QAAQ,SAAS,GAAG;AAC9B,kBAAQ,IAAI,aAAAA,QAAM,MAAM,eAAe,CAAC;AACxC,qBAAW,OAAO,UAAU,SAAS;AACjC,oBAAQ,IAAI,aAAAA,QAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AAAA,UACzC;AACA,kBAAQ,IAAI;AAAA,QAChB;AAEA,YAAI,UAAU,QAAQ,SAAS,GAAG;AAC9B,kBAAQ,IAAI,aAAAA,QAAM,OAAO,eAAe,CAAC;AACzC,qBAAW,OAAO,UAAU,SAAS;AACjC,oBAAQ,IAAI,aAAAA,QAAM,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,UAC1C;AACA,kBAAQ,IAAI;AAAA,QAChB;AAEA,YAAI,UAAU,QAAQ,SAAS,GAAG;AAC9B,kBAAQ,IAAI,aAAAA,QAAM,IAAI,eAAe,CAAC;AACtC,qBAAW,OAAO,UAAU,SAAS;AACjC,oBAAQ,IAAI,aAAAA,QAAM,IAAI,OAAO,GAAG,EAAE,CAAC;AAAA,UACvC;AACA,kBAAQ,IAAI;AAAA,QAChB;AAAA,MACJ;AAGA,UAAI,YAAY;AACZ,6BAAO,KAAK,8BAA8B;AAE1C,cAAM,WAAW,QAAQ,MAAM;AAC/B,cAAM,WAAW,IAAI,CAAC,QAAQ,CAAC;AAE/B,cAAM,gBAAgB,IAAI,MAAM,KAAK,QAAQ,OAAO;AAAA;AAAA,UAE9D,OAAO,SAAS,MAAM,KAAK,OAAO,QAAQ,MAAM,KAAK,OAAO,QAAQ,MAAM;AAAA,SAC3E,UAAU,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM;AAAA;AAAA;AAIvE,cAAM,eAAe,MAAM,WAAW,OAAO,eAAe,+BAAc;AAE1E,YAAI,aAAa,SAAS;AACtB,+BAAO,IAAI,cAAc,aAAa,UAAU,EAAE;AAElD,+BAAO,KAAK,0BAA0B;AACtC,gBAAM,aAAa,MAAM,WAAW,KAAK;AAEzC,cAAI,WAAW,SAAS;AACpB,iCAAO,IAAI,WAAW,OAAO;AAAA,UACjC,OAAO;AACH,iCAAO,QAAQ,+BAA+B;AAC9C,iCAAO,IAAI,WAAW,OAAO;AAC7B,iCAAO,IAAI,gCAAgC;AAAA,UAC/C;AAAA,QACJ,OAAO;AACH,+BAAO,QAAQ,2BAA2B;AAC1C,+BAAO,IAAI,aAAa,OAAO;AAAA,QACnC;AAAA,MACJ;AAEA,cAAQ,IAAI;AACZ,2BAAO,QAAQ,gBAAgB;AAC/B,2BAAO,IAAI,WAAW,OAAO,SAAS,MAAM,KAAK,OAAO,QAAQ,MAAM,KAAK,OAAO,QAAQ,MAAM,EAAE;AAClG,2BAAO,IAAI,UAAU,UAAU,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,EAAE;AAAA,IAC7G,SAAS,OAAO;AACZ,2BAAO,MAAM,cAAc;AAC3B,UAAI,iBAAiB,OAAO;AACxB,6BAAO,IAAI,MAAM,OAAO;AAAA,MAC5B;AACA,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ,CAAC;AACT;",
6
+ "names": ["chalk", "inquirer"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerRunCommand(program: Command): void;
@@ -0,0 +1,246 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var run_exports = {};
29
+ __export(run_exports, {
30
+ registerRunCommand: () => registerRunCommand
31
+ });
32
+ module.exports = __toCommonJS(run_exports);
33
+ var import_logger = require("../utils/logger");
34
+ var import_configService = require("../services/configService");
35
+ var import_farseerService = require("../services/farseerService");
36
+ var import_farseerFactory = require("../services/farseerFactory");
37
+ var import_helpers = require("../utils/helpers");
38
+ var fs = __toESM(require("fs"));
39
+ var path = __toESM(require("path"));
40
+ var import_child_process = require("child_process");
41
+ async function getRunCredentials(tenant, tenantId) {
42
+ const credential = (0, import_configService.getCredential)(tenant);
43
+ if (credential) {
44
+ return {
45
+ tenantId: credential.tenantId,
46
+ apiKey: credential.apiKey,
47
+ basePath: credential.basePath
48
+ };
49
+ }
50
+ const auth = (0, import_configService.getUserAuth)();
51
+ if (!auth) {
52
+ return null;
53
+ }
54
+ if (!(0, import_configService.isUserAuthValid)()) {
55
+ import_logger.logger.dim("Token expired, refreshing...");
56
+ const refreshed = await (0, import_farseerService.refreshAccessToken)(auth.refreshToken, auth.realm || "master");
57
+ if (!refreshed) {
58
+ import_logger.logger.warning("Could not refresh token. Please login again with: farseer login");
59
+ return null;
60
+ }
61
+ (0, import_configService.setUserAuth)({
62
+ accessToken: refreshed.accessToken,
63
+ refreshToken: refreshed.refreshToken,
64
+ expiresAt: new Date(Date.now() + refreshed.expiresIn * 1e3).toISOString(),
65
+ realm: auth.realm
66
+ });
67
+ import_logger.logger.success("Token refreshed");
68
+ }
69
+ const updatedAuth = (0, import_configService.getUserAuth)();
70
+ if (!updatedAuth) return null;
71
+ return {
72
+ tenantId: tenantId || tenant,
73
+ accessToken: updatedAuth.accessToken,
74
+ basePath: (0, import_configService.generateBasePath)(tenant)
75
+ };
76
+ }
77
+ function collectArgs(value, previous) {
78
+ return previous.concat([value]);
79
+ }
80
+ function registerRunCommand(program) {
81
+ program.command("run <args...>").description("Run an app locally with injected credentials").option("--tenant-id <id>", "Tenant ID for env variables (defaults to tenant name)").option("--arg <value>", 'Pass argument in format "Name=Value" (can be used multiple times)', collectArgs, []).action(async (args, options) => {
82
+ const { tenant, appName } = (0, import_helpers.parseAppArgs)(args);
83
+ const clientResult = await (0, import_farseerFactory.getFarseerClientWithFallback)(tenant, options.tenantId);
84
+ if (!clientResult) {
85
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
86
+ process.exit(1);
87
+ }
88
+ const api = clientResult.client;
89
+ import_logger.logger.info(`Loading app: ${appName}...`);
90
+ const app = await api.getAppByName(appName);
91
+ if (!app) {
92
+ import_logger.logger.error(`App not found: ${appName}`);
93
+ import_logger.logger.dim("List available apps with: farseer apps " + tenant);
94
+ process.exit(1);
95
+ }
96
+ if (!app.mainScriptFileId || app.scriptFiles.length === 0) {
97
+ import_logger.logger.error(`App "${appName}" has no scripts configured.`);
98
+ import_logger.logger.dim('Configure the app with: farseer app configure "' + appName + '" --entrypoint <script>');
99
+ process.exit(1);
100
+ }
101
+ const mainScript = app.scriptFiles.find((s) => s.id === app.mainScriptFileId);
102
+ if (!mainScript) {
103
+ import_logger.logger.error(`Entrypoint script not found for app "${appName}".`);
104
+ process.exit(1);
105
+ }
106
+ let scriptName = mainScript.name;
107
+ if (scriptName.toLowerCase().startsWith("scripts/")) {
108
+ scriptName = scriptName.substring("scripts/".length);
109
+ }
110
+ const credentials = await getRunCredentials(tenant, options.tenantId);
111
+ if (!credentials) {
112
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
113
+ process.exit(1);
114
+ }
115
+ const tenantDir = (0, import_helpers.getTenantDir)(tenant);
116
+ const srcDir = (0, import_helpers.getTenantSrcDir)(tenant);
117
+ const scriptPath = path.resolve(srcDir, scriptName);
118
+ if (!fs.existsSync(scriptPath)) {
119
+ import_logger.logger.error(`Script not found locally: ${scriptPath}`);
120
+ import_logger.logger.dim('Run "farseer pull ' + tenant + '" to download scripts first.');
121
+ process.exit(1);
122
+ }
123
+ const nodeModulesPath = path.join(tenantDir, "node_modules");
124
+ if (!fs.existsSync(nodeModulesPath)) {
125
+ import_logger.logger.error(`Dependencies not installed for ${tenant}`);
126
+ import_logger.logger.dim(`Run: farseer install ${tenant}`);
127
+ process.exit(1);
128
+ }
129
+ const appArgs = {};
130
+ for (const arg of app.expectedArguments) {
131
+ appArgs[arg.name] = arg.defaultValue;
132
+ }
133
+ for (const argStr of options.arg) {
134
+ const eqIndex = argStr.indexOf("=");
135
+ if (eqIndex === -1) {
136
+ import_logger.logger.error(`Invalid argument format: ${argStr}`);
137
+ import_logger.logger.dim('Use format: --arg "Name=Value"');
138
+ process.exit(1);
139
+ }
140
+ const name = argStr.substring(0, eqIndex);
141
+ const value = argStr.substring(eqIndex + 1);
142
+ appArgs[name] = value;
143
+ }
144
+ const authType = credentials.apiKey ? "API key" : "access token";
145
+ import_logger.logger.info(`Running app "${app.name}" (${scriptName}) for tenant ${tenant} (using ${authType})...`);
146
+ if (Object.keys(appArgs).length > 0) {
147
+ import_logger.logger.dim("Arguments:");
148
+ for (const [key, value] of Object.entries(appArgs)) {
149
+ import_logger.logger.dim(` ${key}: ${value}`);
150
+ }
151
+ }
152
+ console.log();
153
+ const envVars = {
154
+ ...process.env,
155
+ TENANT_ID: credentials.tenantId,
156
+ FARSEER_URL: credentials.basePath
157
+ };
158
+ if (credentials.apiKey) {
159
+ envVars.FARSEER_API_KEY = credentials.apiKey;
160
+ }
161
+ if (credentials.accessToken) {
162
+ envVars.FARSEER_ACCESS_TOKEN = credentials.accessToken;
163
+ }
164
+ const cmdArgs = [];
165
+ for (const arg of app.expectedArguments) {
166
+ cmdArgs.push(appArgs[arg.name] ?? arg.defaultValue);
167
+ }
168
+ const child = (0, import_child_process.spawn)("npx", ["tsx", `files/Scripts/${scriptName}`, ...cmdArgs], {
169
+ stdio: "inherit",
170
+ cwd: tenantDir,
171
+ shell: true,
172
+ env: envVars
173
+ });
174
+ child.on("close", (code) => {
175
+ if (code !== 0) {
176
+ import_logger.logger.error(`Script exited with code ${code}`);
177
+ process.exit(code || 1);
178
+ }
179
+ });
180
+ child.on("error", (err) => {
181
+ import_logger.logger.error(`Failed to run script: ${err.message}`);
182
+ import_logger.logger.dim("Make sure tsx is installed: npm install -g tsx");
183
+ process.exit(1);
184
+ });
185
+ });
186
+ program.command("run-script <args...>").description("Run a script directly (without app wrapper)").option("--tenant-id <id>", "Tenant ID for env variables (defaults to tenant name)").action(async (args, options) => {
187
+ let { tenant, appName: script } = (0, import_helpers.parseAppArgs)(args);
188
+ const credentials = await getRunCredentials(tenant, options.tenantId);
189
+ if (!credentials) {
190
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
191
+ process.exit(1);
192
+ }
193
+ if (script.toLowerCase().startsWith("scripts/")) {
194
+ script = script.substring("scripts/".length);
195
+ }
196
+ const tenantDir = (0, import_helpers.getTenantDir)(tenant);
197
+ const srcDir = (0, import_helpers.getTenantSrcDir)(tenant);
198
+ const scriptPath = path.resolve(srcDir, script);
199
+ if (!fs.existsSync(scriptPath)) {
200
+ import_logger.logger.error(`Script not found: ${scriptPath}`);
201
+ process.exit(1);
202
+ }
203
+ const nodeModulesPath = path.join(tenantDir, "node_modules");
204
+ if (!fs.existsSync(nodeModulesPath)) {
205
+ import_logger.logger.error(`Dependencies not installed for ${tenant}`);
206
+ import_logger.logger.dim(`Run: farseer install ${tenant}`);
207
+ process.exit(1);
208
+ }
209
+ const authType = credentials.apiKey ? "API key" : "access token";
210
+ import_logger.logger.info(`Running ${script} for tenant ${tenant} (using ${authType})...`);
211
+ console.log();
212
+ const envVars = {
213
+ ...process.env,
214
+ TENANT_ID: credentials.tenantId,
215
+ FARSEER_URL: credentials.basePath
216
+ };
217
+ if (credentials.apiKey) {
218
+ envVars.FARSEER_API_KEY = credentials.apiKey;
219
+ }
220
+ if (credentials.accessToken) {
221
+ envVars.FARSEER_ACCESS_TOKEN = credentials.accessToken;
222
+ }
223
+ const child = (0, import_child_process.spawn)("npx", ["tsx", `files/Scripts/${script}`], {
224
+ stdio: "inherit",
225
+ cwd: tenantDir,
226
+ shell: true,
227
+ env: envVars
228
+ });
229
+ child.on("close", (code) => {
230
+ if (code !== 0) {
231
+ import_logger.logger.error(`Script exited with code ${code}`);
232
+ process.exit(code || 1);
233
+ }
234
+ });
235
+ child.on("error", (err) => {
236
+ import_logger.logger.error(`Failed to run script: ${err.message}`);
237
+ import_logger.logger.dim("Make sure tsx is installed: npm install -g tsx");
238
+ process.exit(1);
239
+ });
240
+ });
241
+ }
242
+ // Annotate the CommonJS export names for ESM import in node:
243
+ 0 && (module.exports = {
244
+ registerRunCommand
245
+ });
246
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/run.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport { logger } from '../utils/logger';\nimport { getCredential, getUserAuth, isUserAuthValid, setUserAuth, generateBasePath } from '../services/configService';\nimport { refreshAccessToken } from '../services/farseerService';\nimport { getFarseerClientWithFallback, showLoginPrompt, IFarseerClient } from '../services/farseerFactory';\nimport { getTenantDir, getTenantSrcDir, parseAppArgs } from '../utils/helpers';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { spawn } from 'child_process';\n\ninterface RunCredentials {\n tenantId: string;\n apiKey?: string;\n accessToken?: string;\n basePath: string;\n}\n\nasync function getRunCredentials(tenant: string, tenantId?: string): Promise<RunCredentials | null> {\n // First try API key config\n const credential = getCredential(tenant);\n if (credential) {\n return {\n tenantId: credential.tenantId,\n apiKey: credential.apiKey,\n basePath: credential.basePath,\n };\n }\n\n // Try user auth (browser login)\n const auth = getUserAuth();\n if (!auth) {\n return null;\n }\n\n // Check if token needs refresh\n if (!isUserAuthValid()) {\n logger.dim('Token expired, refreshing...');\n const refreshed = await refreshAccessToken(auth.refreshToken, auth.realm || 'master');\n if (!refreshed) {\n logger.warning('Could not refresh token. Please login again with: farseer login');\n return null;\n }\n // Save refreshed token\n setUserAuth({\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken,\n expiresAt: new Date(Date.now() + refreshed.expiresIn * 1000).toISOString(),\n realm: auth.realm,\n });\n logger.success('Token refreshed');\n }\n\n const updatedAuth = getUserAuth();\n if (!updatedAuth) return null;\n\n // Use tenant name as organisation for basePath, tenantId for TENANT_ID env var\n return {\n tenantId: tenantId || tenant,\n accessToken: updatedAuth.accessToken,\n basePath: generateBasePath(tenant),\n };\n}\n\n// Helper to collect multiple --arg options\nfunction collectArgs(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n\nexport function registerRunCommand(program: Command): void {\n program\n .command('run <args...>')\n .description('Run an app locally with injected credentials')\n .option('--tenant-id <id>', 'Tenant ID for env variables (defaults to tenant name)')\n .option('--arg <value>', 'Pass argument in format \"Name=Value\" (can be used multiple times)', collectArgs, [])\n .action(async (args: string[], options) => {\n const { tenant, appName } = parseAppArgs(args);\n // First, get the app details to find the entrypoint script\n const clientResult = await getFarseerClientWithFallback(tenant, options.tenantId);\n\n if (!clientResult) {\n showLoginPrompt(tenant);\n process.exit(1);\n }\n\n const api: IFarseerClient = clientResult.client;\n\n // Find the app\n logger.info(`Loading app: ${appName}...`);\n const app = await api.getAppByName(appName);\n\n if (!app) {\n logger.error(`App not found: ${appName}`);\n logger.dim('List available apps with: farseer apps ' + tenant);\n process.exit(1);\n }\n\n if (!app.mainScriptFileId || app.scriptFiles.length === 0) {\n logger.error(`App \"${appName}\" has no scripts configured.`);\n logger.dim('Configure the app with: farseer app configure \"' + appName + '\" --entrypoint <script>');\n process.exit(1);\n }\n\n // Find the entrypoint script name\n const mainScript = app.scriptFiles.find(s => s.id === app.mainScriptFileId);\n if (!mainScript) {\n logger.error(`Entrypoint script not found for app \"${appName}\".`);\n process.exit(1);\n }\n\n // Normalize script name - handle both \"test.ts\" and \"Scripts/test.ts\" formats\n let scriptName = mainScript.name;\n if (scriptName.toLowerCase().startsWith('scripts/')) {\n scriptName = scriptName.substring('scripts/'.length);\n }\n\n // Get credentials for running\n const credentials = await getRunCredentials(tenant, options.tenantId);\n\n if (!credentials) {\n showLoginPrompt(tenant);\n process.exit(1);\n }\n\n const tenantDir = getTenantDir(tenant);\n const srcDir = getTenantSrcDir(tenant);\n\n // Script path is relative to files/Scripts/ folder\n const scriptPath = path.resolve(srcDir, scriptName);\n\n if (!fs.existsSync(scriptPath)) {\n logger.error(`Script not found locally: ${scriptPath}`);\n logger.dim('Run \"farseer pull ' + tenant + '\" to download scripts first.');\n process.exit(1);\n }\n\n // Check if node_modules exists\n const nodeModulesPath = path.join(tenantDir, 'node_modules');\n if (!fs.existsSync(nodeModulesPath)) {\n logger.error(`Dependencies not installed for ${tenant}`);\n logger.dim(`Run: farseer install ${tenant}`);\n process.exit(1);\n }\n\n // Parse arguments\n const appArgs: Record<string, string> = {};\n\n // Start with default values from app config\n for (const arg of app.expectedArguments) {\n appArgs[arg.name] = arg.defaultValue;\n }\n\n // Override with provided arguments\n for (const argStr of options.arg) {\n const eqIndex = argStr.indexOf('=');\n if (eqIndex === -1) {\n logger.error(`Invalid argument format: ${argStr}`);\n logger.dim('Use format: --arg \"Name=Value\"');\n process.exit(1);\n }\n const name = argStr.substring(0, eqIndex);\n const value = argStr.substring(eqIndex + 1);\n appArgs[name] = value;\n }\n\n const authType = credentials.apiKey ? 'API key' : 'access token';\n logger.info(`Running app \"${app.name}\" (${scriptName}) for tenant ${tenant} (using ${authType})...`);\n\n // Show arguments being used\n if (Object.keys(appArgs).length > 0) {\n logger.dim('Arguments:');\n for (const [key, value] of Object.entries(appArgs)) {\n logger.dim(` ${key}: ${value}`);\n }\n }\n console.log();\n\n // Build environment variables based on auth type\n const envVars: Record<string, string> = {\n ...process.env as Record<string, string>,\n TENANT_ID: credentials.tenantId,\n FARSEER_URL: credentials.basePath,\n };\n\n if (credentials.apiKey) {\n envVars.FARSEER_API_KEY = credentials.apiKey;\n }\n if (credentials.accessToken) {\n envVars.FARSEER_ACCESS_TOKEN = credentials.accessToken;\n }\n\n // Build command line arguments from app arguments (in order)\n const cmdArgs: string[] = [];\n for (const arg of app.expectedArguments) {\n cmdArgs.push(appArgs[arg.name] ?? arg.defaultValue);\n }\n\n // Run with credentials injected via environment variables, arguments via command line\n const child = spawn('npx', ['tsx', `files/Scripts/${scriptName}`, ...cmdArgs], {\n stdio: 'inherit',\n cwd: tenantDir,\n shell: true,\n env: envVars,\n });\n\n child.on('close', (code) => {\n if (code !== 0) {\n logger.error(`Script exited with code ${code}`);\n process.exit(code || 1);\n }\n });\n\n child.on('error', (err) => {\n logger.error(`Failed to run script: ${err.message}`);\n logger.dim('Make sure tsx is installed: npm install -g tsx');\n process.exit(1);\n });\n });\n\n // Keep the old script-based run as a separate command\n program\n .command('run-script <args...>')\n .description('Run a script directly (without app wrapper)')\n .option('--tenant-id <id>', 'Tenant ID for env variables (defaults to tenant name)')\n .action(async (args: string[], options) => {\n let { tenant, appName: script } = parseAppArgs(args);\n const credentials = await getRunCredentials(tenant, options.tenantId);\n\n if (!credentials) {\n showLoginPrompt(tenant);\n process.exit(1);\n }\n\n // Normalize script path - strip Scripts/ prefix if present\n if (script.toLowerCase().startsWith('scripts/')) {\n script = script.substring('scripts/'.length);\n }\n\n const tenantDir = getTenantDir(tenant);\n const srcDir = getTenantSrcDir(tenant);\n\n // Script path is relative to files/Scripts/ folder\n const scriptPath = path.resolve(srcDir, script);\n\n if (!fs.existsSync(scriptPath)) {\n logger.error(`Script not found: ${scriptPath}`);\n process.exit(1);\n }\n\n // Check if node_modules exists\n const nodeModulesPath = path.join(tenantDir, 'node_modules');\n if (!fs.existsSync(nodeModulesPath)) {\n logger.error(`Dependencies not installed for ${tenant}`);\n logger.dim(`Run: farseer install ${tenant}`);\n process.exit(1);\n }\n\n const authType = credentials.apiKey ? 'API key' : 'access token';\n logger.info(`Running ${script} for tenant ${tenant} (using ${authType})...`);\n console.log();\n\n // Build environment variables based on auth type\n const envVars: Record<string, string> = {\n ...process.env as Record<string, string>,\n TENANT_ID: credentials.tenantId,\n FARSEER_URL: credentials.basePath,\n };\n\n if (credentials.apiKey) {\n envVars.FARSEER_API_KEY = credentials.apiKey;\n }\n if (credentials.accessToken) {\n envVars.FARSEER_ACCESS_TOKEN = credentials.accessToken;\n }\n\n // Run with credentials injected via environment variables\n const child = spawn('npx', ['tsx', `files/Scripts/${script}`], {\n stdio: 'inherit',\n cwd: tenantDir,\n shell: true,\n env: envVars,\n });\n\n child.on('close', (code) => {\n if (code !== 0) {\n logger.error(`Script exited with code ${code}`);\n process.exit(code || 1);\n }\n });\n\n child.on('error', (err) => {\n logger.error(`Failed to run script: ${err.message}`);\n logger.dim('Make sure tsx is installed: npm install -g tsx');\n process.exit(1);\n });\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSetupCommand(program: Command): void;