@faros-fde-sandbox/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 (48) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +416 -0
  3. package/bin/faros +3 -0
  4. package/lib/commands/logs/index.d.ts +3 -0
  5. package/lib/commands/logs/index.d.ts.map +1 -0
  6. package/lib/commands/logs/index.js +162 -0
  7. package/lib/commands/logs/index.js.map +1 -0
  8. package/lib/commands/sources/index.d.ts +3 -0
  9. package/lib/commands/sources/index.d.ts.map +1 -0
  10. package/lib/commands/sources/index.js +99 -0
  11. package/lib/commands/sources/index.js.map +1 -0
  12. package/lib/commands/sync/ci-cd.d.ts +3 -0
  13. package/lib/commands/sync/ci-cd.d.ts.map +1 -0
  14. package/lib/commands/sync/ci-cd.js +188 -0
  15. package/lib/commands/sync/ci-cd.js.map +1 -0
  16. package/lib/commands/sync/index.d.ts +3 -0
  17. package/lib/commands/sync/index.d.ts.map +1 -0
  18. package/lib/commands/sync/index.js +25 -0
  19. package/lib/commands/sync/index.js.map +1 -0
  20. package/lib/commands/sync/tests.d.ts +3 -0
  21. package/lib/commands/sync/tests.d.ts.map +1 -0
  22. package/lib/commands/sync/tests.js +317 -0
  23. package/lib/commands/sync/tests.js.map +1 -0
  24. package/lib/config/loader.d.ts +5 -0
  25. package/lib/config/loader.d.ts.map +1 -0
  26. package/lib/config/loader.js +137 -0
  27. package/lib/config/loader.js.map +1 -0
  28. package/lib/index.d.ts +3 -0
  29. package/lib/index.d.ts.map +1 -0
  30. package/lib/index.js +73 -0
  31. package/lib/index.js.map +1 -0
  32. package/lib/lib/api/client.d.ts +8 -0
  33. package/lib/lib/api/client.d.ts.map +1 -0
  34. package/lib/lib/api/client.js +43 -0
  35. package/lib/lib/api/client.js.map +1 -0
  36. package/lib/lib/sources/s3.d.ts +19 -0
  37. package/lib/lib/sources/s3.d.ts.map +1 -0
  38. package/lib/lib/sources/s3.js +139 -0
  39. package/lib/lib/sources/s3.js.map +1 -0
  40. package/lib/lib/ui/index.d.ts +32 -0
  41. package/lib/lib/ui/index.d.ts.map +1 -0
  42. package/lib/lib/ui/index.js +88 -0
  43. package/lib/lib/ui/index.js.map +1 -0
  44. package/lib/types/config.d.ts +160 -0
  45. package/lib/types/config.d.ts.map +1 -0
  46. package/lib/types/config.js +40 -0
  47. package/lib/types/config.js.map +1 -0
  48. package/package.json +74 -0
