Modules
IonPath supports external module dependencies — reusable schema packages that your project can import types from. Modules are declared in ion.config.json and imported via the #import directive.
Overview
A module is an IonPath project that exposes its type definitions for use in other projects. Each module has its own ion.config.json and can itself depend on other modules.
- Declare module dependencies in your ion.config.json
- Import specific types using
#import { Type } from "module" - The compiler resolves all modules, parses their
.ionfiles, and makes imported types available
Declaring Dependencies
Add a modules section to your ion.config.json. Each key is the module name, and the value is a relative path to the module's root directory:
{
"name": "MyProject",
"features": ["std"],
"modules": {
"auth": "../shared/auth-contracts",
"common": "../shared/common-types"
},
"generators": {
"dotnet": {
"features": ["models", "client", "server"],
"outputs": "./"
}
}
} The module path must point to a directory containing a valid ion.config.json. If the config file is missing, the compiler reports ION0041.
Importing Types
Use the #import directive to bring specific types from a module into scope:
#import { User, Role } from "auth" service UserService() { GetUser(id: u4): User; GetRoles(userId: u4): Array<Role>; }
Only the listed types are imported — unlike the deprecated #use directive, which imported everything from a file.
Resolution Process
When the compiler encounters module dependencies, it performs the following steps:
Read Module Config
Reads ion.config.json from the module's root directory to discover the module's name, features, and its own dependencies.
Parse Module Files
All .ion files in the module directory are parsed. Types defined in these files become available for import.
Resolve Transitive Dependencies
If the module itself declares dependencies in its modules section, those are resolved recursively. Paths are relative to the dependent module's root.
Content Hashing
A SHA-256 hash of all module source files is computed for change detection. The hash is stored in the lock file and validated on subsequent compilations (ION0046).
Topological Ordering
Modules are sorted in dependency order — dependencies are compiled before dependents, ensuring all types are available when needed.
Cycle Detection
Circular module dependencies are forbidden. If module A depends on B and B depends on A (directly or transitively), the compiler reports ION0040.
// ✗ ion.config.json in project-a { "modules": { "b": "../project-b" } } // ✗ ion.config.json in project-b { "modules": { "a": "../project-a" } // ION0040: Circular module dependency }
Break the cycle by extracting shared types into a separate module that both projects can depend on.
Name Conflicts
If your project defines a type with the same name as a type in an imported module, the compiler reports ION0048 as a warning. Rename one of the types to avoid ambiguity.
Unused Imports
Importing a type that is never referenced produces ION0045 (warning). This helps keep imports clean and explicit.
Related Diagnostics
ion.config.json) not found #use directive