@tamyla/clodo-framework 4.0.13 → 4.0.14
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/CHANGELOG.md +11 -0
- package/README.md +7 -0
- package/dist/cli/commands/create.js +2 -1
- package/dist/middleware/Composer.js +38 -0
- package/dist/middleware/Registry.js +14 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/shared/basicAuth.js +21 -0
- package/dist/middleware/shared/cors.js +28 -0
- package/dist/middleware/shared/index.js +3 -0
- package/dist/middleware/shared/logging.js +14 -0
- package/dist/service-management/GenerationEngine.js +13 -2
- package/dist/service-management/ServiceOrchestrator.js +6 -2
- package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +156 -10
- package/dist/service-management/generators/code/WorkerIndexGenerator.js +75 -9
- package/dist/simple-api.js +32 -1
- package/docs/MIDDLEWARE_MIGRATION_SUMMARY.md +121 -0
- package/package.json +4 -1
- package/scripts/DEPLOY_COMMAND_NEW.js +128 -0
- package/scripts/README-automated-testing-suite.md +356 -0
- package/scripts/README-test-clodo-deployment.md +157 -0
- package/scripts/README.md +50 -0
- package/scripts/analyze-imports.ps1 +104 -0
- package/scripts/analyze-mixed-code.js +163 -0
- package/scripts/analyze-mixed-rationale.js +149 -0
- package/scripts/automated-testing-suite.js +776 -0
- package/scripts/deployment/README.md +31 -0
- package/scripts/deployment/deploy-domain.ps1 +449 -0
- package/scripts/deployment/deploy-staging.js +120 -0
- package/scripts/deployment/validate-staging.js +166 -0
- package/scripts/diagnose-imports.js +362 -0
- package/scripts/framework-diagnostic.js +368 -0
- package/scripts/migration/migrate-middleware-legacy-to-contract.js +47 -0
- package/scripts/post-publish-test.js +663 -0
- package/scripts/scan-worker-issues.js +52 -0
- package/scripts/service-management/README.md +27 -0
- package/scripts/service-management/setup-interactive.ps1 +693 -0
- package/scripts/test-clodo-deployment.js +588 -0
- package/scripts/test-downstream-install.js +237 -0
- package/scripts/test-local-package.ps1 +126 -0
- package/scripts/test-local-package.sh +166 -0
- package/scripts/test-package.js +339 -0
- package/scripts/testing/README.md +49 -0
- package/scripts/testing/test-first.ps1 +0 -0
- package/scripts/testing/test-first50.ps1 +0 -0
- package/scripts/testing/test.ps1 +0 -0
- package/scripts/utilities/README.md +61 -0
- package/scripts/utilities/check-bin.js +8 -0
- package/scripts/utilities/check-bundle.js +23 -0
- package/scripts/utilities/check-dist-imports.js +65 -0
- package/scripts/utilities/check-import-paths.js +191 -0
- package/scripts/utilities/cleanup-cli.js +159 -0
- package/scripts/utilities/deployment-helpers.ps1 +199 -0
- package/scripts/utilities/fix-dist-imports.js +135 -0
- package/scripts/utilities/generate-secrets.js +159 -0
- package/scripts/utilities/safe-push.ps1 +51 -0
- package/scripts/utilities/setup-helpers.ps1 +206 -0
- package/scripts/utilities/test-packaged-artifact.js +92 -0
- package/scripts/utilities/validate-dist-imports.js +189 -0
- package/scripts/utilities/validate-schema.js +102 -0
- package/scripts/verify-exports.js +193 -0
- package/scripts/verify-worker-safety.js +73 -0
- package/types/middleware.d.ts +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Service Management Scripts
|
|
2
|
+
|
|
3
|
+
Scripts for creating, initializing, and setting up Clodo Framework services.
|
|
4
|
+
|
|
5
|
+
## Scripts
|
|
6
|
+
|
|
7
|
+
### setup-interactive.ps1
|
|
8
|
+
Interactive service setup wizard that guides users through creating new services.
|
|
9
|
+
|
|
10
|
+
**Features:**
|
|
11
|
+
- Interactive prompts for service configuration
|
|
12
|
+
- Template selection and customization
|
|
13
|
+
- Domain configuration setup
|
|
14
|
+
- Automatic dependency installation
|
|
15
|
+
|
|
16
|
+
**Usage:**
|
|
17
|
+
```powershell
|
|
18
|
+
.\scripts\service-management\setup-interactive.ps1 -ServiceName my-service -ServiceType api-gateway
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Parameters:**
|
|
22
|
+
- `ServiceName` - Name of the service to create
|
|
23
|
+
- `ServiceType` - Type of service (data-service, auth-service, content-service, api-gateway, generic)
|
|
24
|
+
- `DomainName` - Domain name for the service
|
|
25
|
+
- `NonInteractive` - Skip interactive prompts
|
|
26
|
+
- `TemplatePath` - Path to service templates
|
|
27
|
+
- `OutputPath` - Output directory for the service
|
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[Parameter(Mandatory=$false)]
|
|
3
|
+
[string]$ServiceName,
|
|
4
|
+
|
|
5
|
+
[Parameter(Mandatory=$false)]
|
|
6
|
+
[ValidateSet("data-service", "auth-service", "content-service", "api-gateway", "generic")]
|
|
7
|
+
[string]$ServiceType = "generic",
|
|
8
|
+
|
|
9
|
+
[Parameter(Mandatory=$false)]
|
|
10
|
+
[string]$DomainName,
|
|
11
|
+
|
|
12
|
+
[Parameter(Mandatory=$false)]
|
|
13
|
+
[switch]$NonInteractive,
|
|
14
|
+
|
|
15
|
+
[Parameter(Mandatory=$false)]
|
|
16
|
+
[string]$TemplatePath = ".\templates",
|
|
17
|
+
|
|
18
|
+
[Parameter(Mandatory=$false)]
|
|
19
|
+
[string]$OutputPath = "."
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Import Clodo Framework utilities
|
|
23
|
+
. "$PSScriptRoot\..\utilities\deployment-helpers.ps1"
|
|
24
|
+
. "$PSScriptRoot\..\utilities\setup-helpers.ps1"
|
|
25
|
+
|
|
26
|
+
# Configuration
|
|
27
|
+
$ErrorActionPreference = "Stop"
|
|
28
|
+
$ProgressPreference = "SilentlyContinue"
|
|
29
|
+
|
|
30
|
+
# Colors for output
|
|
31
|
+
$Green = "Green"
|
|
32
|
+
$Yellow = "Yellow"
|
|
33
|
+
$Red = "Red"
|
|
34
|
+
$Cyan = "Cyan"
|
|
35
|
+
$White = "White"
|
|
36
|
+
$Magenta = "Magenta"
|
|
37
|
+
|
|
38
|
+
function Write-Step {
|
|
39
|
+
param([string]$Message)
|
|
40
|
+
Write-Host "==> $Message" -ForegroundColor $Cyan
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function Write-Success {
|
|
44
|
+
param([string]$Message)
|
|
45
|
+
Write-Host "[OK] $Message" -ForegroundColor $Green
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function Write-Warning {
|
|
49
|
+
param([string]$Message)
|
|
50
|
+
Write-Host "WARNING: $Message" -ForegroundColor $Yellow
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function Write-Error-Message {
|
|
54
|
+
param([string]$Message)
|
|
55
|
+
Write-Host "[ERROR] $Message" -ForegroundColor $Red
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function Write-Prompt {
|
|
59
|
+
param([string]$Message)
|
|
60
|
+
Write-Host "$Message" -ForegroundColor $Magenta -NoNewline
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function Exit-WithError {
|
|
64
|
+
param([string]$Message, [int]$ExitCode = 1)
|
|
65
|
+
Write-Error-Message $Message
|
|
66
|
+
exit $ExitCode
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Main setup function
|
|
70
|
+
function Invoke-InteractiveSetup {
|
|
71
|
+
Write-Step "Clodo Framework - Interactive Service Setup"
|
|
72
|
+
Write-Host "Welcome to the Clodo Framework service setup wizard!" -ForegroundColor $Cyan
|
|
73
|
+
Write-Host "This wizard will help you create a new service with proper configuration.`n" -ForegroundColor $White
|
|
74
|
+
|
|
75
|
+
# Gather service information
|
|
76
|
+
$serviceInfo = Get-ServiceInformation
|
|
77
|
+
$domainInfo = Get-DomainInformation
|
|
78
|
+
$cloudflareInfo = Get-CloudflareInformation
|
|
79
|
+
$featureInfo = Get-FeatureConfiguration -ServiceType $serviceInfo.Type
|
|
80
|
+
|
|
81
|
+
# Display configuration summary
|
|
82
|
+
Show-ConfigurationSummary -ServiceInfo $serviceInfo -DomainInfo $domainInfo -CloudflareInfo $cloudflareInfo -FeatureInfo $featureInfo
|
|
83
|
+
|
|
84
|
+
# Confirm setup
|
|
85
|
+
if (-not $NonInteractive) {
|
|
86
|
+
$confirmation = Get-UserConfirmation "Do you want to proceed with this configuration?"
|
|
87
|
+
if (-not $confirmation) {
|
|
88
|
+
Write-Host "Setup cancelled by user." -ForegroundColor $Yellow
|
|
89
|
+
exit 0
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Create service structure
|
|
94
|
+
Write-Step "Creating service structure"
|
|
95
|
+
$servicePath = New-ServiceStructure -ServiceInfo $serviceInfo -OutputPath $OutputPath
|
|
96
|
+
Write-Success "Service structure created at: $servicePath"
|
|
97
|
+
|
|
98
|
+
# Generate configuration files
|
|
99
|
+
Write-Step "Generating configuration files"
|
|
100
|
+
New-ServiceConfiguration -ServiceInfo $serviceInfo -DomainInfo $domainInfo -CloudflareInfo $cloudflareInfo -FeatureInfo $featureInfo -ServicePath $servicePath
|
|
101
|
+
Write-Success "Configuration files generated"
|
|
102
|
+
|
|
103
|
+
# Initialize project
|
|
104
|
+
Write-Step "Initializing project"
|
|
105
|
+
Initialize-ServiceProject -ServicePath $servicePath -ServiceInfo $serviceInfo
|
|
106
|
+
Write-Success "Project initialized"
|
|
107
|
+
|
|
108
|
+
# Setup Cloudflare resources
|
|
109
|
+
if (-not $NonInteractive) {
|
|
110
|
+
$setupCloudflare = Get-UserConfirmation "Do you want to set up Cloudflare resources now?"
|
|
111
|
+
if ($setupCloudflare) {
|
|
112
|
+
Write-Step "Setting up Cloudflare resources"
|
|
113
|
+
$cfResult = Initialize-CloudflareResources -ServiceInfo $serviceInfo -DomainInfo $domainInfo -CloudflareInfo $cloudflareInfo
|
|
114
|
+
if ($cfResult.Success) {
|
|
115
|
+
Write-Success "Cloudflare resources configured"
|
|
116
|
+
} else {
|
|
117
|
+
Write-Warning "Cloudflare setup failed: $($cfResult.Error)"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# Display next steps
|
|
123
|
+
Show-NextSteps -ServiceInfo $serviceInfo -ServicePath $servicePath
|
|
124
|
+
|
|
125
|
+
Write-Step "Service setup completed successfully!"
|
|
126
|
+
Write-Host "`n[SUCCESS] Your new Clodo service is ready to go!" -ForegroundColor $Green
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Gather service information
|
|
130
|
+
function Get-ServiceInformation {
|
|
131
|
+
Write-Step "Service Information"
|
|
132
|
+
|
|
133
|
+
if ($ServiceName) {
|
|
134
|
+
$name = $ServiceName
|
|
135
|
+
} else {
|
|
136
|
+
Write-Prompt "Enter service name: "
|
|
137
|
+
$name = Read-Host
|
|
138
|
+
if (-not $name) {
|
|
139
|
+
Exit-WithError "Service name is required"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
# Validate service name
|
|
144
|
+
if ($name -notmatch '^[a-z0-9-]+$') {
|
|
145
|
+
Exit-WithError "Service name must contain only lowercase letters, numbers, and hyphens"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
$displayName = Get-UserInput "Display name" "$($name -replace '-', ' ' | ForEach-Object { (Get-Culture).TextInfo.ToTitleCase($_) })"
|
|
149
|
+
$description = Get-UserInput "Description" "A Clodo Framework service"
|
|
150
|
+
$version = Get-UserInput "Initial version" "1.0.0"
|
|
151
|
+
$author = Get-UserInput "Author" $env:USERNAME
|
|
152
|
+
|
|
153
|
+
return @{
|
|
154
|
+
Name = $name
|
|
155
|
+
DisplayName = $displayName
|
|
156
|
+
Description = $description
|
|
157
|
+
Version = $version
|
|
158
|
+
Author = $author
|
|
159
|
+
Type = $ServiceType
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# Gather domain information
|
|
164
|
+
function Get-DomainInformation {
|
|
165
|
+
Write-Step "Domain Configuration"
|
|
166
|
+
|
|
167
|
+
if ($DomainName) {
|
|
168
|
+
$name = $DomainName
|
|
169
|
+
} else {
|
|
170
|
+
Write-Prompt "Enter domain name: "
|
|
171
|
+
$name = Read-Host
|
|
172
|
+
if (-not $name) {
|
|
173
|
+
Exit-WithError "Domain name is required"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
$displayName = Get-UserInput "Domain display name" "$($name -replace '-', ' ' | ForEach-Object { (Get-Culture).TextInfo.ToTitleCase($_) })"
|
|
178
|
+
|
|
179
|
+
Write-Host "Domain URLs:" -ForegroundColor $White
|
|
180
|
+
$productionUrl = Get-UserInput "Production URL" "api.$name.com"
|
|
181
|
+
$stagingUrl = Get-UserInput "Staging URL" "staging-api.$name.com"
|
|
182
|
+
$developmentUrl = Get-UserInput "Development URL" "dev-api.$name.com"
|
|
183
|
+
|
|
184
|
+
return @{
|
|
185
|
+
Name = $name
|
|
186
|
+
DisplayName = $displayName
|
|
187
|
+
ProductionUrl = $productionUrl
|
|
188
|
+
StagingUrl = $stagingUrl
|
|
189
|
+
DevelopmentUrl = $developmentUrl
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Gather Cloudflare information
|
|
194
|
+
function Get-CloudflareInformation {
|
|
195
|
+
Write-Step "Cloudflare Configuration"
|
|
196
|
+
|
|
197
|
+
Write-Host "You'll need your Cloudflare account information." -ForegroundColor $White
|
|
198
|
+
Write-Host "You can find this in your Cloudflare dashboard under Account Settings.`n" -ForegroundColor $White
|
|
199
|
+
|
|
200
|
+
$accountId = Get-UserInput "Account ID" ""
|
|
201
|
+
$zoneId = Get-UserInput "Zone ID" ""
|
|
202
|
+
|
|
203
|
+
if (-not $accountId -or -not $zoneId) {
|
|
204
|
+
Write-Warning "Cloudflare IDs are required for deployment. You can configure them later in the generated config files."
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return @{
|
|
208
|
+
AccountId = $accountId
|
|
209
|
+
ZoneId = $zoneId
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Get feature configuration based on service type
|
|
214
|
+
function Get-FeatureConfiguration {
|
|
215
|
+
param([string]$ServiceType)
|
|
216
|
+
|
|
217
|
+
Write-Step "Feature Configuration"
|
|
218
|
+
|
|
219
|
+
$baseFeatures = @{
|
|
220
|
+
logging = $true
|
|
221
|
+
monitoring = $true
|
|
222
|
+
errorReporting = $true
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
$serviceSpecificFeatures = switch ($ServiceType) {
|
|
226
|
+
"data-service" {
|
|
227
|
+
@{
|
|
228
|
+
authentication = $true
|
|
229
|
+
authorization = $true
|
|
230
|
+
fileStorage = $true
|
|
231
|
+
search = $true
|
|
232
|
+
filtering = $true
|
|
233
|
+
pagination = $true
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
"auth-service" {
|
|
237
|
+
@{
|
|
238
|
+
authentication = $true
|
|
239
|
+
authorization = $true
|
|
240
|
+
userProfiles = $true
|
|
241
|
+
emailNotifications = $true
|
|
242
|
+
magicLinkAuth = $true
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
"content-service" {
|
|
246
|
+
@{
|
|
247
|
+
fileStorage = $true
|
|
248
|
+
search = $true
|
|
249
|
+
filtering = $true
|
|
250
|
+
pagination = $true
|
|
251
|
+
caching = $true
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
"api-gateway" {
|
|
255
|
+
@{
|
|
256
|
+
authentication = $true
|
|
257
|
+
authorization = $true
|
|
258
|
+
rateLimiting = $true
|
|
259
|
+
caching = $true
|
|
260
|
+
monitoring = $true
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
default {
|
|
264
|
+
@{
|
|
265
|
+
authentication = $false
|
|
266
|
+
authorization = $false
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
$allFeatures = $baseFeatures + $serviceSpecificFeatures
|
|
272
|
+
|
|
273
|
+
Write-Host "Default features for $ServiceType service:" -ForegroundColor $White
|
|
274
|
+
foreach ($feature in $allFeatures.GetEnumerator() | Sort-Object Name) {
|
|
275
|
+
$status = if ($feature.Value) { "[ENABLED]" } else { "[DISABLED]" }
|
|
276
|
+
Write-Host " $status $($feature.Name)" -ForegroundColor $(if ($feature.Value) { $Green } else { $White })
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
Write-Host ""
|
|
280
|
+
|
|
281
|
+
if (-not $NonInteractive) {
|
|
282
|
+
Write-Host "You can modify these features later in the generated configuration files." -ForegroundColor $Yellow
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return $allFeatures
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
# Display configuration summary
|
|
289
|
+
function Show-ConfigurationSummary {
|
|
290
|
+
param($ServiceInfo, $DomainInfo, $CloudflareInfo, $FeatureInfo)
|
|
291
|
+
|
|
292
|
+
Write-Step "Configuration Summary"
|
|
293
|
+
|
|
294
|
+
Write-Host "Service:" -ForegroundColor $Cyan
|
|
295
|
+
Write-Host " Name: $($ServiceInfo.Name)" -ForegroundColor $White
|
|
296
|
+
Write-Host " Display Name: $($ServiceInfo.DisplayName)" -ForegroundColor $White
|
|
297
|
+
Write-Host " Type: $($ServiceInfo.Type)" -ForegroundColor $White
|
|
298
|
+
Write-Host " Version: $($ServiceInfo.Version)" -ForegroundColor $White
|
|
299
|
+
|
|
300
|
+
Write-Host "`nDomain:" -ForegroundColor $Cyan
|
|
301
|
+
Write-Host " Name: $($DomainInfo.Name)" -ForegroundColor $White
|
|
302
|
+
Write-Host " Production: $($DomainInfo.ProductionUrl)" -ForegroundColor $White
|
|
303
|
+
Write-Host " Staging: $($DomainInfo.StagingUrl)" -ForegroundColor $White
|
|
304
|
+
Write-Host " Development: $($DomainInfo.DevelopmentUrl)" -ForegroundColor $White
|
|
305
|
+
|
|
306
|
+
Write-Host "`nCloudflare:" -ForegroundColor $Cyan
|
|
307
|
+
Write-Host " Account ID: $(if ($CloudflareInfo.AccountId) { $CloudflareInfo.AccountId } else { 'Not configured' })" -ForegroundColor $White
|
|
308
|
+
Write-Host " Zone ID: $(if ($CloudflareInfo.ZoneId) { $CloudflareInfo.ZoneId } else { 'Not configured' })" -ForegroundColor $White
|
|
309
|
+
|
|
310
|
+
Write-Host "`nEnabled Features:" -ForegroundColor $Cyan
|
|
311
|
+
$enabledFeatures = $FeatureInfo.GetEnumerator() | Where-Object { $_.Value } | Sort-Object Name
|
|
312
|
+
foreach ($feature in $enabledFeatures) {
|
|
313
|
+
Write-Host " [ENABLED] $($feature.Name)" -ForegroundColor $Green
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
Write-Host ""
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
# Create service directory structure
|
|
320
|
+
function New-ServiceStructure {
|
|
321
|
+
param($ServiceInfo, [string]$OutputPath)
|
|
322
|
+
|
|
323
|
+
$servicePath = Join-Path $OutputPath $ServiceInfo.Name
|
|
324
|
+
|
|
325
|
+
if (Test-Path $servicePath) {
|
|
326
|
+
if (-not $NonInteractive) {
|
|
327
|
+
$overwrite = Get-UserConfirmation "Service directory already exists. Overwrite?"
|
|
328
|
+
if (-not $overwrite) {
|
|
329
|
+
Exit-WithError "Service directory already exists"
|
|
330
|
+
}
|
|
331
|
+
Remove-Item $servicePath -Recurse -Force
|
|
332
|
+
} else {
|
|
333
|
+
Exit-WithError "Service directory already exists: $servicePath"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
# Create directory structure
|
|
338
|
+
$directories = @(
|
|
339
|
+
$servicePath,
|
|
340
|
+
(Join-Path $servicePath "src"),
|
|
341
|
+
(Join-Path $servicePath "src\config"),
|
|
342
|
+
(Join-Path $servicePath "src\worker"),
|
|
343
|
+
(Join-Path $servicePath "src\routes"),
|
|
344
|
+
(Join-Path $servicePath "src\services"),
|
|
345
|
+
(Join-Path $servicePath "scripts"),
|
|
346
|
+
(Join-Path $servicePath "tests"),
|
|
347
|
+
(Join-Path $servicePath "migrations"),
|
|
348
|
+
(Join-Path $servicePath "docs")
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
foreach ($dir in $directories) {
|
|
352
|
+
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return $servicePath
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Generate configuration files
|
|
359
|
+
function New-ServiceConfiguration {
|
|
360
|
+
param($ServiceInfo, $DomainInfo, $CloudflareInfo, $FeatureInfo, [string]$ServicePath)
|
|
361
|
+
|
|
362
|
+
# Generate package.json
|
|
363
|
+
$packageJson = @{
|
|
364
|
+
name = $ServiceInfo.Name
|
|
365
|
+
version = $ServiceInfo.Version
|
|
366
|
+
description = $ServiceInfo.Description
|
|
367
|
+
main = "src/worker/index.js"
|
|
368
|
+
type = "module"
|
|
369
|
+
scripts = @{
|
|
370
|
+
test = "jest"
|
|
371
|
+
deploy = "powershell .\scripts\deploy.ps1"
|
|
372
|
+
setup = "powershell .\scripts\setup.ps1"
|
|
373
|
+
}
|
|
374
|
+
dependencies = @{
|
|
375
|
+
"@tamyla/clodo-framework" = "^1.0.0"
|
|
376
|
+
"wrangler" = "^3.0.0"
|
|
377
|
+
}
|
|
378
|
+
devDependencies = @{
|
|
379
|
+
"jest" = "^29.7.0"
|
|
380
|
+
"@babel/core" = "^7.23.0"
|
|
381
|
+
"@babel/preset-env" = "^7.23.0"
|
|
382
|
+
}
|
|
383
|
+
author = $ServiceInfo.Author
|
|
384
|
+
license = "MIT"
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
$packageJson | ConvertTo-Json -Depth 10 | Out-File (Join-Path $ServicePath "package.json") -Encoding UTF8
|
|
388
|
+
|
|
389
|
+
# Generate domain configuration
|
|
390
|
+
$featureString = ($FeatureInfo.GetEnumerator() | Where-Object { $_.Value } | ForEach-Object { " $($_.Name): true," }) -join "`n"
|
|
391
|
+
$domainConfig = @"
|
|
392
|
+
import { createDomainConfigSchema } from '@tamyla/clodo-framework';
|
|
393
|
+
|
|
394
|
+
export const domains = {
|
|
395
|
+
'$($DomainInfo.Name)': {
|
|
396
|
+
...createDomainConfigSchema(),
|
|
397
|
+
name: '$($DomainInfo.Name)',
|
|
398
|
+
displayName: '$($DomainInfo.DisplayName)',
|
|
399
|
+
accountId: '$($CloudflareInfo.AccountId)',
|
|
400
|
+
zoneId: '$($CloudflareInfo.ZoneId)',
|
|
401
|
+
domains: {
|
|
402
|
+
production: '$($DomainInfo.ProductionUrl)',
|
|
403
|
+
staging: '$($DomainInfo.StagingUrl)',
|
|
404
|
+
development: '$($DomainInfo.DevelopmentUrl)'
|
|
405
|
+
},
|
|
406
|
+
features: {
|
|
407
|
+
$($featureString)
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
"@
|
|
412
|
+
|
|
413
|
+
$domainConfig | Out-File (Join-Path $ServicePath "src\config\domains.js") -Encoding UTF8
|
|
414
|
+
|
|
415
|
+
# Generate wrangler.toml
|
|
416
|
+
$wranglerConfig = @"
|
|
417
|
+
name = "$($ServiceInfo.Name)-staging"
|
|
418
|
+
main = "src/worker/index.js"
|
|
419
|
+
compatibility_date = $(Get-Date -Format "yyyy-MM-dd")
|
|
420
|
+
|
|
421
|
+
[env.staging]
|
|
422
|
+
name = "$($ServiceInfo.Name)-staging"
|
|
423
|
+
|
|
424
|
+
[env.production]
|
|
425
|
+
name = "$($ServiceInfo.Name)-production"
|
|
426
|
+
|
|
427
|
+
# Database bindings will be added during deployment
|
|
428
|
+
# [[d1_databases]]
|
|
429
|
+
# binding = "$($ServiceInfo.Name)-db"
|
|
430
|
+
# database_name = "$($ServiceInfo.Name)-db"
|
|
431
|
+
"@
|
|
432
|
+
|
|
433
|
+
$wranglerConfig | Out-File (Join-Path $ServicePath "wrangler.toml") -Encoding UTF8
|
|
434
|
+
|
|
435
|
+
# Generate main worker file
|
|
436
|
+
$workerCode = @"
|
|
437
|
+
import { initializeService, createFeatureGuard, COMMON_FEATURES } from '@tamyla/clodo-framework';
|
|
438
|
+
import { domains } from './config/domains.js';
|
|
439
|
+
|
|
440
|
+
export default {
|
|
441
|
+
async fetch(request, env, ctx) {
|
|
442
|
+
try {
|
|
443
|
+
// Initialize service with Clodo Framework
|
|
444
|
+
const service = initializeService(env, domains);
|
|
445
|
+
|
|
446
|
+
// Route handling based on service type: $($ServiceInfo.Type)
|
|
447
|
+
const url = new URL(request.url);
|
|
448
|
+
|
|
449
|
+
// Health check endpoint
|
|
450
|
+
if (url.pathname === '/health') {
|
|
451
|
+
return new Response(JSON.stringify({
|
|
452
|
+
status: 'healthy',
|
|
453
|
+
service: '$($ServiceInfo.Name)',
|
|
454
|
+
version: '$($ServiceInfo.Version)',
|
|
455
|
+
features: service.features
|
|
456
|
+
}), {
|
|
457
|
+
headers: { 'Content-Type': 'application/json' }
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Add your service-specific routes here
|
|
462
|
+
// Example:
|
|
463
|
+
// if (url.pathname.startsWith('/api/')) {
|
|
464
|
+
// return handleApiRequest(request, env, ctx);
|
|
465
|
+
// }
|
|
466
|
+
|
|
467
|
+
return new Response('Clodo Service: $($ServiceInfo.DisplayName)', {
|
|
468
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
} catch (error) {
|
|
472
|
+
console.error('Service error:', error);
|
|
473
|
+
return new Response(JSON.stringify({
|
|
474
|
+
error: 'Internal Server Error',
|
|
475
|
+
message: error.message
|
|
476
|
+
}), {
|
|
477
|
+
status: 500,
|
|
478
|
+
headers: { 'Content-Type': 'application/json' }
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
"@
|
|
484
|
+
|
|
485
|
+
$workerCode | Out-File (Join-Path $ServicePath "src\worker\index.js") -Encoding UTF8
|
|
486
|
+
|
|
487
|
+
# Generate README.md
|
|
488
|
+
$featureList = ($FeatureInfo.GetEnumerator() | Where-Object { $_.Value } | ForEach-Object { "- $($_.Name)" }) -join "`n"
|
|
489
|
+
$readme = @"
|
|
490
|
+
# $($ServiceInfo.DisplayName)
|
|
491
|
+
|
|
492
|
+
$($ServiceInfo.Description)
|
|
493
|
+
|
|
494
|
+
## Features
|
|
495
|
+
|
|
496
|
+
$featureList
|
|
497
|
+
|
|
498
|
+
## Setup
|
|
499
|
+
|
|
500
|
+
1. Install dependencies:
|
|
501
|
+
```bash
|
|
502
|
+
|
|
503
|
+
## Setup
|
|
504
|
+
|
|
505
|
+
1. Install dependencies:
|
|
506
|
+
```bash
|
|
507
|
+
npm install
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
2. Configure your domain settings in `src/config/domains.js`
|
|
511
|
+
|
|
512
|
+
3. Deploy to Cloudflare:
|
|
513
|
+
```bash
|
|
514
|
+
npm run deploy
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Development
|
|
518
|
+
|
|
519
|
+
- Start development server: `npm run dev`
|
|
520
|
+
- Run tests: `npm test`
|
|
521
|
+
- Deploy to staging: `npm run deploy -- --Environment staging`
|
|
522
|
+
- Deploy to production: `npm run deploy -- --Environment production`
|
|
523
|
+
|
|
524
|
+
## Clodo Framework
|
|
525
|
+
|
|
526
|
+
This service is built using the Clodo Framework, which provides:
|
|
527
|
+
- Domain configuration management
|
|
528
|
+
- Feature flag system
|
|
529
|
+
- Deployment automation
|
|
530
|
+
- Consistent service patterns
|
|
531
|
+
|
|
532
|
+
Learn more: [Clodo Framework Documentation](../packages/clodo-framework/README.md)
|
|
533
|
+
"@
|
|
534
|
+
|
|
535
|
+
$readme | Out-File (Join-Path $ServicePath "README.md") -Encoding UTF8
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
# Initialize project
|
|
539
|
+
function Initialize-ServiceProject {
|
|
540
|
+
param([string]$ServicePath, $ServiceInfo)
|
|
541
|
+
|
|
542
|
+
Push-Location $ServicePath
|
|
543
|
+
|
|
544
|
+
try {
|
|
545
|
+
# Initialize git repository
|
|
546
|
+
if (-not (Test-Path ".git")) {
|
|
547
|
+
& git init 2>$null | Out-Null
|
|
548
|
+
Write-Success "Git repository initialized"
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
# Create .gitignore
|
|
552
|
+
$gitignore = @"
|
|
553
|
+
node_modules/
|
|
554
|
+
.env
|
|
555
|
+
.env.local
|
|
556
|
+
.wrangler/
|
|
557
|
+
logs/
|
|
558
|
+
*.log
|
|
559
|
+
coverage/
|
|
560
|
+
.nyc_output/
|
|
561
|
+
"@
|
|
562
|
+
|
|
563
|
+
$gitignore | Out-File ".gitignore" -Encoding UTF8
|
|
564
|
+
|
|
565
|
+
# Create initial .env.example
|
|
566
|
+
$envExample = @"
|
|
567
|
+
# Clodo Framework Environment Variables
|
|
568
|
+
DOMAIN_NAME=$($ServiceInfo.Name)
|
|
569
|
+
ENVIRONMENT=development
|
|
570
|
+
|
|
571
|
+
# Cloudflare Account (configure in src/config/domains.js)
|
|
572
|
+
# CLOUDFLARE_ACCOUNT_ID=your-account-id
|
|
573
|
+
# CLOUDFLARE_ZONE_ID=your-zone-id
|
|
574
|
+
|
|
575
|
+
# Service-specific environment variables
|
|
576
|
+
"@
|
|
577
|
+
|
|
578
|
+
$envExample | Out-File ".env.example" -Encoding UTF8
|
|
579
|
+
|
|
580
|
+
} finally {
|
|
581
|
+
Pop-Location
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
# Setup Cloudflare resources
|
|
586
|
+
function Initialize-CloudflareResources {
|
|
587
|
+
param($ServiceInfo, $DomainInfo, $CloudflareInfo)
|
|
588
|
+
|
|
589
|
+
if (-not $CloudflareInfo.AccountId -or -not $CloudflareInfo.ZoneId) {
|
|
590
|
+
return @{ Success = $false; Error = "Cloudflare credentials not configured" }
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
try {
|
|
594
|
+
# Test Cloudflare authentication
|
|
595
|
+
if (-not (Test-CloudflareAuth)) {
|
|
596
|
+
throw "Cloudflare authentication failed"
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
# Create D1 database
|
|
600
|
+
$dbResult = New-D1Database -DatabaseName "$($ServiceInfo.Name)-db"
|
|
601
|
+
if (-not $dbResult.Success) {
|
|
602
|
+
throw "Failed to create database: $($dbResult.Error)"
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return @{
|
|
606
|
+
Success = $true
|
|
607
|
+
DatabaseId = $dbResult.DatabaseId
|
|
608
|
+
}
|
|
609
|
+
} catch {
|
|
610
|
+
return @{
|
|
611
|
+
Success = $false
|
|
612
|
+
Error = $_.Exception.Message
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
# Display next steps
|
|
618
|
+
function Show-NextSteps {
|
|
619
|
+
param($ServiceInfo, [string]$ServicePath)
|
|
620
|
+
|
|
621
|
+
Write-Step "Next Steps"
|
|
622
|
+
|
|
623
|
+
Write-Host "Your service has been created! Here's what to do next:" -ForegroundColor $Cyan
|
|
624
|
+
Write-Host ""
|
|
625
|
+
|
|
626
|
+
Write-Host "1. Navigate to your service:" -ForegroundColor $White
|
|
627
|
+
Write-Host " cd $ServicePath" -ForegroundColor $Yellow
|
|
628
|
+
Write-Host ""
|
|
629
|
+
|
|
630
|
+
Write-Host "2. Install dependencies:" -ForegroundColor $White
|
|
631
|
+
Write-Host " npm install" -ForegroundColor $Yellow
|
|
632
|
+
Write-Host ""
|
|
633
|
+
|
|
634
|
+
Write-Host "3. Configure your domain settings:" -ForegroundColor $White
|
|
635
|
+
Write-Host " Edit src/config/domains.js" -ForegroundColor $Yellow
|
|
636
|
+
Write-Host ""
|
|
637
|
+
|
|
638
|
+
Write-Host "4. Implement your service logic:" -ForegroundColor $White
|
|
639
|
+
Write-Host " Edit src/worker/index.js" -ForegroundColor $Yellow
|
|
640
|
+
Write-Host ""
|
|
641
|
+
|
|
642
|
+
Write-Host "5. Test your service:" -ForegroundColor $White
|
|
643
|
+
Write-Host " npm test" -ForegroundColor $Yellow
|
|
644
|
+
Write-Host ""
|
|
645
|
+
|
|
646
|
+
Write-Host "6. Deploy to staging:" -ForegroundColor $White
|
|
647
|
+
Write-Host " npm run deploy -- --Environment staging" -ForegroundColor $Yellow
|
|
648
|
+
Write-Host ""
|
|
649
|
+
|
|
650
|
+
Write-Host "7. Deploy to production:" -ForegroundColor $White
|
|
651
|
+
Write-Host " npm run deploy -- --Environment production" -ForegroundColor $Yellow
|
|
652
|
+
Write-Host ""
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
# Helper functions
|
|
656
|
+
function Get-UserInput {
|
|
657
|
+
param([string]$Prompt, [string]$DefaultValue = "")
|
|
658
|
+
|
|
659
|
+
if ($NonInteractive) {
|
|
660
|
+
return $DefaultValue
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
$promptText = $Prompt
|
|
664
|
+
if ($DefaultValue) {
|
|
665
|
+
$promptText += " (default: $DefaultValue)"
|
|
666
|
+
}
|
|
667
|
+
$promptText += ": "
|
|
668
|
+
|
|
669
|
+
Write-Prompt $promptText
|
|
670
|
+
$userInput = Read-Host
|
|
671
|
+
|
|
672
|
+
return if ($userInput) { $userInput } else { $DefaultValue }
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function Get-UserConfirmation {
|
|
676
|
+
param([string]$Prompt)
|
|
677
|
+
|
|
678
|
+
if ($NonInteractive) {
|
|
679
|
+
return $true
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
Write-Prompt "$Prompt (y/N): "
|
|
683
|
+
$response = Read-Host
|
|
684
|
+
|
|
685
|
+
return $response -eq 'y' -or $response -eq 'Y'
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
# Run main setup
|
|
689
|
+
try {
|
|
690
|
+
Invoke-InteractiveSetup
|
|
691
|
+
} catch {
|
|
692
|
+
Exit-WithError "Setup failed: $_"
|
|
693
|
+
}
|