mcpdrift-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +428 -0
- package/dist/approver.d.ts +8 -0
- package/dist/approver.d.ts.map +1 -0
- package/dist/approver.js +90 -0
- package/dist/approver.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +103 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +23 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +148 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +123 -0
- package/dist/config.js.map +1 -0
- package/dist/differ.d.ts +11 -0
- package/dist/differ.d.ts.map +1 -0
- package/dist/differ.js +57 -0
- package/dist/differ.js.map +1 -0
- package/dist/fsUtil.d.ts +15 -0
- package/dist/fsUtil.d.ts.map +1 -0
- package/dist/fsUtil.js +70 -0
- package/dist/fsUtil.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/initializer.d.ts +10 -0
- package/dist/initializer.d.ts.map +1 -0
- package/dist/initializer.js +150 -0
- package/dist/initializer.js.map +1 -0
- package/dist/jsonPointer.d.ts +31 -0
- package/dist/jsonPointer.d.ts.map +1 -0
- package/dist/jsonPointer.js +116 -0
- package/dist/jsonPointer.js.map +1 -0
- package/dist/runner.d.ts +13 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +283 -0
- package/dist/runner.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
+
import type { FailureCategory } from './types.js';
|
|
4
|
+
export declare function parseCommand(commandStr: string): {
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Redacts likely credentials, tokens, and secrets from stderr logs
|
|
10
|
+
*/
|
|
11
|
+
export declare function sanitizeStderr(rawStderr: string): string;
|
|
12
|
+
export declare class McpClientError extends Error {
|
|
13
|
+
category: FailureCategory;
|
|
14
|
+
constructor(message: string, category: FailureCategory);
|
|
15
|
+
}
|
|
16
|
+
export interface McpSession {
|
|
17
|
+
client: Client;
|
|
18
|
+
transport: StdioClientTransport;
|
|
19
|
+
close: () => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export declare function createMcpSession(serverCommand: string, env?: Record<string, string>, timeoutMs?: number): Promise<McpSession>;
|
|
22
|
+
export declare function executeToolWithTimeout(client: Client, toolName: string, args?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAiCpF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,EAAE,eAAe,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe;CAKvD;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,oBAAoB,CAAC;IAChC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,SAAS,GAAE,MAAc,GACxB,OAAO,CAAC,UAAU,CAAC,CAoGrB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,SAAS,GAAE,MAAc,GACxB,OAAO,CAAC,OAAO,CAAC,CAclB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
+
export function parseCommand(commandStr) {
|
|
4
|
+
const tokens = [];
|
|
5
|
+
let current = '';
|
|
6
|
+
let inDouble = false;
|
|
7
|
+
let inSingle = false;
|
|
8
|
+
for (let i = 0; i < commandStr.length; i++) {
|
|
9
|
+
const char = commandStr[i];
|
|
10
|
+
if (char === '"' && !inSingle) {
|
|
11
|
+
inDouble = !inDouble;
|
|
12
|
+
}
|
|
13
|
+
else if (char === "'" && !inDouble) {
|
|
14
|
+
inSingle = !inSingle;
|
|
15
|
+
}
|
|
16
|
+
else if (/\s/.test(char) && !inDouble && !inSingle) {
|
|
17
|
+
if (current.length > 0) {
|
|
18
|
+
tokens.push(current);
|
|
19
|
+
current = '';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
current += char;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (current.length > 0) {
|
|
27
|
+
tokens.push(current);
|
|
28
|
+
}
|
|
29
|
+
if (tokens.length === 0) {
|
|
30
|
+
throw new Error('serverCommand cannot be empty.');
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
command: tokens[0],
|
|
34
|
+
args: tokens.slice(1),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Redacts likely credentials, tokens, and secrets from stderr logs
|
|
39
|
+
*/
|
|
40
|
+
export function sanitizeStderr(rawStderr) {
|
|
41
|
+
if (!rawStderr)
|
|
42
|
+
return '';
|
|
43
|
+
return rawStderr
|
|
44
|
+
.replace(/(Bearer\s+)[A-Za-z0-9_\-\.\~+/]+=*/gi, '$1[REDACTED]')
|
|
45
|
+
.replace(/((?:api[_-]?key|secret|token|password)\s*[:=]\s*['"]?)[^\s'"&]+/gi, '$1[REDACTED]');
|
|
46
|
+
}
|
|
47
|
+
export class McpClientError extends Error {
|
|
48
|
+
category;
|
|
49
|
+
constructor(message, category) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = 'McpClientError';
|
|
52
|
+
this.category = category;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export async function createMcpSession(serverCommand, env, timeoutMs = 15000) {
|
|
56
|
+
const { command, args } = parseCommand(serverCommand);
|
|
57
|
+
const transport = new StdioClientTransport({
|
|
58
|
+
command,
|
|
59
|
+
args,
|
|
60
|
+
env: {
|
|
61
|
+
...process.env,
|
|
62
|
+
...(env || {}),
|
|
63
|
+
},
|
|
64
|
+
stderr: 'pipe',
|
|
65
|
+
});
|
|
66
|
+
const client = new Client({
|
|
67
|
+
name: 'mcpdrift',
|
|
68
|
+
version: '1.0.0',
|
|
69
|
+
}, {
|
|
70
|
+
capabilities: {},
|
|
71
|
+
});
|
|
72
|
+
let stderrOutput = '';
|
|
73
|
+
if (transport.stderr) {
|
|
74
|
+
transport.stderr.on('data', (chunk) => {
|
|
75
|
+
stderrOutput += chunk.toString();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
let spawnError = null;
|
|
79
|
+
// Listen for process errors if transport exposed process
|
|
80
|
+
const proc = transport._process;
|
|
81
|
+
if (proc) {
|
|
82
|
+
proc.once('error', (err) => {
|
|
83
|
+
spawnError = err;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const connectPromise = client.connect(transport);
|
|
87
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
88
|
+
const timer = setTimeout(() => {
|
|
89
|
+
const sanitized = sanitizeStderr(stderrOutput.trim());
|
|
90
|
+
reject(new McpClientError(`Timed out connecting to MCP server after ${timeoutMs}ms.\nCommand: ${serverCommand}${sanitized ? `\nServer stderr: ${sanitized}` : ''}`, 'CONNECTION_FAILURE'));
|
|
91
|
+
}, timeoutMs);
|
|
92
|
+
timer.unref?.();
|
|
93
|
+
});
|
|
94
|
+
try {
|
|
95
|
+
await Promise.race([connectPromise, timeoutPromise]);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
try {
|
|
99
|
+
await transport.close();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Ignore close errors during failure cleanup
|
|
103
|
+
}
|
|
104
|
+
const sanitized = sanitizeStderr(stderrOutput.trim());
|
|
105
|
+
const isSpawn = spawnError || err.code === 'ENOENT' || /spawn.*ENOENT/i.test(err.message);
|
|
106
|
+
const category = isSpawn ? 'STARTUP_FAILURE' : 'CONNECTION_FAILURE';
|
|
107
|
+
throw new McpClientError(`Failed to start or connect to MCP server (${serverCommand}): ${err.message}${sanitized ? `\nServer stderr:\n${sanitized}` : ''}`, category);
|
|
108
|
+
}
|
|
109
|
+
const close = async () => {
|
|
110
|
+
try {
|
|
111
|
+
await transport.close();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Best effort
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
await client.close();
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Best effort
|
|
121
|
+
}
|
|
122
|
+
// Force kill if process remains alive
|
|
123
|
+
const child = transport._process;
|
|
124
|
+
if (child && !child.killed) {
|
|
125
|
+
try {
|
|
126
|
+
child.kill();
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Ignore
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
return { client, transport, close };
|
|
134
|
+
}
|
|
135
|
+
export async function executeToolWithTimeout(client, toolName, args = {}, timeoutMs = 15000) {
|
|
136
|
+
const callPromise = client.callTool({
|
|
137
|
+
name: toolName,
|
|
138
|
+
arguments: args,
|
|
139
|
+
});
|
|
140
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
141
|
+
const timer = setTimeout(() => {
|
|
142
|
+
reject(new McpClientError(`Tool "${toolName}" timed out after ${timeoutMs}ms.`, 'TOOL_TIMEOUT'));
|
|
143
|
+
}, timeoutMs);
|
|
144
|
+
timer.unref?.();
|
|
145
|
+
});
|
|
146
|
+
return (await Promise.race([callPromise, timeoutPromise]));
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpdriftConfig } from './types.js';
|
|
2
|
+
export declare const DEFAULT_CONFIG_FILE = "mcpdrift.config.json";
|
|
3
|
+
export declare const DEFAULT_SNAPSHOT_DIR: string;
|
|
4
|
+
export declare function resolveConfigPath(customPath?: string): string;
|
|
5
|
+
export declare function loadConfig(configPath?: string): {
|
|
6
|
+
config: McpdriftConfig;
|
|
7
|
+
resolvedPath: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function validateConfig(data: any, filePath: string): McpdriftConfig;
|
|
10
|
+
export declare function sanitizeToolFileName(toolName: string): string;
|
|
11
|
+
export declare function getSnapshotPath(snapshotDir: string, caseId: string): string;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAInE,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAC1D,eAAO,MAAM,oBAAoB,QAAsC,CAAC;AAExE,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAyBhG;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CA+F1E;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3E"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { validatePointer } from './jsonPointer.js';
|
|
4
|
+
import { validateCaseId, resolveSafeSnapshotPath } from './fsUtil.js';
|
|
5
|
+
export const DEFAULT_CONFIG_FILE = 'mcpdrift.config.json';
|
|
6
|
+
export const DEFAULT_SNAPSHOT_DIR = path.join('.mcpdrift', 'snapshots');
|
|
7
|
+
export function resolveConfigPath(customPath) {
|
|
8
|
+
if (customPath) {
|
|
9
|
+
return path.resolve(process.cwd(), customPath);
|
|
10
|
+
}
|
|
11
|
+
return path.resolve(process.cwd(), DEFAULT_CONFIG_FILE);
|
|
12
|
+
}
|
|
13
|
+
export function loadConfig(configPath) {
|
|
14
|
+
const targetPath = resolveConfigPath(configPath);
|
|
15
|
+
if (!fs.existsSync(targetPath)) {
|
|
16
|
+
throw new Error(`Configuration file not found at: ${targetPath}\nRun 'mcpdrift init' to generate a starter configuration.`);
|
|
17
|
+
}
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = fs.readFileSync(targetPath, 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
throw new Error(`Failed to read configuration file at ${targetPath}: ${err.message}`);
|
|
24
|
+
}
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw new Error(`Failed to parse JSON configuration file at ${targetPath}: ${err.message}`);
|
|
31
|
+
}
|
|
32
|
+
const config = validateConfig(parsed, targetPath);
|
|
33
|
+
return { config, resolvedPath: targetPath };
|
|
34
|
+
}
|
|
35
|
+
export function validateConfig(data, filePath) {
|
|
36
|
+
if (!data || typeof data !== 'object') {
|
|
37
|
+
throw new Error(`Invalid configuration in ${filePath}: Config must be a JSON object.`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof data.serverCommand !== 'string' || data.serverCommand.trim() === '') {
|
|
40
|
+
throw new Error(`Invalid configuration in ${filePath}: "serverCommand" string is required.`);
|
|
41
|
+
}
|
|
42
|
+
if (!Array.isArray(data.testCases) || data.testCases.length === 0) {
|
|
43
|
+
throw new Error(`Invalid configuration in ${filePath}: "testCases" must be a non-empty array.`);
|
|
44
|
+
}
|
|
45
|
+
// Count occurrences of each tool to determine if default tool-based IDs are safe
|
|
46
|
+
const toolCounts = {};
|
|
47
|
+
for (let i = 0; i < data.testCases.length; i++) {
|
|
48
|
+
const tc = data.testCases[i];
|
|
49
|
+
if (tc && typeof tc === 'object' && typeof tc.tool === 'string') {
|
|
50
|
+
const toolName = tc.tool.trim();
|
|
51
|
+
toolCounts[toolName] = (toolCounts[toolName] || 0) + 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const validatedCases = [];
|
|
55
|
+
const seenIds = new Set();
|
|
56
|
+
for (let i = 0; i < data.testCases.length; i++) {
|
|
57
|
+
const tc = data.testCases[i];
|
|
58
|
+
if (!tc || typeof tc !== 'object') {
|
|
59
|
+
throw new Error(`Invalid testCase at index ${i}: Must be an object.`);
|
|
60
|
+
}
|
|
61
|
+
if (typeof tc.tool !== 'string' || tc.tool.trim() === '') {
|
|
62
|
+
throw new Error(`Invalid testCase at index ${i}: "tool" name string is required.`);
|
|
63
|
+
}
|
|
64
|
+
if (tc.input !== undefined && (typeof tc.input !== 'object' || tc.input === null)) {
|
|
65
|
+
throw new Error(`Invalid testCase for tool "${tc.tool}": "input" must be an object.`);
|
|
66
|
+
}
|
|
67
|
+
const tool = tc.tool.trim();
|
|
68
|
+
let id;
|
|
69
|
+
if (tc.id !== undefined) {
|
|
70
|
+
if (typeof tc.id !== 'string' || tc.id.trim() === '') {
|
|
71
|
+
throw new Error(`Invalid testCase at index ${i}: "id" must be a non-empty string.`);
|
|
72
|
+
}
|
|
73
|
+
id = tc.id.trim();
|
|
74
|
+
validateCaseId(id);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Backward compatibility: If only one case exists for this tool, default id to tool name
|
|
78
|
+
if (toolCounts[tool] > 1) {
|
|
79
|
+
throw new Error(`Ambiguous test case at index ${i} for tool "${tool}": Multiple test cases exist for tool "${tool}". ` +
|
|
80
|
+
`Each must specify a unique "id" to prevent snapshot collisions.`);
|
|
81
|
+
}
|
|
82
|
+
id = tool;
|
|
83
|
+
validateCaseId(id);
|
|
84
|
+
}
|
|
85
|
+
if (seenIds.has(id)) {
|
|
86
|
+
throw new Error(`Duplicate test case ID "${id}" at index ${i}. Every test case must have a globally unique "id".`);
|
|
87
|
+
}
|
|
88
|
+
seenIds.add(id);
|
|
89
|
+
// Validate ignore rules if present
|
|
90
|
+
let ignoreRules;
|
|
91
|
+
if (tc.ignore !== undefined) {
|
|
92
|
+
if (!Array.isArray(tc.ignore)) {
|
|
93
|
+
throw new Error(`Invalid testCase "${id}": "ignore" must be an array of JSON Pointer strings.`);
|
|
94
|
+
}
|
|
95
|
+
for (const rule of tc.ignore) {
|
|
96
|
+
validatePointer(rule);
|
|
97
|
+
}
|
|
98
|
+
ignoreRules = tc.ignore;
|
|
99
|
+
}
|
|
100
|
+
validatedCases.push({
|
|
101
|
+
id,
|
|
102
|
+
tool,
|
|
103
|
+
input: tc.input || {},
|
|
104
|
+
name: tc.name,
|
|
105
|
+
timeout: typeof tc.timeout === 'number' ? tc.timeout : undefined,
|
|
106
|
+
ignore: ignoreRules,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
serverCommand: data.serverCommand.trim(),
|
|
111
|
+
testCases: validatedCases,
|
|
112
|
+
snapshotDir: data.snapshotDir || DEFAULT_SNAPSHOT_DIR,
|
|
113
|
+
timeout: typeof data.timeout === 'number' ? data.timeout : 15000,
|
|
114
|
+
env: data.env || {},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function sanitizeToolFileName(toolName) {
|
|
118
|
+
return toolName.replace(/[<>:"/\\|?*]/g, '_');
|
|
119
|
+
}
|
|
120
|
+
export function getSnapshotPath(snapshotDir, caseId) {
|
|
121
|
+
return resolveSafeSnapshotPath(snapshotDir, caseId);
|
|
122
|
+
}
|
|
123
|
+
//# 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/differ.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sorts object keys recursively to produce deterministic JSON comparisons
|
|
3
|
+
*/
|
|
4
|
+
export declare function sortKeys(obj: any): any;
|
|
5
|
+
export declare function areResponsesEqual(baseline: unknown, actual: unknown): boolean;
|
|
6
|
+
export declare function formatJson(data: unknown): string;
|
|
7
|
+
/**
|
|
8
|
+
* Generates a clean, colored line-by-line diff comparing baseline to actual response
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateDiff(baseline: unknown, actual: unknown, caseId: string, ignoredPointers?: string[]): string;
|
|
11
|
+
//# sourceMappingURL=differ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../src/differ.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAatC;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAI7E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAwCR"}
|
package/dist/differ.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as Diff from 'diff';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Sorts object keys recursively to produce deterministic JSON comparisons
|
|
5
|
+
*/
|
|
6
|
+
export function sortKeys(obj) {
|
|
7
|
+
if (obj === null || typeof obj !== 'object') {
|
|
8
|
+
return obj;
|
|
9
|
+
}
|
|
10
|
+
if (Array.isArray(obj)) {
|
|
11
|
+
return obj.map(sortKeys);
|
|
12
|
+
}
|
|
13
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const key of sortedKeys) {
|
|
16
|
+
result[key] = sortKeys(obj[key]);
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
export function areResponsesEqual(baseline, actual) {
|
|
21
|
+
const sortedBaseline = JSON.stringify(sortKeys(baseline));
|
|
22
|
+
const sortedActual = JSON.stringify(sortKeys(actual));
|
|
23
|
+
return sortedBaseline === sortedActual;
|
|
24
|
+
}
|
|
25
|
+
export function formatJson(data) {
|
|
26
|
+
return JSON.stringify(sortKeys(data), null, 2);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generates a clean, colored line-by-line diff comparing baseline to actual response
|
|
30
|
+
*/
|
|
31
|
+
export function generateDiff(baseline, actual, caseId, ignoredPointers) {
|
|
32
|
+
const baselineStr = formatJson(baseline);
|
|
33
|
+
const actualStr = formatJson(actual);
|
|
34
|
+
const patch = Diff.structuredPatch(`baseline/${caseId}.json`, `actual/${caseId}.json`, baselineStr, actualStr, 'baseline', 'actual');
|
|
35
|
+
const lines = [];
|
|
36
|
+
lines.push(chalk.dim(`--- baseline (.mcpdrift/snapshots/${caseId}.json)`));
|
|
37
|
+
lines.push(chalk.dim(`+++ actual (received from MCP server)`));
|
|
38
|
+
if (ignoredPointers && ignoredPointers.length > 0) {
|
|
39
|
+
lines.push(chalk.dim(`ℹ️ Ignore rules active (${ignoredPointers.length} rule(s) omitted before diff)`));
|
|
40
|
+
}
|
|
41
|
+
for (const hunk of patch.hunks) {
|
|
42
|
+
lines.push(chalk.cyan(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`));
|
|
43
|
+
for (const line of hunk.lines) {
|
|
44
|
+
if (line.startsWith('+')) {
|
|
45
|
+
lines.push(chalk.green(line));
|
|
46
|
+
}
|
|
47
|
+
else if (line.startsWith('-')) {
|
|
48
|
+
lines.push(chalk.red(line));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
lines.push(chalk.dim(line));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return lines.join('\n');
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=differ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"differ.js","sourceRoot":"","sources":["../src/differ.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAQ;IAC/B,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAiB,EAAE,MAAe;IAClE,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,OAAO,cAAc,KAAK,YAAY,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAiB,EACjB,MAAe,EACf,MAAc,EACd,eAA0B;IAE1B,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAErC,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAChC,YAAY,MAAM,OAAO,EACzB,UAAU,MAAM,OAAO,EACvB,WAAW,EACX,SAAS,EACT,UAAU,EACV,QAAQ,CACT,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,MAAM,QAAQ,CAAC,CAAC,CAAC;IAC3E,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAC/D,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,eAAe,CAAC,MAAM,+BAA+B,CAAC,CAAC,CAAC;IAC3G,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,IAAI,CACR,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,CAC9E,CACF,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/fsUtil.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that a test case identifier is safe for filesystem snapshot usage.
|
|
3
|
+
* Prevents path traversal, directory navigation, and invalid characters.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateCaseId(id: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a snapshot path safely, ensuring the target file strictly stays inside snapshotDir.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveSafeSnapshotPath(snapshotDir: string, caseId: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Atomically writes content to a file by writing to a temporary file in the same directory first
|
|
12
|
+
* and then renaming it. Avoids partial/corrupt files if interrupted.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writeAtomic(targetFilePath: string, content: string): void;
|
|
15
|
+
//# sourceMappingURL=fsUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsUtil.d.ts","sourceRoot":"","sources":["../src/fsUtil.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CA6B/C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAanF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA2BzE"}
|
package/dist/fsUtil.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Validates that a test case identifier is safe for filesystem snapshot usage.
|
|
5
|
+
* Prevents path traversal, directory navigation, and invalid characters.
|
|
6
|
+
*/
|
|
7
|
+
export function validateCaseId(id) {
|
|
8
|
+
if (typeof id !== 'string' || id.trim() === '') {
|
|
9
|
+
throw new Error('Test case ID must be a non-empty string.');
|
|
10
|
+
}
|
|
11
|
+
const trimmed = id.trim();
|
|
12
|
+
if (trimmed === '.' || trimmed === '..') {
|
|
13
|
+
throw new Error(`Invalid test case ID "${id}": ID cannot be "." or ".."`);
|
|
14
|
+
}
|
|
15
|
+
// Check for forbidden path traversal characters: /, \, null byte, control characters
|
|
16
|
+
if (/[\/\\\x00-\x1F\x7F]/.test(trimmed)) {
|
|
17
|
+
throw new Error(`Invalid test case ID "${id}": Path traversal characters (/ and \\) and control characters are not allowed.`);
|
|
18
|
+
}
|
|
19
|
+
// Disallow forbidden filename characters across Windows and POSIX: < > : " | ? *
|
|
20
|
+
if (/[<>:"|?*]/.test(trimmed)) {
|
|
21
|
+
throw new Error(`Invalid test case ID "${id}": Forbidden filename characters (< > : " | ? *) are not allowed.`);
|
|
22
|
+
}
|
|
23
|
+
// Max length check to prevent filesystem boundary overflows
|
|
24
|
+
if (trimmed.length > 120) {
|
|
25
|
+
throw new Error(`Invalid test case ID "${id}": ID exceeds maximum length of 120 characters.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves a snapshot path safely, ensuring the target file strictly stays inside snapshotDir.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveSafeSnapshotPath(snapshotDir, caseId) {
|
|
32
|
+
validateCaseId(caseId);
|
|
33
|
+
const absoluteSnapshotDir = path.resolve(snapshotDir);
|
|
34
|
+
const targetFile = path.resolve(absoluteSnapshotDir, `${caseId}.json`);
|
|
35
|
+
// Path traversal check
|
|
36
|
+
const relative = path.relative(absoluteSnapshotDir, targetFile);
|
|
37
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
38
|
+
throw new Error(`Security violation: Snapshot path for "${caseId}" resolves outside snapshot directory.`);
|
|
39
|
+
}
|
|
40
|
+
return targetFile;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Atomically writes content to a file by writing to a temporary file in the same directory first
|
|
44
|
+
* and then renaming it. Avoids partial/corrupt files if interrupted.
|
|
45
|
+
*/
|
|
46
|
+
export function writeAtomic(targetFilePath, content) {
|
|
47
|
+
const dir = path.dirname(targetFilePath);
|
|
48
|
+
if (!fs.existsSync(dir)) {
|
|
49
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
const tempFile = path.join(dir, `.tmp.${path.basename(targetFilePath)}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}`);
|
|
52
|
+
try {
|
|
53
|
+
fs.writeFileSync(tempFile, content, 'utf-8');
|
|
54
|
+
fs.renameSync(tempFile, targetFilePath);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// If rename fails (e.g. edge-case Windows file lock), try to clean up temp file
|
|
58
|
+
try {
|
|
59
|
+
if (fs.existsSync(tempFile)) {
|
|
60
|
+
fs.unlinkSync(tempFile);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Best-effort cleanup
|
|
65
|
+
}
|
|
66
|
+
// Direct write fallback
|
|
67
|
+
fs.writeFileSync(targetFilePath, content, 'utf-8');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=fsUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsUtil.js","sourceRoot":"","sources":["../src/fsUtil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAE1B,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,6BAA6B,CAAC,CAAC;IAC5E,CAAC;IAED,qFAAqF;IACrF,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,yBAAyB,EAAE,iFAAiF,CAC7G,CAAC;IACJ,CAAC;IAED,iFAAiF;IACjF,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,yBAAyB,EAAE,mEAAmE,CAC/F,CAAC;IACJ,CAAC;IAED,4DAA4D;IAC5D,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,iDAAiD,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAAmB,EAAE,MAAc;IACzE,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;IAEvE,uBAAuB;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;IAChE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,wCAAwC,CAAC,CAAC;IAC5G,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,cAAsB,EAAE,OAAe;IACjE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,GAAG,EACH,QAAQ,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAChG,CAAC;IAEF,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7C,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,gFAAgF;QAChF,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QAED,wBAAwB;QACxB,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './config.js';
|
|
3
|
+
export * from './differ.js';
|
|
4
|
+
export * from './client.js';
|
|
5
|
+
export * from './runner.js';
|
|
6
|
+
export * from './approver.js';
|
|
7
|
+
export * from './initializer.js';
|
|
8
|
+
export * from './jsonPointer.js';
|
|
9
|
+
export * from './fsUtil.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './config.js';
|
|
3
|
+
export * from './differ.js';
|
|
4
|
+
export * from './client.js';
|
|
5
|
+
export * from './runner.js';
|
|
6
|
+
export * from './approver.js';
|
|
7
|
+
export * from './initializer.js';
|
|
8
|
+
export * from './jsonPointer.js';
|
|
9
|
+
export * from './fsUtil.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface InitOptions {
|
|
2
|
+
server?: string;
|
|
3
|
+
output?: string;
|
|
4
|
+
force?: boolean;
|
|
5
|
+
tools?: string[];
|
|
6
|
+
allTools?: boolean;
|
|
7
|
+
template?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function initConfig(options?: InitOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=initializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initializer.d.ts","sourceRoot":"","sources":["../src/initializer.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAgED,wBAAsB,UAAU,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuHzE"}
|