{"_id":"@codemind.ec/medusa-plugin-additional-info","_rev":"3-673962a35e7bb080057282f301a6f720","name":"@codemind.ec/medusa-plugin-additional-info","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@codemind.ec/medusa-plugin-additional-info","version":"1.0.0","keywords":["medusa","medusa-plugin","medusa-v2","plugin","additional-info","product-metadata","codemind","kollor"],"author":{"url":"https://codemind.ec","name":"Kollor","email":"dev@codemind.ec"},"license":"MIT","_id":"@codemind.ec/medusa-plugin-additional-info@1.0.0","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"dist":{"shasum":"b1a8803e3a44fdb2f84a34b233b563803a3d4f80","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-additional-info/-/medusa-plugin-additional-info-1.0.0.tgz","fileCount":33,"integrity":"sha512-JiUsZRA4P+KKiGGJGA12TwWldiUjD6U1Q3eHZXsawZx3QlerHV+8z705iuQX1k4QFMUdwGykKNcDuXh3ny1lPQ==","signatures":[{"sig":"MEUCIFmYbml5D57YVg73IU0YFHfPgmJYOHD/eXZawvCeuuPCAiEAsJvzGa6oReiDMOJilRq6o5Q8nXYSJ68JhkdtHkAkias=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":280890},"engines":{"node":">=20"},"exports":{".":{"types":"./src/index.ts","default":"./.medusa/server/src/index.js"},"./*":"./.medusa/server/src/*.js","./admin":{"import":"./.medusa/server/src/admin/index.mjs","default":"./.medusa/server/src/admin/index.js","require":"./.medusa/server/src/admin/index.js"},"./types":"./.medusa/server/src/types.js","./modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./providers/*":"./.medusa/server/src/providers/*/index.js","./package.json":"./package.json","./modules/additional-info":"./.medusa/server/src/modules/additional-info/index.js","./.medusa/server/src/modules/*":"./.medusa/server/src/modules/*/index.js"},"gitHead":"e8f515a4d4fbf47a3ebf48140c0ef2f5ea88c670","scripts":{"dev":"medusa plugin:develop","test":"vitest run","build":"medusa plugin:build","prepublishOnly":"medusa plugin:build"},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"_npmVersion":"10.9.2","description":"Medusa v2 plugin for hierarchical product metadata — tree-based templates, drag-and-drop ordering, and per-variant overrides.","directories":{},"_nodeVersion":"22.15.1","dependencies":{"@dnd-kit/core":"^6.1.0","@dnd-kit/sortable":"^8.0.0","@dnd-kit/utilities":"^3.2.2"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.9","devDependencies":{"vite":"^5.4.14","yalc":"^1.0.0-pre.53","react":"^18.3.1","vitest":"^1.4.0","ts-node":"^10.9.2","@swc/core":"^1.7.28","react-dom":"^18.3.1","prop-types":"^15.8.1","typescript":"^5","@types/node":"^20","@medusajs/ui":"^4.1.3","@types/react":"^18.3.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","react-hook-form":"7.49.1","@medusajs/medusa":"2.13.3","@types/react-dom":"^18.3.0","@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"peerDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","@medusajs/ui":"^4.1.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","react-hook-form":"7.49.1","@medusajs/medusa":"2.13.3","@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/medusa-plugin-additional-info_1.0.0_1774052835111_0.18298026051451344","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@codemind.ec/medusa-plugin-additional-info","version":"1.0.1","keywords":["medusa","medusa-plugin","medusa-v2","plugin","additional-info","product-metadata","codemind","kollor"],"author":{"url":"https://codemind.ec","name":"Kollor","email":"dev@codemind.ec"},"license":"MIT","_id":"@codemind.ec/medusa-plugin-additional-info@1.0.1","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"dist":{"shasum":"ef97a77907d4e3be1e62a1aea06e841f87738073","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-additional-info/-/medusa-plugin-additional-info-1.0.1.tgz","fileCount":34,"integrity":"sha512-W5SuQycTlxcmomKNlBCYMuo7+Y2k//KEijC/Ep4/T4aR+2TajbQzua2/vkI1E4/4+abNzvVkrv53Qaq4EBQf1Q==","signatures":[{"sig":"MEUCIAehmAxg9PZrKLKuTX6kl4akcW82PJEnkFG7mTi+sazEAiEA/ihBM7LqWLj/AkbLywCyYVc2zDJdH3H+GfDVD0YblLI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":285353},"_from":"file:codemind.ec-medusa-plugin-additional-info-1.0.1.tgz","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.ts","default":"./.medusa/server/src/index.js"},"./admin":{"import":"./.medusa/server/src/admin/index.mjs","default":"./.medusa/server/src/admin/index.js","require":"./.medusa/server/src/admin/index.js"},"./types":"./.medusa/server/src/types.js","./modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./package.json":"./package.json","./additional-info":"./.medusa/server/src/modules/additional-info/index.js","./modules/additional-info":"./.medusa/server/src/modules/additional-info/index.js"},"scripts":{"dev":"medusa plugin:develop","test":"vitest run","build":"medusa plugin:build"},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"_resolved":"C:\\Users\\isai_\\AppData\\Local\\Temp\\1bc3ac51a7a7b4f1147da45d9b0ae7a3\\codemind.ec-medusa-plugin-additional-info-1.0.1.tgz","_integrity":"sha512-W5SuQycTlxcmomKNlBCYMuo7+Y2k//KEijC/Ep4/T4aR+2TajbQzua2/vkI1E4/4+abNzvVkrv53Qaq4EBQf1Q==","_npmVersion":"10.9.2","description":"Medusa v2 plugin for hierarchical product metadata — tree-based templates, drag-and-drop ordering, and per-variant overrides.","directories":{},"_nodeVersion":"22.15.1","dependencies":{"@dnd-kit/core":"^6.1.0","@dnd-kit/sortable":"^8.0.0","@dnd-kit/utilities":"^3.2.2"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.14","yalc":"^1.0.0-pre.53","react":"^18.3.1","vitest":"^1.4.0","ts-node":"^10.9.2","@swc/core":"^1.7.28","react-dom":"^18.3.1","prop-types":"^15.8.1","typescript":"^5","@types/node":"^20","@medusajs/ui":"^4.1.3","@types/react":"^18.3.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","react-hook-form":"7.49.1","@medusajs/medusa":"2.13.3","@types/react-dom":"^18.3.0","@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"peerDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","@medusajs/ui":"^4.1.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","react-hook-form":"7.49.1","@medusajs/medusa":"2.13.3","@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/medusa-plugin-additional-info_1.0.1_1774066398723_0.7857862832336984","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@codemind.ec/medusa-plugin-additional-info","description":"Medusa v2 plugin for hierarchical product metadata — tree-based templates, drag-and-drop ordering, and per-variant overrides.","version":"1.0.2","author":{"name":"Kollor","email":"dev@codemind.ec","url":"https://codemind.ec"},"license":"MIT","exports":{".":{"types":"./src/index.ts","default":"./.medusa/server/src/index.js"},"./package.json":"./package.json","./additional-info":"./.medusa/server/src/modules/additional-info/index.js","./modules/additional-info":"./.medusa/server/src/modules/additional-info/index.js","./modules/*":"./.medusa/server/src/modules/*/index.js","./.medusa/server/src/modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./types":"./.medusa/server/src/types.js","./admin":{"import":"./.medusa/server/src/admin/index.mjs","require":"./.medusa/server/src/admin/index.js","default":"./.medusa/server/src/admin/index.js"}},"scripts":{"build":"medusa plugin:build","dev":"medusa plugin:develop","prepublishOnly":"medusa plugin:build","test":"vitest run"},"dependencies":{"@dnd-kit/core":"^6.1.0","@dnd-kit/sortable":"^8.0.0","@dnd-kit/utilities":"^3.2.2"},"devDependencies":{"@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/admin-shared":"2.13.3","@medusajs/cli":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/ui":"^4.1.3","@swc/core":"^1.7.28","@types/node":"^20","@types/react":"^18.3.3","@types/react-dom":"^18.3.0","prop-types":"^15.8.1","react":"^18.3.1","react-dom":"^18.3.1","react-hook-form":"7.49.1","ts-node":"^10.9.2","typescript":"^5","vite":"^5.4.14","vitest":"^1.4.0","yalc":"^1.0.0-pre.53"},"engines":{"node":">=20"},"keywords":["medusa","medusa-plugin","medusa-v2","plugin","additional-info","product-metadata","codemind","kollor"],"packageManager":"pnpm@9.15.9","peerDependencies":{"@hookform/resolvers":"^3.9.0","@medusajs/admin-sdk":"2.13.3","@medusajs/cli":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/ui":"^4.1.3","@tanstack/react-query":"^5.0.0","react":"^18.3.1","react-dom":"^18.3.1","react-hook-form":"7.49.1"},"_id":"@codemind.ec/medusa-plugin-additional-info@1.0.2","gitHead":"4f7974c7a642ed7ecc3c4ff9105b6366ea70b238","_nodeVersion":"22.15.1","_npmVersion":"10.9.2","dist":{"integrity":"sha512-wNuk8xXP/0CLElNCyKq9rq4LtO0ovdmf2FBP9l7KzbgTJO70NeGF4ecjRfJssSvfrx+5JR8FZRhUauQzKAvJSg==","shasum":"a7870c8d83c0c808baf0d7c44b0a78e8976c94c7","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-additional-info/-/medusa-plugin-additional-info-1.0.2.tgz","fileCount":34,"unpackedSize":286274,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHHQplkTVKLAUJkC+f90MRy513bENOUTHY7baVKj0JjcAiEAvWavQ3I3Kt6skz+bVBTUD5XVKvIzAQ0etz3+JspxgCs="}]},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"directories":{},"maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/medusa-plugin-additional-info_1.0.2_1774073437211_0.6873631808887002"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T00:27:14.993Z","modified":"2026-03-21T06:10:37.497Z","1.0.0":"2026-03-21T00:27:15.316Z","1.0.1":"2026-03-21T04:13:18.904Z","1.0.2":"2026-03-21T06:10:37.364Z"},"author":{"name":"Kollor","email":"dev@codemind.ec","url":"https://codemind.ec"},"license":"MIT","keywords":["medusa","medusa-plugin","medusa-v2","plugin","additional-info","product-metadata","codemind","kollor"],"description":"Medusa v2 plugin for hierarchical product metadata — tree-based templates, drag-and-drop ordering, and per-variant overrides.","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"readme":"# @codemind.ec/medusa-plugin-additional-info\r\n\r\nMedusa v2 plugin for **hierarchical product metadata** — tree-based templates, diff-based updates, drag-and-drop ordering, and per-product overrides.\r\n\r\n[![npm version](https://img.shields.io/npm/v/@codemind.ec/medusa-plugin-additional-info.svg)](https://www.npmjs.com/package/@codemind.ec/medusa-plugin-additional-info)\r\n[![Medusa v2](https://img.shields.io/badge/medusa-v2-blueviolet)](https://docs.medusajs.com)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n---\r\n\r\n## Features\r\n\r\n- **Tree-based templates** — define hierarchical structures of sections, items, and content blocks.\r\n- **Versioned schemas** — `tree@1` and `diff@1` schemas with Zod validation.\r\n- **Diff-based overrides** — apply per-product patches, additions, reordering, and hiding without duplicating templates.\r\n- **Content blocks** — markdown (`md`) and list (`bullet`/`number`) blocks per node.\r\n- **Admin UI** — full CRUD interface with drag-and-drop tree editing for templates and product values.\r\n- **Store API** — public endpoint to fetch resolved additional info for any product.\r\n- **Product linking** — automatic Medusa link between additional info values and products.\r\n\r\n---\r\n\r\n## Prerequisites\r\n\r\n| Requirement | Version |\r\n|-------------|---------|\r\n| Node.js     | >= 20   |\r\n| Medusa      | >= 2.4.0 |\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @codemind.ec/medusa-plugin-additional-info\r\n# or\r\npnpm add @codemind.ec/medusa-plugin-additional-info\r\n```\r\n\r\n---\r\n\r\n## Configuration\r\n\r\nAdd the plugin and its module to your `medusa-config.ts`:\r\n\r\n```typescript\r\nimport { defineConfig } from \"@medusajs/framework/utils\"\r\n\r\nexport default defineConfig({\r\n  // ...\r\n  modules: [\r\n    {\r\n      resolve: \"@codemind.ec/medusa-plugin-additional-info/additional-info\",\r\n      definition: { isQueryable: true },\r\n    },\r\n  ],\r\n  plugins: [\r\n    {\r\n      resolve: \"@codemind.ec/medusa-plugin-additional-info\",\r\n      options: {},\r\n    },\r\n  ],\r\n})\r\n```\r\n\r\n> **Nota:** El módulo se registra por separado en `modules[]` con `isQueryable: true` para que sea accesible desde el query graph de Medusa. La entrada en `plugins[]` carga admin UI, API routes, links y workflows.\r\n\r\n---\r\n\r\n## Architecture\r\n\r\n### Module: `additional-info`\r\n\r\n#### `additional_info_template`\r\n\r\nReusable tree structures that define the shape of additional info.\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `id` | string | Primary key |\r\n| `name` | string | Template name |\r\n| `description` | string? | Optional description |\r\n| `attributes` | JSON | Tree document (`tree@1` schema) |\r\n\r\n#### `additional_info_value`\r\n\r\nPer-product values, optionally referencing a template.\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `id` | string | Primary key |\r\n| `product_id` | string | Associated product ID |\r\n| `template` | relation | Parent template (optional) |\r\n| `values` | JSON | Diff document or standalone tree |\r\n\r\n---\r\n\r\n### Schema: Tree v1\r\n\r\nSchema identifier: `com.mariquita.additional-info/tree@1`\r\n\r\n```typescript\r\ntype AITreeDocV1 = {\r\n  schema: \"com.mariquita.additional-info/tree@1\"\r\n  rev: number\r\n  root: \"root\"\r\n  nodes: Record<string, AINodeV1>   // id → node\r\n  children: Record<string, string[]> // parentId → [childIds]\r\n  meta?: { createdAt?: string; updatedAt?: string }\r\n}\r\n\r\ntype AINodeV1 = {\r\n  id: string\r\n  type: \"root\" | \"section\" | \"item\"\r\n  title: string\r\n  blocks?: AIBlockV1[]\r\n  tags?: string[]\r\n  ui?: { icon?: string; collapsed?: boolean }\r\n}\r\n\r\ntype AIBlockV1 =\r\n  | { kind: \"md\"; value: string }\r\n  | { kind: \"list\"; style: \"bullet\" | \"number\"; items: string[] }\r\n```\r\n\r\n### Schema: Diff v1\r\n\r\nSchema identifier: `com.mariquita.additional-info/diff@1`\r\n\r\n```typescript\r\ntype AIDiffDocV1 = {\r\n  schema: \"com.mariquita.additional-info/diff@1\"\r\n  baseRev: number\r\n  overrides?: Record<string, AINodePatchV1>   // per-node patches\r\n  additions?: AIAdditionsV1                    // new subtrees\r\n  childrenOrder?: Record<string, string[]>     // reorder children\r\n}\r\n\r\ntype AIAdditionsV1 = {\r\n  mount: {\r\n    parentId: string\r\n    position?: \"start\" | \"end\"\r\n    index?: number\r\n  }\r\n  nodes: Record<string, AINodeV1>\r\n  children: Record<string, string[]>\r\n  rootIds: string[]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Operations\r\n\r\n| Function | Description |\r\n|----------|-------------|\r\n| `createEmptyTree()` | Creates a canonical empty tree with a root node |\r\n| `validateTreeDocV1(input)` | Validates schema, root existence, cycle detection (DFS), and child references |\r\n| `resolveTree(base, diff?)` | Merges a base tree with a diff: applies overrides, prunes hidden subtrees, mounts additions, and reorders children |\r\n| `pruneHidden(tree, hiddenIds)` | Removes subtrees by ID |\r\n\r\n---\r\n\r\n## API Reference\r\n\r\n### Admin Routes\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/additional-info/templates` | List templates (paginated: `limit`, `offset`) |\r\n| `POST` | `/admin/additional-info/templates` | Create a template |\r\n| `GET` | `/admin/additional-info/templates/:id` | Get a template |\r\n| `PUT` | `/admin/additional-info/templates/:id` | Update a template |\r\n| `DELETE` | `/admin/additional-info/templates/:id` | Delete a template |\r\n| `GET` | `/admin/additional-info/values` | List values (filter: `product_id`, expand: `template`) |\r\n| `POST` | `/admin/additional-info/values` | Create value(s) — single or array |\r\n| `PUT` | `/admin/additional-info/values/:id` | Update a value |\r\n| `DELETE` | `/admin/additional-info/values/:id` | Delete a value |\r\n\r\n### Store Routes\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/store/products/:id/additional-info` | Get resolved additional info for a product |\r\n\r\n### Create a Template\r\n\r\n```bash\r\ncurl -X POST /admin/additional-info/templates \\\r\n  -H \"Content-Type: application/json\" \\\r\n  -d '{\r\n    \"name\": \"Product Specs\",\r\n    \"attributes\": {\r\n      \"schema\": \"com.mariquita.additional-info/tree@1\",\r\n      \"rev\": 1,\r\n      \"root\": \"root\",\r\n      \"nodes\": {\r\n        \"root\": { \"id\": \"root\", \"type\": \"root\", \"title\": \"Root\" },\r\n        \"specs\": { \"id\": \"specs\", \"type\": \"section\", \"title\": \"Specifications\", \"blocks\": [\r\n          { \"kind\": \"md\", \"value\": \"Technical details for this product.\" }\r\n        ]}\r\n      },\r\n      \"children\": { \"root\": [\"specs\"] }\r\n    }\r\n  }'\r\n```\r\n\r\n---\r\n\r\n## Workflows\r\n\r\n### `createAdditionalInfoValuesWorkflow`\r\n\r\n1. **Step 1:** `createAdditionalInfoValuesStep` — creates value records (rollback: soft-delete).\r\n2. **Step 2:** `linkAdditionalInfoProductStep` — establishes links to products (rollback: dismiss links).\r\n\r\n---\r\n\r\n## Product Linking\r\n\r\nThe plugin defines a Medusa link between `additional_info_value` and `Product` (using `Modules.PRODUCT`). This enables:\r\n\r\n- Querying values through product relations\r\n- Automatic cleanup on product deletion\r\n- Multiple values per product (`isList: true`)\r\n\r\n---\r\n\r\n## TypeScript Exports\r\n\r\n```typescript\r\n// Types\r\nimport type { AITreeDocV1, AIDiffDocV1, AINodeV1, AIBlockV1 } from \"@codemind.ec/medusa-plugin-additional-info/types\"\r\n\r\n// Module\r\nimport AdditionalInfoModule from \"@codemind.ec/medusa-plugin-additional-info/modules/additional-info\"\r\n\r\n// Workflows\r\nimport { createAdditionalInfoValuesWorkflow } from \"@codemind.ec/medusa-plugin-additional-info/workflows\"\r\n```\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT — [CodeMind](https://codemind.ec)\r\n","readmeFilename":"README.md"}