@xcrawl/cli 0.2.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 (114) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +115 -0
  3. package/dist/api/client.d.ts +14 -0
  4. package/dist/api/client.js +92 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/api/crawl.d.ts +4 -0
  7. package/dist/api/crawl.js +63 -0
  8. package/dist/api/crawl.js.map +1 -0
  9. package/dist/api/credits.d.ts +2 -0
  10. package/dist/api/credits.js +7 -0
  11. package/dist/api/credits.js.map +1 -0
  12. package/dist/api/map.d.ts +2 -0
  13. package/dist/api/map.js +29 -0
  14. package/dist/api/map.js.map +1 -0
  15. package/dist/api/scrape.d.ts +2 -0
  16. package/dist/api/scrape.js +75 -0
  17. package/dist/api/scrape.js.map +1 -0
  18. package/dist/api/search.d.ts +2 -0
  19. package/dist/api/search.js +25 -0
  20. package/dist/api/search.js.map +1 -0
  21. package/dist/api/whoami.d.ts +2 -0
  22. package/dist/api/whoami.js +7 -0
  23. package/dist/api/whoami.js.map +1 -0
  24. package/dist/commands/config.d.ts +3 -0
  25. package/dist/commands/config.js +64 -0
  26. package/dist/commands/config.js.map +1 -0
  27. package/dist/commands/crawl.d.ts +3 -0
  28. package/dist/commands/crawl.js +91 -0
  29. package/dist/commands/crawl.js.map +1 -0
  30. package/dist/commands/credits.d.ts +3 -0
  31. package/dist/commands/credits.js +60 -0
  32. package/dist/commands/credits.js.map +1 -0
  33. package/dist/commands/doctor.d.ts +3 -0
  34. package/dist/commands/doctor.js +115 -0
  35. package/dist/commands/doctor.js.map +1 -0
  36. package/dist/commands/init.d.ts +2 -0
  37. package/dist/commands/init.js +9 -0
  38. package/dist/commands/init.js.map +1 -0
  39. package/dist/commands/login.d.ts +3 -0
  40. package/dist/commands/login.js +27 -0
  41. package/dist/commands/login.js.map +1 -0
  42. package/dist/commands/map.d.ts +3 -0
  43. package/dist/commands/map.js +48 -0
  44. package/dist/commands/map.js.map +1 -0
  45. package/dist/commands/scrape.d.ts +3 -0
  46. package/dist/commands/scrape.js +118 -0
  47. package/dist/commands/scrape.js.map +1 -0
  48. package/dist/commands/search.d.ts +3 -0
  49. package/dist/commands/search.js +64 -0
  50. package/dist/commands/search.js.map +1 -0
  51. package/dist/commands/shared.d.ts +14 -0
  52. package/dist/commands/shared.js +41 -0
  53. package/dist/commands/shared.js.map +1 -0
  54. package/dist/commands/whoami.d.ts +3 -0
  55. package/dist/commands/whoami.js +61 -0
  56. package/dist/commands/whoami.js.map +1 -0
  57. package/dist/core/auth.d.ts +1 -0
  58. package/dist/core/auth.js +11 -0
  59. package/dist/core/auth.js.map +1 -0
  60. package/dist/core/config.d.ts +20 -0
  61. package/dist/core/config.js +134 -0
  62. package/dist/core/config.js.map +1 -0
  63. package/dist/core/constants.d.ts +3 -0
  64. package/dist/core/constants.js +12 -0
  65. package/dist/core/constants.js.map +1 -0
  66. package/dist/core/env.d.ts +2 -0
  67. package/dist/core/env.js +34 -0
  68. package/dist/core/env.js.map +1 -0
  69. package/dist/core/errors.d.ts +33 -0
  70. package/dist/core/errors.js +66 -0
  71. package/dist/core/errors.js.map +1 -0
  72. package/dist/core/files.d.ts +3 -0
  73. package/dist/core/files.js +37 -0
  74. package/dist/core/files.js.map +1 -0
  75. package/dist/core/logger.d.ts +14 -0
  76. package/dist/core/logger.js +32 -0
  77. package/dist/core/logger.js.map +1 -0
  78. package/dist/core/output.d.ts +17 -0
  79. package/dist/core/output.js +29 -0
  80. package/dist/core/output.js.map +1 -0
  81. package/dist/formatters/json.d.ts +1 -0
  82. package/dist/formatters/json.js +18 -0
  83. package/dist/formatters/json.js.map +1 -0
  84. package/dist/formatters/markdown.d.ts +1 -0
  85. package/dist/formatters/markdown.js +7 -0
  86. package/dist/formatters/markdown.js.map +1 -0
  87. package/dist/formatters/table.d.ts +5 -0
  88. package/dist/formatters/table.js +23 -0
  89. package/dist/formatters/table.js.map +1 -0
  90. package/dist/formatters/text.d.ts +21 -0
  91. package/dist/formatters/text.js +78 -0
  92. package/dist/formatters/text.js.map +1 -0
  93. package/dist/index.d.ts +7 -0
  94. package/dist/index.js +117 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/types/api.d.ts +159 -0
  97. package/dist/types/api.js +3 -0
  98. package/dist/types/api.js.map +1 -0
  99. package/dist/types/cli.d.ts +12 -0
  100. package/dist/types/cli.js +3 -0
  101. package/dist/types/cli.js.map +1 -0
  102. package/dist/types/config.d.ts +19 -0
  103. package/dist/types/config.js +3 -0
  104. package/dist/types/config.js.map +1 -0
  105. package/dist/utils/concurrency.d.ts +1 -0
  106. package/dist/utils/concurrency.js +21 -0
  107. package/dist/utils/concurrency.js.map +1 -0
  108. package/dist/utils/time.d.ts +1 -0
  109. package/dist/utils/time.js +7 -0
  110. package/dist/utils/time.js.map +1 -0
  111. package/dist/utils/validate.d.ts +3 -0
  112. package/dist/utils/validate.js +48 -0
  113. package/dist/utils/validate.js.map +1 -0
  114. package/package.json +47 -0
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCrawlCommand = registerCrawlCommand;
4
+ const crawl_1 = require("../api/crawl");
5
+ const auth_1 = require("../core/auth");
6
+ const errors_1 = require("../core/errors");
7
+ const output_1 = require("../core/output");
8
+ const text_1 = require("../formatters/text");
9
+ const validate_1 = require("../utils/validate");
10
+ const shared_1 = require("./shared");
11
+ function addCommonCrawlOptions(command) {
12
+ return command
13
+ .option('--api-key <key>', 'Override API key')
14
+ .option('--api-base-url <url>', 'Override API base URL')
15
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
16
+ .option('--debug', 'Enable debug output')
17
+ .option('--json', 'Output result as JSON')
18
+ .option('--output <path>', 'Save output to a file');
19
+ }
20
+ function registerCrawlCommand(program, context) {
21
+ const crawl = program.command('crawl').description('Start crawl jobs and query job status');
22
+ addCommonCrawlOptions(crawl
23
+ .command('start')
24
+ .description('Start a crawl job for a target URL')
25
+ .argument('<url>', 'Target URL')
26
+ .option('--wait', 'Wait until the job reaches a terminal status')
27
+ .option('--interval <ms>', 'Polling interval in milliseconds (default: 2000)')
28
+ .option('--wait-timeout <ms>', 'Polling timeout in milliseconds (default: 60000)')
29
+ .option('--max-pages <n>', 'Maximum pages to crawl')).action(async (url, options) => {
30
+ (0, validate_1.assertHttpUrl)(url);
31
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
32
+ apiKey: options.apiKey,
33
+ apiBaseUrl: options.apiBaseUrl,
34
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
35
+ debug: options.debug
36
+ });
37
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
38
+ const client = context.createApiClient(runtime);
39
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
40
+ const started = await (0, crawl_1.startCrawl)(client, {
41
+ url,
42
+ maxPages: (0, validate_1.parsePositiveInt)(options.maxPages, 'max-pages')
43
+ });
44
+ if (!options.wait) {
45
+ await (0, output_1.renderOutput)({
46
+ ctx: { stdout: context.stdout },
47
+ data: started,
48
+ json: options.json,
49
+ outputPath,
50
+ renderText: text_1.formatCrawlStart
51
+ });
52
+ return;
53
+ }
54
+ const intervalMs = (0, validate_1.parsePositiveInt)(options.interval, 'interval') ?? 2000;
55
+ const waitTimeoutMs = (0, validate_1.parsePositiveInt)(options.waitTimeout, 'wait-timeout') ?? 60000;
56
+ const status = await (0, crawl_1.waitForCrawlCompletion)(client, started.jobId, intervalMs, waitTimeoutMs);
57
+ await (0, output_1.renderOutput)({
58
+ ctx: { stdout: context.stdout },
59
+ data: status,
60
+ json: options.json,
61
+ outputPath,
62
+ renderText: text_1.formatCrawlStatus
63
+ });
64
+ });
65
+ addCommonCrawlOptions(crawl
66
+ .command('status')
67
+ .description('Fetch crawl job status by job id')
68
+ .argument('<job-id>', 'Crawl job id')).action(async (jobId, options) => {
69
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
70
+ apiKey: options.apiKey,
71
+ apiBaseUrl: options.apiBaseUrl,
72
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
73
+ debug: options.debug
74
+ });
75
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
76
+ const client = context.createApiClient(runtime);
77
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
78
+ const status = await (0, crawl_1.fetchCrawlStatus)(client, jobId);
79
+ await (0, output_1.renderOutput)({
80
+ ctx: { stdout: context.stdout },
81
+ data: status,
82
+ json: options.json,
83
+ outputPath,
84
+ renderText: text_1.formatCrawlStatus
85
+ });
86
+ });
87
+ crawl.action(() => {
88
+ throw new errors_1.ValidationError('Missing crawl action.', 'Run `xcrawl crawl <url>` (shorthand) or `xcrawl crawl start <url>`, or check `xcrawl crawl --help`.');
89
+ });
90
+ }
91
+ //# sourceMappingURL=crawl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl.js","sourceRoot":"","sources":["../../src/commands/crawl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerCreditsCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCreditsCommand = registerCreditsCommand;
4
+ const credits_1 = require("../api/credits");
5
+ const auth_1 = require("../core/auth");
6
+ const output_1 = require("../core/output");
7
+ const text_1 = require("../formatters/text");
8
+ const validate_1 = require("../utils/validate");
9
+ const shared_1 = require("./shared");
10
+ function registerCreditsCommand(program, context) {
11
+ program
12
+ .command('credits')
13
+ .description('Show account credits and usage')
14
+ .option('--api-key <key>', 'Override API key')
15
+ .option('--api-base-url <url>', 'Override API base URL')
16
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
17
+ .option('--debug', 'Enable debug output')
18
+ .option('--json', 'Output result as JSON')
19
+ .option('--output <path>', 'Save output to a file')
20
+ .action(async (options) => {
21
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
22
+ apiKey: options.apiKey,
23
+ apiBaseUrl: options.apiBaseUrl,
24
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
25
+ debug: options.debug
26
+ });
27
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
28
+ const client = context.createApiClient(runtime);
29
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
30
+ try {
31
+ const result = await (0, credits_1.fetchCredits)(client);
32
+ await (0, output_1.renderOutput)({
33
+ ctx: { stdout: context.stdout },
34
+ data: result,
35
+ json: options.json,
36
+ outputPath,
37
+ renderText: text_1.formatCredits
38
+ });
39
+ return;
40
+ }
41
+ catch (error) {
42
+ if (!(0, shared_1.isAccountEndpointUnavailable)(error, runtime.apiBaseUrl)) {
43
+ throw error;
44
+ }
45
+ const fallback = {
46
+ apiBaseUrl: runtime.apiBaseUrl,
47
+ supported: false,
48
+ note: 'Public API does not expose a standalone credits endpoint. Read total_credits_used from task responses.'
49
+ };
50
+ await (0, output_1.renderOutput)({
51
+ ctx: { stdout: context.stdout },
52
+ data: fallback,
53
+ json: options.json,
54
+ outputPath,
55
+ renderText: (data) => `Credits endpoint unavailable on ${data.apiBaseUrl}. ${data.note}`
56
+ });
57
+ }
58
+ });
59
+ }
60
+ //# sourceMappingURL=credits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/commands/credits.ts"],"names":[],"mappings":";;AAuBA,wDAoDC;AAzED,4CAA8C;AAC9C,uCAA6C;AAC7C,2CAA8C;AAC9C,6CAAmD;AAEnD,gDAAqD;AACrD,qCAIkB;AAWlB,SAAgB,sBAAsB,CAAC,OAAgB,EAAE,OAAmB;IAC1E,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SAC7C,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;SAC3D,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC;SACxC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;SAClD,MAAM,CAAC,KAAK,EAAE,OAAuB,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,MAAM,IAAA,oCAA2B,EAAC,OAAO,EAAE;YACzD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;YACvD,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,GAAG,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAY,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,IAAA,qBAAY,EAAC;gBACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;gBAC/B,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,UAAU;gBACV,UAAU,EAAE,oBAAa;aAC1B,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAA,qCAA4B,EAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC7D,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,QAAQ,GAAG;gBACf,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,SAAS,EAAE,KAAK;gBAChB,IAAI,EAAE,wGAAwG;aAC/G,CAAC;YAEF,MAAM,IAAA,qBAAY,EAAC;gBACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;gBAC/B,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,UAAU;gBACV,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,mCAAmC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,EAAE;aACzF,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerDoctorCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDoctorCommand = registerDoctorCommand;
4
+ const whoami_1 = require("../api/whoami");
5
+ const config_1 = require("../core/config");
6
+ const output_1 = require("../core/output");
7
+ const text_1 = require("../formatters/text");
8
+ const validate_1 = require("../utils/validate");
9
+ const shared_1 = require("./shared");
10
+ function checkNodeVersion() {
11
+ const raw = process.versions.node;
12
+ const major = Number.parseInt(raw.split('.')[0], 10);
13
+ if (major >= 18) {
14
+ return { ok: true, detail: raw };
15
+ }
16
+ return { ok: false, detail: `${raw} (requires Node >= 18)` };
17
+ }
18
+ function registerDoctorCommand(program, context) {
19
+ program
20
+ .command('doctor')
21
+ .description('Run local diagnostics and connectivity checks')
22
+ .option('--api-key <key>', 'Override API key')
23
+ .option('--api-base-url <url>', 'Override API base URL')
24
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
25
+ .option('--debug', 'Enable debug output')
26
+ .option('--json', 'Output result as JSON')
27
+ .option('--output <path>', 'Save output to a file')
28
+ .action(async (options) => {
29
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
30
+ apiKey: options.apiKey,
31
+ apiBaseUrl: options.apiBaseUrl,
32
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
33
+ debug: options.debug
34
+ });
35
+ const configPath = (0, config_1.getConfigPath)(context.homeDir);
36
+ const node = checkNodeVersion();
37
+ const report = {
38
+ version: context.version,
39
+ checks: [
40
+ {
41
+ name: 'node_version',
42
+ ok: node.ok,
43
+ detail: node.detail
44
+ }
45
+ ]
46
+ };
47
+ try {
48
+ await (0, config_1.saveLocalConfig)({}, context.homeDir);
49
+ report.checks.push({
50
+ name: 'config_rw',
51
+ ok: true,
52
+ detail: configPath
53
+ });
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : 'Unable to access config file';
57
+ report.checks.push({
58
+ name: 'config_rw',
59
+ ok: false,
60
+ detail: message
61
+ });
62
+ }
63
+ if (runtime.apiKey) {
64
+ try {
65
+ const client = context.createApiClient(runtime);
66
+ await (0, whoami_1.fetchWhoAmI)(client);
67
+ report.checks.push({
68
+ name: 'api_connectivity',
69
+ ok: true,
70
+ detail: 'whoami check passed'
71
+ });
72
+ }
73
+ catch (error) {
74
+ if ((0, shared_1.isAccountEndpointUnavailable)(error, runtime.apiBaseUrl)) {
75
+ report.checks.push({
76
+ name: 'api_connectivity',
77
+ ok: true,
78
+ detail: 'Authenticated API reachable (public account endpoint is unavailable on run API).'
79
+ });
80
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
81
+ await (0, output_1.renderOutput)({
82
+ ctx: { stdout: context.stdout },
83
+ data: report,
84
+ json: options.json,
85
+ outputPath,
86
+ renderText: text_1.formatDoctorReport
87
+ });
88
+ return;
89
+ }
90
+ const message = error instanceof Error ? error.message : 'whoami check failed';
91
+ report.checks.push({
92
+ name: 'api_connectivity',
93
+ ok: false,
94
+ detail: message
95
+ });
96
+ }
97
+ }
98
+ else {
99
+ report.checks.push({
100
+ name: 'api_key',
101
+ ok: false,
102
+ detail: 'API key not found (configure via login or XCRAWL_API_KEY)'
103
+ });
104
+ }
105
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
106
+ await (0, output_1.renderOutput)({
107
+ ctx: { stdout: context.stdout },
108
+ data: report,
109
+ json: options.json,
110
+ outputPath,
111
+ renderText: text_1.formatDoctorReport
112
+ });
113
+ });
114
+ }
115
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":";;AAkCA,sDAmGC;AAnID,0CAA4C;AAC5C,2CAAgE;AAChE,2CAA8C;AAC9C,6CAA2E;AAE3E,gDAAqD;AACrD,qCAIkB;AAWlB,SAAS,gBAAgB;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAClC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAErD,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,wBAAwB,EAAE,CAAC;AAC/D,CAAC;AAED,SAAgB,qBAAqB,CAAC,OAAgB,EAAE,OAAmB;IACzE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SAC7C,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;SAC3D,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC;SACxC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;SAClD,MAAM,CAAC,KAAK,EAAE,OAAsB,EAAE,EAAE;QACvC,MAAM,OAAO,GAAG,MAAM,IAAA,oCAA2B,EAAC,OAAO,EAAE;YACzD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;YACvD,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,MAAM,GAAiB;YAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE;gBACN;oBACE,IAAI,EAAE,cAAc;oBACpB,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB;aACF;SACF,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAA,wBAAe,EAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;YACxF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBAChD,MAAM,IAAA,oBAAW,EAAC,MAAM,CAAC,CAAC;gBAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;oBACjB,IAAI,EAAE,kBAAkB;oBACxB,EAAE,EAAE,IAAI;oBACR,MAAM,EAAE,qBAAqB;iBAC9B,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,IAAA,qCAA4B,EAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;wBACjB,IAAI,EAAE,kBAAkB;wBACxB,EAAE,EAAE,IAAI;wBACR,MAAM,EAAE,kFAAkF;qBAC3F,CAAC,CAAC;oBACH,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;oBAE9D,MAAM,IAAA,qBAAY,EAAC;wBACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;wBAC/B,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,UAAU;wBACV,UAAU,EAAE,yBAAkB;qBAC/B,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;gBAC/E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;oBACjB,IAAI,EAAE,kBAAkB;oBACxB,EAAE,EAAE,KAAK;oBACT,MAAM,EAAE,OAAO;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,SAAS;gBACf,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,2DAA2D;aACpE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9D,MAAM,IAAA,qBAAY,EAAC;YACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU;YACV,UAAU,EAAE,yBAAkB;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerInitCommand(program: Command): void;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerInitCommand = registerInitCommand;
4
+ function registerInitCommand(program) {
5
+ program.command('init').description('Initialize project workspace (planned)').action(() => {
6
+ process.stdout.write('`init` will be implemented in a later phase.\n');
7
+ });
8
+ }
9
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;AAEA,kDAIC;AAJD,SAAgB,mBAAmB,CAAC,OAAgB;IAClD,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;QACxF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerLoginCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerLoginCommand = registerLoginCommand;
4
+ const config_1 = require("../core/config");
5
+ const errors_1 = require("../core/errors");
6
+ const output_1 = require("../core/output");
7
+ const text_1 = require("../formatters/text");
8
+ function registerLoginCommand(program, context) {
9
+ program
10
+ .command('login')
11
+ .description('Save the XCrawl API key to local config')
12
+ .option('--api-key <key>', 'XCrawl API Key')
13
+ .option('--json', 'Output result as JSON')
14
+ .action(async (options) => {
15
+ if (!options.apiKey || options.apiKey.trim().length === 0) {
16
+ throw new errors_1.ValidationError('Missing required argument: api-key.', 'Run `xcrawl login --api-key <key>`.');
17
+ }
18
+ const configPath = await (0, config_1.saveLocalConfig)({ apiKey: options.apiKey }, context.homeDir);
19
+ await (0, output_1.renderOutput)({
20
+ ctx: { stdout: context.stdout },
21
+ data: { ok: true, configPath },
22
+ json: options.json,
23
+ renderText: () => (0, text_1.formatLoginSuccess)(configPath)
24
+ });
25
+ });
26
+ }
27
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;AAaA,oDAmBC;AA9BD,2CAAiD;AACjD,2CAAiD;AACjD,2CAA8C;AAC9C,6CAAwD;AAQxD,SAAgB,oBAAoB,CAAC,OAAgB,EAAE,OAAmB;IACxE,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;SAC3C,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,EAAE;QACtC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,wBAAe,CAAC,qCAAqC,EAAE,qCAAqC,CAAC,CAAC;QAC1G,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAA,wBAAe,EAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACtF,MAAM,IAAA,qBAAY,EAAC;YACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,GAAG,EAAE,CAAC,IAAA,yBAAkB,EAAC,UAAU,CAAC;SACjD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerMapCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerMapCommand = registerMapCommand;
4
+ const map_1 = require("../api/map");
5
+ const auth_1 = require("../core/auth");
6
+ const output_1 = require("../core/output");
7
+ const text_1 = require("../formatters/text");
8
+ const validate_1 = require("../utils/validate");
9
+ const shared_1 = require("./shared");
10
+ function registerMapCommand(program, context) {
11
+ program
12
+ .command('map')
13
+ .description('Generate site map links for a URL')
14
+ .argument('<url>', 'Target URL')
15
+ .option('--api-key <key>', 'Override API key')
16
+ .option('--api-base-url <url>', 'Override API base URL')
17
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
18
+ .option('--debug', 'Enable debug output')
19
+ .option('--json', 'Output result as JSON')
20
+ .option('--output <path>', 'Save output to a file')
21
+ .option('--max-depth <n>', 'Maximum traversal depth')
22
+ .option('--limit <n>', 'Maximum number of links')
23
+ .action(async (url, options) => {
24
+ (0, validate_1.assertHttpUrl)(url);
25
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
26
+ apiKey: options.apiKey,
27
+ apiBaseUrl: options.apiBaseUrl,
28
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
29
+ debug: options.debug
30
+ });
31
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
32
+ const client = context.createApiClient(runtime);
33
+ const result = await (0, map_1.fetchMap)(client, {
34
+ url,
35
+ maxDepth: (0, validate_1.parsePositiveInt)(options.maxDepth, 'max-depth'),
36
+ limit: (0, validate_1.parsePositiveInt)(options.limit, 'limit')
37
+ });
38
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
39
+ await (0, output_1.renderOutput)({
40
+ ctx: { stdout: context.stdout },
41
+ data: result,
42
+ json: options.json,
43
+ outputPath,
44
+ renderText: text_1.formatMap
45
+ });
46
+ });
47
+ }
48
+ //# sourceMappingURL=map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/commands/map.ts"],"names":[],"mappings":";;AAqBA,gDA0CC;AA7DD,oCAAsC;AACtC,uCAA6C;AAC7C,2CAA8C;AAC9C,6CAA+C;AAE/C,gDAAoE;AACpE,qCAA0E;AAa1E,SAAgB,kBAAkB,CAAC,OAAgB,EAAE,OAAmB;IACtE,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,mCAAmC,CAAC;SAChD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;SAC/B,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SAC7C,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;SAC3D,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC;SACxC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;SAClD,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;SACpD,MAAM,CAAC,aAAa,EAAE,yBAAyB,CAAC;SAChD,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,OAAmB,EAAE,EAAE;QACjD,IAAA,wBAAa,EAAC,GAAG,CAAC,CAAC;QAEnB,MAAM,OAAO,GAAG,MAAM,IAAA,oCAA2B,EAAC,OAAO,EAAE;YACzD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;YACvD,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,GAAG,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAG,MAAM,IAAA,cAAQ,EAAC,MAAM,EAAE;YACpC,GAAG;YACH,QAAQ,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC;YACzD,KAAK,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC;SAChD,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9D,MAAM,IAAA,qBAAY,EAAC;YACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU;YACV,UAAU,EAAE,gBAAS;SACtB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerScrapeCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,118 @@
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.registerScrapeCommand = registerScrapeCommand;
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const scrape_1 = require("../api/scrape");
10
+ const auth_1 = require("../core/auth");
11
+ const errors_1 = require("../core/errors");
12
+ const output_1 = require("../core/output");
13
+ const json_1 = require("../formatters/json");
14
+ const text_1 = require("../formatters/text");
15
+ const files_1 = require("../core/files");
16
+ const concurrency_1 = require("../utils/concurrency");
17
+ const validate_1 = require("../utils/validate");
18
+ const shared_1 = require("./shared");
19
+ function extensionFor(format, jsonMode) {
20
+ if (jsonMode) {
21
+ return 'json';
22
+ }
23
+ switch (format) {
24
+ case 'markdown':
25
+ return 'md';
26
+ case 'html':
27
+ return 'html';
28
+ case 'screenshot':
29
+ return 'png';
30
+ case 'json':
31
+ return 'json';
32
+ default:
33
+ return 'txt';
34
+ }
35
+ }
36
+ async function loadUrlsFromInputFile(inputPath, cwd) {
37
+ const fullPath = node_path_1.default.isAbsolute(inputPath) ? inputPath : node_path_1.default.resolve(cwd, inputPath);
38
+ const content = await (0, promises_1.readFile)(fullPath, 'utf8');
39
+ return content
40
+ .split(/\r?\n/)
41
+ .map((line) => line.trim())
42
+ .filter((line) => line.length > 0 && !line.startsWith('#'));
43
+ }
44
+ function registerScrapeCommand(program, context) {
45
+ program
46
+ .command('scrape')
47
+ .description('Scrape one or more URLs')
48
+ .argument('[url...]', 'URL list to scrape')
49
+ .option('--api-key <key>', 'Override API key')
50
+ .option('--api-base-url <url>', 'Override API base URL')
51
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
52
+ .option('--debug', 'Enable debug output')
53
+ .option('--json', 'Output result as JSON')
54
+ .option('--output <path>', 'Output path; treated as a directory for multiple URLs')
55
+ .option('--format <format>', 'Output format: markdown/json/html/screenshot')
56
+ .option('--wait-for <selector>', 'Wait for selector before scraping')
57
+ .option('--headers <k:v,k2:v2>', 'Additional request headers')
58
+ .option('--cookies <cookies>', 'Cookie string')
59
+ .option('--proxy <proxy>', 'Proxy URL')
60
+ .option('--input <path>', 'Read URLs from a newline-delimited file')
61
+ .option('--concurrency <n>', 'Concurrent scrape workers (default: 3 for batch mode)')
62
+ .action(async (cliUrls, options) => {
63
+ const fileUrls = options.input ? await loadUrlsFromInputFile(options.input, context.cwd) : [];
64
+ const urls = [...cliUrls, ...fileUrls];
65
+ if (urls.length === 0) {
66
+ throw new errors_1.ValidationError('No URL provided.', 'Pass URLs as arguments, or use --input <path>.');
67
+ }
68
+ urls.forEach((url) => (0, validate_1.assertHttpUrl)(url));
69
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
70
+ apiKey: options.apiKey,
71
+ apiBaseUrl: options.apiBaseUrl,
72
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
73
+ debug: options.debug,
74
+ defaultFormat: options.format
75
+ });
76
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
77
+ const format = options.format ?? runtime.defaultFormat;
78
+ const client = context.createApiClient(runtime);
79
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
80
+ const concurrency = (0, validate_1.parsePositiveInt)(options.concurrency, 'concurrency') ?? 3;
81
+ const headers = (0, validate_1.parseHeaders)(options.headers);
82
+ const results = await (0, concurrency_1.runWithConcurrency)(urls, concurrency, async (url) => (0, scrape_1.scrapeUrl)(client, {
83
+ url,
84
+ format,
85
+ timeoutMs: runtime.timeoutMs,
86
+ waitFor: options.waitFor,
87
+ headers,
88
+ cookies: options.cookies,
89
+ proxy: options.proxy
90
+ }));
91
+ if (results.length > 1 && !options.output && options.json) {
92
+ await (0, output_1.renderOutput)({
93
+ ctx: { stdout: context.stdout },
94
+ data: results,
95
+ json: true,
96
+ renderText: () => ''
97
+ });
98
+ return;
99
+ }
100
+ if (results.length > 1) {
101
+ const targetDir = outputPath ?? node_path_1.default.resolve(context.cwd, runtime.outputDir);
102
+ const ext = extensionFor(format, options.json ?? false);
103
+ await (0, output_1.writeBatchOutput)(targetDir, results.map((item) => ({
104
+ fileName: `${(0, files_1.toSafeFileName)(item.url)}.${ext}`,
105
+ content: options.json ? (0, json_1.toStableJson)(item) : `${(0, text_1.formatScrape)(item)}\n`
106
+ })), context.stdout);
107
+ return;
108
+ }
109
+ await (0, output_1.renderOutput)({
110
+ ctx: { stdout: context.stdout },
111
+ data: results[0],
112
+ json: options.json,
113
+ outputPath,
114
+ renderText: text_1.formatScrape
115
+ });
116
+ });
117
+ }
118
+ //# sourceMappingURL=scrape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrape.js","sourceRoot":"","sources":["../../src/commands/scrape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerSearchCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerSearchCommand = registerSearchCommand;
4
+ const search_1 = require("../api/search");
5
+ const auth_1 = require("../core/auth");
6
+ const output_1 = require("../core/output");
7
+ const table_1 = require("../formatters/table");
8
+ const text_1 = require("../formatters/text");
9
+ const validate_1 = require("../utils/validate");
10
+ const shared_1 = require("./shared");
11
+ function formatSearchHuman(data) {
12
+ if (data.results.length === 0) {
13
+ return (0, text_1.formatSearch)(data);
14
+ }
15
+ return [
16
+ `Query: ${data.query}`,
17
+ '',
18
+ (0, table_1.renderTable)(data.results, [
19
+ { key: 'title', title: 'Title' },
20
+ { key: 'url', title: 'URL' }
21
+ ])
22
+ ].join('\n');
23
+ }
24
+ function registerSearchCommand(program, context) {
25
+ program
26
+ .command('search')
27
+ .description('Run a web search')
28
+ .argument('<query...>', 'Search query')
29
+ .option('--api-key <key>', 'Override API key')
30
+ .option('--api-base-url <url>', 'Override API base URL')
31
+ .option('--timeout <ms>', 'Request timeout in milliseconds')
32
+ .option('--debug', 'Enable debug output')
33
+ .option('--json', 'Output result as JSON')
34
+ .option('--output <path>', 'Save output to a file')
35
+ .option('--limit <n>', 'Result limit, default is 10')
36
+ .option('--country <country>', 'Country code, e.g. US')
37
+ .option('--language <language>', 'Language code, e.g. en')
38
+ .action(async (queryParts, options) => {
39
+ const query = queryParts.join(' ').trim();
40
+ const runtime = await (0, shared_1.resolveCommandRuntimeConfig)(context, {
41
+ apiKey: options.apiKey,
42
+ apiBaseUrl: options.apiBaseUrl,
43
+ timeoutMs: (0, validate_1.parsePositiveInt)(options.timeout, 'timeout'),
44
+ debug: options.debug
45
+ });
46
+ runtime.apiKey = (0, auth_1.requireApiKey)(runtime.apiKey);
47
+ const client = context.createApiClient(runtime);
48
+ const result = await (0, search_1.searchWeb)(client, {
49
+ query,
50
+ limit: (0, validate_1.parsePositiveInt)(options.limit, 'limit') ?? 10,
51
+ country: options.country,
52
+ language: options.language
53
+ });
54
+ const outputPath = (0, shared_1.resolveOutputPath)(context, options.output);
55
+ await (0, output_1.renderOutput)({
56
+ ctx: { stdout: context.stdout },
57
+ data: result,
58
+ json: options.json,
59
+ outputPath,
60
+ renderText: formatSearchHuman
61
+ });
62
+ });
63
+ }
64
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":";;AAuCA,sDA2CC;AAhFD,0CAA0C;AAC1C,uCAA6C;AAC7C,2CAA8C;AAC9C,+CAAkD;AAClD,6CAAkD;AAGlD,gDAAqD;AACrD,qCAA0E;AAc1E,SAAS,iBAAiB,CAAC,IAAoB;IAC7C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,UAAU,IAAI,CAAC,KAAK,EAAE;QACtB,EAAE;QACF,IAAA,mBAAW,EAAC,IAAI,CAAC,OAAO,EAAE;YACxB,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAChC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;SAC7B,CAAC;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,qBAAqB,CAAC,OAAgB,EAAE,OAAmB;IACzE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kBAAkB,CAAC;SAC/B,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;SACtC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SAC7C,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;SAC3D,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC;SACxC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;SAClD,MAAM,CAAC,aAAa,EAAE,6BAA6B,CAAC;SACpD,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;SACtD,MAAM,CAAC,uBAAuB,EAAE,wBAAwB,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,UAAoB,EAAE,OAAsB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,IAAA,oCAA2B,EAAC,OAAO,EAAE;YACzD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;YACvD,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,GAAG,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAAC,MAAM,EAAE;YACrC,KAAK;YACL,KAAK,EAAE,IAAA,2BAAgB,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE;YACrD,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9D,MAAM,IAAA,qBAAY,EAAC;YACjB,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU;YACV,UAAU,EAAE,iBAAiB;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { CliContext } from '../types/cli';
2
+ import type { RuntimeConfig, XCrawlConfig } from '../types/config';
3
+ export interface CommonCommandOptions {
4
+ apiKey?: string;
5
+ apiBaseUrl?: string;
6
+ timeout?: number;
7
+ debug?: boolean;
8
+ json?: boolean;
9
+ output?: string;
10
+ }
11
+ export declare function resolveCommandRuntimeConfig(context: CliContext, flags?: XCrawlConfig): Promise<RuntimeConfig>;
12
+ export declare function resolveOutputPath(context: CliContext, outputPath: string | undefined): string | undefined;
13
+ export declare function isRunApiBaseUrl(baseUrl: string): boolean;
14
+ export declare function isAccountEndpointUnavailable(error: unknown, baseUrl: string): boolean;