@@ -0,0 +1,317 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.syncTestsCommand = syncTestsCommand;
7
+ const commander_1 = require("commander");
8
+ const test_results_parser_1 = require("test-results-parser");
9
+ const uuid_1 = require("uuid");
10
+ const p_limit_1 = __importDefault(require("p-limit"));
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const loader_1 = require("../../config/loader");
13
+ const client_1 = require("../../lib/api/client");
14
+ const ui_1 = require("../../lib/ui");
15
+ const s3_1 = require("../../lib/sources/s3");
16
+ var TestResultsFormat;
17
+ (function (TestResultsFormat) {
18
+ TestResultsFormat["Cucumber"] = "cucumber";
19
+ TestResultsFormat["JUnit"] = "junit";
20
+ TestResultsFormat["Mocha"] = "mocha";
21
+ TestResultsFormat["TestNG"] = "testng";
22
+ TestResultsFormat["xUnit"] = "xunit";
23
+ })(TestResultsFormat || (TestResultsFormat = {}));
24
+ var TestType;
25
+ (function (TestType) {
26
+ TestType["Functional"] = "Functional";
27
+ TestType["Integration"] = "Integration";
28
+ TestType["Manual"] = "Manual";
29
+ TestType["Performance"] = "Performance";
30
+ TestType["Regression"] = "Regression";
31
+ TestType["Security"] = "Security";
32
+ TestType["Unit"] = "Unit";
33
+ TestType["Custom"] = "Custom";
34
+ })(TestType || (TestType = {}));
35
+ function convertStatus(status) {
36
+ switch (status.toLowerCase()) {
37
+ case 'success':
38
+ case 'succeed':
39
+ case 'succeeded':
40
+ case 'pass':
41
+ case 'passed':
42
+ return 'Success';
43
+ case 'skip':
44
+ case 'skipped':
45
+ case 'disable':
46
+ case 'disabled':
47
+ return 'Skipped';
48
+ case 'fail':
49
+ case 'failed':
50
+ case 'failure':
51
+ return 'Failure';
52
+ default:
53
+ return 'Custom';
54
+ }
55
+ }
56
+ function parseTime(time) {
57
+ if (time.toLowerCase() === 'now') {
58
+ return new Date().toISOString();
59
+ }
60
+ if (/^\d+$/.test(time)) {
61
+ return new Date(parseInt(time, 10)).toISOString();
62
+ }
63
+ return time;
64
+ }
65
+ async function processTestResults(paths, options) {
66
+ const fileConfig = await (0, loader_1.loadConfig)();
67
+ const config = (0, loader_1.mergeConfig)(fileConfig, options);
68
+ // Determine if paths contain S3 URIs
69
+ const hasS3Uri = paths.some(p => p.startsWith('s3://'));
70
+ let files = [];
71
+ let tempFiles = [];
72
+ try {
73
+ // Handle S3 files
74
+ if (hasS3Uri) {
75
+ const spinner = ui_1.ui.spinner('Fetching files from S3...');
76
+ spinner.start();
77
+ const s3Uri = (0, s3_1.parseS3Uri)(paths[0]); // Assume first path is S3 URI
78
+ const s3Client = (0, s3_1.createS3Client)({
79
+ region: options.s3Region,
80
+ accessKeyId: options.s3AccessKeyId,
81
+ secretAccessKey: options.s3SecretAccessKey,
82
+ profile: options.s3Profile,
83
+ });
84
+ // Determine if it's a single file or directory
85
+ const isSingleFile = s3Uri.key.endsWith('.xml') || s3Uri.key.includes('.');
86
+ let s3Keys = [];
87
+ if (isSingleFile) {
88
+ s3Keys = [s3Uri.key];
89
+ }
90
+ else {
91
+ s3Keys = await (0, s3_1.listS3Objects)(s3Client, s3Uri.bucket, s3Uri.key, options.pattern);
92
+ }
93
+ spinner.succeed(`Found ${s3Keys.length} file(s) in S3`);
94
+ if (s3Keys.length === 0) {
95
+ ui_1.ui.log.warning('No files found matching criteria');
96
+ return;
97
+ }
98
+ const downloadSpinner = ui_1.ui.spinner(`Downloading ${s3Keys.length} file(s)...`);
99
+ downloadSpinner.start();
100
+ tempFiles = await (0, s3_1.downloadS3Objects)(s3Client, s3Uri.bucket, s3Keys);
101
+ files = tempFiles;
102
+ downloadSpinner.succeed(`Downloaded ${files.length} file(s)`);
103
+ }
104
+ else {
105
+ // Local files
106
+ files = paths.flatMap(p => p.split(',').map(v => v.trim()));
107
+ }
108
+ // Parse test results
109
+ const parseSpinner = ui_1.ui.spinner('Parsing test results...');
110
+ parseSpinner.start();
111
+ const results = (0, test_results_parser_1.parse)({
112
+ type: options.format || 'junit',
113
+ files,
114
+ });
115
+ parseSpinner.succeed(`Parsed ${results.suites.length} test suite(s) with ${results.total} total test(s)`);
116
+ // Validation mode
117
+ if (options.validate) {
118
+ ui_1.ui.log.success('All data is valid');
119
+ console.log();
120
+ console.log(chalk_1.default.dim('Would create:'));
121
+ console.log(chalk_1.default.dim(` • ${results.suites.length} qa_TestExecution records`));
122
+ console.log(chalk_1.default.dim(` • ${results.total} qa_TestCase records`));
123
+ console.log(chalk_1.default.dim(` • ${results.total} qa_TestCaseResult records`));
124
+ console.log();
125
+ console.log(chalk_1.default.dim('Run without --validate to sync to Faros'));
126
+ return;
127
+ }
128
+ // Preview mode
129
+ if (options.preview) {
130
+ console.log();
131
+ console.log(chalk_1.default.bold('Sample records (first 2):'));
132
+ console.log();
133
+ const sampleSuite = results.suites[0];
134
+ if (sampleSuite) {
135
+ console.log(chalk_1.default.blue('qa_TestExecution:'));
136
+ console.log(' {');
137
+ console.log(` "suite": "${sampleSuite.name}",`);
138
+ console.log(` "source": "${options.source}",`);
139
+ console.log(` "type": "${options.type || 'Unit'}",`);
140
+ console.log(` "status": "${convertStatus(sampleSuite.status)}",`);
141
+ console.log(` "stats": { "passed": ${sampleSuite.passed}, "failed": ${sampleSuite.failed}, "total": ${sampleSuite.total} }`);
142
+ console.log(' }');
143
+ console.log();
144
+ const sampleCase = sampleSuite.cases[0];
145
+ if (sampleCase) {
146
+ console.log(chalk_1.default.blue('qa_TestCase:'));
147
+ console.log(' {');
148
+ console.log(` "name": "${sampleCase.name}",`);
149
+ console.log(` "type": "${options.type || 'Unit'}",`);
150
+ console.log(` "status": "${convertStatus(sampleCase.status)}"`);
151
+ console.log(' }');
152
+ }
153
+ }
154
+ console.log();
155
+ console.log(chalk_1.default.dim('Run with --dry-run to sync to staging for full verification'));
156
+ return;
157
+ }
158
+ // Determine target graph
159
+ let targetGraph = config.graph;
160
+ if (options.dryRun) {
161
+ targetGraph = (0, loader_1.getStagingGraph)(config);
162
+ ui_1.ui.log.warning(`Dry-run mode: syncing to staging graph '${targetGraph}'`);
163
+ console.log();
164
+ }
165
+ // Create API client
166
+ const client = (0, client_1.createClient)(config);
167
+ // Upload test results
168
+ const progressBar = ui_1.ui.progressBar(results.suites.length, {
169
+ format: `${chalk_1.default.blue('Uploading')} |{bar}| {percentage}% | {value}/{total} suites`,
170
+ });
171
+ progressBar.start(results.suites.length, 0);
172
+ const limit = (0, p_limit_1.default)(options.concurrency || config.defaults?.concurrency || 8);
173
+ const errors = [];
174
+ let uploaded = 0;
175
+ const uploadPromises = results.suites.map(suite => limit(async () => {
176
+ try {
177
+ const cases = suite.cases.map(tc => {
178
+ const steps = tc.steps.map(s => ({
179
+ id: (0, uuid_1.v4)(),
180
+ name: s.name,
181
+ status: convertStatus(s.status),
182
+ statusDetails: s.failure && s.stack_trace
183
+ ? `${s.failure} : ${s.stack_trace}`
184
+ : s.failure ?? s.stack_trace,
185
+ }));
186
+ return {
187
+ id: (0, uuid_1.v4)(),
188
+ name: tc.name,
189
+ type: options.type || 'Unit',
190
+ status: convertStatus(tc.status),
191
+ statusDetails: tc.failure && tc.stack_trace
192
+ ? `${tc.failure} : ${tc.stack_trace}`
193
+ : tc.failure ?? tc.stack_trace,
194
+ ...(steps.length > 0 ? { step: steps } : {}),
195
+ };
196
+ });
197
+ const data = {
198
+ type: 'TestExecution',
199
+ version: '0.0.1',
200
+ origin: config.origin,
201
+ data: {
202
+ commit: options.commit ? { uri: options.commit } : undefined,
203
+ test: {
204
+ id: (0, uuid_1.v4)(),
205
+ suite: suite.name,
206
+ source: options.source || config.defaults?.testSource || 'Unknown',
207
+ type: options.type || config.defaults?.testType || 'Unit',
208
+ status: convertStatus(suite.status),
209
+ statusDetails: suite.status,
210
+ stats: {
211
+ success: suite.passed,
212
+ failure: suite.failed,
213
+ skipped: suite.skipped,
214
+ unknown: 0,
215
+ custom: 0,
216
+ total: suite.total,
217
+ },
218
+ startTime: suite.timestamp || parseTime(options.testStart || 'now'),
219
+ endTime: suite.timestamp
220
+ ? new Date(Date.parse(suite.timestamp) + suite.duration).toISOString()
221
+ : parseTime(options.testEnd || 'now'),
222
+ ...(cases.length > 0 ? { case: cases } : {}),
223
+ },
224
+ },
225
+ };
226
+ await (0, client_1.sendEvent)(client, targetGraph, data);
227
+ uploaded++;
228
+ progressBar.update(uploaded);
229
+ }
230
+ catch (error) {
231
+ errors.push({
232
+ suite: suite.name,
233
+ error: error.message,
234
+ });
235
+ }
236
+ }));
237
+ await Promise.all(uploadPromises);
238
+ progressBar.stop();
239
+ console.log();
240
+ if (errors.length > 0) {
241
+ ui_1.ui.log.error(`Failed to upload ${errors.length} test suite(s)`);
242
+ errors.slice(0, 5).forEach(e => {
243
+ console.error(chalk_1.default.dim(` ${e.suite}: ${e.error}`));
244
+ });
245
+ if (errors.length > 5) {
246
+ console.error(chalk_1.default.dim(` ... and ${errors.length - 5} more`));
247
+ }
248
+ process.exit(1);
249
+ }
250
+ ui_1.ui.log.success(`Synced ${uploaded} test suite(s)${options.dryRun ? ' to staging graph' : ''}`);
251
+ if (options.dryRun) {
252
+ console.log(chalk_1.default.dim(` Graph: ${targetGraph}`));
253
+ console.log(chalk_1.default.dim(` View in Faros: ${config.url.replace('/api', '')}/${targetGraph}/qa`));
254
+ console.log();
255
+ console.log(chalk_1.default.dim('To sync to production, run without --dry-run flag'));
256
+ }
257
+ }
258
+ finally {
259
+ // Cleanup temp files
260
+ if (tempFiles.length > 0) {
261
+ (0, s3_1.cleanupTempFiles)(tempFiles);
262
+ }
263
+ }
264
+ }
265
+ function syncTestsCommand() {
266
+ const cmd = new commander_1.Command('tests');
267
+ cmd
268
+ .description('Sync test results (JUnit/TestNG/xUnit/Cucumber/Mocha) to Faros')
269
+ .argument('<paths...>', 'Path(s) to test result files or S3 URI (s3://bucket/path/)')
270
+ .addOption(new commander_1.Option('--format <format>', 'Test results format')
271
+ .choices(Object.values(TestResultsFormat))
272
+ .default('junit'))
273
+ .addOption(new commander_1.Option('--type <type>', 'Test type')
274
+ .choices(Object.values(TestType))
275
+ .default('Unit'))
276
+ .option('--source <source>', 'Test source system (e.g. Jenkins, GitHub-Actions)')
277
+ .option('--commit <uri>', 'Commit URI: <source>://<org>/<repo>/<sha>')
278
+ .option('--test-start <time>', 'Test start time (ISO-8601, epoch millis, or "Now")', 'now')
279
+ .option('--test-end <time>', 'Test end time (ISO-8601, epoch millis, or "Now")', 'now')
280
+ .option('--concurrency <number>', 'Number of concurrent uploads', parseInt, 8)
281
+ .option('--s3-region <region>', 'AWS region for S3')
282
+ .option('--s3-profile <profile>', 'AWS profile name')
283
+ .option('--s3-access-key-id <key>', 'AWS access key ID')
284
+ .option('--s3-secret-access-key <secret>', 'AWS secret access key')
285
+ .option('--pattern <regex>', 'Regex pattern to filter S3 objects')
286
+ .option('--validate', 'Validate only, don\'t send to Faros (fast, offline)')
287
+ .option('--preview', 'Show sample records without sending')
288
+ .option('--dry-run', 'Sync to staging graph for verification')
289
+ .addHelpText('after', `
290
+ Examples:
291
+ # Sync local test results
292
+ $ faros sync tests test-results/*.xml --source "Jenkins" --commit "GitHub://org/repo/abc"
293
+
294
+ # Sync from S3
295
+ $ faros sync tests s3://bucket/junit/ --pattern ".*\\.xml$" --source "Jenkins"
296
+
297
+ # Validate before syncing
298
+ $ faros sync tests *.xml --validate
299
+
300
+ # Dry run to staging
301
+ $ faros sync tests *.xml --dry-run
302
+ `)
303
+ .action(async (paths, options) => {
304
+ try {
305
+ await processTestResults(paths, options);
306
+ }
307
+ catch (error) {
308
+ ui_1.ui.log.error(error.message);
309
+ if (options.debug) {
310
+ console.error(error.stack);
311
+ }
312
+ process.exit(1);
313
+ }
314
+ });
315
+ return cmd;
316
+ }
317
+ //# sourceMappingURL=tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tests.js","sourceRoot":"","sources":["../../../src/commands/sync/tests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Config } from '../types/config';
2
+ export declare function loadConfig(): Promise<Config | null>;
3
+ export declare function mergeConfig(fileConfig: Config | null, cliOptions: any, envVars?: NodeJS.ProcessEnv): Config;
4
+ export declare function getStagingGraph(config: Config): string;
5
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAkCvD,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBzD;AAED,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,GAAG,EACf,OAAO,GAAE,MAAM,CAAC,UAAwB,GACvC,MAAM,CAoCR;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loadConfig = loadConfig;
40
+ exports.mergeConfig = mergeConfig;
41
+ exports.getStagingGraph = getStagingGraph;
42
+ const cosmiconfig_1 = require("cosmiconfig");
43
+ const config_1 = require("../types/config");
44
+ const dotenv_1 = __importDefault(require("dotenv"));
45
+ const path_1 = __importDefault(require("path"));
46
+ const ui_1 = require("../lib/ui");
47
+ const fs = __importStar(require("fs"));
48
+ // Load .env file if it exists (checks multiple locations)
49
+ const envPaths = [
50
+ path_1.default.join(process.cwd(), '.env'),
51
+ path_1.default.join(process.cwd(), '.env.local'),
52
+ ];
53
+ for (const envPath of envPaths) {
54
+ if (fs.existsSync(envPath)) {
55
+ dotenv_1.default.config({ path: envPath });
56
+ break;
57
+ }
58
+ }
59
+ const explorer = (0, cosmiconfig_1.cosmiconfig)('faros', {
60
+ searchPlaces: [
61
+ 'faros.config.yaml',
62
+ 'faros.config.yml',
63
+ 'faros.config.json',
64
+ 'faros.config.js',
65
+ 'faros.config.cjs',
66
+ '.farosrc.yaml',
67
+ '.farosrc.yml',
68
+ '.farosrc.json',
69
+ '.farosrc.js',
70
+ '.farosrc.cjs',
71
+ ],
72
+ });
73
+ async function loadConfig() {
74
+ try {
75
+ const result = await explorer.search();
76
+ if (!result || result.isEmpty) {
77
+ return null;
78
+ }
79
+ // Validate config
80
+ const config = config_1.ConfigSchema.parse(result.config);
81
+ return config;
82
+ }
83
+ catch (error) {
84
+ if (error.name === 'ZodError') {
85
+ ui_1.ui.log.error('Invalid configuration file:');
86
+ error.errors.forEach((e) => {
87
+ console.error(` ${e.path.join('.')}: ${e.message}`);
88
+ });
89
+ process.exit(1);
90
+ }
91
+ // Config file not found or parse error - that's ok
92
+ return null;
93
+ }
94
+ }
95
+ function mergeConfig(fileConfig, cliOptions, envVars = process.env) {
96
+ const merged = {
97
+ url: 'https://prod.api.faros.ai',
98
+ graph: 'default',
99
+ origin: 'faros-cli',
100
+ defaults: {
101
+ concurrency: 8,
102
+ },
103
+ ...fileConfig,
104
+ };
105
+ // Credentials from environment variables (highest priority for secrets)
106
+ if (envVars.FAROS_API_KEY)
107
+ merged.apiKey = envVars.FAROS_API_KEY;
108
+ if (envVars.LINEAR_API_KEY && merged.sources?.linear) {
109
+ merged.sources.linear.apiKey = envVars.LINEAR_API_KEY;
110
+ }
111
+ if (envVars.GITHUB_TOKEN && merged.sources?.github) {
112
+ merged.sources.github.token = envVars.GITHUB_TOKEN;
113
+ }
114
+ // AWS credentials from environment
115
+ if (envVars.AWS_ACCESS_KEY_ID) {
116
+ // AWS SDK will pick these up automatically
117
+ }
118
+ // Configuration from environment variables (lower priority)
119
+ if (envVars.FAROS_URL)
120
+ merged.url = envVars.FAROS_URL;
121
+ if (envVars.FAROS_GRAPH)
122
+ merged.graph = envVars.FAROS_GRAPH;
123
+ if (envVars.FAROS_ORIGIN)
124
+ merged.origin = envVars.FAROS_ORIGIN;
125
+ // CLI options override everything
126
+ if (cliOptions.apiKey)
127
+ merged.apiKey = cliOptions.apiKey;
128
+ if (cliOptions.url)
129
+ merged.url = cliOptions.url;
130
+ if (cliOptions.graph)
131
+ merged.graph = cliOptions.graph;
132
+ return merged;
133
+ }
134
+ function getStagingGraph(config) {
135
+ return config.stagingGraph || `${config.graph}-staging`;
136
+ }
137
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/lib/index.js ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const update_notifier_1 = __importDefault(require("update-notifier"));
10
+ const sync_1 = require("./commands/sync");
11
+ const sources_1 = require("./commands/sources");
12
+ const logs_1 = require("./commands/logs");
13
+ const ui_1 = require("./lib/ui");
14
+ const pkg = require('../package.json');
15
+ // Check for updates
16
+ const notifier = (0, update_notifier_1.default)({
17
+ pkg,
18
+ updateCheckInterval: 1000 * 60 * 60 * 24, // 1 day
19
+ });
20
+ if (notifier.update) {
21
+ console.log(ui_1.ui.box(`Update available: ${chalk_1.default.dim(notifier.update.current)} → ${chalk_1.default.green(notifier.update.latest)}\n\nRun ${chalk_1.default.cyan('npm install -g @faros-fde-sandbox/cli')} to update`, { borderColor: 'yellow' }));
22
+ }
23
+ async function main() {
24
+ const program = new commander_1.Command();
25
+ program
26
+ .name('faros')
27
+ .description('Modern CLI for Faros AI - sync data, manage sources, view logs')
28
+ .version(pkg.version)
29
+ .addHelpText('before', `
30
+ ${chalk_1.default.bold.blue('Faros CLI')} - Instrumentation & Data Sync
31
+ `)
32
+ .addHelpText('after', `
33
+ ${chalk_1.default.bold('Quick Start:')}
34
+ ${chalk_1.default.dim('# Sync test results')}
35
+ $ faros sync tests test-results/*.xml --source "Jenkins" --commit "GitHub://org/repo/abc"
36
+
37
+ ${chalk_1.default.dim('# Report build status')}
38
+ $ faros sync ci-cd build --status Success --commit "GitHub://org/repo/abc" --run "Jenkins://org/pipeline/123"
39
+
40
+ ${chalk_1.default.dim('# View logs')}
41
+ $ faros logs
42
+
43
+ ${chalk_1.default.dim('# List sources')}
44
+ $ faros sources list
45
+
46
+ ${chalk_1.default.bold('Documentation:')} https://docs.faros.ai
47
+ ${chalk_1.default.bold('Support:')} https://community.faros.ai
48
+ `);
49
+ // Global options
50
+ program
51
+ .option('-k, --api-key <key>', 'Faros API key (or set FAROS_API_KEY)')
52
+ .option('-u, --url <url>', 'Faros API URL')
53
+ .option('-g, --graph <name>', 'Faros graph name')
54
+ .option('--debug', 'Enable debug logging')
55
+ .option('--quiet', 'Minimal output')
56
+ .option('--json', 'Output JSON (for scripting)')
57
+ .option('--no-color', 'Disable colors');
58
+ // Register commands
59
+ program.addCommand((0, sync_1.syncCommand)());
60
+ program.addCommand((0, sources_1.sourcesCommand)());
61
+ program.addCommand((0, logs_1.logsCommand)());
62
+ // Parse arguments
63
+ await program.parseAsync(process.argv);
64
+ }
65
+ // Run CLI
66
+ main().catch((error) => {
67
+ ui_1.ui.log.error(error.message);
68
+ if (process.env.DEBUG) {
69
+ console.error(error.stack);
70
+ }
71
+ process.exit(1);
72
+ });
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,kDAA0B;AAC1B,sEAA6C;AAC7C,0CAA8C;AAC9C,gDAAoD;AACpD,0CAA8C;AAC9C,iCAA8B;AAE9B,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEvC,oBAAoB;AACpB,MAAM,QAAQ,GAAG,IAAA,yBAAc,EAAC;IAC9B,GAAG;IACH,mBAAmB,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,QAAQ;CACnD,CAAC,CAAC;AAEH,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,GAAG,CACT,OAAE,CAAC,GAAG,CACJ,qBAAqB,eAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,eAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,eAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,YAAY,EAC1K,EAAE,WAAW,EAAE,QAAQ,EAAE,CAC1B,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CAAC,gEAAgE,CAAC;SAC7E,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SACpB,WAAW,CAAC,QAAQ,EAAE;EACzB,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;CAC7B,CAAC;SACG,WAAW,CAAC,OAAO,EAAE;EACxB,eAAK,CAAC,IAAI,CAAC,cAAc,CAAC;IACxB,eAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC;;;IAGhC,eAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC;;;IAGlC,eAAK,CAAC,GAAG,CAAC,aAAa,CAAC;;;IAGxB,eAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC;;;EAG7B,eAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC;EAC5B,eAAK,CAAC,IAAI,CAAC,UAAU,CAAC;KACnB,CAAC,CAAC;IAEL,iBAAiB;IACjB,OAAO;SACJ,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,CAAC;SACrE,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC;SAC1C,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;SAChD,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;SACzC,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC;SACnC,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC;SAC/C,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAE1C,oBAAoB;IACpB,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,IAAA,wBAAc,GAAE,CAAC,CAAC;IACrC,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;IAElC,kBAAkB;IAClB,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,UAAU;AACV,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { Config } from '../../types/config';
3
+ export declare function createClient(config: Config): AxiosInstance;
4
+ export declare function sendEvent(client: AxiosInstance, graph: string, data: any, options?: {
5
+ validateOnly?: boolean;
6
+ full?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/api/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA4B1D;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,GAAG,EACT,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;CACX,GACL,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createClient = createClient;
7
+ exports.sendEvent = sendEvent;
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const axios_retry_1 = __importDefault(require("axios-retry"));
10
+ function createClient(config) {
11
+ if (!config.apiKey) {
12
+ throw new Error('Faros API key is required. Set via --api-key, FAROS_API_KEY env var, or config file');
13
+ }
14
+ const client = axios_1.default.create({
15
+ baseURL: config.url,
16
+ timeout: 60000,
17
+ headers: {
18
+ authorization: config.apiKey,
19
+ 'user-agent': 'faros-cli/1.0.0',
20
+ },
21
+ });
22
+ // Add retry logic
23
+ (0, axios_retry_1.default)(client, {
24
+ retries: 3,
25
+ retryDelay: axios_retry_1.default.exponentialDelay,
26
+ retryCondition: (error) => {
27
+ return (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) ||
28
+ error.response?.status === 429 || // Rate limit
29
+ error.response?.status === 503 // Service unavailable
30
+ );
31
+ },
32
+ });
33
+ return client;
34
+ }
35
+ async function sendEvent(client, graph, data, options = {}) {
36
+ await client.post(`/graphs/${graph}/events`, data, {
37
+ params: {
38
+ full: options.full ?? true,
39
+ validateOnly: options.validateOnly ?? false,
40
+ },
41
+ });
42
+ }
43
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/lib/api/client.ts"],"names":[],"mappings":";;;;;AAIA,oCA4BC;AAED,8BAeC;AAjDD,kDAA6C;AAC7C,8DAAqC;AAGrC,SAAgB,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,MAAM,GAAG,eAAK,CAAC,MAAM,CAAC;QAC1B,OAAO,EAAE,MAAM,CAAC,GAAG;QACnB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE;YACP,aAAa,EAAE,MAAM,CAAC,MAAM;YAC5B,YAAY,EAAE,iBAAiB;SAChC;KACF,CAAC,CAAC;IAEH,kBAAkB;IAClB,IAAA,qBAAU,EAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,qBAAU,CAAC,gBAAgB;QACvC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;YACxB,OAAO,CACL,qBAAU,CAAC,iCAAiC,CAAC,KAAK,CAAC;gBACnD,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,aAAa;gBAC/C,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,CAAI,sBAAsB;aACzD,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,MAAqB,EACrB,KAAa,EACb,IAAS,EACT,UAGI,EAAE;IAEN,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,IAAI,EAAE;QACjD,MAAM,EAAE;YACN,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;YAC1B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK;SAC5C;KACF,CAAC,CAAC;AACL,CAAC"}