@frontmcp/nx 0.12.2 → 1.0.0-beta.10
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/build-exec/build-exec.impl.js +1 -1
- package/executors/build-exec/build-exec.impl.js.map +1 -1
- package/executors.json +1 -1
- package/generators/server/files/lambda/template.yaml__tmpl__ +1 -1
- package/generators/server/files/node/docker-compose.yml__tmpl__ +14 -5
- package/generators/server/schema.d.ts +1 -0
- package/generators/server/schema.js.map +1 -1
- package/generators/server/schema.json +6 -0
- package/generators/server/server.js +47 -0
- package/generators/server/server.js.map +1 -1
- package/generators/skill-dir/files/__name__/SKILL.md__tmpl__ +14 -0
- package/generators/skill-dir/schema.d.ts +9 -0
- package/generators/skill-dir/schema.js +3 -0
- package/generators/skill-dir/schema.js.map +1 -0
- package/generators/skill-dir/schema.json +48 -0
- package/generators/skill-dir/skill-dir.d.ts +4 -0
- package/generators/skill-dir/skill-dir.js +35 -0
- package/generators/skill-dir/skill-dir.js.map +1 -0
- package/generators/ui-component/files/__className__/__className__.spec.tsx__tmpl__ +17 -0
- package/generators/ui-component/files/__className__/__className__.tsx__tmpl__ +14 -0
- package/generators/ui-component/files/__className__/index.ts__tmpl__ +3 -0
- package/generators/ui-component/schema.d.ts +5 -0
- package/generators/ui-component/schema.js +3 -0
- package/generators/ui-component/schema.js.map +1 -0
- package/generators/ui-component/schema.json +27 -0
- package/generators/ui-component/ui-component.d.ts +4 -0
- package/generators/ui-component/ui-component.js +33 -0
- package/generators/ui-component/ui-component.js.map +1 -0
- package/generators/ui-page/files/__className__/__className__.spec.tsx__tmpl__ +17 -0
- package/generators/ui-page/files/__className__/__className__.tsx__tmpl__ +16 -0
- package/generators/ui-page/files/__className__/index.ts__tmpl__ +3 -0
- package/generators/ui-page/schema.d.ts +5 -0
- package/generators/ui-page/schema.js +3 -0
- package/generators/ui-page/schema.js.map +1 -0
- package/generators/ui-page/schema.json +27 -0
- package/generators/ui-page/ui-page.d.ts +4 -0
- package/generators/ui-page/ui-page.js +33 -0
- package/generators/ui-page/ui-page.js.map +1 -0
- package/generators/ui-shared/add-ui-entry.d.ts +16 -0
- package/generators/ui-shared/add-ui-entry.js +60 -0
- package/generators/ui-shared/add-ui-entry.js.map +1 -0
- package/generators/ui-shell/files/__fileName__/__fileName__.shell.spec.ts__tmpl__ +16 -0
- package/generators/ui-shell/files/__fileName__/__fileName__.shell.ts__tmpl__ +20 -0
- package/generators/ui-shell/files/__fileName__/index.ts__tmpl__ +2 -0
- package/generators/ui-shell/schema.d.ts +5 -0
- package/generators/ui-shell/schema.js +3 -0
- package/generators/ui-shell/schema.js.map +1 -0
- package/generators/ui-shell/schema.json +27 -0
- package/generators/ui-shell/ui-shell.d.ts +4 -0
- package/generators/ui-shell/ui-shell.js +30 -0
- package/generators/ui-shell/ui-shell.js.map +1 -0
- package/generators/workspace/files/AGENTS.md__tmpl__ +52 -0
- package/generators/workspace/files/CLAUDE.md__tmpl__ +216 -0
- package/generators/workspace/files/README.md__tmpl__ +70 -0
- package/generators/workspace/files/__dot__cursorrules__tmpl__ +3 -0
- package/generators/workspace/files/__dot__gitignore__tmpl__ +3 -0
- package/generators/workspace/files/__dot__mcp.json__tmpl__ +8 -0
- package/generators/workspace/files/__dot__nvmrc__tmpl__ +1 -0
- package/generators/workspace/files/package.json__tmpl__ +1 -1
- package/generators/workspace/workspace.js +19 -0
- package/generators/workspace/workspace.js.map +1 -1
- package/generators.json +20 -0
- package/index.d.ts +3 -0
- package/index.js +7 -1
- package/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = buildExecExecutor;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
async function buildExecExecutor(options, context) {
|
|
6
|
-
const args = ['npx', 'frontmcp', 'build', '--
|
|
6
|
+
const args = ['npx', 'frontmcp', 'build', '--target', 'node'];
|
|
7
7
|
if (options.entry)
|
|
8
8
|
args.push('--entry', options.entry);
|
|
9
9
|
if (options.outputPath)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-exec.impl.js","sourceRoot":"","sources":["../../../../src/executors/build-exec/build-exec.impl.ts"],"names":[],"mappings":";;AAIA,oCAqBC;AAxBD,iDAAyC;AAG1B,KAAK,UAAU,iBAAiB,CAC7C,OAAgC,EAChC,OAAwB;IAExB,MAAM,IAAI,GAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"build-exec.impl.js","sourceRoot":"","sources":["../../../../src/executors/build-exec/build-exec.impl.ts"],"names":[],"mappings":";;AAIA,oCAqBC;AAxBD,iDAAyC;AAG1B,KAAK,UAAU,iBAAiB,CAC7C,OAAgC,EAChC,OAAwB;IAExB,MAAM,IAAI,GAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACxE,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,UAAU;QAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;IAEnC,IAAI,CAAC;QACH,IAAA,wBAAQ,EAAC,OAAO,EAAE;YAChB,GAAG,EAAE,OAAO,CAAC,IAAI;YACjB,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE;SAC1C,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC","sourcesContent":["import type { ExecutorContext } from '../executor-context.js';\nimport { execSync } from 'child_process';\nimport type { BuildExecExecutorSchema } from './schema.js';\n\nexport default async function buildExecExecutor(\n options: BuildExecExecutorSchema,\n context: ExecutorContext,\n): Promise<{ success: boolean }> {\n const args: string[] = ['npx', 'frontmcp', 'build', '--target', 'node'];\n if (options.entry) args.push('--entry', options.entry);\n if (options.outputPath) args.push('--out-dir', options.outputPath);\n\n const command = args.join(' ');\n console.log(`Running: ${command}`);\n\n try {\n execSync(command, {\n cwd: context.root,\n stdio: 'inherit',\n env: { ...process.env, FORCE_COLOR: '1' },\n });\n return { success: true };\n } catch {\n return { success: false };\n }\n}\n"]}
|
package/executors.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"build-exec": {
|
|
9
9
|
"implementation": "./executors/build-exec/build-exec.impl",
|
|
10
10
|
"schema": "./executors/build-exec/schema.json",
|
|
11
|
-
"description": "Build a distributable bundle using frontmcp build --
|
|
11
|
+
"description": "Build a distributable bundle using frontmcp build --target node"
|
|
12
12
|
},
|
|
13
13
|
"dev": {
|
|
14
14
|
"implementation": "./executors/dev/dev.impl",
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
version: '3.8'
|
|
2
|
-
|
|
3
1
|
services:
|
|
4
2
|
app:
|
|
5
3
|
build:
|
|
6
4
|
context: ../..
|
|
7
5
|
dockerfile: <%= projectRoot %>/Dockerfile
|
|
8
6
|
ports:
|
|
9
|
-
- '3000:3000'
|
|
7
|
+
- '${PORT:-3000}:3000'
|
|
10
8
|
environment:
|
|
11
|
-
- NODE_ENV
|
|
9
|
+
- NODE_ENV=${NODE_ENV:-production}
|
|
10
|
+
- PORT=${PORT:-3000}
|
|
12
11
|
<% if (redis === 'docker') { %>
|
|
13
12
|
- REDIS_HOST=redis
|
|
14
13
|
- REDIS_PORT=6379
|
|
@@ -20,9 +19,19 @@ services:
|
|
|
20
19
|
image: redis:7-alpine
|
|
21
20
|
ports:
|
|
22
21
|
- '6379:6379'
|
|
22
|
+
volumes:
|
|
23
|
+
- redis-data:/data
|
|
24
|
+
command: redis-server --appendonly yes
|
|
23
25
|
healthcheck:
|
|
24
26
|
test: ['CMD', 'redis-cli', 'ping']
|
|
25
|
-
interval:
|
|
27
|
+
interval: 3s
|
|
26
28
|
timeout: 5s
|
|
27
29
|
retries: 3
|
|
30
|
+
|
|
31
|
+
volumes:
|
|
32
|
+
redis-data:
|
|
28
33
|
<% } %>
|
|
34
|
+
|
|
35
|
+
# Selective rebuild:
|
|
36
|
+
# docker compose up --build app # rebuild only the app
|
|
37
|
+
# docker compose up --build # rebuild everything
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/generators/server/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface ServerGeneratorSchema {\n name: string;\n directory?: string;\n deploymentTarget?: 'node' | 'vercel' | 'lambda' | 'cloudflare';\n apps: string;\n redis?: 'docker' | 'existing' | 'none';\n tags?: string;\n skipFormat?: boolean;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/generators/server/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface ServerGeneratorSchema {\n name: string;\n directory?: string;\n deploymentTarget?: 'node' | 'vercel' | 'lambda' | 'cloudflare';\n apps: string;\n redis?: 'docker' | 'existing' | 'none';\n skills?: 'recommended' | 'minimal' | 'full' | 'none';\n tags?: string;\n skipFormat?: boolean;\n}\n"]}
|
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"description": "Comma-separated tags",
|
|
52
52
|
"x-priority": "internal"
|
|
53
53
|
},
|
|
54
|
+
"skills": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"description": "Skills bundle to include: recommended, minimal, full, none",
|
|
57
|
+
"enum": ["recommended", "minimal", "full", "none"],
|
|
58
|
+
"default": "recommended"
|
|
59
|
+
},
|
|
54
60
|
"skipFormat": {
|
|
55
61
|
"type": "boolean",
|
|
56
62
|
"description": "Skip formatting files",
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.serverGenerator = serverGenerator;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
4
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
5
7
|
const path_1 = require("path");
|
|
6
8
|
const index_js_1 = require("./lib/index.js");
|
|
7
9
|
async function serverGenerator(tree, schema) {
|
|
@@ -20,9 +22,54 @@ async function serverGeneratorInternal(tree, schema) {
|
|
|
20
22
|
// Generate target-specific files
|
|
21
23
|
const targetDir = (0, path_1.join)(__dirname, 'files', options.deploymentTarget);
|
|
22
24
|
(0, devkit_1.generateFiles)(tree, targetDir, options.projectRoot, templateVars);
|
|
25
|
+
// Copy skills from catalog
|
|
26
|
+
const bundle = schema.skills ?? 'recommended';
|
|
27
|
+
if (bundle !== 'none') {
|
|
28
|
+
scaffoldCatalogSkills(tree, options.projectRoot, options.deploymentTarget, bundle);
|
|
29
|
+
}
|
|
23
30
|
if (!options.skipFormat) {
|
|
24
31
|
await (0, devkit_1.formatFiles)(tree);
|
|
25
32
|
}
|
|
26
33
|
}
|
|
34
|
+
function scaffoldCatalogSkills(tree, projectRoot, target, bundle) {
|
|
35
|
+
// Load skills catalog via @frontmcp/skills package at runtime
|
|
36
|
+
let skills;
|
|
37
|
+
try {
|
|
38
|
+
skills = require('@frontmcp/skills');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let manifest;
|
|
44
|
+
try {
|
|
45
|
+
manifest = skills.loadManifest();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const targetFiltered = skills.getSkillsByTarget(manifest.skills, target);
|
|
51
|
+
const matchingSkills = skills.getSkillsByBundle(targetFiltered, bundle);
|
|
52
|
+
for (const skill of matchingSkills) {
|
|
53
|
+
const sourceDir = skills.resolveSkillPath(skill);
|
|
54
|
+
const destDir = (0, path_1.join)(projectRoot, 'skills', skill.name);
|
|
55
|
+
copyDirToTree(tree, sourceDir, destDir);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function copyDirToTree(tree, sourceDir, destDir) {
|
|
59
|
+
if (!fs.existsSync(sourceDir))
|
|
60
|
+
return;
|
|
61
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
62
|
+
for (const entry of entries) {
|
|
63
|
+
const srcPath = (0, path_1.join)(sourceDir, entry.name);
|
|
64
|
+
const destPath = (0, path_1.join)(destDir, entry.name);
|
|
65
|
+
if (entry.isDirectory()) {
|
|
66
|
+
copyDirToTree(tree, srcPath, destPath);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const content = fs.readFileSync(srcPath);
|
|
70
|
+
tree.write(destPath, content);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
27
74
|
exports.default = serverGenerator;
|
|
28
75
|
//# sourceMappingURL=server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/generators/server/server.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/generators/server/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, formatFiles, generateFiles, names as nxNames, type GeneratorCallback } from '@nx/devkit';\nimport * as fs from 'fs';\nimport { join } from 'path';\nimport type { ServerGeneratorSchema } from './schema.js';\nimport { normalizeOptions } from './lib/index.js';\n\nexport async function serverGenerator(tree: Tree, schema: ServerGeneratorSchema): Promise<GeneratorCallback | void> {\n return serverGeneratorInternal(tree, schema);\n}\n\nasync function serverGeneratorInternal(tree: Tree, schema: ServerGeneratorSchema): Promise<GeneratorCallback | void> {\n const options = normalizeOptions(schema);\n\n const templateVars = {\n ...options,\n names: nxNames,\n tmpl: '',\n dot: '.',\n };\n\n // Generate common files (main.ts, project.json, tsconfig)\n generateFiles(tree, join(__dirname, 'files', 'common'), options.projectRoot, templateVars);\n\n // Generate target-specific files\n const targetDir = join(__dirname, 'files', options.deploymentTarget);\n generateFiles(tree, targetDir, options.projectRoot, templateVars);\n\n // Copy skills from catalog\n const bundle = schema.skills ?? 'recommended';\n if (bundle !== 'none') {\n scaffoldCatalogSkills(tree, options.projectRoot, options.deploymentTarget, bundle);\n }\n\n if (!options.skipFormat) {\n await formatFiles(tree);\n }\n}\n\nfunction scaffoldCatalogSkills(tree: Tree, projectRoot: string, target: string, bundle: string): void {\n // Load skills catalog via @frontmcp/skills package at runtime\n let skills: {\n loadManifest: () => {\n skills: Array<{ name: string; path: string; targets: string[]; hasResources: boolean; bundle?: string[] }>;\n };\n resolveSkillPath: (entry: { path: string }) => string;\n getSkillsByTarget: (\n s: Array<{ targets: string[] }>,\n t: string,\n ) => Array<{ name: string; path: string; targets: string[]; hasResources: boolean; bundle?: string[] }>;\n getSkillsByBundle: (\n s: Array<{ bundle?: string[] }>,\n b: string,\n ) => Array<{ name: string; path: string; targets: string[]; hasResources: boolean; bundle?: string[] }>;\n };\n try {\n skills = require('@frontmcp/skills');\n } catch {\n return;\n }\n\n let manifest;\n try {\n manifest = skills.loadManifest();\n } catch {\n return;\n }\n\n const targetFiltered = skills.getSkillsByTarget(manifest.skills, target);\n const matchingSkills = skills.getSkillsByBundle(targetFiltered, bundle);\n\n for (const skill of matchingSkills) {\n const sourceDir = skills.resolveSkillPath(skill);\n const destDir = join(projectRoot, 'skills', skill.name);\n copyDirToTree(tree, sourceDir, destDir);\n }\n}\n\nfunction copyDirToTree(tree: Tree, sourceDir: string, destDir: string): void {\n if (!fs.existsSync(sourceDir)) return;\n const entries = fs.readdirSync(sourceDir, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = join(sourceDir, entry.name);\n const destPath = join(destDir, entry.name);\n if (entry.isDirectory()) {\n copyDirToTree(tree, srcPath, destPath);\n } else {\n const content = fs.readFileSync(srcPath);\n tree.write(destPath, content);\n }\n }\n}\n\nexport default serverGenerator;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/generators/skill-dir/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface SkillDirGeneratorSchema {\n name: string;\n project: string;\n description?: string;\n directory?: string;\n tags?: string;\n withReferences?: boolean;\n skipFormat?: boolean;\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "FrontMcpSkillDir",
|
|
4
|
+
"title": "FrontMCP Skill Directory Generator",
|
|
5
|
+
"description": "Generate a SKILL.md-based skill directory",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"name": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The skill name (kebab-case)",
|
|
11
|
+
"$default": { "$source": "argv", "index": 0 },
|
|
12
|
+
"x-prompt": "What name would you like for the skill?",
|
|
13
|
+
"x-priority": "important"
|
|
14
|
+
},
|
|
15
|
+
"project": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The project to add the skill to",
|
|
18
|
+
"x-prompt": "Which project should the skill be added to?",
|
|
19
|
+
"x-priority": "important"
|
|
20
|
+
},
|
|
21
|
+
"description": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Short description of what the skill does",
|
|
24
|
+
"x-prompt": "What does this skill do?",
|
|
25
|
+
"x-priority": "important"
|
|
26
|
+
},
|
|
27
|
+
"directory": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Custom directory relative to the project root (default: skills)"
|
|
30
|
+
},
|
|
31
|
+
"tags": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Comma-separated tags for categorization"
|
|
34
|
+
},
|
|
35
|
+
"withReferences": {
|
|
36
|
+
"type": "boolean",
|
|
37
|
+
"description": "Include a references/ directory",
|
|
38
|
+
"default": false
|
|
39
|
+
},
|
|
40
|
+
"skipFormat": {
|
|
41
|
+
"type": "boolean",
|
|
42
|
+
"description": "Skip formatting files",
|
|
43
|
+
"default": false,
|
|
44
|
+
"x-priority": "internal"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"required": ["name", "project"]
|
|
48
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Tree, type GeneratorCallback } from '@nx/devkit';
|
|
2
|
+
import type { SkillDirGeneratorSchema } from './schema.js';
|
|
3
|
+
export declare function skillDirGenerator(tree: Tree, schema: SkillDirGeneratorSchema): Promise<GeneratorCallback | void>;
|
|
4
|
+
export default skillDirGenerator;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.skillDirGenerator = skillDirGenerator;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
async function skillDirGenerator(tree, schema) {
|
|
7
|
+
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, schema.project);
|
|
8
|
+
const projectRoot = projectConfig.root;
|
|
9
|
+
const baseDir = schema.directory ?? 'skills';
|
|
10
|
+
const targetDir = (0, path_1.join)(projectRoot, baseDir);
|
|
11
|
+
const tags = schema.tags
|
|
12
|
+
? schema.tags
|
|
13
|
+
.split(',')
|
|
14
|
+
.map((t) => t.trim())
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.join(', ')
|
|
17
|
+
: schema.name;
|
|
18
|
+
const templateVars = {
|
|
19
|
+
name: schema.name,
|
|
20
|
+
description: schema.description ?? `Skill: ${schema.name}`,
|
|
21
|
+
tags,
|
|
22
|
+
tmpl: '',
|
|
23
|
+
};
|
|
24
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), targetDir, templateVars);
|
|
25
|
+
// Create references/ directory if requested
|
|
26
|
+
if (schema.withReferences) {
|
|
27
|
+
const refDir = (0, path_1.join)(targetDir, schema.name, 'references');
|
|
28
|
+
tree.write((0, path_1.join)(refDir, '.gitkeep'), '');
|
|
29
|
+
}
|
|
30
|
+
if (!schema.skipFormat) {
|
|
31
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.default = skillDirGenerator;
|
|
35
|
+
//# sourceMappingURL=skill-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-dir.js","sourceRoot":"","sources":["../../../../src/generators/skill-dir/skill-dir.ts"],"names":[],"mappings":";;AAIA,8CAmCC;AAvCD,uCAAqH;AACrH,+BAA4B;AAGrB,KAAK,UAAU,iBAAiB,CACrC,IAAU,EACV,MAA+B;IAE/B,MAAM,aAAa,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACrE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,IAAI,QAAQ,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI;QACtB,CAAC,CAAC,MAAM,CAAC,IAAI;aACR,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC;QACf,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAEhB,MAAM,YAAY,GAAG;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,UAAU,MAAM,CAAC,IAAI,EAAE;QAC1D,IAAI;QACJ,IAAI,EAAE,EAAE;KACT,CAAC;IAEF,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAEvE,4CAA4C;IAC5C,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,IAAA,WAAI,EAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,kBAAe,iBAAiB,CAAC","sourcesContent":["import { type Tree, formatFiles, generateFiles, readProjectConfiguration, type GeneratorCallback } from '@nx/devkit';\nimport { join } from 'path';\nimport type { SkillDirGeneratorSchema } from './schema.js';\n\nexport async function skillDirGenerator(\n tree: Tree,\n schema: SkillDirGeneratorSchema,\n): Promise<GeneratorCallback | void> {\n const projectConfig = readProjectConfiguration(tree, schema.project);\n const projectRoot = projectConfig.root;\n const baseDir = schema.directory ?? 'skills';\n const targetDir = join(projectRoot, baseDir);\n\n const tags = schema.tags\n ? schema.tags\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean)\n .join(', ')\n : schema.name;\n\n const templateVars = {\n name: schema.name,\n description: schema.description ?? `Skill: ${schema.name}`,\n tags,\n tmpl: '',\n };\n\n generateFiles(tree, join(__dirname, 'files'), targetDir, templateVars);\n\n // Create references/ directory if requested\n if (schema.withReferences) {\n const refDir = join(targetDir, schema.name, 'references');\n tree.write(join(refDir, '.gitkeep'), '');\n }\n\n if (!schema.skipFormat) {\n await formatFiles(tree);\n }\n}\n\nexport default skillDirGenerator;\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { <%= className %> } from './<%= className %>';
|
|
3
|
+
|
|
4
|
+
describe('<%= className %>', () => {
|
|
5
|
+
it('should be defined', () => {
|
|
6
|
+
expect(<%= className %>).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('should be a function component', () => {
|
|
10
|
+
expect(typeof <%= className %>).toBe('function');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should render without crashing', () => {
|
|
14
|
+
const { container } = render(<<%= className %> />);
|
|
15
|
+
expect(container.firstChild).not.toBeNull();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Typography } from '@mui/material';
|
|
3
|
+
|
|
4
|
+
export interface <%= className %>Props {
|
|
5
|
+
// TODO: define props
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function <%= className %>(props: <%= className %>Props) {
|
|
9
|
+
return (
|
|
10
|
+
<Box>
|
|
11
|
+
<Typography>TODO: implement <%= className %></Typography>
|
|
12
|
+
</Box>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/generators/ui-component/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface UiComponentGeneratorSchema {\n name: string;\n description?: string;\n skipFormat?: boolean;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "FrontMcpUiComponent",
|
|
4
|
+
"title": "FrontMCP UI Component Generator",
|
|
5
|
+
"description": "Add a UI component entry to ui/components",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"name": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Component name (PascalCase, e.g. LoginForm)",
|
|
11
|
+
"$default": { "$source": "argv", "index": 0 },
|
|
12
|
+
"x-prompt": "What name would you like for the component (PascalCase)?",
|
|
13
|
+
"x-priority": "important"
|
|
14
|
+
},
|
|
15
|
+
"description": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Brief description of the component",
|
|
18
|
+
"default": ""
|
|
19
|
+
},
|
|
20
|
+
"skipFormat": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": false,
|
|
23
|
+
"x-priority": "internal"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["name"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Tree, type GeneratorCallback } from '@nx/devkit';
|
|
2
|
+
import type { UiComponentGeneratorSchema } from './schema.js';
|
|
3
|
+
export declare function uiComponentGenerator(tree: Tree, schema: UiComponentGeneratorSchema): Promise<GeneratorCallback | void>;
|
|
4
|
+
export default uiComponentGenerator;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uiComponentGenerator = uiComponentGenerator;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const add_ui_entry_js_1 = require("../ui-shared/add-ui-entry.js");
|
|
7
|
+
const PACKAGE_ROOT = 'ui/components';
|
|
8
|
+
const IMPORT_PATH = '@frontmcp/ui-components';
|
|
9
|
+
async function uiComponentGenerator(tree, schema) {
|
|
10
|
+
const trimmedName = schema.name?.trim();
|
|
11
|
+
if (!trimmedName) {
|
|
12
|
+
throw new Error('Generator name must not be blank');
|
|
13
|
+
}
|
|
14
|
+
const { className } = (0, devkit_1.names)(trimmedName);
|
|
15
|
+
// Generate component files from templates
|
|
16
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), `${PACKAGE_ROOT}/src`, {
|
|
17
|
+
className,
|
|
18
|
+
name: schema.name,
|
|
19
|
+
description: schema.description ?? '',
|
|
20
|
+
tmpl: '',
|
|
21
|
+
});
|
|
22
|
+
// Add entry point to project.json, tsconfig.base.json, and barrel index.ts
|
|
23
|
+
(0, add_ui_entry_js_1.addUiEntry)(tree, {
|
|
24
|
+
packageRoot: PACKAGE_ROOT,
|
|
25
|
+
entryName: className,
|
|
26
|
+
importPath: IMPORT_PATH,
|
|
27
|
+
});
|
|
28
|
+
if (!schema.skipFormat) {
|
|
29
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.default = uiComponentGenerator;
|
|
33
|
+
//# sourceMappingURL=ui-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-component.js","sourceRoot":"","sources":["../../../../src/generators/ui-component/ui-component.ts"],"names":[],"mappings":";;AAQA,oDA6BC;AArCD,uCAAkG;AAClG,+BAA4B;AAE5B,kEAA0D;AAE1D,MAAM,YAAY,GAAG,eAAe,CAAC;AACrC,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAEvC,KAAK,UAAU,oBAAoB,CACxC,IAAU,EACV,MAAkC;IAElC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,cAAK,EAAC,WAAW,CAAC,CAAC;IAEzC,0CAA0C;IAC1C,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,YAAY,MAAM,EAAE;QACnE,SAAS;QACT,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;QACrC,IAAI,EAAE,EAAE;KACT,CAAC,CAAC;IAEH,2EAA2E;IAC3E,IAAA,4BAAU,EAAC,IAAI,EAAE;QACf,WAAW,EAAE,YAAY;QACzB,SAAS,EAAE,SAAS;QACpB,UAAU,EAAE,WAAW;KACxB,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,kBAAe,oBAAoB,CAAC","sourcesContent":["import { type Tree, formatFiles, generateFiles, names, type GeneratorCallback } from '@nx/devkit';\nimport { join } from 'path';\nimport type { UiComponentGeneratorSchema } from './schema.js';\nimport { addUiEntry } from '../ui-shared/add-ui-entry.js';\n\nconst PACKAGE_ROOT = 'ui/components';\nconst IMPORT_PATH = '@frontmcp/ui-components';\n\nexport async function uiComponentGenerator(\n tree: Tree,\n schema: UiComponentGeneratorSchema,\n): Promise<GeneratorCallback | void> {\n const trimmedName = schema.name?.trim();\n if (!trimmedName) {\n throw new Error('Generator name must not be blank');\n }\n\n const { className } = names(trimmedName);\n\n // Generate component files from templates\n generateFiles(tree, join(__dirname, 'files'), `${PACKAGE_ROOT}/src`, {\n className,\n name: schema.name,\n description: schema.description ?? '',\n tmpl: '',\n });\n\n // Add entry point to project.json, tsconfig.base.json, and barrel index.ts\n addUiEntry(tree, {\n packageRoot: PACKAGE_ROOT,\n entryName: className,\n importPath: IMPORT_PATH,\n });\n\n if (!schema.skipFormat) {\n await formatFiles(tree);\n }\n}\n\nexport default uiComponentGenerator;\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { <%= className %> } from './<%= className %>';
|
|
3
|
+
|
|
4
|
+
describe('<%= className %>', () => {
|
|
5
|
+
it('should be defined', () => {
|
|
6
|
+
expect(<%= className %>).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('should be a function component', () => {
|
|
10
|
+
expect(typeof <%= className %>).toBe('function');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should render without crashing', () => {
|
|
14
|
+
const { container } = render(<<%= className %> />);
|
|
15
|
+
expect(container.firstChild).not.toBeNull();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Box, Typography } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
export interface <%= className %>Props {
|
|
4
|
+
title?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function <%= className %>({ title = '<%= className %>' }: <%= className %>Props) {
|
|
8
|
+
return (
|
|
9
|
+
<Box sx={{ p: 3 }}>
|
|
10
|
+
<Typography variant="h4">{title}</Typography>
|
|
11
|
+
<Typography variant="body1" sx={{ mt: 2 }}>
|
|
12
|
+
TODO: implement <%= className %>
|
|
13
|
+
</Typography>
|
|
14
|
+
</Box>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/generators/ui-page/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface UiPageGeneratorSchema {\n name: string;\n description?: string;\n skipFormat?: boolean;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "FrontMcpUiPage",
|
|
4
|
+
"title": "FrontMCP UI Page Generator",
|
|
5
|
+
"description": "Add a UI page entry to ui/pages",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"name": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Page name (PascalCase, e.g. AdminDashboard)",
|
|
11
|
+
"$default": { "$source": "argv", "index": 0 },
|
|
12
|
+
"x-prompt": "What name would you like for the page (PascalCase)?",
|
|
13
|
+
"x-priority": "important"
|
|
14
|
+
},
|
|
15
|
+
"description": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Brief description of the page",
|
|
18
|
+
"default": ""
|
|
19
|
+
},
|
|
20
|
+
"skipFormat": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": false,
|
|
23
|
+
"x-priority": "internal"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["name"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Tree, type GeneratorCallback } from '@nx/devkit';
|
|
2
|
+
import type { UiPageGeneratorSchema } from './schema.js';
|
|
3
|
+
export declare function uiPageGenerator(tree: Tree, schema: UiPageGeneratorSchema): Promise<GeneratorCallback | void>;
|
|
4
|
+
export default uiPageGenerator;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uiPageGenerator = uiPageGenerator;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const add_ui_entry_js_1 = require("../ui-shared/add-ui-entry.js");
|
|
7
|
+
const PACKAGE_ROOT = 'ui/pages';
|
|
8
|
+
const IMPORT_PATH = '@frontmcp/ui-pages';
|
|
9
|
+
async function uiPageGenerator(tree, schema) {
|
|
10
|
+
const trimmedName = schema.name?.trim();
|
|
11
|
+
if (!trimmedName) {
|
|
12
|
+
throw new Error('Generator name must not be blank');
|
|
13
|
+
}
|
|
14
|
+
const { className } = (0, devkit_1.names)(trimmedName);
|
|
15
|
+
// Generate page files from templates
|
|
16
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), `${PACKAGE_ROOT}/src`, {
|
|
17
|
+
className,
|
|
18
|
+
name: schema.name,
|
|
19
|
+
description: schema.description ?? '',
|
|
20
|
+
tmpl: '',
|
|
21
|
+
});
|
|
22
|
+
// Add entry point to project.json, tsconfig.base.json, and barrel index.ts
|
|
23
|
+
(0, add_ui_entry_js_1.addUiEntry)(tree, {
|
|
24
|
+
packageRoot: PACKAGE_ROOT,
|
|
25
|
+
entryName: className,
|
|
26
|
+
importPath: IMPORT_PATH,
|
|
27
|
+
});
|
|
28
|
+
if (!schema.skipFormat) {
|
|
29
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.default = uiPageGenerator;
|
|
33
|
+
//# sourceMappingURL=ui-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-page.js","sourceRoot":"","sources":["../../../../src/generators/ui-page/ui-page.ts"],"names":[],"mappings":";;AAQA,0CA0BC;AAlCD,uCAAkG;AAClG,+BAA4B;AAE5B,kEAA0D;AAE1D,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAElC,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,MAA6B;IAC7E,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,cAAK,EAAC,WAAW,CAAC,CAAC;IAEzC,qCAAqC;IACrC,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,YAAY,MAAM,EAAE;QACnE,SAAS;QACT,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;QACrC,IAAI,EAAE,EAAE;KACT,CAAC,CAAC;IAEH,2EAA2E;IAC3E,IAAA,4BAAU,EAAC,IAAI,EAAE;QACf,WAAW,EAAE,YAAY;QACzB,SAAS,EAAE,SAAS;QACpB,UAAU,EAAE,WAAW;KACxB,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,kBAAe,eAAe,CAAC","sourcesContent":["import { type Tree, formatFiles, generateFiles, names, type GeneratorCallback } from '@nx/devkit';\nimport { join } from 'path';\nimport type { UiPageGeneratorSchema } from './schema.js';\nimport { addUiEntry } from '../ui-shared/add-ui-entry.js';\n\nconst PACKAGE_ROOT = 'ui/pages';\nconst IMPORT_PATH = '@frontmcp/ui-pages';\n\nexport async function uiPageGenerator(tree: Tree, schema: UiPageGeneratorSchema): Promise<GeneratorCallback | void> {\n const trimmedName = schema.name?.trim();\n if (!trimmedName) {\n throw new Error('Generator name must not be blank');\n }\n\n const { className } = names(trimmedName);\n\n // Generate page files from templates\n generateFiles(tree, join(__dirname, 'files'), `${PACKAGE_ROOT}/src`, {\n className,\n name: schema.name,\n description: schema.description ?? '',\n tmpl: '',\n });\n\n // Add entry point to project.json, tsconfig.base.json, and barrel index.ts\n addUiEntry(tree, {\n packageRoot: PACKAGE_ROOT,\n entryName: className,\n importPath: IMPORT_PATH,\n });\n\n if (!schema.skipFormat) {\n await formatFiles(tree);\n }\n}\n\nexport default uiPageGenerator;\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
2
|
+
export interface AddUiEntryOptions {
|
|
3
|
+
/** The UI package root, e.g. 'ui/components' */
|
|
4
|
+
packageRoot: string;
|
|
5
|
+
/** The entry name, e.g. 'LoginForm' or 'admin-dashboard' */
|
|
6
|
+
entryName: string;
|
|
7
|
+
/** The npm scope name, e.g. '@frontmcp/ui-components' */
|
|
8
|
+
importPath: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adds an entry point to an existing UI package:
|
|
12
|
+
* 1. Updates project.json `additionalEntryPoints` in both build-cjs and build-esm
|
|
13
|
+
* 2. Updates tsconfig.base.json path aliases (wildcard already covers it, but explicit is fine)
|
|
14
|
+
* 3. Adds re-export to the barrel index.ts
|
|
15
|
+
*/
|
|
16
|
+
export declare function addUiEntry(tree: Tree, options: AddUiEntryOptions): void;
|