{"owner":"medusajs","repo":"medusa","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"files":{"CLAUDE.md":"# Medusa Core\n\nOpen-source commerce platform. TypeScript monorepo with 30+ modular commerce packages.\n\n> When working on the API reference documentation (`www/apps/api-reference`), read [`www/apps/api-reference/CLAUDE.md`](www/apps/api-reference/CLAUDE.md) for its path structure and the OAS → public docs flow.\n\n> When working on the resources documentation (`www/apps/resources`), read [`www/apps/resources/CLAUDE.md`](www/apps/resources/CLAUDE.md) for details on references and how they're generated and built\n\n### 1. Codebase Structure\n\n**Monorepo Organization:**\n```\n/packages/\n├── medusa/              # Main Medusa package\n├── core/                # Core framework packages\n│   ├── framework/       # Core runtime\n│   ├── types/           # TypeScript definitions\n│   ├── utils/           # Utilities\n│   ├── workflows-sdk/   # Workflow composition\n│   ├── core-flows/      # Predefined workflows\n│   └── modules-sdk/     # Module development\n├── modules/             # 30+ commerce modules\n│   ├── product/, order/, cart/, payment/...\n│   └── providers/       # 15+ provider implementations\n├── admin/               # Dashboard packages\n│   └── dashboard/       # React admin UI\n├── cli/                 # CLI tools\n└── design-system/       # UI components\n/integration-tests/      # Full-stack tests\n/www/                    # Documentation site\n```\n\n**Key Directories:**\n- `packages/core/framework/` - Core runtime, HTTP, database\n- `packages/medusa/src/api/` - API routes\n- `packages/modules/` - Commerce feature modules\n- `packages/admin/dashboard/` - Admin React app\n\n### 2. Build System & Commands\n\n**Package Manager**: Yarn 3.2.1 with node-modules linker\n\n**Essential Commands:**\n```bash\n# Install dependencies\nyarn install\n# Build all packages\nyarn build\n# Build specific package\nyarn workspace @medusajs/medusa build\n# Watch mode (in package directory)\nyarn watch\n```\n\n**Testing Commands:**\n```bash\n# All unit tests\nyarn test\n# Package integration tests\nyarn test:integration:packages\n# HTTP integration tests\nyarn test:integration:http\n# API integration tests\nyarn test:integration:api\n# Module integration tests\nyarn test:integration:modules\n```\n\n**Generated Files:**\n\nAfter adding or removing keys in `packages/admin/dashboard/src/i18n/translations/en.json`, regenerate the JSON schema that validates all translation files:\n```bash\ncd packages/admin/dashboard && yarn i18n:schema\n```\nSkipping this leaves `Property <key> is not allowed` warnings on `en.json`, since `translations/$schema.json` is generated from `en.json` and lists every key in both `properties` and `required`. Commit the regenerated `$schema.json` with the translation change.\n\n### 3. Testing Conventions\n\n**Frameworks:**\n- Jest 29.7.0 (backend/core)\n- Vitest 3.0.5 (admin/frontend)\n\n**Test Locations:**\n- Unit tests: `__tests__/` directories alongside source\n- Package integration tests: `packages/*/integration-tests/__tests__/`\n- HTTP integration tests: `integration-tests/http/__tests__/`\n\n**Patterns:**\n- File extension: `.spec.ts` or `.test.ts`\n- Unit test structure: `describe/it` blocks\n- Integration tests: Use custom test runners with DB setup\n\n### 4. Code Style Conventions\n\n**Formatting (Prettier):**\n- No semicolons\n- Double quotes\n- 2 space indentation\n- ES5 trailing commas\n- Always use parens in arrow functions\n\n**TypeScript:**\n- Target: ES2021\n- Module: Node16\n- Strict null checks enabled\n- Decorators enabled (experimental)\n\n**Naming Conventions:**\n- Files: kebab-case (`define-config.ts`)\n- Types/Interfaces/Classes: PascalCase\n- Functions/Variables: camelCase\n- Constants: SCREAMING_SNAKE_CASE\n- DB fields: snake_case\n\n**Branch Naming:**\nBranch names must be prefixed by type, since the prefix drives the labels automatically applied to the PR:\n- `feat/readable-name`: new features\n- `fix/readable-name`: bug fixes\n- `chore/readable-name`: refactors, clean-ups, and similar work\n- `docs/readable-name`: docs-only PRs\n\n`readable-name` must describe the PR's changes (kebab-case). Do NOT use just the ticket number (e.g. use `fix/loyalty-admin-auth-type`, not `dx-2801`).\n\n**Export Patterns:**\n- Barrel exports via `export * from`\n- Named re-exports for specific items\n\n**General Conventions:**\n- NEVER use emojos.\n\n### 5. Architecture Patterns\n\n#### 5.1 Module Pattern - Services with Decorators\n\n**Service Structure:**\n- Extend `MedusaService<T>` with typed model definitions\n- Inject dependencies via constructor\n- Use decorators for cross-cutting concerns\n\n**Key Decorators:**\n- `@InjectManager()` - Inject entity manager (use on public methods)\n- `@InjectTransactionManager()` - Inject transaction manager (use on protected methods)\n- `@MedusaContext()` - Inject shared context as parameter\n- `@EmitEvents()` - Emit domain events after operation\n\n**Example:**\n```typescript\nexport class OrderModuleService\n  extends MedusaService<{ Order: { dto: OrderDTO } }>({ Order })\n  implements IOrderModuleService\n{\n  @InjectManager()\n  @EmitEvents()\n  async deleteOrders(\n    ids: string[],\n    @MedusaContext() sharedContext: Context = {}\n  ) {\n    return await this.deleteOrders_(ids, sharedContext)\n  }\n\n  @InjectTransactionManager()\n  protected async deleteOrders_(\n    ids: string[],\n    @MedusaContext() sharedContext: Context = {}\n  ) {\n    await this.orderService_.softDelete(ids, sharedContext)\n  }\n}\n```\n\n**Reference Files:**\n- `packages/modules/order/src/services/order-module-service.ts`\n- `packages/modules/api-key/src/services/api-key-module-service.ts`\n\n#### 5.2 API Route Pattern\n\n**Route Structure:**\n- Named exports for HTTP methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`\n- Type request: `AuthenticatedMedusaRequest<T>` or `MedusaRequest<T>`\n- Type response: `MedusaResponse<T>`\n- Access dependencies from `req.scope`\n- Use workflows from `@medusajs/core-flows`\n\n**Example:**\n```typescript\nimport { deleteOrderWorkflow } from \"@medusajs/core-flows\"\nimport { HttpTypes } from \"@medusajs/framework/types\"\nimport {\n  AuthenticatedMedusaRequest,\n  MedusaResponse,\n} from \"@medusajs/framework/http\"\n\nexport const DELETE = async (\n  req: AuthenticatedMedusaRequest,\n  res: MedusaResponse<HttpTypes.AdminOrderDeleteResponse>\n) => {\n  const { id } = req.params\n\n  await deleteOrderWorkflow(req.scope).run({\n    input: { id },\n  })\n\n  res.status(200).json({\n    id,\n    object: \"order\",\n    deleted: true,\n  })\n}\n```\n\n**Common Patterns:**\n- Filters: `req.filterableFields`\n- Pagination: `req.queryConfig.pagination`\n- Fields: `req.queryConfig.fields`\n- Resolve services: `req.scope.resolve(ContainerRegistrationKeys.QUERY)`\n\n**Reference Files:**\n- `packages/medusa/src/api/admin/orders/route.ts`\n- `packages/medusa/src/api/admin/payment-collections/[id]/route.ts`\n\n#### 5.3 Workflow Pattern\n\n**Step Definition:**\n- Create steps with `createStep(id, mainAction, compensationAction?)`\n- Return `StepResponse(result, compensationData)`\n- Compensation function handles rollback\n\n**Workflow Composition:**\n- Create workflows with `createWorkflow(id, function)`\n- Use `WorkflowData<T>` for typed input\n- Return `WorkflowResponse<T>` for typed output\n- Chain steps, use `transform()`, `when()`, `parallelize()`\n- Query data with `useQueryGraphStep()`\n- Emit events with `createHook()`\n\n**Example Step:**\n```typescript\nexport const deletePromotionsStep = createStep(\n  \"delete-promotions\",\n  async (ids: string[], { container }) => {\n    const promotionModule = container.resolve<IPromotionModuleService>(\n      Modules.PROMOTION\n    )\n    await promotionModule.softDeletePromotions(ids)\n    return new StepResponse(void 0, ids)\n  },\n  async (idsToRestore, { container }) => {\n    if (!idsToRestore?.length) return\n    const promotionModule = container.resolve<IPromotionModuleService>(\n      Modules.PROMOTION\n    )\n    await promotionModule.restorePromotions(idsToRestore)\n  }\n)\n```\n\n**Example Workflow:**\n```typescript\nexport const deletePromotionsWorkflow = createWorkflow(\n  \"delete-promotions\",\n  (input: WorkflowData<{ ids: string[] }>) => {\n    const deletedPromotions = deletePromotionsStep(input.ids)\n    const promotionsDeleted = createHook(\"promotionsDeleted\", {\n      ids: input.ids,\n    })\n    return new WorkflowResponse(deletedPromotions, {\n      hooks: [promotionsDeleted],\n    })\n  }\n)\n```\n\n**Reference Files:**\n- `packages/core/core-flows/src/promotion/steps/delete-promotions.ts`\n- `packages/core/core-flows/src/promotion/workflows/delete-promotions.ts`\n- `packages/core/core-flows/src/order/workflows/update-order.ts`\n\n#### 5.4 Error Handling\n\n**MedusaError Pattern:**\n- Use `new MedusaError(type, message)` for all error throwing\n- Provide contextual, user-friendly error messages\n- Validate inputs early in services and workflow steps\n\n**Common Error Types:**\n- `MedusaError.Types.NOT_FOUND` - Resource not found\n- `MedusaError.Types.INVALID_DATA` - Invalid input or state\n- `MedusaError.Types.NOT_ALLOWED` - Operation not permitted\n\n**Example:**\n```typescript\nimport { MedusaError, validateEmail } from \"@medusajs/framework/utils\"\n\n// In service\nif (!entity) {\n  throw new MedusaError(\n    MedusaError.Types.NOT_FOUND,\n    `Order with id: ${id} was not found`\n  )\n}\n\n// In workflow step\nif (input.email) {\n  validateEmail(input.email)\n}\n\nif (order.status === \"cancelled\") {\n  throw new MedusaError(\n    MedusaError.Types.NOT_ALLOWED,\n    \"Cannot update a cancelled order\"\n  )\n}\n```\n\n**Reference Files:**\n- `packages/core/utils/src/modules-sdk/medusa-internal-service.ts`\n- `packages/core/core-flows/src/order/workflows/update-order.ts`\n\n#### 5.5 Common Import Patterns\n\n**Path Aliases (configured in tsconfig.json):**\n- `@models` - Entity models\n- `@types` - DTO and type definitions\n- `@services` - Service dependencies\n- `@repositories` - Data access layer\n- `@utils` - Utility functions\n\n**Framework Imports:**\n```typescript\n// Utils and decorators\nimport {\n  InjectManager,\n  InjectTransactionManager,\n  MedusaContext,\n  MedusaError,\n  MedusaService,\n  EmitEvents,\n  Modules,\n} from \"@medusajs/framework/utils\"\n\n// Types\nimport type {\n  Context,\n  DAL,\n  IOrderModuleService,\n} from \"@medusajs/framework/types\"\n\n// Workflows\nimport {\n  WorkflowData,\n  WorkflowResponse,\n  createStep,\n  createWorkflow,\n  transform,\n} from \"@medusajs/framework/workflows-sdk\"\n\n// Core flows\nimport { deleteOrderWorkflow } from \"@medusajs/core-flows\"\n\n// HTTP\nimport {\n  AuthenticatedMedusaRequest,\n  MedusaResponse,\n} from \"@medusajs/framework/http\"\n```\n"}}