1+ <#
2+ . SYNOPSIS
3+ Prepares a Clean Architecture solution as a template.
4+
5+ . DESCRIPTION
6+ This script prepares the Clean Architecture solution as a template by
7+ tokenizing namespace references and setting up the structure for packaging.
8+ It does NOT create the actual NuGet package - this is handled separately.
9+
10+ . PARAMETER SourceDirectory
11+ The directory containing the source code to templatize. Default is the current directory.
12+
13+ . PARAMETER TemplateNamespace
14+ The current namespace prefix used in the solution that will be tokenized. Default is "Contact".
15+
16+ . PARAMETER OutputDirectory
17+ The directory where the prepared template will be created. Default is ".\template-output".
18+ #>
19+
20+ param (
21+ [string ]$SourceDirectory = " ." ,
22+ [string ]$TemplateNamespace = " Contact" ,
23+ [string ]$OutputDirectory = " .\template-output"
24+ )
25+
26+ # Create a timestamp for logging purposes
27+ $timestamp = Get-Date - Format " yyyy-MM-dd HH:mm:ss"
28+ Write-Host " [$timestamp ] Template preparation process started"
29+
30+ # Ensure output directory exists and is empty
31+ if (Test-Path $OutputDirectory ) {
32+ Write-Host " [$timestamp ] Cleaning existing output directory..."
33+ Remove-Item - Path " $OutputDirectory \*" - Recurse - Force - ErrorAction SilentlyContinue
34+ } else {
35+ Write-Host " [$timestamp ] Creating output directory..."
36+ New-Item - Path $OutputDirectory - ItemType Directory | Out-Null
37+ }
38+
39+ # Create template structure directories
40+ $templateConfigDir = Join-Path $OutputDirectory " .template.config"
41+ New-Item - Path $templateConfigDir - ItemType Directory - Force | Out-Null
42+
43+ # Copy all solution files to the output directory
44+ Write-Host " [$timestamp ] Copying solution files..."
45+ $excludedItems = @ (
46+ " bin" , " obj" , " node_modules" , " .vs" , " .vscode" , " dist" , " .git" ,
47+ " .angular" , " package-lock.json" , " yarn.lock" , " .env" ,
48+ " appsettings.Development.json" , " CreateTemplate.ps1" , " nupkg"
49+ )
50+
51+ # Get all directories in the source directory except excluded ones
52+ Get-ChildItem - Path $SourceDirectory - Directory |
53+ Where-Object { $excludedItems -notcontains $_.Name } |
54+ ForEach-Object {
55+ Copy-Item - Path $_.FullName - Destination $OutputDirectory - Recurse - Force
56+ }
57+
58+ # Get all files in the source directory except excluded ones or hidden files
59+ Get-ChildItem - Path $SourceDirectory - File |
60+ Where-Object {
61+ -not $_.Name.StartsWith (' .' ) -and
62+ $_.Name -ne " CreateTemplate.ps1" -and
63+ $_.Extension -ne " .nupkg"
64+ } |
65+ ForEach-Object {
66+ Copy-Item - Path $_.FullName - Destination $OutputDirectory - Force
67+ }
68+
69+ # Clean up binary files from the output directory
70+ Write-Host " [$timestamp ] Cleaning up binary and temporary files..."
71+ Get-ChildItem - Path $OutputDirectory - Include @ (" bin" , " obj" , " node_modules" , " .vs" , " .vscode" , " dist" , " .git" , " .angular" , " .github" ) - Recurse - Directory |
72+ ForEach-Object {
73+ Write-Host " Removing $ ( $_.FullName ) "
74+ Remove-Item - Path $_.FullName - Recurse - Force - ErrorAction SilentlyContinue
75+ }
76+
77+ # Find and replace namespace references in C# files
78+ Write-Host " [$timestamp ] Tokenizing namespace references..."
79+ $filesToProcess = Get-ChildItem - Path $OutputDirectory - Include @ (" *.cs" , " *.csproj" , " *.sln" ) - Recurse - File
80+
81+ foreach ($file in $filesToProcess ) {
82+ Write-Host " Processing $ ( $file.FullName ) "
83+ $content = Get-Content - Path $file.FullName - Raw
84+
85+ # Replace namespace references
86+ if ($file.Extension -eq " .cs" ) {
87+ $content = $content -replace " namespace\s+$TemplateNamespace \." , " namespace ${TemplateNamespace} ."
88+ $content = $content -replace " using\s+$TemplateNamespace \." , " using ${TemplateNamespace} ."
89+ }
90+ elseif ($file.Extension -eq " .csproj" ) {
91+ $content = $content -replace " <RootNamespace>$TemplateNamespace \." , " <RootNamespace>${TemplateNamespace} ."
92+ $content = $content -replace " <AssemblyName>$TemplateNamespace \." , " <AssemblyName>${TemplateNamespace} ."
93+ }
94+ elseif ($file.Name -eq " *.sln" ) {
95+ $content = $content -replace " $TemplateNamespace \." , " ${TemplateNamespace} ."
96+ }
97+
98+ # Write the modified content back to the file
99+ Set-Content - Path $file.FullName - Value $content - NoNewline
100+ }
101+
102+ # Create template.json configuration file
103+ Write-Host " [$timestamp ] Creating template configuration..."
104+ $templateJson = @ {
105+ ' $schema' = " http://json.schemastore.org/template"
106+ author = " Template Author" # This will be overridden in the GitHub Action
107+ classifications = @ (" Web" , " API" , " Angular" , " Clean Architecture" , " Full-Stack" )
108+ identity = " CleanArchitecture.FullStack.Template"
109+ name = " Clean Architecture Full-Stack Solution"
110+ shortName = " cleanarch-fullstack"
111+ tags = @ {
112+ language = " C#"
113+ type = " project"
114+ }
115+ sourceName = $TemplateNamespace
116+ preferNameDirectory = $true
117+ symbols = @ {
118+ Framework = @ {
119+ type = " parameter"
120+ description = " The target framework for the project."
121+ datatype = " choice"
122+ choices = @ (
123+ @ {
124+ choice = " net9.0"
125+ description = " .NET 9.0"
126+ }
127+ )
128+ defaultValue = " net9.0"
129+ }
130+ Organization = @ {
131+ type = " parameter"
132+ datatype = " string"
133+ description = " Organization name to use in the project"
134+ defaultValue = " YourCompany"
135+ replaces = $TemplateNamespace
136+ }
137+ SkipRestore = @ {
138+ type = " parameter"
139+ datatype = " bool"
140+ description = " If specified, skips the automatic restore of the project on create."
141+ defaultValue = $false
142+ }
143+ IncludeAngular = @ {
144+ type = " parameter"
145+ datatype = " bool"
146+ description = " If specified, includes the Angular frontend project."
147+ defaultValue = $true
148+ }
149+ }
150+ sources = @ (
151+ @ {
152+ source = " backend/"
153+ target = " backend/"
154+ }
155+ @ {
156+ source = " frontend/"
157+ target = " frontend/"
158+ condition = " IncludeAngular"
159+ }
160+ @ {
161+ source = " docker-compose.yml"
162+ target = " docker-compose.yml"
163+ }
164+ @ {
165+ source = " .env-example"
166+ target = " .env-example"
167+ }
168+ @ {
169+ source = " README.md"
170+ target = " README.md"
171+ }
172+ )
173+ postActions = @ (
174+ @ {
175+ condition = " (!SkipRestore)"
176+ description = " Restore NuGet packages required by this project."
177+ manualInstructions = @ (
178+ @ {
179+ text = " Run 'dotnet restore' in the backend directory"
180+ }
181+ )
182+ actionId = " 210D431B-A78B-4D2F-B762-4ED3E3EA9025"
183+ continueOnError = $true
184+ }
185+ )
186+ }
187+
188+ # Convert the template configuration to JSON
189+ $templateJsonContent = $templateJson | ConvertTo-Json - Depth 10
190+ Set-Content - Path (Join-Path $templateConfigDir " template.json" ) - Value $templateJsonContent
191+
192+ Write-Host " [$timestamp ] Template preparation completed successfully."
193+ Write-Host " Template output directory: $OutputDirectory "
0 commit comments