netcore-blueprint 0.0.80 → 0.0.82

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.
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ const { findSolutionFileFixed, copyRecursive, addProjectReferencesToCsproj } = require('../lib/replacer');
3
4
  const fs = require('fs');
4
5
  const path = require('path');
5
6
  const { execSync } = require('child_process');
@@ -9,7 +10,6 @@ const { execSync } = require('child_process');
9
10
  // Example: copy-module __MODULE__
10
11
  // Will create: __MODULE__Module
11
12
  // =====================================================
12
-
13
13
  const sourceModuleName = process.argv[2];
14
14
  const targetFolder = process.argv[3];
15
15
  const force = process.argv.includes('--force');
@@ -25,7 +25,7 @@ const modulesPath = process.cwd();
25
25
  const templateRoot = path.join(modulesPath, sourceModuleName);
26
26
  const targetModuleRoot = path.join(modulesPath, '..', targetFolder, 'Modules', `${sourceModuleName}Module`);
27
27
 
28
- const solutionFile = findSolutionFileFixed(modulesPath);
28
+ const solutionFile = findSolutionFileFixed(modulesPath, targetFolder);
29
29
 
30
30
  if (!fs.existsSync(templateRoot)) {
31
31
  console.error(`❌ Source module folder not found: ${templateRoot}`);
@@ -100,7 +100,7 @@ projects.forEach(p => {
100
100
  // 3. Copy template files (no csproj)
101
101
  // =====================================================
102
102
 
103
- const templateSubFolder = getTemplateSubFolder(p.name, templateRoot);
103
+ const templateSubFolder = path.join(templateRoot, p.name);
104
104
 
105
105
  if (!templateSubFolder || !fs.existsSync(templateSubFolder)) {
106
106
  console.warn(`⚠️ Template subfolder not found: ${templateSubFolder}`);
@@ -142,163 +142,16 @@ addModuleReferencesToHostApi(sourceModuleName, hostApiProjectPath);
142
142
  // =====================================================
143
143
  // Helpers
144
144
  // =====================================================
145
-
146
- function getTemplateSubFolder(projectName, templateRoot) {
147
- if (projectName.endsWith('.API')) {
148
- return path.join(templateRoot, `${projectName}`);
149
- }
150
- if (projectName.endsWith('.Core')) {
151
- return path.join(templateRoot, `${projectName}`);
152
- }
153
- if (projectName.endsWith('.Infrastructure')) {
154
- return path.join(templateRoot, `${projectName}`);
155
- }
156
- return null;
157
- }
158
-
159
- function copyRecursive(src, dest) {
160
- if (!fs.existsSync(dest)) {
161
- fs.mkdirSync(dest, { recursive: true });
162
- }
163
-
164
- const entries = fs.readdirSync(src, { withFileTypes: true });
165
- console.log(`📄 copy-module src: ${src}`);
166
- console.log(`📄 copy-module dest: ${dest}`);
167
-
168
- for (const entry of entries) {
169
- console.log(`📄 copy-module Item: ${entry.name}`);
170
- const srcPath = path.join(src, entry.name);
171
- const destPath = path.join(dest, entry.name);
172
-
173
- // Do NOT overwrite .csproj generated by dotnet new
174
- if (entry.isFile() && entry.name.endsWith('.csproj')) {
175
- console.log(`🧬 Merging ItemGroup from template csproj: ${srcPath}`);
176
- mergeItemGroupFromTemplate(srcPath, destPath);
177
- continue;
178
- }
179
-
180
- if (entry.isDirectory()) {
181
- copyRecursive(srcPath, destPath);
182
- } else {
183
- fs.copyFileSync(srcPath, destPath);
184
- }
185
- }
186
- }
187
-
188
- function findSolutionFileFixed(startDir) {
189
- // startDir = .../Modules/SomeModule
190
- const root = path.dirname(startDir);
191
- const targetSolution = path.join(root, targetFolder);
192
-
193
- if (!fs.existsSync(targetSolution)) {
194
- throw new Error('Target folder not found');
195
- }
196
-
197
- const btFiles = fs.readdirSync(targetSolution);
198
- const sln = btFiles.find(f => f.endsWith('.sln') || f.endsWith('.slnx'));
199
-
200
- if (!sln) {
201
- throw new Error('No .sln file found in Target folder');
202
- }
203
-
204
- return path.join(targetSolution, sln);
205
- }
206
-
207
- function mergeItemGroupFromTemplate(templateCsprojPath, targetCsprojPath) {
208
- if (!fs.existsSync(targetCsprojPath)) {
209
- console.warn(`⚠️ Target csproj not found, skipping merge: ${targetCsprojPath}`);
210
- return;
211
- }
212
-
213
- const templateContent = fs.readFileSync(templateCsprojPath, 'utf8');
214
- const targetContent = fs.readFileSync(targetCsprojPath, 'utf8');
215
-
216
- // Extract all ItemGroup blocks from template
217
- const itemGroupMatches = templateContent.match(/<ItemGroup>[\s\S]*?<\/ItemGroup>/g);
218
-
219
- if (!itemGroupMatches || itemGroupMatches.length === 0) {
220
- console.log(`ℹ️ No <ItemGroup> found in template csproj: ${templateCsprojPath}`);
221
- return;
222
- }
223
-
224
- const itemGroupsToInsert = '\n\n' + itemGroupMatches.join('\n\n') + '\n';
225
-
226
- // Insert right after </PropertyGroup>
227
- if (!targetContent.includes('</PropertyGroup>')) {
228
- console.warn(`⚠️ No </PropertyGroup> found in target csproj: ${targetCsprojPath}`);
229
- return;
230
- }
231
-
232
- const updatedTarget = targetContent.replace(
233
- /<\/PropertyGroup>/,
234
- `</PropertyGroup>${itemGroupsToInsert}`
235
- );
236
-
237
- fs.writeFileSync(targetCsprojPath, updatedTarget, 'utf8');
238
-
239
- console.log(`✅ ItemGroup merged into: ${targetCsprojPath}`);
240
- }
241
-
242
145
  function addModuleReferencesToHostApi(moduleName, hostApiCsprojPath) {
243
- if (!fs.existsSync(hostApiCsprojPath)) {
244
- console.warn(`⚠️ HostAPI.csproj not found: ${hostApiCsprojPath}`);
245
- return;
246
- }
247
-
248
- let content = fs.readFileSync(hostApiCsprojPath, 'utf8');
146
+ const refs = buildStaticProjectRefs(moduleName);
147
+ addProjectReferencesToCsproj(hostApiCsprojPath, refs);
148
+ }
249
149
 
250
- const refs = [
150
+ // Build refs (giữ nguyên logic cũ)
151
+ function buildStaticProjectRefs(moduleName) {
152
+ return [
251
153
  `..\\Modules\\${moduleName}Module\\${moduleName}Module.API\\${moduleName}Module.API.csproj`,
252
154
  `..\\Modules\\${moduleName}Module\\${moduleName}Module.Core\\${moduleName}Module.Core.csproj`,
253
155
  `..\\Modules\\${moduleName}Module\\${moduleName}Module.Infrastructure\\${moduleName}Module.Infrastructure.csproj`,
254
156
  ];
255
-
256
- // Avoid duplicate
257
- if (refs.some(r => content.includes(r))) {
258
- console.log(`ℹ️ HostAPI already contains references for ${moduleName}Module`);
259
- return;
260
- }
261
-
262
- const projectRefXml = refs
263
- .map(r => ` <ProjectReference Include="${r}" />`)
264
- .join('\n');
265
-
266
- // 🔥 Find ItemGroup that has ProjectReference BUT NOT PackageReference
267
- const projectOnlyItemGroupRegex =
268
- /<ItemGroup>(?:(?!<PackageReference)[\s\S])*?<ProjectReference[\s\S]*?<\/ItemGroup>/;
269
-
270
- const match = content.match(projectOnlyItemGroupRegex);
271
-
272
- if (match) {
273
- // ✅ Append to correct ProjectReference-only ItemGroup
274
- const originalGroup = match[0];
275
-
276
- const updatedGroup = originalGroup.replace(
277
- /<\/ItemGroup>/,
278
- `${projectRefXml}\n </ItemGroup>`
279
- );
280
-
281
- content = content.replace(originalGroup, updatedGroup);
282
-
283
- console.log(`✅ Appended to ProjectReference-only ItemGroup`);
284
- } else {
285
- // 🆕 Fallback: create new clean ProjectReference ItemGroup
286
- const newItemGroup = `
287
-
288
- <ItemGroup>
289
- ${projectRefXml}
290
- </ItemGroup>
291
- `;
292
-
293
- content = content.replace(
294
- /<\/Project>/,
295
- `${newItemGroup}\n</Project>`
296
- );
297
-
298
- console.log(`🆕 Created new ProjectReference ItemGroup`);
299
- }
300
-
301
- fs.writeFileSync(hostApiCsprojPath, content, 'utf8');
302
-
303
- console.log(`🎯 HostAPI references updated for ${moduleName}Module`);
304
- }
157
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { buildReplaceMap, applyReplacements } = require('../lib/replacer');
5
+ const { buildReplaceMap, copyAndRenameFiles } = require('../lib/replacer');
6
6
 
7
7
  // =======================
8
8
  // Args
@@ -67,35 +67,6 @@ console.log(`📁 To: ${destinationAssistantPath}`);
67
67
  // Run
68
68
  // =======================
69
69
 
70
- copyAndRenameFiles(sourceAssistantPath, destinationAssistantPath);
70
+ copyAndRenameFiles(sourceAssistantPath, destinationAssistantPath, replaceMap);
71
71
 
72
- console.log(`🎉 Assistant "${newAssistantName}" created successfully!`);
73
-
74
- // =======================
75
- // Core Logic
76
- // =======================
77
-
78
- function copyAndRenameFiles(src, dest) {
79
- console.log(src);
80
- console.log(dest);
81
- const stat = fs.lstatSync(src);
82
-
83
- if (stat.isDirectory()) {
84
- fs.mkdirSync(dest, { recursive: true });
85
-
86
- const entries = fs.readdirSync(src, { withFileTypes: true });
87
-
88
- for (const entry of entries) {
89
- const srcPath = path.join(src, entry.name);
90
-
91
- const renamed = applyReplacements(entry.name, replaceMap);
92
- const destPath = path.join(dest, renamed);
93
-
94
- copyAndRenameFiles(srcPath, destPath);
95
- }
96
- } else {
97
- let content = fs.readFileSync(src, 'utf8');
98
- content = applyReplacements(content, replaceMap);
99
- fs.writeFileSync(dest, content, 'utf8');
100
- }
101
- }
72
+ console.log(`🎉 Assistant "${newAssistantName}" created successfully!`);
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { buildReplaceMap, applyReplacements } = require('../lib/replacer');
5
+ const { buildReplaceMap, copyAndRenameFiles } = require('../lib/replacer');
6
6
 
7
7
  // =======================
8
8
  // Args
@@ -66,33 +66,6 @@ console.log(`📁 To: ${destinationModulePath}`);
66
66
  // Run
67
67
  // =======================
68
68
 
69
- copyAndRenameFiles(sourceModulePath, destinationModulePath);
69
+ copyAndRenameFiles(sourceModulePath, destinationModulePath, replaceMap);
70
70
 
71
- console.log(`🎉 Module "${newModuleName}" created successfully!`);
72
-
73
- // =======================
74
- // Core Logic
75
- // =======================
76
-
77
- function copyAndRenameFiles(src, dest) {
78
- const stat = fs.lstatSync(src);
79
-
80
- if (stat.isDirectory()) {
81
- fs.mkdirSync(dest, { recursive: true });
82
-
83
- const entries = fs.readdirSync(src, { withFileTypes: true });
84
-
85
- for (const entry of entries) {
86
- const srcPath = path.join(src, entry.name);
87
-
88
- const renamed = applyReplacements(entry.name, replaceMap);
89
- const destPath = path.join(dest, renamed);
90
-
91
- copyAndRenameFiles(srcPath, destPath);
92
- }
93
- } else {
94
- let content = fs.readFileSync(src, 'utf8');
95
- content = applyReplacements(content, replaceMap);
96
- fs.writeFileSync(dest, content, 'utf8');
97
- }
98
- }
71
+ console.log(`🎉 Module "${newModuleName}" created successfully!`);
package/lib/replacer.js CHANGED
@@ -21,7 +21,178 @@ function applyReplacements(text, replaceMap) {
21
21
  return result;
22
22
  }
23
23
 
24
+ function copyAndRenameFiles(src, dest, replaceMap) {
25
+ const stat = fs.lstatSync(src);
26
+
27
+ if (stat.isDirectory()) {
28
+ fs.mkdirSync(dest, { recursive: true });
29
+
30
+ const entries = fs.readdirSync(src, { withFileTypes: true });
31
+
32
+ for (const entry of entries) {
33
+ const srcPath = path.join(src, entry.name);
34
+
35
+ const renamed = applyReplacements(entry.name, replaceMap);
36
+ const destPath = path.join(dest, renamed);
37
+
38
+ copyAndRenameFiles(srcPath, destPath);
39
+ }
40
+ } else {
41
+ let content = fs.readFileSync(src, 'utf8');
42
+ content = applyReplacements(content, replaceMap);
43
+ fs.writeFileSync(dest, content, 'utf8');
44
+ }
45
+ }
46
+
47
+ function findSolutionFileFixed(startDir, targetFolder) {
48
+ // startDir = .../Modules/SomeModule
49
+ const root = path.dirname(startDir);
50
+ const targetSolution = path.join(root, targetFolder);
51
+
52
+ if (!fs.existsSync(targetSolution)) {
53
+ throw new Error('Target folder not found');
54
+ }
55
+
56
+ const btFiles = fs.readdirSync(targetSolution);
57
+ const sln = btFiles.find(f => f.endsWith('.sln') || f.endsWith('.slnx'));
58
+
59
+ if (!sln) {
60
+ throw new Error('No .sln file found in Target folder');
61
+ }
62
+
63
+ return path.join(targetSolution, sln);
64
+ }
65
+
66
+ function copyRecursive(src, dest) {
67
+ if (!fs.existsSync(dest)) {
68
+ fs.mkdirSync(dest, { recursive: true });
69
+ }
70
+
71
+ const entries = fs.readdirSync(src, { withFileTypes: true });
72
+
73
+ console.log(`📄 Copy src: ${src}`);
74
+ console.log(`📄 Copy dest: ${dest}`);
75
+
76
+ for (const entry of entries) {
77
+ const srcPath = path.join(src, entry.name);
78
+ const destPath = path.join(dest, entry.name);
79
+
80
+ console.log(`📄 Item: ${entry.name}`);
81
+
82
+ // 👉 Handle .csproj riêng
83
+ if (entry.isFile() && entry.name.endsWith('.csproj')) {
84
+ handleCsprojFile(srcPath, destPath);
85
+ continue;
86
+ }
87
+
88
+ if (entry.isDirectory()) {
89
+ copyRecursive(srcPath, destPath);
90
+ } else {
91
+ fs.copyFileSync(srcPath, destPath);
92
+ }
93
+ }
94
+ }
95
+
96
+ function handleCsprojFile(templatePath, targetPath) {
97
+ if (!fs.existsSync(targetPath)) {
98
+ console.warn(`⚠️ Target csproj not found: ${targetPath}`);
99
+ return;
100
+ }
101
+
102
+ const templateContent = fs.readFileSync(templatePath, 'utf8');
103
+ let targetContent = fs.readFileSync(targetPath, 'utf8');
104
+
105
+ const itemGroups = templateContent.match(/<ItemGroup>[\s\S]*?<\/ItemGroup>/g);
106
+
107
+ if (!itemGroups || itemGroups.length === 0) {
108
+ console.log(`ℹ️ No <ItemGroup> found in template: ${templatePath}`);
109
+ return;
110
+ }
111
+
112
+ // ✅ tránh duplicate
113
+ const newGroups = itemGroups.filter(group => !targetContent.includes(group));
114
+
115
+ if (newGroups.length === 0) {
116
+ console.log(`ℹ️ No new ItemGroup to merge`);
117
+ return;
118
+ }
119
+
120
+ const insertContent = '\n\n' + newGroups.join('\n\n') + '\n';
121
+
122
+ // ✅ fallback nếu không có PropertyGroup
123
+ if (targetContent.includes('</PropertyGroup>')) {
124
+ targetContent = targetContent.replace(
125
+ '</PropertyGroup>',
126
+ `</PropertyGroup>${insertContent}`
127
+ );
128
+ } else {
129
+ targetContent = targetContent.replace(
130
+ '</Project>',
131
+ `${insertContent}\n</Project>`
132
+ );
133
+ }
134
+
135
+ fs.writeFileSync(targetPath, targetContent, 'utf8');
136
+
137
+ console.log(`✅ ItemGroup merged into: ${targetPath}`);
138
+ }
139
+
140
+ function addProjectReferencesToCsproj(hostApiCsprojPath, refs) {
141
+ if (!fs.existsSync(hostApiCsprojPath)) {
142
+ console.warn(`⚠️ HostAPI.csproj not found: ${hostApiCsprojPath}`);
143
+ return;
144
+ }
145
+
146
+ let content = fs.readFileSync(hostApiCsprojPath, 'utf8');
147
+
148
+ if (refs.some(r => content.includes(r))) {
149
+ console.log(`ℹ️ HostAPI already contains references`);
150
+ return;
151
+ }
152
+
153
+ const projectRefXml = refs
154
+ .map(r => `<ProjectReference Include="${r}" />`)
155
+ .join('\n');
156
+
157
+ content = appendProjectReferences(content, projectRefXml);
158
+
159
+ fs.writeFileSync(hostApiCsprojPath, content, 'utf8');
160
+
161
+ console.log(`🎯 HostAPI references updated`);
162
+ }
163
+
164
+ // Append logic
165
+ function appendProjectReferences(content, projectRefXml) {
166
+ const projectOnlyItemGroupRegex =
167
+ /<ItemGroup>(?:(?!<PackageReference)[\s\S])*?<ProjectReference[\s\S]*?<\/ItemGroup>/;
168
+
169
+ const match = content.match(projectOnlyItemGroupRegex);
170
+
171
+ if (match) {
172
+ const updatedGroup = match[0].replace(
173
+ /<\/ItemGroup>/,
174
+ `${projectRefXml}\n </ItemGroup>`
175
+ );
176
+
177
+ console.log(`✅ Appended to ProjectReference-only ItemGroup`);
178
+ return content.replace(match[0], updatedGroup);
179
+ }
180
+
181
+ const newItemGroup = `
182
+ <ItemGroup>
183
+ ${projectRefXml}
184
+ </ItemGroup>
185
+ `;
186
+
187
+ console.log(`🆕 Created new ProjectReference ItemGroup`);
188
+
189
+ return content.replace(/<\/Project>/, `${newItemGroup}\n</Project>`);
190
+ }
191
+
24
192
  module.exports = {
25
193
  buildReplaceMap,
26
- applyReplacements
194
+ copyAndRenameFiles,
195
+ findSolutionFileFixed,
196
+ copyRecursive,
197
+ addProjectReferencesToCsproj
27
198
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "netcore-blueprint",
3
- "version": "0.0.80",
3
+ "version": "0.0.82",
4
4
  "description": "A custom project blueprint",
5
5
  "main": "create.js",
6
6
  "bin": {