Files
breakpilot-compliance/admin-compliance/lib/sdk/export-zip.ts
Sharang Parnerkar 58e95d5e8e refactor(admin): split 9 more oversized lib/ files into focused modules
Files split by agents before rate limit:
  - dsr/api.ts (669 → barrel + helpers)
  - einwilligungen/context.tsx (669 → barrel + hooks/reducer)
  - export.ts (753 → barrel + domain exporters)
  - incidents/api.ts (845 → barrel + api-helpers)
  - tom-generator/context.tsx (720 → barrel + hooks/reducer)
  - vendor-compliance/context.tsx (1010 → 234 provider + hooks/reducer)
  - api-docs/endpoints.ts — partially split (3 domain files created)
  - academy/api.ts — partially split (helpers extracted)
  - whistleblower/api.ts — partially split (helpers extracted)

next build passes. api-client.ts (885) deferred to next session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:12:09 +02:00

241 lines
7.4 KiB
TypeScript

/**
* SDK ZIP Export
* Packages SDK state, documents, and a PDF report into a ZIP archive
*/
import JSZip from 'jszip'
import { SDKState, SDK_STEPS } from './types'
import { ExportOptions, DEFAULT_OPTIONS, formatDate, exportToPDF } from './export-pdf'
// =============================================================================
// ZIP EXPORT
// =============================================================================
export async function exportToZIP(state: SDKState, options: ExportOptions = {}): Promise<Blob> {
const opts = { ...DEFAULT_OPTIONS, ...options }
const zip = new JSZip()
const rootFolder = zip.folder('ai-compliance-sdk-export')
if (!rootFolder) throw new Error('Failed to create ZIP folder')
const phase1Folder = rootFolder.folder('phase1-assessment')
const phase2Folder = rootFolder.folder('phase2-documents')
const dataFolder = rootFolder.folder('data')
// Main State JSON
if (opts.includeRawData && dataFolder) {
dataFolder.file('state.json', JSON.stringify(state, null, 2))
}
// README
const readmeContent = `# AI Compliance SDK Export
Generated: ${formatDate(new Date())}
Tenant: ${state.tenantId}
Version: ${state.version}
## Folder Structure
- **phase1-assessment/**: Compliance Assessment Ergebnisse
- use-cases.json: Alle Use Cases
- risks.json: Identifizierte Risiken
- controls.json: Definierte Controls
- requirements.json: Compliance-Anforderungen
- **phase2-documents/**: Generierte Dokumente
- dsfa.json: Datenschutz-Folgenabschaetzung
- toms.json: Technische und organisatorische Massnahmen
- vvt.json: Verarbeitungsverzeichnis
- documents.json: Rechtliche Dokumente
- **data/**: Rohdaten
- state.json: Kompletter SDK State
## Progress
Phase 1: ${SDK_STEPS.filter(s => s.phase === 1 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 1).length} completed
Phase 2: ${SDK_STEPS.filter(s => s.phase === 2 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 2).length} completed
## Key Metrics
- Use Cases: ${state.useCases.length}
- Risks: ${state.risks.length}
- Controls: ${state.controls.length}
- Requirements: ${state.requirements.length}
- Evidence: ${state.evidence.length}
`
rootFolder.file('README.md', readmeContent)
// Phase 1 Files
if (phase1Folder) {
phase1Folder.file('use-cases.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.useCases.length,
useCases: state.useCases,
}, null, 2))
phase1Folder.file('risks.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.risks.length,
risks: state.risks,
summary: {
critical: state.risks.filter(r => r.severity === 'CRITICAL').length,
high: state.risks.filter(r => r.severity === 'HIGH').length,
medium: state.risks.filter(r => r.severity === 'MEDIUM').length,
low: state.risks.filter(r => r.severity === 'LOW').length,
},
}, null, 2))
phase1Folder.file('controls.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.controls.length,
controls: state.controls,
}, null, 2))
phase1Folder.file('requirements.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.requirements.length,
requirements: state.requirements,
}, null, 2))
phase1Folder.file('modules.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.modules.length,
modules: state.modules,
}, null, 2))
if (opts.includeEvidence) {
phase1Folder.file('evidence.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.evidence.length,
evidence: state.evidence,
}, null, 2))
}
phase1Folder.file('checkpoints.json', JSON.stringify({
exportedAt: new Date().toISOString(),
checkpoints: state.checkpoints,
}, null, 2))
if (state.screening) {
phase1Folder.file('screening.json', JSON.stringify({
exportedAt: new Date().toISOString(),
screening: state.screening,
}, null, 2))
}
}
// Phase 2 Files
if (phase2Folder) {
if (state.dsfa) {
phase2Folder.file('dsfa.json', JSON.stringify({
exportedAt: new Date().toISOString(),
dsfa: state.dsfa,
}, null, 2))
}
phase2Folder.file('toms.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.toms.length,
toms: state.toms,
}, null, 2))
phase2Folder.file('vvt.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.vvt.length,
processingActivities: state.vvt,
}, null, 2))
if (opts.includeDocuments) {
phase2Folder.file('documents.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.documents.length,
documents: state.documents,
}, null, 2))
}
if (state.cookieBanner) {
phase2Folder.file('cookie-banner.json', JSON.stringify({
exportedAt: new Date().toISOString(),
config: state.cookieBanner,
}, null, 2))
}
phase2Folder.file('retention-policies.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.retentionPolicies.length,
policies: state.retentionPolicies,
}, null, 2))
if (state.aiActClassification) {
phase2Folder.file('ai-act-classification.json', JSON.stringify({
exportedAt: new Date().toISOString(),
classification: state.aiActClassification,
}, null, 2))
}
phase2Folder.file('obligations.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.obligations.length,
obligations: state.obligations,
}, null, 2))
phase2Folder.file('consents.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.consents.length,
consents: state.consents,
}, null, 2))
if (state.dsrConfig) {
phase2Folder.file('dsr-config.json', JSON.stringify({
exportedAt: new Date().toISOString(),
config: state.dsrConfig,
}, null, 2))
}
phase2Folder.file('escalation-workflows.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.escalationWorkflows.length,
workflows: state.escalationWorkflows,
}, null, 2))
}
// Security Data
if (dataFolder) {
if (state.sbom) {
dataFolder.file('sbom.json', JSON.stringify({
exportedAt: new Date().toISOString(),
sbom: state.sbom,
}, null, 2))
}
if (state.securityIssues.length > 0) {
dataFolder.file('security-issues.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.securityIssues.length,
issues: state.securityIssues,
}, null, 2))
}
if (state.securityBacklog.length > 0) {
dataFolder.file('security-backlog.json', JSON.stringify({
exportedAt: new Date().toISOString(),
count: state.securityBacklog.length,
backlog: state.securityBacklog,
}, null, 2))
}
}
// Generate PDF and include in ZIP
try {
const pdfBlob = await exportToPDF(state, options)
const pdfArrayBuffer = await pdfBlob.arrayBuffer()
rootFolder.file('compliance-report.pdf', pdfArrayBuffer)
} catch (error) {
console.error('Failed to generate PDF for ZIP:', error)
}
return zip.generateAsync({ type: 'blob', compression: 'DEFLATE' })
}