vaspera 2.10.0 → 2.10.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/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.js +188 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js +363 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js +226 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/index.test.js +214 -0
- package/dist/__tests__/scanners/ai-code/index.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.js +67 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/index.test.js +84 -0
- package/dist/__tests__/scanners/deploy/index.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.js +88 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/types.test.js +126 -0
- package/dist/__tests__/scanners/deploy/types.test.js.map +1 -0
- package/dist/__tests__/scanners/fp-feedback.test.js +1 -1
- package/dist/__tests__/scanners/fp-feedback.test.js.map +1 -1
- package/dist/__tests__/scanners/fp-tracker.test.js +1 -1
- package/dist/__tests__/scanners/fp-tracker.test.js.map +1 -1
- package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.js +94 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js +195 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/index.test.js +120 -0
- package/dist/__tests__/scanners/runtime/index.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/types.test.js +126 -0
- package/dist/__tests__/scanners/runtime/types.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.js +187 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/index.test.js +87 -0
- package/dist/__tests__/scanners/scale/index.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.js +122 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/types.test.js +129 -0
- package/dist/__tests__/scanners/scale/types.test.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +874 -0
- package/dist/index.js.map +1 -1
- package/dist/install-skills.d.ts +11 -0
- package/dist/install-skills.d.ts.map +1 -0
- package/dist/install-skills.js +81 -0
- package/dist/install-skills.js.map +1 -0
- package/dist/scanners/ai-code/ai-detector.d.ts +25 -0
- package/dist/scanners/ai-code/ai-detector.d.ts.map +1 -0
- package/dist/scanners/ai-code/ai-detector.js +192 -0
- package/dist/scanners/ai-code/ai-detector.js.map +1 -0
- package/dist/scanners/ai-code/confidence-scorer.d.ts +40 -0
- package/dist/scanners/ai-code/confidence-scorer.d.ts.map +1 -0
- package/dist/scanners/ai-code/confidence-scorer.js +148 -0
- package/dist/scanners/ai-code/confidence-scorer.js.map +1 -0
- package/dist/scanners/ai-code/hallucination-checker.d.ts +36 -0
- package/dist/scanners/ai-code/hallucination-checker.d.ts.map +1 -0
- package/dist/scanners/ai-code/hallucination-checker.js +298 -0
- package/dist/scanners/ai-code/hallucination-checker.js.map +1 -0
- package/dist/scanners/ai-code/index.d.ts +30 -0
- package/dist/scanners/ai-code/index.d.ts.map +1 -0
- package/dist/scanners/ai-code/index.js +224 -0
- package/dist/scanners/ai-code/index.js.map +1 -0
- package/dist/scanners/ai-code/types.d.ts +192 -0
- package/dist/scanners/ai-code/types.d.ts.map +1 -0
- package/dist/scanners/ai-code/types.js +37 -0
- package/dist/scanners/ai-code/types.js.map +1 -0
- package/dist/scanners/deploy/health-checker.d.ts +38 -0
- package/dist/scanners/deploy/health-checker.d.ts.map +1 -0
- package/dist/scanners/deploy/health-checker.js +272 -0
- package/dist/scanners/deploy/health-checker.js.map +1 -0
- package/dist/scanners/deploy/index.d.ts +44 -0
- package/dist/scanners/deploy/index.d.ts.map +1 -0
- package/dist/scanners/deploy/index.js +208 -0
- package/dist/scanners/deploy/index.js.map +1 -0
- package/dist/scanners/deploy/provider-detector.d.ts +25 -0
- package/dist/scanners/deploy/provider-detector.d.ts.map +1 -0
- package/dist/scanners/deploy/provider-detector.js +177 -0
- package/dist/scanners/deploy/provider-detector.js.map +1 -0
- package/dist/scanners/deploy/types.d.ts +406 -0
- package/dist/scanners/deploy/types.d.ts.map +1 -0
- package/dist/scanners/deploy/types.js +58 -0
- package/dist/scanners/deploy/types.js.map +1 -0
- package/dist/scanners/deploy/vercel-integration.d.ts +52 -0
- package/dist/scanners/deploy/vercel-integration.d.ts.map +1 -0
- package/dist/scanners/deploy/vercel-integration.js +280 -0
- package/dist/scanners/deploy/vercel-integration.js.map +1 -0
- package/dist/scanners/runtime/app-launcher.d.ts +33 -0
- package/dist/scanners/runtime/app-launcher.d.ts.map +1 -0
- package/dist/scanners/runtime/app-launcher.js +419 -0
- package/dist/scanners/runtime/app-launcher.js.map +1 -0
- package/dist/scanners/runtime/golden-path-runner.d.ts +48 -0
- package/dist/scanners/runtime/golden-path-runner.d.ts.map +1 -0
- package/dist/scanners/runtime/golden-path-runner.js +373 -0
- package/dist/scanners/runtime/golden-path-runner.js.map +1 -0
- package/dist/scanners/runtime/index.d.ts +41 -0
- package/dist/scanners/runtime/index.d.ts.map +1 -0
- package/dist/scanners/runtime/index.js +164 -0
- package/dist/scanners/runtime/index.js.map +1 -0
- package/dist/scanners/runtime/playwright-executor.d.ts +50 -0
- package/dist/scanners/runtime/playwright-executor.d.ts.map +1 -0
- package/dist/scanners/runtime/playwright-executor.js +387 -0
- package/dist/scanners/runtime/playwright-executor.js.map +1 -0
- package/dist/scanners/runtime/types.d.ts +215 -0
- package/dist/scanners/runtime/types.d.ts.map +1 -0
- package/dist/scanners/runtime/types.js +40 -0
- package/dist/scanners/runtime/types.js.map +1 -0
- package/dist/scanners/scale/bottleneck-detector.d.ts +17 -0
- package/dist/scanners/scale/bottleneck-detector.d.ts.map +1 -0
- package/dist/scanners/scale/bottleneck-detector.js +250 -0
- package/dist/scanners/scale/bottleneck-detector.js.map +1 -0
- package/dist/scanners/scale/capacity-estimator.d.ts +17 -0
- package/dist/scanners/scale/capacity-estimator.d.ts.map +1 -0
- package/dist/scanners/scale/capacity-estimator.js +197 -0
- package/dist/scanners/scale/capacity-estimator.js.map +1 -0
- package/dist/scanners/scale/index.d.ts +37 -0
- package/dist/scanners/scale/index.d.ts.map +1 -0
- package/dist/scanners/scale/index.js +101 -0
- package/dist/scanners/scale/index.js.map +1 -0
- package/dist/scanners/scale/load-profiler.d.ts +48 -0
- package/dist/scanners/scale/load-profiler.d.ts.map +1 -0
- package/dist/scanners/scale/load-profiler.js +377 -0
- package/dist/scanners/scale/load-profiler.js.map +1 -0
- package/dist/scanners/scale/types.d.ts +529 -0
- package/dist/scanners/scale/types.d.ts.map +1 -0
- package/dist/scanners/scale/types.js +57 -0
- package/dist/scanners/scale/types.js.map +1 -0
- package/dist/scanners/secrets.d.ts.map +1 -1
- package/dist/scanners/secrets.js +13 -2
- package/dist/scanners/secrets.js.map +1 -1
- package/package.json +4 -2
- package/skills/vaspera-add-tests/SKILL.md +102 -0
- package/skills/vaspera-ai-verify/SKILL.md +166 -0
- package/skills/vaspera-audit/SKILL.md +67 -0
- package/skills/vaspera-certify/SKILL.md +130 -0
- package/skills/vaspera-deploy/SKILL.md +152 -0
- package/skills/vaspera-fix-critical/SKILL.md +52 -0
- package/skills/vaspera-fix-high/SKILL.md +81 -0
- package/skills/vaspera-fix-medium/SKILL.md +56 -0
- package/skills/vaspera-fix-rls/SKILL.md +85 -0
- package/skills/vaspera-harden/SKILL.md +102 -0
- package/skills/vaspera-help/SKILL.md +61 -0
- package/skills/vaspera-load-test/SKILL.md +167 -0
- package/skills/vaspera-verify/SKILL.md +70 -0
- package/skills/vaspera-verify-e2e/SKILL.md +117 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Verification Scanner
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates deployment verification including health checks,
|
|
5
|
+
* smoke tests, and canary analysis.
|
|
6
|
+
*
|
|
7
|
+
* @module scanners/deploy
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, mkdir, writeFile } from "fs/promises";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
import { parse as parseYaml } from "yaml";
|
|
12
|
+
import { logger } from "../../logger.js";
|
|
13
|
+
import { detectProvider } from "./provider-detector.js";
|
|
14
|
+
import { checkAllHealth, runAllSmokeTests, calculateHealthScore, calculateSmokeTestScore, } from "./health-checker.js";
|
|
15
|
+
import { isVercelAvailable, getLatestDeployment, analyzeCanary, } from "./vercel-integration.js";
|
|
16
|
+
import { DeployConfigSchema, } from "./types.js";
|
|
17
|
+
export * from "./types.js";
|
|
18
|
+
export { detectProvider, isDeploymentEnvironment, } from "./provider-detector.js";
|
|
19
|
+
export { checkAllHealth, runAllSmokeTests, calculateHealthScore, calculateSmokeTestScore, } from "./health-checker.js";
|
|
20
|
+
export { isVercelAvailable, getLatestDeployment, getDeployment, listDeployments, promoteToProduction, rollback, analyzeCanary, } from "./vercel-integration.js";
|
|
21
|
+
const CONFIG_PATH = ".vaspera/deploy.yaml";
|
|
22
|
+
/**
|
|
23
|
+
* Load deployment config
|
|
24
|
+
*/
|
|
25
|
+
export async function loadDeployConfig(projectPath) {
|
|
26
|
+
try {
|
|
27
|
+
const configPath = join(projectPath, CONFIG_PATH);
|
|
28
|
+
const content = await readFile(configPath, "utf-8");
|
|
29
|
+
const parsed = parseYaml(content);
|
|
30
|
+
return DeployConfigSchema.parse(parsed);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate sample deploy config
|
|
38
|
+
*/
|
|
39
|
+
export async function generateDeployConfig(projectPath, provider) {
|
|
40
|
+
const configDir = join(projectPath, ".vaspera");
|
|
41
|
+
await mkdir(configDir, { recursive: true });
|
|
42
|
+
const config = `# Deployment Verification Configuration
|
|
43
|
+
# This file configures health checks, smoke tests, and canary deployment
|
|
44
|
+
|
|
45
|
+
${provider ? `provider: ${provider}` : "# provider: vercel # Auto-detected if not specified"}
|
|
46
|
+
|
|
47
|
+
# Endpoints to check for health
|
|
48
|
+
healthEndpoints:
|
|
49
|
+
- /
|
|
50
|
+
- /api/health
|
|
51
|
+
|
|
52
|
+
# Smoke tests to run after deployment
|
|
53
|
+
smokeTests:
|
|
54
|
+
- name: "Homepage loads"
|
|
55
|
+
endpoint: "/"
|
|
56
|
+
method: GET
|
|
57
|
+
expectedStatus: 200
|
|
58
|
+
|
|
59
|
+
- name: "API health check"
|
|
60
|
+
endpoint: "/api/health"
|
|
61
|
+
method: GET
|
|
62
|
+
expectedStatus: 200
|
|
63
|
+
assertions:
|
|
64
|
+
- type: latency
|
|
65
|
+
operator: lt
|
|
66
|
+
value: 500
|
|
67
|
+
|
|
68
|
+
# Add your critical path tests:
|
|
69
|
+
# - name: "User can login"
|
|
70
|
+
# endpoint: "/api/auth/login"
|
|
71
|
+
# method: POST
|
|
72
|
+
# expectedStatus: 200
|
|
73
|
+
# body:
|
|
74
|
+
# email: "test@example.com"
|
|
75
|
+
# password: "testpass"
|
|
76
|
+
|
|
77
|
+
# Canary deployment settings (for supported providers)
|
|
78
|
+
canary:
|
|
79
|
+
enabled: false
|
|
80
|
+
trafficPercent: 10
|
|
81
|
+
duration: "10m"
|
|
82
|
+
thresholds:
|
|
83
|
+
errorRate: 0.01
|
|
84
|
+
p95Latency: 500
|
|
85
|
+
healthCheckFailures: 2
|
|
86
|
+
rollbackOnFailure: true
|
|
87
|
+
|
|
88
|
+
# Rollback settings
|
|
89
|
+
rollback:
|
|
90
|
+
autoRollback: true
|
|
91
|
+
retainVersions: 5
|
|
92
|
+
|
|
93
|
+
# Optional notifications
|
|
94
|
+
# notifications:
|
|
95
|
+
# slack: "https://hooks.slack.com/..."
|
|
96
|
+
# email:
|
|
97
|
+
# - team@example.com
|
|
98
|
+
`;
|
|
99
|
+
const configPath = join(configDir, "deploy.yaml");
|
|
100
|
+
await writeFile(configPath, config, "utf-8");
|
|
101
|
+
logger.info("deploy.config_generated", { path: configPath });
|
|
102
|
+
return configPath;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Run deployment verification
|
|
106
|
+
*/
|
|
107
|
+
export async function runDeployVerification(projectPath, deploymentUrl, options = {}) {
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
logger.info("deploy.verification_started", { projectPath, deploymentUrl });
|
|
110
|
+
// Detect provider
|
|
111
|
+
const providerDetection = await detectProvider(projectPath);
|
|
112
|
+
// Load config
|
|
113
|
+
const config = await loadDeployConfig(projectPath);
|
|
114
|
+
const healthEndpoints = config?.healthEndpoints || ["/", "/api/health"];
|
|
115
|
+
const smokeTests = config?.smokeTests || [];
|
|
116
|
+
// Run health checks
|
|
117
|
+
let healthResults = [];
|
|
118
|
+
if (!options.skipHealthCheck) {
|
|
119
|
+
healthResults = await checkAllHealth(deploymentUrl, healthEndpoints);
|
|
120
|
+
}
|
|
121
|
+
// Run smoke tests
|
|
122
|
+
let smokeTestResults = [];
|
|
123
|
+
if (!options.skipSmokeTests && smokeTests.length > 0) {
|
|
124
|
+
smokeTestResults = await runAllSmokeTests(deploymentUrl, smokeTests);
|
|
125
|
+
}
|
|
126
|
+
// Run canary analysis if requested
|
|
127
|
+
let canaryResult;
|
|
128
|
+
if (options.runCanary) {
|
|
129
|
+
canaryResult = await analyzeCanary(deploymentUrl, {
|
|
130
|
+
duration: options.canaryDuration || 60000,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Calculate scores
|
|
134
|
+
const healthScore = calculateHealthScore(healthResults);
|
|
135
|
+
const smokeTestScore = smokeTests.length > 0
|
|
136
|
+
? calculateSmokeTestScore(smokeTestResults)
|
|
137
|
+
: 50; // Neutral if no tests
|
|
138
|
+
const canaryScore = canaryResult
|
|
139
|
+
? (canaryResult.thresholdsPassed ? 100 : 30)
|
|
140
|
+
: 50; // Neutral if no canary
|
|
141
|
+
const overallScore = Math.round((healthScore * 0.4) + (smokeTestScore * 0.4) + (canaryScore * 0.2));
|
|
142
|
+
// Get deployment info if Vercel
|
|
143
|
+
let deployment;
|
|
144
|
+
if (providerDetection.provider === "vercel" && isVercelAvailable() && providerDetection.projectId) {
|
|
145
|
+
deployment = await getLatestDeployment(providerDetection.projectId) || undefined;
|
|
146
|
+
}
|
|
147
|
+
const result = {
|
|
148
|
+
success: overallScore >= 70,
|
|
149
|
+
provider: providerDetection.provider,
|
|
150
|
+
deployment,
|
|
151
|
+
healthChecks: healthResults,
|
|
152
|
+
smokeTests: smokeTestResults,
|
|
153
|
+
canary: canaryResult,
|
|
154
|
+
score: {
|
|
155
|
+
healthScore,
|
|
156
|
+
smokeTestScore,
|
|
157
|
+
canaryScore,
|
|
158
|
+
overallScore,
|
|
159
|
+
},
|
|
160
|
+
duration: Date.now() - startTime,
|
|
161
|
+
};
|
|
162
|
+
logger.info("deploy.verification_completed", {
|
|
163
|
+
success: result.success,
|
|
164
|
+
overallScore,
|
|
165
|
+
healthScore,
|
|
166
|
+
smokeTestScore,
|
|
167
|
+
canaryScore,
|
|
168
|
+
duration: result.duration,
|
|
169
|
+
});
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Quick health check (no smoke tests or canary)
|
|
174
|
+
*/
|
|
175
|
+
export async function quickDeployCheck(deploymentUrl, endpoints = ["/", "/api/health"]) {
|
|
176
|
+
const checks = await checkAllHealth(deploymentUrl, endpoints);
|
|
177
|
+
const score = calculateHealthScore(checks);
|
|
178
|
+
return {
|
|
179
|
+
healthy: score >= 70,
|
|
180
|
+
score,
|
|
181
|
+
checks,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create default smoke tests from OpenAPI/routes
|
|
186
|
+
*/
|
|
187
|
+
export function createDefaultSmokeTests() {
|
|
188
|
+
return [
|
|
189
|
+
{
|
|
190
|
+
name: "Homepage loads",
|
|
191
|
+
endpoint: "/",
|
|
192
|
+
method: "GET",
|
|
193
|
+
expectedStatus: 200,
|
|
194
|
+
timeout: 10000,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "Health endpoint",
|
|
198
|
+
endpoint: "/api/health",
|
|
199
|
+
method: "GET",
|
|
200
|
+
expectedStatus: 200,
|
|
201
|
+
timeout: 10000,
|
|
202
|
+
assertions: [
|
|
203
|
+
{ type: "latency", operator: "lt", value: 500 },
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/deploy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACjF,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EAKnB,aAAa,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,GAKnB,MAAM,YAAY,CAAC;AAEpB,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,QAAQ,EACR,aAAa,GACd,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB;IACxD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,QAAyB;IAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG;;;EAGf,QAAQ,CAAC,CAAC,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC,CAAC,sDAAsD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqD5F,CAAC;IAEA,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAClD,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE7C,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAE7D,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,WAAmB,EACnB,aAAqB,EACrB,UAKI,EAAE;IAEN,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC;IAE3E,kBAAkB;IAClB,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IAE5D,cAAc;IACd,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,eAAe,GAAG,MAAM,EAAE,eAAe,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,IAAI,EAAE,CAAC;IAE5C,oBAAoB;IACpB,IAAI,aAAa,GAA+C,EAAE,CAAC;IACnE,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC7B,aAAa,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IACvE,CAAC;IAED,kBAAkB;IAClB,IAAI,gBAAgB,GAAiD,EAAE,CAAC;IACxE,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IACvE,CAAC;IAED,mCAAmC;IACnC,IAAI,YAAmE,CAAC;IACxE,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,YAAY,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE;YAChD,QAAQ,EAAE,OAAO,CAAC,cAAc,IAAI,KAAK;SAC1C,CAAC,CAAC;IACL,CAAC;IAED,mBAAmB;IACnB,MAAM,WAAW,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC;QAC1C,CAAC,CAAC,uBAAuB,CAAC,gBAAgB,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC,CAAC,sBAAsB;IAC9B,MAAM,WAAW,GAAG,YAAY;QAC9B,CAAC,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,CAAC,CAAC,EAAE,CAAC,CAAC,uBAAuB;IAE/B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAC7B,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,CACnE,CAAC;IAEF,gCAAgC;IAChC,IAAI,UAAU,CAAC;IACf,IAAI,iBAAiB,CAAC,QAAQ,KAAK,QAAQ,IAAI,iBAAiB,EAAE,IAAI,iBAAiB,CAAC,SAAS,EAAE,CAAC;QAClG,UAAU,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;IACnF,CAAC;IAED,MAAM,MAAM,GAA6B;QACvC,OAAO,EAAE,YAAY,IAAI,EAAE;QAC3B,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;QACpC,UAAU;QACV,YAAY,EAAE,aAAa;QAC3B,UAAU,EAAE,gBAAgB;QAC5B,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE;YACL,WAAW;YACX,cAAc;YACd,WAAW;YACX,YAAY;SACb;QACD,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACjC,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;QAC3C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,YAAY;QACZ,WAAW;QACX,cAAc;QACd,WAAW;QACX,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,aAAqB,EACrB,YAAsB,CAAC,GAAG,EAAE,aAAa,CAAC;IAM1C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,KAAK,IAAI,EAAE;QACpB,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL;YACE,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,GAAG;YACnB,OAAO,EAAE,KAAK;SACf;QACD;YACE,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,aAAa;YACvB,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,GAAG;YACnB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE;gBACV,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;aAChD;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects deployment provider from project configuration.
|
|
5
|
+
*
|
|
6
|
+
* @module scanners/deploy/provider-detector
|
|
7
|
+
*/
|
|
8
|
+
import type { DeployProvider, ProviderDetection } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Detect deployment provider from project
|
|
11
|
+
*/
|
|
12
|
+
export declare function detectProvider(projectPath: string): Promise<ProviderDetection>;
|
|
13
|
+
/**
|
|
14
|
+
* Get provider-specific deployment URL pattern
|
|
15
|
+
*/
|
|
16
|
+
export declare function getDeploymentUrlPattern(provider: DeployProvider): RegExp | null;
|
|
17
|
+
/**
|
|
18
|
+
* Check if running in a deployment environment
|
|
19
|
+
*/
|
|
20
|
+
export declare function isDeploymentEnvironment(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Get current environment from provider
|
|
23
|
+
*/
|
|
24
|
+
export declare function getCurrentEnvironment(provider: DeployProvider): string;
|
|
25
|
+
//# sourceMappingURL=provider-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-detector.d.ts","sourceRoot":"","sources":["../../../src/scanners/deploy/provider-detector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAiDpE;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwFpF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAa/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CASjD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAWtE"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects deployment provider from project configuration.
|
|
5
|
+
*
|
|
6
|
+
* @module scanners/deploy/provider-detector
|
|
7
|
+
*/
|
|
8
|
+
import { readFile, access } from "fs/promises";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
import { logger } from "../../logger.js";
|
|
11
|
+
/**
|
|
12
|
+
* Provider detection patterns
|
|
13
|
+
*/
|
|
14
|
+
const PROVIDER_PATTERNS = [
|
|
15
|
+
{
|
|
16
|
+
provider: "vercel",
|
|
17
|
+
files: ["vercel.json", "vercel.ts", ".vercel/project.json"],
|
|
18
|
+
packageIndicators: ["@vercel/node", "@vercel/next", "vercel"],
|
|
19
|
+
envIndicators: ["VERCEL", "VERCEL_URL", "VERCEL_ENV"],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
provider: "aws",
|
|
23
|
+
files: ["serverless.yml", "serverless.yaml", "samconfig.toml", "cdk.json", "amplify.yml"],
|
|
24
|
+
packageIndicators: ["@aws-cdk/core", "aws-cdk-lib", "serverless", "@aws-amplify/cli"],
|
|
25
|
+
envIndicators: ["AWS_REGION", "AWS_LAMBDA_FUNCTION_NAME"],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
provider: "gcp",
|
|
29
|
+
files: ["app.yaml", "cloudbuild.yaml", ".gcloudignore"],
|
|
30
|
+
packageIndicators: ["@google-cloud/functions-framework", "firebase-functions"],
|
|
31
|
+
envIndicators: ["GOOGLE_CLOUD_PROJECT", "GCLOUD_PROJECT", "GCP_PROJECT"],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
provider: "railway",
|
|
35
|
+
files: ["railway.json", "railway.toml"],
|
|
36
|
+
packageIndicators: [],
|
|
37
|
+
envIndicators: ["RAILWAY_ENVIRONMENT", "RAILWAY_PROJECT_ID"],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
provider: "render",
|
|
41
|
+
files: ["render.yaml"],
|
|
42
|
+
packageIndicators: [],
|
|
43
|
+
envIndicators: ["RENDER", "RENDER_SERVICE_ID"],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
provider: "fly",
|
|
47
|
+
files: ["fly.toml"],
|
|
48
|
+
packageIndicators: [],
|
|
49
|
+
envIndicators: ["FLY_APP_NAME", "FLY_REGION"],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Detect deployment provider from project
|
|
54
|
+
*/
|
|
55
|
+
export async function detectProvider(projectPath) {
|
|
56
|
+
const indicators = [];
|
|
57
|
+
let bestMatch;
|
|
58
|
+
let bestConfidence = 0;
|
|
59
|
+
for (const pattern of PROVIDER_PATTERNS) {
|
|
60
|
+
let confidence = 0;
|
|
61
|
+
// Check for provider-specific files
|
|
62
|
+
for (const file of pattern.files) {
|
|
63
|
+
try {
|
|
64
|
+
await access(join(projectPath, file));
|
|
65
|
+
confidence += 40;
|
|
66
|
+
indicators.push(`Found ${file}`);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// File doesn't exist
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Check package.json for dependencies
|
|
73
|
+
try {
|
|
74
|
+
const packageJsonPath = join(projectPath, "package.json");
|
|
75
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
|
|
76
|
+
const allDeps = {
|
|
77
|
+
...packageJson.dependencies,
|
|
78
|
+
...packageJson.devDependencies,
|
|
79
|
+
};
|
|
80
|
+
for (const indicator of pattern.packageIndicators) {
|
|
81
|
+
if (allDeps[indicator]) {
|
|
82
|
+
confidence += 25;
|
|
83
|
+
indicators.push(`Found ${indicator} in package.json`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// No package.json or parse error
|
|
89
|
+
}
|
|
90
|
+
// Check environment variables
|
|
91
|
+
for (const envVar of pattern.envIndicators) {
|
|
92
|
+
if (process.env[envVar]) {
|
|
93
|
+
confidence += 35;
|
|
94
|
+
indicators.push(`Found ${envVar} environment variable`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (confidence > bestConfidence) {
|
|
98
|
+
bestConfidence = confidence;
|
|
99
|
+
bestMatch = pattern;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (bestMatch && bestConfidence > 0) {
|
|
103
|
+
// Try to get project ID from config
|
|
104
|
+
let projectId;
|
|
105
|
+
let configPath;
|
|
106
|
+
if (bestMatch.provider === "vercel") {
|
|
107
|
+
try {
|
|
108
|
+
const vercelProject = JSON.parse(await readFile(join(projectPath, ".vercel/project.json"), "utf-8"));
|
|
109
|
+
projectId = vercelProject.projectId;
|
|
110
|
+
configPath = ".vercel/project.json";
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// No project.json
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
logger.info("deploy.provider_detected", {
|
|
117
|
+
provider: bestMatch.provider,
|
|
118
|
+
confidence: Math.min(bestConfidence, 100),
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
provider: bestMatch.provider,
|
|
122
|
+
confidence: Math.min(bestConfidence, 100),
|
|
123
|
+
indicators,
|
|
124
|
+
projectId,
|
|
125
|
+
configPath,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
provider: "unknown",
|
|
130
|
+
confidence: 0,
|
|
131
|
+
indicators: ["No deployment provider detected"],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get provider-specific deployment URL pattern
|
|
136
|
+
*/
|
|
137
|
+
export function getDeploymentUrlPattern(provider) {
|
|
138
|
+
switch (provider) {
|
|
139
|
+
case "vercel":
|
|
140
|
+
return /https:\/\/[\w-]+\.vercel\.app/;
|
|
141
|
+
case "railway":
|
|
142
|
+
return /https:\/\/[\w-]+\.railway\.app/;
|
|
143
|
+
case "render":
|
|
144
|
+
return /https:\/\/[\w-]+\.onrender\.com/;
|
|
145
|
+
case "fly":
|
|
146
|
+
return /https:\/\/[\w-]+\.fly\.dev/;
|
|
147
|
+
default:
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check if running in a deployment environment
|
|
153
|
+
*/
|
|
154
|
+
export function isDeploymentEnvironment() {
|
|
155
|
+
return !!(process.env.VERCEL ||
|
|
156
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
|
157
|
+
process.env.GOOGLE_CLOUD_PROJECT ||
|
|
158
|
+
process.env.RAILWAY_ENVIRONMENT ||
|
|
159
|
+
process.env.RENDER ||
|
|
160
|
+
process.env.FLY_APP_NAME);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get current environment from provider
|
|
164
|
+
*/
|
|
165
|
+
export function getCurrentEnvironment(provider) {
|
|
166
|
+
switch (provider) {
|
|
167
|
+
case "vercel":
|
|
168
|
+
return process.env.VERCEL_ENV || "development";
|
|
169
|
+
case "railway":
|
|
170
|
+
return process.env.RAILWAY_ENVIRONMENT || "development";
|
|
171
|
+
case "render":
|
|
172
|
+
return process.env.RENDER ? "production" : "development";
|
|
173
|
+
default:
|
|
174
|
+
return process.env.NODE_ENV || "development";
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=provider-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-detector.js","sourceRoot":"","sources":["../../../src/scanners/deploy/provider-detector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAGzC;;GAEG;AACH,MAAM,iBAAiB,GAKlB;IACH;QACE,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,sBAAsB,CAAC;QAC3D,iBAAiB,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,CAAC;QAC7D,aAAa,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC;KACtD;IACD;QACE,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,CAAC;QACzF,iBAAiB,EAAE,CAAC,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,CAAC;QACrF,aAAa,EAAE,CAAC,YAAY,EAAE,0BAA0B,CAAC;KAC1D;IACD;QACE,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,eAAe,CAAC;QACvD,iBAAiB,EAAE,CAAC,mCAAmC,EAAE,oBAAoB,CAAC;QAC9E,aAAa,EAAE,CAAC,sBAAsB,EAAE,gBAAgB,EAAE,aAAa,CAAC;KACzE;IACD;QACE,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;QACvC,iBAAiB,EAAE,EAAE;QACrB,aAAa,EAAE,CAAC,qBAAqB,EAAE,oBAAoB,CAAC;KAC7D;IACD;QACE,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,CAAC,aAAa,CAAC;QACtB,iBAAiB,EAAE,EAAE;QACrB,aAAa,EAAE,CAAC,QAAQ,EAAE,mBAAmB,CAAC;KAC/C;IACD;QACE,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,CAAC,UAAU,CAAC;QACnB,iBAAiB,EAAE,EAAE;QACrB,aAAa,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;KAC9C;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,SAAoD,CAAC;IACzD,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,oCAAoC;QACpC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;gBACtC,UAAU,IAAI,EAAE,CAAC;gBACjB,UAAU,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;QACH,CAAC;QAED,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;YACzE,MAAM,OAAO,GAAG;gBACd,GAAG,WAAW,CAAC,YAAY;gBAC3B,GAAG,WAAW,CAAC,eAAe;aAC/B,CAAC;YAEF,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;gBAClD,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;oBACvB,UAAU,IAAI,EAAE,CAAC;oBACjB,UAAU,CAAC,IAAI,CAAC,SAAS,SAAS,kBAAkB,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;QAED,8BAA8B;QAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxB,UAAU,IAAI,EAAE,CAAC;gBACjB,UAAU,CAAC,IAAI,CAAC,SAAS,MAAM,uBAAuB,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;YAChC,cAAc,GAAG,UAAU,CAAC;YAC5B,SAAS,GAAG,OAAO,CAAC;QACtB,CAAC;IACH,CAAC;IAED,IAAI,SAAS,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACpC,oCAAoC;QACpC,IAAI,SAA6B,CAAC;QAClC,IAAI,UAA8B,CAAC;QAEnC,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAC9B,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAAE,OAAO,CAAC,CACnE,CAAC;gBACF,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;gBACpC,UAAU,GAAG,sBAAsB,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,kBAAkB;YACpB,CAAC;QACH,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;YACtC,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC;SAC1C,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC;YACzC,UAAU;YACV,SAAS;YACT,UAAU;SACX,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC,iCAAiC,CAAC;KAChD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAwB;IAC9D,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,+BAA+B,CAAC;QACzC,KAAK,SAAS;YACZ,OAAO,gCAAgC,CAAC;QAC1C,KAAK,QAAQ;YACX,OAAO,iCAAiC,CAAC;QAC3C,KAAK,KAAK;YACR,OAAO,4BAA4B,CAAC;QACtC;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,CAAC,CAAC,CACP,OAAO,CAAC,GAAG,CAAC,MAAM;QAClB,OAAO,CAAC,GAAG,CAAC,wBAAwB;QACpC,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAChC,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAC/B,OAAO,CAAC,GAAG,CAAC,MAAM;QAClB,OAAO,CAAC,GAAG,CAAC,YAAY,CACzB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAwB;IAC5D,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,CAAC;QACjD,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,aAAa,CAAC;QAC1D,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;QAC3D;YACE,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;IACjD,CAAC;AACH,CAAC"}
|