{"_id":"@bambiste/medusa-barcode","name":"@bambiste/medusa-barcode","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.2":{"name":"@bambiste/medusa-barcode","version":"0.0.2","description":"Production-ready barcode scanning, multi-provider lookup and automatic product creation plugin for MedusaJS v2","author":{"name":"Ibrahima Touré"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bambiste/medusa-plugins.git","directory":"packages/medusa-barcode"},"publishConfig":{"registry":"https://registry.npmjs.org/","access":"public"},"exports":{"./package.json":"./package.json","./workflows":"./.medusa/server/src/workflows/index.js","./.medusa/server/src/modules/barcode":"./.medusa/server/src/modules/barcode/index.js","./.medusa/server/src/modules/barcode/*":"./.medusa/server/src/modules/barcode/*.js","./*":"./.medusa/server/src/*.js",".":"./.medusa/server/src/index.js","./admin":{"import":"./.medusa/server/src/admin/index.mjs","require":"./.medusa/server/src/admin/index.js","default":"./.medusa/server/src/admin/index.js"}},"keywords":["medusa","plugin","barcode","ean13","upc","product-creation","medusa-plugin","medusa-v2"],"devDependencies":{"@medusajs/admin-sdk":"2.14.2","@medusajs/cli":"2.14.2","@medusajs/framework":"2.14.2","@medusajs/medusa":"2.14.2","@medusajs/test-utils":"2.14.2","@swc/core":"^1.7.28","@types/node":"^20.0.0","ts-node":"^10.9.2","typescript":"^5.6.2","vite":"^5.2.11","zod":"^3.22.4","yalc":"1.0.0-pre.53"},"peerDependencies":{"@medusajs/admin-sdk":"2.14.2","@medusajs/cli":"2.14.2","@medusajs/framework":"2.14.2","@medusajs/medusa":"2.14.2","@medusajs/test-utils":"2.14.2"},"engines":{"node":">=20"},"scripts":{"build":"medusa plugin:build","dev":"medusa plugin:develop"},"_id":"@bambiste/medusa-barcode@0.0.2","bugs":{"url":"https://github.com/bambiste/medusa-plugins/issues"},"homepage":"https://github.com/bambiste/medusa-plugins#readme","_integrity":"sha512-pEXDQc2UvR34AraGjtj0qyzDjHhEkf7TrxdZsd9l6fgh9xLAa4mCFtpHEU38w9+af7EEbAuI46Kcu61jVQvT2A==","_resolved":"/tmp/dfa9516a492a849a140c126237277e15/bambiste-medusa-barcode-0.0.2.tgz","_from":"file:bambiste-medusa-barcode-0.0.2.tgz","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-pEXDQc2UvR34AraGjtj0qyzDjHhEkf7TrxdZsd9l6fgh9xLAa4mCFtpHEU38w9+af7EEbAuI46Kcu61jVQvT2A==","shasum":"8e41a15bff205b27b3f0ef7dcc1d6b334b1122c9","tarball":"https://registry.npmjs.org/@bambiste/medusa-barcode/-/medusa-barcode-0.0.2.tgz","fileCount":36,"unpackedSize":196333,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC1Bjt7Dox+CO3pXXusf/WrcH/FP5cJtPXDBRX+pMis/gIgY5DQV27b38bRo0az1vqzJ6YsESLkybDLLFzZEP0H1Eo="}]},"_npmUser":{"name":"bambiste","email":"ibrahima.toure.dev@gmail.com"},"directories":{},"maintainers":[{"name":"bambiste","email":"ibrahima.toure.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/medusa-barcode_0.0.2_1785291086811_0.09350149333677638"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-29T02:11:26.527Z","0.0.2":"2026-07-29T02:11:26.963Z","modified":"2026-07-29T02:11:27.219Z"},"maintainers":[{"name":"bambiste","email":"ibrahima.toure.dev@gmail.com"}],"description":"Production-ready barcode scanning, multi-provider lookup and automatic product creation plugin for MedusaJS v2","homepage":"https://github.com/bambiste/medusa-plugins#readme","keywords":["medusa","plugin","barcode","ean13","upc","product-creation","medusa-plugin","medusa-v2"],"repository":{"type":"git","url":"git+https://github.com/bambiste/medusa-plugins.git","directory":"packages/medusa-barcode"},"author":{"name":"Ibrahima Touré"},"bugs":{"url":"https://github.com/bambiste/medusa-plugins/issues"},"license":"MIT","readme":"<p align=\"center\">\n  <a href=\"https://www.medusajs.com\">\n    <img alt=\"Medusa\" src=\"https://user-images.githubusercontent.com/59018053/229103726-e5b529a3-9b3f-4970-8a1f-c6af37f087bf.svg\" width=\"180\" />\n  </a>\n</p>\n\n# @bambiste/medusa-barcode\n\n**Production-ready barcode scanning, multi-provider lookup and automatic product creation for MedusaJS v2.**\n\n![License: MIT](https://img.shields.io/badge/License-MIT-22c55e.svg)\n![Medusa](https://img.shields.io/badge/Medusa-v2-7c3aed)\n![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white)\n![Registry](https://img.shields.io/badge/registry-GitHub%20Packages-181717?logo=github)\n\n---\n\n## Features\n\n| Feature | Status |\n|---|---|\n| EAN-13 / UPC-A / UPC-E / Code128 / QR support | ✅ |\n| GS1 checksum validation | ✅ |\n| PostgreSQL cache (configurable TTL) | ✅ |\n| Multi-provider fallback chain | ✅ |\n| OpenFoodFacts provider | ✅ |\n| UpcItemDb provider (trial + paid) | ✅ |\n| Extensible provider registry | ✅ |\n| Automatic Medusa product creation | ✅ |\n| Default variant with EAN / UPC / barcode fields | ✅ |\n| Workflow-based orchestration (transaction-safe) | ✅ |\n| Batch import (up to 200 barcodes) | ✅ |\n| Admin REST API | ✅ |\n| Zod request validation | ✅ |\n| Startup cache purge | ✅ |\n\n---\n\n## Installation\n\n```bash\n# From the leuzman-backend workspace\npnpm add medusa-barcode\n```\n\n---\n\n## medusa-config.ts\n\n```typescript\nimport { defineConfig } from \"@medusajs/framework/utils\"\n\nexport default defineConfig({\n  modules: [\n    {\n      resolve: \"./src/modules/barcode\",\n      options: {\n        // NOTE: \"providers\" is reserved by Medusa's module loader — use \"providerConfig\"\n        providerConfig: {\n          openFoodFacts: {\n            enabled: true,\n            country: \"world\",   // subdomain: world | fr | de | es …\n            timeout: 12000,\n            retries: 2,\n            priority: 10,       // lower = higher priority in fallback chain\n          },\n          upcItemDb: {\n            enabled: true,\n            apiKey:  process.env.UPCITEMDB_API_KEY,   // omit for trial tier\n            timeout: 10000,\n            retries: 2,\n            priority: 20,\n          },\n        },\n        cache: {\n          ttl: 86400,   // seconds — 24 h default\n        },\n      },\n    },\n  ],\n})\n```\n\n---\n\n## REST API\n\n### `POST /admin/barcodes/lookup`\n\nLookup a barcode via cache → providers.\n\n```json\n// Request\n{ \"barcode\": \"3017620422003\", \"skipCache\": false }\n\n// Response 200\n{\n  \"found\": true,\n  \"fromCache\": false,\n  \"provider\": \"open-food-facts\",\n  \"barcodeType\": \"ean13\",\n  \"normalized\": \"3017620422003\",\n  \"product\": {\n    \"title\": \"Nutella\",\n    \"brand\": \"Ferrero\",\n    \"category\": \"Spreads\",\n    \"image\": \"https://images.openfoodfacts.org/…/front.jpg\",\n    \"weight\": \"400g\",\n    \"barcode\": \"3017620422003\"\n  }\n}\n```\n\n---\n\n### `POST /admin/barcodes/create-from-barcode`\n\nLookup and create a draft Medusa product.\n\n```json\n// Request\n{\n  \"barcode\": \"3017620422003\",\n  \"salesChannelIds\": [\"sc_xxx\"],\n  \"categoryIds\": [\"pcat_xxx\"],\n  \"publishImmediately\": false\n}\n\n// Response 201\n{\n  \"created\": true,\n  \"product_id\": \"prod_01JXXXXXXX\",\n  \"variant_id\": \"variant_01JXXXXXXX\",\n  \"provider\": \"open-food-facts\",\n  \"title\": \"Nutella\"\n}\n\n// Response 200 (already exists)\n{\n  \"created\": false,\n  \"existing\": true,\n  \"product_id\": \"prod_01JXXXXXXX\",\n  \"variant_id\": \"variant_01JXXXXXXX\"\n}\n```\n\n---\n\n### `POST /admin/barcodes/batch`\n\nImport up to 200 barcodes in one request.\n\n```json\n// Request\n{\n  \"barcodes\": [\"3017620422003\", \"012000161155\", \"0075457179247\"],\n  \"salesChannelIds\": [\"sc_xxx\"],\n  \"skipExisting\": true\n}\n\n// Response 207\n{\n  \"total\": 3,\n  \"created\": 2,\n  \"skipped\": 1,\n  \"failed\": 0,\n  \"results\": [...]\n}\n```\n\n---\n\n### `GET /admin/barcodes`\n\nList all BarcodeProduct records.\n\nQuery params: `limit`, `offset`, `product_id`\n\n---\n\n### `GET /admin/barcodes/:barcode`\n\nGet BarcodeProduct + latest cache entry for a specific barcode.\n\n---\n\n### `DELETE /admin/barcodes/:barcode`\n\nRemove the BarcodeProduct mapping and invalidate cache. Does **not** delete the\nMedusa product.\n\n---\n\n### `GET /admin/barcodes/cache`\n\nReturn cache statistics: `{ \"total\": N, \"expired\": M }`.\n\n### `DELETE /admin/barcodes/cache`\n\nPurge all expired cache entries: `{ \"purged\": N }`.\n\n---\n\n## Custom Provider\n\nExtend `BaseBarcodeProvider` and register it at startup:\n\n```typescript\nimport { BaseBarcodeProvider } from \"medusa-barcode\"\nimport type { NormalizedProduct } from \"medusa-barcode\"\n\nclass MyCustomProvider extends BaseBarcodeProvider {\n  constructor() {\n    super(\"my-provider\", { priority: 5 })\n  }\n\n  supports(barcodeType: string): boolean {\n    return barcodeType === \"ean13\"\n  }\n\n  async lookup(barcode: string): Promise<NormalizedProduct | null> {\n    const data = await this.withRetry(() =>\n      this.fetchWithTimeout(`https://myapi.example/products/${barcode}`)\n        .then(r => r.json())\n    )\n    if (!data?.found) return null\n    return {\n      title:   data.name,\n      barcode,\n      brand:   data.brand,\n    }\n  }\n}\n```\n\nThen in a loader:\n\n```typescript\n// src/loaders/register-providers.ts\nimport { BARCODE_MODULE }   from \"medusa-barcode\"\nimport { MyCustomProvider } from \"./my-custom-provider\"\n\nexport default async function({ container }) {\n  const svc = container.resolve(BARCODE_MODULE)\n  svc.registerProvider(new MyCustomProvider())\n}\n```\n\n---\n\n## Barcode Types Supported\n\n| Type | Example | Validation |\n|---|---|---|\n| EAN-13 | `3017620422003` | GS1 checksum |\n| UPC-A | `012000161155` | GS1 checksum |\n| UPC-E | `01210501` | Expands + validates |\n| Code128 | `LOT-2024-ABC` | Length ≥ 1 |\n| QR | `https://…` | Any URL |\n| DataMatrix | `A3F9BC00…` | Hex pattern |\n\n---\n\n## Workflow\n\nThe `lookupAndCreateProductWorkflow` is transaction-safe:\n\n```\nvalidateBarcodeStep\n  → checkExistingBarcodeProductStep\n  → lookupBarcodeStep             ← cache + provider fallback\n  → downloadThumbnailStep         ← best-effort, never fails\n  → createMedusaProductStep       ← compensation: deleteProducts\n  → saveBarcodeRelationStep       ← compensation: removeBarcodeProduct\n```\n\nIf any step after product creation fails, the compensation chain rolls back the\nproduct and the BarcodeProduct row automatically.\n","readmeFilename":"README.md","_rev":"1-55549fbf2e7e2269b112aa06c023680b"}