@tamyla/clodo-framework 3.1.21 → 3.1.22
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 +9 -0
- package/README.md +53 -0
- package/dist/bin/clodo-service.js +47 -15
- package/dist/bin/commands/deploy.js +115 -83
- package/dist/bin/commands/helpers/deployment-ui.js +138 -0
- package/dist/bin/commands/helpers/deployment-verification.js +251 -0
- package/dist/bin/commands/helpers/error-recovery.js +80 -0
- package/dist/bin/commands/helpers/resource-detection.js +113 -0
- package/dist/bin/commands/validate.js +1 -1
- package/dist/bin/security/security-cli.js +1 -1
- package/dist/bin/shared/cache/configuration-cache.js +82 -0
- package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
- package/dist/bin/shared/cloudflare/index.js +1 -1
- package/dist/bin/shared/cloudflare/ops.js +6 -4
- package/dist/bin/shared/config/ConfigurationManager.js +23 -1
- package/dist/bin/shared/config/command-config-manager.js +19 -3
- package/dist/bin/shared/config/index.js +1 -1
- package/dist/bin/shared/deployment/credential-collector.js +30 -7
- package/dist/bin/shared/deployment/index.js +2 -2
- package/dist/bin/shared/deployment/rollback-manager.js +4 -520
- package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
- package/dist/bin/shared/deployment/validator.js +40 -10
- package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
- package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
- package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
- package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
- package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
- package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
- package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
- package/dist/bin/shared/error-handling/error-classifier.js +46 -0
- package/dist/bin/shared/monitoring/health-checker.js +129 -1
- package/dist/bin/shared/monitoring/memory-manager.js +17 -6
- package/dist/bin/shared/routing/domain-router.js +1 -1
- package/dist/bin/shared/utils/deployment-validator.js +97 -0
- package/dist/bin/shared/utils/formatters.js +10 -0
- package/dist/bin/shared/utils/index.js +13 -1
- package/dist/bin/shared/utils/interactive-prompts.js +34 -18
- package/dist/bin/shared/utils/progress-manager.js +2 -2
- package/dist/bin/shared/utils/progress-spinner.js +53 -0
- package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
- package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/patterns/insecure-patterns.js +1 -1
- package/dist/utils/constants.js +102 -0
- package/dist/utils/deployment/wrangler-config-manager.js +215 -48
- package/dist/utils/framework-config.js +2 -2
- package/dist/utils/interactive-prompts.js +10 -59
- package/package.json +16 -8
- package/dist/bin/clodo-service-old.js +0 -868
- package/dist/bin/clodo-service-test.js +0 -10
- package/dist/bin/commands/assess.js +0 -91
- package/dist/bin/commands/create.js +0 -77
- package/dist/bin/commands/diagnose.js +0 -83
- package/dist/bin/commands/helpers.js +0 -138
- package/dist/bin/commands/update.js +0 -75
- package/dist/bin/database/deployment-db-manager.js +0 -423
- package/dist/bin/database/enterprise-db-manager.js +0 -457
- package/dist/bin/database/wrangler-d1-manager.js +0 -685
- package/dist/bin/deployment/enterprise-deploy.js +0 -877
- package/dist/bin/deployment/master-deploy.js +0 -1376
- package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
- package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
- package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
- package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
- package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
- package/dist/bin/deployment/modules/ValidationManager.js +0 -342
- package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/bin/deployment/test-interactive-utils.js +0 -66
- package/dist/bin/portfolio/portfolio-manager.js +0 -487
- package/dist/bin/service-management/create-service.js +0 -122
- package/dist/bin/service-management/init-service.js +0 -79
- package/dist/config/customers.js +0 -623
- package/dist/config/domains.js +0 -186
- package/dist/config/index.js +0 -6
- package/dist/database/database-orchestrator.js +0 -795
- package/dist/database/index.js +0 -4
- package/dist/deployment/index.js +0 -11
- package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/deployment/orchestration/index.js +0 -17
- package/dist/deployment/rollback-manager.js +0 -36
- package/dist/deployment/wrangler-deployer.js +0 -640
- package/dist/handlers/GenericRouteHandler.js +0 -532
- package/dist/migration/MigrationAdapters.js +0 -562
- package/dist/modules/ModuleManager.js +0 -668
- package/dist/modules/security.js +0 -96
- package/dist/orchestration/cross-domain-coordinator.js +0 -1083
- package/dist/orchestration/index.js +0 -5
- package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
- package/dist/orchestration/modules/DomainResolver.js +0 -198
- package/dist/orchestration/modules/StateManager.js +0 -332
- package/dist/orchestration/multi-domain-orchestrator.js +0 -724
- package/dist/routing/EnhancedRouter.js +0 -158
- package/dist/schema/SchemaManager.js +0 -778
- package/dist/service-management/ConfirmationEngine.js +0 -412
- package/dist/service-management/ErrorTracker.js +0 -299
- package/dist/service-management/GenerationEngine.js +0 -447
- package/dist/service-management/InputCollector.js +0 -619
- package/dist/service-management/ServiceCreator.js +0 -265
- package/dist/service-management/ServiceInitializer.js +0 -453
- package/dist/service-management/ServiceOrchestrator.js +0 -633
- package/dist/service-management/generators/BaseGenerator.js +0 -233
- package/dist/service-management/generators/GeneratorRegistry.js +0 -254
- package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
- package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
- package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
- package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
- package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
- package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
- package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
- package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
- package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
- package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
- package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
- package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
- package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
- package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
- package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
- package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
- package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
- package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
- package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
- package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
- package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
- package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
- package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
- package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
- package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
- package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
- package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
- package/dist/service-management/generators/utils/FileWriter.js +0 -179
- package/dist/service-management/generators/utils/PathResolver.js +0 -157
- package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
- package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
- package/dist/service-management/generators/utils/index.js +0 -18
- package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
- package/dist/service-management/handlers/GenerationHandler.js +0 -80
- package/dist/service-management/handlers/InputHandler.js +0 -59
- package/dist/service-management/handlers/ValidationHandler.js +0 -203
- package/dist/service-management/index.js +0 -14
- package/dist/service-management/routing/DomainRouteMapper.js +0 -311
- package/dist/service-management/routing/RouteGenerator.js +0 -266
- package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
- package/dist/service-management/routing/index.js +0 -14
- package/dist/service-management/services/DirectoryStructureService.js +0 -56
- package/dist/service-management/services/GenerationCoordinator.js +0 -208
- package/dist/service-management/services/GeneratorRegistry.js +0 -174
- package/dist/services/GenericDataService.js +0 -501
- package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
- package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
- package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
- package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
- package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
- package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
- package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
- package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
- package/dist/ui-structures/reference/service-manifest-template.json +0 -342
- package/dist/version/VersionDetector.js +0 -723
- package/dist/worker/index.js +0 -4
- package/dist/worker/integration.js +0 -351
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { BaseGenerator } from '../BaseGenerator.js';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { writeFileSync } from 'fs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Docker Compose Generator
|
|
7
|
-
* Generates docker-compose.yml for local development environment
|
|
8
|
-
*/
|
|
9
|
-
export class DockerComposeGenerator extends BaseGenerator {
|
|
10
|
-
/**
|
|
11
|
-
* Generate docker-compose.yml file
|
|
12
|
-
* @param {Object} context - Generation context
|
|
13
|
-
* @returns {Promise<string>} Path to generated docker-compose.yml file
|
|
14
|
-
*/
|
|
15
|
-
async generate(context) {
|
|
16
|
-
const {
|
|
17
|
-
coreInputs,
|
|
18
|
-
confirmedValues,
|
|
19
|
-
servicePath
|
|
20
|
-
} = this.extractContext(context);
|
|
21
|
-
if (!this.shouldGenerate(context)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const dockerComposeContent = this._generateDockerComposeContent(coreInputs, confirmedValues);
|
|
25
|
-
const filePath = join(servicePath, 'docker-compose.yml');
|
|
26
|
-
writeFileSync(filePath, dockerComposeContent, 'utf8');
|
|
27
|
-
return filePath;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Generate docker-compose.yml content
|
|
32
|
-
* @private
|
|
33
|
-
*/
|
|
34
|
-
_generateDockerComposeContent(coreInputs, confirmedValues) {
|
|
35
|
-
return `version: '3.8'
|
|
36
|
-
|
|
37
|
-
services:
|
|
38
|
-
${coreInputs.serviceName}:
|
|
39
|
-
build:
|
|
40
|
-
context: .
|
|
41
|
-
dockerfile: Dockerfile
|
|
42
|
-
ports:
|
|
43
|
-
- "8787:8787"
|
|
44
|
-
environment:
|
|
45
|
-
- NODE_ENV=development
|
|
46
|
-
- SERVICE_NAME=${coreInputs.serviceName}
|
|
47
|
-
- SERVICE_TYPE=${coreInputs.serviceType}
|
|
48
|
-
- ENVIRONMENT=development
|
|
49
|
-
volumes:
|
|
50
|
-
- .:/app
|
|
51
|
-
- /app/node_modules
|
|
52
|
-
command: npm run dev
|
|
53
|
-
|
|
54
|
-
${coreInputs.serviceName}-db:
|
|
55
|
-
image: cloudflare/d1
|
|
56
|
-
ports:
|
|
57
|
-
- "8788:8787"
|
|
58
|
-
environment:
|
|
59
|
-
- DATABASE_NAME=${confirmedValues.databaseName}
|
|
60
|
-
volumes:
|
|
61
|
-
- .wrangler:/data
|
|
62
|
-
`;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Determine if generator should run
|
|
67
|
-
*/
|
|
68
|
-
shouldGenerate(context) {
|
|
69
|
-
return true; // Always generate docker-compose.yml
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { BaseGenerator } from '../BaseGenerator.js';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { writeFileSync } from 'fs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Gitignore Generator
|
|
7
|
-
* Generates comprehensive .gitignore file for Cloudflare Workers projects
|
|
8
|
-
*/
|
|
9
|
-
export class GitignoreGenerator extends BaseGenerator {
|
|
10
|
-
/**
|
|
11
|
-
* Generate .gitignore file
|
|
12
|
-
* @param {Object} context - Generation context
|
|
13
|
-
* @returns {Promise<string>} Path to generated .gitignore file
|
|
14
|
-
*/
|
|
15
|
-
async generate(context) {
|
|
16
|
-
const {
|
|
17
|
-
coreInputs,
|
|
18
|
-
confirmedValues,
|
|
19
|
-
servicePath
|
|
20
|
-
} = this.extractContext(context);
|
|
21
|
-
if (!this.shouldGenerate(context)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const gitignoreContent = this._generateGitignoreContent(coreInputs, confirmedValues);
|
|
25
|
-
const filePath = join(servicePath, '.gitignore');
|
|
26
|
-
writeFileSync(filePath, gitignoreContent, 'utf8');
|
|
27
|
-
return filePath;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Generate .gitignore content
|
|
32
|
-
* @private
|
|
33
|
-
*/
|
|
34
|
-
_generateGitignoreContent(coreInputs, confirmedValues) {
|
|
35
|
-
return `# Dependencies
|
|
36
|
-
node_modules/
|
|
37
|
-
npm-debug.log*
|
|
38
|
-
yarn-debug.log*
|
|
39
|
-
yarn-error.log*
|
|
40
|
-
|
|
41
|
-
# Environment variables
|
|
42
|
-
.env
|
|
43
|
-
.env.local
|
|
44
|
-
.env.development.local
|
|
45
|
-
.env.test.local
|
|
46
|
-
.env.production.local
|
|
47
|
-
|
|
48
|
-
# Build outputs
|
|
49
|
-
dist/
|
|
50
|
-
build/
|
|
51
|
-
coverage/
|
|
52
|
-
|
|
53
|
-
# Logs
|
|
54
|
-
logs/
|
|
55
|
-
*.log
|
|
56
|
-
npm-debug.log*
|
|
57
|
-
yarn-debug.log*
|
|
58
|
-
yarn-error.log*
|
|
59
|
-
lerna-debug.log*
|
|
60
|
-
|
|
61
|
-
# Runtime data
|
|
62
|
-
pids/
|
|
63
|
-
*.pid
|
|
64
|
-
*.seed
|
|
65
|
-
*.pid.lock
|
|
66
|
-
|
|
67
|
-
# Coverage directory used by tools like istanbul
|
|
68
|
-
coverage/
|
|
69
|
-
*.lcov
|
|
70
|
-
|
|
71
|
-
# nyc test coverage
|
|
72
|
-
.nyc_output/
|
|
73
|
-
|
|
74
|
-
# Dependency directories
|
|
75
|
-
jspm_packages/
|
|
76
|
-
|
|
77
|
-
# Optional npm cache directory
|
|
78
|
-
.npm
|
|
79
|
-
|
|
80
|
-
# Optional eslint cache
|
|
81
|
-
.eslintcache
|
|
82
|
-
|
|
83
|
-
# Microbundle cache
|
|
84
|
-
.rpt2_cache/
|
|
85
|
-
.rts2_cache_cjs/
|
|
86
|
-
.rts2_cache_es/
|
|
87
|
-
.rts2_cache_umd/
|
|
88
|
-
|
|
89
|
-
# Optional REPL history
|
|
90
|
-
.node_repl_history
|
|
91
|
-
|
|
92
|
-
# Output of 'npm pack'
|
|
93
|
-
*.tgz
|
|
94
|
-
|
|
95
|
-
# Yarn Integrity file
|
|
96
|
-
.yarn-integrity
|
|
97
|
-
|
|
98
|
-
# parcel-bundler cache (https://parceljs.org/)
|
|
99
|
-
.cache
|
|
100
|
-
.parcel-cache
|
|
101
|
-
|
|
102
|
-
# Next.js build / generate output
|
|
103
|
-
.next
|
|
104
|
-
|
|
105
|
-
# Nuxt.js build / generate output
|
|
106
|
-
.nuxt
|
|
107
|
-
dist
|
|
108
|
-
|
|
109
|
-
# Gatsby files
|
|
110
|
-
.cache/
|
|
111
|
-
public
|
|
112
|
-
|
|
113
|
-
# Storybook build outputs
|
|
114
|
-
.out
|
|
115
|
-
.storybook-out
|
|
116
|
-
|
|
117
|
-
# Temporary folders
|
|
118
|
-
tmp/
|
|
119
|
-
temp/
|
|
120
|
-
|
|
121
|
-
# Editor directories and files
|
|
122
|
-
.vscode/*
|
|
123
|
-
!.vscode/extensions.json
|
|
124
|
-
.idea
|
|
125
|
-
.DS_Store
|
|
126
|
-
*.suo
|
|
127
|
-
*.ntvs*
|
|
128
|
-
*.njsproj
|
|
129
|
-
*.sln
|
|
130
|
-
*.sw?
|
|
131
|
-
|
|
132
|
-
# Cloudflare
|
|
133
|
-
.wrangler/
|
|
134
|
-
`;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Determine if generator should run
|
|
139
|
-
*/
|
|
140
|
-
shouldGenerate(context) {
|
|
141
|
-
return true; // Always generate .gitignore
|
|
142
|
-
}
|
|
143
|
-
}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FileWriter - Handles atomic file writing operations
|
|
3
|
-
*
|
|
4
|
-
* Provides safe file writing with directory creation, overwrite protection,
|
|
5
|
-
* and atomic operations.
|
|
6
|
-
*
|
|
7
|
-
* NOTE: This class uses Node.js filesystem APIs and is designed for
|
|
8
|
-
* build-time usage during service generation, not runtime in Cloudflare Workers.
|
|
9
|
-
*/
|
|
10
|
-
import { promises as fs } from 'fs';
|
|
11
|
-
import path from 'path';
|
|
12
|
-
export class FileWriter {
|
|
13
|
-
/**
|
|
14
|
-
* Create a new file writer instance
|
|
15
|
-
* @param {Object} options - Configuration options
|
|
16
|
-
* @param {string} options.basePath - Base path for all file operations
|
|
17
|
-
* @param {boolean} options.dryRun - If true, simulate writes without actually writing (default: false)
|
|
18
|
-
*/
|
|
19
|
-
constructor(options = {}) {
|
|
20
|
-
this.basePath = options.basePath;
|
|
21
|
-
this.dryRun = options.dryRun === true;
|
|
22
|
-
this.writtenFiles = [];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Write content to a file
|
|
27
|
-
* Creates parent directories if they don't exist
|
|
28
|
-
* @param {string} filePath - Path relative to basePath (or absolute)
|
|
29
|
-
* @param {string} content - File content to write
|
|
30
|
-
* @param {Object} options - Write options
|
|
31
|
-
* @param {boolean} options.overwrite - Whether to overwrite existing files (default: true)
|
|
32
|
-
* @param {string} options.encoding - File encoding (default: 'utf8')
|
|
33
|
-
* @returns {Promise<Object>} - Result object { written: boolean, path: string, reason?: string }
|
|
34
|
-
*/
|
|
35
|
-
async writeFile(filePath, content, options = {}) {
|
|
36
|
-
const overwrite = options.overwrite !== false; // Default to true
|
|
37
|
-
const encoding = options.encoding || 'utf8';
|
|
38
|
-
|
|
39
|
-
// Resolve full path
|
|
40
|
-
const fullPath = this.basePath ? path.join(this.basePath, filePath) : filePath;
|
|
41
|
-
|
|
42
|
-
// Validate path (security check)
|
|
43
|
-
if (this.basePath) {
|
|
44
|
-
const resolved = path.resolve(fullPath);
|
|
45
|
-
const baseResolved = path.resolve(this.basePath);
|
|
46
|
-
if (!resolved.startsWith(baseResolved)) {
|
|
47
|
-
throw new Error(`Path traversal detected: ${filePath}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Check if file exists
|
|
52
|
-
const exists = await this.fileExists(fullPath);
|
|
53
|
-
if (exists && !overwrite) {
|
|
54
|
-
return {
|
|
55
|
-
written: false,
|
|
56
|
-
path: fullPath,
|
|
57
|
-
reason: 'File exists and overwrite is disabled'
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Dry run mode
|
|
62
|
-
if (this.dryRun) {
|
|
63
|
-
this.writtenFiles.push(fullPath);
|
|
64
|
-
return {
|
|
65
|
-
written: true,
|
|
66
|
-
path: fullPath,
|
|
67
|
-
dryRun: true
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Ensure parent directory exists
|
|
72
|
-
await this.ensureDirectory(path.dirname(fullPath));
|
|
73
|
-
|
|
74
|
-
// Write file atomically (write to temp file, then rename)
|
|
75
|
-
const tempPath = `${fullPath}.tmp`;
|
|
76
|
-
try {
|
|
77
|
-
await fs.writeFile(tempPath, content, encoding);
|
|
78
|
-
await fs.rename(tempPath, fullPath);
|
|
79
|
-
this.writtenFiles.push(fullPath);
|
|
80
|
-
return {
|
|
81
|
-
written: true,
|
|
82
|
-
path: fullPath
|
|
83
|
-
};
|
|
84
|
-
} catch (error) {
|
|
85
|
-
// Clean up temp file if it exists
|
|
86
|
-
try {
|
|
87
|
-
await fs.unlink(tempPath);
|
|
88
|
-
} catch {
|
|
89
|
-
// Ignore cleanup errors
|
|
90
|
-
}
|
|
91
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
92
|
-
throw new Error(`Failed to write file '${filePath}': ${errorMessage}`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Ensure a directory exists, creating it recursively if needed
|
|
98
|
-
* @param {string} dirPath - Directory path
|
|
99
|
-
* @returns {Promise<void>}
|
|
100
|
-
*/
|
|
101
|
-
async ensureDirectory(dirPath) {
|
|
102
|
-
if (this.dryRun) {
|
|
103
|
-
return; // Skip in dry run mode
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
await fs.mkdir(dirPath, {
|
|
107
|
-
recursive: true
|
|
108
|
-
});
|
|
109
|
-
} catch (error) {
|
|
110
|
-
// Ignore error if directory already exists
|
|
111
|
-
if (error.code !== 'EEXIST') {
|
|
112
|
-
throw new Error(`Failed to create directory '${dirPath}': ${error.message}`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Check if a file exists
|
|
119
|
-
* @param {string} filePath - Path to check
|
|
120
|
-
* @returns {Promise<boolean>} - True if file exists
|
|
121
|
-
*/
|
|
122
|
-
async fileExists(filePath) {
|
|
123
|
-
try {
|
|
124
|
-
await fs.access(filePath);
|
|
125
|
-
return true;
|
|
126
|
-
} catch {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Delete a file
|
|
133
|
-
* @param {string} filePath - Path to delete
|
|
134
|
-
* @returns {Promise<boolean>} - True if file was deleted
|
|
135
|
-
*/
|
|
136
|
-
async deleteFile(filePath) {
|
|
137
|
-
const fullPath = this.basePath ? path.join(this.basePath, filePath) : filePath;
|
|
138
|
-
if (this.dryRun) {
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
await fs.unlink(fullPath);
|
|
143
|
-
return true;
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (error.code === 'ENOENT') {
|
|
146
|
-
return false; // File doesn't exist
|
|
147
|
-
}
|
|
148
|
-
throw new Error(`Failed to delete file '${filePath}': ${error.message}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Get list of files written in this session
|
|
154
|
-
* @returns {string[]} - Array of file paths
|
|
155
|
-
*/
|
|
156
|
-
getWrittenFiles() {
|
|
157
|
-
return [...this.writtenFiles];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Clear the written files list
|
|
162
|
-
*/
|
|
163
|
-
clearHistory() {
|
|
164
|
-
this.writtenFiles = [];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Get statistics about write operations
|
|
169
|
-
* @returns {Object} - Statistics
|
|
170
|
-
*/
|
|
171
|
-
getStats() {
|
|
172
|
-
return {
|
|
173
|
-
filesWritten: this.writtenFiles.length,
|
|
174
|
-
dryRun: this.dryRun,
|
|
175
|
-
basePath: this.basePath
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
export default FileWriter;
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PathResolver - Handles cross-platform path resolution
|
|
3
|
-
*
|
|
4
|
-
* Provides platform-independent path operations with security checks
|
|
5
|
-
* and consistent path handling across Windows, Linux, and macOS.
|
|
6
|
-
*/
|
|
7
|
-
import path from 'path';
|
|
8
|
-
export class PathResolver {
|
|
9
|
-
/**
|
|
10
|
-
* Create a new path resolver instance
|
|
11
|
-
* @param {Object} options - Configuration options
|
|
12
|
-
* @param {string} options.basePath - Base path for all path operations
|
|
13
|
-
*/
|
|
14
|
-
constructor(options = {}) {
|
|
15
|
-
this.basePath = options.basePath;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Resolve a path relative to the base path
|
|
20
|
-
* @param {...string} paths - Path segments to resolve
|
|
21
|
-
* @returns {string} - Resolved absolute path
|
|
22
|
-
*/
|
|
23
|
-
resolve(...paths) {
|
|
24
|
-
if (this.basePath) {
|
|
25
|
-
return path.resolve(this.basePath, ...paths);
|
|
26
|
-
}
|
|
27
|
-
return path.resolve(...paths);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Join path segments
|
|
32
|
-
* @param {...string} paths - Path segments to join
|
|
33
|
-
* @returns {string} - Joined path
|
|
34
|
-
*/
|
|
35
|
-
join(...paths) {
|
|
36
|
-
return path.join(...paths);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Normalize a path (resolve . and .., convert slashes)
|
|
41
|
-
* @param {string} filepath - Path to normalize
|
|
42
|
-
* @returns {string} - Normalized path
|
|
43
|
-
*/
|
|
44
|
-
normalize(filepath) {
|
|
45
|
-
return path.normalize(filepath);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get the relative path from one location to another
|
|
50
|
-
* @param {string} from - Starting path
|
|
51
|
-
* @param {string} to - Target path
|
|
52
|
-
* @returns {string} - Relative path
|
|
53
|
-
*/
|
|
54
|
-
relative(from, to) {
|
|
55
|
-
return path.relative(from, to);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get the directory name of a path
|
|
60
|
-
* @param {string} filepath - File path
|
|
61
|
-
* @returns {string} - Directory name
|
|
62
|
-
*/
|
|
63
|
-
dirname(filepath) {
|
|
64
|
-
return path.dirname(filepath);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get the base name of a path (filename with extension)
|
|
69
|
-
* @param {string} filepath - File path
|
|
70
|
-
* @param {string} ext - Optional extension to remove
|
|
71
|
-
* @returns {string} - Base name
|
|
72
|
-
*/
|
|
73
|
-
basename(filepath, ext) {
|
|
74
|
-
return path.basename(filepath, ext);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Get the extension of a path
|
|
79
|
-
* @param {string} filepath - File path
|
|
80
|
-
* @returns {string} - Extension (including the dot)
|
|
81
|
-
*/
|
|
82
|
-
extname(filepath) {
|
|
83
|
-
return path.extname(filepath);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Check if a path is absolute
|
|
88
|
-
* @param {string} filepath - Path to check
|
|
89
|
-
* @returns {boolean} - True if absolute
|
|
90
|
-
*/
|
|
91
|
-
isAbsolute(filepath) {
|
|
92
|
-
return path.isAbsolute(filepath);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Validate a path for security (no path traversal outside base)
|
|
97
|
-
* @param {string} filepath - Path to validate
|
|
98
|
-
* @returns {boolean} - True if path is safe
|
|
99
|
-
* @throws {Error} - If path attempts to traverse outside base
|
|
100
|
-
*/
|
|
101
|
-
validatePath(filepath) {
|
|
102
|
-
if (!this.basePath) {
|
|
103
|
-
return true; // No base path, can't validate
|
|
104
|
-
}
|
|
105
|
-
const resolved = path.resolve(this.basePath, filepath);
|
|
106
|
-
const baseResolved = path.resolve(this.basePath);
|
|
107
|
-
if (!resolved.startsWith(baseResolved)) {
|
|
108
|
-
throw new Error(`Path traversal detected: ${filepath} resolves outside base path`);
|
|
109
|
-
}
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Convert a path to use forward slashes (for URLs, cross-platform consistency)
|
|
115
|
-
* @param {string} filepath - Path to convert
|
|
116
|
-
* @returns {string} - Path with forward slashes
|
|
117
|
-
*/
|
|
118
|
-
toForwardSlashes(filepath) {
|
|
119
|
-
return filepath.split(path.sep).join('/');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Convert a path to use the platform's native separators
|
|
124
|
-
* @param {string} filepath - Path to convert
|
|
125
|
-
* @returns {string} - Path with native separators
|
|
126
|
-
*/
|
|
127
|
-
toNativeSeparators(filepath) {
|
|
128
|
-
return filepath.split('/').join(path.sep);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Get the platform-specific path separator
|
|
133
|
-
* @returns {string} - Path separator ('/' or '\')
|
|
134
|
-
*/
|
|
135
|
-
getSeparator() {
|
|
136
|
-
return path.sep;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Parse a path into its components
|
|
141
|
-
* @param {string} filepath - Path to parse
|
|
142
|
-
* @returns {Object} - Path components { root, dir, base, ext, name }
|
|
143
|
-
*/
|
|
144
|
-
parse(filepath) {
|
|
145
|
-
return path.parse(filepath);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Format path components into a path string
|
|
150
|
-
* @param {Object} pathObject - Path components
|
|
151
|
-
* @returns {string} - Formatted path
|
|
152
|
-
*/
|
|
153
|
-
format(pathObject) {
|
|
154
|
-
return path.format(pathObject);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
export default PathResolver;
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { relative } from 'path';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Service Manifest Generator
|
|
5
|
-
* Creates service manifests with metadata, file categorization, and checksums
|
|
6
|
-
*/
|
|
7
|
-
export class ServiceManifestGenerator {
|
|
8
|
-
/**
|
|
9
|
-
* Create a service manifest
|
|
10
|
-
* @param {Object} coreInputs - Core service configuration
|
|
11
|
-
* @param {Object} confirmedValues - User-confirmed values
|
|
12
|
-
* @param {Array<string>} generatedFiles - List of generated file paths
|
|
13
|
-
* @returns {Object} Service manifest
|
|
14
|
-
*/
|
|
15
|
-
createManifest(coreInputs, confirmedValues, generatedFiles) {
|
|
16
|
-
return {
|
|
17
|
-
manifestVersion: '1.0.0',
|
|
18
|
-
frameworkVersion: '3.0.0',
|
|
19
|
-
generatedAt: new Date().toISOString(),
|
|
20
|
-
service: {
|
|
21
|
-
name: coreInputs.serviceName,
|
|
22
|
-
displayName: confirmedValues.displayName,
|
|
23
|
-
description: confirmedValues.description,
|
|
24
|
-
type: coreInputs.serviceType,
|
|
25
|
-
version: confirmedValues.version,
|
|
26
|
-
author: confirmedValues.author
|
|
27
|
-
},
|
|
28
|
-
configuration: {
|
|
29
|
-
coreInputs,
|
|
30
|
-
confirmedValues,
|
|
31
|
-
urls: {
|
|
32
|
-
production: confirmedValues.productionUrl,
|
|
33
|
-
staging: confirmedValues.stagingUrl,
|
|
34
|
-
development: confirmedValues.developmentUrl,
|
|
35
|
-
documentation: confirmedValues.documentationUrl
|
|
36
|
-
},
|
|
37
|
-
api: {
|
|
38
|
-
basePath: confirmedValues.apiBasePath,
|
|
39
|
-
healthCheckPath: confirmedValues.healthCheckPath
|
|
40
|
-
},
|
|
41
|
-
cloudflare: {
|
|
42
|
-
accountId: coreInputs.cloudflareAccountId,
|
|
43
|
-
zoneId: coreInputs.cloudflareZoneId,
|
|
44
|
-
workerName: confirmedValues.workerName,
|
|
45
|
-
databaseName: confirmedValues.databaseName
|
|
46
|
-
},
|
|
47
|
-
features: confirmedValues.features
|
|
48
|
-
},
|
|
49
|
-
files: {
|
|
50
|
-
total: generatedFiles.length,
|
|
51
|
-
list: generatedFiles.map(file => relative(process.cwd(), file)),
|
|
52
|
-
byCategory: this.categorizeFiles(generatedFiles)
|
|
53
|
-
},
|
|
54
|
-
metadata: {
|
|
55
|
-
generationEngine: 'GenerationEngine v1.0.0',
|
|
56
|
-
tier: 'Tier 3 - Automated Generation',
|
|
57
|
-
checksum: this.generateChecksum(generatedFiles)
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Categorize generated files by type
|
|
64
|
-
* @param {Array<string>} files - List of file paths
|
|
65
|
-
* @returns {Object} Categorized files
|
|
66
|
-
*/
|
|
67
|
-
categorizeFiles(files) {
|
|
68
|
-
const categories = {
|
|
69
|
-
core: [],
|
|
70
|
-
service: [],
|
|
71
|
-
environment: [],
|
|
72
|
-
testing: [],
|
|
73
|
-
documentation: [],
|
|
74
|
-
automation: []
|
|
75
|
-
};
|
|
76
|
-
files.forEach(file => {
|
|
77
|
-
const relativePath = relative(process.cwd(), file);
|
|
78
|
-
if (relativePath.includes('package.json') || relativePath.includes('wrangler.toml') || relativePath.includes('.env')) {
|
|
79
|
-
categories.core.push(relativePath);
|
|
80
|
-
} else if (relativePath.includes('src/')) {
|
|
81
|
-
categories.service.push(relativePath);
|
|
82
|
-
} else if (relativePath.includes('config/') || relativePath.includes('scripts/')) {
|
|
83
|
-
categories.environment.push(relativePath);
|
|
84
|
-
} else if (relativePath.includes('test/') || relativePath.includes('jest.config.js') || relativePath.includes('.eslintrc.js')) {
|
|
85
|
-
categories.testing.push(relativePath);
|
|
86
|
-
} else if (relativePath.includes('docs/') || relativePath.includes('README.md')) {
|
|
87
|
-
categories.documentation.push(relativePath);
|
|
88
|
-
} else if (relativePath.includes('.github/') || relativePath.includes('.gitignore') || relativePath.includes('docker-compose.yml')) {
|
|
89
|
-
categories.automation.push(relativePath);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
return categories;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Generate checksum for file verification
|
|
97
|
-
* @param {Array<string>} files - List of file paths
|
|
98
|
-
* @returns {string} Hexadecimal checksum
|
|
99
|
-
*/
|
|
100
|
-
generateChecksum(files) {
|
|
101
|
-
// Simple checksum based on file count and names
|
|
102
|
-
const fileString = files.map(f => relative(process.cwd(), f)).sort().join('');
|
|
103
|
-
let hash = 0;
|
|
104
|
-
for (let i = 0; i < fileString.length; i++) {
|
|
105
|
-
const char = fileString.charCodeAt(i);
|
|
106
|
-
hash = (hash << 5) - hash + char;
|
|
107
|
-
hash = hash & hash; // Convert to 32-bit integer
|
|
108
|
-
}
|
|
109
|
-
return Math.abs(hash).toString(16);
|
|
110
|
-
}
|
|
111
|
-
}
|