@ng-annotate/angular 0.3.6 → 0.3.7
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/package.json +1 -1
- package/schematics/ng-add/index.js +93 -21
- package/schematics/ng-add/index.ts +75 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-annotate/angular",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"schematics": "./schematics/collection.json",
|
|
5
5
|
"description": "Angular library for ng-annotate-mcp — browser overlay for annotating components and routing instructions to an AI agent",
|
|
6
6
|
"keywords": [
|
|
@@ -1,8 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.default = default_1;
|
|
4
37
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
5
38
|
const tasks_1 = require("@angular-devkit/schematics/tasks");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
6
41
|
/** Insert `newImport` on the line after the last import statement (handles multi-line imports and blank lines between groups). */
|
|
7
42
|
function insertAfterLastImport(content, newImport) {
|
|
8
43
|
const lines = content.split('\n');
|
|
@@ -90,12 +125,43 @@ function addProviders() {
|
|
|
90
125
|
context.logger.info(`✅ Added provideNgAnnotate() to ${appConfigPath}`);
|
|
91
126
|
};
|
|
92
127
|
}
|
|
128
|
+
/** Walk up from startDir until we find a .git folder; returns that directory or null. */
|
|
129
|
+
function findGitRoot(startDir) {
|
|
130
|
+
let dir = path.resolve(startDir);
|
|
131
|
+
while (true) {
|
|
132
|
+
if (fs.existsSync(path.join(dir, '.git')))
|
|
133
|
+
return dir;
|
|
134
|
+
const parent = path.dirname(dir);
|
|
135
|
+
if (parent === dir)
|
|
136
|
+
return null;
|
|
137
|
+
dir = parent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Write a config file outside the schematic Tree (e.g. to a parent git root).
|
|
142
|
+
* Uses fs directly — intentionally bypasses Tree so it works for out-of-project paths.
|
|
143
|
+
*/
|
|
144
|
+
function writeOutsideTree(absPath, content, context) {
|
|
145
|
+
const dir = path.dirname(absPath);
|
|
146
|
+
if (!fs.existsSync(dir))
|
|
147
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
148
|
+
if (fs.existsSync(absPath)) {
|
|
149
|
+
context.logger.info(`${path.basename(absPath)} already exists at workspace root, skipping.`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
fs.writeFileSync(absPath, content, 'utf-8');
|
|
153
|
+
context.logger.info(`✅ Created ${path.basename(absPath)} at workspace root (${dir})`);
|
|
154
|
+
}
|
|
93
155
|
function addMcpConfig(options) {
|
|
94
156
|
return (tree, context) => {
|
|
95
|
-
const projectRoot = process.cwd()
|
|
96
|
-
const env = { NG_ANNOTATE_PROJECT_ROOT: projectRoot };
|
|
157
|
+
const projectRoot = process.cwd();
|
|
158
|
+
const env = { NG_ANNOTATE_PROJECT_ROOT: projectRoot.replace(/\\/g, '/') };
|
|
97
159
|
const isWindows = process.platform === 'win32';
|
|
98
160
|
const { aiTool } = options;
|
|
161
|
+
// Detect monorepo: if git root is a parent of the Angular project, VS Code is likely
|
|
162
|
+
// opened there — write configs to both the project folder and the git root.
|
|
163
|
+
const gitRoot = findGitRoot(projectRoot);
|
|
164
|
+
const isSubproject = gitRoot !== null && path.resolve(gitRoot) !== path.resolve(projectRoot);
|
|
99
165
|
if (aiTool === 'other') {
|
|
100
166
|
const claudeConfig = JSON.stringify({
|
|
101
167
|
mcpServers: {
|
|
@@ -125,41 +191,47 @@ function addMcpConfig(options) {
|
|
|
125
191
|
}
|
|
126
192
|
// .mcp.json — Claude Code (needs cmd /c on Windows to invoke npx.cmd)
|
|
127
193
|
if (aiTool === 'claude-code' || aiTool === 'both') {
|
|
194
|
+
const mcpConfig = JSON.stringify({
|
|
195
|
+
mcpServers: {
|
|
196
|
+
'ng-annotate': isWindows
|
|
197
|
+
? { command: 'cmd', args: ['/c', 'npx', '-y', '@ng-annotate/mcp-server'], env }
|
|
198
|
+
: { command: 'npx', args: ['-y', '@ng-annotate/mcp-server'], env },
|
|
199
|
+
},
|
|
200
|
+
}, null, 2) + '\n';
|
|
128
201
|
if (!tree.exists('.mcp.json')) {
|
|
129
|
-
|
|
130
|
-
mcpServers: {
|
|
131
|
-
'ng-annotate': isWindows
|
|
132
|
-
? { command: 'cmd', args: ['/c', 'npx', '-y', '@ng-annotate/mcp-server'], env }
|
|
133
|
-
: { command: 'npx', args: ['-y', '@ng-annotate/mcp-server'], env },
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
tree.create('.mcp.json', JSON.stringify(mcpConfig, null, 2) + '\n');
|
|
202
|
+
tree.create('.mcp.json', mcpConfig);
|
|
137
203
|
context.logger.info('✅ Created .mcp.json');
|
|
138
204
|
}
|
|
139
205
|
else {
|
|
140
206
|
context.logger.info('.mcp.json already exists, skipping.');
|
|
141
207
|
}
|
|
208
|
+
if (isSubproject) {
|
|
209
|
+
writeOutsideTree(path.join(gitRoot, '.mcp.json'), mcpConfig, context);
|
|
210
|
+
}
|
|
142
211
|
}
|
|
143
212
|
// .vscode/mcp.json — VS Code Copilot
|
|
144
213
|
if (aiTool === 'vscode' || aiTool === 'both') {
|
|
214
|
+
const vscodeMcpConfig = JSON.stringify({
|
|
215
|
+
servers: {
|
|
216
|
+
'ng-annotate': {
|
|
217
|
+
type: 'stdio',
|
|
218
|
+
command: 'npx',
|
|
219
|
+
args: ['-y', '@ng-annotate/mcp-server'],
|
|
220
|
+
env,
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
}, null, 2) + '\n';
|
|
145
224
|
const vscodeMcpPath = '.vscode/mcp.json';
|
|
146
225
|
if (!tree.exists(vscodeMcpPath)) {
|
|
147
|
-
|
|
148
|
-
servers: {
|
|
149
|
-
'ng-annotate': {
|
|
150
|
-
type: 'stdio',
|
|
151
|
-
command: 'npx',
|
|
152
|
-
args: ['-y', '@ng-annotate/mcp-server'],
|
|
153
|
-
env,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
tree.create(vscodeMcpPath, JSON.stringify(vscodeMcpConfig, null, 2) + '\n');
|
|
226
|
+
tree.create(vscodeMcpPath, vscodeMcpConfig);
|
|
158
227
|
context.logger.info('✅ Created .vscode/mcp.json');
|
|
159
228
|
}
|
|
160
229
|
else {
|
|
161
230
|
context.logger.info('.vscode/mcp.json already exists, skipping.');
|
|
162
231
|
}
|
|
232
|
+
if (isSubproject) {
|
|
233
|
+
writeOutsideTree(path.join(gitRoot, '.vscode', 'mcp.json'), vscodeMcpConfig, context);
|
|
234
|
+
}
|
|
163
235
|
}
|
|
164
236
|
};
|
|
165
237
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Rule, SchematicContext, Tree, chain, SchematicsException } from '@angular-devkit/schematics';
|
|
2
2
|
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
3
5
|
|
|
4
6
|
/** Insert `newImport` on the line after the last import statement (handles multi-line imports and blank lines between groups). */
|
|
5
7
|
function insertAfterLastImport(content: string, newImport: string): string {
|
|
@@ -116,13 +118,45 @@ function addProviders(): Rule {
|
|
|
116
118
|
};
|
|
117
119
|
}
|
|
118
120
|
|
|
121
|
+
/** Walk up from startDir until we find a .git folder; returns that directory or null. */
|
|
122
|
+
function findGitRoot(startDir: string): string | null {
|
|
123
|
+
let dir = path.resolve(startDir);
|
|
124
|
+
while (true) {
|
|
125
|
+
if (fs.existsSync(path.join(dir, '.git'))) return dir;
|
|
126
|
+
const parent = path.dirname(dir);
|
|
127
|
+
if (parent === dir) return null;
|
|
128
|
+
dir = parent;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Write a config file outside the schematic Tree (e.g. to a parent git root).
|
|
134
|
+
* Uses fs directly — intentionally bypasses Tree so it works for out-of-project paths.
|
|
135
|
+
*/
|
|
136
|
+
function writeOutsideTree(absPath: string, content: string, context: SchematicContext): void {
|
|
137
|
+
const dir = path.dirname(absPath);
|
|
138
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
139
|
+
if (fs.existsSync(absPath)) {
|
|
140
|
+
context.logger.info(`${path.basename(absPath)} already exists at workspace root, skipping.`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
fs.writeFileSync(absPath, content, 'utf-8');
|
|
144
|
+
context.logger.info(`✅ Created ${path.basename(absPath)} at workspace root (${dir})`);
|
|
145
|
+
}
|
|
146
|
+
|
|
119
147
|
function addMcpConfig(options: Options): Rule {
|
|
120
148
|
return (tree: Tree, context: SchematicContext) => {
|
|
121
|
-
const projectRoot = process.cwd()
|
|
122
|
-
const env = { NG_ANNOTATE_PROJECT_ROOT: projectRoot };
|
|
149
|
+
const projectRoot = process.cwd();
|
|
150
|
+
const env = { NG_ANNOTATE_PROJECT_ROOT: projectRoot.replace(/\\/g, '/') };
|
|
123
151
|
const isWindows = process.platform === 'win32';
|
|
124
152
|
const { aiTool } = options;
|
|
125
153
|
|
|
154
|
+
// Detect monorepo: if git root is a parent of the Angular project, VS Code is likely
|
|
155
|
+
// opened there — write configs to both the project folder and the git root.
|
|
156
|
+
const gitRoot = findGitRoot(projectRoot);
|
|
157
|
+
const isSubproject =
|
|
158
|
+
gitRoot !== null && path.resolve(gitRoot) !== path.resolve(projectRoot);
|
|
159
|
+
|
|
126
160
|
if (aiTool === 'other') {
|
|
127
161
|
const claudeConfig = JSON.stringify(
|
|
128
162
|
{
|
|
@@ -163,40 +197,60 @@ function addMcpConfig(options: Options): Rule {
|
|
|
163
197
|
|
|
164
198
|
// .mcp.json — Claude Code (needs cmd /c on Windows to invoke npx.cmd)
|
|
165
199
|
if (aiTool === 'claude-code' || aiTool === 'both') {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
200
|
+
const mcpConfig =
|
|
201
|
+
JSON.stringify(
|
|
202
|
+
{
|
|
203
|
+
mcpServers: {
|
|
204
|
+
'ng-annotate': isWindows
|
|
205
|
+
? { command: 'cmd', args: ['/c', 'npx', '-y', '@ng-annotate/mcp-server'], env }
|
|
206
|
+
: { command: 'npx', args: ['-y', '@ng-annotate/mcp-server'], env },
|
|
207
|
+
},
|
|
172
208
|
},
|
|
173
|
-
|
|
174
|
-
|
|
209
|
+
null,
|
|
210
|
+
2,
|
|
211
|
+
) + '\n';
|
|
212
|
+
|
|
213
|
+
if (!tree.exists('.mcp.json')) {
|
|
214
|
+
tree.create('.mcp.json', mcpConfig);
|
|
175
215
|
context.logger.info('✅ Created .mcp.json');
|
|
176
216
|
} else {
|
|
177
217
|
context.logger.info('.mcp.json already exists, skipping.');
|
|
178
218
|
}
|
|
219
|
+
|
|
220
|
+
if (isSubproject) {
|
|
221
|
+
writeOutsideTree(path.join(gitRoot!, '.mcp.json'), mcpConfig, context);
|
|
222
|
+
}
|
|
179
223
|
}
|
|
180
224
|
|
|
181
225
|
// .vscode/mcp.json — VS Code Copilot
|
|
182
226
|
if (aiTool === 'vscode' || aiTool === 'both') {
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
const vscodeMcpConfig =
|
|
228
|
+
JSON.stringify(
|
|
229
|
+
{
|
|
230
|
+
servers: {
|
|
231
|
+
'ng-annotate': {
|
|
232
|
+
type: 'stdio',
|
|
233
|
+
command: 'npx',
|
|
234
|
+
args: ['-y', '@ng-annotate/mcp-server'],
|
|
235
|
+
env,
|
|
236
|
+
},
|
|
192
237
|
},
|
|
193
238
|
},
|
|
194
|
-
|
|
195
|
-
|
|
239
|
+
null,
|
|
240
|
+
2,
|
|
241
|
+
) + '\n';
|
|
242
|
+
|
|
243
|
+
const vscodeMcpPath = '.vscode/mcp.json';
|
|
244
|
+
if (!tree.exists(vscodeMcpPath)) {
|
|
245
|
+
tree.create(vscodeMcpPath, vscodeMcpConfig);
|
|
196
246
|
context.logger.info('✅ Created .vscode/mcp.json');
|
|
197
247
|
} else {
|
|
198
248
|
context.logger.info('.vscode/mcp.json already exists, skipping.');
|
|
199
249
|
}
|
|
250
|
+
|
|
251
|
+
if (isSubproject) {
|
|
252
|
+
writeOutsideTree(path.join(gitRoot!, '.vscode', 'mcp.json'), vscodeMcpConfig, context);
|
|
253
|
+
}
|
|
200
254
|
}
|
|
201
255
|
};
|
|
202
256
|
}
|