{"_id":"@droplinked_inc/editor-core","_rev":"3-54ac43834d7476251d58ae0089fb137b","name":"@droplinked_inc/editor-core","dist-tags":{"latest":"0.2.3"},"versions":{"0.2.0":{"name":"@droplinked_inc/editor-core","version":"0.2.0","license":"MIT","_id":"@droplinked_inc/editor-core@0.2.0","maintainers":[{"name":"droplinked_inc","email":"ali@droplinked.com"}],"homepage":"https://github.com/droplinked/droplink-packages#readme","bugs":{"url":"https://github.com/droplinked/droplink-packages/issues"},"dist":{"shasum":"26e098da5aafc0c16f08760171306476ea9ec87c","tarball":"https://registry.npmjs.org/@droplinked_inc/editor-core/-/editor-core-0.2.0.tgz","fileCount":56,"integrity":"sha512-Ycf3NfQrogICU93wwO3LbACbfkliogPjX4fNtCqUHBfNbJiUWjAk3N82itBunbZh6V0kEdCvLMjL6psnU/9MUw==","signatures":[{"sig":"MEQCIBChNduVF429ATwIxU4eaQzwBdMpZqEs7ZR55Qe66Y/OAiBH2kPWATtG/3mcDWBuSrrg6KtwlPHHAnqqCHN6b8cHKg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107678},"main":"./dist/index.js","type":"module","_from":"file:droplinked_inc-editor-core-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint src","test":"jest","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json","test:coverage":"jest --coverage"},"_npmUser":{"name":"droplinked_inc","email":"ali@droplinked.com"},"_resolved":"/tmp/3ebf8e2ec049320e7eba6dcc1829fe89/droplinked_inc-editor-core-0.2.0.tgz","_integrity":"sha512-Ycf3NfQrogICU93wwO3LbACbfkliogPjX4fNtCqUHBfNbJiUWjAk3N82itBunbZh6V0kEdCvLMjL6psnU/9MUw==","repository":{"url":"git+https://github.com/droplinked/droplink-packages.git","type":"git","directory":"packages/editor-core"},"_npmVersion":"10.9.7","description":"Hardened core primitives (types + validators + tree helpers) for the Droplinked page editor. Successor to droplinked-editor-core, types-and-runtime split; UI components deferred to @droplinked_inc/editor-ui.","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.23.8"},"publishConfig":{"access":"public","provenance":false},"_hasShrinkwrap":false,"devDependencies":{"fast-check":"^3.23.1"},"_npmOperationalInternal":{"tmp":"tmp/editor-core_0.2.0_1779168342952_0.6188668870097358","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@droplinked_inc/editor-core","version":"0.2.2","license":"MIT","_id":"@droplinked_inc/editor-core@0.2.2","maintainers":[{"name":"droplinked_inc","email":"ali@droplinked.com"}],"homepage":"https://github.com/droplinked/droplink-packages#readme","bugs":{"url":"https://github.com/droplinked/droplink-packages/issues"},"dist":{"shasum":"e5e140426a2dcf9784267e8e6cf1d76fcc31fa45","tarball":"https://registry.npmjs.org/@droplinked_inc/editor-core/-/editor-core-0.2.2.tgz","fileCount":83,"integrity":"sha512-WA2wgE+bxWesybTigLJ4/kWFZxila53Na5DcU4m88IHvwSqkWDHf7Fuz3pz39tvD4OTi4zkAJkGKdzcZ5eLuIA==","signatures":[{"sig":"MEUCIFy7FrZw5fXTogH6I5zl+jfH7J4YE+dKooZknk471rTWAiEAqjVJ+E+6ta1gWa7TEKaPX04skwASe4XjFA/sjZgdfYA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":154830},"main":"./dist/cjs/index.js","type":"module","_from":"file:droplinked_inc-editor-core-0.2.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/cjs/index.js"}},"scripts":{"lint":"eslint src","test":"jest","build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}))\"","typecheck":"tsc --noEmit -p tsconfig.json","test:coverage":"jest --coverage"},"_npmUser":{"name":"droplinked_inc","email":"ali@droplinked.com"},"_resolved":"/tmp/adb7713fc7f4c993590632669aba9221/droplinked_inc-editor-core-0.2.2.tgz","_integrity":"sha512-WA2wgE+bxWesybTigLJ4/kWFZxila53Na5DcU4m88IHvwSqkWDHf7Fuz3pz39tvD4OTi4zkAJkGKdzcZ5eLuIA==","repository":{"url":"git+https://github.com/droplinked/droplink-packages.git","type":"git","directory":"packages/editor-core"},"_npmVersion":"10.9.7","description":"Hardened core primitives (types + validators + tree helpers) for the Droplinked page editor. Successor to droplinked-editor-core, types-and-runtime split; UI components deferred to @droplinked_inc/editor-ui.","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.23.8"},"publishConfig":{"access":"public","provenance":false},"_hasShrinkwrap":false,"devDependencies":{"fast-check":"^3.23.1"},"_npmOperationalInternal":{"tmp":"tmp/editor-core_0.2.2_1779173508673_0.11622580690033368","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@droplinked_inc/editor-core","version":"0.2.3","description":"Hardened core primitives (types + validators + tree helpers) for the Droplinked page editor. Successor to droplinked-editor-core, types-and-runtime split; UI components deferred to @droplinked_inc/editor-ui.","license":"MIT","type":"module","main":"./dist/cjs/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/cjs/index.js","default":"./dist/index.js"}},"publishConfig":{"provenance":false,"access":"public"},"repository":{"type":"git","url":"git+https://github.com/droplinked/droplink-packages.git","directory":"packages/editor-core"},"engines":{"node":">=22.0.0"},"dependencies":{"zod":"^3.23.8"},"devDependencies":{"fast-check":"^3.23.1"},"scripts":{"build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}))\"","test":"jest","test:coverage":"jest --coverage","lint":"eslint src","typecheck":"tsc --noEmit -p tsconfig.json"},"_id":"@droplinked_inc/editor-core@0.2.3","bugs":{"url":"https://github.com/droplinked/droplink-packages/issues"},"homepage":"https://github.com/droplinked/droplink-packages#readme","_integrity":"sha512-Bmp1nf7xzr1dKEIcKIIsCx3oGzPw59eXRSr+QCAkEkcFbgI5Fzu7f+d1LQ/vMBovyjKK6KkWb56HtV0gUZOZgw==","_resolved":"/tmp/f90a6c99189edec71964151790b68fd3/droplinked_inc-editor-core-0.2.3.tgz","_from":"file:droplinked_inc-editor-core-0.2.3.tgz","_nodeVersion":"22.23.1","_npmVersion":"11.19.0","dist":{"integrity":"sha512-Bmp1nf7xzr1dKEIcKIIsCx3oGzPw59eXRSr+QCAkEkcFbgI5Fzu7f+d1LQ/vMBovyjKK6KkWb56HtV0gUZOZgw==","shasum":"8b37da7e3f1e8b9958ac96d4976fc529cdbac2bf","tarball":"https://registry.npmjs.org/@droplinked_inc/editor-core/-/editor-core-0.2.3.tgz","fileCount":83,"unpackedSize":154931,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDDR8ITl/89T4ZwVohOdbKSJSB310lR/it3HDLugDFdkwIhALBqP4bmQpukpZac3PJGD1o4ocFoXPuqCSAzFRC4dyHl"}]},"_npmUser":{"name":"droplinked_inc","email":"ali@droplinked.com"},"directories":{},"maintainers":[{"name":"droplinked_inc","email":"ali@droplinked.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/editor-core_0.2.3_1786016230070_0.46238365684639415"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-19T05:25:42.839Z","modified":"2026-08-06T11:37:10.360Z","0.2.0":"2026-05-19T05:25:43.105Z","0.2.2":"2026-05-19T06:51:48.835Z","0.2.3":"2026-08-06T11:37:10.211Z"},"bugs":{"url":"https://github.com/droplinked/droplink-packages/issues"},"license":"MIT","homepage":"https://github.com/droplinked/droplink-packages#readme","repository":{"type":"git","url":"git+https://github.com/droplinked/droplink-packages.git","directory":"packages/editor-core"},"description":"Hardened core primitives (types + validators + tree helpers) for the Droplinked page editor. Successor to droplinked-editor-core, types-and-runtime split; UI components deferred to @droplinked_inc/editor-ui.","maintainers":[{"name":"droplinked_inc","email":"ali@droplinked.com"}],"readme":"# @droplinked_inc/editor-core\n\n> Replaces `droplinked-editor-core`. See [MIGRATION.md](../../docs/MIGRATION.md) for the swap path.\n\nHardened **type-and-runtime core primitives** for the Droplinked page editor.\nSuccessor to the legacy `droplinked-editor-core@1.1.15`. Built from the\noriginal `.d.ts` API surface with the runtime re-implemented from a\nbehavioural oracle of the published `dist/`.\n\n## Scope\n\nThis package now ships only the parts that can be reasoned about and\ntested without React rendering:\n\n- Public TypeScript types (`Config`, `Data`, `ComponentData`, `Field`, …)\n- zod schemas + `parseEditorData` / `parseEditorConfig` validators\n- Pure-data helpers: `defaultData`, `walkTree`, `transformProps`, `migrate`\n- DoS-safe utilities: `safeDeepMerge`, `safeDeepClone`, `isPlainObject`\n- Centralised structural limits (`LIMITS`) and forbidden keys (`FORBIDDEN_KEYS`)\n\nThe original substrate also shipped a Puck-fork editor UI (`<Puck>`,\n`<Render>`, `<AutoField>`, `<DropZone>`, etc.). Those are **deferred to a\nsibling `@droplinked_inc/editor-ui` package** so this core stays\ntestable in a Node-only jest environment and so the dependency footprint\n(no Chakra, no DnD-Kit, no Framer Motion, no zustand) stays minimal.\n`icons` is similarly deferred.\n\n## Install\n\n```bash\npnpm add @droplinked_inc/editor-core\n```\n\n## Quick start\n\n```ts\nimport { parseEditorData, walkTree, migrate, transformProps } from '@droplinked_inc/editor-core';\n\n// 1. Validate untrusted input at the trust boundary\nconst parsed = parseEditorData(rawJsonFromDB);\nif (!parsed.ok) {\n  throw new Error(`Editor data invalid: ${parsed.issues.join('; ')}`);\n}\n\n// 2. Migrate forward through known schema revisions\nconst { data, report } = migrate(parsed.value);\n\n// 3. Walk every content array (zones + root) and transform\nconst walked = walkTree(data, (content, { parentId, propName }) => {\n  return content.filter((c) => c.type !== 'Deprecated');\n});\n\n// 4. Apply per-type prop transforms (e.g. URL rewriting)\nconst finalData = transformProps(walked, {\n  Image: (props) => ({ ...props, src: rewriteToCdn(props.src as string) }),\n  root:  (props) => ({ ...props, title: (props.title as string).trim() }),\n});\n```\n\n## Security\n\nThis package replaces a previously hostile-published predecessor.\nEvery external boundary funnels through a zod schema; every recursive\nhelper is depth-and-breadth-capped (see `LIMITS`). See\n[`THREAT_MODEL.md`](./THREAT_MODEL.md) for the full attacker model and\nthe mitigations.\n\nHighlights:\n\n- **No `eval`, no `Function()`, no dynamic `require`** anywhere in the\n  package.\n- **Prototype-pollution-safe deep merge.** `__proto__`, `constructor`,\n  `prototype` keys are silently dropped from both base and patch, and\n  intermediate scratch objects use `Object.create(null)` so a malicious\n  `toString` etc. cannot shadow `Object.prototype`.\n- **DoS caps** on object depth, key count, array length, total node\n  count, registered components, categories, and zones (`LIMITS`).\n- **URL allow-list** on shop-default favicon: `http:`/`https:`/`mailto:`\n  only — `javascript:` / `data:` URLs are rejected by the schema.\n- **No React/UI surface** in this package — that runtime lives in\n  `@droplinked_inc/editor-ui` (deferred) and can be reviewed independently.\n\n## Compatibility note for `@droplinked_inc/editor-configs`\n\nThe current `editor-configs` (PR #1) package uses a local\n`EditorConfigShape` placeholder. This package exports\n`EditorConfigShape` as an alias for `Config`, so the follow-up swap is a\none-line import change in `editor-configs`.\n\n## License\n\nMIT.\n","readmeFilename":"README.md"}