next2d-development-mcp 0.0.1
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/README.md +344 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +211 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/prompts.test.d.ts +2 -0
- package/dist/prompts/prompts.test.d.ts.map +1 -0
- package/dist/prompts/prompts.test.js +23 -0
- package/dist/prompts/prompts.test.js.map +1 -0
- package/dist/references/develop-specs.md +1576 -0
- package/dist/references/framework-specs.md +1687 -0
- package/dist/references/player-specs.md +3292 -0
- package/dist/resources/index.d.ts +3 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +185 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/resources.test.d.ts +2 -0
- package/dist/resources/resources.test.d.ts.map +1 -0
- package/dist/resources/resources.test.js +32 -0
- package/dist/resources/resources.test.js.map +1 -0
- package/dist/templates/animation.d.ts +6 -0
- package/dist/templates/animation.d.ts.map +1 -0
- package/dist/templates/animation.js +65 -0
- package/dist/templates/animation.js.map +1 -0
- package/dist/templates/animation.test.d.ts +2 -0
- package/dist/templates/animation.test.d.ts.map +1 -0
- package/dist/templates/animation.test.js +30 -0
- package/dist/templates/animation.test.js.map +1 -0
- package/dist/templates/domainService.d.ts +9 -0
- package/dist/templates/domainService.d.ts.map +1 -0
- package/dist/templates/domainService.js +56 -0
- package/dist/templates/domainService.js.map +1 -0
- package/dist/templates/domainService.test.d.ts +2 -0
- package/dist/templates/domainService.test.d.ts.map +1 -0
- package/dist/templates/domainService.test.js +33 -0
- package/dist/templates/domainService.test.js.map +1 -0
- package/dist/templates/interfaceFile.d.ts +5 -0
- package/dist/templates/interfaceFile.d.ts.map +1 -0
- package/dist/templates/interfaceFile.js +16 -0
- package/dist/templates/interfaceFile.js.map +1 -0
- package/dist/templates/interfaceFile.test.d.ts +2 -0
- package/dist/templates/interfaceFile.test.d.ts.map +1 -0
- package/dist/templates/interfaceFile.test.js +30 -0
- package/dist/templates/interfaceFile.test.js.map +1 -0
- package/dist/templates/loading.d.ts +5 -0
- package/dist/templates/loading.d.ts.map +1 -0
- package/dist/templates/loading.js +62 -0
- package/dist/templates/loading.js.map +1 -0
- package/dist/templates/loading.test.d.ts +2 -0
- package/dist/templates/loading.test.d.ts.map +1 -0
- package/dist/templates/loading.test.js +31 -0
- package/dist/templates/loading.test.js.map +1 -0
- package/dist/templates/repository.d.ts +2 -0
- package/dist/templates/repository.d.ts.map +1 -0
- package/dist/templates/repository.js +42 -0
- package/dist/templates/repository.js.map +1 -0
- package/dist/templates/repository.test.d.ts +2 -0
- package/dist/templates/repository.test.d.ts.map +1 -0
- package/dist/templates/repository.test.js +44 -0
- package/dist/templates/repository.test.js.map +1 -0
- package/dist/templates/uiComponent.d.ts +4 -0
- package/dist/templates/uiComponent.d.ts.map +1 -0
- package/dist/templates/uiComponent.js +108 -0
- package/dist/templates/uiComponent.js.map +1 -0
- package/dist/templates/uiComponent.test.d.ts +2 -0
- package/dist/templates/uiComponent.test.d.ts.map +1 -0
- package/dist/templates/uiComponent.test.js +76 -0
- package/dist/templates/uiComponent.test.js.map +1 -0
- package/dist/templates/usecase.d.ts +2 -0
- package/dist/templates/usecase.d.ts.map +1 -0
- package/dist/templates/usecase.js +31 -0
- package/dist/templates/usecase.js.map +1 -0
- package/dist/templates/usecase.test.d.ts +2 -0
- package/dist/templates/usecase.test.d.ts.map +1 -0
- package/dist/templates/usecase.test.js +23 -0
- package/dist/templates/usecase.test.js.map +1 -0
- package/dist/templates/view.d.ts +3 -0
- package/dist/templates/view.d.ts.map +1 -0
- package/dist/templates/view.js +112 -0
- package/dist/templates/view.js.map +1 -0
- package/dist/templates/view.test.d.ts +2 -0
- package/dist/templates/view.test.d.ts.map +1 -0
- package/dist/templates/view.test.js +71 -0
- package/dist/templates/view.test.js.map +1 -0
- package/dist/tools/addRoute.d.ts +3 -0
- package/dist/tools/addRoute.d.ts.map +1 -0
- package/dist/tools/addRoute.js +101 -0
- package/dist/tools/addRoute.js.map +1 -0
- package/dist/tools/createAnimation.d.ts +3 -0
- package/dist/tools/createAnimation.d.ts.map +1 -0
- package/dist/tools/createAnimation.js +53 -0
- package/dist/tools/createAnimation.js.map +1 -0
- package/dist/tools/createDomainService.d.ts +3 -0
- package/dist/tools/createDomainService.d.ts.map +1 -0
- package/dist/tools/createDomainService.js +82 -0
- package/dist/tools/createDomainService.js.map +1 -0
- package/dist/tools/createInterface.d.ts +3 -0
- package/dist/tools/createInterface.d.ts.map +1 -0
- package/dist/tools/createInterface.js +59 -0
- package/dist/tools/createInterface.js.map +1 -0
- package/dist/tools/createLoading.d.ts +3 -0
- package/dist/tools/createLoading.d.ts.map +1 -0
- package/dist/tools/createLoading.js +52 -0
- package/dist/tools/createLoading.js.map +1 -0
- package/dist/tools/createRepository.d.ts +3 -0
- package/dist/tools/createRepository.d.ts.map +1 -0
- package/dist/tools/createRepository.js +55 -0
- package/dist/tools/createRepository.js.map +1 -0
- package/dist/tools/createUiComponent.d.ts +3 -0
- package/dist/tools/createUiComponent.d.ts.map +1 -0
- package/dist/tools/createUiComponent.js +80 -0
- package/dist/tools/createUiComponent.js.map +1 -0
- package/dist/tools/createUseCase.d.ts +3 -0
- package/dist/tools/createUseCase.d.ts.map +1 -0
- package/dist/tools/createUseCase.js +52 -0
- package/dist/tools/createUseCase.js.map +1 -0
- package/dist/tools/createView.d.ts +3 -0
- package/dist/tools/createView.d.ts.map +1 -0
- package/dist/tools/createView.js +59 -0
- package/dist/tools/createView.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +25 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/tools.test.d.ts +2 -0
- package/dist/tools/tools.test.d.ts.map +1 -0
- package/dist/tools/tools.test.js +58 -0
- package/dist/tools/tools.test.js.map +1 -0
- package/dist/tools/validateArchitecture.d.ts +3 -0
- package/dist/tools/validateArchitecture.d.ts.map +1 -0
- package/dist/tools/validateArchitecture.js +134 -0
- package/dist/tools/validateArchitecture.js.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +18 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +34 -0
- package/dist/utils.test.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { generateUiComponent, generateContent } from "../templates/uiComponent.js";
|
|
3
|
+
import { toPascalCase } from "../utils.js";
|
|
4
|
+
export function registerCreateUiComponent(server) {
|
|
5
|
+
server.registerTool("create_ui_component", {
|
|
6
|
+
"description": "Create a new UI component following Atomic Design pattern. " +
|
|
7
|
+
"Levels: atom (smallest), molecule (composite), organism (complex), page (full screen). " +
|
|
8
|
+
"Located in src/ui/component/{level}/. " +
|
|
9
|
+
"Also supports creating Animation Tool content wrappers in src/ui/content/.",
|
|
10
|
+
"inputSchema": {
|
|
11
|
+
"name": z.string().describe("Component name (e.g. 'Button', 'HomeBtn', 'QuestCard')"),
|
|
12
|
+
"level": z.enum(["atom", "molecule", "organism", "page", "content"]).describe("Atomic Design level: atom, molecule, organism, page, or 'content' for Animation Tool wrapper"),
|
|
13
|
+
"parentClass": z.string().optional().default("Sprite").describe("Parent DisplayObject class (default: 'Sprite'). Options: Sprite, MovieClip, Shape, TextField"),
|
|
14
|
+
"screen": z.string().optional().describe("Screen name for page-level components (e.g. 'top', 'home', 'quest'). " +
|
|
15
|
+
"Determines the subdirectory under page/. Required for page level.")
|
|
16
|
+
}
|
|
17
|
+
}, async ({ name, level, parentClass, screen }) => {
|
|
18
|
+
const pascal = toPascalCase(name);
|
|
19
|
+
if (level === "content") {
|
|
20
|
+
const contentName = pascal.endsWith("Content") ? pascal : `${pascal}Content`;
|
|
21
|
+
const filePath = `src/ui/content/${contentName}.ts`;
|
|
22
|
+
const code = generateContent(name.replace("Content", ""));
|
|
23
|
+
return {
|
|
24
|
+
"content": [
|
|
25
|
+
{
|
|
26
|
+
"type": "text",
|
|
27
|
+
"text": [
|
|
28
|
+
`## Generated Content: ${contentName}`,
|
|
29
|
+
"",
|
|
30
|
+
`### File: ${filePath}`,
|
|
31
|
+
"```typescript",
|
|
32
|
+
code.trim(),
|
|
33
|
+
"```",
|
|
34
|
+
"",
|
|
35
|
+
"### Usage",
|
|
36
|
+
"- Content wraps Animation Tool (.n2d) assets",
|
|
37
|
+
"- Set `namespace` to match the symbol name in the .n2d file",
|
|
38
|
+
"- Load via routing.json with `type: \"content\"`"
|
|
39
|
+
].join("\n")
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const suffix = level.charAt(0).toUpperCase() + level.slice(1);
|
|
45
|
+
const className = pascal.endsWith(suffix) ? pascal : `${pascal}${suffix}`;
|
|
46
|
+
// Page components are organized by screen subdirectory
|
|
47
|
+
const screenDir = level === "page"
|
|
48
|
+
? (screen || name.toLowerCase())
|
|
49
|
+
: "";
|
|
50
|
+
const filePath = level === "page"
|
|
51
|
+
? `src/ui/component/page/${screenDir}/${className}.ts`
|
|
52
|
+
: `src/ui/component/${level}/${className}.ts`;
|
|
53
|
+
const code = generateUiComponent(name.endsWith(suffix) ? name.replace(new RegExp(`${suffix}$`), "") : name, level, parentClass, screenDir);
|
|
54
|
+
return {
|
|
55
|
+
"content": [
|
|
56
|
+
{
|
|
57
|
+
"type": "text",
|
|
58
|
+
"text": [
|
|
59
|
+
`## Generated ${suffix} Component: ${className}`,
|
|
60
|
+
"",
|
|
61
|
+
`### File: ${filePath}`,
|
|
62
|
+
"```typescript",
|
|
63
|
+
code.trim(),
|
|
64
|
+
"```",
|
|
65
|
+
"",
|
|
66
|
+
`### Atomic Design - ${suffix} Level`,
|
|
67
|
+
level === "atom"
|
|
68
|
+
? "- Smallest reusable unit (Button, Text, Icon)"
|
|
69
|
+
: level === "molecule"
|
|
70
|
+
? "- Combination of Atoms (e.g. TopBtnMolecule extends ButtonAtom with TextAtom child)"
|
|
71
|
+
: level === "organism"
|
|
72
|
+
? "- Complex component with business logic connections"
|
|
73
|
+
: "- Full screen layout, used directly in View"
|
|
74
|
+
].join("\n")
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=createUiComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createUiComponent.js","sourceRoot":"","sources":["../../src/tools/createUiComponent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createUseCase.d.ts","sourceRoot":"","sources":["../../src/tools/createUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4D7D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { generateUseCase } from "../templates/usecase.js";
|
|
3
|
+
import { toPascalCase } from "../utils.js";
|
|
4
|
+
export function registerCreateUseCase(server) {
|
|
5
|
+
server.registerTool("create_usecase", {
|
|
6
|
+
"description": "Create a new UseCase class in the Application layer. " +
|
|
7
|
+
"Each UseCase represents a single user action with an execute() method. " +
|
|
8
|
+
"Located in src/model/application/{screen}/usecase/.",
|
|
9
|
+
"inputSchema": {
|
|
10
|
+
"name": z.string().describe("UseCase name (e.g. 'StartDrag', 'NavigateToView', 'FetchUserData')"),
|
|
11
|
+
"screen": z.string().describe("Screen/view name this UseCase belongs to (e.g. 'home', 'top')")
|
|
12
|
+
}
|
|
13
|
+
}, async ({ name, screen }) => {
|
|
14
|
+
const pascal = toPascalCase(name);
|
|
15
|
+
const useCaseName = pascal.endsWith("UseCase") ? pascal : `${pascal}UseCase`;
|
|
16
|
+
const filePath = `src/model/application/${screen.toLowerCase()}/usecase/${useCaseName}.ts`;
|
|
17
|
+
const code = generateUseCase(name.endsWith("UseCase") ? name : `${name}UseCase`, screen);
|
|
18
|
+
return {
|
|
19
|
+
"content": [
|
|
20
|
+
{
|
|
21
|
+
"type": "text",
|
|
22
|
+
"text": [
|
|
23
|
+
`## Generated UseCase: ${useCaseName}`,
|
|
24
|
+
"",
|
|
25
|
+
`### File: ${filePath}`,
|
|
26
|
+
"```typescript",
|
|
27
|
+
code.trim(),
|
|
28
|
+
"```",
|
|
29
|
+
"",
|
|
30
|
+
"### Usage in ViewModel",
|
|
31
|
+
"```typescript",
|
|
32
|
+
`import { ${useCaseName} } from "@/model/application/${screen.toLowerCase()}/usecase/${useCaseName}";`,
|
|
33
|
+
"",
|
|
34
|
+
`private readonly ${useCaseName.charAt(0).toLowerCase() + useCaseName.slice(1)}: ${useCaseName};`,
|
|
35
|
+
"",
|
|
36
|
+
"constructor () {",
|
|
37
|
+
" super();",
|
|
38
|
+
` this.${useCaseName.charAt(0).toLowerCase() + useCaseName.slice(1)} = new ${useCaseName}();`,
|
|
39
|
+
"}",
|
|
40
|
+
"```",
|
|
41
|
+
"",
|
|
42
|
+
"### Rules",
|
|
43
|
+
"- 1 action = 1 UseCase (single responsibility)",
|
|
44
|
+
"- Entry point is always `execute()` method",
|
|
45
|
+
"- Depend on interfaces, not concrete classes"
|
|
46
|
+
].join("\n")
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=createUseCase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createUseCase.js","sourceRoot":"","sources":["../../src/tools/createUseCase.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACf,gBAAgB,EAChB;QACI,aAAa,EACT,uDAAuD;YACvD,yEAAyE;YACzE,qDAAqD;QACzD,aAAa,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACvB,oEAAoE,CACvE;YACD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACzB,+DAA+D,CAClE;SACJ;KACJ,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,SAAS,CAAC;QAC7E,MAAM,QAAQ,GAAG,yBAAyB,MAAM,CAAC,WAAW,EAAE,YAAY,WAAW,KAAK,CAAC;QAC3F,MAAM,IAAI,GAAG,eAAe,CACxB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,EAClD,MAAM,CACT,CAAC;QAEF,OAAO;YACH,SAAS,EAAE;gBACP;oBACI,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE;wBACJ,yBAAyB,WAAW,EAAE;wBACtC,EAAE;wBACF,aAAa,QAAQ,EAAE;wBACvB,eAAe;wBACf,IAAI,CAAC,IAAI,EAAE;wBACX,KAAK;wBACL,EAAE;wBACF,wBAAwB;wBACxB,eAAe;wBACf,YAAY,WAAW,gCAAgC,MAAM,CAAC,WAAW,EAAE,YAAY,WAAW,IAAI;wBACtG,EAAE;wBACF,oBAAoB,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,WAAW,GAAG;wBACjG,EAAE;wBACF,kBAAkB;wBAClB,cAAc;wBACd,YAAY,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,WAAW,KAAK;wBAChG,GAAG;wBACH,KAAK;wBACL,EAAE;wBACF,WAAW;wBACX,gDAAgD;wBAChD,4CAA4C;wBAC5C,8CAA8C;qBACjD,CAAC,IAAI,CAAC,IAAI,CAAC;iBACf;aACJ;SACJ,CAAC;IACN,CAAC,CACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createView.d.ts","sourceRoot":"","sources":["../../src/tools/createView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D1D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { generateView, generateViewModel } from "../templates/view.js";
|
|
3
|
+
import { toPascalCase } from "../utils.js";
|
|
4
|
+
export function registerCreateView(server) {
|
|
5
|
+
server.registerTool("create_view", {
|
|
6
|
+
"description": "Create a new View and ViewModel pair following MVVM pattern. " +
|
|
7
|
+
"Generates {Name}View.ts and {Name}ViewModel.ts in src/view/{name}/. " +
|
|
8
|
+
"View extends Sprite and manages UI display. ViewModel handles business logic via UseCases.",
|
|
9
|
+
"inputSchema": {
|
|
10
|
+
"name": z.string().describe("View name (e.g. 'home', 'quest/list'). " +
|
|
11
|
+
"Slash-separated names create nested paths and PascalCase class names.")
|
|
12
|
+
}
|
|
13
|
+
}, async ({ name }) => {
|
|
14
|
+
const pascal = toPascalCase(name);
|
|
15
|
+
// Screen directory is the first segment for slash-separated routes
|
|
16
|
+
const screenDir = name.includes("/") ? name.split("/")[0].toLowerCase() : name.toLowerCase();
|
|
17
|
+
const dirPath = `src/view/${screenDir}`;
|
|
18
|
+
const viewCode = generateView(name);
|
|
19
|
+
const viewModelCode = generateViewModel(name);
|
|
20
|
+
return {
|
|
21
|
+
"content": [
|
|
22
|
+
{
|
|
23
|
+
"type": "text",
|
|
24
|
+
"text": [
|
|
25
|
+
`## Generated View/ViewModel: ${pascal}`,
|
|
26
|
+
"",
|
|
27
|
+
`### File: ${dirPath}/${pascal}View.ts`,
|
|
28
|
+
"```typescript",
|
|
29
|
+
viewCode.trim(),
|
|
30
|
+
"```",
|
|
31
|
+
"",
|
|
32
|
+
`### File: ${dirPath}/${pascal}ViewModel.ts`,
|
|
33
|
+
"```typescript",
|
|
34
|
+
viewModelCode.trim(),
|
|
35
|
+
"```",
|
|
36
|
+
"",
|
|
37
|
+
"### Next Steps",
|
|
38
|
+
`1. Create directory: \`${dirPath}/\``,
|
|
39
|
+
"2. Save the above files",
|
|
40
|
+
"3. Add route to `src/config/routing.json`:",
|
|
41
|
+
"```json",
|
|
42
|
+
`"${name.toLowerCase()}": {`,
|
|
43
|
+
" \"requests\": []",
|
|
44
|
+
"}",
|
|
45
|
+
"```",
|
|
46
|
+
"4. Register in `src/Packages.ts`:",
|
|
47
|
+
"```typescript",
|
|
48
|
+
`import { ${pascal}View } from "@/view/${screenDir}/${pascal}View";`,
|
|
49
|
+
`import { ${pascal}ViewModel } from "@/view/${screenDir}/${pascal}ViewModel";`,
|
|
50
|
+
"```",
|
|
51
|
+
`5. Update \`src/interface/IViewName.ts\` (add "${name.toLowerCase()}" to ViewName union type)`,
|
|
52
|
+
"6. Add UI components (Page/Molecule/Atom) in `src/ui/`"
|
|
53
|
+
].join("\n")
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=createView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createView.js","sourceRoot":"","sources":["../../src/tools/createView.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAChD,MAAM,CAAC,YAAY,CACf,aAAa,EACb;QACI,aAAa,EACT,+DAA+D;YAC/D,sEAAsE;YACtE,4FAA4F;QAChG,aAAa,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACvB,yCAAyC;gBACzC,uEAAuE,CAC1E;SACJ;KACJ,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAClC,mEAAmE;QACnE,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7F,MAAM,OAAO,GAAG,YAAY,SAAS,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,aAAa,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAE9C,OAAO;YACH,SAAS,EAAE;gBACP;oBACI,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE;wBACJ,gCAAgC,MAAM,EAAE;wBACxC,EAAE;wBACF,aAAa,OAAO,IAAI,MAAM,SAAS;wBACvC,eAAe;wBACf,QAAQ,CAAC,IAAI,EAAE;wBACf,KAAK;wBACL,EAAE;wBACF,aAAa,OAAO,IAAI,MAAM,cAAc;wBAC5C,eAAe;wBACf,aAAa,CAAC,IAAI,EAAE;wBACpB,KAAK;wBACL,EAAE;wBACF,gBAAgB;wBAChB,0BAA0B,OAAO,KAAK;wBACtC,yBAAyB;wBACzB,4CAA4C;wBAC5C,SAAS;wBACT,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM;wBAC5B,sBAAsB;wBACtB,GAAG;wBACH,KAAK;wBACL,mCAAmC;wBACnC,eAAe;wBACf,YAAY,MAAM,uBAAuB,SAAS,IAAI,MAAM,QAAQ;wBACpE,YAAY,MAAM,4BAA4B,SAAS,IAAI,MAAM,aAAa;wBAC9E,KAAK;wBACL,kDAAkD,IAAI,CAAC,WAAW,EAAE,2BAA2B;wBAC/F,wDAAwD;qBAC3D,CAAC,IAAI,CAAC,IAAI,CAAC;iBACf;aACJ;SACJ,CAAC;IACN,CAAC,CACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,OAAO,EAAE,CAAC,EAAE,CAAC;AAEb,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAWrD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { registerCreateView } from "./createView.js";
|
|
3
|
+
import { registerCreateUseCase } from "./createUseCase.js";
|
|
4
|
+
import { registerCreateRepository } from "./createRepository.js";
|
|
5
|
+
import { registerCreateUiComponent } from "./createUiComponent.js";
|
|
6
|
+
import { registerAddRoute } from "./addRoute.js";
|
|
7
|
+
import { registerCreateInterface } from "./createInterface.js";
|
|
8
|
+
import { registerValidateArchitecture } from "./validateArchitecture.js";
|
|
9
|
+
import { registerCreateAnimation } from "./createAnimation.js";
|
|
10
|
+
import { registerCreateDomainService } from "./createDomainService.js";
|
|
11
|
+
import { registerCreateLoading } from "./createLoading.js";
|
|
12
|
+
export { z };
|
|
13
|
+
export function registerTools(server) {
|
|
14
|
+
registerCreateView(server);
|
|
15
|
+
registerCreateUseCase(server);
|
|
16
|
+
registerCreateRepository(server);
|
|
17
|
+
registerCreateUiComponent(server);
|
|
18
|
+
registerAddRoute(server);
|
|
19
|
+
registerCreateInterface(server);
|
|
20
|
+
registerValidateArchitecture(server);
|
|
21
|
+
registerCreateAnimation(server);
|
|
22
|
+
registerCreateDomainService(server);
|
|
23
|
+
registerCreateLoading(server);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,CAAC;AAEb,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC3C,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.d.ts","sourceRoot":"","sources":["../../src/tools/tools.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { registerCreateView } from "./createView.js";
|
|
4
|
+
import { registerCreateUseCase } from "./createUseCase.js";
|
|
5
|
+
import { registerCreateRepository } from "./createRepository.js";
|
|
6
|
+
import { registerCreateUiComponent } from "./createUiComponent.js";
|
|
7
|
+
import { registerAddRoute } from "./addRoute.js";
|
|
8
|
+
import { registerCreateInterface } from "./createInterface.js";
|
|
9
|
+
import { registerCreateAnimation } from "./createAnimation.js";
|
|
10
|
+
import { registerCreateDomainService } from "./createDomainService.js";
|
|
11
|
+
import { registerTools } from "./index.js";
|
|
12
|
+
describe("Tool registration", () => {
|
|
13
|
+
let server;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
server = new McpServer({ name: "test", version: "0.0.1" });
|
|
16
|
+
});
|
|
17
|
+
it("registerCreateView registers without error", () => {
|
|
18
|
+
expect(() => registerCreateView(server)).not.toThrow();
|
|
19
|
+
});
|
|
20
|
+
it("registerCreateUseCase registers without error", () => {
|
|
21
|
+
expect(() => registerCreateUseCase(server)).not.toThrow();
|
|
22
|
+
});
|
|
23
|
+
it("registerCreateRepository registers without error", () => {
|
|
24
|
+
expect(() => registerCreateRepository(server)).not.toThrow();
|
|
25
|
+
});
|
|
26
|
+
it("registerCreateUiComponent registers without error", () => {
|
|
27
|
+
expect(() => registerCreateUiComponent(server)).not.toThrow();
|
|
28
|
+
});
|
|
29
|
+
it("registerAddRoute registers without error", () => {
|
|
30
|
+
expect(() => registerAddRoute(server)).not.toThrow();
|
|
31
|
+
});
|
|
32
|
+
it("registerCreateInterface registers without error", () => {
|
|
33
|
+
expect(() => registerCreateInterface(server)).not.toThrow();
|
|
34
|
+
});
|
|
35
|
+
it("registerCreateAnimation registers without error", () => {
|
|
36
|
+
expect(() => registerCreateAnimation(server)).not.toThrow();
|
|
37
|
+
});
|
|
38
|
+
it("registerCreateDomainService registers without error", () => {
|
|
39
|
+
expect(() => registerCreateDomainService(server)).not.toThrow();
|
|
40
|
+
});
|
|
41
|
+
it("registerTools registers all 10 tools", () => {
|
|
42
|
+
const spy = vi.spyOn(server, "registerTool");
|
|
43
|
+
registerTools(server);
|
|
44
|
+
expect(spy).toHaveBeenCalledTimes(10);
|
|
45
|
+
const toolNames = spy.mock.calls.map((call) => call[0]);
|
|
46
|
+
expect(toolNames).toContain("create_view");
|
|
47
|
+
expect(toolNames).toContain("create_usecase");
|
|
48
|
+
expect(toolNames).toContain("create_repository");
|
|
49
|
+
expect(toolNames).toContain("create_ui_component");
|
|
50
|
+
expect(toolNames).toContain("add_route");
|
|
51
|
+
expect(toolNames).toContain("create_interface");
|
|
52
|
+
expect(toolNames).toContain("validate_architecture");
|
|
53
|
+
expect(toolNames).toContain("create_animation");
|
|
54
|
+
expect(toolNames).toContain("create_domain_service");
|
|
55
|
+
expect(toolNames).toContain("create_loading");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../src/tools/tools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateArchitecture.d.ts","sourceRoot":"","sources":["../../src/tools/validateArchitecture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAezE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyIpE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
function checkDir(base, dir) {
|
|
5
|
+
const full = path.join(base, dir);
|
|
6
|
+
return { "exists": fs.existsSync(full), "path": full };
|
|
7
|
+
}
|
|
8
|
+
function checkFile(base, file) {
|
|
9
|
+
const full = path.join(base, file);
|
|
10
|
+
return { "exists": fs.existsSync(full), "path": full };
|
|
11
|
+
}
|
|
12
|
+
export function registerValidateArchitecture(server) {
|
|
13
|
+
server.registerTool("validate_architecture", {
|
|
14
|
+
"description": "Validate that a Next2D project follows the expected architecture. " +
|
|
15
|
+
"Checks directory structure, config files, and naming conventions. " +
|
|
16
|
+
"Reports missing directories, files, and architecture violations.",
|
|
17
|
+
"inputSchema": {
|
|
18
|
+
"projectPath": z.string().optional().default(".").describe("Path to the project root directory (default: current directory)")
|
|
19
|
+
}
|
|
20
|
+
}, async ({ projectPath }) => {
|
|
21
|
+
const base = path.resolve(projectPath);
|
|
22
|
+
const issues = [];
|
|
23
|
+
const ok = [];
|
|
24
|
+
// Check required directories
|
|
25
|
+
const requiredDirs = [
|
|
26
|
+
"src/config",
|
|
27
|
+
"src/interface",
|
|
28
|
+
"src/model",
|
|
29
|
+
"src/model/application",
|
|
30
|
+
"src/model/domain",
|
|
31
|
+
"src/model/infrastructure",
|
|
32
|
+
"src/model/infrastructure/repository",
|
|
33
|
+
"src/ui",
|
|
34
|
+
"src/ui/animation",
|
|
35
|
+
"src/ui/component",
|
|
36
|
+
"src/ui/component/atom",
|
|
37
|
+
"src/ui/component/molecule",
|
|
38
|
+
"src/ui/component/page",
|
|
39
|
+
"src/ui/content",
|
|
40
|
+
"src/view"
|
|
41
|
+
];
|
|
42
|
+
for (const dir of requiredDirs) {
|
|
43
|
+
const check = checkDir(base, dir);
|
|
44
|
+
if (check.exists) {
|
|
45
|
+
ok.push(`β
${dir}/`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
issues.push(`β Missing directory: ${dir}/`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Check required config files
|
|
52
|
+
const requiredFiles = [
|
|
53
|
+
"src/config/config.json",
|
|
54
|
+
"src/config/routing.json",
|
|
55
|
+
"src/config/stage.json",
|
|
56
|
+
"src/config/Config.ts",
|
|
57
|
+
"src/Packages.ts",
|
|
58
|
+
"src/index.ts"
|
|
59
|
+
];
|
|
60
|
+
for (const file of requiredFiles) {
|
|
61
|
+
const check = checkFile(base, file);
|
|
62
|
+
if (check.exists) {
|
|
63
|
+
ok.push(`β
${file}`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
issues.push(`β Missing file: ${file}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Validate routing.json <-> view directory consistency
|
|
70
|
+
const routingPath = path.join(base, "src/config/routing.json");
|
|
71
|
+
if (fs.existsSync(routingPath)) {
|
|
72
|
+
try {
|
|
73
|
+
const routing = JSON.parse(fs.readFileSync(routingPath, "utf-8"));
|
|
74
|
+
for (const key of Object.keys(routing)) {
|
|
75
|
+
if (key.startsWith("@")) {
|
|
76
|
+
continue;
|
|
77
|
+
} // Skip cluster definitions
|
|
78
|
+
// View directory uses the first segment for slash routes (e.g. "quest/list" β "quest")
|
|
79
|
+
const screenDir = key.includes("/") ? key.split("/")[0].toLowerCase() : key.toLowerCase();
|
|
80
|
+
const viewDir = path.join(base, "src/view", screenDir);
|
|
81
|
+
if (fs.existsSync(viewDir)) {
|
|
82
|
+
ok.push(`β
View directory for route '${key}'`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
issues.push(`β οΈ Route '${key}' defined in routing.json but missing view directory: src/view/${screenDir}/`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
issues.push("β routing.json is not valid JSON");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Check stage.json validity
|
|
94
|
+
const stagePath = path.join(base, "src/config/stage.json");
|
|
95
|
+
if (fs.existsSync(stagePath)) {
|
|
96
|
+
try {
|
|
97
|
+
const stage = JSON.parse(fs.readFileSync(stagePath, "utf-8"));
|
|
98
|
+
if (!stage.width || !stage.height || !stage.fps) {
|
|
99
|
+
issues.push("β οΈ stage.json missing required fields: width, height, fps");
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
ok.push(`β
stage.json valid (${stage.width}x${stage.height} @${stage.fps}fps)`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
issues.push("β stage.json is not valid JSON");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const summary = issues.length === 0
|
|
110
|
+
? "π Architecture validation passed! No issues found."
|
|
111
|
+
: `β οΈ Found ${issues.length} issue(s).`;
|
|
112
|
+
return {
|
|
113
|
+
"content": [
|
|
114
|
+
{
|
|
115
|
+
"type": "text",
|
|
116
|
+
"text": [
|
|
117
|
+
"## Architecture Validation Report",
|
|
118
|
+
"",
|
|
119
|
+
`### Project: ${base}`,
|
|
120
|
+
"",
|
|
121
|
+
summary,
|
|
122
|
+
"",
|
|
123
|
+
issues.length > 0 ? "### Issues" : "",
|
|
124
|
+
...issues,
|
|
125
|
+
"",
|
|
126
|
+
"### Passed Checks",
|
|
127
|
+
...ok
|
|
128
|
+
].join("\n")
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=validateArchitecture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateArchitecture.js","sourceRoot":"","sources":["../../src/tools/validateArchitecture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAW;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAiB;IAC1D,MAAM,CAAC,YAAY,CACf,uBAAuB,EACvB;QACI,aAAa,EACT,oEAAoE;YACpE,oEAAoE;YACpE,kEAAkE;QACtE,aAAa,EAAE;YACX,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CACtD,iEAAiE,CACpE;SACJ;KACJ,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAa,EAAE,CAAC;QAExB,6BAA6B;QAC7B,MAAM,YAAY,GAAG;YACjB,YAAY;YACZ,eAAe;YACf,WAAW;YACX,uBAAuB;YACvB,kBAAkB;YAClB,0BAA0B;YAC1B,qCAAqC;YACrC,QAAQ;YACR,kBAAkB;YAClB,kBAAkB;YAClB,uBAAuB;YACvB,2BAA2B;YAC3B,uBAAuB;YACvB,gBAAgB;YAChB,UAAU;SACb,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACf,EAAE,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,IAAI,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;YAChD,CAAC;QACL,CAAC;QAED,8BAA8B;QAC9B,MAAM,aAAa,GAAG;YAClB,wBAAwB;YACxB,yBAAyB;YACzB,uBAAuB;YACvB,sBAAsB;YACtB,iBAAiB;YACjB,cAAc;SACjB,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACf,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;YAC3C,CAAC;QACL,CAAC;QAED,uDAAuD;QACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACtB,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CACxC,CAAC;gBAEF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;wBAAC,SAAQ;oBAAC,CAAC,CAAC,2BAA2B;oBACjE,uFAAuF;oBACvF,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;oBACvD,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;wBACzB,EAAE,CAAC,IAAI,CAAC,+BAA+B,GAAG,GAAG,CAAC,CAAC;oBACnD,CAAC;yBAAM,CAAC;wBACJ,MAAM,CAAC,IAAI,CACP,aAAa,GAAG,kEAAkE,SAAS,GAAG,CACjG,CAAC;oBACN,CAAC;gBACL,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACL,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;YACpD,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACpB,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CACtC,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;oBAC9C,MAAM,CAAC,IAAI,CACP,2DAA2D,CAC9D,CAAC;gBACN,CAAC;qBAAM,CAAC;oBACJ,EAAE,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;gBACpF,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACL,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;YAClD,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;YAC/B,CAAC,CAAC,qDAAqD;YACvD,CAAC,CAAC,YAAY,MAAM,CAAC,MAAM,YAAY,CAAC;QAE5C,OAAO;YACH,SAAS,EAAE;gBACP;oBACI,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE;wBACJ,mCAAmC;wBACnC,EAAE;wBACF,gBAAgB,IAAI,EAAE;wBACtB,EAAE;wBACF,OAAO;wBACP,EAAE;wBACF,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;wBACrC,GAAG,MAAM;wBACT,EAAE;wBACF,mBAAmB;wBACnB,GAAG,EAAE;qBACR,CAAC,IAAI,CAAC,IAAI,CAAC;iBACf;aACJ;SACJ,CAAC;IACN,CAAC,CACJ,CAAC;AACN,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PascalCase γ«ε€ζ (γΉγ©γγ·γ₯εΊεγγε―ΎεΏ)
|
|
3
|
+
* "quest/list" -> "QuestList"
|
|
4
|
+
*/
|
|
5
|
+
export declare function toPascalCase(str: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* camelCase γ«ε€ζ
|
|
8
|
+
*/
|
|
9
|
+
export declare function toCamelCase(str: string): string;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PascalCase γ«ε€ζ (γΉγ©γγ·γ₯εΊεγγε―ΎεΏ)
|
|
3
|
+
* "quest/list" -> "QuestList"
|
|
4
|
+
*/
|
|
5
|
+
export function toPascalCase(str) {
|
|
6
|
+
return str
|
|
7
|
+
.split(/[\\/]/)
|
|
8
|
+
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
9
|
+
.join("");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* camelCase γ«ε€ζ
|
|
13
|
+
*/
|
|
14
|
+
export function toCamelCase(str) {
|
|
15
|
+
const pascal = toPascalCase(str);
|
|
16
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACpC,OAAO,GAAG;SACL,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { toPascalCase, toCamelCase } from "./utils.js";
|
|
3
|
+
describe("toPascalCase", () => {
|
|
4
|
+
it("converts simple name", () => {
|
|
5
|
+
expect(toPascalCase("home")).toBe("Home");
|
|
6
|
+
});
|
|
7
|
+
it("converts slash-separated name", () => {
|
|
8
|
+
expect(toPascalCase("quest/list")).toBe("QuestList");
|
|
9
|
+
});
|
|
10
|
+
it("converts backslash-separated name", () => {
|
|
11
|
+
expect(toPascalCase("quest\\detail")).toBe("QuestDetail");
|
|
12
|
+
});
|
|
13
|
+
it("handles already PascalCase", () => {
|
|
14
|
+
expect(toPascalCase("Home")).toBe("Home");
|
|
15
|
+
});
|
|
16
|
+
it("handles multi-segment path", () => {
|
|
17
|
+
expect(toPascalCase("user/profile/edit")).toBe("UserProfileEdit");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe("toCamelCase", () => {
|
|
21
|
+
it("converts simple name", () => {
|
|
22
|
+
expect(toCamelCase("home")).toBe("home");
|
|
23
|
+
});
|
|
24
|
+
it("converts slash-separated name", () => {
|
|
25
|
+
expect(toCamelCase("quest/list")).toBe("questList");
|
|
26
|
+
});
|
|
27
|
+
it("handles already camelCase", () => {
|
|
28
|
+
expect(toCamelCase("home")).toBe("home");
|
|
29
|
+
});
|
|
30
|
+
it("lowercases first char of PascalCase input", () => {
|
|
31
|
+
expect(toCamelCase("Home")).toBe("home");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|