netcore-blueprint 0.0.29 → 0.0.31

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.
Files changed (2) hide show
  1. package/bin/copy-module.js +136 -78
  2. package/package.json +1 -1
@@ -2,111 +2,169 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { buildReplaceMap, applyReplacements } = require('../lib/replacer');
6
-
7
- // =======================
8
- // Args
9
- // =======================
10
- // Usage:
11
- // create-module <NewModuleName> <NewEntityName>
12
- // Example:
13
- // create-module AiAssistant Prompt
14
- // =======================
15
-
16
- const newModuleName = process.argv[2];
17
- const newEntityName = process.argv[3];
18
-
19
- if (!newModuleName || !newEntityName) {
20
- console.error("❌ Usage: create-module <NewModuleName> <NewEntityName>");
21
- console.error(" Example: create-module AiAssistant Prompt");
22
- process.exit(1);
23
- }
5
+ const { execSync } = require('child_process');
24
6
 
25
- // =======================
26
- // Template Source (Module mẫu)
27
- // =======================
7
+ // =====================================================
8
+ // Param = Source Module Name
9
+ // Example: copy-module __MODULE__
10
+ // Will create: Modules\__MODULE__Module\*
11
+ // =====================================================
28
12
 
29
- const sourceModuleName = "ItemModule"; // module mẫu
30
- const sourceEntityName = "Item"; // entity mẫu
13
+ const sourceModuleName = process.argv[2];
14
+ const force = process.argv.includes('--force');
31
15
 
32
- const modulesTemplateRoot = path.join(__dirname, "..", "Modules");
33
- const sourceModulePath = path.join(modulesTemplateRoot, sourceModuleName);
16
+ if (!sourceModuleName) {
17
+ console.error("❌ Usage: copy-module <SourceModuleName>");
18
+ console.error(" Example: copy-module __MODULE__");
19
+ process.exit(1);
20
+ }
34
21
 
35
- // =======================
36
- // Destination (nơi user đang đứng)
37
- // =======================
22
+ // Assume current working directory is Modules/
23
+ const modulesPath = process.cwd();
38
24
 
39
- const destinationRoot = process.cwd(); // thường là thư mục Modules
40
- const destinationModulePath = path.join(destinationRoot, newModuleName);
25
+ const templateRoot = path.join(modulesPath, sourceModuleName);
26
+ const targetModuleName = `${sourceModuleName}Module`;
27
+ const targetModuleRoot = path.join(modulesPath, targetModuleName);
41
28
 
42
- // =======================
43
- // Guards
44
- // =======================
29
+ const solutionFile = findSolutionFileUpwards(modulesPath);
45
30
 
