maintouch 0.1.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.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Maintouch CLI
2
+
3
+ The Maintouch CLI wraps the public API in a script-friendly command line tool.
4
+
5
+ ```bash
6
+ maintouch
7
+ maintouch auth setup
8
+ maintouch auth validate
9
+ maintouch posts export --status scheduled
10
+ maintouch performance summary --start-date 2026-01-01 --end-date 2026-03-31
11
+ maintouch on-page actions --limit 25
12
+ ```
13
+
14
+ ## Install
15
+
16
+ From this monorepo:
17
+
18
+ ```bash
19
+ pnpm --filter maintouch build
20
+ node packages/cli/dist/index.js help
21
+ ```
22
+
23
+ When published:
24
+
25
+ ```bash
26
+ npm install -g maintouch
27
+ ```
28
+
29
+ ## Auth
30
+
31
+ Run `maintouch` to open the interactive shell. Inside the shell you can type commands without the `maintouch` prefix.
32
+
33
+ ```text
34
+ maintouch › setup
35
+ Maintouch API key:
36
+ maintouch › posts export --status scheduled
37
+ ```
38
+
39
+ Save your API key once.
40
+
41
+ ```bash
42
+ maintouch auth setup
43
+ ```
44
+
45
+ The CLI opens Maintouch in your browser, where you can create a CLI API key with one click. Copy the new key, return to the terminal, and paste it into the hidden prompt. The CLI stores credentials in `~/.config/maintouch/config.json` with `0600` permissions. `maintouch auth login` still works as an alias, but `auth setup` is the clearer command because this configures API-key access. Avoid passing live API keys with `--api-key` in a shell because that can leave the key in shell history.
46
+
47
+ Check the active credential source.
48
+
49
+ ```bash
50
+ maintouch auth status
51
+ ```
52
+
53
+ Environment variables and flags still work as one-off overrides.
54
+
55
+ ```bash
56
+ export MAINTOUCH_API_KEY="mt_live_YOUR_KEY_HERE"
57
+ maintouch posts export
58
+ ```
59
+
60
+ The default API URL is `https://api.maintouch.com`. Override it with `MAINTOUCH_API_URL` or `--base-url` only for trusted development endpoints. By default, the CLI refuses to send API keys to non-Maintouch hosts except localhost. Use `--allow-insecure-base-url` or `MAINTOUCH_ALLOW_INSECURE_API_URL=1` only when you control the target server.
61
+
62
+ The browser login helper opens `https://app.maintouch.com` by default. Override it with `MAINTOUCH_APP_URL` for local development.
63
+
64
+ Network requests time out after 30 seconds. Override this with `--timeout <milliseconds>` or `MAINTOUCH_TIMEOUT_MS`.
65
+
66
+ ## Commands
67
+
68
+ Run `maintouch help` for the full command list.
69
+
70
+ The CLI prints JSON by default. Use `--raw` when you want compact JSON.
71
+
72
+ ```bash
73
+ maintouch keyword-gaps gaps --competitors acme.com,rival.io --limit 10
74
+ maintouch request GET /v1/performance/pages --query period=3m --query limit=10
75
+ ```
package/dist/args.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export type ParsedArgs = {
2
+ positional: string[];
3
+ options: Record<string, string | boolean | string[]>;
4
+ };
5
+ export declare function parseArgs(argv: string[]): ParsedArgs;
6
+ export declare function splitCommandLine(input: string): string[];
7
+ export declare function toCamelCase(value: string): string;
8
+ export declare function getString(options: ParsedArgs["options"], key: string): string | undefined;
9
+ export declare function getBoolean(options: ParsedArgs["options"], key: string): boolean;
10
+ export declare function getStringList(options: ParsedArgs["options"], key: string): string[];
11
+ export declare function getRepeatedStrings(options: ParsedArgs["options"], key: string): string[];
12
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;CACtD,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA4CpD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgDxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAiBD,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKzF;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQnF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKxF"}
package/dist/args.js ADDED
@@ -0,0 +1,125 @@
1
+ export function parseArgs(argv) {
2
+ const positional = [];
3
+ const options = {};
4
+ for (let index = 0; index < argv.length; index += 1) {
5
+ const arg = argv[index];
6
+ if (arg === "--") {
7
+ positional.push(...argv.slice(index + 1));
8
+ break;
9
+ }
10
+ if (!arg.startsWith("-") || arg === "-") {
11
+ positional.push(arg);
12
+ continue;
13
+ }
14
+ if (arg.startsWith("--no-")) {
15
+ options[toCamelCase(arg.slice(5))] = false;
16
+ continue;
17
+ }
18
+ const option = arg.startsWith("--") ? arg.slice(2) : arg.slice(1);
19
+ const equalsIndex = option.indexOf("=");
20
+ const rawKey = equalsIndex === -1 ? option : option.slice(0, equalsIndex);
21
+ const key = toCamelCase(rawKey);
22
+ const inlineValue = equalsIndex === -1 ? undefined : option.slice(equalsIndex + 1);
23
+ if (inlineValue !== undefined) {
24
+ addOption(options, key, inlineValue);
25
+ continue;
26
+ }
27
+ const next = argv[index + 1];
28
+ if (next !== undefined && (!next.startsWith("-") || next === "-")) {
29
+ addOption(options, key, next);
30
+ index += 1;
31
+ continue;
32
+ }
33
+ addOption(options, key, true);
34
+ }
35
+ return { positional, options };
36
+ }
37
+ export function splitCommandLine(input) {
38
+ const args = [];
39
+ let current = "";
40
+ let quote;
41
+ let escaping = false;
42
+ for (const char of input.trim()) {
43
+ if (escaping) {
44
+ current += char;
45
+ escaping = false;
46
+ continue;
47
+ }
48
+ if (char === "\\") {
49
+ escaping = true;
50
+ continue;
51
+ }
52
+ if (quote !== undefined) {
53
+ if (char === quote) {
54
+ quote = undefined;
55
+ }
56
+ else {
57
+ current += char;
58
+ }
59
+ continue;
60
+ }
61
+ if (char === "\"" || char === "'") {
62
+ quote = char;
63
+ continue;
64
+ }
65
+ if (/\s/.test(char)) {
66
+ if (current.length > 0) {
67
+ args.push(current);
68
+ current = "";
69
+ }
70
+ continue;
71
+ }
72
+ current += char;
73
+ }
74
+ if (escaping)
75
+ current += "\\";
76
+ if (quote !== undefined)
77
+ throw new Error(`Unclosed ${quote} quote.`);
78
+ if (current.length > 0)
79
+ args.push(current);
80
+ return args;
81
+ }
82
+ export function toCamelCase(value) {
83
+ return value.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
84
+ }
85
+ function addOption(options, key, value) {
86
+ const current = options[key];
87
+ if (current === undefined) {
88
+ options[key] = value;
89
+ return;
90
+ }
91
+ if (Array.isArray(current)) {
92
+ current.push(String(value));
93
+ return;
94
+ }
95
+ options[key] = [String(current), String(value)];
96
+ }
97
+ export function getString(options, key) {
98
+ const value = options[key];
99
+ if (Array.isArray(value))
100
+ return value.at(-1);
101
+ if (typeof value === "string")
102
+ return value;
103
+ return undefined;
104
+ }
105
+ export function getBoolean(options, key) {
106
+ return options[key] === true;
107
+ }
108
+ export function getStringList(options, key) {
109
+ const value = options[key];
110
+ if (value === undefined || value === false)
111
+ return [];
112
+ const values = Array.isArray(value) ? value : [value];
113
+ return values
114
+ .flatMap(item => String(item).split(","))
115
+ .map(item => item.trim())
116
+ .filter(Boolean);
117
+ }
118
+ export function getRepeatedStrings(options, key) {
119
+ const value = options[key];
120
+ if (value === undefined || value === false)
121
+ return [];
122
+ const values = Array.isArray(value) ? value : [value];
123
+ return values.map(item => String(item));
124
+ }
125
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function colorize(value: string, color: "orange" | "bold" | "muted", enabled: boolean): string;
2
+ export declare function renderHeader(enabled?: boolean, columns?: number): string;
3
+ export declare function renderVersion(enabled?: boolean, columns?: number): string;
4
+ //# sourceMappingURL=ascii.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii.d.ts","sourceRoot":"","sources":["../src/ascii.ts"],"names":[],"mappings":"AA8BA,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAKpG;AAED,wBAAgB,YAAY,CAAC,OAAO,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAUjE;AAED,wBAAgB,aAAa,CAAC,OAAO,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAElE"}
package/dist/ascii.js ADDED
@@ -0,0 +1,47 @@
1
+ const RESET = "\x1b[0m";
2
+ const BOLD = "\x1b[1m";
3
+ const MUTED = "\x1b[2m";
4
+ const ORANGE = "\x1b[38;2;255;101;0m";
5
+ const WIDE_WORDMARK = String.raw `
6
+ ███╗ ███╗ █████╗ ██╗███╗ ██╗████████╗ ██████╗ ██╗ ██╗ ██████╗██╗ ██╗
7
+ ████╗ ████║██╔══██╗██║████╗ ██║╚══██╔══╝██╔═══██╗██║ ██║██╔════╝██║ ██║
8
+ ██╔████╔██║███████║██║██╔██╗ ██║ ██║ ██║ ██║██║ ██║██║ ███████║
9
+ ██║╚██╔╝██║██╔══██║██║██║╚██╗██║ ██║ ██║ ██║██║ ██║██║ ██╔══██║
10
+ ██║ ╚═╝ ██║██║ ██║██║██║ ╚████║ ██║ ╚██████╔╝╚██████╔╝╚██████╗██║ ██║
11
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝
12
+ `.trim().split("\n");
13
+ const COMPACT_WORDMARK = String.raw `
14
+ ███╗ ███╗ █████╗ ██╗███╗ ██╗████████╗
15
+ ████╗ ████║██╔══██╗██║████╗ ██║╚══██╔══╝
16
+ ██╔████╔██║███████║██║██╔██╗ ██║ ██║
17
+ ██║╚██╔╝██║██╔══██║██║██║╚██╗██║ ██║
18
+ ██║ ╚═╝ ██║██║ ██║██║██║ ╚████║ ██║
19
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝
20
+
21
+ ████████╗ ██████╗ ██╗ ██╗ ██████╗██╗ ██╗
22
+ ╚══██╔══╝██╔═══██╗██║ ██║██╔════╝██║ ██║
23
+ ██║ ██║ ██║██║ ██║██║ ███████║
24
+ ██║ ██║ ██║██║ ██║██║ ██╔══██║
25
+ ██║ ╚██████╔╝╚██████╔╝╚██████╗██║ ██║
26
+ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝
27
+ `.trim().split("\n");
28
+ export function colorize(value, color, enabled) {
29
+ if (!enabled)
30
+ return value;
31
+ const code = color === "orange" ? ORANGE : color === "bold" ? BOLD : MUTED;
32
+ return `${code}${value}${RESET}`;
33
+ }
34
+ export function renderHeader(enabled = true, columns = 80) {
35
+ const muted = (value) => colorize(value, "muted", enabled);
36
+ const wordmark = columns >= 79 ? WIDE_WORDMARK : COMPACT_WORDMARK;
37
+ return [
38
+ "",
39
+ ...wordmark.map(row => (row.length === 0 ? "" : ` ${colorize(row, "orange", enabled)}`)),
40
+ "",
41
+ ` ${colorize("✦", "orange", enabled)} ${colorize("Maintouch CLI", "bold", enabled)} ${muted("public API shell")}`,
42
+ ].join("\n");
43
+ }
44
+ export function renderVersion(enabled = true, columns = 80) {
45
+ return `${renderHeader(enabled, columns)}\n\n${colorize("maintouch", "bold", enabled)} 0.1.0\n`;
46
+ }
47
+ //# sourceMappingURL=ascii.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii.js","sourceRoot":"","sources":["../src/ascii.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,MAAM,GAAG,sBAAsB,CAAC;AAEtC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;CAO/B,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAErB,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;CAclC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAErB,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,KAAkC,EAAE,OAAgB;IAC1F,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3B,MAAM,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,EAAE;IACvD,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAElE,OAAO;QACL,EAAE;QACF,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACxF,EAAE;QACF,IAAI,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,EAAE;KAClH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,EAAE;IACxD,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC;AAClG,CAAC"}
@@ -0,0 +1,23 @@
1
+ export type MaintouchConfig = {
2
+ apiKey?: string;
3
+ baseUrl?: string;
4
+ };
5
+ export declare const DEFAULT_BASE_URL = "https://api.maintouch.com";
6
+ export declare const DEFAULT_APP_URL = "https://app.maintouch.com";
7
+ export declare function getConfigPath(env: NodeJS.ProcessEnv): string;
8
+ export declare function readConfig(env: NodeJS.ProcessEnv): MaintouchConfig;
9
+ export declare function writeConfig(env: NodeJS.ProcessEnv, config: MaintouchConfig): string;
10
+ export declare function deleteConfig(env: NodeJS.ProcessEnv): boolean;
11
+ export declare function resolveCredentials(env: NodeJS.ProcessEnv, options: {
12
+ apiKey?: string;
13
+ baseUrl?: string;
14
+ }): {
15
+ apiKey: string | undefined;
16
+ baseUrl: string;
17
+ source: string;
18
+ configPath: string;
19
+ };
20
+ export declare function resolveAppUrl(env: NodeJS.ProcessEnv): string;
21
+ export declare function isSafeBaseUrl(baseUrl: string): boolean;
22
+ export declare function redactKey(key: string | undefined): string;
23
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAG3D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAK5D;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,eAAe,CAelE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM,CAMnF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAK5D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;EAexG;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAE5D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYtD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIzD"}
package/dist/config.js ADDED
@@ -0,0 +1,87 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ export const DEFAULT_BASE_URL = "https://api.maintouch.com";
5
+ export const DEFAULT_APP_URL = "https://app.maintouch.com";
6
+ const LOCAL_API_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
7
+ export function getConfigPath(env) {
8
+ if (env.MAINTOUCH_CONFIG)
9
+ return env.MAINTOUCH_CONFIG;
10
+ const configHome = env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
11
+ return join(configHome, "maintouch", "config.json");
12
+ }
13
+ export function readConfig(env) {
14
+ const path = getConfigPath(env);
15
+ if (!existsSync(path))
16
+ return {};
17
+ try {
18
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
19
+ if (!parsed || typeof parsed !== "object")
20
+ return {};
21
+ return {
22
+ apiKey: getStringField(parsed, "apiKey"),
23
+ baseUrl: getStringField(parsed, "baseUrl"),
24
+ };
25
+ }
26
+ catch {
27
+ return {};
28
+ }
29
+ }
30
+ export function writeConfig(env, config) {
31
+ const path = getConfigPath(env);
32
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
33
+ writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
34
+ chmodSync(path, 0o600);
35
+ return path;
36
+ }
37
+ export function deleteConfig(env) {
38
+ const path = getConfigPath(env);
39
+ if (!existsSync(path))
40
+ return false;
41
+ rmSync(path);
42
+ return true;
43
+ }
44
+ export function resolveCredentials(env, options) {
45
+ const config = readConfig(env);
46
+ return {
47
+ apiKey: options.apiKey ?? env.MAINTOUCH_API_KEY ?? env.MT_API_KEY ?? config.apiKey,
48
+ baseUrl: options.baseUrl ?? env.MAINTOUCH_API_URL ?? config.baseUrl ?? DEFAULT_BASE_URL,
49
+ source: options.apiKey
50
+ ? "flag"
51
+ : env.MAINTOUCH_API_KEY || env.MT_API_KEY
52
+ ? "environment"
53
+ : config.apiKey
54
+ ? "config"
55
+ : "missing",
56
+ configPath: getConfigPath(env),
57
+ };
58
+ }
59
+ export function resolveAppUrl(env) {
60
+ return env.MAINTOUCH_APP_URL ?? DEFAULT_APP_URL;
61
+ }
62
+ export function isSafeBaseUrl(baseUrl) {
63
+ try {
64
+ const url = new URL(baseUrl);
65
+ const defaultUrl = new URL(DEFAULT_BASE_URL);
66
+ const isHttp = url.protocol === "http:" || url.protocol === "https:";
67
+ if (!isHttp)
68
+ return false;
69
+ // keep live api keys on maintouch or local dev origins by default
70
+ return url.origin === defaultUrl.origin || LOCAL_API_HOSTS.has(url.hostname);
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ export function redactKey(key) {
77
+ if (!key)
78
+ return "(not set)";
79
+ if (key.length <= 14)
80
+ return `${key.slice(0, 4)}...`;
81
+ return `${key.slice(0, 10)}...${key.slice(-4)}`;
82
+ }
83
+ function getStringField(value, key) {
84
+ const field = value[key];
85
+ return typeof field === "string" && field.length > 0 ? field : undefined;
86
+ }
87
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/help.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare function introText(color?: boolean, columns?: number): string;
2
+ export declare function shellIntroText(color?: boolean, columns?: number): string;
3
+ export declare function helpText(color?: boolean, columns?: number): string;
4
+ export declare function commandsText(color?: boolean, columns?: number): string;
5
+ export declare function workflowsText(color?: boolean, columns?: number): string;
6
+ export declare function topicHelpText(topic: string | undefined, color?: boolean, columns?: number): string | undefined;
7
+ //# sourceMappingURL=help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAQ5D;AAED,wBAAgB,cAAc,CAAC,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAOjE;AAED,wBAAgB,QAAQ,CAAC,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAe3D;AAED,wBAAgB,YAAY,CAAC,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAwC/D;AAED,wBAAgB,aAAa,CAAC,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,CAiChE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,UAAO,EAAE,OAAO,SAAK,GAAG,MAAM,GAAG,SAAS,CA2FvG"}
package/dist/help.js ADDED
@@ -0,0 +1,196 @@
1
+ import { colorize, renderHeader } from "./ascii.js";
2
+ export function introText(color = true, columns = 80) {
3
+ const detail = (value) => colorize(value, "muted", color);
4
+ return `${renderHeader(color, columns)}
5
+
6
+ ${detail("Run")} maintouch ${detail("in a terminal to open the shell.")}
7
+ ${detail("Run")} maintouch help ${detail("to see commands.")}
8
+ `;
9
+ }
10
+ export function shellIntroText(color = true, columns = 80) {
11
+ const detail = (value) => colorize(value, "muted", color);
12
+ return `${renderHeader(color, columns)}
13
+
14
+ ${detail("Type")} help ${detail("for commands,")} status ${detail("for auth,")} exit ${detail("to quit.")}
15
+ `;
16
+ }
17
+ export function helpText(color = true, columns = 80) {
18
+ const section = (label) => colorize(label, "orange", color);
19
+ const detail = (value) => colorize(value, "muted", color);
20
+ void columns;
21
+ return `${section("Usage")}
22
+ maintouch <command> [options]
23
+
24
+ ${section("Start")}
25
+ maintouch ${detail("Open the interactive shell")}
26
+ maintouch auth setup ${detail("Create and save your API key")}
27
+ maintouch commands ${detail("List commands")}
28
+ maintouch workflows ${detail("See common workflows")}
29
+ maintouch help <group> ${detail("Show focused help")}
30
+ `;
31
+ }
32
+ export function commandsText(color = true, columns = 80) {
33
+ const section = (label) => colorize(label, "orange", color);
34
+ const command = (value) => colorize(value.padEnd(34), "bold", color);
35
+ void columns;
36
+ return `${section("Commands")}
37
+ ${command("auth setup")}Create, save, and validate your API key
38
+ ${command("auth validate")}Check that your API key works
39
+ ${command("auth status")}Show the active credential source
40
+ ${command("auth logout")}Remove saved credentials
41
+ ${command("interactive")}Open the interactive shell
42
+ ${command("posts export")}Export scheduled or published posts
43
+ ${command("posts get")}Get one exported post by ID
44
+ ${command("posts mark-published")}Mark a post live after publishing
45
+ ${command("on-page actions")}List on-page SEO actions
46
+ ${command("on-page mark-resolved")}Resolve one or more SEO actions
47
+ ${command("on-page generate-suggestions")}Generate fixes for SEO actions
48
+ ${command("on-page accept-suggestion")}Accept a generated SEO suggestion
49
+ ${command("on-page ignore")}Ignore one or more SEO actions
50
+ ${command("on-page ignore-page")}Ignore actions for a page
51
+ ${command("ai prompts")}List tracked AI visibility prompts
52
+ ${command("ai prompt")}Get one tracked prompt
53
+ ${command("ai stats")}Get AI visibility rollups
54
+ ${command("ai highlights")}Show winning and at-risk prompts
55
+ ${command("keyword-gaps competitors")}List configured competitors
56
+ ${command("keyword-gaps start")}Start a keyword gap job
57
+ ${command("keyword-gaps jobs")}List keyword gap jobs
58
+ ${command("keyword-gaps job")}Get a keyword gap job
59
+ ${command("keyword-gaps gaps")}List keyword gap opportunities
60
+ ${command("performance summary")}Get dashboard summary metrics
61
+ ${command("performance pages")}Get page performance
62
+ ${command("performance queries")}Get query performance
63
+ ${command("performance live")}Get live performance data
64
+ ${command("content-ideas create")}Create queued content ideas
65
+ ${command("request")}Call any public API route
66
+
67
+ ${section("More Help")}
68
+ maintouch help <group>
69
+ maintouch workflows
70
+ `;
71
+ }
72
+ export function workflowsText(color = true, columns = 80) {
73
+ const section = (label) => colorize(label, "orange", color);
74
+ void columns;
75
+ return `${section("Setup")}
76
+ maintouch auth setup
77
+ maintouch auth validate
78
+
79
+ ${section("Publishing")}
80
+ maintouch posts export --status scheduled
81
+ maintouch posts get <post-id>
82
+ maintouch posts mark-published <post-id> --url <published-url>
83
+
84
+ ${section("On-Page SEO")}
85
+ maintouch on-page actions --limit 25
86
+ maintouch on-page generate-suggestions <action-id>
87
+ maintouch on-page accept-suggestion <action-id>
88
+ maintouch on-page mark-resolved <action-id>
89
+
90
+ ${section("Performance")}
91
+ maintouch performance summary --start-date 2026-01-01 --end-date 2026-03-31
92
+ maintouch performance pages --period 3m --limit 25
93
+ maintouch performance queries --period 3m --limit 25
94
+
95
+ ${section("Keyword Gaps")}
96
+ maintouch keyword-gaps competitors
97
+ maintouch keyword-gaps start --competitor acme.com --competitor rival.io
98
+ maintouch keyword-gaps jobs --status completed
99
+ maintouch keyword-gaps gaps --competitors acme.com --limit 25
100
+
101
+ ${section("Content Queue")}
102
+ maintouch content-ideas create --title "How to improve page speed" --keyword "page speed"
103
+ `;
104
+ }
105
+ export function topicHelpText(topic, color = true, columns = 80) {
106
+ const section = (label) => colorize(label, "orange", color);
107
+ void columns;
108
+ switch (topic) {
109
+ case "auth":
110
+ return `${section("auth")}
111
+ maintouch auth setup [--api-key <key>] [--base-url <url>]
112
+ maintouch auth login [--api-key <key>] [--base-url <url>]
113
+ maintouch auth validate
114
+ maintouch auth status
115
+ maintouch auth logout
116
+
117
+ By default, setup stores credentials in ~/.config/maintouch/config.json.
118
+ Setup opens Maintouch in your browser to create a CLI key.
119
+ auth login is kept as an alias for auth setup.
120
+ The API key prompt is hidden. Prefer MAINTOUCH_API_KEY for scripts.
121
+ Use --api-key only when shell history is not a concern.
122
+ Custom base URLs require --allow-insecure-base-url unless they are localhost.
123
+ `;
124
+ case "interactive":
125
+ case "shell":
126
+ return `${section("interactive")}
127
+ maintouch
128
+ maintouch interactive
129
+ maintouch shell
130
+
131
+ Inside the shell, type commands without the maintouch prefix.
132
+ Aliases: setup, login, status, validate, logout, ?, exit.
133
+ `;
134
+ case "posts":
135
+ case "blogs":
136
+ return `${section("posts")}
137
+ maintouch posts export [--status scheduled|published]
138
+ maintouch posts get <post-id>
139
+ maintouch posts mark-published <post-id> --url <published-url>
140
+
141
+ Use this workflow to pull posts into your CMS and tell Maintouch when the post is live.
142
+ The old "blogs" command group works as an alias.
143
+ `;
144
+ case "on-page":
145
+ return `${section("on-page")}
146
+ maintouch on-page actions [--url <url>] [--type <type>] [--limit <n>] [--offset <n>]
147
+ maintouch on-page generate-suggestions <action-id...>
148
+ maintouch on-page accept-suggestion <action-id...>
149
+ maintouch on-page mark-resolved <action-id...>
150
+ maintouch on-page ignore <action-id...>
151
+ maintouch on-page ignore-page <url>
152
+ `;
153
+ case "ai":
154
+ return `${section("ai")}
155
+ maintouch ai prompts [--limit <n>] [--offset <n>] [--llm-platform <provider>]
156
+ maintouch ai prompt <prompt-id>
157
+ maintouch ai stats [--time-range lastRun|7d|30d|90d|180d|365d]
158
+ maintouch ai highlights [--llm-platform <provider>]
159
+ maintouch ai fan-out-queries [public API query options]
160
+ `;
161
+ case "keyword-gaps":
162
+ return `${section("keyword-gaps")}
163
+ maintouch keyword-gaps competitors
164
+ maintouch keyword-gaps start --competitor <domain> [--competitor <domain>]
165
+ maintouch keyword-gaps jobs [--status scheduled|processing|completed|failed]
166
+ maintouch keyword-gaps job <job-id>
167
+ maintouch keyword-gaps gaps [public API query options]
168
+ `;
169
+ case "performance":
170
+ return `${section("performance")}
171
+ maintouch performance summary [--start-date YYYY-MM-DD] [--end-date YYYY-MM-DD] [--refresh]
172
+ maintouch performance pages [public API query options]
173
+ maintouch performance queries [public API query options]
174
+ maintouch performance live --start-date YYYY-MM-DD --end-date YYYY-MM-DD [public API query options]
175
+ `;
176
+ case "content-ideas":
177
+ return `${section("content-ideas")}
178
+ maintouch content-ideas create --title <title> --keyword <keyword> [--keyword <keyword>]
179
+ maintouch content-ideas create --data '{"ideas":[...],"queuePosition":"tail"}'
180
+ `;
181
+ case "request":
182
+ return `${section("request")}
183
+ maintouch request <method> <path> [--query key=value] [--data '{"json":true}']
184
+
185
+ Use this escape hatch for public API routes that do not have a named command yet.
186
+ Requests time out after 30 seconds. Override with --timeout <milliseconds>.
187
+ `;
188
+ case "commands":
189
+ return commandsText(color, columns);
190
+ case "workflows":
191
+ return workflowsText(color, columns);
192
+ default:
193
+ return undefined;
194
+ }
195
+ }
196
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ export type CliIo = {
3
+ stdin?: NodeJS.ReadStream;
4
+ stdout: Pick<NodeJS.WriteStream, "write"> & {
5
+ columns?: number;
6
+ };
7
+ stderr: Pick<NodeJS.WriteStream, "write">;
8
+ };
9
+ export declare function runCli(argv: string[], env: NodeJS.ProcessEnv, io: CliIo, fetchImpl?: typeof fetch): Promise<number>;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAYA,MAAM,MAAM,KAAK,GAAG;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC;AAEF,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA8GzH"}