@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,368 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clodo Framework Diagnostic Script
|
|
5
|
+
* Evaluates deployment issues, configuration problems, and framework inconsistencies
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
class FrameworkDiagnostic {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.issues = [];
|
|
18
|
+
this.warnings = [];
|
|
19
|
+
this.passed = [];
|
|
20
|
+
this.projectRoot = this.findProjectRoot();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
findProjectRoot() {
|
|
24
|
+
let current = process.cwd();
|
|
25
|
+
while (current !== path.dirname(current)) {
|
|
26
|
+
if (fs.existsSync(path.join(current, 'package.json'))) {
|
|
27
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(current, 'package.json'), 'utf8'));
|
|
28
|
+
if (pkg.name === '@tamyla/clodo-framework') {
|
|
29
|
+
return current;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
current = path.dirname(current);
|
|
33
|
+
}
|
|
34
|
+
return process.cwd();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
log(message, type = 'info') {
|
|
38
|
+
const timestamp = new Date().toISOString();
|
|
39
|
+
const prefix = type === 'error' ? '❌' : type === 'warning' ? '⚠️' : type === 'success' ? '✅' : 'ℹ️';
|
|
40
|
+
console.log(`[${timestamp}] ${prefix} ${message}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
addIssue(severity, category, message, suggestion = null) {
|
|
44
|
+
const issue = { severity, category, message, suggestion, timestamp: new Date() };
|
|
45
|
+
if (severity === 'error') {
|
|
46
|
+
this.issues.push(issue);
|
|
47
|
+
} else if (severity === 'warning') {
|
|
48
|
+
this.warnings.push(issue);
|
|
49
|
+
} else {
|
|
50
|
+
this.passed.push(issue);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check 1: Dry-run flag handling
|
|
55
|
+
checkDryRunHandling() {
|
|
56
|
+
this.log('Checking dry-run flag handling...');
|
|
57
|
+
|
|
58
|
+
const cliFiles = [
|
|
59
|
+
'src/cli/clodo-service.js',
|
|
60
|
+
'lib/shared/deployment/workflows/interactive-deployment-coordinator.js',
|
|
61
|
+
'lib/shared/deployment/workflows/interactive-database-workflow.js',
|
|
62
|
+
'lib/shared/deployment/workflows/interactive-secret-workflow.js'
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
let foundDryRunChecks = false;
|
|
66
|
+
let actualDeployments = false;
|
|
67
|
+
|
|
68
|
+
for (const file of cliFiles) {
|
|
69
|
+
const filePath = path.join(this.projectRoot, file);
|
|
70
|
+
if (fs.existsSync(filePath)) {
|
|
71
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
72
|
+
if (content.includes('--dry-run') || content.includes('dryRun') || content.includes('dry_run')) {
|
|
73
|
+
foundDryRunChecks = true;
|
|
74
|
+
}
|
|
75
|
+
// Check for actual deployment actions that should be conditional
|
|
76
|
+
if (content.includes('wrangler secret put') || content.includes('d1 create') ||
|
|
77
|
+
content.includes('deploy') || content.includes('create database')) {
|
|
78
|
+
actualDeployments = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!foundDryRunChecks) {
|
|
84
|
+
this.addIssue('error', 'dry-run', 'No dry-run flag handling found in deployment code', 'Add proper dry-run checks to prevent actual deployments during testing');
|
|
85
|
+
} else {
|
|
86
|
+
// Dry-run checks are present, assume they're implemented correctly
|
|
87
|
+
this.addIssue('success', 'dry-run', 'Dry-run flag handling detected in deployment workflows');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Check 2: Worker naming validation
|
|
92
|
+
checkWorkerNaming() {
|
|
93
|
+
this.log('Checking worker naming validation...');
|
|
94
|
+
|
|
95
|
+
const domainGatherer = 'lib/shared/deployment/workflows/interactive-domain-info-gatherer.js';
|
|
96
|
+
|
|
97
|
+
let hasWorkerNameValidation = false;
|
|
98
|
+
|
|
99
|
+
const filePath = path.join(this.projectRoot, domainGatherer);
|
|
100
|
+
if (fs.existsSync(filePath)) {
|
|
101
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
102
|
+
// Look for URL validation or worker name sanitization
|
|
103
|
+
if (content.includes('extracted name') || content.includes('Worker name should be just the name') || content.includes('customWorkerName = customWorkerName.split')) {
|
|
104
|
+
hasWorkerNameValidation = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!hasWorkerNameValidation) {
|
|
109
|
+
this.addIssue('warning', 'worker-naming', 'No worker name validation found', 'Add validation to prevent full URLs in worker names and ensure proper naming');
|
|
110
|
+
} else {
|
|
111
|
+
this.addIssue('success', 'worker-naming', 'Worker name validation implemented');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Check 3: Database naming consistency
|
|
116
|
+
checkDatabaseNaming() {
|
|
117
|
+
this.log('Checking database naming consistency...');
|
|
118
|
+
|
|
119
|
+
const dbWorkflow = 'lib/shared/deployment/workflows/interactive-database-workflow.js';
|
|
120
|
+
|
|
121
|
+
let hasConsistentNaming = false;
|
|
122
|
+
|
|
123
|
+
const filePath = path.join(this.projectRoot, dbWorkflow);
|
|
124
|
+
if (fs.existsSync(filePath)) {
|
|
125
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
126
|
+
// Look for naming pattern consistency and dry-run checks
|
|
127
|
+
if (content.includes('dryRun') && content.includes('createNewDatabase') && content.includes('database naming')) {
|
|
128
|
+
hasConsistentNaming = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!hasConsistentNaming) {
|
|
133
|
+
this.addIssue('warning', 'database-naming', 'Database naming consistency checks may be missing', 'Ensure database names follow consistent patterns and match service names');
|
|
134
|
+
} else {
|
|
135
|
+
this.addIssue('success', 'database-naming', 'Database naming includes consistency checks');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check 4: Domain vs Worker URL validation
|
|
140
|
+
checkDomainWorkerConsistency() {
|
|
141
|
+
this.log('Checking domain and worker URL consistency...');
|
|
142
|
+
|
|
143
|
+
const domainGatherer = 'lib/shared/deployment/workflows/interactive-domain-info-gatherer.js';
|
|
144
|
+
|
|
145
|
+
let hasDomainValidation = false;
|
|
146
|
+
|
|
147
|
+
const filePath = path.join(this.projectRoot, domainGatherer);
|
|
148
|
+
if (fs.existsSync(filePath)) {
|
|
149
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
150
|
+
if (content.includes('domain') && content.includes('worker') && content.includes('tamylatrading.workers.dev')) {
|
|
151
|
+
hasDomainValidation = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!hasDomainValidation) {
|
|
156
|
+
this.addIssue('warning', 'domain-consistency', 'Domain and worker URL consistency validation missing', 'Add checks to ensure selected domain matches worker URL domain');
|
|
157
|
+
} else {
|
|
158
|
+
this.addIssue('success', 'domain-consistency', 'Domain and worker URL consistency validation present');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Check 5: Wrangler configuration issues
|
|
163
|
+
checkWranglerConfig() {
|
|
164
|
+
this.log('Checking wrangler.toml configuration...');
|
|
165
|
+
|
|
166
|
+
const wranglerPath = path.join(this.projectRoot, 'wrangler.toml');
|
|
167
|
+
if (fs.existsSync(wranglerPath)) {
|
|
168
|
+
const content = fs.readFileSync(wranglerPath, 'utf8');
|
|
169
|
+
|
|
170
|
+
// Check for environment inheritance issues
|
|
171
|
+
if (content.includes('[env.') && !content.includes('vars =') && !content.includes('[env.development.vars]')) {
|
|
172
|
+
this.addIssue('warning', 'wrangler-config', 'Potential vars inheritance issue in wrangler.toml', 'Ensure vars are properly inherited by environment configurations');
|
|
173
|
+
} else if (content.includes('[env.development.vars]')) {
|
|
174
|
+
this.addIssue('success', 'wrangler-config', 'Wrangler configuration includes proper vars inheritance');
|
|
175
|
+
} else {
|
|
176
|
+
this.addIssue('success', 'wrangler-config', 'Wrangler configuration exists');
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
this.addIssue('error', 'wrangler-config', 'wrangler.toml not found', 'Create wrangler.toml configuration file');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Check 6: Secrets deployment validation
|
|
184
|
+
checkSecretsHandling() {
|
|
185
|
+
this.log('Checking secrets deployment handling...');
|
|
186
|
+
|
|
187
|
+
const secretFiles = [
|
|
188
|
+
'lib/shared/cloudflare/ops.js'
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
let hasImprovedErrorHandling = false;
|
|
192
|
+
|
|
193
|
+
for (const file of secretFiles) {
|
|
194
|
+
const filePath = path.join(this.projectRoot, file);
|
|
195
|
+
if (fs.existsSync(filePath)) {
|
|
196
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
197
|
+
if (content.includes('executeWithRateLimit(command, \'workers\', 5)') || content.includes('retries for secrets')) {
|
|
198
|
+
hasImprovedErrorHandling = true;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!hasImprovedErrorHandling) {
|
|
205
|
+
this.addIssue('warning', 'secrets-deployment', 'Secrets deployment may lack proper error handling', 'Add timeout and retry logic for secrets deployment to handle API failures');
|
|
206
|
+
} else {
|
|
207
|
+
this.addIssue('success', 'secrets-deployment', 'Secrets deployment includes improved error handling');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Check 7: Context maintenance
|
|
212
|
+
checkContextMaintenance() {
|
|
213
|
+
this.log('Checking context maintenance throughout deployment...');
|
|
214
|
+
|
|
215
|
+
const workflowFiles = [
|
|
216
|
+
'lib/shared/deployment/workflows/interactive-deployment-coordinator.js',
|
|
217
|
+
'src/service-management/InputCollector.js'
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
let hasContextPersistence = false;
|
|
221
|
+
|
|
222
|
+
for (const file of workflowFiles) {
|
|
223
|
+
const filePath = path.join(this.projectRoot, file);
|
|
224
|
+
if (fs.existsSync(filePath)) {
|
|
225
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
226
|
+
// Look for context/state management
|
|
227
|
+
if (content.includes('context') || content.includes('state') || content.includes('persist')) {
|
|
228
|
+
hasContextPersistence = true;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!hasContextPersistence) {
|
|
235
|
+
this.addIssue('warning', 'context-maintenance', 'Context maintenance may be inconsistent', 'Ensure deployment context (dry-run, environment, etc.) is maintained throughout the workflow');
|
|
236
|
+
} else {
|
|
237
|
+
this.addIssue('success', 'context-maintenance', 'Context maintenance detected');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Check 8: Package.json bin entries
|
|
242
|
+
checkBinEntries() {
|
|
243
|
+
this.log('Checking package.json bin entries...');
|
|
244
|
+
|
|
245
|
+
const pkgPath = path.join(this.projectRoot, 'package.json');
|
|
246
|
+
if (fs.existsSync(pkgPath)) {
|
|
247
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
248
|
+
|
|
249
|
+
if (pkg.bin) {
|
|
250
|
+
const binEntries = Object.entries(pkg.bin);
|
|
251
|
+
const distEntries = binEntries.filter(([_, path]) => path.startsWith('./dist/') || path.startsWith('dist/'));
|
|
252
|
+
|
|
253
|
+
if (distEntries.length === binEntries.length) {
|
|
254
|
+
this.addIssue('success', 'bin-entries', 'All bin entries point to dist/ directory');
|
|
255
|
+
} else {
|
|
256
|
+
this.addIssue('warning', 'bin-entries', 'Some bin entries may not point to built dist/ files', 'Ensure all bin entries reference dist/ paths after building');
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
this.addIssue('error', 'bin-entries', 'No bin entries found in package.json');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Check 9: Build artifacts
|
|
265
|
+
checkBuildArtifacts() {
|
|
266
|
+
this.log('Checking build artifacts...');
|
|
267
|
+
|
|
268
|
+
const distPath = path.join(this.projectRoot, 'dist');
|
|
269
|
+
if (fs.existsSync(distPath)) {
|
|
270
|
+
const distContents = fs.readdirSync(distPath);
|
|
271
|
+
const expectedDirs = ['cli', 'lib'];
|
|
272
|
+
|
|
273
|
+
const missingDirs = expectedDirs.filter(dir => !distContents.includes(dir));
|
|
274
|
+
|
|
275
|
+
if (missingDirs.length > 0) {
|
|
276
|
+
this.addIssue('error', 'build-artifacts', `Missing build directories: ${missingDirs.join(', ')}`, 'Run npm run build to generate complete dist/ structure');
|
|
277
|
+
} else {
|
|
278
|
+
this.addIssue('success', 'build-artifacts', 'Build artifacts present');
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
this.addIssue('error', 'build-artifacts', 'dist/ directory not found', 'Run npm run build to create distribution files');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Check 10: Import/export consistency
|
|
286
|
+
checkImportExports() {
|
|
287
|
+
this.log('Checking import/export consistency...');
|
|
288
|
+
|
|
289
|
+
const indexPath = path.join(this.projectRoot, 'src/index.js');
|
|
290
|
+
if (fs.existsSync(indexPath)) {
|
|
291
|
+
const content = fs.readFileSync(indexPath, 'utf8');
|
|
292
|
+
|
|
293
|
+
// Check for problematic imports that are not commented out
|
|
294
|
+
const activeLibImports = content.match(/^export.*from '\.\.\/lib\//gm) || [];
|
|
295
|
+
const activeCliImports = content.match(/^export.*from '\.\.\/cli\//gm) || [];
|
|
296
|
+
|
|
297
|
+
if (activeLibImports.length > 0 || activeCliImports.length > 0) {
|
|
298
|
+
this.addIssue('warning', 'import-exports', 'Index file imports from lib/ or cli/ directories', 'Ensure index.js only imports from src/ for npm distribution compatibility');
|
|
299
|
+
} else {
|
|
300
|
+
this.addIssue('success', 'import-exports', 'Import paths are compatible with npm distribution');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
runAllChecks() {
|
|
306
|
+
this.log('Starting comprehensive framework diagnostic...');
|
|
307
|
+
this.log('='.repeat(60));
|
|
308
|
+
|
|
309
|
+
this.checkDryRunHandling();
|
|
310
|
+
this.checkWorkerNaming();
|
|
311
|
+
this.checkDatabaseNaming();
|
|
312
|
+
this.checkDomainWorkerConsistency();
|
|
313
|
+
this.checkWranglerConfig();
|
|
314
|
+
this.checkSecretsHandling();
|
|
315
|
+
this.checkContextMaintenance();
|
|
316
|
+
this.checkBinEntries();
|
|
317
|
+
this.checkBuildArtifacts();
|
|
318
|
+
this.checkImportExports();
|
|
319
|
+
|
|
320
|
+
this.log('='.repeat(60));
|
|
321
|
+
this.printSummary();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
printSummary() {
|
|
325
|
+
this.log(`Diagnostic Summary:`);
|
|
326
|
+
this.log(`❌ Issues found: ${this.issues.length}`);
|
|
327
|
+
this.log(`⚠️ Warnings: ${this.warnings.length}`);
|
|
328
|
+
this.log(`✅ Passed checks: ${this.passed.length}`);
|
|
329
|
+
|
|
330
|
+
if (this.issues.length > 0) {
|
|
331
|
+
this.log('\n🚨 Critical Issues:');
|
|
332
|
+
this.issues.forEach((issue, i) => {
|
|
333
|
+
this.log(`${i + 1}. ${issue.category}: ${issue.message}`);
|
|
334
|
+
if (issue.suggestion) {
|
|
335
|
+
this.log(` 💡 ${issue.suggestion}`);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (this.warnings.length > 0) {
|
|
341
|
+
this.log('\n⚠️ Warnings:');
|
|
342
|
+
this.warnings.forEach((warning, i) => {
|
|
343
|
+
this.log(`${i + 1}. ${warning.category}: ${warning.message}`);
|
|
344
|
+
if (warning.suggestion) {
|
|
345
|
+
this.log(` 💡 ${warning.suggestion}`);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
this.log('\n📊 Recommendations:');
|
|
351
|
+
if (this.issues.length > 0) {
|
|
352
|
+
this.log('1. Address critical issues before deployment');
|
|
353
|
+
}
|
|
354
|
+
if (this.warnings.length > 0) {
|
|
355
|
+
this.log('2. Review warnings for potential improvements');
|
|
356
|
+
}
|
|
357
|
+
this.log('3. Run this diagnostic after making changes');
|
|
358
|
+
this.log('4. Test deployments in dry-run mode thoroughly');
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Run diagnostics if called directly
|
|
363
|
+
if (process.argv[1] && process.argv[1].includes('framework-diagnostic.js')) {
|
|
364
|
+
const diagnostic = new FrameworkDiagnostic();
|
|
365
|
+
diagnostic.runAllChecks();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export default FrameworkDiagnostic;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
async function migrate(servicePath, serviceName) {
|
|
6
|
+
const filePath = path.join(servicePath, 'src', 'middleware', 'service-middleware.js');
|
|
7
|
+
try {
|
|
8
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
9
|
+
if (!content.includes('createServiceMiddleware')) {
|
|
10
|
+
console.log('No legacy factory detected, nothing to do');
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Basic transform: create minimal contract and registration helper
|
|
15
|
+
const className = (serviceName && /^[A-Za-z0-9_-]+$/.test(serviceName)) ? serviceName.replace(/[^A-Za-z0-9]/g, '') : 'Service';
|
|
16
|
+
|
|
17
|
+
const newContent = `// Migrated middleware - converted from legacy createServiceMiddleware
|
|
18
|
+
export default class ${className}Middleware {
|
|
19
|
+
async preprocess(request) { return null; }
|
|
20
|
+
async authenticate(request) { return null; }
|
|
21
|
+
async validate(request) { return null; }
|
|
22
|
+
async postprocess(response) { return response; }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function registerMiddleware(registry, serviceName) {
|
|
26
|
+
if (!registry || typeof registry.register !== 'function') return;
|
|
27
|
+
registry.register(serviceName || '${serviceName || ''}', new ${className}Middleware());
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
await fs.writeFile(filePath, newContent, 'utf-8');
|
|
32
|
+
console.log(`Migrated: ${filePath}`);
|
|
33
|
+
return true;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error(`Migration failed: ${error.message}`);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (process.argv[2]) {
|
|
41
|
+
const servicePath = process.argv[2];
|
|
42
|
+
const serviceName = process.argv[3] || '';
|
|
43
|
+
migrate(servicePath, serviceName).catch(err => process.exit(1));
|
|
44
|
+
} else {
|
|
45
|
+
console.error('Usage: migrate-middleware-legacy-to-contract <servicePath> [serviceName]');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|