Djazair Package Manager (DPM)

DPM is the official, self-hosted package manager and build orchestrator for the Djazair Programming Language. Written natively in Djazair, DPM provides project scaffolding, Semantic Versioning (SemVer) dependency resolution, multi-source downloading (GitHub monorepos, Git repositories, HTTP ZIPs, and local archives), isolated per-project dependency trees, global tool installations, and automated native compilation for hybrid C/C++ packages.

Native Architecture

DPM is implemented as a core Djazair application (dpm/init.dz) and can be executed either directly via the standalone dpm wrapper script (dpm.bat on Windows, dpm on POSIX) or through the language driver: djazair dpm <command>.

Architecture & Core Concepts

DPM is architected around deterministic dependency management, clean isolation, and cross-platform portability. Understanding these foundations is essential for developing production-grade applications and reusable packages in Djazair.

Local Isolation vs Global Scope

DPM operates in two distinct execution modes:

  • Local Project Scope (Default): Dependencies are installed strictly within the project directory inside the isolated djazair_packages/ folder. Modifications are recorded directly in the project's root dpm.json manifest. This ensures completely reproducible builds and guarantees that two projects on the same machine can safely depend on different versions of the same library without conflict.
  • Global System Scope (-g, --global): Installs packages system-wide in the language runtime directory (or ~/.djazair/packages). This mode is ideal for developer command-line tools, language extensions, and global utilities that need to be accessible from any working directory.
Scope Default Installation Directory Manifest Impact Primary Use Case
Local (Default) <project_root>/djazair_packages/ Pinned to root dpm.json (require) Application libraries, database drivers, framework plugins
Global (-g) <djazair_root>/packages/ or ~/.djazair/packages/ None (standalone installation) CLI utilities, linters, system-wide code generators

Package Classification: Pure vs Hybrid

DPM explicitly recognizes two primary categories of packages:

  1. Pure Packages ("type": "pure"): Built entirely in Djazair source code (.dz files). They require no external compiler toolchain, install instantaneously across all operating systems (Windows, Linux, macOS), and have zero native binary dependencies.
  2. Hybrid Packages ("type": "hybrid"): Contain both Djazair wrapper code and low-level C or C++ extensions (e.g., SQLite, WebSockets, image processing). They declare platform-specific build scripts (build.bat on Windows, build.sh on POSIX) and link against the Djazair C runtime header files (djazair_api.h) and static library (libdjazair.a).

Runtime Module Resolution Hierarchy

When your Djazair script issues an import or use statement, the interpreter resolves packages in the following strictly defined order:

  1. Project-Local Directory Package: <project_root>/djazair_packages/<name>/init.dz
  2. Project-Local Single-File Package: <project_root>/djazair_packages/<name>.dz
  3. Global System Package: <djazair_root>/packages/<name>/init.dz
  4. Built-In Standard Library: Embedded C/Djazair standard modules (e.g., math, json, http, file).
---

Semantic Versioning (SemVer 2.0.0 Engine)

DPM embeds an internal, full-featured SemVer parsing and evaluation engine (dpm/core/semver.dz). When declaring dependencies or updating packages, DPM evaluates version constraints to ensure breaking changes are never introduced unintentionally.

Constraint Pattern Example Matching Versions Behavior & Rationale
Caret (^) (Default) ^1.2.0 1.2.0, 1.2.3, 1.9.9 (Rejects 2.0.0) Allows backwards-compatible minor and patch updates. For zero-major versions (^0.2.0), minor increments are treated as breaking (matches 0.2.x, rejects 0.3.0).
Tilde (~) ~1.2.0 1.2.0, 1.2.9 (Rejects 1.3.0) Restricts updates strictly to patch releases. Useful when minor versions might alter API behavior.
Exact 1.2.3 Only 1.2.3 Locks dependency to an exact release. Essential for ultra-deterministic critical deployments.
Wildcard / Latest * or latest Any version Matches the absolute latest release found upstream.
Comparison Operators >=1.0.0 <2.0.0 Any version in range Supports standard relational bounds (>=, >, <=, <).
Pre-Release Identifiers 1.0.0-rc.1 SemVer pre-release Parsed cleanly via semver.parse(), allowing development candidate tracking.
---

