@lensmcp/nx-plugin 1.18.3 → 1.18.6
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/executors/agent-build/agent-build.d.ts +0 -1
- package/executors/agent-build/agent-build.js +2 -86
- package/executors/agent-dev/agent-dev.d.ts +0 -1
- package/executors/agent-dev/agent-dev.js +4 -425
- package/executors/agent-verify/agent-verify.d.ts +0 -1
- package/executors/agent-verify/agent-verify.js +3 -166
- package/generators/init/init.d.ts +0 -1
- package/generators/init/init.js +9 -167
- package/generators/setup-nest/setup-nest.d.ts +0 -1
- package/generators/setup-nest/setup-nest.js +8 -281
- package/generators/setup-vite/setup-vite.d.ts +0 -1
- package/generators/setup-vite/setup-vite.js +5 -125
- package/index.d.ts +0 -1
- package/index.js +1 -21
- package/lens-frontend.d.ts +0 -1
- package/lens-frontend.js +1 -205
- package/package.json +1 -1
- package/executors/agent-build/agent-build.d.ts.map +0 -1
- package/executors/agent-dev/agent-dev.d.ts.map +0 -1
- package/executors/agent-verify/agent-verify.d.ts.map +0 -1
- package/generators/init/init.d.ts.map +0 -1
- package/generators/setup-nest/setup-nest.d.ts.map +0 -1
- package/generators/setup-vite/setup-vite.d.ts.map +0 -1
- package/index.d.ts.map +0 -1
- package/lens-frontend.d.ts.map +0 -1
|
@@ -1,166 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const node_child_process_1 = require("node:child_process");
|
|
5
|
-
const node_fs_1 = require("node:fs");
|
|
6
|
-
const node_path_1 = require("node:path");
|
|
7
|
-
/**
|
|
8
|
-
* `agent-verify` — the deterministic verification loop the agent runs
|
|
9
|
-
* to know "did my fix work?".
|
|
10
|
-
*
|
|
11
|
-
* Phase 2 covers the frontend slice: typecheck (`tsc --noEmit`), lint
|
|
12
|
-
* (`eslint`), and build (`vite build`). Each stage runs sequentially;
|
|
13
|
-
* a stage failure marks the verify as `failed` but later stages still
|
|
14
|
-
* run so the agent gets a complete picture, not just the first error.
|
|
15
|
-
*
|
|
16
|
-
* The report is written to `.lensmcp/verifications/<project>-<ts>.json`
|
|
17
|
-
* and to `.lensmcp/verifications/latest.json` for easy resource access.
|
|
18
|
-
* The MCP-side `agent://latest-verification` resource (Phase 2.5) reads
|
|
19
|
-
* from `latest.json`.
|
|
20
|
-
*/
|
|
21
|
-
async function agentVerifyExecutor(options, context) {
|
|
22
|
-
const opts = {
|
|
23
|
-
kind: options.kind ?? 'vite-react',
|
|
24
|
-
skipTypecheck: options.skipTypecheck ?? false,
|
|
25
|
-
skipLint: options.skipLint ?? false,
|
|
26
|
-
skipBuild: options.skipBuild ?? false,
|
|
27
|
-
projectRoot: options.projectRoot,
|
|
28
|
-
};
|
|
29
|
-
const projectName = context.projectName ?? null;
|
|
30
|
-
const projectRoot = opts.projectRoot
|
|
31
|
-
? (0, node_path_1.resolve)(context.root, opts.projectRoot)
|
|
32
|
-
: projectName && context.projectsConfigurations
|
|
33
|
-
? (0, node_path_1.resolve)(context.root, context.projectsConfigurations.projects[projectName]?.root ?? '.')
|
|
34
|
-
: context.root;
|
|
35
|
-
const startedAt = Date.now();
|
|
36
|
-
const stages = [];
|
|
37
|
-
// 1. typecheck — `tsc --noEmit -p <root>` if a tsconfig is present.
|
|
38
|
-
if (!opts.skipTypecheck) {
|
|
39
|
-
const tscBin = locateBin('tsc', [projectRoot, context.root]);
|
|
40
|
-
const tsconfig = resolveFirstExisting(['tsconfig.json'], projectRoot);
|
|
41
|
-
if (!tscBin || !tsconfig) {
|
|
42
|
-
stages.push({ name: 'typecheck', result: 'skipped', durationMs: 0, summary: 'no tsc/tsconfig' });
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
const t0 = Date.now();
|
|
46
|
-
const r = runStageCommand('tsc --noEmit', tscBin, ['--noEmit', '-p', tsconfig], projectRoot);
|
|
47
|
-
stages.push({
|
|
48
|
-
name: 'typecheck',
|
|
49
|
-
result: r.status === 0 ? 'passed' : 'failed',
|
|
50
|
-
durationMs: Date.now() - t0,
|
|
51
|
-
exitCode: r.status ?? -1,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
stages.push({ name: 'typecheck', result: 'skipped', durationMs: 0 });
|
|
57
|
-
}
|
|
58
|
-
// 2. lint — `eslint .` if eslint is present.
|
|
59
|
-
if (!opts.skipLint) {
|
|
60
|
-
const eslintBin = locateBin('eslint', [projectRoot, context.root]);
|
|
61
|
-
if (!eslintBin) {
|
|
62
|
-
stages.push({ name: 'lint', result: 'skipped', durationMs: 0, summary: 'no eslint' });
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
const t0 = Date.now();
|
|
66
|
-
const r = runStageCommand('eslint .', eslintBin, ['.'], projectRoot);
|
|
67
|
-
stages.push({
|
|
68
|
-
name: 'lint',
|
|
69
|
-
result: r.status === 0 ? 'passed' : 'failed',
|
|
70
|
-
durationMs: Date.now() - t0,
|
|
71
|
-
exitCode: r.status ?? -1,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
stages.push({ name: 'lint', result: 'skipped', durationMs: 0 });
|
|
77
|
-
}
|
|
78
|
-
// 3. build — `vite build` if vite is present.
|
|
79
|
-
if (!opts.skipBuild) {
|
|
80
|
-
const viteBin = locateBin('vite', [projectRoot, context.root]);
|
|
81
|
-
if (!viteBin) {
|
|
82
|
-
stages.push({ name: 'build', result: 'skipped', durationMs: 0, summary: 'no vite' });
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
const viteConfig = resolveFirstExisting(['vite.config.ts', 'vite.config.js', 'vite.config.mjs'], projectRoot) ??
|
|
86
|
-
(0, node_path_1.join)(projectRoot, 'vite.config.ts');
|
|
87
|
-
const t0 = Date.now();
|
|
88
|
-
const r = runStageCommand('vite build', viteBin, ['build', '--config', viteConfig, projectRoot], projectRoot);
|
|
89
|
-
stages.push({
|
|
90
|
-
name: 'build',
|
|
91
|
-
result: r.status === 0 ? 'passed' : 'failed',
|
|
92
|
-
durationMs: Date.now() - t0,
|
|
93
|
-
exitCode: r.status ?? -1,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
stages.push({ name: 'build', result: 'skipped', durationMs: 0 });
|
|
99
|
-
}
|
|
100
|
-
const status = stages.some((s) => s.result === 'failed') ? 'failed' : 'passed';
|
|
101
|
-
const report = {
|
|
102
|
-
schemaVersion: 1,
|
|
103
|
-
project: projectName,
|
|
104
|
-
timestamp: new Date(startedAt).toISOString(),
|
|
105
|
-
durationMs: Date.now() - startedAt,
|
|
106
|
-
status,
|
|
107
|
-
stages,
|
|
108
|
-
};
|
|
109
|
-
const outDir = (0, node_path_1.join)(context.root, '.lensmcp', 'verifications');
|
|
110
|
-
try {
|
|
111
|
-
(0, node_fs_1.mkdirSync)(outDir, { recursive: true });
|
|
112
|
-
const ts = startedAt;
|
|
113
|
-
// Project names like `@lensmcp/example-web` contain `/`. Flatten so
|
|
114
|
-
// the report filename is a single path segment.
|
|
115
|
-
const safeName = (projectName ?? 'app').replace(/[^a-zA-Z0-9_-]+/g, '-');
|
|
116
|
-
const filename = `${safeName}-${ts}.json`;
|
|
117
|
-
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(outDir, filename), JSON.stringify(report, null, 2) + '\n');
|
|
118
|
-
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(outDir, 'latest.json'), JSON.stringify(report, null, 2) + '\n');
|
|
119
|
-
}
|
|
120
|
-
catch (e) {
|
|
121
|
-
console.warn(`[agent-verify] could not write report: ${e.message}`);
|
|
122
|
-
}
|
|
123
|
-
for (const s of report.stages) {
|
|
124
|
-
console.log(`[agent-verify] ${s.name}: ${s.result}${s.exitCode !== undefined ? ` (exit ${s.exitCode})` : ''}`);
|
|
125
|
-
}
|
|
126
|
-
console.log(`[agent-verify] ${status} in ${report.durationMs}ms`);
|
|
127
|
-
return { success: status === 'passed' };
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Run a verify sub-command, capturing its output and re-emitting it INDENTED.
|
|
131
|
-
*
|
|
132
|
-
* agent-verify deliberately runs commands that may fail — it IS the agent's
|
|
133
|
-
* edit→verify loop, so a failing stage is a normal, expected outcome. In CI a
|
|
134
|
-
* raw tool error printed at column 0 (`file(line,col): error TS....`) is picked
|
|
135
|
-
* up by GitHub's problem matchers and turned into a spurious build *annotation*.
|
|
136
|
-
* Indenting every line by two spaces keeps the output fully readable while
|
|
137
|
-
* defeating the matchers (they anchor on a non-space first character), so a
|
|
138
|
-
* verify failure never masquerades as a CI error.
|
|
139
|
-
*/
|
|
140
|
-
function runStageCommand(label, bin, args, cwd) {
|
|
141
|
-
console.log(`[agent-verify] ${label}`);
|
|
142
|
-
const r = (0, node_child_process_1.spawnSync)(bin, args, { cwd, encoding: 'utf8' });
|
|
143
|
-
const out = `${r.stdout ?? ''}${r.stderr ?? ''}`;
|
|
144
|
-
if (out.trim())
|
|
145
|
-
process.stdout.write(out.replace(/^(?=.)/gm, ' '));
|
|
146
|
-
return r;
|
|
147
|
-
}
|
|
148
|
-
function locateBin(name, roots) {
|
|
149
|
-
for (const root of roots) {
|
|
150
|
-
const candidate = (0, node_path_1.join)(root, 'node_modules', '.bin', name);
|
|
151
|
-
if ((0, node_fs_1.existsSync)(candidate))
|
|
152
|
-
return candidate;
|
|
153
|
-
}
|
|
154
|
-
return undefined;
|
|
155
|
-
}
|
|
156
|
-
function resolveFirstExisting(names, root) {
|
|
157
|
-
for (const n of names) {
|
|
158
|
-
const p = (0, node_path_1.join)(root, n);
|
|
159
|
-
if ((0, node_fs_1.existsSync)(p))
|
|
160
|
-
return p;
|
|
161
|
-
}
|
|
162
|
-
return undefined;
|
|
163
|
-
}
|
|
164
|
-
// Unused helpers, kept available for future re-use by tools that may
|
|
165
|
-
// drive the report differently.
|
|
166
|
-
void node_path_1.dirname;
|
|
1
|
+
"use strict";var k=Object.defineProperty;var d=(s,e)=>k(s,"name",{value:e,configurable:!0});var g=Object.defineProperty,l=d((s,e)=>g(s,"name",{value:e,configurable:!0}),"l");Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=agentVerifyExecutor;const node_child_process_1=require("node:child_process"),node_fs_1=require("node:fs"),node_path_1=require("node:path");async function agentVerifyExecutor(s,e){const i={kind:s.kind??"vite-react",skipTypecheck:s.skipTypecheck??!1,skipLint:s.skipLint??!1,skipBuild:s.skipBuild??!1,projectRoot:s.projectRoot},n=e.projectName??null,o=i.projectRoot?(0,node_path_1.resolve)(e.root,i.projectRoot):n&&e.projectsConfigurations?(0,node_path_1.resolve)(e.root,e.projectsConfigurations.projects[n]?.root??"."):e.root,c=Date.now(),r=[];if(i.skipTypecheck)r.push({name:"typecheck",result:"skipped",durationMs:0});else{const t=locateBin("tsc",[o,e.root]),a=resolveFirstExisting(["tsconfig.json"],o);if(!t||!a)r.push({name:"typecheck",result:"skipped",durationMs:0,summary:"no tsc/tsconfig"});else{const u=Date.now(),p=runStageCommand("tsc --noEmit",t,["--noEmit","-p",a],o);r.push({name:"typecheck",result:p.status===0?"passed":"failed",durationMs:Date.now()-u,exitCode:p.status??-1})}}if(i.skipLint)r.push({name:"lint",result:"skipped",durationMs:0});else{const t=locateBin("eslint",[o,e.root]);if(!t)r.push({name:"lint",result:"skipped",durationMs:0,summary:"no eslint"});else{const a=Date.now(),u=runStageCommand("eslint .",t,["."],o);r.push({name:"lint",result:u.status===0?"passed":"failed",durationMs:Date.now()-a,exitCode:u.status??-1})}}if(i.skipBuild)r.push({name:"build",result:"skipped",durationMs:0});else{const t=locateBin("vite",[o,e.root]);if(!t)r.push({name:"build",result:"skipped",durationMs:0,summary:"no vite"});else{const a=resolveFirstExisting(["vite.config.ts","vite.config.js","vite.config.mjs"],o)??(0,node_path_1.join)(o,"vite.config.ts"),u=Date.now(),p=runStageCommand("vite build",t,["build","--config",a,o],o);r.push({name:"build",result:p.status===0?"passed":"failed",durationMs:Date.now()-u,exitCode:p.status??-1})}}const m=r.some(t=>t.result==="failed")?"failed":"passed",f={schemaVersion:1,project:n,timestamp:new Date(c).toISOString(),durationMs:Date.now()-c,status:m,stages:r},y=(0,node_path_1.join)(e.root,".lensmcp","verifications");try{(0,node_fs_1.mkdirSync)(y,{recursive:!0});const t=c,a=`${(n??"app").replace(/[^a-zA-Z0-9_-]+/g,"-")}-${t}.json`;(0,node_fs_1.writeFileSync)((0,node_path_1.join)(y,a),JSON.stringify(f,null,2)+`
|
|
2
|
+
`),(0,node_fs_1.writeFileSync)((0,node_path_1.join)(y,"latest.json"),JSON.stringify(f,null,2)+`
|
|
3
|
+
`)}catch(t){console.warn(`[agent-verify] could not write report: ${t.message}`)}for(const t of f.stages)console.log(`[agent-verify] ${t.name}: ${t.result}${t.exitCode!==void 0?` (exit ${t.exitCode})`:""}`);return console.log(`[agent-verify] ${m} in ${f.durationMs}ms`),{success:m==="passed"}}d(agentVerifyExecutor,"agentVerifyExecutor"),l(agentVerifyExecutor,"agentVerifyExecutor");function runStageCommand(s,e,i,n){console.log(`[agent-verify] ${s}`);const o=(0,node_child_process_1.spawnSync)(e,i,{cwd:n,encoding:"utf8"}),c=`${o.stdout??""}${o.stderr??""}`;return c.trim()&&process.stdout.write(c.replace(/^(?=.)/gm," ")),o}d(runStageCommand,"runStageCommand"),l(runStageCommand,"runStageCommand");function locateBin(s,e){for(const i of e){const n=(0,node_path_1.join)(i,"node_modules",".bin",s);if((0,node_fs_1.existsSync)(n))return n}}d(locateBin,"locateBin"),l(locateBin,"locateBin");function resolveFirstExisting(s,e){for(const i of s){const n=(0,node_path_1.join)(e,i);if((0,node_fs_1.existsSync)(n))return n}}d(resolveFirstExisting,"resolveFirstExisting"),l(resolveFirstExisting,"resolveFirstExisting"),node_path_1.dirname;
|
package/generators/init/init.js
CHANGED
|
@@ -1,167 +1,9 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
retention: {
|
|
11
|
-
sessions: 5,
|
|
12
|
-
events: 5000,
|
|
13
|
-
screenshots: 50,
|
|
14
|
-
buildReports: 20,
|
|
15
|
-
visualFrames: 200,
|
|
16
|
-
heapSnapshots: 3,
|
|
17
|
-
tracesWithErrors: 20,
|
|
18
|
-
verifications: 10,
|
|
19
|
-
},
|
|
20
|
-
redaction: {
|
|
21
|
-
headers: ['authorization', 'cookie', 'set-cookie', 'x-api-key'],
|
|
22
|
-
paths: ['password', 'token', 'secret', 'apiKey', 'api_key'],
|
|
23
|
-
},
|
|
24
|
-
channels: {
|
|
25
|
-
blockingStatusChanged: { enabled: true, minSeverity: 'error' },
|
|
26
|
-
memoryLeakSuspected: { enabled: true, minSeverity: 'warning' },
|
|
27
|
-
bundleRegression: { enabled: true, minSeverity: 'warning' },
|
|
28
|
-
visualViolationBlocking: { enabled: true, minSeverity: 'error' },
|
|
29
|
-
verificationCompleted: { enabled: true, minSeverity: 'info' },
|
|
30
|
-
},
|
|
31
|
-
// Tunable detection thresholds — when each signal fires. Edit to taste;
|
|
32
|
-
// the server reads these at boot (see @lensmcp/core resolveThresholds).
|
|
33
|
-
thresholds: {
|
|
34
|
-
dbInLoop: 5,
|
|
35
|
-
nPlusOne: 3,
|
|
36
|
-
renderStorm: 5,
|
|
37
|
-
slowRouteMs: 500,
|
|
38
|
-
slowRenderMs: 16,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
const LENSMCP_GITIGNORE_MARKER = '# LensMCP runtime artifacts (per-session storage)';
|
|
42
|
-
const LENSMCP_GITIGNORE_ENTRY = '.lensmcp/';
|
|
43
|
-
async function initGenerator(tree, rawOptions = {}) {
|
|
44
|
-
const options = {
|
|
45
|
-
skipFormat: rawOptions.skipFormat ?? false,
|
|
46
|
-
registerHostConfig: rawOptions.registerHostConfig ?? 'auto',
|
|
47
|
-
};
|
|
48
|
-
const steps = [];
|
|
49
|
-
// 1. Register the plugin + lensmcp config in nx.json (idempotent).
|
|
50
|
-
if (tree.exists('nx.json')) {
|
|
51
|
-
(0, devkit_1.updateJson)(tree, 'nx.json', (nx) => {
|
|
52
|
-
nx.plugins = Array.isArray(nx.plugins) ? nx.plugins : [];
|
|
53
|
-
const alreadyRegistered = nx.plugins.some((p) => {
|
|
54
|
-
if (typeof p === 'string')
|
|
55
|
-
return p === '@lensmcp/nx-plugin';
|
|
56
|
-
if (p && typeof p === 'object' && 'plugin' in p) {
|
|
57
|
-
return p.plugin === '@lensmcp/nx-plugin';
|
|
58
|
-
}
|
|
59
|
-
return false;
|
|
60
|
-
});
|
|
61
|
-
if (!alreadyRegistered) {
|
|
62
|
-
nx.plugins.push('@lensmcp/nx-plugin');
|
|
63
|
-
steps.push('nx.json: registered @lensmcp/nx-plugin');
|
|
64
|
-
}
|
|
65
|
-
const existing = (nx.lensmcp ?? {});
|
|
66
|
-
nx.lensmcp = mergeDeep(DEFAULT_LENSMCP_CONFIG, existing);
|
|
67
|
-
if (!('lensmcp' in nx) || Object.keys(existing).length === 0) {
|
|
68
|
-
steps.push('nx.json: added workspace-wide `lensmcp` config block');
|
|
69
|
-
}
|
|
70
|
-
return nx;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
throw new Error('No nx.json found at the workspace root. Are you in a Nx workspace?');
|
|
75
|
-
}
|
|
76
|
-
// 2. .gitignore — add `.lensmcp/` line (idempotent).
|
|
77
|
-
const gitignorePath = '.gitignore';
|
|
78
|
-
const existing = tree.exists(gitignorePath) ? tree.read(gitignorePath, 'utf-8') ?? '' : '';
|
|
79
|
-
if (!existing.split('\n').some((l) => l.trim() === LENSMCP_GITIGNORE_ENTRY)) {
|
|
80
|
-
const trailingNewline = existing.endsWith('\n') ? '' : '\n';
|
|
81
|
-
tree.write(gitignorePath, `${existing}${trailingNewline}\n${LENSMCP_GITIGNORE_MARKER}\n${LENSMCP_GITIGNORE_ENTRY}\n`);
|
|
82
|
-
steps.push(`${gitignorePath}: added \`${LENSMCP_GITIGNORE_ENTRY}\``);
|
|
83
|
-
}
|
|
84
|
-
// 3. Reserve the .lensmcp/ directory with a sentinel file.
|
|
85
|
-
const keepPath = (0, devkit_1.joinPathFragments)('.lensmcp', '.keep');
|
|
86
|
-
if (!tree.exists(keepPath)) {
|
|
87
|
-
tree.write(keepPath, '');
|
|
88
|
-
steps.push(`${keepPath}: created`);
|
|
89
|
-
}
|
|
90
|
-
// 4. Write an install trail so subsequent re-runs can read what was
|
|
91
|
-
// done and (in future generators) un-install precisely.
|
|
92
|
-
const trailPath = (0, devkit_1.joinPathFragments)('.lensmcp', 'install-trail.json');
|
|
93
|
-
const existingTrail = tree.exists(trailPath)
|
|
94
|
-
? JSON.parse(tree.read(trailPath, 'utf-8') ?? '{}')
|
|
95
|
-
: undefined;
|
|
96
|
-
const trail = existingTrail ?? {
|
|
97
|
-
schemaVersion: 1,
|
|
98
|
-
installedAt: new Date().toISOString(),
|
|
99
|
-
steps: [],
|
|
100
|
-
};
|
|
101
|
-
trail.steps.push(...steps);
|
|
102
|
-
tree.write(trailPath, JSON.stringify(trail, null, 2) + '\n');
|
|
103
|
-
// 5. Register the LensMCP MCP server in the workspace `.mcp.json` so any
|
|
104
|
-
// coding agent (Claude Code, Cursor, …) opening this project gets the
|
|
105
|
-
// lens automatically. Workspace-local edits happen here, in the Nx
|
|
106
|
-
// tree (idempotent). Global agent configs (~/.claude, ~/.cursor) are
|
|
107
|
-
// only touched by `lensmcp` when `registerHostConfig: 'always'`,
|
|
108
|
-
// since those live outside the workspace.
|
|
109
|
-
if (options.registerHostConfig !== 'never') {
|
|
110
|
-
registerWorkspaceMcpConfig(tree, steps);
|
|
111
|
-
}
|
|
112
|
-
if (!options.skipFormat) {
|
|
113
|
-
await (0, devkit_1.formatFiles)(tree);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
/** The stdio MCP server entry a host agent uses to launch LensMCP. */
|
|
117
|
-
const LENSMCP_MCP_SERVER_ENTRY = {
|
|
118
|
-
command: 'npx',
|
|
119
|
-
args: ['-y', 'lensmcp', 'mcp'],
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Ensure `<workspace>/.mcp.json` has a `lensmcp` MCP server entry.
|
|
123
|
-
* Idempotent: creates the file if absent, merges into existing
|
|
124
|
-
* `mcpServers`, and never clobbers a `lensmcp` entry the user already
|
|
125
|
-
* customised.
|
|
126
|
-
*/
|
|
127
|
-
function registerWorkspaceMcpConfig(tree, steps) {
|
|
128
|
-
const path = '.mcp.json';
|
|
129
|
-
let config = {};
|
|
130
|
-
if (tree.exists(path)) {
|
|
131
|
-
try {
|
|
132
|
-
config = JSON.parse(tree.read(path, 'utf-8') ?? '{}');
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
config = {};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (!config || typeof config !== 'object')
|
|
139
|
-
config = {};
|
|
140
|
-
if (!config.mcpServers || typeof config.mcpServers !== 'object') {
|
|
141
|
-
config.mcpServers = {};
|
|
142
|
-
}
|
|
143
|
-
if (config.mcpServers['lensmcp'])
|
|
144
|
-
return; // already registered — leave it
|
|
145
|
-
config.mcpServers['lensmcp'] = { ...LENSMCP_MCP_SERVER_ENTRY };
|
|
146
|
-
tree.write(path, JSON.stringify(config, null, 2) + '\n');
|
|
147
|
-
steps.push('.mcp.json: registered lensmcp MCP server (stdio)');
|
|
148
|
-
}
|
|
149
|
-
exports.default = initGenerator;
|
|
150
|
-
// -------- helpers --------
|
|
151
|
-
function mergeDeep(defaults, overrides) {
|
|
152
|
-
const out = { ...defaults };
|
|
153
|
-
for (const [key, value] of Object.entries(overrides)) {
|
|
154
|
-
if (value !== null &&
|
|
155
|
-
typeof value === 'object' &&
|
|
156
|
-
!Array.isArray(value) &&
|
|
157
|
-
out[key] !== null &&
|
|
158
|
-
typeof out[key] === 'object' &&
|
|
159
|
-
!Array.isArray(out[key])) {
|
|
160
|
-
out[key] = mergeDeep(out[key], value);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
out[key] = value;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return out;
|
|
167
|
-
}
|
|
1
|
+
"use strict";var f=Object.defineProperty;var p=(n,t)=>f(n,"name",{value:t,configurable:!0});var m=Object.defineProperty,a=p((n,t)=>m(n,"name",{value:t,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.initGenerator=initGenerator;const devkit_1=require("@nx/devkit"),DEFAULT_LENSMCP_CONFIG={schemaVersion:1,storage:"memory",transport:"stdio",retention:{sessions:5,events:5e3,screenshots:50,buildReports:20,visualFrames:200,heapSnapshots:3,tracesWithErrors:20,verifications:10},redaction:{headers:["authorization","cookie","set-cookie","x-api-key"],paths:["password","token","secret","apiKey","api_key"]},channels:{blockingStatusChanged:{enabled:!0,minSeverity:"error"},memoryLeakSuspected:{enabled:!0,minSeverity:"warning"},bundleRegression:{enabled:!0,minSeverity:"warning"},visualViolationBlocking:{enabled:!0,minSeverity:"error"},verificationCompleted:{enabled:!0,minSeverity:"info"}},thresholds:{dbInLoop:5,nPlusOne:3,renderStorm:5,slowRouteMs:500,slowRenderMs:16}},LENSMCP_GITIGNORE_MARKER="# LensMCP runtime artifacts (per-session storage)",LENSMCP_GITIGNORE_ENTRY=".lensmcp/";async function initGenerator(n,t={}){const s={skipFormat:t.skipFormat??!1,registerHostConfig:t.registerHostConfig??"auto"},e=[];if(n.exists("nx.json"))(0,devkit_1.updateJson)(n,"nx.json",r=>{r.plugins=Array.isArray(r.plugins)?r.plugins:[],r.plugins.some(o=>typeof o=="string"?o==="@lensmcp/nx-plugin":o&&typeof o=="object"&&"plugin"in o?o.plugin==="@lensmcp/nx-plugin":!1)||(r.plugins.push("@lensmcp/nx-plugin"),e.push("nx.json: registered @lensmcp/nx-plugin"));const d=r.lensmcp??{};return r.lensmcp=mergeDeep(DEFAULT_LENSMCP_CONFIG,d),(!("lensmcp"in r)||Object.keys(d).length===0)&&e.push("nx.json: added workspace-wide `lensmcp` config block"),r});else throw new Error("No nx.json found at the workspace root. Are you in a Nx workspace?");const i=".gitignore",c=n.exists(i)?n.read(i,"utf-8")??"":"";if(!c.split(`
|
|
2
|
+
`).some(r=>r.trim()===LENSMCP_GITIGNORE_ENTRY)){const r=c.endsWith(`
|
|
3
|
+
`)?"":`
|
|
4
|
+
`;n.write(i,`${c}${r}
|
|
5
|
+
${LENSMCP_GITIGNORE_MARKER}
|
|
6
|
+
${LENSMCP_GITIGNORE_ENTRY}
|
|
7
|
+
`),e.push(`${i}: added \`${LENSMCP_GITIGNORE_ENTRY}\``)}const l=(0,devkit_1.joinPathFragments)(".lensmcp",".keep");n.exists(l)||(n.write(l,""),e.push(`${l}: created`));const u=(0,devkit_1.joinPathFragments)(".lensmcp","install-trail.json"),g=(n.exists(u)?JSON.parse(n.read(u,"utf-8")??"{}"):void 0)??{schemaVersion:1,installedAt:new Date().toISOString(),steps:[]};g.steps.push(...e),n.write(u,JSON.stringify(g,null,2)+`
|
|
8
|
+
`),s.registerHostConfig!=="never"&®isterWorkspaceMcpConfig(n,e),s.skipFormat||await(0,devkit_1.formatFiles)(n)}p(initGenerator,"initGenerator"),a(initGenerator,"initGenerator");const LENSMCP_MCP_SERVER_ENTRY={command:"npx",args:["-y","lensmcp","mcp"]};function registerWorkspaceMcpConfig(n,t){const s=".mcp.json";let e={};if(n.exists(s))try{e=JSON.parse(n.read(s,"utf-8")??"{}")}catch{e={}}(!e||typeof e!="object")&&(e={}),(!e.mcpServers||typeof e.mcpServers!="object")&&(e.mcpServers={}),!e.mcpServers.lensmcp&&(e.mcpServers.lensmcp={...LENSMCP_MCP_SERVER_ENTRY},n.write(s,JSON.stringify(e,null,2)+`
|
|
9
|
+
`),t.push(".mcp.json: registered lensmcp MCP server (stdio)"))}p(registerWorkspaceMcpConfig,"registerWorkspaceMcpConfig"),a(registerWorkspaceMcpConfig,"registerWorkspaceMcpConfig"),exports.default=initGenerator;function mergeDeep(n,t){const s={...n};for(const[e,i]of Object.entries(t))i!==null&&typeof i=="object"&&!Array.isArray(i)&&s[e]!==null&&typeof s[e]=="object"&&!Array.isArray(s[e])?s[e]=mergeDeep(s[e],i):s[e]=i;return s}p(mergeDeep,"mergeDeep"),a(mergeDeep,"mergeDeep");
|
|
@@ -38,4 +38,3 @@ export declare function patchMainBootstrap(src: string, projectName: string): st
|
|
|
38
38
|
* Idempotent. Returns `null` when no `@Module` imports array is found.
|
|
39
39
|
*/
|
|
40
40
|
export declare function patchAppModule(src: string, projectName: string): string | null;
|
|
41
|
-
//# sourceMappingURL=setup-nest.d.ts.map
|