{"_id":"@berryn/preservation","_rev":"3-68a1cc64ccc48d7c3ac4cca7f6d58d74","name":"@berryn/preservation","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@berryn/preservation","version":"0.1.0","author":"Berryn Core Engineering Team","license":"MIT","_id":"@berryn/preservation@0.1.0","maintainers":[{"name":"aaryan28","email":"aaryan28rwt@gmail.com"}],"homepage":"https://github.com/Grevix/berryn","bugs":{"url":"https://github.com/Grevix/berryn/issues"},"dist":{"shasum":"6b460e59e59bf230bda4d140f2b368fceb18be11","tarball":"https://registry.npmjs.org/@berryn/preservation/-/preservation-0.1.0.tgz","fileCount":17,"integrity":"sha512-7+WLUweSoWo7/8WrbnGjkrN2TiG1XP7TTRWh2JdGSBDKX0EBw4n97QiJEaStjtGD7EsL42Lsch+7XZ2txxfXUA==","signatures":[{"sig":"MEUCICyaXfDkyt8raFWWCANvOQviTrzO7gJ3c2bNV4CQjXmxAiEAxtSyxcS2eIue6COO8GnOQiTx9ePQmc+7VMBkR2evmc0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11118},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"scripts":{"build":"tsc --build","clean":"rimraf dist"},"_npmUser":{"name":"aaryan28","email":"aaryan28rwt@gmail.com"},"repository":{"url":"https://github.com/Grevix/berryn.git","type":"git"},"description":"Berryn Bounded Preservation Engine — Preservation manifests and no-silent-loss mutation guards","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@berryn/core":"0.1.0","@berryn/diagnostics":"0.1.0","@berryn/xlsx-inspect":"0.1.0"},"_hasShrinkwrap":false,"devDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/preservation_0.1.0_1787000976086_0.9925232414311547","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@berryn/preservation","version":"0.2.0","author":{"name":"Berryn Core Engineering Team"},"license":"MIT","_id":"@berryn/preservation@0.2.0","maintainers":[{"name":"aaryan28","email":"aaryan28rwt@gmail.com"}],"homepage":"https://github.com/Grevix/berryn#readme","bugs":{"url":"https://github.com/Grevix/berryn/issues"},"dist":{"shasum":"5e6fa7b763f37b1b17990b52bb5a378588b18a2b","tarball":"https://registry.npmjs.org/@berryn/preservation/-/preservation-0.2.0.tgz","fileCount":14,"integrity":"sha512-0SibUk6HcYJ38k7mQ7lGOw49aPt1ijwgHqiucf3pAGiP3mLYpTe+OyLwA8KKmlDrm+fVBPVHIKBMHSzVvUQB8g==","signatures":[{"sig":"MEYCIQCC3jJdx8tZy82x2LXoQsukjXIpQv2/ANZeg/2QexX2VQIhAMrkWtbbCt8b17uz3Z1LNZ18xTkAK2QK7btZJzmrSAo5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12573},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"fc466500ff83c2753bb41429713719eacd7895d4","scripts":{"build":"tsc --build","clean":"rimraf dist"},"_npmUser":{"name":"aaryan28","email":"aaryan28rwt@gmail.com"},"repository":{"url":"git+https://github.com/Grevix/berryn.git","type":"git"},"_npmVersion":"11.9.0","description":"Berryn Bounded Preservation Engine — Preservation manifests and no-silent-loss mutation guards","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@berryn/core":"workspace:*","@berryn/diagnostics":"workspace:*","@berryn/xlsx-inspect":"workspace:*"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/preservation_0.2.0_1788160244123_0.8278162878424937","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@berryn/preservation","version":"0.2.1","description":"Berryn Bounded Preservation Engine — Preservation manifests and no-silent-loss mutation guards","repository":{"type":"git","url":"git+https://github.com/Grevix/berryn.git"},"homepage":"https://github.com/Grevix/berryn#readme","bugs":{"url":"https://github.com/Grevix/berryn/issues"},"license":"MIT","author":{"name":"Berryn Core Engineering Team"},"engines":{"node":">=22.0.0"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"type":"module","scripts":{"build":"tsc --build","clean":"rimraf dist"},"dependencies":{"@berryn/core":"0.2.1","@berryn/diagnostics":"0.2.1","@berryn/xlsx-inspect":"0.2.1"},"devDependencies":{},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"gitHead":"576fa2934836ad4f045966f8a86d99490cbea05b","_id":"@berryn/preservation@0.2.1","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-qtxlMc51DWy0Rzks9dVgdxHlWW7iCekVDIHMCHphA0Ql7Z990+Go6j1Vg9s3Y33IFUMXIfJ3M+exOSox++vv7A==","shasum":"3179eb78fdf3d9da6642a8c8037474f770146ca8","tarball":"https://registry.npmjs.org/@berryn/preservation/-/preservation-0.2.1.tgz","fileCount":14,"unpackedSize":12555,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCLCroHO/bxCTv4ZsQGa+72Tl79EF8n21nAcXiyiACkGgIgBddY7guIBEDJXPXIKdqoqUJ85egJiLMvk1txZGuy+Ms="}]},"_npmUser":{"name":"aaryan28","email":"aaryan28rwt@gmail.com"},"directories":{},"maintainers":[{"name":"aaryan28","email":"aaryan28rwt@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/preservation_0.2.1_1788165854287_0.6469753937133664"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-17T21:09:35.835Z","modified":"2026-08-31T08:44:15.286Z","0.1.0":"2026-08-17T21:09:36.216Z","0.2.0":"2026-08-31T07:10:44.243Z","0.2.1":"2026-08-31T08:44:14.420Z"},"bugs":{"url":"https://github.com/Grevix/berryn/issues"},"author":{"name":"Berryn Core Engineering Team"},"license":"MIT","homepage":"https://github.com/Grevix/berryn#readme","repository":{"type":"git","url":"git+https://github.com/Grevix/berryn.git"},"description":"Berryn Bounded Preservation Engine — Preservation manifests and no-silent-loss mutation guards","maintainers":[{"name":"aaryan28","email":"aaryan28rwt@gmail.com"}],"readme":"# @berryn/preservation\n\n> **Opaque OOXML part preservation manifest and `assertNoSilentLoss()` mutation safety guard.**\n\n[![npm version](https://img.shields.io/npm/v/@berryn/preservation.svg)](https://www.npmjs.com/package/@berryn/preservation)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.7%2B-blue.svg)](https://www.typescriptlang.org/)\n\n---\n\n## Overview\n\nA critical flaw in legacy spreadsheet libraries (such as older versions of SheetJS/`xlsx` or `exceljs`) is the silent deletion of unmodeled OOXML parts. When a library opens a workbook containing pivot tables, VBA macros, embedded vector drawings, custom XML parts, or chart sheets, it frequently discards them upon re-serialization without warning the user.\n\n`@berryn/preservation` establishes an immutable contract: **No Silent Data Loss**. It tracks all container parts via a `PreservationManifest` and enforces strict invariants with `assertNoSilentLoss()`. If a mutation drops an unmodeled opaque part, Berryn aborts and throws an explicit error rather than producing corrupted files.\n\n---\n\n## Installation\n\n```bash\n# Using pnpm\npnpm add @berryn/preservation\n\n# Using npm\nnpm install @berryn/preservation\n```\n\n---\n\n## How It Works\n\n```mermaid\nflowchart LR\n    A[Original Workbook] --> B[Compute Preservation Manifest]\n    B --> C{Preservation Action}\n    C -->|Core Part| D[Semantically Rewritten]\n    C -->|Opaque Part: Pivot/Drawing| E[Opaque Retained Byte-for-Byte]\n    C -->|Unmodeled Part Dropped?| F[assertNoSilentLoss Throws NoSilentLossError]\n```\n\n1. **Manifest Computation (`computePreservationManifest`)**: Inventories all parts within the source container and determines the preservation action (`byte-preserved`, `semantically-rewritten`, `opaque-retained`, `dropped-rejected`).\n2. **Mutation Guard (`assertNoSilentLoss`)**: Compares before/after manifests. If any `opaque-retained` part (e.g. chart, pivot table, drawing) is missing from the output manifest, it throws `NoSilentLossError` (`BRN-XLSX-004`).\n\n---\n\n## Usage Examples\n\n### 1. Computing a Preservation Manifest\n\n```typescript\nimport { readFileSync } from 'node:fs';\nimport { inspectXlsx } from '@berryn/xlsx-inspect';\nimport { computePreservationManifest } from '@berryn/preservation';\n\nconst buffer = readFileSync('template_with_charts.xlsx');\nconst { value: inspectionReport } = inspectXlsx(buffer);\n\nconst manifest = computePreservationManifest(inspectionReport);\n\nconsole.log(`Total Parts: ${manifest.totalParts}`);\nconsole.log(`Preserved Count: ${manifest.preservedPartCount}`);\nconsole.log(`Unmodeled Opaque Count: ${manifest.unmodeledOpaqueCount}`);\n\nfor (const part of manifest.parts) {\n  console.log(`${part.partPath}: [${part.preservationAction}]`);\n}\n```\n\n---\n\n### 2. Guarding Mutations with `assertNoSilentLoss`\n\n```typescript\nimport { computePreservationManifest, assertNoSilentLoss, NoSilentLossError } from '@berryn/preservation';\n\nconst beforeManifest = computePreservationManifest(beforeReport);\nconst afterManifest = computePreservationManifest(afterReport);\n\ntry {\n  // Asserts that no opaque-retained parts were dropped\n  assertNoSilentLoss(beforeManifest, afterManifest);\n  console.log('Preservation check clean: Zero silent data loss.');\n} catch (err) {\n  if (err instanceof NoSilentLossError) {\n    console.error('MUTATION BLOCKED:', err.message);\n  }\n}\n```\n\n---\n\n## Exported Symbols\n\n| Symbol | Category | Description |\n|---|---|---|\n| `computePreservationManifest` | Function | Generates a manifest classifying all parts into retention states. |\n| `assertNoSilentLoss` | Function | Compares before and after manifests, throwing if opaque parts were dropped. |\n| `NoSilentLossError` | Class | Error thrown upon violation with attached `BRN-XLSX-004` diagnostic. |\n| `PreservationManifest` | Interface | Schema containing manifest ID, part counts, and preservation state list. |\n| `PartPreservationState` | Interface | Per-part retention descriptor (`partPath`, `contentType`, `preservationAction`, `originalHash`). |\n\n---\n\n## Links\n\n- **Repository**: [https://github.com/Grevix/berryn](https://github.com/Grevix/berryn)\n- **License**: [MIT](https://opensource.org/licenses/MIT) © 2026 Berryn Core Engineering Team\n","readmeFilename":"README.md"}