Import System
Janus provides a clear, hierarchical import system that distinguishes between native Janus modules, Zig libraries, and C libraries. This guide covers all three mechanisms and explains when to use each.
The Three Import Mechanisms
Section titled “The Three Import Mechanisms”| Mechanism | Syntax | Purpose | Runtime Cost |
|---|---|---|---|
| Native | use module.name | Import Janus modules | Zero |
| Zig Bridge | use zig "path.zig" | Import an explicit Zig bridge module or generated wrapper | Zero |
| C Graft | graft c "header.h" | Import C libraries | FFI boundary |
Native Imports: use
Section titled “Native Imports: use”The use statement is the Janus-native module import mechanism. It creates a namespace binding named after the last path component.
Basic Usage
Section titled “Basic Usage”// Import a module — binds the name "http" to the module's exportsuse std.net.http
// Use the imported moduleconst response = http.get("https://api.example.com/data")Resolution Algorithm
Section titled “Resolution Algorithm”The compiler resolves module paths by:
- Joining identifiers with
/(e.g.,std.net.http→std/net/http.jan) - Appending
.janextension - Searching relative to the source file’s directory
- Falling back to Janus stdlib root
Aliases with as
Section titled “Aliases with as”When you need a different name or want to avoid conflicts:
// Rename on importuse std.crypto.blake3 as hashuse std.io.file as fs
// Use the aliasconst digest = hash.digest(data)const content = fs.read("config.txt")Public Re-exports
Section titled “Public Re-exports”Modules can re-export other modules to create convenience indexes:
// std/std.jan — Standard Library Indexpub use std.core as corepub use std.io as iopub use std.net.http as http
// Users can now:// use std.http // Instead of use std.net.httpExplicit Zig Bridges: use zig
Section titled “Explicit Zig Bridges: use zig”Use use zig only when you are crossing an intentional Janus/Zig boundary.
That usually means one of these:
- an approved bridge module under
std/bridge - a local project bridge file
- a compiler-generated wrapper
Normal application .jan files should prefer Janus modules such as use std.crypto.blake3.
Importing Approved Bridge Modules
Section titled “Importing Approved Bridge Modules”// Explicit bridge modulesuse zig "std/bridge/process_bridge.zig"use zig "std/bridge/json_bridge.zig"
// Local project bridges are also validuse zig "bridge/net_bridge.zig"Why “Grafting”?
Section titled “Why “Grafting”?”The term “graft” reflects the Janus philosophy: foreign code is explicitly marked, contained, and can be replaced. Unlike opaque FFI bindings, grafted code:
- Is visible in your source (explicit
use zigorgraft c) - Is typed (Zig/C types map to Janus types at compile time)
- Is replaceable (swap the graft without changing call sites)
C Grafting: graft c
Section titled “C Grafting: graft c”For C libraries, use the graft c syntax with explicit aliasing and optional linking.
Basic C Import
Section titled “Basic C Import”// Import a C header with an aliasgraft c "oqs/oqs.h" as oqsgraft c "argon2.h" as argon2
// Use via the aliasconst rc = oqs.OQS_SIG_ml_dsa_65_verify(...)With Link Flags
Section titled “With Link Flags”// Specify the library to link againstgraft c "oqs/oqs.h" as oqs link "oqs"graft c "argon2.h" as argon2 link "argon2"graft c "sodium.h" as sodium link "sodium"The Grafting Doctrine (GD-1)
Section titled “The Grafting Doctrine (GD-1)”C code integration follows three principles:
- Explicit: The
graft ckeyword makes foreign code obvious - Contained: All FFI calls go through the named alias
- Replaceable: Swap implementations without changing consuming code
Comparison Table
Section titled “Comparison Table”// ❌ WRONG — Don't mix mechanismsconst std = @import("std") // Zig syntax, not Janusimport * as http from "http" // JavaScript syntax#include <stdio.h> // C preprocessor syntax
// ✅ CORRECT — Janus-native importsuse std.iouse zig "std/bridge/http_bridge.zig"graft c "stdio.h" as c_stdioModule Path Conventions
Section titled “Module Path Conventions”Janus Modules
Section titled “Janus Modules”// Standard libraryuse std.coreuse std.io.fileuse std.net.httpuse std.crypto.blake3
// Local project modulesuse myapp.modelsuse myapp.controllers.authZig Paths
Section titled “Zig Paths”// Approved bridge modulesuse zig "std/bridge/process_bridge.zig"use zig "std/bridge/http_bridge.zig"
// Local Zig files (relative to source file)use zig "../native/optimized.zig"use zig "bridge/wasm.zig"C Headers
Section titled “C Headers”// System headersgraft c "stdio.h" as c_stdiograft c "stdlib.h" as c_stdlib
// Local headersgraft c "../vendor/custom.h" as vendorgraft c "native/specialized.h" as nativeBest Practices
Section titled “Best Practices”1. Prefer Native Janus
Section titled “1. Prefer Native Janus”Use native Janus modules when available:
// ✅ Good — Native Janususe std.crypto.blake3
// ⚠️ Only if needed — explicit bridge moduleuse zig "std/bridge/json_bridge.zig"2. Use Descriptive Aliases
Section titled “2. Use Descriptive Aliases”// ✅ Good — Clear intentuse std.crypto.blake3 as hasheruse std.io.file as fs
// ❌ Avoid — Cryptic aliasesuse std.crypto.blake3 as b3use std.io.file as f3. Group Imports
Section titled “3. Group Imports”// Standard library importsuse std.coreuse std.iouse std.net.http
// Explicit bridge importsuse zig "std/bridge/process_bridge.zig"
// C library importsgraft c "oqs/oqs.h" as oqs
// Local project importsuse myapp.configuse myapp.models4. Document C Grafts
Section titled “4. Document C Grafts”//! TLS implementation using OpenSSL via graft
graft c "openssl/ssl.h" as ssl link "ssl"graft c "openssl/err.h" as ssl_err link "ssl"
/// Initialize SSL context/// Requires: libssl-dev installed on systempub func initContext() ssl.SSL_CTX { // ...}Migration from @import
Section titled “Migration from @import”Prior to version 2026.4.3, some Janus files incorrectly used Zig’s @import syntax. This has been deprecated and removed. Migrations should prefer Janus module paths first and only introduce use zig when the target is an explicit bridge module.
Migration Examples
Section titled “Migration Examples”| Old (Zig syntax) | New (Janus syntax) |
|---|---|
const std = @import("std") | use std |
const core = @import("core.jan") | use std.core as core |
const hash = @import("crypto/blake3.jan") | use std.crypto.blake3 as hash |
const local = @import("../local.jan") | use local (or appropriate module path) |
Why the Change?
Section titled “Why the Change?”- Language Identity: Janus is distinct from Zig; mixing syntax creates confusion
- Future-Proofing: The
@character is reserved for future inline documentation (e.g.,@param,@deprecated) - Consistency: A single, clear import mechanism for each use case
Related Concepts
Section titled “Related Concepts”- Grafting Doctrine — Deep dive into the philosophy and implementation of grafting
- Zig Integration Tutorial — Step-by-step guide to integrating Zig code
- Package Management — How Hinge manages module dependencies
- Language Reference — Complete syntax and semantics