# https://github.com/reactioncommerce/reaction Project Manual

Generated at: 2026-07-09 00:06:35 UTC

## Table of Contents

- [Overview](#page-overview)
- [Lib](#page-packages-api-utils-lib)
- [Src](#page-packages-api-plugin-accounts-src)
- [Src](#page-packages-api-plugin-carts-src)

<a id='page-overview'></a>

## Overview

### Related Pages

Related topics: [Lib](#page-packages-api-utils-lib)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/reactioncommerce/reaction/blob/main/README.md)
- [apps/meteor-blaze-app/package.json](https://github.com/reactioncommerce/reaction/blob/main/apps/meteor-blaze-app/package.json)
- [apps/reaction/.reaction/project-hooks/README.md](https://github.com/reactioncommerce/reaction/blob/main/apps/reaction/.reaction/project-hooks/README.md)
- [apps/reaction/package.json](https://github.com/reactioncommerce/reaction/blob/main/apps/reaction/package.json)
- [package.json](https://github.com/reactioncommerce/reaction/blob/main/package.json)
- [packages/api-core/README.md](https://github.com/reactioncommerce/reaction/blob/main/packages/api-core/README.md)
</details>

# Overview

## Project Purpose

Reaction is an open-source, API-first e-commerce platform built using Node.js, Express, MongoDB, and GraphQL. The repository hosts a Yarn workspaces monorepo that bundles the storefront/admin app, the legacy Blaze admin app, and a collection of reusable npm packages. The current major release is v5.0.0, which marks a major version bump in the API core. Source: [README.md:1-40]()

The platform targets headless commerce use cases and exposes its functionality through GraphQL mutations and queries rather than through the older Meteor pub/sub model. The goal of this transition is to make the API server runnable as a standalone Node application, decoupled from Meteor's runtime. Source: [README.md:30-60]()

## Repository Structure

The monorepo is organized into two top-level directories: `apps/` and `packages/`. Workspaces are declared at the root and glued together with a shared `package.json` and shared Node engine constraint.

| Directory | Purpose |
| --- | --- |
| `apps/reaction` | The main Reaction app — Node/Express API + modern admin |
| `apps/meteor-blaze-app` | Legacy Blaze-based admin UI running on Meteor |
| `packages/` | Reusable npm packages, e.g. `api-core`, plugins |

The root `package.json` declares the workspace glob, the engine pin to Node, and the scripts that orchestrate building, linting, and testing across all workspaces. Source: [package.json:1-40]() The `api-core` package README documents how plugins register and how the core Express/GraphQL server is assembled. Source: [packages/api-core/README.md:1-30]()

## Applications

### `apps/reaction`

This is the primary application. Its `package.json` declares the dependency on `@reactioncommerce/api-core` and other workspace packages, and it is the entry point the CLI and `reaction-cli` bootstrap. The `project-hooks` directory contains scripts that run during install/upgrade to seed configuration and copy fixtures into the project. Source: [apps/reaction/.reaction/project-hooks/README.md:1-20]() The app's `package.json` exposes scripts such as `start`, `build`, `lint`, and `test`. Source: [apps/reaction/package.json:1-60]()

### `apps/meteor-blaze-app`

The Blaze app is the legacy administration interface. It is a Meteor application and is being phased out in favor of the modern admin built into the main `apps/reaction` application. Its `package.json` declares Meteor-specific dependencies such as `meteor-node-stubs` and Blaze templating libraries. Source: [apps/meteor-blaze-app/package.json:1-60]()

## Architecture and Migration

The codebase has historically run on Meteor, both for the client (Blaze) and the server (publications and methods). Community issue #4996 ("[EPIC] Moving the API off Meteor") tracks the effort to extract the API server so it can boot as a plain Node process. Source: [README.md:30-60]()

In parallel, issue #5747 ("GQL: All the things") tracks the conversion of remaining Meteor methods, publications, and direct MongoDB writes into GraphQL operations. Sub-tasks for catalog and core have been completed. Source: [README.md:30-60]()

```mermaid
graph LR
  A[apps/reaction] --> C[Express + GraphQL API]
  C --> D[(MongoDB)]
  C --> E[packages/api-core]
  C --> F[plugins/* packages]
  B[apps/meteor-blaze-app] -->|legacy admin| D
  G[CLI / reaction-cli] --> A
  G --> B
```

## Packages and Plugins

`packages/api-core` is the keystone of the API server. It exports the bootstrap function that wires Express, GraphQL, the plugin loader, and the context factory used by resolvers. Plugins register themselves by name, register GraphQL schemas, register mutations/queries, and add startup hooks. Source: [packages/api-core/README.md:10-40]()

Other workspace packages typically live next to `api-core` and follow the same plugin conventions so they can be composed into a single API instance at startup. The root `package.json` workspace glob is what makes these packages resolvable to the apps via standard `node_modules` symlinks. Source: [package.json:1-30]()

## Developer Tooling

The root scripts delegate to Yarn workspaces to run lifecycle tasks across every workspace. Common scripts include `lint`, `test`, `build`, and `clean`, each of which fans out to the matching script defined in every workspace's `package.json`. Source: [package.json:20-50]() The main app defines scripts for running the API, seeding the database, and building distribution bundles. Source: [apps/reaction/package.json:10-50]() The Blaze app's scripts use Meteor's CLI under the hood, reflecting its distinct runtime. Source: [apps/meteor-blaze-app/package.json:5-40]()

## Known Operational Issues

Community-reported friction often centers on three areas. First, CLI install problems — issue #6856 documents cases where dependencies fail to publish to npm and break the local CLI install. Second, runtime image-upload failures — issue #6298 reports an exception during product image upload in the admin UI, traced to a runtime error in the asset pipeline. Third, overall performance, tracked in the long-standing #3233 epic, which benchmarks and improves request latency, Meteor startup time, and MongoDB query performance. Source: [README.md:30-60]()

Together these define the practical scope of the project today: a multi-app monorepo whose API server is being moved off Meteor, whose data access is being standardized on GraphQL, and whose plugin model lives in `packages/api-core`. New contributors should start by reading `README.md`, then `packages/api-core/README.md`, and then the `package.json` of the application they intend to modify.

---

<a id='page-packages-api-utils-lib'></a>

## Lib

### Related Pages

Related topics: [Overview](#page-overview), [Src](#page-packages-api-plugin-accounts-src)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [packages/api-utils/lib/CountryDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryDefinitions.js)
- [packages/api-utils/lib/CountryOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryOptions.js)
- [packages/api-utils/lib/CurrencyDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyDefinitions.js)
- [packages/api-utils/lib/CurrencyOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyOptions.js)
- [packages/api-utils/lib/LanguageOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/LanguageOptions.js)
- [packages/api-utils/lib/arrayJoinPlusRemainingQuery.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/arrayJoinPlusRemainingQuery.js)
</details>

# Lib

## Overview and Scope

The `lib` directory inside `packages/api-utils/` is the implementation heart of the Reaction Commerce `@reactioncommerce/api-utils` package. It groups together the static reference data and small, pure helper functions that are reused by the GraphQL API layer, plugins, and admin UI without depending on the wider app context (database, accounts, etc.). All exports are intended to be dependency-free and side-effect free, which makes them safe to import from server-only contexts as the project continues migrating off Meteor (tracked in [#4996](https://github.com/reactioncommerce/reaction/issues/4996)).

The folder is split into two thematic groups:

- **Reference data** — countries, currencies, and languages, each exposed both as raw definitions and as pre-shaped "options" consumable by UI select inputs.
- **Generic utilities** — small helpers such as `arrayJoinPlusRemainingQuery` that operate on plain JavaScript values.

Source: [packages/api-utils/lib/CountryDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryDefinitions.js), [packages/api-utils/lib/CurrencyDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyDefinitions.js), [packages/api-utils/lib/LanguageOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/LanguageOptions.js)

## Reference Data Files

### Country Data

`CountryDefinitions.js` provides the canonical list of supported countries used by shop, address, and tax-related resolvers. Adjacent to it, `CountryOptions.js` projects those definitions into the lightweight `{ value, label }` shape required by admin dropdowns and GraphQL enum-adjacent inputs. Keeping the two files separate lets server code depend on rich definitions while UI surfaces depend only on the slimmed-down options.

Source: [packages/api-utils/lib/CountryDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryDefinitions.js), [packages/api-utils/lib/CountryOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryOptions.js)

### Currency Data

`CurrencyDefinitions.js` mirrors the country pattern but for ISO 4217 currencies. It is the source of truth for currency codes, symbols, and display formatting that the catalog, cart, and pricing logic rely on. `CurrencyOptions.js` then reshapes those records into the same `{ value, label }` option list, ensuring UI components and GraphQL inputs share a single normalized shape.

Source: [packages/api-utils/lib/CurrencyDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyDefinitions.js), [packages/api-utils/lib/CurrencyOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyOptions.js)

### Language Data

`LanguageOptions.js` follows the same conventions as the country and currency option files, exposing a uniform list of supported languages. This uniformity is what allows the admin UI to render country, currency, and language pickers with identical components and the same data contract.

Source: [packages/api-utils/lib/LanguageOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/LanguageOptions.js)

## Generic Utility Functions

### `arrayJoinPlusRemainingQuery`

`arrayJoinPlusRemainingQuery.js` is a small string-building helper. It joins the first *n* items of an array with a separator and appends the remaining count in a query-string form (for example, `"a, b, c and 2 more"`). The function is intentionally framework-agnostic so it can be reused in URL construction, log lines, or human-readable summaries produced by GraphQL resolvers without pulling in extra dependencies.

Source: [packages/api-utils/lib/arrayJoinPlusRemainingQuery.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/arrayJoinPlusRemainingQuery.js)

## Conventions Inside the Directory

Every file in `lib/` follows two consistent conventions that downstream consumers can rely on:

| Pattern | Purpose |
| --- | --- |
| Raw `*Definitions.js` files | Authoritative reference data, suitable for server-side logic |
| Paired `*Options.js` files | Flat `{ value, label }` arrays ready for select inputs |

This pairing pattern means consumers should import `Definitions` when they need fields beyond a label, and `Options` when they only need an id/label pair. Adopting this rule keeps bundle size small on the client and avoids leaking data the UI does not render.

Source: [packages/api-utils/lib/CountryDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryDefinitions.js), [packages/api-utils/lib/CountryOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryOptions.js), [packages/api-utils/lib/CurrencyDefinitions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyDefinitions.js)

## Relationship to the Broader Migration

Because the items in this directory are pure data and pure functions, they are among the easiest modules to migrate off Meteor. They are referenced indirectly by the GraphQL conversion epic ([#5747](https://github.com/reactioncommerce/reaction/issues/5747)) because every country, currency, or language field exposed through GraphQL ultimately points back at the option lists defined here. Maintaining a single source for these values is what prevents drift between server validation and UI pickers — a frequent source of bugs in earlier versions where the data was duplicated across plugins.

Source: [packages/api-utils/lib/CountryOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CountryOptions.js), [packages/api-utils/lib/CurrencyOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/CurrencyOptions.js), [packages/api-utils/lib/LanguageOptions.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-utils/lib/LanguageOptions.js)

---

<a id='page-packages-api-plugin-accounts-src'></a>

## Src

### Related Pages

Related topics: [Lib](#page-packages-api-utils-lib), [Src](#page-packages-api-plugin-carts-src)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [packages/api-plugin-accounts/src/config.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/config.js)
- [packages/api-plugin-accounts/src/index.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/index.js)
- [packages/api-plugin-accounts/src/mutations/createAccount.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/mutations/createAccount.js)
- [packages/api-plugin-accounts/src/queries/roles.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/queries/roles.js)
- [packages/api-plugin-accounts/src/i18n/ar.json](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/i18n/ar.json)
- [packages/api-plugin-accounts/src/i18n/en.json](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/i18n/en.json)
- [packages/api-plugin-accounts/src/i18n/fr.json](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/i18n/fr.json)
- [packages/api-plugin-accounts/src/i18n/vi.json](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/i18n/vi.json)
- [packages/api-plugin-accounts/src/registration/setupAccount.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/registration/setupAccount.js)
- [packages/api-plugin-accounts/src/schemas/accounts.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-accounts/src/schemas/accounts.js)
</details>

# Src

The `src` directory in a Reaction Commerce plugin (e.g., `packages/api-plugin-accounts/src`) is the canonical location for all executable, declarative, and locale-specific source code belonging to that plugin. Every API plugin in the Reaction monorepo follows the same `src/` layout so that the platform's plugin loader can resolve entry points, mutations, queries, schemas, and translation strings uniformly. Source: [packages/api-plugin-accounts/src/index.js:1-40]()

## Role and Scope

`src/` is where plugin authors place the JavaScript modules, GraphQL schemas, JSON translation files, and helper functions that make up a plugin's runtime behavior. The top-level `src/index.js` typically registers the plugin with the Reaction API, including its name, GraphQL type definitions, resolvers, mutations, queries, and any background functions. Source: [packages/api-plugin-accounts/src/index.js:1-80]() The directory intentionally excludes build artifacts, tests, and fixtures, which live in sibling folders.

Within the plugin, `src/` is subdivided into thematic subdirectories that group related concerns:

| Subdirectory | Purpose |
| --- | --- |
| `mutations/` | GraphQL mutation resolvers (e.g., createAccount) |
| `queries/` | GraphQL query resolvers (e.g., roles) |
| `schemas/` | GraphQL SDL schemas and input types |
| `registration/` | Account lifecycle helpers (e.g., setupAccount) |
| `i18n/` | JSON translation catalogues keyed by locale |
| `config.js` | Static plugin configuration values |

Source: [packages/api-plugin-accounts/src/mutations/createAccount.js:1-50](), [packages/api-plugin-accounts/src/queries/roles.js:1-40](), [packages/api-plugin-accounts/src/schemas/accounts.js:1-30]()

## Common Code Patterns

### Entry Point and Plugin Registration

`src/index.js` exports a default plugin descriptor that the API runtime consumes. It wires together the GraphQL schemas from `schemas/`, the mutation resolvers from `mutations/`, the query resolvers from `queries/`, and the registration helpers from `registration/`. This is the file imported by `node_modules/@reactioncommerce/api-plugin-accounts` at runtime. Source: [packages/api-plugin-accounts/src/index.js:20-120]()

### Configuration

`src/config.js` exports static, non-secret configuration (such as default session ages or password policy thresholds) as JavaScript objects. Mutations and queries read from this file rather than embedding magic numbers. Source: [packages/api-plugin-accounts/src/config.js:1-60]()

### Mutations, Queries, and Resolvers

Mutation modules export async functions that accept a GraphQL `context` and resolved input, then perform database writes through the context's collections. Query modules export analogous functions for reads. The naming convention is verb-first (`createAccount`, `inviteShopMember`). Source: [packages/api-plugin-accounts/src/mutations/createAccount.js:10-90]()

### GraphQL Schemas

`src/schemas/*.js` files export tagged template literals written with the `@graphly/dapper`/`apollo` template tag, defining GraphQL type extensions, input types, and the mutations/queries themselves. The plugin's `index.js` references these to compose its public API surface. Source: [packages/api-plugin-accounts/src/schemas/accounts.js:1-80]()

### Account Lifecycle Helpers

`src/registration/setupAccount.js` and similar files encapsulate reusable workflows used by multiple mutations, keeping mutation files thin and delegating the orchestration logic. Source: [packages/api-plugin-accounts/src/registration/setupAccount.js:1-50]()

## Internationalization (i18n)

The `src/i18n/` subdirectory contains locale-specific JSON catalogs, one file per language (`en.json`, `fr.json`, `vi.json`, `ar.json`, etc.). Each file exports an object whose keys map to string identifiers used by the plugin's UI surfaces. Adding a new language is a matter of dropping a new JSON file with translated values; the API loader picks them up automatically based on the active shop locale. Source: [packages/api-plugin-accounts/src/i18n/en.json:1-200](), [packages/api-plugin-accounts/src/i18n/fr.json:1-200](), [packages/api-plugin-accounts/src/i18n/vi.json:1-200](), [packages/api-plugin-accounts/src/i18n/ar.json:1-200]()

This locale layout is particularly important because account-related strings (validation messages, email subjects, invitation copy) are surfaced in many places; centralizing them in `src/i18n/` avoids duplication. Community issue #6856 reported broken CLI workflows that prevented dependable dependency resolution — when packages fail to publish, the i18n JSON files are sometimes the first assets dropped, so the loader's tolerant behavior matters in practice. Source: [packages/api-plugin-accounts/src/i18n/en.json:1-50]()

## Architectural Summary

```mermaid
flowchart TD
  A["src/index.js (plugin descriptor)"] --> B["mutations/"]
  A --> C["queries/"]
  A --> D["schemas/"]
  A --> E["registration/"]
  A --> F["config.js"]
  A --> G["i18n/*.json"]
  B --> H["context.collections, context.account"]
  C --> H
  D --> I["GraphQL SDL strings"]
  E --> J["workflow helpers"]
```

Source: [packages/api-plugin-accounts/src/index.js:30-100](), [packages/api-plugin-accounts/src/mutations/createAccount.js:1-60](), [packages/api-plugin-accounts/src/queries/roles.js:1-40](), [packages/api-plugin-accounts/src/schemas/accounts.js:1-50](), [packages/api-plugin-accounts/src/registration/setupAccount.js:1-40](), [packages/api-plugin-accounts/src/config.js:1-50]()

## Practical Notes for Contributors

- New mutations belong in `src/mutations/` and must be referenced from `src/index.js` under the plugin's `mutations` field to be exposed on the GraphQL gateway. Source: [packages/api-plugin-accounts/src/index.js:40-90]()
- Keep `config.js` free of environment-specific secrets — secrets live in the platform's configuration loader, while `config.js` holds defaults. Source: [packages/api-plugin-accounts/src/config.js:1-40]()
- When adding a string visible to users, prefer reusing an existing i18n key in `src/i18n/en.json`; if a new key is required, supply translations for all supported locales to avoid fallback warnings. Source: [packages/api-plugin-accounts/src/i18n/en.json:1-100]()
- The `src/` boundary mirrors the public package boundary — anything exported from `src/index.js` should be considered a stable surface, while internal helpers (e.g., in `registration/`) may change. Source: [packages/api-plugin-accounts/src/registration/setupAccount.js:1-30]()

Because the Reaction platform emphasizes moving "all the things" to GraphQL (#5747) and decoupling from Meteor (#4996), the structure of `src/` is intentionally narrow and explicit: each plugin ships its own `src/` with a predictable shape, which makes it feasible to compose the platform from independently publishable npm packages while preserving a uniform developer experience.

---

<a id='page-packages-api-plugin-carts-src'></a>

## Src

### Related Pages

Related topics: [Src](#page-packages-api-plugin-accounts-src)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [packages/api-plugin-carts/src/index.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-carts/src/index.js)
- [packages/api-plugin-carts/src/fulfillmentCartVersion.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-carts/src/fulfillmentCartVersion.js)
- [packages/api-plugin-carts/src/mutations/convertAnonymousCartToNewAccountCart.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-carts/src/mutations/convertAnonymousCartToNewAccountCart.js)
- [packages/api-plugin-carts/src/mutations/reconcileCarts.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-carts/src/mutations/reconcileCarts.js)
- [packages/api-plugin-carts/src/queries/cart.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-carts/src/queries/cart.js)
- [packages/api-plugin-orders/src/index.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-orders/src/index.js)
- [packages/api-plugin-products/src/index.js](https://github.com/reactioncommerce/reaction/blob/main/packages/api-plugin-products/src/index.js)
</details>

# Src

The `src` directory is the canonical home for all hand-written application code in the Reaction Commerce monorepo. Every plugin in the `packages/*` workspace exposes its runtime logic from a `src/` folder, which is compiled by the platform's Babel/Node toolchain and registered with the main Reaction API at boot. Reading any plugin in this repository starts inside its `src/` tree.

## Purpose and Scope

`src/` contains the executable logic, GraphQL schemas, and resolvers that implement a plugin's domain behavior. Configuration metadata (package version, name, dependencies) lives one level up in `package.json`, while compiled artifacts land in `dist/` after the build step. Everything in `src/` is plain ES modules/CommonJS source consumed by the host application through the plugin's exported `index.js`.

The contents of `src/` are organized to map cleanly to Reaction's plugin contract: each plugin declares the mutations, queries, schemas, and simple helpers it contributes, then exports them from a single `index.js` entry. This convention is what allows the v5 platform to compose features such as carts, orders, products, and payments as independent, composable modules. The community has tracked the effort to consolidate this surface into GraphQL under the "GQL: All the things" epic (issue #5747), and `src/` is where that consolidation is implemented.

## Layout of a Typical `src/` Tree

While the exact contents differ per plugin, a Reaction plugin's `src/` directory follows a recurring shape:

- `index.js` — plugin entry point. Registers the plugin, declares its name/version, and wires its provided functions into the Reaction plugin registry.
- `mutations/` — one file per GraphQL mutation, each exporting a pure async function that takes a context object and an input object and returns the mutation result.
- `queries/` — one file per GraphQL query, structured identically to mutations but read-only.
- `schemas/` — GraphQL type definitions (`.graphql`) and resolvers consumed by the Apollo server.
- `simpleSchemas/` — SimpleSchema definitions that validate inputs and outputs in Node.
- Pre-compiled helpers, such as `fulfillmentCartVersion.js`, that are reused across multiple mutations/queries without being resolvers themselves.

For example, the carts plugin puts its cart reconciliation logic in `mutations/reconcileCarts.js` and the cart fetch in `queries/cart.js`, with cross-cutting helpers such as `fulfillmentCartVersion.js` living at the top of `src/`. Snapshot tests accompany each mutation under `mutations/__snapshots__/`, giving reviewers a contract for the JSON shape returned to callers. This layout is mirrored across `api-plugin-orders`, `api-plugin-products`, and other domain plugins.

## Plugin Registration and Entry Point

The `index.js` of each plugin is the single integration point with the Reaction platform. It calls `reactionApp.registerPlugin` (or the equivalent registration helper exposed by the platform) and passes an object describing what the plugin provides. The registered object typically includes the plugin's `name`, `version`, and a `contextAdditions` or `functionsByType` map listing the GraphQL queries, mutations, and event hooks contributed by this plugin.

The `fulfillmentCartVersion.js` helper, for instance, is imported by mutations inside `mutations/` and re-exported as part of the plugin's public surface only when other plugins need it. This keeps the `index.js` file small and focused on registration, while domain logic stays close to the GraphQL operations that invoke it. The pattern is consistent with the move away from Meteor methods that the community has been working through in epic #4996 ("Moving the API off Meteor"); today's `src/` files are pure Node modules with no Meteor runtime assumptions.

## Practical Guidance for Contributors

When working in `src/`, three conventions tend to surprise newcomers:

1. **Mutations are pure functions of context + input.** They do not read from Express request objects or session state directly; the context object is assembled by the platform and passed in. Adding a new mutation means adding a new file under `mutations/`, a corresponding `__snapshots__/` test, and an entry in the plugin's `index.js`.
2. **SimpleSchema still guards inputs.** Even though the runtime is no longer Meteor-based, schema validation is performed by SimpleSchema definitions colocated in `simpleSchemas/` and called at the top of each mutation. This is the source of several runtime errors users have reported, for example the "Upload images" failure tracked in issue #6298.
3. **Performance matters at this layer.** Because every request funnels through `src/` functions, the long-running "Performance" epic (#3233) tracks benchmarking and optimization work primarily against code in this directory. Hot paths such as `reconcileCarts.js` and `convertAnonymousCartToNewAccountCart.js` are the typical targets.

| Directory        | Role                                                              |
|------------------|-------------------------------------------------------------------|
| `index.js`       | Plugin registration and exports                                   |
| `mutations/`     | One file per write operation; snapshots under `__snapshots__/`    |
| `queries/`       | One file per read operation                                       |
| `schemas/`       | GraphQL SDL and resolvers for Apollo                              |
| `simpleSchemas/` | SimpleSchema definitions for input/output validation              |
| `*.js` helpers   | Domain logic shared between mutations/queries (e.g. version keys) |

In summary, `src/` is where Reaction's plugin model becomes concrete: a predictable directory layout, a single registration entry point, and pure-function GraphQL operations that the platform composes into the running API. Familiarity with this layout is the prerequisite for contributing to any of the v5 plugin packages.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: reactioncommerce/reaction

Summary: Found 11 structured pitfall item(s), including 5 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

## 1. Installation risk - Installation risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/reactioncommerce/reaction/issues/6866

## 2. Configuration risk - Configuration risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/reactioncommerce/reaction/issues/6484

## 3. Maintenance risk - Maintenance risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/reactioncommerce/reaction/issues/6869

## 4. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/reactioncommerce/reaction/issues/6871

## 5. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/reactioncommerce/reaction/issues/6400

## 6. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/reactioncommerce/reaction

## 7. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/reactioncommerce/reaction

## 8. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/reactioncommerce/reaction

## 9. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/reactioncommerce/reaction

## 10. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/reactioncommerce/reaction

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/reactioncommerce/reaction

<!-- canonical_name: reactioncommerce/reaction; human_manual_source: deepwiki_human_wiki -->
