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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/tools/syncTools.ts"],
4
+ "sourcesContent": ["/**\n * File Synchronization Tools\n *\n * Tools for syncing files between local repository and Farseer instance.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createPatch } from 'diff';\nimport { SyncService } from '../../services/syncService';\nimport { AppSyncService } from '../../services/appSyncService';\nimport { getFarseerClientWithFallback } from '../../services/farseerFactory';\nimport { getCurrentCheckout } from '../../services/configService';\nimport {\n successResponse,\n errorResponse,\n authRequiredResponse,\n tenantRequiredResponse,\n} from '../utils/helpers';\n\n// Define schemas outside of tool registration to avoid deep type instantiation\nconst pullSchema = {\n tenant: z.string().optional().describe('Tenant name. Uses checked-out tenant if omitted.'),\n tenantId: z\n .string()\n .optional()\n .describe('Override X-TENANT-ID header if different from tenant name'),\n all: z.boolean().optional().describe('Download all files, not just scripts (.ts, .js)'),\n};\n\nconst pushSchema = {\n tenant: z.string().optional().describe('Tenant name. Uses checked-out tenant if omitted.'),\n tenantId: z\n .string()\n .optional()\n .describe('Override X-TENANT-ID header if different from tenant name'),\n force: z.boolean().optional().describe('Skip remote changes check (may overwrite remote changes)'),\n};\n\nconst statusSchema = {\n tenant: z.string().optional().describe('Tenant name. Uses checked-out tenant if omitted.'),\n tenantId: z.string().optional().describe('Override X-TENANT-ID header'),\n all: z.boolean().optional().describe('Show all files, not just scripts'),\n};\n\nconst diffSchema = {\n tenant: z.string().optional().describe('Tenant name'),\n file: z.string().optional().describe('Specific file path to diff. If omitted, shows all differences.'),\n showRemote: z.boolean().optional().describe('Show only the remote content instead of diff'),\n};\n\nconst listFilesSchema = {\n tenant: z.string().optional().describe('Tenant name'),\n all: z.boolean().optional().describe('Show all files, not just scripts'),\n};\n\nexport function registerSyncTools(server: McpServer): void {\n // farseer_pull - Download files from remote\n server.tool(\n 'farseer_pull',\n `Pull (download) files and app configurations from a Farseer instance to the local repository.\n\nWhat gets pulled:\n- TypeScript/JavaScript scripts from Files/ folder (searched recursively)\n- App configurations (saved as JSON in apps/ folder)\n\nFiles are saved to: apps/<tenant>/files/\nApps are saved to: apps/<tenant>/apps/\n\nBy default only script files (.ts, .js, .mjs, .cjs) are pulled.\nUse all=true to pull all files including images, data files, etc.\n\nIf no tenant is specified, uses the currently checked-out tenant.`,\n pullSchema,\n async (params: { tenant?: string; tenantId?: string; all?: boolean }) => {\n const { tenant: tenantArg, tenantId, all } = params;\n const checkout = getCurrentCheckout();\n const tenant = tenantArg || checkout?.tenant;\n const organisation = tenantArg || checkout?.organisation;\n\n if (!tenant || !organisation) {\n return tenantRequiredResponse();\n }\n\n const clientResult = await getFarseerClientWithFallback(organisation, tenantId || tenant);\n if (!clientResult) {\n return authRequiredResponse(tenant);\n }\n\n try {\n // Pull files\n const syncService = new SyncService(organisation, clientResult.client);\n const fileResult = await syncService.pull({ all });\n\n // Pull apps (only with JWT auth)\n let appResult = null;\n if (clientResult.authType === 'jwt') {\n const appSyncService = new AppSyncService(organisation, clientResult.client);\n appResult = await appSyncService.pull();\n }\n\n return successResponse({\n tenant,\n files: {\n downloaded: fileResult.downloaded,\n deleted: fileResult.deleted,\n unchanged: fileResult.unchanged.length,\n },\n apps: appResult\n ? {\n created: appResult.created,\n updated: appResult.updated,\n deleted: appResult.deleted,\n unchanged: appResult.unchanged.length,\n }\n : { note: 'App sync requires browser login (JWT)' },\n message: `Pulled ${fileResult.downloaded.length} files${appResult ? ` and ${appResult.created.length + appResult.updated.length} apps` : ''}`,\n });\n } catch (error) {\n return errorResponse(\n `Pull failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n );\n }\n }\n );\n\n // farseer_push - Upload files to remote\n server.tool(\n 'farseer_push',\n `Push (upload) local file and app changes to a Farseer instance.\n\nWhat gets pushed:\n- New/modified scripts from apps/<tenant>/files/\n- New/modified app configurations from apps/<tenant>/apps/\n- Deleted files (if they were previously synced)\n\nImportant:\n- Checks for unpulled remote changes first to prevent conflicts\n- Use force=true to skip this check (may overwrite remote changes)\n\nIf no tenant is specified, uses the currently checked-out tenant.`,\n pushSchema,\n async (params: { tenant?: string; tenantId?: string; force?: boolean }) => {\n const { tenant: tenantArg, tenantId, force } = params;\n const checkout = getCurrentCheckout();\n const tenant = tenantArg || checkout?.tenant;\n const organisation = tenantArg || checkout?.organisation;\n\n if (!tenant || !organisation) {\n return tenantRequiredResponse();\n }\n\n const clientResult = await getFarseerClientWithFallback(organisation, tenantId || tenant);\n if (!clientResult) {\n return authRequiredResponse(tenant);\n }\n\n try {\n const syncService = new SyncService(organisation, clientResult.client);\n\n // Check for remote changes unless force is true\n if (!force) {\n const hasRemoteChanges = await syncService.checkRemoteChanges();\n if (hasRemoteChanges) {\n return errorResponse(\n 'Remote has unpulled changes. Pull first or use force=true to overwrite.',\n 'VALIDATION_ERROR'\n );\n }\n }\n\n // Push files\n const fileResult = await syncService.push();\n\n // Push apps (only with JWT auth)\n let appResult = null;\n if (clientResult.authType === 'jwt') {\n const appSyncService = new AppSyncService(organisation, clientResult.client);\n appResult = await appSyncService.push();\n }\n\n return successResponse({\n tenant,\n files: {\n uploaded: fileResult.uploaded,\n updated: fileResult.updated,\n deleted: fileResult.deleted,\n unchanged: fileResult.unchanged.length,\n },\n apps: appResult\n ? {\n created: appResult.created,\n updated: appResult.updated,\n unchanged: appResult.unchanged.length,\n }\n : { note: 'App sync requires browser login (JWT)' },\n summary: `Pushed ${fileResult.uploaded.length + fileResult.updated.length} files${appResult ? ` and ${appResult.created.length + appResult.updated.length} apps` : ''}`,\n });\n } catch (error) {\n return errorResponse(\n `Push failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n );\n }\n }\n );\n\n // farseer_status - Check sync status\n server.tool(\n 'farseer_status',\n `Check the synchronization status between local files and the remote Farseer instance.\n\nShows which files are:\n- Modified locally (changed since last sync)\n- Modified remotely (changed on server since last sync)\n- Only local (new files not yet pushed)\n- Only remote (files not yet pulled)\n- In sync (no changes)\n\nAlso shows app sync status if using JWT authentication.\n\nIf no tenant is specified, uses the currently checked-out tenant.`,\n statusSchema,\n async (params: { tenant?: string; tenantId?: string; all?: boolean }) => {\n const { tenant: tenantArg, tenantId, all } = params;\n const checkout = getCurrentCheckout();\n const tenant = tenantArg || checkout?.tenant;\n const organisation = tenantArg || checkout?.organisation;\n\n if (!tenant || !organisation) {\n return tenantRequiredResponse();\n }\n\n const clientResult = await getFarseerClientWithFallback(organisation, tenantId || tenant);\n if (!clientResult) {\n return authRequiredResponse(tenant);\n }\n\n try {\n const syncService = new SyncService(organisation, clientResult.client);\n const fileStatus = await syncService.getStatus({ all });\n\n // Get app status (only with JWT auth)\n let appStatus = null;\n if (clientResult.authType === 'jwt') {\n const appSyncService = new AppSyncService(organisation, clientResult.client);\n appStatus = await appSyncService.getStatus();\n }\n\n const hasChanges =\n fileStatus.modifiedLocally.length > 0 ||\n fileStatus.modifiedRemotely.length > 0 ||\n fileStatus.onlyLocal.length > 0 ||\n fileStatus.onlyRemote.length > 0;\n\n return successResponse({\n tenant,\n files: {\n modifiedLocally: fileStatus.modifiedLocally,\n modifiedRemotely: fileStatus.modifiedRemotely,\n onlyLocal: fileStatus.onlyLocal,\n onlyRemote: fileStatus.onlyRemote,\n inSync: fileStatus.inSync.length,\n },\n apps: appStatus\n ? {\n newLocal: appStatus.newLocal,\n newRemote: appStatus.newRemote,\n modified: appStatus.modified,\n synced: appStatus.synced.length,\n }\n : { note: 'App sync requires browser login (JWT)' },\n summary: hasChanges ? 'Changes detected' : 'Everything is in sync',\n });\n } catch (error) {\n return errorResponse(\n `Status check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n );\n }\n }\n );\n\n // farseer_diff - Show file differences\n server.tool(\n 'farseer_diff',\n `Show the differences between local and remote versions of files.\n\nCan show:\n- Unified diff format (default)\n- Just the remote content (showRemote=true)\n\nUseful for reviewing changes before pull or push.\n\nIf no file is specified, shows diffs for all changed files.`,\n diffSchema,\n async (params: { tenant?: string; file?: string; showRemote?: boolean }) => {\n const { tenant: tenantArg, file, showRemote } = params;\n const checkout = getCurrentCheckout();\n const tenant = tenantArg || checkout?.tenant;\n const organisation = tenantArg || checkout?.organisation;\n\n if (!tenant || !organisation) {\n return tenantRequiredResponse();\n }\n\n const clientResult = await getFarseerClientWithFallback(organisation, tenant);\n if (!clientResult) {\n return authRequiredResponse(tenant);\n }\n\n try {\n const syncService = new SyncService(organisation, clientResult.client);\n\n if (file) {\n // Single file diff\n const { localContent, remoteContent } = await syncService.getFileDiff(file);\n\n if (showRemote) {\n return successResponse({\n file,\n remoteContent: remoteContent || '(file does not exist on remote)',\n });\n }\n\n const diff = createPatch(\n file,\n remoteContent || '',\n localContent || '',\n 'remote',\n 'local'\n );\n\n return successResponse({\n file,\n localExists: localContent !== null,\n remoteExists: remoteContent !== null,\n diff,\n });\n } else {\n // All changed files\n const status = await syncService.getStatus();\n const changedFiles = [\n ...status.modifiedLocally,\n ...status.modifiedRemotely,\n ...status.onlyLocal,\n ...status.onlyRemote,\n ];\n\n const diffs: Array<{\n file: string;\n localExists: boolean;\n remoteExists: boolean;\n diff: string;\n }> = [];\n\n for (const f of changedFiles.slice(0, 10)) {\n // Limit to 10 files\n const { localContent, remoteContent } = await syncService.getFileDiff(f);\n const diff = createPatch(f, remoteContent || '', localContent || '', 'remote', 'local');\n diffs.push({\n file: f,\n localExists: localContent !== null,\n remoteExists: remoteContent !== null,\n diff,\n });\n }\n\n return successResponse({\n totalChangedFiles: changedFiles.length,\n diffs,\n note:\n changedFiles.length > 10\n ? `Showing first 10 of ${changedFiles.length} changed files`\n : undefined,\n });\n }\n } catch (error) {\n return errorResponse(\n `Diff failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n );\n }\n }\n );\n\n // farseer_list_files - List remote files\n server.tool(\n 'farseer_list_files',\n `List all files stored on the remote Farseer instance in the Files/ folder.\n\nBy default shows only script files (.ts, .js, .mjs, .cjs).\nUse all=true to show all files including images, data files, etc.\n\nReturns file paths relative to the Files/ folder.`,\n listFilesSchema,\n async (params: { tenant?: string; all?: boolean }) => {\n const { tenant: tenantArg, all } = params;\n const checkout = getCurrentCheckout();\n const tenant = tenantArg || checkout?.tenant;\n const organisation = tenantArg || checkout?.organisation;\n\n if (!tenant || !organisation) {\n return tenantRequiredResponse();\n }\n\n const clientResult = await getFarseerClientWithFallback(organisation, tenant);\n if (!clientResult) {\n return authRequiredResponse(tenant);\n }\n\n try {\n let files = await clientResult.client.listFiles();\n\n // Filter to scripts unless --all\n if (!all) {\n const scriptExtensions = ['.ts', '.js', '.mjs', '.cjs'];\n files = files.filter((f) =>\n scriptExtensions.some((ext) => f.name.toLowerCase().endsWith(ext))\n );\n }\n\n // Group by directory\n const byDirectory: Record<string, string[]> = {};\n for (const file of files) {\n const dir = file.path.includes('/') ? file.path.split('/').slice(0, -1).join('/') : '.';\n if (!byDirectory[dir]) {\n byDirectory[dir] = [];\n }\n byDirectory[dir].push(file.name);\n }\n\n return successResponse({\n tenant,\n totalFiles: files.length,\n files: files.map((f) => ({\n name: f.name,\n path: f.path,\n reference: f.reference,\n })),\n byDirectory,\n });\n } catch (error) {\n return errorResponse(\n `List files failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'NETWORK_ERROR'\n );\n }\n }\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * MCP Utility Functions
3
+ *
4
+ * Helper functions for MCP tools including tenant resolution and response formatting.
5
+ */
6
+ import { IFarseerClient } from '../../services/farseerFactory';
7
+ /**
8
+ * Resolve tenant from argument or checkout state
9
+ */
10
+ export declare function resolveTenant(tenantArg?: string): string | null;
11
+ /**
12
+ * Resolve organisation from argument or checkout state
13
+ */
14
+ export declare function resolveOrganisation(orgArg?: string, tenantArg?: string): string | null;
15
+ /**
16
+ * Get authenticated Farseer client
17
+ */
18
+ export declare function getClient(tenant: string, tenantId?: string): Promise<IFarseerClient | null>;
19
+ /**
20
+ * Create a success response
21
+ */
22
+ export declare function successResponse(data: Record<string, unknown>): {
23
+ content: Array<{
24
+ type: 'text';
25
+ text: string;
26
+ }>;
27
+ };
28
+ /**
29
+ * Create an error response
30
+ */
31
+ export declare function errorResponse(message: string, errorCode?: 'AUTH_REQUIRED' | 'NOT_FOUND' | 'NETWORK_ERROR' | 'VALIDATION_ERROR' | 'UNKNOWN'): {
32
+ content: Array<{
33
+ type: 'text';
34
+ text: string;
35
+ }>;
36
+ isError: true;
37
+ };
38
+ /**
39
+ * Create auth required error response
40
+ */
41
+ export declare function authRequiredResponse(tenant?: string): {
42
+ content: Array<{
43
+ type: 'text';
44
+ text: string;
45
+ }>;
46
+ isError: true;
47
+ };
48
+ /**
49
+ * Create tenant required error response
50
+ */
51
+ export declare function tenantRequiredResponse(): {
52
+ content: Array<{
53
+ type: 'text';
54
+ text: string;
55
+ }>;
56
+ isError: true;
57
+ };
58
+ /**
59
+ * Get auth status info
60
+ */
61
+ export declare function getAuthStatus(): {
62
+ jwtValid: boolean;
63
+ jwtExpiresAt?: string;
64
+ currentCheckout?: {
65
+ organisation: string;
66
+ tenant: string;
67
+ };
68
+ configuredTenants: string[];
69
+ };
@@ -0,0 +1,113 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var helpers_exports = {};
19
+ __export(helpers_exports, {
20
+ authRequiredResponse: () => authRequiredResponse,
21
+ errorResponse: () => errorResponse,
22
+ getAuthStatus: () => getAuthStatus,
23
+ getClient: () => getClient,
24
+ resolveOrganisation: () => resolveOrganisation,
25
+ resolveTenant: () => resolveTenant,
26
+ successResponse: () => successResponse,
27
+ tenantRequiredResponse: () => tenantRequiredResponse
28
+ });
29
+ module.exports = __toCommonJS(helpers_exports);
30
+ var import_configService = require("../../services/configService");
31
+ var import_farseerFactory = require("../../services/farseerFactory");
32
+ function resolveTenant(tenantArg) {
33
+ if (tenantArg) {
34
+ return tenantArg;
35
+ }
36
+ return (0, import_configService.getCurrentTenant)() || null;
37
+ }
38
+ function resolveOrganisation(orgArg, tenantArg) {
39
+ if (orgArg) {
40
+ return orgArg;
41
+ }
42
+ if (tenantArg) {
43
+ return tenantArg;
44
+ }
45
+ const checkout = (0, import_configService.getCurrentCheckout)();
46
+ return checkout?.organisation || null;
47
+ }
48
+ async function getClient(tenant, tenantId) {
49
+ const result = await (0, import_farseerFactory.getFarseerClientWithFallback)(tenant, tenantId);
50
+ return result?.client || null;
51
+ }
52
+ function successResponse(data) {
53
+ return {
54
+ content: [
55
+ {
56
+ type: "text",
57
+ text: JSON.stringify({ success: true, ...data }, null, 2)
58
+ }
59
+ ]
60
+ };
61
+ }
62
+ function errorResponse(message, errorCode) {
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: JSON.stringify(
68
+ {
69
+ success: false,
70
+ error: message,
71
+ errorCode: errorCode || "UNKNOWN"
72
+ },
73
+ null,
74
+ 2
75
+ )
76
+ }
77
+ ],
78
+ isError: true
79
+ };
80
+ }
81
+ function authRequiredResponse(tenant) {
82
+ const message = tenant ? `Authentication required for tenant "${tenant}". Run "farseer login" to authenticate.` : 'Authentication required. Run "farseer login" to authenticate.';
83
+ return errorResponse(message, "AUTH_REQUIRED");
84
+ }
85
+ function tenantRequiredResponse() {
86
+ return errorResponse(
87
+ 'No tenant specified. Either provide tenant parameter or run "farseer checkout <tenant>" first.',
88
+ "VALIDATION_ERROR"
89
+ );
90
+ }
91
+ function getAuthStatus() {
92
+ const auth = (0, import_configService.getUserAuth)();
93
+ const checkout = (0, import_configService.getCurrentCheckout)();
94
+ const credentials = (0, import_configService.listCredentials)();
95
+ return {
96
+ jwtValid: (0, import_configService.isUserAuthValid)(),
97
+ jwtExpiresAt: auth?.expiresAt,
98
+ currentCheckout: checkout,
99
+ configuredTenants: Object.keys(credentials)
100
+ };
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ authRequiredResponse,
105
+ errorResponse,
106
+ getAuthStatus,
107
+ getClient,
108
+ resolveOrganisation,
109
+ resolveTenant,
110
+ successResponse,
111
+ tenantRequiredResponse
112
+ });
113
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/utils/helpers.ts"],
4
+ "sourcesContent": ["/**\n * MCP Utility Functions\n *\n * Helper functions for MCP tools including tenant resolution and response formatting.\n */\n\nimport {\n getCurrentCheckout,\n getCurrentTenant,\n getUserAuth,\n isUserAuthValid,\n listCredentials,\n} from '../../services/configService';\nimport { getFarseerClientWithFallback, IFarseerClient } from '../../services/farseerFactory';\n\n/**\n * Resolve tenant from argument or checkout state\n */\nexport function resolveTenant(tenantArg?: string): string | null {\n if (tenantArg) {\n return tenantArg;\n }\n return getCurrentTenant() || null;\n}\n\n/**\n * Resolve organisation from argument or checkout state\n */\nexport function resolveOrganisation(orgArg?: string, tenantArg?: string): string | null {\n if (orgArg) {\n return orgArg;\n }\n if (tenantArg) {\n // If tenant specified but not org, assume org = tenant\n return tenantArg;\n }\n const checkout = getCurrentCheckout();\n return checkout?.organisation || null;\n}\n\n/**\n * Get authenticated Farseer client\n */\nexport async function getClient(tenant: string, tenantId?: string): Promise<IFarseerClient | null> {\n const result = await getFarseerClientWithFallback(tenant, tenantId);\n return result?.client || null;\n}\n\n/**\n * Create a success response\n */\nexport function successResponse(data: Record<string, unknown>): { content: Array<{ type: 'text'; text: string }> } {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ success: true, ...data }, null, 2),\n },\n ],\n };\n}\n\n/**\n * Create an error response\n */\nexport function errorResponse(\n message: string,\n errorCode?: 'AUTH_REQUIRED' | 'NOT_FOUND' | 'NETWORK_ERROR' | 'VALIDATION_ERROR' | 'UNKNOWN'\n): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: false,\n error: message,\n errorCode: errorCode || 'UNKNOWN',\n },\n null,\n 2\n ),\n },\n ],\n isError: true,\n };\n}\n\n/**\n * Create auth required error response\n */\nexport function authRequiredResponse(tenant?: string): {\n content: Array<{ type: 'text'; text: string }>;\n isError: true;\n} {\n const message = tenant\n ? `Authentication required for tenant \"${tenant}\". Run \"farseer login\" to authenticate.`\n : 'Authentication required. Run \"farseer login\" to authenticate.';\n\n return errorResponse(message, 'AUTH_REQUIRED');\n}\n\n/**\n * Create tenant required error response\n */\nexport function tenantRequiredResponse(): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return errorResponse(\n 'No tenant specified. Either provide tenant parameter or run \"farseer checkout <tenant>\" first.',\n 'VALIDATION_ERROR'\n );\n}\n\n/**\n * Get auth status info\n */\nexport function getAuthStatus(): {\n jwtValid: boolean;\n jwtExpiresAt?: string;\n currentCheckout?: { organisation: string; tenant: string };\n configuredTenants: string[];\n} {\n const auth = getUserAuth();\n const checkout = getCurrentCheckout();\n const credentials = listCredentials();\n\n return {\n jwtValid: isUserAuthValid(),\n jwtExpiresAt: auth?.expiresAt,\n currentCheckout: checkout,\n configuredTenants: Object.keys(credentials),\n };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,2BAMO;AACP,4BAA6D;AAKtD,SAAS,cAAc,WAAmC;AAC7D,MAAI,WAAW;AACX,WAAO;AAAA,EACX;AACA,aAAO,uCAAiB,KAAK;AACjC;AAKO,SAAS,oBAAoB,QAAiB,WAAmC;AACpF,MAAI,QAAQ;AACR,WAAO;AAAA,EACX;AACA,MAAI,WAAW;AAEX,WAAO;AAAA,EACX;AACA,QAAM,eAAW,yCAAmB;AACpC,SAAO,UAAU,gBAAgB;AACrC;AAKA,eAAsB,UAAU,QAAgB,UAAmD;AAC/F,QAAM,SAAS,UAAM,oDAA6B,QAAQ,QAAQ;AAClE,SAAO,QAAQ,UAAU;AAC7B;AAKO,SAAS,gBAAgB,MAAmF;AAC/G,SAAO;AAAA,IACH,SAAS;AAAA,MACL;AAAA,QACI,MAAM;AAAA,QACN,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAAA,MAC5D;AAAA,IACJ;AAAA,EACJ;AACJ;AAKO,SAAS,cACZ,SACA,WACiE;AACjE,SAAO;AAAA,IACH,SAAS;AAAA,MACL;AAAA,QACI,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,UACP;AAAA,YACI,SAAS;AAAA,YACT,OAAO;AAAA,YACP,WAAW,aAAa;AAAA,UAC5B;AAAA,UACA;AAAA,UACA;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,EACb;AACJ;AAKO,SAAS,qBAAqB,QAGnC;AACE,QAAM,UAAU,SACV,uCAAuC,MAAM,4CAC7C;AAEN,SAAO,cAAc,SAAS,eAAe;AACjD;AAKO,SAAS,yBAA4F;AACxG,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;AAKO,SAAS,gBAKd;AACE,QAAM,WAAO,kCAAY;AACzB,QAAM,eAAW,yCAAmB;AACpC,QAAM,kBAAc,sCAAgB;AAEpC,SAAO;AAAA,IACH,cAAU,sCAAgB;AAAA,IAC1B,cAAc,MAAM;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB,OAAO,KAAK,WAAW;AAAA,EAC9C;AACJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,75 @@
1
+ import { IFarseerClient } from './farseerFactory';
2
+ export interface LocalAppConfig {
3
+ name: string;
4
+ description: string;
5
+ entrypoint: string | null;
6
+ scripts: string[];
7
+ arguments: {
8
+ name: string;
9
+ defaultValue: string;
10
+ }[];
11
+ _remote?: {
12
+ id: number;
13
+ reference: string;
14
+ };
15
+ }
16
+ export interface AppSyncResult {
17
+ created: string[];
18
+ updated: string[];
19
+ deleted: string[];
20
+ unchanged: string[];
21
+ }
22
+ export interface AppSyncStatus {
23
+ newLocal: string[];
24
+ newRemote: string[];
25
+ modified: string[];
26
+ synced: string[];
27
+ }
28
+ /**
29
+ * Service for syncing app configurations between local JSON files and remote Farseer instance
30
+ */
31
+ export declare class AppSyncService {
32
+ private api;
33
+ private appsDir;
34
+ constructor(tenant: string, api: IFarseerClient);
35
+ /**
36
+ * Get filename for an app (keep original name, just sanitize for filesystem)
37
+ */
38
+ private getAppFilename;
39
+ /**
40
+ * Load all local app configs
41
+ */
42
+ loadLocalApps(): Map<string, LocalAppConfig>;
43
+ /**
44
+ * Save a local app config
45
+ */
46
+ saveLocalApp(config: LocalAppConfig): void;
47
+ /**
48
+ * Delete a local app config
49
+ */
50
+ deleteLocalApp(name: string): boolean;
51
+ /**
52
+ * Convert remote app to local config format
53
+ */
54
+ private remoteToLocal;
55
+ /**
56
+ * Check if local and remote app configs are equivalent
57
+ */
58
+ private areAppsEqual;
59
+ /**
60
+ * Pull apps from remote and save locally
61
+ */
62
+ pull(): Promise<AppSyncResult>;
63
+ /**
64
+ * Push local apps to remote
65
+ */
66
+ push(): Promise<AppSyncResult>;
67
+ /**
68
+ * Build update payload for API
69
+ */
70
+ private buildUpdatePayload;
71
+ /**
72
+ * Get sync status without making changes
73
+ */
74
+ getStatus(): Promise<AppSyncStatus>;
75
+ }