Migrate from dependency-cruiser
The config of Oxcruise is much smaller than the config of dependency-cruiser.
Oxcruise does not read .dependency-cruiser.* files in a check.
The oxcruise --migrate command converts one and says what it could not convert.
Run the migration
npx oxcruise --migrate
npx oxcruise --migrate -c .oxcruiserc.json
npx oxcruise --migrate=config/.dependency-cruiser.cjs -c config/oxcruise.config.ts- The first command reads
.dependency-cruiser.json,.js,.cjsor.mjs. It writesoxcruise.config.ts. -cnames the file to write. A.jsonname gives a JSON file.--migrate=FILEnames the file to read.
--migrate never overwrites a file. When the target exists, the command stops with "already exists".
Delete the file or choose another name with -c.
How the conversion works
The conversion is conservative:
- A path regex becomes a glob only when it has a common shape. See Regex to glob.
- Oxcruise drops a whole rule that uses a condition that it does not have, with a named warning. Dropping only the condition would make the rule broader than you wrote it.
- A regex that does not convert drops its rule, with a named warning.
- When the target is a TypeScript file, every warning is also in that file, as a
// TODO:comment. A.jsontarget has no comments, so the warnings go to stderr only. - Oxcruise drops
allowedandrequiredsections with a warning.
What maps
| dependency-cruiser | Oxcruise | If dropped, use instead |
|---|---|---|
forbidden[] | forbid[]. comment becomes message. | |
from.path, pathNot (regex) | from: a glob or a list. pathNot becomes a !glob in the same list. | |
to.path, pathNot (regex) | to: a glob or a list, or to.path | |
$1 back-references | {c1} captures: from: "src/{c1}/**" and to: ["src/**", "!src/{c1}/**"] | Write {name} yourself. |
to.dynamic, to.preCompilationOnly | to.dynamic, to.typeOnly | |
to.couldNotResolve: true | to.kind: "unresolved", or the unresolved-dependencies rule | |
to.reachable: true | to.reachable: true | |
severity | level: error, warn or off. info becomes warn, with a warning. | |
allowed[], allowedSeverity | Dropped. | The layers rule, or forbid rules. |
required[] | Dropped. | The require option of folder-structure for a file that a folder must have. Otherwise a JS plugin rule. |
from.orphan, to.orphan | Dropped. | The orphan-modules rule. |
numberOfDependents{Less,More}Than | Dropped. | A JS plugin rule. |
to.dependencyTypes, dependencyTypesNot, moreThanOneDependencyType | Dropped. | to.kind and to.typeOnly. The rules undeclared-packages, dev-dependencies-in-production, duplicate-packages, optional-dependencies, peer-dependencies and deprecated-dependencies. |
to.circular, via, viaOnly | Dropped. | The circular-dependencies rule with ignore and includeTypeOnly. Use overrides.files to limit it. |
to.exoticallyRequired, license, moreUnstable, ancestor | Dropped. | A JS plugin rule. |
scope: "folder" | Dropped. | The folders option of circular-dependencies for cycles between folders. Otherwise a JS plugin rule. |
options.doNotFollow | doNotFollow. Files in node_modules are always leaves. | |
options.exclude | ignorePatterns | |
options.includeOnly | Dropped. | Start from the right entries and list the rest in ignorePatterns. |
options.maxDepth | Dropped. | The --max-depth flag. |
options.tsConfig.fileName | resolve.tsconfig | |
enhancedResolveOptions.conditionNames | resolve.conditions. Oxcruise always tries import, require, node and default. | |
enhancedResolveOptions.extensions, mainFields | Dropped. | The resolver defaults. |
options.exoticRequireStrings | calls | |
options.detectJSDocImports, tsPreCompilationDeps | Always on. | |
extends: "dependency-cruiser/configs/recommended" | The default categories. | |
extends: ".../recommended-strict" | categories: { suspicious: "error" } | |
extends: ".../recommended-warn-only" | categories: { correctness: "warn" } | |
extends: "./other.json" | Oxcruise converts the other file too and merges it into the output. | |
webpackConfig, babelConfig | Dropped. | resolve.alias |
knownViolations, cache, combinedDependencies, moduleSystems | Dropped. |
Regex to glob
| Regex | Glob |
|---|---|
^src/ | src/** |
^src | src*. A regex without $ matches src2/, and the glob does too. |
[.]spec[.]ts$ | **/*.spec.ts |
(^|/)x/ | **/x/** |
^(src|lib)/ | {src,lib}/** |
^src/([^/]+)/ | src/{c1}/** |
a|b at the top level | Two globs. |
Other regexes do not convert. Examples are \d, [a-z], look-around and quantified groups.
Oxcruise drops the rule or the entry and names the regex.
The recommended rules
Oxcruise has the rules of the recommended config of dependency-cruiser built in. It sorts them into categories, and the default level of a category applies.
Two of the rules are off by default: optional-dependencies and peer-dependencies.
| dependency-cruiser | Oxcruise | Category |
|---|---|---|
no-circular | circular-dependencies. It checks runtime cycles only. | correctness, error |
not-to-unresolvable | unresolved-dependencies | correctness |
no-non-package-json | undeclared-packages | correctness |
not-to-dev-dep | dev-dependencies-in-production | correctness |
not-to-test, not-to-spec | dependencies-on-tests | correctness |
no-orphans | orphan-modules. By default it ignores dotfiles, .d.ts files, tsconfig*.json and *.config.*. | suspicious, warn |
no-deprecated-core, no-deprecated-npm | deprecated-dependencies | suspicious |
no-duplicate-dep-types | duplicate-packages | suspicious |
optional-deps-used, peer-deps-used | optional-dependencies, peer-dependencies | restriction, off |
What behaves differently
- Globs, not regexes. The
regexcrate matches rules in linear time, so Oxcruise needs no guard for unsafe regexes. Globs have*,**,?,[ab],{a,b}and{name}captures. - One report for each cycle. Oxcruise reports a cycle once and, by default, only when it exists at runtime. A compiler erases
import type. - Ignore comments exist. See Inline ignore comments.
- Exit codes. Errors give
1.--deny-warningswith warnings, and--max-warnings Nwhen exceeded, also give1. A bad config gives2. There is no--compat. - Output formats. They are
default,long,json,github,textand plugin reporters. The--visualizemode replacesdot,mermaidandarchi: it writes an interactive site (see Visualize the graph). Thejsonformat of Oxcruise has a different shape from thejsonformat of dependency-cruiser. A tool that reads the old output must read the new format. See Output formats. - Dual packages. Oxcruise resolves them by import syntax, as Node.js does. See Differences.
- Merged syntax kinds. A file that both imports and re-exports one module has both kinds on that dependency.
- No TypeScript install. Oxcruise parses TS, TSX, MTS, CTS, JSX, Vue, Svelte and Astro itself.
- Always extracted. They are JSDoc imports, triple-slash directives, and
new URL("./x", import.meta.url)andnew Worker(new URL(...)). callsreplacesexoticRequireStrings. The first string argument of the function is a dependency. It resolves as an ES import, unless the name of the function starts withrequire.- AMD. Ids without a leading
./resolve like package specifiers. Oxcruise does not read the requirejsbaseUrlandpathsconfig.
Check your migration
npx oxcruise --migrate -c .oxcruiserc.json
npx depcruise src -T json > before.json
npx oxcruise src -f json > after.jsonCompare the modules and the dependencies in the two files.
The tasks/conformance folder of the repository does this against dependency-cruiser 18.7. See Differences.

