Skip to content

Check a manifest

$ grim manifest:validate src/Admissions

You have edited a module.json by hand: added a dependency, set a category, bumped something. The same rules run in CI when a tag is pushed to the package's repository, and a red run there costs a round trip. grim manifest:validate applies them locally and names every broken field at once.

It is also the quick answer to "is anything in this project malformed": pointed at a project root it walks every manifest it can find.

Usage

$ grim manifest:validate                         # everything under the current directory
$ grim manifest:validate src/Admissions          # one module
$ grim manifest:validate resources/themes/frontend/shop-front/theme.json

It runs anywhere and needs no grim.json, no Docker and no login. The exit code is 1 when any manifest is invalid, so it fits a pre-commit hook.

Arguments and options

Validate module.json / theme.json / core.json against the grim manifest schema

Usage

grim manifest:validate [<path>]

Arguments

Argument Description
path Manifest file, package directory or monorepo root (optional, default: .)

What it actually does

  1. Finds the manifests. A file is taken as it is. A directory with module.json or theme.json at its root is a single package. Any other directory is walked as a project: core.json, every src/*/module.json and every resources/themes/*/*/theme.json.
  2. Validates each one by its file name and prints a or a with the path. Under a comes one line per problem, for example requires["cart"] must be a train constraint like "~2.0", got "^2.0".
  3. Prints a summary. Manifests, valid, invalid, and how many modules have no category.

What the schema asks for

Key module.json theme.json core.json
name Required, kebab-case Required, kebab-case Must be core
version Required, X.Y.Z Required, X.Y.Z Required, X.Y.Z
type module or core-module frontend or admin Not checked
namespace Required, PascalCase Not checked Not checked
provider Required, PascalCase, ends with Provider Not checked Not checked
requires Optional map of module to ~X.Y Not checked Not checked
requires-modules Not checked Optional list of module names Not checked
category Optional, from a fixed list Not checked Not checked
php Optional object with an extensions list Not checked Required constraint string, such as ^8.5
modules Not checked Not checked Optional, but then a sorted list without duplicates, never empty

Two keys are refused in every manifest: minimum-core and soft-requires. Both were removed with the 2.0 train, and the message says to delete them.

Pitfalls

Only ~X.Y passes as a constraint

^2.0, 2.0.* and >=2.0 are all rejected in requires. A module depends on a train, and ~2.0 is the one spelling of that. This is stricter than grim.json, where the core constraint may pin a single train.

A missing category is counted, not failed

Uncategorized 3 (category not set) in the summary is information. A category that is set must be one of commerce, insurance, finance, crm, content, communication, hr, ops, integrations or dev; anything else is an error.

The file name decides the rules

A manifest saved as module.backup.json fails with unknown manifest file name. Only module.json, theme.json and core.json are recognised.

After it finishes

Fix what it named and run it again until the summary reads Manifests valid. Then the change is safe to send on with grim push.

Questions

Does it check that the required modules exist?

No. It checks the shape of the file: names, versions, constraints. Whether cart exists on the train you asked for is resolved when the project installs or updates.

Does it change anything?

No. It reads files and prints. Nothing is fetched and nothing is written.

Recipes that use it

The idea underneath