46
- if (!fs.existsSync(sourceModulePath)) {
47
- console.error(`❌ Source module template not found: ${sourceModulePath}`);
31
+ if (!fs.existsSync(templateRoot)) {
32
+ console.error(`❌ Source module folder not found: ${templateRoot}`);
48
33
  process.exit(1);
49
34
  }
50
35
 
51
- if (fs.existsSync(destinationModulePath)) {
52
- console.error(`❌ Destination module already exists: ${destinationModulePath}`);
36
+ if (fs.existsSync(targetModuleRoot)) {
37
+ if (!force) {
38
+ console.error(`❌ Target module already exists: ${targetModuleRoot}`);
39
+ console.error(` Use --force to overwrite.`);
40
+ process.exit(1);
41
+ }
42
+
43
+ console.log(`🔥 --force detected. Removing existing module: ${targetModuleRoot}`);
44
+ fs.rmSync(targetModuleRoot, { recursive: true, force: true });
45
+ }
46
+
47
+ if (!solutionFile) {
48
+ console.error("❌ Could not find .sln or .slnx file.");
53
49
  process.exit(1);
54
50
  }
55
51
 
56
- // =======================
57
- // Replace Map
58
- // =======================
52
+ console.log(`🚀 Cloning module template:`);
53
+ console.log(` From: ${templateRoot}`);
54
+ console.log(` To: ${targetModuleRoot}`);
55
+ console.log(`🧩 Solution: ${solutionFile}`);
59
56
 
60
- const replaceMap = buildReplaceMap({
61
- sourceModuleName,
62
- newModuleName,
63
- sourceEntityName,
64
- newEntityName
65
- });
57
+ // =====================================================
58
+ // 1. Create module root folder
59
+ // =====================================================
60
+
61
+ fs.mkdirSync(targetModuleRoot, { recursive: true });
62
+
63
+ // =====================================================
64
+ // 2. Create projects (ALL classlib)
65
+ // =====================================================
66
+
67
+ const projects = [
68
+ { name: `${targetModuleName}.API`, type: 'classlib' },
69
+ { name: `${targetModuleName}.Core`, type: 'classlib' },
70
+ { name: `${targetModuleName}.Infrastructure`, type: 'classlib' },
71
+ ];
72
+
73
+ projects.forEach(p => {
74
+ console.log(`📦 Creating project: ${p.name}`);
75
+
76
+ execSync(`dotnet new ${p.type} -n ${p.name}`, {
77
+ cwd: targetModuleRoot,
78
+ stdio: 'inherit'
79
+ });
80
+
81
+ const projectPath = path.join(targetModuleRoot, p.name);
82
+
83
+ // =====================================================
84
+ // 3. Copy template files (NO csproj)
85
+ // =====================================================
66
86
 
67
- // =======================
68
- // Logs
69
- // =======================
87
+ const templateSubFolder = getTemplateSubFolder(p.name, templateRoot);
70
88
 
71
- console.log(`🚀 Creating module from template`);
72
- console.log(`📦 New Module: ${newModuleName}`);
73
- console.log(`🧩 New Entity: ${newEntityName}`);
74
- console.log(`📁 Template: ${sourceModulePath}`);
75
- console.log(`📁 Target: ${destinationModulePath}`);
89
+ if (!templateSubFolder || !fs.existsSync(templateSubFolder)) {
90
+ console.warn(`⚠️ Template subfolder not found: ${templateSubFolder}`);
91
+ return;
92
+ }
93
+
94
+ console.log(`📄 Copying template from: ${templateSubFolder}`);
95
+ copyRecursive(templateSubFolder, projectPath);
96
+ });
76
97
 
77
- // =======================
78
- // Run
79
- // =======================
98
+ // =====================================================
99
+ // 4. Add Solution Folder + add projects under it
100
+ // =====================================================
80
101
 
81
- copyAndRenameFiles(sourceModulePath, destinationModulePath);
102
+ console.log(`📁 Creating solution folder: Modules\\${targetModuleName}`);
103
+ execSync(
104
+ `dotnet sln "${solutionFile}" add --solution-folder "Modules\\${targetModuleName}" "${targetModuleRoot}\\*\\*.csproj"`,
105
+ { stdio: 'inherit' }
106
+ );
82
107
 
83
- console.log(`🎉 Module "${newModuleName}" created with Entity "${newEntityName}" successfully!`);
108
+ console.log(`🎉 Module "${targetModuleName}" created successfully!`);
84
109
 
85
- // =======================
86
- // Core Logic
87
- // =======================
110
+ // =====================================================
111
+ // Helpers
112
+ // =====================================================
88
113
 
89
- function copyAndRenameFiles(src, dest) {
90
- const stat = fs.lstatSync(src);
114
+ function getTemplateSubFolder(projectName, templateRoot) {
115
+ if (projectName.endsWith('.API')) {
116
+ return path.join(templateRoot, 'API');
117
+ }
118
+ if (projectName.endsWith('.Core')) {
119
+ return path.join(templateRoot, 'Core');
120
+ }
121
+ if (projectName.endsWith('.Infrastructure')) {
122
+ return path.join(templateRoot, 'Infrastructure');
123
+ }
124
+ return null;
125
+ }
91
126
 
92
- if (stat.isDirectory()) {
127
+ function copyRecursive(src, dest) {
128
+ if (!fs.existsSync(dest)) {
93
129
  fs.mkdirSync(dest, { recursive: true });
130
+ }
94
131
 
95
- const entries = fs.readdirSync(src, { withFileTypes: true });
132
+ const entries = fs.readdirSync(src, { withFileTypes: true });
96
133
 
97
- for (const entry of entries) {
98
- const srcPath = path.join(src, entry.name);
134
+ for (const entry of entries) {
135
+ const srcPath = path.join(src, entry.name);
136
+ const destPath = path.join(dest, entry.name);
99
137
 
100
- // Rename folder/file name
101
- const renamedName = applyReplacements(entry.name, replaceMap);
102
- const destPath = path.join(dest, renamedName);
138
+ // Do NOT overwrite .csproj
139
+ if (entry.isFile() && entry.name.endsWith('.csproj')) {
140
+ continue;
141
+ }
142
+
143
+ if (entry.isDirectory()) {
144
+ copyRecursive(srcPath, destPath);
145
+ } else {
146
+ fs.copyFileSync(srcPath, destPath);
147
+ }
148
+ }
149
+ }
150
+
151
+ function findSolutionFileUpwards(startDir) {
152
+ let current = startDir;
103
153
 
104
- copyAndRenameFiles(srcPath, destPath);
154
+ while (true) {
155
+ const files = fs.readdirSync(current);
156
+ let sln = files.find(f => f.endsWith('.sln') || f.endsWith('.slnx'));
157
+ if (sln) return path.join(current, sln);
158
+
159
+ const blueprintTemplate = path.join(current, 'BlueprintTemplate');
160
+ if (fs.existsSync(blueprintTemplate)) {
161
+ const btFiles = fs.readdirSync(blueprintTemplate);
162
+ sln = btFiles.find(f => f.endsWith('.sln') || f.endsWith('.slnx'));
163
+ if (sln) return path.join(blueprintTemplate, sln);
105
164
  }
106
- } else {
107
- // Copy + replace file content
108
- let content = fs.readFileSync(src, 'utf8');
109
- content = applyReplacements(content, replaceMap);
110
- fs.writeFileSync(dest, content, 'utf8');
165
+
166
+ const parent = path.dirname(current);
167
+ if (parent === current) return null;
168
+ current = parent;
111
169
  }
112
170
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "netcore-blueprint",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "description": "A custom project blueprint",
5
5
  "main": "create.js",
6
6
  "bin": {