@tamyla/clodo-framework 4.0.12 ā 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 +708 -426
- package/README.md +7 -0
- package/dist/cli/commands/create.js +2 -1
- package/dist/deployment/wrangler-deployer.js +1 -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/service-management/generators/config/WranglerTomlGenerator.js +1 -1
- package/dist/simple-api.js +32 -1
- package/docs/MIDDLEWARE_MIGRATION_SUMMARY.md +121 -0
- package/package.json +7 -2
- 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,339 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Comprehensive Package Testing Script
|
|
4
|
+
* Tests the built package as a downstream developer would use it
|
|
5
|
+
*
|
|
6
|
+
* This script:
|
|
7
|
+
* 1. Creates a temporary test project
|
|
8
|
+
* 2. Packs the current package (creates a .tgz file)
|
|
9
|
+
* 3. Installs it in the test project like a real user would
|
|
10
|
+
* 4. Tests all exported modules and APIs
|
|
11
|
+
* 5. Checks for import errors, circular dependencies, and runtime issues
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
16
|
+
import { join } from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
import { dirname } from 'path';
|
|
19
|
+
|
|
20
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = dirname(__filename);
|
|
22
|
+
const projectRoot = join(__dirname, '..');
|
|
23
|
+
const testDir = join(projectRoot, 'tmp', 'package-test');
|
|
24
|
+
|
|
25
|
+
console.log('\nš§Ŗ Starting Comprehensive Package Test\n');
|
|
26
|
+
console.log('ā'.repeat(60));
|
|
27
|
+
|
|
28
|
+
// Clean up previous test
|
|
29
|
+
if (existsSync(testDir)) {
|
|
30
|
+
console.log('š§¹ Cleaning up previous test directory...');
|
|
31
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Step 1: Build the package
|
|
35
|
+
console.log('\nš¦ Step 1: Building package...');
|
|
36
|
+
try {
|
|
37
|
+
execSync('npm run build', { cwd: projectRoot, stdio: 'inherit' });
|
|
38
|
+
console.log('ā
Build successful');
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('ā Build failed');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Step 2: Pack the package (creates .tgz)
|
|
45
|
+
console.log('\nš¦ Step 2: Packing package...');
|
|
46
|
+
let tarballPath;
|
|
47
|
+
try {
|
|
48
|
+
const output = execSync('npm pack', { cwd: projectRoot, encoding: 'utf8' });
|
|
49
|
+
tarballPath = output.trim().split('\n').pop();
|
|
50
|
+
console.log(`ā
Package created: ${tarballPath}`);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('ā Pack failed');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Step 3: Create test project
|
|
57
|
+
console.log('\nš Step 3: Creating test project...');
|
|
58
|
+
mkdirSync(testDir, { recursive: true });
|
|
59
|
+
|
|
60
|
+
// Create package.json for test project
|
|
61
|
+
const testPackageJson = {
|
|
62
|
+
name: 'test-downstream-project',
|
|
63
|
+
version: '1.0.0',
|
|
64
|
+
type: 'module',
|
|
65
|
+
private: true
|
|
66
|
+
};
|
|
67
|
+
writeFileSync(
|
|
68
|
+
join(testDir, 'package.json'),
|
|
69
|
+
JSON.stringify(testPackageJson, null, 2)
|
|
70
|
+
);
|
|
71
|
+
console.log('ā
Test project created');
|
|
72
|
+
|
|
73
|
+
// Step 4: Install the packed package
|
|
74
|
+
console.log('\nš„ Step 4: Installing package in test project...');
|
|
75
|
+
try {
|
|
76
|
+
const tarballFullPath = join(projectRoot, tarballPath);
|
|
77
|
+
execSync(`npm install "${tarballFullPath}"`, {
|
|
78
|
+
cwd: testDir,
|
|
79
|
+
stdio: 'inherit'
|
|
80
|
+
});
|
|
81
|
+
console.log('ā
Package installed');
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('ā Installation failed');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Step 5: Test all exports
|
|
88
|
+
console.log('\nš§Ŗ Step 5: Testing package exports...');
|
|
89
|
+
|
|
90
|
+
const tests = [
|
|
91
|
+
{
|
|
92
|
+
name: 'Main Entry Point',
|
|
93
|
+
code: `import * as framework from '@tamyla/clodo-framework';
|
|
94
|
+
console.log('ā Main export loaded');
|
|
95
|
+
if (!framework.initializeService) throw new Error('Missing initializeService');
|
|
96
|
+
console.log('ā initializeService exists');`
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Worker Integration',
|
|
100
|
+
code: `import { initializeService, configManager } from '@tamyla/clodo-framework/worker';
|
|
101
|
+
console.log('ā Worker exports loaded');
|
|
102
|
+
if (typeof initializeService !== 'function') throw new Error('initializeService is not a function');
|
|
103
|
+
console.log('ā initializeService is a function');`
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Config Module',
|
|
107
|
+
code: `import * as config from '@tamyla/clodo-framework/config';
|
|
108
|
+
console.log('ā Config exports loaded');
|
|
109
|
+
if (!config.getDomainFromEnv) throw new Error('Missing getDomainFromEnv');
|
|
110
|
+
console.log('ā getDomainFromEnv exists');`
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Services Module',
|
|
114
|
+
code: `import { GenericDataService, createDataService } from '@tamyla/clodo-framework/services';
|
|
115
|
+
console.log('ā Services exports loaded');
|
|
116
|
+
if (typeof createDataService !== 'function') throw new Error('createDataService is not a function');
|
|
117
|
+
console.log('ā createDataService is a function');`
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'Schema Module',
|
|
121
|
+
code: `import { SchemaManager, schemaManager } from '@tamyla/clodo-framework/schema';
|
|
122
|
+
console.log('ā Schema exports loaded');
|
|
123
|
+
if (!SchemaManager) throw new Error('Missing SchemaManager');
|
|
124
|
+
console.log('ā SchemaManager exists');`
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'Routing Module',
|
|
128
|
+
code: `import { EnhancedRouter, createEnhancedRouter } from '@tamyla/clodo-framework/routing';
|
|
129
|
+
console.log('ā Routing exports loaded');
|
|
130
|
+
if (typeof createEnhancedRouter !== 'function') throw new Error('createEnhancedRouter is not a function');
|
|
131
|
+
console.log('ā createEnhancedRouter is a function');`
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'Security Module',
|
|
135
|
+
code: `import { SecurityCLI, SecretGenerator } from '@tamyla/clodo-framework/security';
|
|
136
|
+
console.log('ā Security exports loaded');
|
|
137
|
+
if (!SecurityCLI) throw new Error('Missing SecurityCLI');
|
|
138
|
+
console.log('ā SecurityCLI exists');`
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'Service Management',
|
|
142
|
+
code: `import { ServiceCreator, ServiceOrchestrator } from '@tamyla/clodo-framework/service-management';
|
|
143
|
+
console.log('ā Service management exports loaded');
|
|
144
|
+
if (!ServiceCreator) throw new Error('Missing ServiceCreator');
|
|
145
|
+
console.log('ā ServiceCreator exists');`
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'Database Module',
|
|
149
|
+
code: `import * as db from '@tamyla/clodo-framework/database';
|
|
150
|
+
console.log('ā Database exports loaded');
|
|
151
|
+
if (!db.DatabaseOrchestrator) throw new Error('Missing DatabaseOrchestrator');
|
|
152
|
+
console.log('ā DatabaseOrchestrator exists');`
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'Deployment Module',
|
|
156
|
+
code: `import { DeploymentValidator, DeploymentAuditor } from '@tamyla/clodo-framework/deployment';
|
|
157
|
+
console.log('ā Deployment exports loaded');
|
|
158
|
+
if (!DeploymentValidator) throw new Error('Missing DeploymentValidator');
|
|
159
|
+
console.log('ā DeploymentValidator exists');`
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'Cloudflare Utils',
|
|
163
|
+
code: `import * as cf from '@tamyla/clodo-framework/utils/cloudflare';
|
|
164
|
+
console.log('ā Cloudflare utils exports loaded');
|
|
165
|
+
if (!cf.CloudflareAPI) throw new Error('Missing CloudflareAPI');
|
|
166
|
+
console.log('ā CloudflareAPI exists');`
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'Dynamic Import Test (frameworkConfig)',
|
|
170
|
+
code: `import { initializeService } from '@tamyla/clodo-framework/worker';
|
|
171
|
+
// Test that dynamic imports work at runtime
|
|
172
|
+
const env = { DOMAIN: 'test' };
|
|
173
|
+
const domains = { test: { name: 'test', accountId: '123' } };
|
|
174
|
+
try {
|
|
175
|
+
const result = initializeService(env, domains);
|
|
176
|
+
console.log('ā initializeService executed without import errors');
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error.message.includes('Cannot find module')) {
|
|
179
|
+
throw new Error('Dynamic import path broken: ' + error.message);
|
|
180
|
+
}
|
|
181
|
+
// Other errors are OK (we're not testing full functionality, just imports)
|
|
182
|
+
console.log('ā No import path errors (functional errors are OK for this test)');
|
|
183
|
+
}`
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'Circular Dependency Check',
|
|
187
|
+
code: `import * as framework from '@tamyla/clodo-framework';
|
|
188
|
+
import * as worker from '@tamyla/clodo-framework/worker';
|
|
189
|
+
import * as config from '@tamyla/clodo-framework/config';
|
|
190
|
+
console.log('ā No circular dependency errors on import');
|
|
191
|
+
// Check that we can access nested properties without infinite loops
|
|
192
|
+
if (config.getDomainFromEnv) {
|
|
193
|
+
console.log('ā Config module accessible');
|
|
194
|
+
}
|
|
195
|
+
if (worker.initializeService) {
|
|
196
|
+
console.log('ā Worker module accessible');
|
|
197
|
+
}
|
|
198
|
+
console.log('ā No circular reference runtime errors');`
|
|
199
|
+
}
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
let passed = 0;
|
|
203
|
+
let failed = 0;
|
|
204
|
+
const failures = [];
|
|
205
|
+
|
|
206
|
+
for (const test of tests) {
|
|
207
|
+
const testFile = join(testDir, `test-${passed + failed}.mjs`);
|
|
208
|
+
writeFileSync(testFile, test.code);
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
console.log(`\n Testing: ${test.name}`);
|
|
212
|
+
execSync(`node "${testFile}"`, { cwd: testDir, encoding: 'utf8', stdio: 'pipe' });
|
|
213
|
+
console.log(` ā
${test.name} passed`);
|
|
214
|
+
passed++;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error(` ā ${test.name} failed`);
|
|
217
|
+
console.error(` ${error.message}`);
|
|
218
|
+
failed++;
|
|
219
|
+
failures.push({ name: test.name, error: error.message });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Step 6: Check for common issues in dist/
|
|
224
|
+
console.log('\nš Step 6: Checking for common packaging issues...');
|
|
225
|
+
|
|
226
|
+
const distPath = join(projectRoot, 'dist');
|
|
227
|
+
const issuesFound = [];
|
|
228
|
+
|
|
229
|
+
// Check for references to src/ or ../lib/ that escaped outside dist/
|
|
230
|
+
function checkFileForBadImports(filePath, relativePath) {
|
|
231
|
+
const content = readFileSync(filePath, 'utf8');
|
|
232
|
+
const lines = content.split('\n');
|
|
233
|
+
|
|
234
|
+
//Skip re-export wrappers in dist/utils/ that are intended to re-export from dist/lib/
|
|
235
|
+
// Normalize path separators to forward slashes for consistent matching
|
|
236
|
+
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
237
|
+
const isReExportWrapper = normalizedPath.match(/^utils\/(file-manager|formatters|logger|index|cloudflare\/ops)\.js$/);
|
|
238
|
+
const isServiceManagementGenerator = normalizedPath.match(/^service-management\/generators\/testing\//);
|
|
239
|
+
|
|
240
|
+
lines.forEach((line, index) => {
|
|
241
|
+
// Check for imports that go outside dist/
|
|
242
|
+
// Skip if this is within lib/ going to another lib location or to config/ (which is also in dist/)
|
|
243
|
+
const isLibToLib = normalizedPath.startsWith('lib/') && line.match(/from\s+['"]\.\.\/\.\.\//);
|
|
244
|
+
const isLibToConfig = normalizedPath.startsWith('lib/shared/config/') && line.includes('../../../config/');
|
|
245
|
+
|
|
246
|
+
if (line.match(/from\s+['"]\.\.\/\.\.\/\.\.\//)) {
|
|
247
|
+
if (!isLibToLib && !isLibToConfig) {
|
|
248
|
+
issuesFound.push({
|
|
249
|
+
file: relativePath,
|
|
250
|
+
line: index + 1,
|
|
251
|
+
issue: 'Import path goes too far up (../../../)',
|
|
252
|
+
code: line.trim()
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Check for absolute imports to src/ or lib/
|
|
258
|
+
if (line.match(/from\s+['"].*\/src\//) && !isServiceManagementGenerator) {
|
|
259
|
+
issuesFound.push({
|
|
260
|
+
file: relativePath,
|
|
261
|
+
line: index + 1,
|
|
262
|
+
issue: 'Absolute import to src/ (should be relative within dist/)',
|
|
263
|
+
code: line.trim()
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Check for imports that try to access lib/ from project root
|
|
268
|
+
if (line.match(/from\s+['"]\.\.\/lib\//) && !relativePath.includes('lib\\') && !relativePath.includes('lib/') && !isReExportWrapper) {
|
|
269
|
+
issuesFound.push({
|
|
270
|
+
file: relativePath,
|
|
271
|
+
line: index + 1,
|
|
272
|
+
issue: 'Import tries to access lib/ outside dist/',
|
|
273
|
+
code: line.trim()
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function walkDir(dir, baseDir = dir) {
|
|
280
|
+
const files = readdirSync(dir, { withFileTypes: true });
|
|
281
|
+
files.forEach(file => {
|
|
282
|
+
const fullPath = join(dir, file.name);
|
|
283
|
+
if (file.isDirectory()) {
|
|
284
|
+
walkDir(fullPath, baseDir);
|
|
285
|
+
} else if (file.name.endsWith('.js')) {
|
|
286
|
+
const relativePath = fullPath.substring(baseDir.length + 1);
|
|
287
|
+
checkFileForBadImports(fullPath, relativePath);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
walkDir(distPath);
|
|
293
|
+
|
|
294
|
+
if (issuesFound.length > 0) {
|
|
295
|
+
console.log('\nā ļø Found potential packaging issues:');
|
|
296
|
+
issuesFound.forEach(issue => {
|
|
297
|
+
console.log(`\n File: ${issue.file}:${issue.line}`);
|
|
298
|
+
console.log(` Issue: ${issue.issue}`);
|
|
299
|
+
console.log(` Code: ${issue.code}`);
|
|
300
|
+
});
|
|
301
|
+
} else {
|
|
302
|
+
console.log('ā
No obvious packaging issues found');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Final Report
|
|
306
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
307
|
+
console.log('\nš TEST SUMMARY');
|
|
308
|
+
console.log('ā'.repeat(60));
|
|
309
|
+
console.log(`\n ā
Passed: ${passed}`);
|
|
310
|
+
console.log(` ā Failed: ${failed}`);
|
|
311
|
+
|
|
312
|
+
if (issuesFound.length > 0) {
|
|
313
|
+
console.log(` ā ļø Packaging issues: ${issuesFound.length}`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (failed > 0) {
|
|
317
|
+
console.log('\nā FAILURES:');
|
|
318
|
+
failures.forEach(f => {
|
|
319
|
+
console.log(`\n ${f.name}:`);
|
|
320
|
+
console.log(` ${f.error}`);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
325
|
+
|
|
326
|
+
// Cleanup
|
|
327
|
+
console.log('\nš§¹ Cleaning up...');
|
|
328
|
+
const tarballFullPath = join(projectRoot, tarballPath);
|
|
329
|
+
if (existsSync(tarballFullPath)) {
|
|
330
|
+
rmSync(tarballFullPath);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (failed > 0 || issuesFound.length > 0) {
|
|
334
|
+
console.log('\nā Package has issues that need to be fixed before publishing!\n');
|
|
335
|
+
process.exit(1);
|
|
336
|
+
} else {
|
|
337
|
+
console.log('\nā
Package is ready for publication!\n');
|
|
338
|
+
process.exit(0);
|
|
339
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Testing Scripts
|
|
2
|
+
|
|
3
|
+
Scripts for testing Clodo Framework services and functionality.
|
|
4
|
+
|
|
5
|
+
## Scripts
|
|
6
|
+
|
|
7
|
+
### test.ps1
|
|
8
|
+
Basic test runner for services.
|
|
9
|
+
|
|
10
|
+
**Usage:**
|
|
11
|
+
```powershell
|
|
12
|
+
.\scripts\testing\test.ps1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### test-first.ps1
|
|
16
|
+
Test the first service or item in a collection.
|
|
17
|
+
|
|
18
|
+
**Features:**
|
|
19
|
+
- Focused testing on initial items
|
|
20
|
+
- Quick validation of basic functionality
|
|
21
|
+
- Useful for CI/CD pipelines
|
|
22
|
+
|
|
23
|
+
**Usage:**
|
|
24
|
+
```powershell
|
|
25
|
+
.\scripts\testing\test-first.ps1 -ServiceName my-service
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### test-first50.ps1
|
|
29
|
+
Test the first 50 services or items.
|
|
30
|
+
|
|
31
|
+
**Features:**
|
|
32
|
+
- Batch testing of multiple items
|
|
33
|
+
- Performance validation
|
|
34
|
+
- Scalability testing
|
|
35
|
+
|
|
36
|
+
**Usage:**
|
|
37
|
+
```powershell
|
|
38
|
+
.\scripts\testing\test-first50.ps1 -ServiceType api-gateway
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Common Parameters
|
|
42
|
+
|
|
43
|
+
All testing scripts support:
|
|
44
|
+
- `ServiceName` - Name of the service to test
|
|
45
|
+
- `ServiceType` - Type of service to test
|
|
46
|
+
- `DomainName` - Domain to test against
|
|
47
|
+
- `NonInteractive` - Run without user interaction
|
|
48
|
+
- `TemplatePath` - Path to test templates
|
|
49
|
+
- `OutputPath` - Output directory for test results
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Utility Scripts
|
|
2
|
+
|
|
3
|
+
General utility scripts for maintenance, validation, and operations.
|
|
4
|
+
|
|
5
|
+
## Scripts
|
|
6
|
+
|
|
7
|
+
### check-bundle.js
|
|
8
|
+
Validate and check bundle integrity for deployments.
|
|
9
|
+
|
|
10
|
+
**Features:**
|
|
11
|
+
- Bundle size validation
|
|
12
|
+
- Dependency checking
|
|
13
|
+
- Asset verification
|
|
14
|
+
- Performance metrics
|
|
15
|
+
|
|
16
|
+
**Usage:**
|
|
17
|
+
```bash
|
|
18
|
+
node scripts/utilities/check-bundle.js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### cleanup-cli.js
|
|
22
|
+
Clean up CLI tools and temporary files.
|
|
23
|
+
|
|
24
|
+
**Features:**
|
|
25
|
+
- Remove temporary files
|
|
26
|
+
- Clean build artifacts
|
|
27
|
+
- Clear cache directories
|
|
28
|
+
- Disk space optimization
|
|
29
|
+
|
|
30
|
+
**Usage:**
|
|
31
|
+
```bash
|
|
32
|
+
node scripts/utilities/cleanup-cli.js
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### generate-secrets.js
|
|
36
|
+
Generate secure secrets and tokens for services.
|
|
37
|
+
|
|
38
|
+
**Features:**
|
|
39
|
+
- Cryptographically secure random generation
|
|
40
|
+
- Multiple secret types (API keys, JWT secrets, etc.)
|
|
41
|
+
- Configurable entropy levels
|
|
42
|
+
- Secure storage recommendations
|
|
43
|
+
|
|
44
|
+
**Usage:**
|
|
45
|
+
```bash
|
|
46
|
+
node scripts/utilities/generate-secrets.js --type jwt --length 256
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### validate-schema.js
|
|
50
|
+
Validate configuration schemas and data structures.
|
|
51
|
+
|
|
52
|
+
**Features:**
|
|
53
|
+
- JSON schema validation
|
|
54
|
+
- Configuration file checking
|
|
55
|
+
- Data structure verification
|
|
56
|
+
- Error reporting and suggestions
|
|
57
|
+
|
|
58
|
+
**Usage:**
|
|
59
|
+
```bash
|
|
60
|
+
node scripts/utilities/validate-schema.js --file config/domains.js --schema domain-schema.json
|
|
61
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
|
|
8
|
+
// Go up two levels from scripts/utilities/ to project root, then to dist/
|
|
9
|
+
const distDir = path.join(__dirname, '..', '..', 'dist');
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(distDir)) {
|
|
12
|
+
console.error('dist/ directory does not exist. Run npm run build first.');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const files = fs.readdirSync(distDir);
|
|
17
|
+
if (files.length === 0) {
|
|
18
|
+
console.error('dist/ directory is empty. Build may have failed.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.log(`Bundle check passed: ${files.length} files in dist/`);
|
|
23
|
+
files.forEach(file => console.log(`- ${file}`));
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check Dist Imports
|
|
5
|
+
*
|
|
6
|
+
* Validates that all relative imports in `dist/` resolve to paths inside `dist/`.
|
|
7
|
+
* This prevents published packages from including relative imports that escape
|
|
8
|
+
* the `dist/` tree and point to non-existent files at package root.
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
|
|
14
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const projectRoot = path.join(__dirname, '../../');
|
|
16
|
+
const distRoot = path.join(projectRoot, 'dist');
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(distRoot)) {
|
|
19
|
+
console.error('dist/ directory not found. Run: npm run build');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function walk(dir) {
|
|
24
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
25
|
+
const files = [];
|
|
26
|
+
for (const e of entries) {
|
|
27
|
+
const full = path.join(dir, e.name);
|
|
28
|
+
if (e.isDirectory()) files.push(...walk(full));
|
|
29
|
+
else if (e.isFile() && full.endsWith('.js')) files.push(full);
|
|
30
|
+
}
|
|
31
|
+
return files;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const importRegex = /(?:from\s+['"]([^'"\n]+)['"])|(?:import\(['"]([^'"\n]+)['"]\))/g;
|
|
35
|
+
let failures = [];
|
|
36
|
+
const files = walk(distRoot);
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
39
|
+
let m;
|
|
40
|
+
while ((m = importRegex.exec(content)) !== null) {
|
|
41
|
+
const imp = m[1] || m[2];
|
|
42
|
+
if (!imp) continue;
|
|
43
|
+
// only check relative imports
|
|
44
|
+
if (!imp.startsWith('.')) continue;
|
|
45
|
+
|
|
46
|
+
// Resolve the import target
|
|
47
|
+
const resolved = path.resolve(path.dirname(file), imp);
|
|
48
|
+
const normalizedDist = path.resolve(distRoot) + path.sep;
|
|
49
|
+
if (!resolved.startsWith(normalizedDist)) {
|
|
50
|
+
failures.push({ file, imp, resolved });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (failures.length > 0) {
|
|
56
|
+
console.error('\nā Dist import validation failed. The following relative imports resolve outside dist/:\n');
|
|
57
|
+
for (const f of failures) {
|
|
58
|
+
console.error(` - ${path.relative(projectRoot, f.file)} imports '${f.imp}' ā resolves to ${f.resolved}`);
|
|
59
|
+
}
|
|
60
|
+
console.error(`\nRecommendation: adjust relative imports so they point into 'dist/' (e.g. '../lib/...' from dist/<subdir>/ files).`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('\nā
All relative imports in dist/ resolve inside dist/.');
|
|
65
|
+
process.exit(0);
|