@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,41 @@
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.resolveCommandRuntimeConfig = resolveCommandRuntimeConfig;
7
+ exports.resolveOutputPath = resolveOutputPath;
8
+ exports.isRunApiBaseUrl = isRunApiBaseUrl;
9
+ exports.isAccountEndpointUnavailable = isAccountEndpointUnavailable;
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const errors_1 = require("../core/errors");
12
+ const config_1 = require("../core/config");
13
+ const env_1 = require("../core/env");
14
+ async function resolveCommandRuntimeConfig(context, flags = {}) {
15
+ const localConfig = await (0, config_1.readLocalConfig)(context.homeDir);
16
+ const envConfig = (0, env_1.readEnvConfig)(context.env);
17
+ return (0, config_1.resolveRuntimeConfig)({
18
+ flags,
19
+ env: envConfig,
20
+ local: localConfig
21
+ });
22
+ }
23
+ function resolveOutputPath(context, outputPath) {
24
+ if (!outputPath) {
25
+ return undefined;
26
+ }
27
+ return node_path_1.default.isAbsolute(outputPath) ? outputPath : node_path_1.default.resolve(context.cwd, outputPath);
28
+ }
29
+ function isRunApiBaseUrl(baseUrl) {
30
+ try {
31
+ const parsed = new URL(baseUrl);
32
+ return parsed.hostname === 'run.xcrawl.com';
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ function isAccountEndpointUnavailable(error, baseUrl) {
39
+ return isRunApiBaseUrl(baseUrl) && error instanceof errors_1.ApiError && error.status === 404;
40
+ }
41
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/commands/shared.ts"],"names":[],"mappings":";;;;;AAgBA,kEAYC;AAED,8CAMC;AAED,0CAOC;AAED,oEAEC;AAjDD,0DAA6B;AAG7B,2CAA0C;AAC1C,2CAAuE;AACvE,qCAA4C;AAWrC,KAAK,UAAU,2BAA2B,CAC/C,OAAmB,EACnB,QAAsB,EAAE;IAExB,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAe,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAA,mBAAa,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAE7C,OAAO,IAAA,6BAAoB,EAAC;QAC1B,KAAK;QACL,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAmB,EAAE,UAA8B;IACnF,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,mBAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AAC1F,CAAC;AAED,SAAgB,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC,QAAQ,KAAK,gBAAgB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAgB,4BAA4B,CAAC,KAAc,EAAE,OAAe;IAC1E,OAAO,eAAe,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,iBAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC;AACvF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { CliContext } from '../types/cli';
3
+ export declare function registerWhoamiCommand(program: Command, context: CliContext): void;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerWhoamiCommand = registerWhoamiCommand;
4
+ const whoami_1 = require("../api/whoami");
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 registerWhoamiCommand(program, context) {
11
+ program
12
+ .command('whoami')
13
+ .description('Show the current account info')
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, whoami_1.fetchWhoAmI)(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.formatWhoami
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
+ apiKeyConfigured: true,
48
+ supported: false,
49
+ note: 'Public API does not provide a whoami endpoint. Use dashboard for account details.'
50
+ };
51
+ await (0, output_1.renderOutput)({
52
+ ctx: { stdout: context.stdout },
53
+ data: fallback,
54
+ json: options.json,
55
+ outputPath,
56
+ renderText: (data) => `Whoami endpoint unavailable on ${data.apiBaseUrl}. ${data.note}`
57
+ });
58
+ }
59
+ });
60
+ }
61
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":";;AAuBA,sDAsDC;AA3ED,0CAA4C;AAC5C,uCAA6C;AAC7C,2CAA8C;AAC9C,6CAAkD;AAElD,gDAAqD;AACrD,qCAIkB;AAWlB,SAAgB,qBAAqB,CAAC,OAAgB,EAAE,OAAmB;IACzE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,+BAA+B,CAAC;SAC5C,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,OAAO,CAAC,MAAM,GAAG,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE/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,oBAAW,EAAC,MAAM,CAAC,CAAC;YAEzC,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,mBAAY;aACzB,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,gBAAgB,EAAE,IAAI;gBACtB,SAAS,EAAE,KAAK;gBAChB,IAAI,EAAE,mFAAmF;aAC1F,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,kCAAkC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,EAAE;aACxF,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function requireApiKey(apiKey: string | undefined): string;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireApiKey = requireApiKey;
4
+ const errors_1 = require("./errors");
5
+ function requireApiKey(apiKey) {
6
+ if (apiKey && apiKey.trim().length > 0) {
7
+ return apiKey;
8
+ }
9
+ throw new errors_1.AuthError('Missing API key.', 'Run `xcrawl login --api-key <key>` first, or set `XCRAWL_API_KEY`.');
10
+ }
11
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":";;AAEA,sCASC;AAXD,qCAAqC;AAErC,SAAgB,aAAa,CAAC,MAA0B;IACtD,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,kBAAS,CACjB,kBAAkB,EAClB,oEAAoE,CACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ConfigField, ConfigKey, RuntimeConfig, XCrawlConfig } from '../types/config';
2
+ export declare function getConfigPath(homeDir?: string): string;
3
+ export declare function readLocalConfig(homeDir?: string): Promise<XCrawlConfig>;
4
+ export declare function saveLocalConfig(nextConfig: XCrawlConfig, homeDir?: string): Promise<string>;
5
+ export interface ResolveRuntimeConfigInput {
6
+ flags?: XCrawlConfig;
7
+ env?: XCrawlConfig;
8
+ local?: XCrawlConfig;
9
+ defaults?: RuntimeConfig;
10
+ }
11
+ export declare function resolveRuntimeConfig(input: ResolveRuntimeConfigInput): RuntimeConfig;
12
+ export declare function isConfigKey(value: string): value is ConfigKey;
13
+ export declare function resolveConfigField(key: string): ConfigField;
14
+ export declare function parseConfigValue(field: ConfigField, rawValue: string): XCrawlConfig[ConfigField];
15
+ export declare function getConfigValue(key: string, homeDir?: string): Promise<unknown>;
16
+ export declare function setConfigValue(key: string, rawValue: string, homeDir?: string): Promise<{
17
+ configPath: string;
18
+ field: ConfigField;
19
+ value: unknown;
20
+ }>;
@@ -0,0 +1,134 @@
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.getConfigPath = getConfigPath;
7
+ exports.readLocalConfig = readLocalConfig;
8
+ exports.saveLocalConfig = saveLocalConfig;
9
+ exports.resolveRuntimeConfig = resolveRuntimeConfig;
10
+ exports.isConfigKey = isConfigKey;
11
+ exports.resolveConfigField = resolveConfigField;
12
+ exports.parseConfigValue = parseConfigValue;
13
+ exports.getConfigValue = getConfigValue;
14
+ exports.setConfigValue = setConfigValue;
15
+ const promises_1 = require("node:fs/promises");
16
+ const node_os_1 = __importDefault(require("node:os"));
17
+ const node_path_1 = __importDefault(require("node:path"));
18
+ const constants_1 = require("./constants");
19
+ const errors_1 = require("./errors");
20
+ const CONFIG_KEY_TO_FIELD = {
21
+ 'api-key': 'apiKey',
22
+ 'api-base-url': 'apiBaseUrl',
23
+ 'default-format': 'defaultFormat',
24
+ 'output-dir': 'outputDir',
25
+ 'timeout-ms': 'timeoutMs',
26
+ debug: 'debug'
27
+ };
28
+ const ALLOWED_DEFAULT_FORMATS = new Set(['markdown', 'json', 'html', 'screenshot', 'text']);
29
+ function getConfigPath(homeDir = node_os_1.default.homedir()) {
30
+ return node_path_1.default.join(homeDir, '.xcrawl', 'config.json');
31
+ }
32
+ async function readLocalConfig(homeDir) {
33
+ const configPath = getConfigPath(homeDir);
34
+ try {
35
+ await (0, promises_1.access)(configPath);
36
+ }
37
+ catch {
38
+ return {};
39
+ }
40
+ try {
41
+ const raw = await (0, promises_1.readFile)(configPath, 'utf8');
42
+ const parsed = JSON.parse(raw);
43
+ return parsed;
44
+ }
45
+ catch (error) {
46
+ throw new errors_1.ConfigError(`Failed to read config file: ${configPath}`, 'Please verify the JSON format is valid.', error);
47
+ }
48
+ }
49
+ async function saveLocalConfig(nextConfig, homeDir) {
50
+ const configPath = getConfigPath(homeDir);
51
+ const configDir = node_path_1.default.dirname(configPath);
52
+ const existing = await readLocalConfig(homeDir);
53
+ const merged = { ...existing, ...nextConfig };
54
+ try {
55
+ await (0, promises_1.mkdir)(configDir, { recursive: true });
56
+ await (0, promises_1.writeFile)(configPath, `${JSON.stringify(merged, null, 2)}\n`, 'utf8');
57
+ return configPath;
58
+ }
59
+ catch (error) {
60
+ throw new errors_1.ConfigError(`Failed to write config file: ${configPath}`, 'Please check directory permissions.', error);
61
+ }
62
+ }
63
+ function resolveRuntimeConfig(input) {
64
+ const defaults = input.defaults ?? constants_1.DEFAULT_RUNTIME_CONFIG;
65
+ const flags = input.flags ?? {};
66
+ const env = input.env ?? {};
67
+ const local = input.local ?? {};
68
+ return {
69
+ apiKey: flags.apiKey ?? env.apiKey ?? local.apiKey,
70
+ apiBaseUrl: flags.apiBaseUrl ?? env.apiBaseUrl ?? local.apiBaseUrl ?? defaults.apiBaseUrl,
71
+ defaultFormat: flags.defaultFormat ?? env.defaultFormat ?? local.defaultFormat ?? defaults.defaultFormat,
72
+ outputDir: flags.outputDir ?? env.outputDir ?? local.outputDir ?? defaults.outputDir,
73
+ timeoutMs: flags.timeoutMs ?? env.timeoutMs ?? local.timeoutMs ?? defaults.timeoutMs,
74
+ debug: flags.debug ?? env.debug ?? local.debug ?? defaults.debug
75
+ };
76
+ }
77
+ function isConfigKey(value) {
78
+ return Object.prototype.hasOwnProperty.call(CONFIG_KEY_TO_FIELD, value);
79
+ }
80
+ function resolveConfigField(key) {
81
+ if (!isConfigKey(key)) {
82
+ throw new errors_1.ValidationError(`Unsupported config key: ${key}`, 'Use one of: api-key, api-base-url, default-format, output-dir, timeout-ms, debug.');
83
+ }
84
+ return CONFIG_KEY_TO_FIELD[key];
85
+ }
86
+ function parseBoolean(value) {
87
+ const normalized = value.trim().toLowerCase();
88
+ if (normalized === 'true' || normalized === '1') {
89
+ return true;
90
+ }
91
+ if (normalized === 'false' || normalized === '0') {
92
+ return false;
93
+ }
94
+ throw new errors_1.ValidationError('Invalid boolean value.', 'Use true/false or 1/0.');
95
+ }
96
+ function parseDefaultFormat(value) {
97
+ if (ALLOWED_DEFAULT_FORMATS.has(value)) {
98
+ return value;
99
+ }
100
+ throw new errors_1.ValidationError(`Invalid default format: ${value}`, 'Use one of: markdown, json, html, screenshot, text.');
101
+ }
102
+ function parseConfigValue(field, rawValue) {
103
+ switch (field) {
104
+ case 'timeoutMs': {
105
+ const timeoutMs = Number.parseInt(rawValue, 10);
106
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
107
+ throw new errors_1.ValidationError('Invalid timeout-ms value.', 'Use a positive integer for timeout-ms.');
108
+ }
109
+ return timeoutMs;
110
+ }
111
+ case 'debug':
112
+ return parseBoolean(rawValue);
113
+ case 'defaultFormat':
114
+ return parseDefaultFormat(rawValue);
115
+ default:
116
+ return rawValue;
117
+ }
118
+ }
119
+ async function getConfigValue(key, homeDir) {
120
+ const field = resolveConfigField(key);
121
+ const config = await readLocalConfig(homeDir);
122
+ return config[field];
123
+ }
124
+ async function setConfigValue(key, rawValue, homeDir) {
125
+ const field = resolveConfigField(key);
126
+ const value = parseConfigValue(field, rawValue);
127
+ const configPath = await saveLocalConfig({ [field]: value }, homeDir);
128
+ return {
129
+ configPath,
130
+ field,
131
+ value
132
+ };
133
+ }
134
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RuntimeConfig } from '../types/config';
2
+ export declare const DEFAULT_API_BASE_URL = "https://run.xcrawl.com";
3
+ export declare const DEFAULT_RUNTIME_CONFIG: RuntimeConfig;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_RUNTIME_CONFIG = exports.DEFAULT_API_BASE_URL = void 0;
4
+ exports.DEFAULT_API_BASE_URL = 'https://run.xcrawl.com';
5
+ exports.DEFAULT_RUNTIME_CONFIG = {
6
+ apiBaseUrl: exports.DEFAULT_API_BASE_URL,
7
+ defaultFormat: 'markdown',
8
+ outputDir: '.xcrawl',
9
+ timeoutMs: 30000,
10
+ debug: false
11
+ };
12
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/core/constants.ts"],"names":[],"mappings":";;;AAEa,QAAA,oBAAoB,GAAG,wBAAwB,CAAC;AAEhD,QAAA,sBAAsB,GAAkB;IACnD,UAAU,EAAE,4BAAoB;IAChC,aAAa,EAAE,UAAU;IACzB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,KAAK;CACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { XCrawlConfig } from '../types/config';
2
+ export declare function readEnvConfig(env?: NodeJS.ProcessEnv): XCrawlConfig;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readEnvConfig = readEnvConfig;
4
+ function parseBoolean(value) {
5
+ if (value === undefined) {
6
+ return undefined;
7
+ }
8
+ const normalized = value.trim().toLowerCase();
9
+ if (['1', 'true', 'yes', 'on'].includes(normalized)) {
10
+ return true;
11
+ }
12
+ if (['0', 'false', 'no', 'off'].includes(normalized)) {
13
+ return false;
14
+ }
15
+ return undefined;
16
+ }
17
+ function parseNumber(value) {
18
+ if (!value) {
19
+ return undefined;
20
+ }
21
+ const parsed = Number.parseInt(value, 10);
22
+ return Number.isFinite(parsed) ? parsed : undefined;
23
+ }
24
+ function readEnvConfig(env = process.env) {
25
+ return {
26
+ apiKey: env.XCRAWL_API_KEY,
27
+ apiBaseUrl: env.XCRAWL_API_BASE_URL,
28
+ defaultFormat: env.XCRAWL_DEFAULT_FORMAT,
29
+ outputDir: env.XCRAWL_OUTPUT_DIR,
30
+ timeoutMs: parseNumber(env.XCRAWL_TIMEOUT_MS),
31
+ debug: parseBoolean(env.XCRAWL_DEBUG)
32
+ };
33
+ }
34
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":";;AA4BA,sCASC;AAnCD,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED,SAAgB,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IAChE,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,cAAc;QAC1B,UAAU,EAAE,GAAG,CAAC,mBAAmB;QACnC,aAAa,EAAE,GAAG,CAAC,qBAAsD;QACzE,SAAS,EAAE,GAAG,CAAC,iBAAiB;QAChC,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC7C,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ export interface CliErrorShape {
2
+ code: string;
3
+ message: string;
4
+ hint?: string;
5
+ cause?: unknown;
6
+ }
7
+ export declare class CliError extends Error implements CliErrorShape {
8
+ code: string;
9
+ hint?: string;
10
+ cause?: unknown;
11
+ constructor(code: string, message: string, hint?: string, cause?: unknown);
12
+ }
13
+ export declare class ConfigError extends CliError {
14
+ constructor(message: string, hint?: string, cause?: unknown);
15
+ }
16
+ export declare class AuthError extends CliError {
17
+ constructor(message: string, hint?: string, cause?: unknown);
18
+ }
19
+ export declare class ApiError extends CliError {
20
+ status?: number;
21
+ constructor(message: string, hint?: string, status?: number, cause?: unknown);
22
+ }
23
+ export declare class ValidationError extends CliError {
24
+ constructor(message: string, hint?: string, cause?: unknown);
25
+ }
26
+ export declare class OutputError extends CliError {
27
+ constructor(message: string, hint?: string, cause?: unknown);
28
+ }
29
+ export declare class NetworkError extends CliError {
30
+ constructor(message: string, hint?: string, cause?: unknown);
31
+ }
32
+ export declare function toCliError(error: unknown): CliError;
33
+ export declare function formatErrorForUser(error: unknown): string;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NetworkError = exports.OutputError = exports.ValidationError = exports.ApiError = exports.AuthError = exports.ConfigError = exports.CliError = void 0;
4
+ exports.toCliError = toCliError;
5
+ exports.formatErrorForUser = formatErrorForUser;
6
+ class CliError extends Error {
7
+ constructor(code, message, hint, cause) {
8
+ super(message);
9
+ this.code = code;
10
+ this.hint = hint;
11
+ this.cause = cause;
12
+ }
13
+ }
14
+ exports.CliError = CliError;
15
+ class ConfigError extends CliError {
16
+ constructor(message, hint, cause) {
17
+ super('CONFIG_ERROR', message, hint, cause);
18
+ }
19
+ }
20
+ exports.ConfigError = ConfigError;
21
+ class AuthError extends CliError {
22
+ constructor(message, hint, cause) {
23
+ super('AUTH_ERROR', message, hint, cause);
24
+ }
25
+ }
26
+ exports.AuthError = AuthError;
27
+ class ApiError extends CliError {
28
+ constructor(message, hint, status, cause) {
29
+ super('API_ERROR', message, hint, cause);
30
+ this.status = status;
31
+ }
32
+ }
33
+ exports.ApiError = ApiError;
34
+ class ValidationError extends CliError {
35
+ constructor(message, hint, cause) {
36
+ super('VALIDATION_ERROR', message, hint, cause);
37
+ }
38
+ }
39
+ exports.ValidationError = ValidationError;
40
+ class OutputError extends CliError {
41
+ constructor(message, hint, cause) {
42
+ super('OUTPUT_ERROR', message, hint, cause);
43
+ }
44
+ }
45
+ exports.OutputError = OutputError;
46
+ class NetworkError extends CliError {
47
+ constructor(message, hint, cause) {
48
+ super('NETWORK_ERROR', message, hint, cause);
49
+ }
50
+ }
51
+ exports.NetworkError = NetworkError;
52
+ function toCliError(error) {
53
+ if (error instanceof CliError) {
54
+ return error;
55
+ }
56
+ if (error instanceof Error) {
57
+ return new CliError('UNKNOWN_ERROR', error.message, 'Please retry, or run with --debug for more details.', error);
58
+ }
59
+ return new CliError('UNKNOWN_ERROR', 'An unknown error occurred.', 'Please retry, or verify your input arguments.', error);
60
+ }
61
+ function formatErrorForUser(error) {
62
+ const cliError = toCliError(error);
63
+ const hintText = cliError.hint ? `\nHint: ${cliError.hint}` : '';
64
+ return `[${cliError.code}] ${cliError.message}${hintText}`;
65
+ }
66
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":";;;AA2DA,gCAUC;AAED,gDAIC;AApED,MAAa,QAAS,SAAQ,KAAK;IAKjC,YAAY,IAAY,EAAE,OAAe,EAAE,IAAa,EAAE,KAAe;QACvE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAXD,4BAWC;AAED,MAAa,WAAY,SAAQ,QAAQ;IACvC,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF;AAJD,kCAIC;AAED,MAAa,SAAU,SAAQ,QAAQ;IACrC,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;CACF;AAJD,8BAIC;AAED,MAAa,QAAS,SAAQ,QAAQ;IAGpC,YAAY,OAAe,EAAE,IAAa,EAAE,MAAe,EAAE,KAAe;QAC1E,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAPD,4BAOC;AAED,MAAa,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF;AAJD,0CAIC;AAED,MAAa,WAAY,SAAQ,QAAQ;IACvC,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF;AAJD,kCAIC;AAED,MAAa,YAAa,SAAQ,QAAQ;IACxC,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;CACF;AAJD,oCAIC;AAED,SAAgB,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC,OAAO,EAAE,qDAAqD,EAAE,KAAK,CAAC,CAAC;IACpH,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,eAAe,EAAE,4BAA4B,EAAE,+CAA+C,EAAE,KAAK,CAAC,CAAC;AAC7H,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function ensureDir(dirPath: string): Promise<void>;
2
+ export declare function writeUtf8File(filePath: string, content: string): Promise<void>;
3
+ export declare function toSafeFileName(input: string): string;
@@ -0,0 +1,37 @@
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.ensureDir = ensureDir;
7
+ exports.writeUtf8File = writeUtf8File;
8
+ exports.toSafeFileName = toSafeFileName;
9
+ const promises_1 = require("node:fs/promises");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const errors_1 = require("./errors");
12
+ async function ensureDir(dirPath) {
13
+ try {
14
+ await (0, promises_1.mkdir)(dirPath, { recursive: true });
15
+ }
16
+ catch (error) {
17
+ throw new errors_1.OutputError(`Failed to create directory: ${dirPath}`, 'Please check permissions or the output path.', error);
18
+ }
19
+ }
20
+ async function writeUtf8File(filePath, content) {
21
+ const dirPath = node_path_1.default.dirname(filePath);
22
+ await ensureDir(dirPath);
23
+ try {
24
+ await (0, promises_1.writeFile)(filePath, content, 'utf8');
25
+ }
26
+ catch (error) {
27
+ throw new errors_1.OutputError(`Failed to write file: ${filePath}`, 'Please check the file path or disk permissions.', error);
28
+ }
29
+ }
30
+ function toSafeFileName(input) {
31
+ return input
32
+ .replace(/^https?:\/\//i, '')
33
+ .replace(/[^a-zA-Z0-9._-]+/g, '_')
34
+ .replace(/^_+|_+$/g, '')
35
+ .slice(0, 120) || 'result';
36
+ }
37
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/core/files.ts"],"names":[],"mappings":";;;;;AAKA,8BAMC;AAED,sCASC;AAED,wCAMC;AA9BD,+CAAoD;AACpD,0DAA6B;AAE7B,qCAAuC;AAEhC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,IAAI,CAAC;QACH,MAAM,IAAA,gBAAK,EAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,oBAAW,CAAC,+BAA+B,OAAO,EAAE,EAAE,8CAA8C,EAAE,KAAK,CAAC,CAAC;IACzH,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe;IACnE,MAAM,OAAO,GAAG,mBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,IAAA,oBAAS,EAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,oBAAW,CAAC,yBAAyB,QAAQ,EAAE,EAAE,iDAAiD,EAAE,KAAK,CAAC,CAAC;IACvH,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,KAAa;IAC1C,OAAO,KAAK;SACT,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;SACjC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface Logger {
2
+ info(message: string): void;
3
+ warn(message: string): void;
4
+ error(message: string): void;
5
+ success(message: string): void;
6
+ debug(message: string): void;
7
+ }
8
+ interface LoggerOptions {
9
+ stdout?: NodeJS.WritableStream;
10
+ stderr?: NodeJS.WritableStream;
11
+ debug?: boolean;
12
+ }
13
+ export declare function createLogger(options?: LoggerOptions): Logger;
14
+ export {};
@@ -0,0 +1,32 @@
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.createLogger = createLogger;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ function createLogger(options = {}) {
9
+ const stdout = options.stdout ?? process.stdout;
10
+ const stderr = options.stderr ?? process.stderr;
11
+ const debugEnabled = options.debug ?? false;
12
+ return {
13
+ info(message) {
14
+ stdout.write(`${message}\n`);
15
+ },
16
+ warn(message) {
17
+ stderr.write(`${chalk_1.default.yellow('WARN')} ${message}\n`);
18
+ },
19
+ error(message) {
20
+ stderr.write(`${chalk_1.default.red('ERROR')} ${message}\n`);
21
+ },
22
+ success(message) {
23
+ stdout.write(`${chalk_1.default.green('OK')} ${message}\n`);
24
+ },
25
+ debug(message) {
26
+ if (debugEnabled) {
27
+ stderr.write(`${chalk_1.default.gray('DEBUG')} ${message}\n`);
28
+ }
29
+ }
30
+ };
31
+ }
32
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":";;;;;AAgBA,oCAwBC;AAxCD,kDAA0B;AAgB1B,SAAgB,YAAY,CAAC,UAAyB,EAAE;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IAE5C,OAAO;QACL,IAAI,CAAC,OAAe;YAClB,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,OAAe;YAClB,MAAM,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,KAAK,CAAC,OAAe;YACnB,MAAM,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,CAAC,OAAe;YACrB,MAAM,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,CAAC,OAAe;YACnB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface OutputContext {
2
+ stdout: NodeJS.WritableStream;
3
+ }
4
+ export interface RenderOutputInput<T> {
5
+ ctx: OutputContext;
6
+ data: T;
7
+ json?: boolean;
8
+ outputPath?: string;
9
+ renderText: (data: T) => string;
10
+ }
11
+ export declare function renderOutput<T>(input: RenderOutputInput<T>): Promise<void>;
12
+ interface BatchOutputItem {
13
+ fileName: string;
14
+ content: string;
15
+ }
16
+ export declare function writeBatchOutput(dirPath: string, items: BatchOutputItem[], stdout: NodeJS.WritableStream): Promise<void>;
17
+ export {};
@@ -0,0 +1,29 @@
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.renderOutput = renderOutput;
7
+ exports.writeBatchOutput = writeBatchOutput;
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const json_1 = require("../formatters/json");
10
+ const files_1 = require("./files");
11
+ async function renderOutput(input) {
12
+ const json = input.json ?? false;
13
+ const content = json ? (0, json_1.toStableJson)(input.data) : `${input.renderText(input.data)}\n`;
14
+ if (input.outputPath) {
15
+ await (0, files_1.writeUtf8File)(input.outputPath, content);
16
+ input.ctx.stdout.write(`Saved output: ${input.outputPath}\n`);
17
+ return;
18
+ }
19
+ input.ctx.stdout.write(content);
20
+ }
21
+ async function writeBatchOutput(dirPath, items, stdout) {
22
+ await (0, files_1.ensureDir)(dirPath);
23
+ for (const item of items) {
24
+ const fullPath = node_path_1.default.join(dirPath, item.fileName);
25
+ await (0, files_1.writeUtf8File)(fullPath, item.content);
26
+ stdout.write(`Saved output: ${fullPath}\n`);
27
+ }
28
+ }
29
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/core/output.ts"],"names":[],"mappings":";;;;;AAiBA,oCAWC;AAOD,4CAQC;AA3CD,0DAA6B;AAE7B,6CAAkD;AAClD,mCAAmD;AAc5C,KAAK,UAAU,YAAY,CAAI,KAA2B;IAC/D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAA,mBAAY,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IAEtF,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,MAAM,IAAA,qBAAa,EAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAOM,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,KAAwB,EAAE,MAA6B;IAC7G,MAAM,IAAA,iBAAS,EAAC,OAAO,CAAC,CAAC;IAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,IAAA,qBAAa,EAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,iBAAiB,QAAQ,IAAI,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function toStableJson(input: unknown, pretty?: boolean): string;