Complete CLI Reference & Workflows

DPM commands share a consistent interface, intuitive aliases, and standardized flag behavior:

bash
dpm <command> [options] [arguments]
# or
djazair dpm <command> [options] [arguments]

Global Command-Line Flags

  • -g, --global: Target the global language packages directory instead of the project-local workspace.
  • -q, --quiet: Run quietly, suppressing all non-error informational logs.
  • --verbose: Enable verbose diagnostic traces, showing git command outputs and path resolution steps.
  • -v, --version: Print DPM version, Djazair engine version, host OS platform, and author info.
  • -h, --help: Display interactive help screen.

1. Project Scaffolding: dpm init

Initializes a new Djazair project or library package. It launches an interactive wizard that prompts for project metadata and automatically generates a standard dpm.json manifest, starter entrypoint, .gitignore, and README.md.

bash
# Interactive scaffolding wizard
dpm init

# Non-interactive mode (accepts all sensible defaults immediately)
dpm init --yes
# or
dpm init -y

When run, dpm init scaffolds the following standard directory structure:

bash
my_project/
├── dpm.json         # Package manifest & dependency declarations
├── init.dz          # Primary entrypoint with starter function
├── .gitignore       # Pre-configured to ignore djazair_packages/ and build binaries
└── README.md        # Formatted markdown documentation with install/usage examples
Automatic Git Safety

The generated .gitignore automatically excludes djazair_packages/, native build artifacts (*.dll, *.so, *.dylib, *.o, *.a), build flags (.built), and the DPM temporary cache (.dpm_cache/). This ensures you never accidentally commit downloaded dependencies or compiled binaries to source control.

2. Package Installation: dpm install

The install command (aliases: i, add) handles both batch dependency synchronization and single package retrieval.

Batch Manifest Installation

Running dpm install without arguments reads the local dpm.json, parses the require block, and recursively downloads, verifies, and installs every listed dependency:

bash
dpm install

Supported Package Specifiers & Source Formats

DPM supports an exceptionally versatile range of source identifiers:

Source Format Syntax Example Resolution Mechanism
Shorthand Name dpm install sqlite
dpm install qalam
Checks local offline packages (<djazair_root>/packages/) first; if not found, fetches from the official extensions monorepo (github:djazair-language/djazair-extensions/<name>).
GitHub Monorepo Subdirectory dpm install github:org/repo/subfolder Clones/caches the repository and extracts the specified subdirectory as a standalone package.
GitHub Repository Shorthand dpm install github:user/repo Clones directly from https://github.com/user/repo.git.
Direct Git URL dpm install https://github.com/team/auth.git Executes shallow clone (--depth 1), cleans up .git metadata, and places package in djazair_packages/auth.
Direct HTTP/HTTPS ZIP Archive dpm install https://cdn.example.com/matrix.zip Downloads archive to DPM cache and extracts cleanly into project packages.
Local Directory or Archive dpm install ./libs/my-custom-pkg
dpm install ../archives/pkg.zip
Copies local filesystem directory or extracts local archive directly into djazair_packages/.

Installation Modifiers

bash
# Install globally into language packages directory
dpm install -g qalam

# Install without updating the root dpm.json manifest
dpm install sqlite --no-save

# Force re-download and re-install even if package directory exists
dpm install sqlite --force

3. Package Upgrades: dpm update

The update command (alias: up) inspects installed packages against their remote origin. For Git-backed packages, DPM queries remote tags (git ls-remote --tags), compares available versions using its SemVer engine, and upgrades the package when a newer compatible version is detected.

bash
# Update a specific package locally
dpm update sqlite

# Update all installed packages in the current project
dpm update *
# or
dpm update

