Project structure
O3 consists of both monorepos and standalone repositories. Monorepos are used to group domain-specific packages that are related to each other. For example, patient management concerns such as registration and search live in the Patient Management (opens in a new tab) monorepo. Standalone repositories are used for single-purpose packages that are not related to other packages. For example, the Form Builder (opens in a new tab) package is a standalone repository that contains functionality for building and managing form schemas.
-
Monorepos should contain domain-specific packages that are related to each other. For example, patient management concerns such as registration and search live in the
openmrs-esm-patient-management
monorepo. -
Shared configuration files should generally exist at the root of the monorepo directory. These include:
.eslintignore
- ESLint ignore file.eslintrc
- ESLint configuration file.prettier.config.js
- Prettier configuration file.prettierignore
- Prettier ignore file.yarnrc.yml
- Yarn configuration filetsconfig.json
- Root TypeScript configuration fileturbo.json
- Turbo configuration filepackage.json
- Root package manifest file. This:- Defines workspace-level scripts for the monorepo
- Sets the
private: true
property which prevents the monorepo from accidentally being published to the npm registry. - Declares shared dependencies for the monorepo in the
peerDependencies
anddependencies
properties. - Defines the
workspaces
property which tells Yarn how to find the workspaces in the monorepo.
A typical convention is to place configuration files for the i18next parser, test utilities, and the Jest test setup file in a
tools
directory at the root of the monorepo:tools/i18next-parser.config.js
- i18next parser configuration filetools/setupTests.ts
- Jest test setup filetools/test-utils.tsx
- Test utilities
Configuration files you'd expect to find at the root of each package in the monorepo include:
package.json
- Manifest file for the package. This is where you should put scripts for the package. Importantly, this file doesn't have theprivate
property, meaning the package can be published to the npm registry.tsconfig.json
- TypeScript configuration file that extends the root TypeScript configuration file.jest.config.ts
- Jest configuration file that extends the root Jest configuration file.webpack.config.js
- Webpack configuration file that extends the root Webpack configuration file.
-
Place e2e tests in the
e2e/specs
directory at the root of your repository. -
Place test mocks in the top level
__mocks__
directory at the root of your repository. Mocks should be named after the module they are mocking. For example, if you have a mock with data for the@openmrs/esm-patient-allergies
module, your mock should be namedallergies.mock.ts
. The root-level Typescript configuration file will automatically pick up any mocks in the__mocks__
directory courtesy of thepaths
configuration in the roottsconfig.json
file:"paths": { "__mocks__": ["./__mocks__"], "tools": ["./tools"] },
This means you can import the mock in your tests using a path alias:
// TypeScript will automatically resolve the path to the mock import { mockAllergy } from '__mocks__';
TypeScript automatically resolves the path to the top-level
tools
directory using the same mechanism. This means you can also import test utilities from thetools
directory using a path alias:// TypeScript will automatically resolve the path to the tools directory import { waitForLoadingToFinish } from 'tools';