1. Project Overview & Quickstart (reactioncommerce/reaction)
File: README.md
Mailchimp Open Commerce (formerly Reaction Commerce)
[Open Commerce Website](https://mailchimp.com/developer/open-commerce/) | [Twitter](https://twitter.com/getreaction) | [Documentation](https://mailchimp.com/developer/open-commerce/) | [Discord](https://discord.gg/Bwm63tBcQY) | [Discussions](https://github.com/reactioncommerce/reaction/discussions)
Mailchimp Open Commerce is an API-first, headless commerce platform built using Node.js, MongoDB, and GraphQL. It plays nicely with npm, Docker and Kubernetes.
Features
| Fast | Returns data in split seconds, and faster queries mean faster web pages |
|---|---|
| Proven | Open Commerce fuels sites doing 10's of thousands of orders per day with 100's of thousands of products |
| Composable | A flexible plugin system allows you to pick and choose which integrations work best for you |
| Multi-tenant | Host multiple shops in the same installation |
| Scalable | Start out with a single server and scale up to hundreds |
| Flexible Products | Allows Products, with options and variants to fit a wide variety of needs |
| Inventory | Track inventory, allow or disallow backorders and more |
| Shipping | Integrate with a shipping rate provider or build your own custom table |
| Taxes | Integrate with a tax rate provider or build your own custom tax table |
| Fulfillment | Flexible fulfillment system allows you create your own fulfillment methods |
| Order Tracking | View and manage your orders in the included admin system |
| Emails | Customizable templates for Order confirmations and more |
| Open | Fully open source. Never be locked in again |
Getting started
To start working with your own project built on Mailchimp Open Commerce you can start by using our new CLI. The CLI is
the quickest and easiest way to develop on Open Commerce. It allows you to create and work with API, Admin, and Storefront projects all via the command line.
What you need
We recommend installing nvm
-
In addition, you need to have your system setup for SSH authentication with GitHub
Install the CLI
First install the cli by running:
npm install reaction-cliYou can test to see if it has worked here by running:
reaction helpCreating a project
You can create your Open Commerce project by running:
reaction create-project api <your-project-name>This will create an Open Commerce project in the directory
Once this is complete, navigate to the project directory:
cd <your-project-name>Install the project dependencies:
npm installFinally, start the server in development mode:
reaction develop apiNote: Optionally, from within the project-directory you may issue the above command without mentioning the project type and the CLI would check your package.json for the "projectType" and pick it up from there. This expects that the project itself was built using the latest version of the CLI as explained in the above steps.
Example, instead of the above command, you may skip mentioning 'api' and just use:
reaction developThis will start the Open Commerce GraphQL server and Mongo Server. Press Ctrl+C to stop.
- A sample custom plugin has been installed, and you should see its output in the logs. (Your Sample Plugin)
- To add a new plugin based on our plugin template run:
reaction create-plugin api <your-plugin-name>Validate whether the plugin was created in the custom-packages
cd custom-packagescd <your-plugin-name>npm installYou now need to change back up to the root:
cd ../../now you can run:
reaction developThis plugin will now be loaded the next time you start Open Commerce.
Congratulations!! You're ready to start developing with Open Commerce
See the Complete CLI instructions for how to create your local storefront and admin.
Go to the complete installation instructions to see how to set up your store
API development
If you are working on core plugins (not developing plugins for your own installation) you should follow these
instructions
What you need
Install PNPM
npm i [email protected]Clone and Start the source
git clone https://github.com/reactioncommerce/reaction.git
cd reaction
pnpm install
cp apps/reaction/.env.example apps/reaction/.envStart dev-server with mongo on local:
## you must change MONGO_URL in the .env to mongodb://localhost:27017/reaction before start
pnpm run start:devStart dev-server with mongodb on docker
docker-compose up -d
pnpm run start:devDevelopment Flow
- Make some changes in one or more packages.
- Add a changeset in that same PR.
- Repeat the process of making changes and adding changesets.
- Create PR
How to release
- Run
releaseaction to createVersion PR. This PR will remove all changeset files, bump up packages versions, update CHANGELOG files. - Merge
Version PRinto trunk, CircleCI will publish all the packages into npm.
Prerelease flows
- All PRs will be merged into
prereleasebranch before triggeringPRERELEASEaction. - Before merging PRs into
prereleasebranch, please make sure that all the changesets are added. - Manually trigger
PRERELEASEaction to createVersion Packages (next)PR. After merged, the changeset/action will bump up packages versions as{next-version}-next.{number}, update CHANGELOG files. - Merge
Version Packages (next)PR intoprereleasebranch, action will publish all the packages into npm.
Get involved
Contribute
:star: If you like what you see, star us on GitHub.
Find a bug, a typo, or something thatโs not documented well? Weโd love for you to open an issue telling us what we can improve! This project uses commitlint, please use their commit message format.
We love your pull requests! Check out our Good First Issue and Help Wanted tags for good issues to tackle.
Check out our contributors guide for more information
License
Reaction is GNU GPLv3 Licensed
File: packages/reaction-error/README.md
reaction-error
Error handling for the Reaction API.
How To Use
Note: Be sure you are using NPM 5+
First install in your project directory:
npm install @reactioncommerce/reaction-errorImport ReactionError in the file you wish to use it in
import ReactionError from "@reactioncommerce/reaction-error";Releases
This NPM package is published automatically on every push to the trunk branch. Be sure to use proper Git commit messages so that the version will be bumped properly and release notes can be automatically generated.
- Refer to https://github.com/semantic-release/semantic-release#commit-message-format
- To avoid triggering a release, such as for a README-only change, include
[skip release]in your commit message.
File: packages/random/README.md
Random
A drop-in replacement for the Meteor random package. Unlike the Meteor package, you can use this either with or without Meteor.
Installation
npm i --save @reactioncommerce/randomUsage
import Random from "@reactioncommerce/random";
const id = Random.id();API
See Meteor package documentation
Other similar packages
The meteor-random NPM package ported Meteor's random package a few years back. This has the latest updates, modernized code, and tests.
File: packages/logger/README.md
reaction-logger
Reaction uses the Bunyan logging library to provide a stream capable log handler that can send your logs to a variety of places. By default, the Reaction logger outputs to the console (stdout), but you can also stream your server side logs to services like Loggly (see below) or even save them to your database.
Log Level
Most loggers have the concept of log level. That allows you to filter what is visible in your logs (see available levels and their descriptions below). The default levels in Reaction are INFO on the server and WARN on the client. To override the log level on the server, you can modify REACTION_LOG_LEVEL environment variable. Overriding the log level on the client requires using the settings.json approach - specifically in the public object (see below).
Environment Variables
To set the logger name that appears at the beginning of every log line and as the name key in the raw JSON output, you can set...
# default: Reaction
export REACTION_LOGGER_NAME="My Custom Logger"The default log level is INFO. You can override that with REACTION_LOG_LEVEL (see more about available levels below).
To set the server log level in development, you can add the environment variable before the reaction command when starting the app.
REACTION_LOG_LEVEL="DEBUG" reactionOr export it first...
export REACTION_LOG_LEVEL="DEBUG"
reactionTo set it in production (assuming you're using Docker), it would look like this:
docker run -e REACTION_LOG_LEVEL="DEBUG" ...Log Levels
When doing custom development and adding more logging to the app, we suggest following the Bunyan recommendations on log levels and use appropriate levels for your messages.
The log levels in Bunyan are as follows. The level descriptions are best practice opinions.
- "TRACE" (10): Logging from external libraries used by your app or very detailed application logging.
- "DEBUG" (20): Anything too verbose to be included in the standard "info" level.
- "INFO" (30): Detail on regular operation.
- "WARN" (40): Detail on something that should probably be looked at by an operator eventually.
- "ERROR" (50): Fatal for a particular event, but the service/app continues servicing other events. An operator should look at this soon.
- "FATAL" (60): The service/app is going to stop or become unusable now. An operator should definitely look into this soon.
Suggestions: Use "DEBUG" sparingly. Information that will be useful to debug errors post mortem should usually be included in "info" messages if it's generally relevant or else with the corresponding "error" event. Don't rely on spewing mostly irrelevant debug messages all the time and sifting through them when an error occurs.
Usage
import Logger from "@reactioncommerce/logger";
/**
* Logging general info
*/
// a general message string
Logger.info("Something important happened!");
// include some event-specific data in the message string
Logger.info(`Order ID ${order._id} has been submitted by user ${order.userId}`);
// or extend the JSON output of the logger with an object
// (note that the object should go before the message text)
Logger.info({ order }, "Order has been submitted");
/**
* Logging warnings
*/
// Log a non-critical warning that should be investigated
Logger.warn("API key missing. The feature won't work.");
/**
* Logging errors
*/
Logger.error("Something went wrong!");
// Bunyan has an error object parser built in, so you can pass
// errors into the logger and it will format them in your console
// as well as extend the raw JSON log output if you are piping
// your logs to another service like Loggly.
// (note that the error object should go before the message text)
doSomething((err, result) => {
if (err) {
Logger.error(err, "Something went wrong!");
throw err;
}
Logger.info("That thing worked!");
// or
Logger.info({ result }, "That thing worked!");
});
/**
* Logging fatal events
*/
// If an event is considered fatal (will stop the app from functioning
// entirely), you should use the FATAL log level.
// Note that this will rarely be needed. Most negative events
// are just warnings or errors and don't entirely prevent the
// app from running.
Logger.fatal("The app is going to crash now! Attention needed!");Outputs
As mentioned above, Bunyan is capable of sending your logs to a variety of services or you can even build your own plugin to send the raw JSON output to any API you choose. We suggest searching npm for Bunyan to see what options are already available before attempting to build your own. There are already a lot to choose from.
By default, Reaction sends logs to the console, but we also support sending to Loggly.
Loggly
Default level: DEBUG
Environment variables
# required
LOGGLY_SUBDOMAIN=""
LOGGLY_TOKEN=""
# optional
LOGGLY_LOG_LEVEL=""Developer Certificate of Origin
We use the Developer Certificate of Origin (DCO) in lieu of a Contributor License Agreement for all contributions to Reaction Commerce open source projects. We request that contributors agree to the terms of the DCO and indicate that agreement by signing-off all commits made to Reaction Commerce projects by adding a line with your name and email address to every Git commit message contributed:
Signed-off-by: Jane Doe <[email protected]>You can sign-off your commit automatically with Git by using git commit -s if you have your user.name and user.email set as part of your Git configuration.
We ask that you use your real full name (please no anonymous contributions or pseudonyms) and a real email address. By signing-off your commit you are certifying that you have the right to submit it under the MIT License.
We use the Probot DCO GitHub app to check for DCO sign-offs of every commit.
If you forget to sign-off your commits, the DCO bot will remind you and give you detailed instructions for how to amend your commits to add a signature.
License
Reaction Logger is MIT Licensed
File: packages/file-collections-sa-gridfs/README.md
file-collections-sa-gridfs
File: packages/file-collections-sa-base/README.md
file-collections-sa-base
File: packages/file-collections/README.md
file-collections
File: packages/db-version-check/README.md
@reactioncommerce/db-version-check
An NPM package that provides migrations for use with the @reactioncommerce/migrator CLI tool should use this package to check whether data is at the correct version before running any database commands.
Usage
This package exports only one function: doesDatabaseVersionMatch.
import doesDatabaseVersionMatch from "@reactioncommerce/db-version-check";
const ok = await doesDatabaseVersionMatch({
// `db` is a Db instance from the `mongodb` NPM package,
// such as what is returned when you do `client.db()`
db,
// These must match one of the namespaces and versions
// your package exports in the `migrations` named export
expectedVersion: 2,
namespace: "my-package-name",
// Defines what to do if no current version is found for this track in
// the database. By default, the check will fail. That is, we will assume
// that some data must need to be migrated. If you have a way of checking
// whether it's an empty database or confirming that no migrations are
// needed, you can do that and pass `true` here. Then the check will
// succeed and the current version for the track will be set to
// `expectedVersion`. Alternatively, pass a function that returns
// a Promise that returns `true` or `false`. This way you can avoid
// database lookups unless a decision is necessary.
async setToExpectedIfMissing() {
const anyAccount = await db.collection("Accounts").findOne();
// If there are no accounts, it's probably a brand new database
// so we can assume all our data will be at the latest version
// and mark it as such in the database.
return !anyAccount;
}
});
if (!ok) {
throw new Error('Database needs migrating. The "my-package-name" namespace must be at version 2.');
}Commit Messages
To ensure that all contributors follow the correct message convention, each time you commit your message will be validated with the commitlint package, enabled by the husky Git hooks manager.
Publication to NPM
The @reactioncommerce/db-version-check package is automatically published by CI when commits are merged or pushed to the trunk branch.
Developer Certificate of Origin
We use the Developer Certificate of Origin (DCO) in lieu of a Contributor License Agreement for all contributions to Reaction Commerce open source projects. We request that contributors agree to the terms of the DCO and indicate that agreement by signing-off all commits made to Reaction Commerce projects by adding a line with your name and email address to every Git commit message contributed:
Signed-off-by: Jane Doe <[email protected]>You can sign-off your commit automatically with Git by using git commit -s if you have your user.name and user.email set as part of your Git configuration.
We ask that you use your real full name (please no anonymous contributions or pseudonyms) and a real email address. By signing-off your commit you are certifying that you have the right to submit it under the Apache 2.0 License.
We use the Probot DCO GitHub app to check for DCO sign-offs of every commit.
If you forget to sign-off your commits, the DCO bot will remind you and give you detailed instructions for how to amend your commits to add a signature.
License
Copyright 2020 Reaction Commerce
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
File: packages/api-utils/docs/generateFilterQuery.md
generateFilterQuery
A function that generates a MongoDB filter query from an input GraphQL conditions object. It expects the input GraphQL conditions object to be in the format of the FilterConditionsInput input type (detailed below) defined in the GraphQL Schemas along with other parameters like context, collectionName and shopId.
As seen in the format below,
The input object is a nested object where you could use either
alloranykeys.Both the top level
all&anykeys are an array of objects with one more level ofalloranykeys.The inner
alloranykeys is an array of objects with the structure defined bySingleConditionInput.The
SingleConditionInputobject has the fields which define a single condition to filter on.The
allkey is equivalent of the$andoperator in MongoDB and theanykey is equivalent of the$oroperator in MongoDB.In the
SingleConditionInputobject, mandatory fields are thekey,relationalOperatorand exactly any ONE of the value fields. Thekeyis the field name to filter on. TherelationalOperatoris the relational operator to use to filter on the field (predefined as enum values). ThestringValue,integerValue,floatValue,booleanValue,dateValue,stringArrayValue,integerArrayValue,floatArrayValueare the values to filter on (use exactly one of this) depending on the key.Finally there are two more optional fields
caseSensitiveandlogicalNot. ThecaseSensitiveis a boolean flag to set if the regex is case sensitive. ThelogicalNotis a boolean flag to set if the condition is to be negated.
FilterConditionsInput format below (from GraphQL Schemas). Example follows the format below:
input FilterConditionsInput {
all: [ConditionsArray]
any: [ConditionsArray]
}
input ConditionsArray {
all: [SingleConditionInput]
any: [SingleConditionInput]
}
input SingleConditionInput {
booleanValue: Boolean
caseSensitive: Boolean
dateValue: DateTime
floatArrayValue: [Float]
floatValue: Float
integerArrayValue: [Int]
integerValue: Int
key: String!
logicalNot: Boolean
relationalOperator: RelationalOperatorTypes!
stringArrayValue: [String]
stringValue: String
}
enum RelationalOperatorTypes{
beginsWith
endsWith
eq
gt
gte
in
lt
lte
ne
nin
regex
}Example
Example of invoking the function with a simple conditions object. Here we are querying for products collection for entries with the handle as 'mens-waterproof-outdoor-rain-jacket'. Since it is single condition, using either all or any will not make difference.
import generateFilterQuery from "@reactioncommerce/api-utils/generateFilterQuery.js";
const conditions = {
all: [
{
any:[
{
key: "handle",
stringValue: "mens-waterproof-outdoor-rain-jacket",
relationalOperator: eq,
logicalNot: false
}
]
}
]
}
const { filterQuery } = generateFilterQuery(context, "Product", conditions, shopId);
return Products.find(filterQuery);Please refer to readme in the respective plugins for more detailed examples (example: api-plugin-products).
File: packages/api-utils/docs/getAbsoluteUrl.md
getAbsoluteUrl
A function that takes a root URL and a relative URL and combines them. Handles URLs that do and don't begin and end with slashes.
- It's fine to pass a path that may be undefined. Just the root URL will be returned.
- It's fine to pass a path that may already be absolute. It will be left alone.
Example:
const rootUrl = "http://localhost:3000/";
const path = "/media/test.jpg";
const url = getAbsoluteUrl(rootUrl, path); // http://localhost:3000/media/test.jpg2. Official Technical Reference & Guides (reactioncommerce/reaction-docs)
File: README.md
reaction-docs
๐ reaction-docs is the new static documentation generator for all Reaction Commerce projects.
Requirements
- Node, 6.x and above
- Yarn
- Docker
Stack
- Docusaurus, for static-site documentation generation
- Markdown for Docs
- React for components
- highlight.js for JavaScript, HTML, CSS, shell syntax highlighting
- Prism.js for JSX, GraphQL syntax highlighting
- Algolia DocSearch
- ESLint configured with Reaction Commerce eslint config
- LiveReload during development
- Docker
Contributing documentation
Run the docs website locally
git clone [email protected]:reactioncommerce/reaction-docs.git
cd reaction-docs
bin/setup
docker-compose upUpdate existing documentation
To update docs for the current released version of Reaction, edit existing Markdown files in website/versioned_docs.
- Find the Markdown file you want to edit in the latest version's folder, at
website/versioned_docs/version-CURRENTVERSION. If the document you want to edit is not in that folder, check in previous versions' folders until you find the latest one. - Edit the file and save.
- Go to
http://localhost:4242/docs/<YOURMARKDOWNFILE_ID>to see your changes locally.
Documenting unreleased features, changes
To update docs of unreleased features, you will need to edit existing Markdown files in public_docs. For example, if you were documenting upcoming Reaction API changes to Cart that are merged into trunk but not yet tagged in a release, you'd update the public-docs/cart.md file.
- Edit the file and save.
- Go to
http://localhost:4242/docs/next/<YOURMARKDOWNFILE_ID>to see your changes locally.
Documenting new, unreleased features
To create brand new documentation files for unreleased code that has previously not been documented, you will need to create new files in public_docs:
- At the start of the file, add the required frontmatter:
---
id: doc2
title: document number 2
---- Add the Markdown file to the table of contents, at
website/sidebars.json. - When you update
sidebars.json, you'll need to restart the app to see changes. Restart the app. - Go to
http://localhost:4242/docs/next/<YOURMARKDOWNFILE_ID>to see your new file locally.
Tips for documenting
- To add images, save the image in website/static/assets and reference it like this:
- To link to other articles, reference other articles by their filename:
Refer to the [FAQs](faqs.md) articleTo enable code syntax highlighting, add
js,jsx,graphql,html,sh,git,yamland more after the ```.For more Markdown features, including autogenerated table of contents, refer to Docusaurus docs.
Sign off your commits
We use the Developer Certificate of Origin (DCO) in lieu of a Contributor License Agreement for all contributions to Reaction Commerce open source projects. We request that contributors agree to the terms of the DCO and indicate that agreement by signing off all commits made to Reaction Commerce projects by adding a line with your name and email address to every Git commit message contributed:
Signed-off-by: Jane Doe [email protected]
You can sign off your commit automatically with Git by using git commit -s if you have your user.name and user.email set as part of your Git configuration.
We ask that you use your real name (please no anonymous contributions or pseudonyms). By signing your commit you are certifying that you have the right to submit it under the open source license used by that particular Reaction Commerce project. You must use your real name (no pseudonyms or anonymous contributions are allowed.)
We use the Probot DCO GitHub app to check for DCO signoffs of every commit.
If you forget to sign off git your commits, the DCO bot will remind you and give you detailed instructions for how to amend your commits to add a signature.
Contributing development
The Header, Footer, index page and version pages are developed in React and CSS within the website/core and website/static directories. Site configuration details are managed in website/siteConfig.js.
Logging
docker-compose up -d && docker-compose logs -fLinting
docker-compose run --rm web yarn lintdocker-compose run --rm web yarn lint:fix:eslintBuilding
docker-compose run --rm web yarn buildRunning commands
docker-compose run --rm web [...] will run any command inside a Docker container and then remove the container.
Restart
docker-compose run --rm web yarn install \
&& docker-compose down --rmi local \
&& docker-compose build \
&& docker-compose upTests
Tests are stubbed out for now.
Versioning
Add a new version
docker-compose run --rm web yarn run version <version>Rename an existing version to a new name
docker-compose run --rm web yarn run rename-version <currentVersion> <newVersion>See Versioning guide for more.
Releasing a new version
- Add a new version
docker-compose run --rm web yarn run version <version-number>- Restart the container:
docker-compose down && docker-compose upRun locally to confirm the version number has been changed in the header on http://localhost:4242, and the previous version has been added to the http://localhost:4242/versions list.
If all things look good, push the branch up to make a pull request.
Merge to
trunkto auto-deploy
Deploying
Merge to `staging` branch
Merging to staging will trigger a CircleCI build to https://reaction-docs-staging.reactioncommerce.com/ using Netlify.
Merge to `trunk` branch
Merging to trunk will trigger a CircleCI build to https://docs.reactioncommerce.com/ using Netlify.
Algolia search configuration
Search is generously provided by Algolia DocSearch. The configuration for this site's search available here and can be configured by sending a pull request to that repository. More details here.
File: docs/README.md
Architectural Decisions Records
Information around the architectural decisions made for this project should be
added to the architecture/decisions directory.
The NPM package adr is installed with this
project and can be used to add new decisions.
docker-compose run --rm web adr new "Implement the Torpedos"