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,166 @@
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 checkout_exports = {};
29
+ __export(checkout_exports, {
30
+ registerCheckoutCommand: () => registerCheckoutCommand
31
+ });
32
+ module.exports = __toCommonJS(checkout_exports);
33
+ var import_chalk = __toESM(require("chalk"));
34
+ var import_logger = require("../utils/logger");
35
+ var import_configService = require("../services/configService");
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
+ var path = __toESM(require("path"));
44
+ function registerCheckoutCommand(program) {
45
+ program.command("checkout [first] [second]").description("Set default tenant for commands (runs auth check and pull)").option("--no-pull", "Skip automatic pull").option("--no-git", "Skip git operations during pull").option("--clear", "Clear current checkout").action(async (first, second, options) => {
46
+ if (options.clear) {
47
+ (0, import_configService.clearCurrentTenant)();
48
+ import_logger.logger.success("Checkout cleared. You now need to specify tenant for each command.");
49
+ return;
50
+ }
51
+ if (!first) {
52
+ const current = (0, import_configService.getCurrentCheckout)();
53
+ if (current) {
54
+ if (current.organisation === current.tenant) {
55
+ import_logger.logger.info(`Currently checked out: ${import_chalk.default.bold(current.tenant)}`);
56
+ } else {
57
+ import_logger.logger.info(`Currently checked out: ${import_chalk.default.bold(current.tenant)} (org: ${import_chalk.default.bold(current.organisation)})`);
58
+ }
59
+ import_logger.logger.dim('Run "farseer checkout <tenant>" to switch tenants.');
60
+ import_logger.logger.dim('Run "farseer checkout --clear" to clear checkout.');
61
+ } else {
62
+ import_logger.logger.info("No tenant currently checked out.");
63
+ import_logger.logger.dim('Run "farseer checkout <tenant>" to set a default tenant.');
64
+ import_logger.logger.dim('Run "farseer checkout <org> <tenant>" if organisation and tenant differ.');
65
+ }
66
+ return;
67
+ }
68
+ const organisation = second ? first : first;
69
+ const tenant = second || first;
70
+ import_logger.logger.info(`Checking out tenant: ${import_chalk.default.bold(tenant)} (org: ${import_chalk.default.bold(organisation)})...`);
71
+ console.log();
72
+ import_logger.logger.info("Verifying authentication...");
73
+ const clientResult = await (0, import_farseerFactory.getFarseerClientWithFallback)(organisation, tenant);
74
+ if (!clientResult) {
75
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
76
+ process.exit(1);
77
+ }
78
+ const authLabel = clientResult.authType === "apiKey" ? "API key" : "browser login";
79
+ import_logger.logger.success(`Authenticated (using ${authLabel})`);
80
+ (0, import_configService.setCurrentCheckout)(organisation, tenant);
81
+ if (options.pull) {
82
+ console.log();
83
+ import_logger.logger.info("Pulling latest files and apps...");
84
+ const gitService = new import_gitService.GitService();
85
+ const syncService = new import_syncService.SyncService(tenant, clientResult.client);
86
+ const tenantDir = (0, import_helpers.getTenantDir)(tenant);
87
+ (0, import_helpers.ensureDirectoryExists)(tenantDir);
88
+ const gitEnabled = options.git && !process.env.FARSEER_NO_GIT;
89
+ try {
90
+ if (gitEnabled) {
91
+ const gitPullResult = await gitService.pull();
92
+ if (!gitPullResult.success) {
93
+ import_logger.logger.warning("Git pull failed: " + gitPullResult.message);
94
+ }
95
+ }
96
+ const packageJsonPath = path.join(tenantDir, "package.json");
97
+ if (!fs.existsSync(packageJsonPath)) {
98
+ createDefaultPackageJson(tenant, packageJsonPath);
99
+ }
100
+ const result = await syncService.pull({ all: false });
101
+ import_logger.logger.dim(`Files: +${result.downloaded.length} -${result.deleted.length} (${result.unchanged.length} unchanged)`);
102
+ const appSyncService = new import_appSyncService.AppSyncService(tenant, clientResult.client);
103
+ const appResult = await appSyncService.pull();
104
+ import_logger.logger.dim(`Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length} (${appResult.unchanged.length} unchanged)`);
105
+ if (gitEnabled) {
106
+ const hasChanges = result.downloaded.length > 0 || result.deleted.length > 0 || appResult.created.length > 0 || appResult.updated.length > 0 || appResult.deleted.length > 0;
107
+ if (hasChanges) {
108
+ const appsPath = `apps/${tenant}`;
109
+ await gitService.add([appsPath]);
110
+ const commitMessage = `[${tenant}] Checkout sync
111
+
112
+ Files: +${result.downloaded.length} -${result.deleted.length}
113
+ Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}
114
+
115
+ \u{1F916} Generated with Farseer CLI`;
116
+ await gitService.commit(commitMessage, import_constants.CLI_GIT_AUTHOR);
117
+ await gitService.push();
118
+ }
119
+ }
120
+ import_logger.logger.success("Pull complete!");
121
+ } catch (error) {
122
+ import_logger.logger.warning("Pull failed, but checkout is complete.");
123
+ if (error instanceof Error) {
124
+ import_logger.logger.dim(error.message);
125
+ }
126
+ }
127
+ }
128
+ console.log();
129
+ import_logger.logger.success(`Tenant ${import_chalk.default.bold(tenant)} is now checked out.`);
130
+ import_logger.logger.dim("You can now run commands without specifying the tenant:");
131
+ import_logger.logger.dim(" farseer status");
132
+ import_logger.logger.dim(" farseer model --variables");
133
+ import_logger.logger.dim(" farseer apps");
134
+ import_logger.logger.dim(" farseer push");
135
+ });
136
+ }
137
+ function createDefaultPackageJson(tenant, packageJsonPath) {
138
+ const packageJson = {
139
+ name: `farseer-${tenant}`,
140
+ version: "1.0.0",
141
+ description: `Farseer scripts for ${tenant}`,
142
+ type: "module",
143
+ scripts: {
144
+ build: "tsc"
145
+ },
146
+ dependencies: {
147
+ "farseer-client": "https://storage.googleapis.com/farseer-remote-jobs-results/farseer-client/release-1.4.5.tar",
148
+ arquero: "^7.0.1",
149
+ xlsx: "^0.18.5",
150
+ xmldom: "^0.6.0"
151
+ },
152
+ devDependencies: {
153
+ "@types/node": "^22.5.0",
154
+ "@types/xmldom": "^0.1.34",
155
+ "ts-node": "^10.9.2",
156
+ typescript: "^5.5.4"
157
+ }
158
+ };
159
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
160
+ import_logger.logger.dim(`Created package.json for ${tenant}`);
161
+ }
162
+ // Annotate the CommonJS export names for ESM import in node:
163
+ 0 && (module.exports = {
164
+ registerCheckoutCommand
165
+ });
166
+ //# sourceMappingURL=checkout.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/checkout.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { logger } from '../utils/logger';\nimport { getCurrentCheckout, setCurrentCheckout, clearCurrentTenant, getCurrentOrganisation } from '../services/configService';\nimport { getFarseerClientWithFallback, showLoginPrompt } from '../services/farseerFactory';\nimport { SyncService } from '../services/syncService';\nimport { AppSyncService } from '../services/appSyncService';\nimport { GitService } from '../services/gitService';\nimport { getTenantDir, ensureDirectoryExists } from '../utils/helpers';\nimport { CLI_GIT_AUTHOR } from '../utils/constants';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport function registerCheckoutCommand(program: Command): void {\n program\n .command('checkout [first] [second]')\n .description('Set default tenant for commands (runs auth check and pull)')\n .option('--no-pull', 'Skip automatic pull')\n .option('--no-git', 'Skip git operations during pull')\n .option('--clear', 'Clear current checkout')\n .action(async (first, second, options) => {\n // Handle --clear flag\n if (options.clear) {\n clearCurrentTenant();\n logger.success('Checkout cleared. You now need to specify tenant for each command.');\n return;\n }\n\n // If no arguments specified, show current checkout status\n if (!first) {\n const current = getCurrentCheckout();\n if (current) {\n if (current.organisation === current.tenant) {\n logger.info(`Currently checked out: ${chalk.bold(current.tenant)}`);\n } else {\n logger.info(`Currently checked out: ${chalk.bold(current.tenant)} (org: ${chalk.bold(current.organisation)})`);\n }\n logger.dim('Run \"farseer checkout <tenant>\" to switch tenants.');\n logger.dim('Run \"farseer checkout --clear\" to clear checkout.');\n } else {\n logger.info('No tenant currently checked out.');\n logger.dim('Run \"farseer checkout <tenant>\" to set a default tenant.');\n logger.dim('Run \"farseer checkout <org> <tenant>\" if organisation and tenant differ.');\n }\n return;\n }\n\n // Determine organisation and tenant\n // If two arguments: first=organisation, second=tenant\n // If one argument: organisation=tenant=first\n const organisation = second ? first : first;\n const tenant = second || first;\n\n logger.info(`Checking out tenant: ${chalk.bold(tenant)} (org: ${chalk.bold(organisation)})...`);\n console.log();\n\n // Step 1: Verify authentication\n logger.info('Verifying authentication...');\n const clientResult = await getFarseerClientWithFallback(organisation, tenant);\n\n if (!clientResult) {\n showLoginPrompt(tenant);\n process.exit(1);\n }\n\n const authLabel = clientResult.authType === 'apiKey' ? 'API key' : 'browser login';\n logger.success(`Authenticated (using ${authLabel})`);\n\n // Step 2: Set as current checkout\n setCurrentCheckout(organisation, tenant);\n\n // Step 3: Auto-pull (unless --no-pull)\n if (options.pull) {\n console.log();\n logger.info('Pulling latest files and apps...');\n\n const gitService = new GitService();\n const syncService = new SyncService(tenant, clientResult.client);\n const tenantDir = getTenantDir(tenant);\n ensureDirectoryExists(tenantDir);\n\n const gitEnabled = options.git && !process.env.FARSEER_NO_GIT;\n\n try {\n // Git pull first\n if (gitEnabled) {\n const gitPullResult = await gitService.pull();\n if (!gitPullResult.success) {\n logger.warning('Git pull failed: ' + gitPullResult.message);\n }\n }\n\n // Ensure package.json exists\n const packageJsonPath = path.join(tenantDir, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n createDefaultPackageJson(tenant, packageJsonPath);\n }\n\n // Pull files (scripts only by default)\n const result = await syncService.pull({ all: false });\n logger.dim(`Files: +${result.downloaded.length} -${result.deleted.length} (${result.unchanged.length} unchanged)`);\n\n // Pull apps\n const appSyncService = new AppSyncService(tenant, clientResult.client);\n const appResult = await appSyncService.pull();\n logger.dim(`Apps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length} (${appResult.unchanged.length} unchanged)`);\n\n // Git commit if there were changes\n if (gitEnabled) {\n const hasChanges = result.downloaded.length > 0 || result.deleted.length > 0 ||\n appResult.created.length > 0 || appResult.updated.length > 0 || appResult.deleted.length > 0;\n\n if (hasChanges) {\n const appsPath = `apps/${tenant}`;\n await gitService.add([appsPath]);\n\n const commitMessage = `[${tenant}] Checkout sync\n\nFiles: +${result.downloaded.length} -${result.deleted.length}\nApps: +${appResult.created.length} ~${appResult.updated.length} -${appResult.deleted.length}\n\n\uD83E\uDD16 Generated with Farseer CLI`;\n\n await gitService.commit(commitMessage, CLI_GIT_AUTHOR);\n await gitService.push();\n }\n }\n\n logger.success('Pull complete!');\n } catch (error) {\n logger.warning('Pull failed, but checkout is complete.');\n if (error instanceof Error) {\n logger.dim(error.message);\n }\n }\n }\n\n // Final message\n console.log();\n logger.success(`Tenant ${chalk.bold(tenant)} is now checked out.`);\n logger.dim('You can now run commands without specifying the tenant:');\n logger.dim(' farseer status');\n logger.dim(' farseer model --variables');\n logger.dim(' farseer apps');\n logger.dim(' farseer push');\n });\n}\n\nfunction createDefaultPackageJson(tenant: string, packageJsonPath: string): void {\n const packageJson = {\n name: `farseer-${tenant}`,\n version: '1.0.0',\n description: `Farseer scripts for ${tenant}`,\n type: 'module',\n scripts: {\n build: 'tsc',\n },\n dependencies: {\n 'farseer-client': 'https://storage.googleapis.com/farseer-remote-jobs-results/farseer-client/release-1.4.5.tar',\n arquero: '^7.0.1',\n xlsx: '^0.18.5',\n xmldom: '^0.6.0',\n },\n devDependencies: {\n '@types/node': '^22.5.0',\n '@types/xmldom': '^0.1.34',\n 'ts-node': '^10.9.2',\n typescript: '^5.5.4',\n },\n };\n\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8');\n logger.dim(`Created package.json for ${tenant}`);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["chalk"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerConfigCommand(program: Command): void;
@@ -0,0 +1,139 @@
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 config_exports = {};
19
+ __export(config_exports, {
20
+ registerConfigCommand: () => registerConfigCommand
21
+ });
22
+ module.exports = __toCommonJS(config_exports);
23
+ var import_logger = require("../utils/logger");
24
+ var import_configService = require("../services/configService");
25
+ var import_farseerService = require("../services/farseerService");
26
+ var import_helpers = require("../utils/helpers");
27
+ function registerConfigCommand(program) {
28
+ const configCmd = program.command("config").description("Manage Farseer CLI configuration").addHelpText("after", `
29
+ Commands:
30
+ set <tenant> Set API key for a tenant
31
+ remove <tenant> Remove credentials for a tenant
32
+ list List all configured tenants
33
+ show <tenant> Show full credentials (including API key)
34
+ test <tenant> Test connection to a tenant
35
+
36
+ Examples:
37
+ $ farseer config set mycompany --api-key xxx
38
+ $ farseer config set mycompany --api-key xxx --org myorg
39
+ $ farseer config list
40
+ $ farseer config test mycompany
41
+ `);
42
+ configCmd.command("set <tenant>").description("Set credentials for a tenant (use --org if org differs from tenant)").requiredOption("--api-key <key>", "API key for the tenant").option("--org <organisation>", "Organisation name if different from tenant (e.g., --org mycompany)").option("--base-path <url>", "Custom base path (overrides organisation)").option("--no-test", "Skip connection test").action(async (tenant, options) => {
43
+ const organisation = options.org || tenant;
44
+ const basePath = options.basePath || (0, import_configService.generateBasePath)(organisation);
45
+ const apiKey = options.apiKey;
46
+ const credential = {
47
+ type: "apiKey",
48
+ tenantId: tenant,
49
+ apiKey,
50
+ basePath
51
+ };
52
+ if (options.test !== false) {
53
+ import_logger.logger.info("Testing connection...");
54
+ const service = new import_farseerService.FarseerService(credential);
55
+ const isConnected = await service.testConnection();
56
+ if (!isConnected) {
57
+ import_logger.logger.error("Connection failed. Please check your credentials.");
58
+ import_logger.logger.dim(`Tried to connect to: ${basePath}`);
59
+ process.exit(1);
60
+ }
61
+ }
62
+ (0, import_configService.setCredential)(tenant, credential);
63
+ import_logger.logger.success(`Credentials saved for tenant: ${tenant}`);
64
+ import_logger.logger.table([
65
+ { label: "Tenant ID", value: tenant },
66
+ { label: "Base Path", value: basePath },
67
+ { label: "API Key", value: apiKey.substring(0, 8) + "..." }
68
+ ]);
69
+ });
70
+ configCmd.command("remove <tenant>").description("Remove credentials for a tenant").action((tenant) => {
71
+ const removed = (0, import_configService.removeCredential)(tenant);
72
+ if (removed) {
73
+ import_logger.logger.success(`Removed credentials for tenant: ${tenant}`);
74
+ } else {
75
+ import_logger.logger.warning(`No credentials found for tenant: ${tenant}`);
76
+ }
77
+ });
78
+ configCmd.command("list").description("List all configured tenants").action(() => {
79
+ const credentials = (0, import_configService.listCredentials)();
80
+ const tenants = Object.keys(credentials);
81
+ if (tenants.length === 0) {
82
+ import_logger.logger.info("No tenants configured.");
83
+ import_logger.logger.dim('Use "farseer config set <tenant> --api-key <key>" to add one.');
84
+ return;
85
+ }
86
+ import_logger.logger.header("Configured Tenants");
87
+ for (const tenant of tenants) {
88
+ const cred = credentials[tenant];
89
+ console.log(` ${tenant}`);
90
+ import_logger.logger.dim(` Base: ${cred.basePath}`);
91
+ import_logger.logger.dim(` Key: ${cred.apiKey.substring(0, 8)}...`);
92
+ console.log();
93
+ }
94
+ });
95
+ configCmd.command("show <tenant>").description("Show full credentials for a tenant (including API key)").action((tenant) => {
96
+ const credentials = (0, import_configService.listCredentials)();
97
+ const cred = credentials[tenant];
98
+ if (!cred) {
99
+ import_logger.logger.error(`No credentials found for tenant: ${tenant}`);
100
+ import_logger.logger.dim((0, import_helpers.getCredentialsHint)(tenant));
101
+ process.exit(1);
102
+ }
103
+ import_logger.logger.header(`Credentials for ${tenant}`);
104
+ import_logger.logger.table([
105
+ { label: "Tenant ID", value: tenant },
106
+ { label: "Base Path", value: cred.basePath },
107
+ { label: "API Key", value: cred.apiKey }
108
+ ]);
109
+ });
110
+ configCmd.command("test <tenant>").description("Test connection to a tenant").action(async (tenant) => {
111
+ const credentials = (0, import_configService.listCredentials)();
112
+ const cred = credentials[tenant];
113
+ if (!cred) {
114
+ import_logger.logger.error(`No credentials found for tenant: ${tenant}`);
115
+ import_logger.logger.dim((0, import_helpers.getCredentialsHint)(tenant));
116
+ process.exit(1);
117
+ }
118
+ import_logger.logger.info(`Testing connection to ${tenant}...`);
119
+ const service = new import_farseerService.FarseerService(cred);
120
+ const isConnected = await service.testConnection();
121
+ if (isConnected) {
122
+ import_logger.logger.success(`Connection successful!`);
123
+ const filesFolder = await service.getFilesFolder();
124
+ if (filesFolder) {
125
+ import_logger.logger.dim("Files folder found.");
126
+ } else {
127
+ import_logger.logger.warning("Files folder not found. It will be created on first push.");
128
+ }
129
+ } else {
130
+ import_logger.logger.error("Connection failed.");
131
+ process.exit(1);
132
+ }
133
+ });
134
+ }
135
+ // Annotate the CommonJS export names for ESM import in node:
136
+ 0 && (module.exports = {
137
+ registerConfigCommand
138
+ });
139
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/config.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport { logger } from '../utils/logger';\nimport {\n setCredential,\n removeCredential,\n listCredentials,\n generateBasePath,\n ApiKeyCredential,\n} from '../services/configService';\nimport { FarseerService } from '../services/farseerService';\nimport { getCredentialsHint } from '../utils/helpers';\n\nexport function registerConfigCommand(program: Command): void {\n const configCmd = program\n .command('config')\n .description('Manage Farseer CLI configuration')\n .addHelpText('after', `\nCommands:\n set <tenant> Set API key for a tenant\n remove <tenant> Remove credentials for a tenant\n list List all configured tenants\n show <tenant> Show full credentials (including API key)\n test <tenant> Test connection to a tenant\n\nExamples:\n $ farseer config set mycompany --api-key xxx\n $ farseer config set mycompany --api-key xxx --org myorg\n $ farseer config list\n $ farseer config test mycompany\n`);\n\n configCmd\n .command('set <tenant>')\n .description('Set credentials for a tenant (use --org if org differs from tenant)')\n .requiredOption('--api-key <key>', 'API key for the tenant')\n .option('--org <organisation>', 'Organisation name if different from tenant (e.g., --org mycompany)')\n .option('--base-path <url>', 'Custom base path (overrides organisation)')\n .option('--no-test', 'Skip connection test')\n .action(async (tenant, options) => {\n const organisation = options.org || tenant;\n const basePath = options.basePath || generateBasePath(organisation);\n const apiKey = options.apiKey;\n\n const credential: ApiKeyCredential = {\n type: 'apiKey',\n tenantId: tenant,\n apiKey: apiKey,\n basePath: basePath,\n };\n\n if (options.test !== false) {\n logger.info('Testing connection...');\n const service = new FarseerService(credential);\n const isConnected = await service.testConnection();\n\n if (!isConnected) {\n logger.error('Connection failed. Please check your credentials.');\n logger.dim(`Tried to connect to: ${basePath}`);\n process.exit(1);\n }\n }\n\n setCredential(tenant, credential);\n logger.success(`Credentials saved for tenant: ${tenant}`);\n logger.table([\n { label: 'Tenant ID', value: tenant },\n { label: 'Base Path', value: basePath },\n { label: 'API Key', value: apiKey.substring(0, 8) + '...' },\n ]);\n });\n\n configCmd\n .command('remove <tenant>')\n .description('Remove credentials for a tenant')\n .action((tenant) => {\n const removed = removeCredential(tenant);\n if (removed) {\n logger.success(`Removed credentials for tenant: ${tenant}`);\n } else {\n logger.warning(`No credentials found for tenant: ${tenant}`);\n }\n });\n\n configCmd\n .command('list')\n .description('List all configured tenants')\n .action(() => {\n const credentials = listCredentials();\n const tenants = Object.keys(credentials);\n\n if (tenants.length === 0) {\n logger.info('No tenants configured.');\n logger.dim('Use \"farseer config set <tenant> --api-key <key>\" to add one.');\n return;\n }\n\n logger.header('Configured Tenants');\n\n for (const tenant of tenants) {\n const cred = credentials[tenant];\n console.log(` ${tenant}`);\n logger.dim(` Base: ${cred.basePath}`);\n logger.dim(` Key: ${cred.apiKey.substring(0, 8)}...`);\n console.log();\n }\n });\n\n configCmd\n .command('show <tenant>')\n .description('Show full credentials for a tenant (including API key)')\n .action((tenant) => {\n const credentials = listCredentials();\n const cred = credentials[tenant];\n\n if (!cred) {\n logger.error(`No credentials found for tenant: ${tenant}`);\n logger.dim(getCredentialsHint(tenant));\n process.exit(1);\n }\n\n logger.header(`Credentials for ${tenant}`);\n logger.table([\n { label: 'Tenant ID', value: tenant },\n { label: 'Base Path', value: cred.basePath },\n { label: 'API Key', value: cred.apiKey },\n ]);\n });\n\n configCmd\n .command('test <tenant>')\n .description('Test connection to a tenant')\n .action(async (tenant) => {\n const credentials = listCredentials();\n const cred = credentials[tenant];\n\n if (!cred) {\n logger.error(`No credentials found for tenant: ${tenant}`);\n logger.dim(getCredentialsHint(tenant));\n process.exit(1);\n }\n\n logger.info(`Testing connection to ${tenant}...`);\n\n const service = new FarseerService(cred);\n const isConnected = await service.testConnection();\n\n if (isConnected) {\n logger.success(`Connection successful!`);\n\n // Try to get files folder\n const filesFolder = await service.getFilesFolder();\n if (filesFolder) {\n logger.dim('Files folder found.');\n } else {\n logger.warning('Files folder not found. It will be created on first push.');\n }\n } else {\n logger.error('Connection failed.');\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 registerDiffCommand(program: Command): void;
@@ -0,0 +1,183 @@
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 diff_exports = {};
29
+ __export(diff_exports, {
30
+ registerDiffCommand: () => registerDiffCommand
31
+ });
32
+ module.exports = __toCommonJS(diff_exports);
33
+ var import_chalk = __toESM(require("chalk"));
34
+ var Diff = __toESM(require("diff"));
35
+ var import_logger = require("../utils/logger");
36
+ var import_farseerFactory = require("../services/farseerFactory");
37
+ var import_syncService = require("../services/syncService");
38
+ var import_helpers = require("../utils/helpers");
39
+ var fs = __toESM(require("fs"));
40
+ function registerDiffCommand(program) {
41
+ program.command("diff [arg1] [arg2] [file]").description("Show differences between local and remote files\n\nUsage: diff <org> <tenant> [file] OR diff <tenant> [file] (if org is known)").option("--remote", "Show remote version of file(s)").action(async (arg1, arg2, file, options) => {
42
+ let organisation;
43
+ let tenant;
44
+ let actualFile;
45
+ if (arg2 && (arg2.includes("/") || arg2.includes("."))) {
46
+ const resolved = (0, import_helpers.resolveTenantWithOrgMapping)(arg1, void 0);
47
+ organisation = resolved.organisation;
48
+ tenant = resolved.tenant;
49
+ actualFile = arg2;
50
+ } else if (arg2) {
51
+ const resolved = (0, import_helpers.resolveTenantWithOrgMapping)(arg1, arg2);
52
+ organisation = resolved.organisation;
53
+ tenant = resolved.tenant;
54
+ actualFile = file;
55
+ } else {
56
+ const resolved = (0, import_helpers.resolveTenantWithOrgMapping)(arg1, void 0);
57
+ organisation = resolved.organisation;
58
+ tenant = resolved.tenant;
59
+ actualFile = void 0;
60
+ }
61
+ const clientResult = await (0, import_farseerFactory.getFarseerClientWithFallback)(organisation, tenant);
62
+ if (!clientResult) {
63
+ (0, import_farseerFactory.showLoginPrompt)(tenant);
64
+ process.exit(1);
65
+ }
66
+ const filesDir = (0, import_helpers.getTenantFilesDir)(tenant);
67
+ const syncService = new import_syncService.SyncService(tenant, clientResult.client);
68
+ if (actualFile) {
69
+ await showFileDiff(syncService, actualFile, options.remote);
70
+ } else {
71
+ await showAllDiffs(syncService, filesDir);
72
+ }
73
+ });
74
+ }
75
+ async function showFileDiff(syncService, filePath, showRemote) {
76
+ import_logger.logger.info(`Fetching diff for: ${filePath}`);
77
+ console.log();
78
+ try {
79
+ const { localContent, remoteContent } = await syncService.getFileDiff(filePath);
80
+ if (showRemote) {
81
+ if (remoteContent) {
82
+ console.log(remoteContent);
83
+ } else {
84
+ import_logger.logger.warning("File does not exist on remote.");
85
+ }
86
+ return;
87
+ }
88
+ if (!localContent && !remoteContent) {
89
+ import_logger.logger.warning("File does not exist locally or remotely.");
90
+ return;
91
+ }
92
+ if (!localContent) {
93
+ import_logger.logger.info("File only exists on remote (not downloaded).");
94
+ console.log();
95
+ console.log(import_chalk.default.green("--- Remote content ---"));
96
+ console.log(remoteContent);
97
+ return;
98
+ }
99
+ if (!remoteContent) {
100
+ import_logger.logger.info("File only exists locally (new file).");
101
+ console.log();
102
+ console.log(import_chalk.default.yellow("--- Local content ---"));
103
+ console.log(localContent);
104
+ return;
105
+ }
106
+ if (localContent === remoteContent) {
107
+ import_logger.logger.success("Files are identical.");
108
+ return;
109
+ }
110
+ printDiff(filePath, remoteContent, localContent);
111
+ } catch (error) {
112
+ import_logger.logger.error("Failed to get diff.");
113
+ if (error instanceof Error) {
114
+ import_logger.logger.dim(error.message);
115
+ }
116
+ process.exit(1);
117
+ }
118
+ }
119
+ async function showAllDiffs(syncService, filesDir) {
120
+ if (!fs.existsSync(filesDir)) {
121
+ import_logger.logger.warning('Local folder not found. Run "farseer pull" first.');
122
+ return;
123
+ }
124
+ import_logger.logger.info("Fetching status...");
125
+ try {
126
+ const status = await syncService.getStatus();
127
+ const changedFiles = [
128
+ ...status.modifiedLocally,
129
+ ...status.modifiedRemotely.filter((f) => !status.modifiedLocally.includes(f))
130
+ ];
131
+ if (changedFiles.length === 0) {
132
+ import_logger.logger.success("No differences found.");
133
+ return;
134
+ }
135
+ for (const file of changedFiles) {
136
+ console.log();
137
+ console.log(import_chalk.default.bold(`=== ${file} ===`));
138
+ console.log();
139
+ const { localContent, remoteContent } = await syncService.getFileDiff(file);
140
+ if (!localContent && remoteContent) {
141
+ console.log(import_chalk.default.red("File only exists on remote (deleted locally or new on remote)."));
142
+ } else if (localContent && !remoteContent) {
143
+ console.log(import_chalk.default.green("File only exists locally (new file or deleted on remote)."));
144
+ } else if (localContent && remoteContent) {
145
+ if (localContent === remoteContent) {
146
+ console.log(import_chalk.default.green("Files are identical."));
147
+ } else {
148
+ printDiff(file, remoteContent, localContent);
149
+ }
150
+ }
151
+ }
152
+ console.log();
153
+ import_logger.logger.dim(`${changedFiles.length} file(s) with differences.`);
154
+ } catch (error) {
155
+ import_logger.logger.error("Failed to get diffs.");
156
+ if (error instanceof Error) {
157
+ import_logger.logger.dim(error.message);
158
+ }
159
+ process.exit(1);
160
+ }
161
+ }
162
+ function printDiff(fileName, oldContent, newContent) {
163
+ const diff = Diff.createPatch(fileName, oldContent, newContent, "remote", "local");
164
+ const lines = diff.split("\n");
165
+ for (const line of lines) {
166
+ if (line.startsWith("+++") || line.startsWith("---")) {
167
+ console.log(import_chalk.default.bold(line));
168
+ } else if (line.startsWith("+")) {
169
+ console.log(import_chalk.default.green(line));
170
+ } else if (line.startsWith("-")) {
171
+ console.log(import_chalk.default.red(line));
172
+ } else if (line.startsWith("@@")) {
173
+ console.log(import_chalk.default.cyan(line));
174
+ } else {
175
+ console.log(line);
176
+ }
177
+ }
178
+ }
179
+ // Annotate the CommonJS export names for ESM import in node:
180
+ 0 && (module.exports = {
181
+ registerDiffCommand
182
+ });
183
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/diff.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport * as Diff from 'diff';\nimport { logger } from '../utils/logger';\nimport { getFarseerClientWithFallback, showLoginPrompt } from '../services/farseerFactory';\nimport { SyncService } from '../services/syncService';\nimport { getTenantFilesDir, resolveTenantWithOrgMapping } from '../utils/helpers';\nimport * as fs from 'fs';\n\nexport function registerDiffCommand(program: Command): void {\n program\n .command('diff [arg1] [arg2] [file]')\n .description('Show differences between local and remote files\\n\\nUsage: diff <org> <tenant> [file] OR diff <tenant> [file] (if org is known)')\n .option('--remote', 'Show remote version of file(s)')\n .action(async (arg1, arg2, file, options) => {\n // Resolve org/tenant based on number of args\n let organisation: string;\n let tenant: string;\n let actualFile: string | undefined;\n\n // If arg2 looks like a file path (has extension or slash), treat as: diff <tenant> <file>\n if (arg2 && (arg2.includes('/') || arg2.includes('.'))) {\n const resolved = resolveTenantWithOrgMapping(arg1, undefined);\n organisation = resolved.organisation;\n tenant = resolved.tenant;\n actualFile = arg2;\n } else if (arg2) {\n // Two non-file args: diff <org> <tenant> [file]\n const resolved = resolveTenantWithOrgMapping(arg1, arg2);\n organisation = resolved.organisation;\n tenant = resolved.tenant;\n actualFile = file;\n } else {\n // One arg: diff <tenant> [file] or diff [file] (if checked out)\n const resolved = resolveTenantWithOrgMapping(arg1, undefined);\n organisation = resolved.organisation;\n tenant = resolved.tenant;\n actualFile = undefined;\n }\n\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 const syncService = new SyncService(tenant, clientResult.client);\n\n if (actualFile) {\n // Show diff for specific file\n await showFileDiff(syncService, actualFile, options.remote);\n } else {\n // Show diff for all changed files\n await showAllDiffs(syncService, filesDir);\n }\n });\n}\n\nasync function showFileDiff(syncService: SyncService, filePath: string, showRemote: boolean): Promise<void> {\n logger.info(`Fetching diff for: ${filePath}`);\n console.log();\n\n try {\n const { localContent, remoteContent } = await syncService.getFileDiff(filePath);\n\n if (showRemote) {\n if (remoteContent) {\n console.log(remoteContent);\n } else {\n logger.warning('File does not exist on remote.');\n }\n return;\n }\n\n if (!localContent && !remoteContent) {\n logger.warning('File does not exist locally or remotely.');\n return;\n }\n\n if (!localContent) {\n logger.info('File only exists on remote (not downloaded).');\n console.log();\n console.log(chalk.green('--- Remote content ---'));\n console.log(remoteContent);\n return;\n }\n\n if (!remoteContent) {\n logger.info('File only exists locally (new file).');\n console.log();\n console.log(chalk.yellow('--- Local content ---'));\n console.log(localContent);\n return;\n }\n\n if (localContent === remoteContent) {\n logger.success('Files are identical.');\n return;\n }\n\n printDiff(filePath, remoteContent, localContent);\n } catch (error) {\n logger.error('Failed to get diff.');\n if (error instanceof Error) {\n logger.dim(error.message);\n }\n process.exit(1);\n }\n}\n\nasync function showAllDiffs(syncService: SyncService, filesDir: string): Promise<void> {\n if (!fs.existsSync(filesDir)) {\n logger.warning('Local folder not found. Run \"farseer pull\" first.');\n return;\n }\n\n logger.info('Fetching status...');\n\n try {\n const status = await syncService.getStatus();\n\n const changedFiles = [\n ...status.modifiedLocally,\n ...status.modifiedRemotely.filter((f) => !status.modifiedLocally.includes(f)),\n ];\n\n if (changedFiles.length === 0) {\n logger.success('No differences found.');\n return;\n }\n\n for (const file of changedFiles) {\n console.log();\n console.log(chalk.bold(`=== ${file} ===`));\n console.log();\n\n const { localContent, remoteContent } = await syncService.getFileDiff(file);\n\n if (!localContent && remoteContent) {\n console.log(chalk.red('File only exists on remote (deleted locally or new on remote).'));\n } else if (localContent && !remoteContent) {\n console.log(chalk.green('File only exists locally (new file or deleted on remote).'));\n } else if (localContent && remoteContent) {\n if (localContent === remoteContent) {\n console.log(chalk.green('Files are identical.'));\n } else {\n printDiff(file, remoteContent, localContent);\n }\n }\n }\n\n console.log();\n logger.dim(`${changedFiles.length} file(s) with differences.`);\n } catch (error) {\n logger.error('Failed to get diffs.');\n if (error instanceof Error) {\n logger.dim(error.message);\n }\n process.exit(1);\n }\n}\n\nfunction printDiff(fileName: string, oldContent: string, newContent: string): void {\n const diff = Diff.createPatch(fileName, oldContent, newContent, 'remote', 'local');\n\n const lines = diff.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('+++') || line.startsWith('---')) {\n console.log(chalk.bold(line));\n } else if (line.startsWith('+')) {\n console.log(chalk.green(line));\n } else if (line.startsWith('-')) {\n console.log(chalk.red(line));\n } else if (line.startsWith('@@')) {\n console.log(chalk.cyan(line));\n } else {\n console.log(line);\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["chalk"]
7
+ }