# Update a globally installed package
dpm update -g qalam

# Force re-installation of the latest version
dpm update sqlite --force

4. Package Uninstallation: dpm remove

The remove command (aliases: rm, uninstall) safely deletes a package from djazair_packages/ and automatically removes its dependency constraint from dpm.json:

bash
# Remove package locally and update dpm.json
dpm remove sqlite

# Remove a globally installed package
dpm remove -g qalam

5. Inventory Inspection: dpm list

The list command (alias: ls) scans the packages directory and outputs a cleanly formatted table of all installed packages, their detected versions, and package types:

bash
# List project-local packages
dpm list

# List globally installed packages
dpm list -g

6. Deep Metadata Inspection: dpm info

The info command (alias: show) prints an exhaustive diagnostic report for any package, including its scope, installation location, entrypoint, author, dependency map, update availability, and file inventory:

bash
dpm info sqlite
text
Package Information: sqlite
----------------------------------------------------
  Name:        sqlite
  Scope:       Local
  Location:    D:\Projects\app\djazair_packages\sqlite
  Version:     1.0.0
  Type:        hybrid
  Description: SQLite native embedded database engine for Djazair
  Source:      github:djazair-language/djazair-extensions/sqlite
  Entrypoint:  init.dz
  Developer:   Harizi Riyadh <hariziriyadh@gmail.com>
  Dependencies: None
  Files (6):   dpm.json, init.dz, build.bat, build.sh, sqlite3.c, sqlite3.h

7. Distributable Bundling: dpm pack

Packages the current project or library into a clean, distributable ZIP archive named <name>-<version>.zip. It automatically excludes local dependencies (djazair_packages/), compiled binaries, and temporary files, producing a production-ready distribution artifact ready to be published or shared.

bash
dpm pack
# Output: Package archive created: 'D:\Projects\my_lib\my_lib-1.0.0.zip'
---

Package Manifest (dpm.json) Specification

The dpm.json file is the single source of truth for any Djazair project or distributable library. Below is the complete annotated specification:

json
{
  "name": "super_cache",
  "version": "1.2.0",
  "description": "High-performance LRU cache and memory storage for Djazair",
  "type": "pure",
  "entry": "init.dz",
  "source": "github:developer/super_cache",
  "developer": {
    "name": "Harizi Riyadh",
    "email": "hariziriyadh@gmail.com"
  },
  "require": {
    "qalam": "^0.2.0",
    "sqlite": "~1.0.0"
  },
  "build": {
    "windows": "build.bat",
    "linux": "./build.sh"
  }
}
Field Type Required Description
name String Yes The unique identifier of the package. Must use lowercase alphanumeric characters, dashes, or underscores (e.g. "json_validator").
version String Yes Valid SemVer 2.0.0 string (MAJOR.MINOR.PATCH[-PRERELEASE]).
description String No Concise overview of the package's purpose and functionality.
type String Yes Either "pure" (Djazair code only) or "hybrid" (contains native C/C++ build steps).
entry String No Main entrypoint file executed when the package is imported. Defaults to "init.dz".
source String No Upstream repository specifier (e.g. "github:org/repo" or Git URL) used for automated updates.
developer Object No Metadata map containing author "name" and "email".
require Object No Dictionary of package dependencies mapped to SemVer constraints (e.g., {"qalam": "^0.2.0"}).
build Object No (Hybrid only) Cross-platform build scripts for hybrid packages (e.g., "windows": "build.bat", "linux": "./build.sh").
---

Professional Tutorial: Creating & Publishing a Package

Follow this end-to-end walkthrough to create, structure, test, bundle, and distribute a professional Djazair package.

Step 1: Scaffolding the Package

Create a dedicated directory for your library and initialize it with DPM:

bash
mkdir string_utils
cd string_utils
dpm init

Fill in the interactive prompts:

text
Package name (string_utils): string_utils
Version (0.1.0): 1.0.0
Description: Advanced string transformation algorithms for Djazair
Type (pure/hybrid) [pure]: pure
Author Name: Harizi Riyadh
Author Email: hariziriyadh@gmail.com

