@tamyla/clodo-framework 3.0.15 → 3.1.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/CHANGELOG.md +219 -153
- package/README.md +133 -1
- package/bin/clodo-service.js +1 -1
- package/bin/security/security-cli.js +0 -0
- package/bin/service-management/create-service.js +0 -0
- package/bin/service-management/init-service.js +2 -1
- package/dist/service-management/GenerationEngine.js +298 -3025
- package/dist/service-management/InputCollector.js +14 -0
- package/dist/service-management/ServiceCreator.js +19 -3
- package/dist/service-management/generators/BaseGenerator.js +233 -0
- package/dist/service-management/generators/GeneratorRegistry.js +254 -0
- package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +87 -0
- package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +106 -0
- package/dist/service-management/generators/code/ServiceHandlersGenerator.js +235 -0
- package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +116 -0
- package/dist/service-management/generators/code/ServiceUtilsGenerator.js +246 -0
- package/dist/service-management/generators/code/WorkerIndexGenerator.js +143 -0
- package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +101 -0
- package/dist/service-management/generators/config/DomainsConfigGenerator.js +175 -0
- package/dist/service-management/generators/config/EnvExampleGenerator.js +178 -0
- package/dist/service-management/generators/config/ProductionEnvGenerator.js +97 -0
- package/dist/service-management/generators/config/StagingEnvGenerator.js +97 -0
- package/dist/service-management/generators/config/WranglerTomlGenerator.js +238 -0
- package/dist/service-management/generators/core/PackageJsonGenerator.js +243 -0
- package/dist/service-management/generators/core/SiteConfigGenerator.js +115 -0
- package/dist/service-management/generators/documentation/ApiDocsGenerator.js +331 -0
- package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +294 -0
- package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +244 -0
- package/dist/service-management/generators/documentation/ReadmeGenerator.js +196 -0
- package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +190 -0
- package/dist/service-management/generators/scripts/DeployScriptGenerator.js +123 -0
- package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +101 -0
- package/dist/service-management/generators/scripts/SetupScriptGenerator.js +88 -0
- package/dist/service-management/generators/service-types/StaticSiteGenerator.js +342 -0
- package/dist/service-management/generators/testing/EslintConfigGenerator.js +85 -0
- package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +237 -0
- package/dist/service-management/generators/testing/JestConfigGenerator.js +72 -0
- package/dist/service-management/generators/testing/UnitTestsGenerator.js +277 -0
- package/dist/service-management/generators/tooling/DockerComposeGenerator.js +71 -0
- package/dist/service-management/generators/tooling/GitignoreGenerator.js +143 -0
- package/dist/service-management/generators/utils/FileWriter.js +179 -0
- package/dist/service-management/generators/utils/PathResolver.js +157 -0
- package/dist/service-management/generators/utils/ServiceManifestGenerator.js +111 -0
- package/dist/service-management/generators/utils/TemplateEngine.js +185 -0
- package/dist/service-management/generators/utils/index.js +18 -0
- package/dist/service-management/routing/DomainRouteMapper.js +311 -0
- package/dist/service-management/routing/RouteGenerator.js +266 -0
- package/dist/service-management/routing/WranglerRoutesBuilder.js +273 -0
- package/dist/service-management/routing/index.js +14 -0
- package/dist/service-management/services/DirectoryStructureService.js +56 -0
- package/dist/service-management/services/GenerationCoordinator.js +208 -0
- package/dist/service-management/services/GeneratorRegistry.js +174 -0
- package/dist/services/GenericDataService.js +14 -1
- package/dist/utils/config/unified-config-manager.js +128 -12
- package/dist/utils/framework-config.js +74 -2
- package/dist/worker/integration.js +4 -1
- package/package.json +6 -1
- package/templates/generic/clodo-service-manifest.json +25 -0
- package/templates/static-site/.env.example +61 -0
- package/templates/static-site/README.md +176 -0
- package/templates/static-site/clodo-service-manifest.json +66 -0
- package/templates/static-site/package.json +28 -0
- package/templates/static-site/public/404.html +87 -0
- package/templates/static-site/public/app.js +100 -0
- package/templates/static-site/public/index.html +48 -0
- package/templates/static-site/public/styles.css +123 -0
- package/templates/static-site/scripts/deploy.ps1 +121 -0
- package/templates/static-site/scripts/setup.ps1 +179 -0
- package/templates/static-site/src/config/domains.js +35 -0
- package/templates/static-site/src/worker/index.js +153 -0
- package/templates/static-site/wrangler.toml +43 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* Basic styles for {{SERVICE_DISPLAY_NAME}} */
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
body {
|
|
10
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
11
|
+
line-height: 1.6;
|
|
12
|
+
color: #333;
|
|
13
|
+
max-width: 1200px;
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
padding: 0 20px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
header {
|
|
19
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
20
|
+
color: white;
|
|
21
|
+
padding: 2rem 0;
|
|
22
|
+
text-align: center;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
header h1 {
|
|
26
|
+
margin-bottom: 1rem;
|
|
27
|
+
font-size: 2.5rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
nav {
|
|
31
|
+
margin-top: 1rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
nav a {
|
|
35
|
+
color: white;
|
|
36
|
+
text-decoration: none;
|
|
37
|
+
margin: 0 1rem;
|
|
38
|
+
padding: 0.5rem 1rem;
|
|
39
|
+
border-radius: 4px;
|
|
40
|
+
transition: background-color 0.3s;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
nav a:hover {
|
|
44
|
+
background-color: rgba(255, 255, 255, 0.1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main {
|
|
48
|
+
padding: 2rem 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#hero {
|
|
52
|
+
text-align: center;
|
|
53
|
+
margin-bottom: 3rem;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#hero h2 {
|
|
57
|
+
font-size: 2rem;
|
|
58
|
+
margin-bottom: 1rem;
|
|
59
|
+
color: #667eea;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#hero p {
|
|
63
|
+
font-size: 1.1rem;
|
|
64
|
+
margin-bottom: 1rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#features {
|
|
68
|
+
background: #f8f9fa;
|
|
69
|
+
padding: 2rem;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
margin-bottom: 2rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#features h3 {
|
|
75
|
+
text-align: center;
|
|
76
|
+
margin-bottom: 1.5rem;
|
|
77
|
+
color: #667eea;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#features ul {
|
|
81
|
+
list-style: none;
|
|
82
|
+
display: grid;
|
|
83
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
84
|
+
gap: 1rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#features li {
|
|
88
|
+
padding: 1rem;
|
|
89
|
+
background: white;
|
|
90
|
+
border-radius: 4px;
|
|
91
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
footer {
|
|
95
|
+
text-align: center;
|
|
96
|
+
padding: 2rem 0;
|
|
97
|
+
border-top: 1px solid #eee;
|
|
98
|
+
color: #666;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
footer a {
|
|
102
|
+
color: #667eea;
|
|
103
|
+
text-decoration: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
footer a:hover {
|
|
107
|
+
text-decoration: underline;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@media (max-width: 768px) {
|
|
111
|
+
header h1 {
|
|
112
|
+
font-size: 2rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
nav a {
|
|
116
|
+
display: block;
|
|
117
|
+
margin: 0.5rem 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#features ul {
|
|
121
|
+
grid-template-columns: 1fr;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Deployment script for {{SERVICE_NAME}}
|
|
2
|
+
# Generated by Clodo Framework
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[string]$Environment = "production",
|
|
6
|
+
[switch]$DryRun,
|
|
7
|
+
[switch]$Verbose
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
Write-Host "🚀 Deploying {{SERVICE_DISPLAY_NAME}} ($Environment)" -ForegroundColor Cyan
|
|
11
|
+
Write-Host "Generated by Clodo Framework" -ForegroundColor Gray
|
|
12
|
+
Write-Host ""
|
|
13
|
+
|
|
14
|
+
# Load environment variables
|
|
15
|
+
if (Test-Path ".env") {
|
|
16
|
+
Write-Host "📋 Loading environment configuration..." -ForegroundColor Yellow
|
|
17
|
+
Get-Content ".env" | ForEach-Object {
|
|
18
|
+
if ($_ -match "^([^#][^=]+)=(.*)$") {
|
|
19
|
+
$key = $matches[1].Trim()
|
|
20
|
+
$value = $matches[2].Trim()
|
|
21
|
+
[Environment]::SetEnvironmentVariable($key, $value)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
Write-Warning "⚠️ No .env file found. Using defaults."
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Validate required environment variables
|
|
29
|
+
$requiredVars = @("CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID")
|
|
30
|
+
$missingVars = @()
|
|
31
|
+
|
|
32
|
+
foreach ($var in $requiredVars) {
|
|
33
|
+
if (-not [Environment]::GetEnvironmentVariable($var)) {
|
|
34
|
+
$missingVars += $var
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if ($missingVars.Count -gt 0) {
|
|
39
|
+
Write-Error "❌ Missing required environment variables: $($missingVars -join ', ')"
|
|
40
|
+
Write-Host "Please set these in your .env file or environment." -ForegroundColor Red
|
|
41
|
+
exit 1
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Set deployment environment
|
|
45
|
+
$env:CLOUDFLARE_API_TOKEN = [Environment]::GetEnvironmentVariable("CLOUDFLARE_API_TOKEN")
|
|
46
|
+
$env:CLOUDFLARE_ACCOUNT_ID = [Environment]::GetEnvironmentVariable("CLOUDFLARE_ACCOUNT_ID")
|
|
47
|
+
|
|
48
|
+
if ($Verbose) {
|
|
49
|
+
Write-Host "🔧 Environment: $Environment" -ForegroundColor Blue
|
|
50
|
+
Write-Host "📦 Service: {{SERVICE_NAME}}" -ForegroundColor Blue
|
|
51
|
+
Write-Host "🌐 Domain: {{DOMAIN_NAME}}" -ForegroundColor Blue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Check if wrangler is available
|
|
55
|
+
try {
|
|
56
|
+
$wranglerVersion = & wrangler --version 2>$null
|
|
57
|
+
Write-Host "✅ Wrangler version: $wranglerVersion" -ForegroundColor Green
|
|
58
|
+
} catch {
|
|
59
|
+
Write-Error "❌ Wrangler CLI not found. Please install: npm install -g wrangler"
|
|
60
|
+
exit 1
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Validate static files exist
|
|
64
|
+
if (-not (Test-Path "public")) {
|
|
65
|
+
Write-Error "❌ Public directory not found. Please ensure static files are in ./public/"
|
|
66
|
+
exit 1
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
$fileCount = (Get-ChildItem "public" -Recurse -File).Count
|
|
70
|
+
Write-Host "📁 Found $fileCount static files in public directory" -ForegroundColor Blue
|
|
71
|
+
|
|
72
|
+
# Dry run mode
|
|
73
|
+
if ($DryRun) {
|
|
74
|
+
Write-Host "🏃 Dry run mode - would execute:" -ForegroundColor Yellow
|
|
75
|
+
Write-Host " wrangler deploy --env $Environment" -ForegroundColor Gray
|
|
76
|
+
Write-Host ""
|
|
77
|
+
Write-Host "✅ Dry run complete - no changes made" -ForegroundColor Green
|
|
78
|
+
exit 0
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Deploy to Cloudflare
|
|
82
|
+
Write-Host "🚀 Starting deployment..." -ForegroundColor Cyan
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
if ($Verbose) {
|
|
86
|
+
& wrangler deploy --env $Environment
|
|
87
|
+
} else {
|
|
88
|
+
& wrangler deploy --env $Environment 2>$null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if ($LASTEXITCODE -eq 0) {
|
|
92
|
+
Write-Host "" -ForegroundColor Green
|
|
93
|
+
Write-Host "✅ Deployment successful!" -ForegroundColor Green
|
|
94
|
+
Write-Host "🌐 Your site is now live at: https://{{DOMAIN_NAME}}" -ForegroundColor Cyan
|
|
95
|
+
Write-Host ""
|
|
96
|
+
|
|
97
|
+
# Health check
|
|
98
|
+
Write-Host "🔍 Running health check..." -ForegroundColor Yellow
|
|
99
|
+
try {
|
|
100
|
+
$healthResponse = Invoke-WebRequest -Uri "https://{{DOMAIN_NAME}}/health" -TimeoutSec 10 -UseBasicParsing
|
|
101
|
+
if ($healthResponse.StatusCode -eq 200) {
|
|
102
|
+
Write-Host "✅ Health check passed" -ForegroundColor Green
|
|
103
|
+
} else {
|
|
104
|
+
Write-Warning "⚠️ Health check returned status: $($healthResponse.StatusCode)"
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
Write-Warning "⚠️ Health check failed: $($_.Exception.Message)"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
} else {
|
|
111
|
+
Write-Error "❌ Deployment failed with exit code: $LASTEXITCODE"
|
|
112
|
+
exit $LASTEXITCODE
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
} catch {
|
|
116
|
+
Write-Error "❌ Deployment error: $($_.Exception.Message)"
|
|
117
|
+
exit 1
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Write-Host ""
|
|
121
|
+
Write-Host "🎉 {{SERVICE_DISPLAY_NAME}} deployment complete!" -ForegroundColor Green
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Setup script for {{SERVICE_NAME}}
|
|
2
|
+
# Generated by Clodo Framework
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[switch]$Force,
|
|
6
|
+
[switch]$Verbose
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
Write-Host "🔧 Setting up {{SERVICE_DISPLAY_NAME}}" -ForegroundColor Cyan
|
|
10
|
+
Write-Host "Generated by Clodo Framework" -ForegroundColor Gray
|
|
11
|
+
Write-Host ""
|
|
12
|
+
|
|
13
|
+
# Check if already set up
|
|
14
|
+
if ((Test-Path ".env") -and -not $Force) {
|
|
15
|
+
Write-Warning "⚠️ .env file already exists. Use -Force to overwrite."
|
|
16
|
+
Write-Host "Current configuration:" -ForegroundColor Yellow
|
|
17
|
+
Get-Content ".env" | Select-String "^[^#]" | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
|
|
18
|
+
exit 0
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Create .env file from template
|
|
22
|
+
Write-Host "📋 Creating .env configuration file..." -ForegroundColor Yellow
|
|
23
|
+
|
|
24
|
+
$envContent = @"
|
|
25
|
+
# Deployment Configuration for {{SERVICE_NAME}}
|
|
26
|
+
# Generated by Clodo Framework on $(Get-Date -Format "yyyy-MM-dd")
|
|
27
|
+
|
|
28
|
+
# ============================================
|
|
29
|
+
# Core Customer Identity
|
|
30
|
+
# ============================================
|
|
31
|
+
CUSTOMER_ID={{SERVICE_NAME}}
|
|
32
|
+
CUSTOMER_NAME={{SERVICE_NAME}}
|
|
33
|
+
ENVIRONMENT=development
|
|
34
|
+
|
|
35
|
+
# ============================================
|
|
36
|
+
# Cloudflare Configuration
|
|
37
|
+
# ============================================
|
|
38
|
+
CLOUDFLARE_ACCOUNT_ID=your_account_id_here
|
|
39
|
+
CLOUDFLARE_ZONE_ID=your_zone_id_here
|
|
40
|
+
CLOUDFLARE_API_TOKEN=your_api_token_here
|
|
41
|
+
|
|
42
|
+
# ============================================
|
|
43
|
+
# Service Configuration
|
|
44
|
+
# ============================================
|
|
45
|
+
SERVICE_NAME={{SERVICE_NAME}}
|
|
46
|
+
SERVICE_TYPE=static-site
|
|
47
|
+
DISPLAY_NAME={{SERVICE_DISPLAY_NAME}}
|
|
48
|
+
DESCRIPTION=A static site service powered by Clodo Framework
|
|
49
|
+
|
|
50
|
+
# ============================================
|
|
51
|
+
# Domain Configuration
|
|
52
|
+
# ============================================
|
|
53
|
+
DOMAIN={{DOMAIN_NAME}}
|
|
54
|
+
CUSTOMER_DOMAIN={{DOMAIN_NAME}}
|
|
55
|
+
DEPLOYMENT_URL=https://{{DOMAIN_NAME}}
|
|
56
|
+
API_DOMAIN=https://{{DOMAIN_NAME}}
|
|
57
|
+
|
|
58
|
+
# ============================================
|
|
59
|
+
# Static-Site Configuration
|
|
60
|
+
# ============================================
|
|
61
|
+
PUBLIC_DIR=public
|
|
62
|
+
INDEX_FILE=index.html
|
|
63
|
+
ERROR_FILE=404.html
|
|
64
|
+
CACHE_CONTROL=public, max-age=31536000, immutable
|
|
65
|
+
SPA_FALLBACK=true
|
|
66
|
+
CLEAN_URLS=true
|
|
67
|
+
COMPRESS_TEXT=true
|
|
68
|
+
CORS_ENABLED=true
|
|
69
|
+
|
|
70
|
+
# ============================================
|
|
71
|
+
# Additional Configuration
|
|
72
|
+
# ============================================
|
|
73
|
+
HEALTH_CHECK_PATH=/health
|
|
74
|
+
API_BASE_PATH=/
|
|
75
|
+
LOG_LEVEL=info
|
|
76
|
+
NODE_COMPATIBILITY=v18
|
|
77
|
+
|
|
78
|
+
# ============================================
|
|
79
|
+
# Custom Environment Variables
|
|
80
|
+
# ============================================
|
|
81
|
+
# Add your custom environment variables here
|
|
82
|
+
# CUSTOM_VAR=value
|
|
83
|
+
"@
|
|
84
|
+
|
|
85
|
+
if ($Force -or -not (Test-Path ".env")) {
|
|
86
|
+
$envContent | Out-File -FilePath ".env" -Encoding UTF8
|
|
87
|
+
Write-Host "✅ Created .env file" -ForegroundColor Green
|
|
88
|
+
} else {
|
|
89
|
+
Write-Host "ℹ️ .env file already exists, skipping creation" -ForegroundColor Blue
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Check Node.js version
|
|
93
|
+
Write-Host "🔍 Checking Node.js version..." -ForegroundColor Yellow
|
|
94
|
+
try {
|
|
95
|
+
$nodeVersion = & node --version
|
|
96
|
+
Write-Host "✅ Node.js: $nodeVersion" -ForegroundColor Green
|
|
97
|
+
|
|
98
|
+
# Check if version is compatible
|
|
99
|
+
$versionNumber = $nodeVersion -replace '^v', ''
|
|
100
|
+
$majorVersion = [int]($versionNumber -split '\.')[0]
|
|
101
|
+
|
|
102
|
+
if ($majorVersion -lt 18) {
|
|
103
|
+
Write-Warning "⚠️ Node.js version $nodeVersion detected. Clodo Framework recommends Node.js 18+"
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
Write-Error "❌ Node.js not found. Please install Node.js 18+ from https://nodejs.org/"
|
|
107
|
+
exit 1
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Check npm
|
|
111
|
+
try {
|
|
112
|
+
$npmVersion = & npm --version
|
|
113
|
+
Write-Host "✅ npm: $npmVersion" -ForegroundColor Green
|
|
114
|
+
} catch {
|
|
115
|
+
Write-Warning "⚠️ npm not found. It should be included with Node.js."
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Install dependencies
|
|
119
|
+
if (Test-Path "package.json") {
|
|
120
|
+
Write-Host "📦 Installing dependencies..." -ForegroundColor Yellow
|
|
121
|
+
try {
|
|
122
|
+
if ($Verbose) {
|
|
123
|
+
& npm install
|
|
124
|
+
} else {
|
|
125
|
+
& npm install 2>$null
|
|
126
|
+
}
|
|
127
|
+
Write-Host "✅ Dependencies installed" -ForegroundColor Green
|
|
128
|
+
} catch {
|
|
129
|
+
Write-Error "❌ Failed to install dependencies: $($_.Exception.Message)"
|
|
130
|
+
exit 1
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
Write-Warning "⚠️ package.json not found. Dependencies not installed."
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Check Wrangler CLI
|
|
137
|
+
Write-Host "🔧 Checking Wrangler CLI..." -ForegroundColor Yellow
|
|
138
|
+
try {
|
|
139
|
+
$wranglerVersion = & npx wrangler --version 2>$null
|
|
140
|
+
Write-Host "✅ Wrangler: $wranglerVersion" -ForegroundColor Green
|
|
141
|
+
} catch {
|
|
142
|
+
Write-Host "📥 Installing Wrangler CLI..." -ForegroundColor Yellow
|
|
143
|
+
try {
|
|
144
|
+
& npm install wrangler --save-dev
|
|
145
|
+
Write-Host "✅ Wrangler CLI installed" -ForegroundColor Green
|
|
146
|
+
} catch {
|
|
147
|
+
Write-Warning "⚠️ Failed to install Wrangler CLI. You may need to install it manually: npm install -g wrangler"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Validate static files
|
|
152
|
+
Write-Host "📁 Validating static files..." -ForegroundColor Yellow
|
|
153
|
+
$requiredFiles = @("public/index.html", "public/styles.css", "public/app.js")
|
|
154
|
+
$missingFiles = @()
|
|
155
|
+
|
|
156
|
+
foreach ($file in $requiredFiles) {
|
|
157
|
+
if (-not (Test-Path $file)) {
|
|
158
|
+
$missingFiles += $file
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if ($missingFiles.Count -eq 0) {
|
|
163
|
+
Write-Host "✅ All required static files present" -ForegroundColor Green
|
|
164
|
+
} else {
|
|
165
|
+
Write-Warning "⚠️ Missing static files: $($missingFiles -join ', ')"
|
|
166
|
+
Write-Host "These will be created when you run the setup." -ForegroundColor Gray
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# Setup complete
|
|
170
|
+
Write-Host "" -ForegroundColor Green
|
|
171
|
+
Write-Host "🎉 Setup complete for {{SERVICE_DISPLAY_NAME}}!" -ForegroundColor Green
|
|
172
|
+
Write-Host "" -ForegroundColor Cyan
|
|
173
|
+
Write-Host "Next steps:" -ForegroundColor White
|
|
174
|
+
Write-Host " 1. Edit .env with your Cloudflare credentials" -ForegroundColor White
|
|
175
|
+
Write-Host " 2. Customize static files in public/" -ForegroundColor White
|
|
176
|
+
Write-Host " 3. Run 'npm run dev' to start development" -ForegroundColor White
|
|
177
|
+
Write-Host " 4. Run 'npm run deploy' to deploy to production" -ForegroundColor White
|
|
178
|
+
Write-Host ""
|
|
179
|
+
Write-Host "📚 For help, see README.md or visit https://clodo.dev/docs" -ForegroundColor Gray
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain configuration for {{SERVICE_DISPLAY_NAME}}
|
|
3
|
+
* Generated by Clodo Framework
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const domains = {
|
|
7
|
+
// Primary domain for this service
|
|
8
|
+
primary: '{{DOMAIN_NAME}}',
|
|
9
|
+
|
|
10
|
+
// Alternative domains (add as needed)
|
|
11
|
+
alternatives: [
|
|
12
|
+
// 'www.{{DOMAIN_NAME}}',
|
|
13
|
+
// 'staging.{{DOMAIN_NAME}}'
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
// Environment-specific domain mappings
|
|
17
|
+
environments: {
|
|
18
|
+
development: '{{SERVICE_NAME}}-dev.{{WORKERS_DEV_DOMAIN}}',
|
|
19
|
+
staging: 'staging.{{DOMAIN_NAME}}',
|
|
20
|
+
production: '{{DOMAIN_NAME}}'
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// Routing configuration
|
|
24
|
+
routing: {
|
|
25
|
+
// SPA fallback - serve index.html for client-side routing
|
|
26
|
+
spaFallback: true,
|
|
27
|
+
spaFallbackPath: '/index.html',
|
|
28
|
+
|
|
29
|
+
// Clean URLs - serve .html files without extension
|
|
30
|
+
cleanUrls: true,
|
|
31
|
+
|
|
32
|
+
// Trailing slash handling
|
|
33
|
+
trailingSlash: false
|
|
34
|
+
}
|
|
35
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { initializeService, createFeatureGuard, COMMON_FEATURES } from '@tamyla/clodo-framework';
|
|
2
|
+
import { domains } from './config/domains.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* {{SERVICE_DISPLAY_NAME}} - Clodo Framework Static Site Service
|
|
6
|
+
*
|
|
7
|
+
* Generated on: {{CURRENT_DATE}}
|
|
8
|
+
* Service Type: static-site
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Static file serving with Workers Sites
|
|
12
|
+
* - MIME type detection
|
|
13
|
+
* - Cache headers for optimal performance
|
|
14
|
+
* - SPA fallback support
|
|
15
|
+
* - CORS support
|
|
16
|
+
* - Compression
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
async fetch(request, env, ctx) {
|
|
21
|
+
try {
|
|
22
|
+
// Initialize service with Clodo Framework
|
|
23
|
+
const service = initializeService(env, domains);
|
|
24
|
+
|
|
25
|
+
// Log request (if logging is enabled)
|
|
26
|
+
if (service.features.includes(COMMON_FEATURES.LOGGING)) {
|
|
27
|
+
console.log(`${request.method} ${request.url} - ${service.domain} (${service.environment})`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const url = new URL(request.url);
|
|
31
|
+
|
|
32
|
+
// Health check endpoint
|
|
33
|
+
if (url.pathname === '/health') {
|
|
34
|
+
return new Response(JSON.stringify({
|
|
35
|
+
status: 'healthy',
|
|
36
|
+
service: '{{SERVICE_NAME}}',
|
|
37
|
+
version: '1.0.0',
|
|
38
|
+
type: 'static-site',
|
|
39
|
+
features: service.features,
|
|
40
|
+
domain: service.domain,
|
|
41
|
+
environment: service.environment,
|
|
42
|
+
timestamp: new Date().toISOString()
|
|
43
|
+
}), {
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Cache-Control': 'no-cache'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Service information endpoint
|
|
52
|
+
if (url.pathname === '/info') {
|
|
53
|
+
return new Response(JSON.stringify({
|
|
54
|
+
name: '{{SERVICE_NAME}}',
|
|
55
|
+
displayName: '{{SERVICE_DISPLAY_NAME}}',
|
|
56
|
+
type: 'static-site',
|
|
57
|
+
version: '1.0.0',
|
|
58
|
+
framework: 'Clodo Framework',
|
|
59
|
+
staticConfig: {
|
|
60
|
+
publicDir: env.PUBLIC_DIR || 'public',
|
|
61
|
+
indexFile: env.INDEX_FILE || 'index.html',
|
|
62
|
+
errorFile: env.ERROR_FILE || '404.html',
|
|
63
|
+
spaFallback: env.SPA_FALLBACK !== 'false',
|
|
64
|
+
cleanUrls: env.CLEAN_URLS !== 'false',
|
|
65
|
+
compressText: env.COMPRESS_TEXT !== 'false',
|
|
66
|
+
corsEnabled: env.CORS_ENABLED !== 'false'
|
|
67
|
+
},
|
|
68
|
+
domain: service.domain,
|
|
69
|
+
environment: service.environment
|
|
70
|
+
}), {
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
'Cache-Control': 'no-cache'
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Handle CORS preflight requests
|
|
79
|
+
if (request.method === 'OPTIONS' && env.CORS_ENABLED !== 'false') {
|
|
80
|
+
return new Response(null, {
|
|
81
|
+
status: 204,
|
|
82
|
+
headers: {
|
|
83
|
+
'Access-Control-Allow-Origin': '*',
|
|
84
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
85
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
86
|
+
'Access-Control-Max-Age': '86400'
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// For static sites, let Workers Sites handle the file serving
|
|
92
|
+
// This worker mainly adds custom logic and health checks
|
|
93
|
+
// The [site] configuration in wrangler.toml handles the actual file serving
|
|
94
|
+
|
|
95
|
+
// Add CORS headers to all responses if enabled
|
|
96
|
+
const corsHeaders = env.CORS_ENABLED !== 'false' ? {
|
|
97
|
+
'Access-Control-Allow-Origin': '*',
|
|
98
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
99
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
|
|
100
|
+
} : {};
|
|
101
|
+
|
|
102
|
+
// Let Workers Sites handle the request
|
|
103
|
+
// This will serve static files from the public directory
|
|
104
|
+
const page = await env.ASSETS.fetch(request);
|
|
105
|
+
|
|
106
|
+
// Clone the response to add custom headers
|
|
107
|
+
const response = new Response(page.body, page);
|
|
108
|
+
|
|
109
|
+
// Add CORS headers if enabled
|
|
110
|
+
if (env.CORS_ENABLED !== 'false') {
|
|
111
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
112
|
+
response.headers.set(key, value);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Add compression if enabled and response is text-based
|
|
117
|
+
if (env.COMPRESS_TEXT !== 'false' && shouldCompress(response)) {
|
|
118
|
+
response.headers.set('Content-Encoding', 'gzip');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return response;
|
|
122
|
+
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error('Static site worker error:', error);
|
|
125
|
+
|
|
126
|
+
// Return a basic error response
|
|
127
|
+
return new Response(JSON.stringify({
|
|
128
|
+
error: 'Internal Server Error',
|
|
129
|
+
message: error.message,
|
|
130
|
+
timestamp: new Date().toISOString()
|
|
131
|
+
}), {
|
|
132
|
+
status: 500,
|
|
133
|
+
headers: {
|
|
134
|
+
'Content-Type': 'application/json',
|
|
135
|
+
'Cache-Control': 'no-cache'
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Determine if a response should be compressed
|
|
144
|
+
* @param {Response} response - The response to check
|
|
145
|
+
* @returns {boolean} - Whether to compress
|
|
146
|
+
*/
|
|
147
|
+
function shouldCompress(response) {
|
|
148
|
+
const contentType = response.headers.get('Content-Type') || '';
|
|
149
|
+
return contentType.includes('text/') ||
|
|
150
|
+
contentType.includes('application/json') ||
|
|
151
|
+
contentType.includes('application/javascript') ||
|
|
152
|
+
contentType.includes('application/xml');
|
|
153
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name = "{{SERVICE_NAME}}-dev"
|
|
2
|
+
main = "src/worker/index.js"
|
|
3
|
+
compatibility_date = "{{CURRENT_DATE}}"
|
|
4
|
+
|
|
5
|
+
# Workers Sites configuration for static file serving
|
|
6
|
+
[site]
|
|
7
|
+
bucket = "./public"
|
|
8
|
+
include = ["**/*"]
|
|
9
|
+
exclude = [
|
|
10
|
+
"node_modules/**",
|
|
11
|
+
".git/**",
|
|
12
|
+
".DS_Store",
|
|
13
|
+
"*.log",
|
|
14
|
+
"wrangler.toml",
|
|
15
|
+
"package.json",
|
|
16
|
+
"package-lock.json"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[env.development]
|
|
20
|
+
name = "{{SERVICE_NAME}}-dev"
|
|
21
|
+
|
|
22
|
+
[env.staging]
|
|
23
|
+
name = "{{SERVICE_NAME}}-staging"
|
|
24
|
+
|
|
25
|
+
[env.production]
|
|
26
|
+
name = "{{SERVICE_NAME}}"
|
|
27
|
+
|
|
28
|
+
# Environment variables
|
|
29
|
+
[vars]
|
|
30
|
+
DOMAIN_NAME = "{{SERVICE_NAME}}.{{DOMAIN_NAME}}"
|
|
31
|
+
ENVIRONMENT = "development"
|
|
32
|
+
SERVICE_NAME = "{{SERVICE_NAME}}"
|
|
33
|
+
SERVICE_TYPE = "static-site"
|
|
34
|
+
PUBLIC_DIR = "public"
|
|
35
|
+
INDEX_FILE = "index.html"
|
|
36
|
+
ERROR_FILE = "404.html"
|
|
37
|
+
SPA_FALLBACK = "true"
|
|
38
|
+
CLEAN_URLS = "true"
|
|
39
|
+
COMPRESS_TEXT = "true"
|
|
40
|
+
CORS_ENABLED = "true"
|
|
41
|
+
|
|
42
|
+
# Add your custom environment variables here
|
|
43
|
+
# CUSTOM_VAR = "value"
|