@atlasauth/cli 0.5.0 → 0.6.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/CHANGELOG.md +7 -0
- package/dist/args.d.ts +33 -0
- package/dist/args.js +13 -0
- package/dist/args.js.map +1 -1
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.js +116 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/mcp.d.ts +38 -0
- package/dist/commands/mcp.js +108 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/referrals.d.ts +6 -6
- package/dist/commands/referrals.js +28 -28
- package/dist/help.d.ts +1 -1
- package/dist/help.js +52 -5
- package/dist/help.js.map +1 -1
- package/dist/import/csv.d.ts +6 -0
- package/dist/import/csv.js +63 -0
- package/dist/import/csv.js.map +1 -0
- package/dist/import/vendors.d.ts +57 -0
- package/dist/import/vendors.js +568 -0
- package/dist/import/vendors.js.map +1 -0
- package/dist/run.js +4 -0
- package/dist/run.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @atlasauth/cli changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 — 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `atlas import --from <auth0|clerk|supabase|firebase|cognito|authjs|workos|better-auth> <file>`: maps each provider's export onto the bulk import, with `--dry-run`, resumable upsert batches (`--state-file`), `--hashes`, `--hash-config` and `--create-orgs`.
|
|
8
|
+
- `atlas mcp install --cursor | --claude-code | --codex | --vscode`: adds the Atlas MCP server (docs search) to the agent's config.
|
|
9
|
+
|
|
3
10
|
## 0.5.0
|
|
4
11
|
|
|
5
12
|
### Added
|
package/dist/args.d.ts
CHANGED
|
@@ -177,6 +177,39 @@ declare const OPTIONS: {
|
|
|
177
177
|
readonly wait: {
|
|
178
178
|
readonly type: "boolean";
|
|
179
179
|
};
|
|
180
|
+
readonly from: {
|
|
181
|
+
readonly type: "string";
|
|
182
|
+
};
|
|
183
|
+
readonly 'batch-size': {
|
|
184
|
+
readonly type: "string";
|
|
185
|
+
};
|
|
186
|
+
readonly 'state-file': {
|
|
187
|
+
readonly type: "string";
|
|
188
|
+
};
|
|
189
|
+
readonly 'hash-config': {
|
|
190
|
+
readonly type: "string";
|
|
191
|
+
};
|
|
192
|
+
readonly hashes: {
|
|
193
|
+
readonly type: "string";
|
|
194
|
+
};
|
|
195
|
+
readonly 'create-orgs': {
|
|
196
|
+
readonly type: "boolean";
|
|
197
|
+
};
|
|
198
|
+
readonly cursor: {
|
|
199
|
+
readonly type: "boolean";
|
|
200
|
+
};
|
|
201
|
+
readonly 'claude-code': {
|
|
202
|
+
readonly type: "boolean";
|
|
203
|
+
};
|
|
204
|
+
readonly codex: {
|
|
205
|
+
readonly type: "boolean";
|
|
206
|
+
};
|
|
207
|
+
readonly vscode: {
|
|
208
|
+
readonly type: "boolean";
|
|
209
|
+
};
|
|
210
|
+
readonly global: {
|
|
211
|
+
readonly type: "boolean";
|
|
212
|
+
};
|
|
180
213
|
};
|
|
181
214
|
type OptionValue<O> = O extends {
|
|
182
215
|
type: 'boolean';
|
package/dist/args.js
CHANGED
|
@@ -80,6 +80,19 @@ const OPTIONS = {
|
|
|
80
80
|
map: { type: 'string' },
|
|
81
81
|
'metadata-path': { type: 'string' },
|
|
82
82
|
wait: { type: 'boolean' },
|
|
83
|
+
// import --from <vendor>.
|
|
84
|
+
from: { type: 'string' },
|
|
85
|
+
'batch-size': { type: 'string' },
|
|
86
|
+
'state-file': { type: 'string' },
|
|
87
|
+
'hash-config': { type: 'string' },
|
|
88
|
+
hashes: { type: 'string' },
|
|
89
|
+
'create-orgs': { type: 'boolean' },
|
|
90
|
+
// mcp install.
|
|
91
|
+
cursor: { type: 'boolean' },
|
|
92
|
+
'claude-code': { type: 'boolean' },
|
|
93
|
+
codex: { type: 'boolean' },
|
|
94
|
+
vscode: { type: 'boolean' },
|
|
95
|
+
global: { type: 'boolean' },
|
|
83
96
|
};
|
|
84
97
|
/** Parse argv, turning parseArgs' own errors (unknown/invalid flag) into clean CliErrors. */
|
|
85
98
|
function parse(argv) {
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.importUsers = importUsers;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const args_1 = require("../args");
|
|
7
|
+
const errors_1 = require("../errors");
|
|
8
|
+
const output_1 = require("../output");
|
|
9
|
+
const project_1 = require("../project");
|
|
10
|
+
const vendors_1 = require("../import/vendors");
|
|
11
|
+
const shared_1 = require("./shared");
|
|
12
|
+
async function importUsers(ctx, args) {
|
|
13
|
+
const vendor = (0, args_1.str)(args.values, 'from');
|
|
14
|
+
if (!vendor || !vendors_1.VENDORS.includes(vendor)) {
|
|
15
|
+
throw new errors_1.CliError(`import needs --from <${vendors_1.VENDORS.join('|')}>.`);
|
|
16
|
+
}
|
|
17
|
+
const file = args.positionals[1];
|
|
18
|
+
if (!file)
|
|
19
|
+
throw new errors_1.CliError(`import needs the export file: atlas import --from ${vendor} <file>`);
|
|
20
|
+
const text = ctx.readFile(file);
|
|
21
|
+
let doc;
|
|
22
|
+
let hashes;
|
|
23
|
+
try {
|
|
24
|
+
doc = (0, vendors_1.parseExport)(text, file);
|
|
25
|
+
const hashesFile = (0, args_1.str)(args.values, 'hashes');
|
|
26
|
+
if (hashesFile)
|
|
27
|
+
hashes = (0, vendors_1.parseExport)(ctx.readFile(hashesFile), hashesFile);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw new errors_1.CliError(err instanceof Error ? err.message : String(err));
|
|
31
|
+
}
|
|
32
|
+
const { rows, warnings } = (0, vendors_1.mapExport)(vendor, doc, hashes);
|
|
33
|
+
const json = (0, shared_1.wantsJson)(args.values);
|
|
34
|
+
const summary = (0, vendors_1.summarize)(rows);
|
|
35
|
+
let hashConfig;
|
|
36
|
+
const hashConfigFile = (0, args_1.str)(args.values, 'hash-config');
|
|
37
|
+
if (hashConfigFile) {
|
|
38
|
+
try {
|
|
39
|
+
hashConfig = JSON.parse(ctx.readFile(hashConfigFile));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new errors_1.CliError(`--hash-config ${hashConfigFile} is not valid JSON.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (vendor === 'firebase' && (summary.with_password_hash ?? 0) > 0 && !hashConfig && !args.values['dry-run']) {
|
|
46
|
+
throw new errors_1.CliError('Firebase password hashes need the project hash parameters. Copy them from the Firebase console (Authentication > Users > Password hash parameters) into a JSON file and pass --hash-config <file>.');
|
|
47
|
+
}
|
|
48
|
+
if (args.values['dry-run']) {
|
|
49
|
+
if (json)
|
|
50
|
+
(0, output_1.printJson)(ctx.io, { vendor, summary, warnings, sample: rows.slice(0, 3).map(redact) });
|
|
51
|
+
else {
|
|
52
|
+
ctx.io.out(`Dry run: ${rows.length} user(s) mapped from ${vendor}. Nothing was sent.`);
|
|
53
|
+
for (const [k, v] of Object.entries(summary))
|
|
54
|
+
ctx.io.out(` ${k.replace(/_/g, ' ')}: ${v}`);
|
|
55
|
+
for (const w of warnings)
|
|
56
|
+
ctx.io.out(` note: ${w}`);
|
|
57
|
+
}
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
if (rows.length === 0)
|
|
61
|
+
throw new errors_1.CliError('The export contains no users with an email address.');
|
|
62
|
+
const batchSize = Math.min(Math.max(Number((0, args_1.str)(args.values, 'batch-size') ?? 100) || 100, 1), 100);
|
|
63
|
+
const statePath = (0, args_1.str)(args.values, 'state-file') ?? `${file}.atlas-import.json`;
|
|
64
|
+
const sha = (0, node_crypto_1.createHash)('sha256').update(text).digest('hex');
|
|
65
|
+
let state = { vendor, input_sha256: sha, next_index: 0, total: rows.length, succeeded: 0, failed: 0, jobs: [] };
|
|
66
|
+
if ((0, node_fs_1.existsSync)(statePath)) {
|
|
67
|
+
const saved = JSON.parse((0, node_fs_1.readFileSync)(statePath, 'utf8'));
|
|
68
|
+
if (saved.input_sha256 !== sha || saved.vendor !== vendor) {
|
|
69
|
+
throw new errors_1.CliError(`${statePath} belongs to a different export. Delete it or pass --state-file to start over.`);
|
|
70
|
+
}
|
|
71
|
+
state = saved;
|
|
72
|
+
if (state.next_index >= rows.length) {
|
|
73
|
+
ctx.io.out(`Already imported: ${state.succeeded} succeeded, ${state.failed} failed. Delete ${statePath} to run again.`);
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
ctx.io.err(`Resuming at user ${state.next_index + 1} of ${rows.length}.`);
|
|
77
|
+
}
|
|
78
|
+
const auth = (0, shared_1.resolveAuth)(ctx, args.values);
|
|
79
|
+
const http = (0, project_1.httpFor)(ctx, { secretKey: auth.secretKey, apiUrl: auth.apiUrl });
|
|
80
|
+
for (const w of warnings)
|
|
81
|
+
ctx.io.err(`note: ${w}`);
|
|
82
|
+
while (state.next_index < rows.length) {
|
|
83
|
+
const batch = rows.slice(state.next_index, state.next_index + batchSize);
|
|
84
|
+
const body = { users: batch, upsert: true };
|
|
85
|
+
if (args.values['create-orgs'])
|
|
86
|
+
body.create_organizations = true;
|
|
87
|
+
if (hashConfig)
|
|
88
|
+
body.password_hash_config = { firebase: hashConfig };
|
|
89
|
+
let job = await http.post('/v1/user_imports', body);
|
|
90
|
+
// A batch over the inline limit is queued; poll it to completion.
|
|
91
|
+
while (job.status === 'pending' || job.status === 'processing') {
|
|
92
|
+
await (ctx.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))))(2000);
|
|
93
|
+
job = await http.get(`/v1/jobs/${job.id}`);
|
|
94
|
+
}
|
|
95
|
+
state.next_index += batch.length;
|
|
96
|
+
state.succeeded += job.succeeded;
|
|
97
|
+
state.failed += job.failed;
|
|
98
|
+
state.jobs.push(job.id);
|
|
99
|
+
(0, node_fs_1.writeFileSync)(statePath, JSON.stringify(state, null, 2));
|
|
100
|
+
if (!json)
|
|
101
|
+
ctx.io.err(` ${state.next_index}/${rows.length} sent (job ${job.id}: ${job.succeeded} ok, ${job.failed} issues)`);
|
|
102
|
+
}
|
|
103
|
+
if (json)
|
|
104
|
+
(0, output_1.printJson)(ctx.io, { ...state, summary, warnings });
|
|
105
|
+
else {
|
|
106
|
+
ctx.io.out(`Imported ${rows.length} user(s) from ${vendor}: ${state.succeeded} created or updated, ${state.failed} row issue(s).`);
|
|
107
|
+
if (state.failed)
|
|
108
|
+
ctx.io.out(`Per-row issues: GET /v1/jobs/<job-id>/errors for jobs ${state.jobs.join(', ')}`);
|
|
109
|
+
}
|
|
110
|
+
return state.failed > 0 ? 2 : 0;
|
|
111
|
+
}
|
|
112
|
+
/** A dry-run sample never prints a password hash. */
|
|
113
|
+
function redact(row) {
|
|
114
|
+
return row.password_hash ? { ...row, password_hash: '[redacted]', ...(row.password_salt ? { password_salt: '[redacted]' } : {}) } : row;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ParsedArgs } from '../args';
|
|
2
|
+
import type { RunContext } from '../context';
|
|
3
|
+
/**
|
|
4
|
+
* `atlas mcp install --cursor | --claude-code | --codex | --vscode` — add the
|
|
5
|
+
* Atlas MCP server to an AI coding agent's config, so the agent can search and
|
|
6
|
+
* read the Atlas docs while it works.
|
|
7
|
+
*
|
|
8
|
+
* The server runs as `npx -y @atlasauth/mcp`. No key is written: without
|
|
9
|
+
* `ATLAS_SECRET_KEY` it serves only the read-only docs tools, which is what a
|
|
10
|
+
* coding agent needs. Existing servers in the file are kept; an existing
|
|
11
|
+
* `atlas` entry is replaced (or, in Codex's TOML, left alone and reported).
|
|
12
|
+
*/
|
|
13
|
+
export declare const MCP_SERVER_NAME = "atlas";
|
|
14
|
+
export declare const MCP_CLIENTS: readonly ["cursor", "claude-code", "codex", "vscode"];
|
|
15
|
+
export type McpClient = (typeof MCP_CLIENTS)[number];
|
|
16
|
+
interface InstallResult {
|
|
17
|
+
client: McpClient;
|
|
18
|
+
path: string;
|
|
19
|
+
status: 'added' | 'updated' | 'unchanged';
|
|
20
|
+
}
|
|
21
|
+
/** Where each client keeps its MCP config. Project files go under `dir`. */
|
|
22
|
+
export declare function mcpConfigPath(client: McpClient, opts: {
|
|
23
|
+
dir: string;
|
|
24
|
+
global: boolean;
|
|
25
|
+
env: NodeJS.ProcessEnv;
|
|
26
|
+
}): string;
|
|
27
|
+
/** Merge the Atlas server into a JSON MCP config. Pure, for tests. */
|
|
28
|
+
export declare function mergeJsonConfig(existing: string | null, client: McpClient): {
|
|
29
|
+
text: string;
|
|
30
|
+
status: InstallResult['status'];
|
|
31
|
+
};
|
|
32
|
+
/** Append the Atlas server to Codex's TOML config, unless one is already there. Pure, for tests. */
|
|
33
|
+
export declare function mergeCodexToml(existing: string | null): {
|
|
34
|
+
text: string;
|
|
35
|
+
status: InstallResult['status'];
|
|
36
|
+
};
|
|
37
|
+
export declare function mcp(ctx: RunContext, args: ParsedArgs): Promise<number>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MCP_CLIENTS = exports.MCP_SERVER_NAME = void 0;
|
|
4
|
+
exports.mcpConfigPath = mcpConfigPath;
|
|
5
|
+
exports.mergeJsonConfig = mergeJsonConfig;
|
|
6
|
+
exports.mergeCodexToml = mergeCodexToml;
|
|
7
|
+
exports.mcp = mcp;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_os_1 = require("node:os");
|
|
10
|
+
const node_path_1 = require("node:path");
|
|
11
|
+
const args_1 = require("../args");
|
|
12
|
+
const errors_1 = require("../errors");
|
|
13
|
+
const output_1 = require("../output");
|
|
14
|
+
const shared_1 = require("./shared");
|
|
15
|
+
/**
|
|
16
|
+
* `atlas mcp install --cursor | --claude-code | --codex | --vscode` — add the
|
|
17
|
+
* Atlas MCP server to an AI coding agent's config, so the agent can search and
|
|
18
|
+
* read the Atlas docs while it works.
|
|
19
|
+
*
|
|
20
|
+
* The server runs as `npx -y @atlasauth/mcp`. No key is written: without
|
|
21
|
+
* `ATLAS_SECRET_KEY` it serves only the read-only docs tools, which is what a
|
|
22
|
+
* coding agent needs. Existing servers in the file are kept; an existing
|
|
23
|
+
* `atlas` entry is replaced (or, in Codex's TOML, left alone and reported).
|
|
24
|
+
*/
|
|
25
|
+
exports.MCP_SERVER_NAME = 'atlas';
|
|
26
|
+
const COMMAND = 'npx';
|
|
27
|
+
const ARGS = ['-y', '@atlasauth/mcp'];
|
|
28
|
+
exports.MCP_CLIENTS = ['cursor', 'claude-code', 'codex', 'vscode'];
|
|
29
|
+
/** Where each client keeps its MCP config. Project files go under `dir`. */
|
|
30
|
+
function mcpConfigPath(client, opts) {
|
|
31
|
+
const home = opts.env.HOME || (0, node_os_1.homedir)();
|
|
32
|
+
switch (client) {
|
|
33
|
+
case 'cursor':
|
|
34
|
+
return opts.global ? (0, node_path_1.join)(home, '.cursor', 'mcp.json') : (0, node_path_1.join)(opts.dir, '.cursor', 'mcp.json');
|
|
35
|
+
case 'claude-code':
|
|
36
|
+
// Project scope: a checked-in `.mcp.json` that Claude Code offers to the whole team.
|
|
37
|
+
return (0, node_path_1.join)(opts.dir, '.mcp.json');
|
|
38
|
+
case 'vscode':
|
|
39
|
+
return (0, node_path_1.join)(opts.dir, '.vscode', 'mcp.json');
|
|
40
|
+
case 'codex':
|
|
41
|
+
return (0, node_path_1.join)(opts.env.CODEX_HOME || (0, node_path_1.join)(home, '.codex'), 'config.toml');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Merge the Atlas server into a JSON MCP config. Pure, for tests. */
|
|
45
|
+
function mergeJsonConfig(existing, client) {
|
|
46
|
+
let doc = {};
|
|
47
|
+
if (existing && existing.trim()) {
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(existing);
|
|
50
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
51
|
+
throw new Error('not an object');
|
|
52
|
+
doc = parsed;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
throw new errors_1.CliError('The existing MCP config is not valid JSON. Fix or move it, then run this again; it was not changed.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// VS Code calls the map `servers` and wants an explicit transport type.
|
|
59
|
+
const key = client === 'vscode' ? 'servers' : 'mcpServers';
|
|
60
|
+
const entry = client === 'vscode' ? { type: 'stdio', command: COMMAND, args: ARGS } : { command: COMMAND, args: ARGS };
|
|
61
|
+
const servers = (typeof doc[key] === 'object' && doc[key] !== null ? doc[key] : {});
|
|
62
|
+
const before = servers[exports.MCP_SERVER_NAME];
|
|
63
|
+
const status = before === undefined ? 'added' : JSON.stringify(before) === JSON.stringify(entry) ? 'unchanged' : 'updated';
|
|
64
|
+
doc[key] = { ...servers, [exports.MCP_SERVER_NAME]: entry };
|
|
65
|
+
return { text: `${JSON.stringify(doc, null, 2)}\n`, status };
|
|
66
|
+
}
|
|
67
|
+
/** Append the Atlas server to Codex's TOML config, unless one is already there. Pure, for tests. */
|
|
68
|
+
function mergeCodexToml(existing) {
|
|
69
|
+
const current = existing ?? '';
|
|
70
|
+
if (/^\s*\[mcp_servers\.(atlas|"atlas")\]\s*$/m.test(current))
|
|
71
|
+
return { text: current, status: 'unchanged' };
|
|
72
|
+
const block = `[mcp_servers.${exports.MCP_SERVER_NAME}]\ncommand = "${COMMAND}"\nargs = [${ARGS.map((a) => JSON.stringify(a)).join(', ')}]\n`;
|
|
73
|
+
const sep = current === '' ? '' : current.endsWith('\n\n') ? '' : current.endsWith('\n') ? '\n' : '\n\n';
|
|
74
|
+
return { text: `${current}${sep}${block}`, status: 'added' };
|
|
75
|
+
}
|
|
76
|
+
async function mcp(ctx, args) {
|
|
77
|
+
const sub = args.positionals[1];
|
|
78
|
+
if (sub !== 'install')
|
|
79
|
+
throw new errors_1.CliError("Usage: atlas mcp install --cursor | --claude-code | --codex | --vscode");
|
|
80
|
+
const chosen = exports.MCP_CLIENTS.filter((c) => args.values[c] === true);
|
|
81
|
+
if (chosen.length === 0) {
|
|
82
|
+
throw new errors_1.CliError('Choose at least one client: --cursor, --claude-code, --codex or --vscode.');
|
|
83
|
+
}
|
|
84
|
+
const dir = (0, node_path_1.resolve)((0, args_1.str)(args.values, 'dir') ?? process.cwd());
|
|
85
|
+
const global = args.values.global === true;
|
|
86
|
+
const results = [];
|
|
87
|
+
for (const client of chosen) {
|
|
88
|
+
const path = mcpConfigPath(client, { dir, global, env: ctx.env });
|
|
89
|
+
const existing = (0, node_fs_1.existsSync)(path) ? (0, node_fs_1.readFileSync)(path, 'utf8') : null;
|
|
90
|
+
const merged = client === 'codex' ? mergeCodexToml(existing) : mergeJsonConfig(existing, client);
|
|
91
|
+
if (merged.status !== 'unchanged') {
|
|
92
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(path), { recursive: true });
|
|
93
|
+
(0, node_fs_1.writeFileSync)(path, merged.text);
|
|
94
|
+
}
|
|
95
|
+
results.push({ client, path, status: merged.status });
|
|
96
|
+
}
|
|
97
|
+
if ((0, shared_1.wantsJson)(args.values))
|
|
98
|
+
(0, output_1.printJson)(ctx.io, { server: exports.MCP_SERVER_NAME, command: [COMMAND, ...ARGS].join(' '), results });
|
|
99
|
+
else {
|
|
100
|
+
for (const r of results) {
|
|
101
|
+
const verb = r.status === 'unchanged' ? 'already set up in' : r.status === 'updated' ? 'updated in' : 'added to';
|
|
102
|
+
ctx.io.out(`${r.client}: Atlas MCP server ${verb} ${r.path}`);
|
|
103
|
+
}
|
|
104
|
+
ctx.io.out('Restart the client (or reload its MCP servers). It can now search and read the Atlas docs.');
|
|
105
|
+
}
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,12 +4,12 @@ import type { RunContext } from '../context';
|
|
|
4
4
|
* `atlas referrals connect | backfill | status`: referral attribution from the
|
|
5
5
|
* terminal.
|
|
6
6
|
*
|
|
7
|
-
* `connect --provider referally` is bring-your-own-key: the
|
|
8
|
-
* key is used for one call (it creates the Atlas connection on
|
|
9
|
-
* is never stored or printed. The connection id and secret
|
|
7
|
+
* `connect --provider referally` is bring-your-own-key: the Referalli merchant
|
|
8
|
+
* key is used for one call (it creates the Atlas connection on Referalli) and
|
|
9
|
+
* is never stored or printed. The connection id and secret Referalli returns
|
|
10
10
|
* go straight onto the instance; the secret is never printed either.
|
|
11
11
|
*/
|
|
12
|
-
/** The
|
|
12
|
+
/** The Referalli API version pinned on every call. */
|
|
13
13
|
export declare const REFERALLY_VERSION = "2026-10-21";
|
|
14
14
|
interface PingRead {
|
|
15
15
|
ok?: boolean;
|
|
@@ -36,12 +36,12 @@ export declare function pingSkewMs(ping: PingRead, receivedAt: number, latencyMs
|
|
|
36
36
|
export declare function describeTestLines(test: TestRead, receivedAt: number): string[];
|
|
37
37
|
/** A `customerRef,code` CSV → map; throws on a bad line. A header row is skipped. */
|
|
38
38
|
export declare function parseCodeCsv(text: string): Record<string, string>;
|
|
39
|
-
/** The
|
|
39
|
+
/** The Referalli topics two-way sync subscribes to (changes to a referral after sign-up). */
|
|
40
40
|
export declare const REFERALLY_SYNC_TOPICS: readonly ["referral.created", "referral.held", "referral.paused", "referral.resumed", "referral.approved", "referral.voided", "referral.reassigned"];
|
|
41
41
|
/**
|
|
42
42
|
* Whether the merchant key reaches live or test data: the org's `livemode`,
|
|
43
43
|
* else the key prefix (rk_test_ = test; rk_live_ and older rk_ keys = live).
|
|
44
|
-
* `known` is false when
|
|
44
|
+
* `known` is false when Referalli reports no mode (no test mode there).
|
|
45
45
|
*/
|
|
46
46
|
export declare function referallyKeyMode(ctx: RunContext, input: {
|
|
47
47
|
baseUrl: string;
|
|
@@ -19,12 +19,12 @@ const shared_1 = require("./shared");
|
|
|
19
19
|
* `atlas referrals connect | backfill | status`: referral attribution from the
|
|
20
20
|
* terminal.
|
|
21
21
|
*
|
|
22
|
-
* `connect --provider referally` is bring-your-own-key: the
|
|
23
|
-
* key is used for one call (it creates the Atlas connection on
|
|
24
|
-
* is never stored or printed. The connection id and secret
|
|
22
|
+
* `connect --provider referally` is bring-your-own-key: the Referalli merchant
|
|
23
|
+
* key is used for one call (it creates the Atlas connection on Referalli) and
|
|
24
|
+
* is never stored or printed. The connection id and secret Referalli returns
|
|
25
25
|
* go straight onto the instance; the secret is never printed either.
|
|
26
26
|
*/
|
|
27
|
-
/** The
|
|
27
|
+
/** The Referalli API version pinned on every call. */
|
|
28
28
|
exports.REFERALLY_VERSION = '2026-10-21';
|
|
29
29
|
const PROVIDERS = ['referally', 'webhook'];
|
|
30
30
|
/** Read a key from a file, or stdin with '-'. A bare key or a dotenv line. Never printed. */
|
|
@@ -113,7 +113,7 @@ function parseCodeCsv(text) {
|
|
|
113
113
|
});
|
|
114
114
|
return out;
|
|
115
115
|
}
|
|
116
|
-
/** One call to the
|
|
116
|
+
/** One call to the Referalli merchant API with the merchant key. Throws a CliError naming `what` on failure. */
|
|
117
117
|
async function referallyRequest(ctx, input) {
|
|
118
118
|
const fetchImpl = ctx.fetch ?? globalThis.fetch;
|
|
119
119
|
let res;
|
|
@@ -130,7 +130,7 @@ async function referallyRequest(ctx, input) {
|
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
catch (err) {
|
|
133
|
-
throw new errors_1.CliError(`Could not reach
|
|
133
|
+
throw new errors_1.CliError(`Could not reach Referalli at ${input.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
134
134
|
}
|
|
135
135
|
const text = await res.text();
|
|
136
136
|
let json = {};
|
|
@@ -146,18 +146,18 @@ async function referallyRequest(ctx, input) {
|
|
|
146
146
|
(Array.isArray(err) && err[0] && typeof err[0] === 'object' && 'message' in err[0] ? String(err[0].message) : null) ??
|
|
147
147
|
(typeof json.message === 'string' ? json.message : null);
|
|
148
148
|
const hint = res.status === 401 || res.status === 403 ? ' Check the merchant key.' : '';
|
|
149
|
-
throw new errors_1.CliError(`
|
|
149
|
+
throw new errors_1.CliError(`Referalli refused to ${input.what} (HTTP ${res.status})${msg ? `: ${msg}` : ''}.${hint}`);
|
|
150
150
|
}
|
|
151
151
|
return json;
|
|
152
152
|
}
|
|
153
153
|
async function referallyCreateConnection(ctx, input) {
|
|
154
154
|
const json = await referallyRequest(ctx, { ...input, method: 'POST', path: '/v1/auth/connections', what: 'create the connection' });
|
|
155
155
|
if (typeof json.id !== 'string' || typeof json.secret !== 'string') {
|
|
156
|
-
throw new errors_1.CliError('
|
|
156
|
+
throw new errors_1.CliError('Referalli answered without a connection id and secret.');
|
|
157
157
|
}
|
|
158
158
|
return json;
|
|
159
159
|
}
|
|
160
|
-
/** The
|
|
160
|
+
/** The Referalli topics two-way sync subscribes to (changes to a referral after sign-up). */
|
|
161
161
|
exports.REFERALLY_SYNC_TOPICS = [
|
|
162
162
|
'referral.created',
|
|
163
163
|
'referral.held',
|
|
@@ -170,7 +170,7 @@ exports.REFERALLY_SYNC_TOPICS = [
|
|
|
170
170
|
/**
|
|
171
171
|
* Whether the merchant key reaches live or test data: the org's `livemode`,
|
|
172
172
|
* else the key prefix (rk_test_ = test; rk_live_ and older rk_ keys = live).
|
|
173
|
-
* `known` is false when
|
|
173
|
+
* `known` is false when Referalli reports no mode (no test mode there).
|
|
174
174
|
*/
|
|
175
175
|
async function referallyKeyMode(ctx, input) {
|
|
176
176
|
try {
|
|
@@ -206,12 +206,12 @@ async function connect(ctx, args) {
|
|
|
206
206
|
throw new errors_1.CliError('referrals connect --provider referally needs --program <prg_…>.');
|
|
207
207
|
const baseRaw = (0, args_1.str)(v, 'base-url') ?? ctx.env.REFERALLY_BASE_URL?.trim();
|
|
208
208
|
if (!baseRaw)
|
|
209
|
-
throw new errors_1.CliError('Pass --base-url <your
|
|
209
|
+
throw new errors_1.CliError('Pass --base-url <your Referalli base URL> (or set REFERALLY_BASE_URL).');
|
|
210
210
|
const baseUrl = httpsUrl(baseRaw, '--base-url');
|
|
211
211
|
const keyFile = (0, args_1.str)(v, 'referally-key-file');
|
|
212
|
-
const key = (0, args_1.str)(v, 'referally-key') ?? (keyFile ? readKeyFile(ctx, keyFile, 'the
|
|
212
|
+
const key = (0, args_1.str)(v, 'referally-key') ?? (keyFile ? readKeyFile(ctx, keyFile, 'the Referalli key') : ctx.env.REFERALLY_API_KEY?.trim());
|
|
213
213
|
if (!key) {
|
|
214
|
-
throw new errors_1.CliError('Pass your
|
|
214
|
+
throw new errors_1.CliError('Pass your Referalli merchant key with --referally-key-file <path|-> (or --referally-key, or REFERALLY_API_KEY). It is used once and never stored.');
|
|
215
215
|
}
|
|
216
216
|
const destination = (0, args_1.str)(v, 'destination');
|
|
217
217
|
if (destination)
|
|
@@ -222,7 +222,7 @@ async function connect(ctx, args) {
|
|
|
222
222
|
const instanceLive = instance.environment === 'production';
|
|
223
223
|
const mode = await referallyKeyMode(ctx, { baseUrl, key });
|
|
224
224
|
if (mode.known && mode.live !== instanceLive) {
|
|
225
|
-
const message = `the
|
|
225
|
+
const message = `the Referalli key reaches ${mode.live ? 'live' : 'test'} data but instance ${instance.id} is ` +
|
|
226
226
|
`${instance.environment ?? 'not production'}. Use ${instanceLive ? 'a live (rk_live_…)' : 'a test (rk_test_…)'} key` +
|
|
227
227
|
` for it, or pass --allow-mode-mismatch.`;
|
|
228
228
|
if (v['allow-mode-mismatch'] !== true)
|
|
@@ -230,7 +230,7 @@ async function connect(ctx, args) {
|
|
|
230
230
|
ctx.io.err(`atlas: warning: ${message.replace(/, or pass --allow-mode-mismatch\.$/, '.')}`);
|
|
231
231
|
}
|
|
232
232
|
else if (!mode.known && !instanceLive) {
|
|
233
|
-
ctx.io.err(`atlas: warning:
|
|
233
|
+
ctx.io.err(`atlas: warning: Referalli did not say whether this key reaches test data; instance ${instance.id} is ${instance.environment ?? 'not production'}.`);
|
|
234
234
|
}
|
|
235
235
|
const created = await referallyCreateConnection(ctx, {
|
|
236
236
|
baseUrl,
|
|
@@ -274,21 +274,21 @@ async function connect(ctx, args) {
|
|
|
274
274
|
saved = await http.patch('/v1/instance/referrals', patch);
|
|
275
275
|
}
|
|
276
276
|
catch (err) {
|
|
277
|
-
// The secret is shown once by
|
|
277
|
+
// The secret is shown once by Referalli: keep it so the merchant can finish by hand.
|
|
278
278
|
const saved = (0, secrets_1.deliverSecret)({
|
|
279
279
|
io: out,
|
|
280
280
|
env: ctx.env,
|
|
281
281
|
product,
|
|
282
282
|
fileName: `referally-connection-${created.id}.env`,
|
|
283
283
|
entries: { REFERALLY_CONNECTION_ID: created.id, REFERALLY_CONNECTION_SECRET: created.secret },
|
|
284
|
-
label: 'The
|
|
284
|
+
label: 'The Referalli connection secret (not saved on Atlas)',
|
|
285
285
|
force: v.force === true,
|
|
286
|
-
comment: `
|
|
286
|
+
comment: `Referalli connection ${created.id}: saving it on the Atlas instance failed. Paste it in Users → Referrals.`,
|
|
287
287
|
});
|
|
288
|
-
ctx.io.err(`atlas: the connection ${created.id} was created on
|
|
288
|
+
ctx.io.err(`atlas: the connection ${created.id} was created on Referalli, but saving it on the instance failed.${saved.path ? ` Its secret is in ${saved.path}.` : ''}`);
|
|
289
289
|
throw err;
|
|
290
290
|
}
|
|
291
|
-
// Two-way sync:
|
|
291
|
+
// Two-way sync: Referalli's referral events go to the instance's inbound URL.
|
|
292
292
|
let syncEndpoint = null;
|
|
293
293
|
const inboundUrl = saved?.inbound?.url ?? null;
|
|
294
294
|
if (v['no-sync'] !== true && inboundUrl) {
|
|
@@ -302,7 +302,7 @@ async function connect(ctx, args) {
|
|
|
302
302
|
what: 'register the referral event webhook',
|
|
303
303
|
});
|
|
304
304
|
if (typeof endpoint.id !== 'string' || typeof endpoint.secret !== 'string') {
|
|
305
|
-
throw new errors_1.CliError('
|
|
305
|
+
throw new errors_1.CliError('Referalli answered without a webhook endpoint id and secret.');
|
|
306
306
|
}
|
|
307
307
|
try {
|
|
308
308
|
await http.patch('/v1/instance/referrals', { inbound_secret: endpoint.secret, inbound_endpoint_id: endpoint.id });
|
|
@@ -315,17 +315,17 @@ async function connect(ctx, args) {
|
|
|
315
315
|
product,
|
|
316
316
|
fileName: `referally-webhook-${endpoint.id}.env`,
|
|
317
317
|
entries: { REFERALLY_WEBHOOK_ENDPOINT_ID: endpoint.id, REFERALLY_WEBHOOK_SECRET: endpoint.secret },
|
|
318
|
-
label: 'The
|
|
318
|
+
label: 'The Referalli webhook secret (not saved on Atlas)',
|
|
319
319
|
force: v.force === true,
|
|
320
|
-
comment: `
|
|
320
|
+
comment: `Referalli webhook ${endpoint.id}: saving it on the Atlas instance failed. Paste it as the inbound secret in Users → Referrals.`,
|
|
321
321
|
});
|
|
322
|
-
ctx.io.err(`atlas: warning: the webhook ${endpoint.id} was registered on
|
|
322
|
+
ctx.io.err(`atlas: warning: the webhook ${endpoint.id} was registered on Referalli, but saving its secret failed (${err instanceof Error ? err.message : String(err)}).${kept.path ? ` It is in ${kept.path}.` : ''}`);
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
325
|
catch (err) {
|
|
326
326
|
if (!(err instanceof errors_1.CliError))
|
|
327
327
|
throw err;
|
|
328
|
-
ctx.io.err(`atlas: warning: ${err.message} Referral changes on
|
|
328
|
+
ctx.io.err(`atlas: warning: ${err.message} Referral changes on Referalli won't reach Atlas until it is registered (see the docs).`);
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
summary = {
|
|
@@ -340,9 +340,9 @@ async function connect(ctx, args) {
|
|
|
340
340
|
sync_endpoint_id: syncEndpoint,
|
|
341
341
|
};
|
|
342
342
|
if (!json) {
|
|
343
|
-
out.out(`Created
|
|
343
|
+
out.out(`Created Referalli connection ${created.id} for instance ${instance.id} and saved it (the secret was not printed).`);
|
|
344
344
|
if (syncEndpoint)
|
|
345
|
-
out.out(`Referral changes on
|
|
345
|
+
out.out(`Referral changes on Referalli sync back to Atlas (webhook ${syncEndpoint}).`);
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
else {
|
|
@@ -516,7 +516,7 @@ async function status(ctx, args) {
|
|
|
516
516
|
lines.push(`Failed (7 days): ${c.failed_calls_7d ?? 0} Retrying: ${c.retrying_calls ?? 0}`);
|
|
517
517
|
const inbound = settings.inbound;
|
|
518
518
|
if (inbound?.url) {
|
|
519
|
-
//
|
|
519
|
+
// Referalli needs its own webhook secret; the Atlas protocol falls back to the signing secret.
|
|
520
520
|
const syncing = inbound.secret_set || (settings.provider === 'webhook' && settings.signing_secret_set);
|
|
521
521
|
lines.push(`Two-way sync: ${syncing ? 'on' : 'off (no inbound secret)'}${inbound.endpoint_id ? ` (webhook ${inbound.endpoint_id})` : ''}`);
|
|
522
522
|
lines.push(`Inbound URL: ${inbound.url}`);
|
package/dist/help.d.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
* out of the handlers so the dispatch code stays about control flow and the
|
|
4
4
|
* copy can be read (and kept consistent) in one place.
|
|
5
5
|
*/
|
|
6
|
-
export declare const TOP_HELP = "atlas \u2014 manage an Atlas instance from the terminal\n\nUsage: atlas <command> [subcommand] [arguments] [options]\n\nCommands:\n login Authenticate and store a profile credential\n logout Remove a stored profile credential\n whoami Show the active profile and instance\n users list|get|create|delete\n orgs list|get|members\n api-keys list|create|revoke\n webhooks list|create\n sessions revoke\n config export|import Config-as-code: round-trip the instance's config\n actions list|deploy|test|logs\n init Create or complete an app's setup (idempotent); secrets to 0600 files\n preflight Check an instance's setup; non-zero exit on errors (for CI)\n env Print deploy variables: public values + secret file paths\n client rotate Rotate an OAuth client secret straight into its file\n referrals connect|backfill|status\n Connect a referral platform, backfill, check the connection\n\nGlobal options:\n --profile <name> Use a named profile (default: active, else \"default\")\n --json Emit raw JSON instead of a human table\n --limit <n> Page size for list commands that paginate\n --starting-after <cursor> Pagination cursor (from a prior page's hint)\n -h, --help Show this help, or help for a command\n -v, --version Print the version\n\nEnvironment overrides:\n ATLAS_SECRET_KEY Secret key to use instead of the stored one\n ATLAS_API_URL API URL to use instead of the stored one\n ATLAS_PLATFORM_KEY Platform key (psk_) for atlas init\n REFERALLY_BASE_URL
|
|
6
|
+
export declare const TOP_HELP = "atlas \u2014 manage an Atlas instance from the terminal\n\nUsage: atlas <command> [subcommand] [arguments] [options]\n\nCommands:\n login Authenticate and store a profile credential\n logout Remove a stored profile credential\n whoami Show the active profile and instance\n users list|get|create|delete\n orgs list|get|members\n api-keys list|create|revoke\n webhooks list|create\n sessions revoke\n config export|import Config-as-code: round-trip the instance's config\n actions list|deploy|test|logs\n init Create or complete an app's setup (idempotent); secrets to 0600 files\n preflight Check an instance's setup; non-zero exit on errors (for CI)\n env Print deploy variables: public values + secret file paths\n client rotate Rotate an OAuth client secret straight into its file\n referrals connect|backfill|status\n Connect a referral platform, backfill, check the connection\n import --from <vendor> <file>\n Move users from Auth0, Clerk, Supabase, Firebase, Cognito,\n Auth.js, WorkOS or Better Auth (resumable; --dry-run first)\n mcp install Add the Atlas MCP server (docs search) to Cursor, Claude Code,\n Codex or VS Code\n\nGlobal options:\n --profile <name> Use a named profile (default: active, else \"default\")\n --json Emit raw JSON instead of a human table\n --limit <n> Page size for list commands that paginate\n --starting-after <cursor> Pagination cursor (from a prior page's hint)\n -h, --help Show this help, or help for a command\n -v, --version Print the version\n\nEnvironment overrides:\n ATLAS_SECRET_KEY Secret key to use instead of the stored one\n ATLAS_API_URL API URL to use instead of the stored one\n ATLAS_PLATFORM_KEY Platform key (psk_) for atlas init\n REFERALLY_BASE_URL Referalli base URL for atlas referrals connect\n REFERALLY_API_KEY Referalli merchant key for atlas referrals connect (never stored)\n\nSecrets: a command that receives a secret writes it to a 0600 file under\n~/.config/<product>/ and prints only the path. --print-secret prints it instead.\n\nRun 'atlas <command> --help' for command-specific help.";
|
|
7
7
|
/** Per-command help, keyed by the resource word. */
|
|
8
8
|
export declare const COMMAND_HELP: Record<string, string>;
|