Step 2: Designing the Package Architecture

A professional package organizes its internal logic under a src/ directory and exports a clean public API through init.dz:

bash
string_utils/
├── dpm.json
├── init.dz
├── src/
│   ├── case.dz
│   └── slugify.dz
├── tests/
│   └── test_string_utils.dz
└── README.md

Write your internal modules inside src/:

ruby
# src/slugify.dz
fn toSlug(text)
    let clean = text.lower().strip()
    let result = ""
    for ch in clean
        if (ch >= "a" and ch <= "z") or (ch >= "0" and ch <= "9")
            result = result + ch
        elif ch == " " or ch == "_" or ch == "-"
            if !result.endsWith("-") and result.length() > 0
                result = result + "-"
            end
        end
    end
    return result
end

Expose your public functions in the package entrypoint (init.dz):

ruby
# init.dz — Public API Gateway
import "src/slugify.dz" as slug

# Re-export clean functions
fn slugify(text)
    return slug.toSlug(text)
end

fn version()
    return "1.0.0"
end

Step 3: Managing Dependencies

If your package requires helper libraries (e.g. qalam for colored output or logging), install them directly:

bash
dpm install qalam

DPM installs qalam into djazair_packages/qalam and automatically records "qalam": "^0.2.0" in your dpm.json.

Step 4: Writing Unit Tests

Create a test runner under tests/test_string_utils.dz utilizing the standard assert library:

ruby
# tests/test_string_utils.dz
use assert
import "../init.dz" as string_utils

print("==> Testing string_utils...")

assert.equal(string_utils.slugify("Hello World! 2026"), "hello-world-2026", "Slugification failed")
assert.equal(string_utils.slugify("Djazair   Programming"), "djazair-programming", "Multiple spaces failed")

print("==> All tests passed successfully!")

Execute your tests:

bash
djazair tests/test_string_utils.dz

Step 5: Packaging & Publishing

When ready for release, bundle your package using dpm pack:

bash
dpm pack
# Produces: string_utils-1.0.0.zip

To publish via Git, push your code to GitHub with a SemVer release tag:

bash
git init
git add .
git commit -m "Release v1.0.0"
git tag v1.0.0
git remote add origin https://github.com/myusername/string_utils.git
git push -u origin main --tags

Step 6: Consuming the Published Package

Other developers can now install and consume your package directly:

bash
# Install via GitHub shorthand
dpm install github:myusername/string_utils

# Or install from direct ZIP release
dpm install https://github.com/myusername/string_utils/releases/download/v1.0.0/string_utils-1.0.0.zip

In consumer code:

ruby
use string_utils

let slug = string_utils.slugify("Building with Djazair and DPM")
print("Generated Slug: " + slug)
# Output: Generated Slug: building-with-djazair-and-dpm
---

Authoring Hybrid Packages (C/C++ Extensions)

Hybrid packages bridge high-performance C or C++ shared libraries into the Djazair runtime. DPM automates native builds by orchestrating cross-platform build scripts.

Hybrid Package Layout

bash
fast_hash/
├── dpm.json         # Declares "type": "hybrid" and "build" scripts
├── init.dz          # Djazair bindings loading the native library
├── build.bat        # Windows compilation script (MinGW / MSVC)
├── build.sh         # Linux & macOS compilation script (GCC / Clang)
└── src/
    ├── native.c     # C implementation using Djazair C API
    └── native.h

Hybrid dpm.json

json
{
  "name": "fast_hash",
  "version": "1.0.0",
  "description": "Native high-speed hashing module for Djazair",
  "type": "hybrid",
  "entry": "init.dz",
  "build": {
    "windows": "build.bat",
    "linux": "./build.sh"
  }
}

Standard Build Scripts

DPM sets the DJAZAIR_ROOT environment variable before executing your build scripts. Your scripts should reference the Djazair header files in $DJAZAIR_ROOT/src/include and link against libdjazair:

bash
@echo off
setlocal

:: Set include and library directories
if "%DJAZAIR_ROOT%"=="" set DJAZAIR_ROOT=..\..

gcc -O3 -shared -fPIC ^
    -I"%DJAZAIR_ROOT%\src\include" ^
    -o fast_hash.dll ^
    src\native.c ^
    -L"%DJAZAIR_ROOT%\build\lib" -ldjazair

if %ERRORLEVEL% equ 0 (
    echo [OK] fast_hash.dll compiled successfully.
    exit /b 0
) else (
    echo [ERROR] Compilation failed.
    exit /b 1
)
bash
#!/usr/bin/env bash
set -e

: "${DJAZAIR_ROOT:=../..}"

gcc -O3 -shared -fPIC \
    -I"${DJAZAIR_ROOT}/src/include" \
    -o fast_hash.so \
    src/native.c \
    -L"${DJAZAIR_ROOT}/build/lib" -ldjazair

echo "[OK] fast_hash.so compiled successfully."
---

Programmatic Package Inspection via lang

Djazair's standard library lang module provides native functions to inspect packages and query update states directly from your running scripts:

Function Return Type Description
lang.packagesDir() String Returns the absolute path to the active global packages directory.
lang.packageExist(name, [isGlobal]) Boolean Checks if a package exists locally or globally. Alias: lang.packageExists().
lang.checkPackageUpdate(name, [isGlobal]) Map Returns a dictionary with isInstalled, hasUpdate, currentVersion, latestVersion, path, and scope.
lang.hasUpdate(name, [isGlobal]) Boolean Convenience predicate checking if a newer version is available upstream.

Real-World Dynamic Inspection Example

ruby
use lang

# Check if SQLite package is available
if lang.packageExist("sqlite")
    let info = lang.checkPackageUpdate("sqlite")
    print("SQLite Version: " + info["currentVersion"])
    print("Installed Path: " + info["path"])

    if info["hasUpdate"]
        print("Notice: A newer SQLite release (v" + info["latestVersion"] + ") is available!")
        print("Run 'dpm update sqlite' to upgrade.")
    end
else
    print("SQLite is not installed. Please run: dpm install sqlite")
end
---

Production & CI/CD Best Practices

1. Git Repository Hygiene

  • Always commit dpm.json: The manifest defines exact version bounds and is critical for team collaboration.
  • Never commit djazair_packages/: Always ignore dependencies in .gitignore. Team members and CI servers will reconstitute them deterministically using dpm install.
  • Never commit binary artifacts: Ensure *.dll, *.so, *.dylib, and .dpm_cache/ are gitignored.

2. Continuous Integration (CI/CD) Configuration

In automated GitHub Actions or GitLab CI environments, incorporate DPM dependency synchronization into your build matrix:

yaml
# .github/workflows/ci.yml
name: Test Suite

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Source
        uses: actions/checkout@v4

      - name: Setup Djazair & DPM
        run: |
          sudo apt-get update && sudo apt-get install -y gcc make
          # Build or install Djazair binaries
          make install

      - name: Install Project Dependencies
        run: dpm install

      - name: Run Test Suite
        run: djazair tests/run_all.dz

3. Troubleshooting Common Issues

  • Git is not recognized: DPM relies on the system git command to fetch repositories. Ensure Git is installed and added to your system PATH.
  • Compiler toolchain missing for hybrid packages: On Windows, ensure MinGW GCC (e.g. MSYS2 or WinLibs) is in your PATH. On Linux, install build-essential (GCC/Clang and Make).
  • Cleaning Cache: DPM caches monorepos and downloaded archives in your OS temporary directory under dpm_cache/. To clear stale caches, delete the directory:
    bash
    # Windows PowerShell
    Remove-Item -Recurse -Force "$env:TEMP\dpm_cache"
    
    # Linux / macOS
    rm -rf /tmp/dpm_cache