Home Doh Ref
Guides โ–ผ
Dohballs โ–ผ
  • ๐Ÿ“ doh_modules
    • ๐Ÿ“ฆ dataforge
    • ๐Ÿ“ฆ express
    • ๐Ÿ“ sso
    • ๐Ÿ“ user

Auto-Packager: Automated Dependencies

Auto-Packager

The Auto-Packager is the intelligent backbone of the Doh framework's load system. It automatically analyzes your codebase to:

  • Discover and register modules, packages, and patterns
  • Manage dependencies between components
  • Generate essential manifests for the framework
  • Create distributable packages (Dohballs)
  • Handle ESM imports for Node.js and browser environments
  • Optimize performance through caching and parallel processing

With minimal configuration, the Auto-Packager ensures your Doh application's components are properly linked, versioned, cached, and ready for distribution.

Note: For a higher-level view of how the Auto-Packager interacts with DohPath, Manifests, and the runtime Load System, see the Doh.js Core Architecture Overview.

Key Concepts

Packages

Packages are the fundamental units of code organization in Doh. They have:

  • A unique name identifier
  • A set of load instructions (dependencies)
  • Optional installation requirements
  • Associated metadata

Packages can be defined in JavaScript files using Doh.Package() or in YAML files with .doh.yaml extension. Doh.Package() is a compile-time declaration the Auto-Packager scans from .js files to collect JSON-like metadata (name, load, install, pod, cli). It does not reference modules or attach callbacks.

Modules

Modules are executable units of code in Doh, defined using Doh.Module(). A module is a package with a callback, created atomically under the same name in Doh.Packages. Do not pair a separate Doh.Package(name, ...) with a later Doh.Module(name, ...) for the same name; overlapping declarations are treated as conflicts by the scanner. A module typically:

  • Has a unique name
  • Contains a set of patterns
  • A set of load instructions (dependencies)
  • Has a callback function that executes when loaded

Patterns

Patterns define reusable components within modules. They support inheritance and can be used to build complex UI and business logic components.

Dohballs

Dohballs are versioned, self-contained distribution units that package related Doh components together. They:

  • Are an entirely optional alternate/sibling to npm private repos and git sub-modules (Doh Package/Module DO NOT REQUIRE DOHBALLS)
  • Can be generated by the Auto-Packager
  • Use content-based versioning (via dohball.json within the source folder) to ensure consistency and trigger rebuilds
  • Can be hosted and shared between Doh applications
  • Can be baked in parallel for faster builds
  • Can be used and distributed via Git (traditional) OR HTTP/S hosting (direct) using the dohball_host module

Environment Branching Handling

The Auto-Packager intelligently processes environment-specific code defined through conditional decorators in load statements. Here's how it works:

1. Conditional Load Statement Processing

When the Auto-Packager encounters conditional load statements (e.g., browser?? feature_ui or nodejs?? server_feature), it:

  1. Parses and extracts the condition and the actual dependency
  2. Records both in the dependency graph, marking the dependency as conditional
  3. Includes the dependency in appropriate manifests, maintaining the condition
  4. Ensures that even conditional dependencies are properly resolved and tracked

Example:

// Auto-Packager processes this structure while preserving conditions
Doh.Package('feature', {
  load: [
    'core',                    // Always loaded
    'browser?? ui_components', // Browser-only
    'nodejs?? server_api'      // Node.js-only
  ]
});

2. Environment-Specific Dependency Graphs

The Auto-Packager builds separate dependency sub-graphs for different environments:

  1. It identifies environment-specific branches in the dependency tree
  2. Validates that environment-specific dependencies don't create cross-environment conflicts
  3. Ensures that conditional dependencies only affect their intended environments

3. Bifurcated Module Pattern Support

The Auto-Packager is optimized to handle the common bifurcated module pattern:

// Main package with environment branching
Doh.Package('feature_name', {
  load: [
    'feature_name_common',         // Common functionality
    'browser?? feature_name_ui',    // Browser-specific implementation
    'nodejs?? feature_name_server'  // Node.js-specific implementation
  ]
});

The Auto-Packager ensures that:

  • The common module is properly loaded in all environments
  • Browser-specific modules are only included in browser bundles
  • Server-specific modules are only included in Node.js bundles
  • Dependency ordering is maintained correctly across environments

Using the Auto-Packager

Automatic Operation

The Auto-Packager runs automatically when Doh boots, unless run with no-pack (doh run no-pack). It:

  1. Scans your project directories
  2. Processes JavaScript and YAML files
  3. Extracts Doh-specific declarations
  4. Generates necessary manifests

Manual Triggering

You can manually trigger the Auto-Packager using the Doh CLI:

# Run the auto-packager to update manifests
doh update

# Upgrade all Dohballs from configured hosts
doh upgrade

# Bake specific or all locally hosted Dohballs
# Use no argument to bake all eligible packages
# Specify package names to bake only those
doh bake [package_name...]

# Force rebake specific or all locally hosted Dohballs
doh rebake [package_name...]

Configuration

The Auto-Packager's behavior is controlled through the pod.yaml file:

# Update behavior controls
always_reinstall_dohballs: false
always_upgrade_dohballs: false
always_restore_dohballs: false
always_update_npm_dependencies: false

# Dohball generation configuration
dohball_deployment:
  expose_packages: '*'     # Glob pattern or list of packages to expose as Dohballs ('*' for all eligible)
  expose_doh_js: false     # Whether to include doh_js in Dohballs (rarely needed)
  ignore_packages:         # List of packages to never expose as Dohballs
    - private_package
  ignore_paths:            # List of directory paths (relative to root) to never include in Dohballs
    - secret_folder
    - build_output
  rebake: false            # Force rebake on every run (useful for debugging)
  compile_manifest: true   # Generate a dohball_manifest.json for hosting baked dohballs
  worker_pool_size: 4      # Number of parallel workers for baking Dohballs

# ESM Import handling via esm.sh
esm_sh_external: []       # List of packages to exclude from esm.sh auto-bundling (e.g., ['react', 'react-dom'])
always_esbuild: false     # Whether to always run the esbuild processor after packaging

# Dohball hosts for fetching remote packages
dohball_host:
  - https://main.dohball.host
  - https://backup.dohball.host

# Packages to load when the host is booted (auto run)
host_load:
  - core_module
  - ui_module

# Files/folders to ignore during scanning
packager_ignore:
  directories:
    # DEFAULTS:
    - node_modules
    - .git
    - .doh # Auto-ignored, but good practice to list
    - dohballs # Auto-ignored
    - dist # Often contains build artifacts not part of source

File Processing

JavaScript Files

The Auto-Packager parses JavaScript files looking for Doh-specific declarations:

// Module definition
Doh.Module('myModule', ['dep1', 'dep2'], function(Pattern) {
  // Module implementation

  // Pattern definition
  Pattern('MyPattern', ['InheritsFrom'], {
    // Pattern implementation
  });
});

// Package definition (repacking an npm module as a Doh module of the same name)
// Note: explicit install is NOT required for imports.
// All imports are auto-installed at 'latest' unless pinned.
// Pin by adding @version to the import specifier: "dep2@^2".
Doh.Package('dep2', {
  load: ['dep1', 'global import * as dp2 from "dep2"'],
});


// CLI command registration
Doh.CLI('myModule', {
  'command-name': {
    file: 'path/to/script.js', // dynamically imported when command is called
    help: 'help displayed in `doh help` for this command'
  }
});

// Optional: Manual installation instructions (advanced)
// Prefer pinning versions in import specifiers or rely on auto-install at 'latest'.
// Doh.Install remains for edge cases or non-imported assets.
Doh.Install('myModule', {
  'npm:axios': '^1.6.0'
});

// Pod configuration
Doh.Pod('myModule', {
  // Pod configuration outer scope
  // add keys for your module as needed
  myModule: {
    // your settings
  }
});

YAML Files

The Auto-Packager also processes .doh.yaml files for simpler package definitions:

# Simple definition with just a load dependency
simple_package: dependency_package

# Complex definition with multiple options
complex_package:
  load: 
    - import YAML from "yaml"
    - import Axios from "axios"
  install:
    'npm:yaml': '' # empty value for latest
    'npm:axios': ''

Parameter resolution (SPR) and module communication

The Autoโ€‘Packager catalogs callback parameters (including destructured forms) to enable Scoped Parameter Resolution (SPR) at runtime (see Modules โ†’ SPR). Mental model: load arrays build scope; callback params consume scope. Modules are both producers (load arrays) and consumers (callbacks); Packages are producers only.

  1. For each Doh.Module() declaration, it extracts the callbackโ€™s parameter list (simple identifiers and destructured identifiers).
  2. These parameter specs are recorded in the module's metadata and manifests.
  3. At runtime, each parameter is resolved by name via the rule of four: current moduleโ€™s producers โ†’ ancestor modules exports then producers (Resolution Order) โ†’ Doh.Globals[name] (shared state) โ†’ globalThis[name]. If still not found, resolution yields undefined (with a diagnostic). Legacy compatibility: enabling Doh.pod.ignore_missing_module_params (discouraged) will autoโ€‘create a placeholder {} in Doh.Globals[name]. Prefer explicit construction via parameter defaults (e.g., param = {} or param = { globalThis: {} }).
  4. For object destructuring (e.g., { format, parse }), each requested property name is resolved independently through the same cascade and then re-packed into the single object argument. The runtime also supports object-literal defaults to repack a single object by resolving each keyโ€™s lookup name.
  5. String default values act as aliases: a parameter like param = 'aliasName' resolves param using 'aliasName' as the lookup name.
  6. Empty-object defaults ensure container creation in Doh.Globals: function(Store = {}) {} guarantees Doh.Globals.Store exists and injects it.
  7. { globalThis: {} } defaults ensure container creation in globalThis: function(Registry = { globalThis: {} }) {} guarantees globalThis.Registry exists and injects it.
  8. Special mappings: $ is treated as jQuery during resolution; DohPath is injected as an Overloaded instance bound to the module file (not globalized).

Think of the load block as the scope builder and the parameter list as the scope consumer. This system allows modules to communicate without explicit import/export statements while preserving specificity across dependency layers:

// The Auto-Packager sees both modules use 'SharedData' parameter
// and ensures they receive the same object instance via Doh.Globals

Doh.Module('ModuleA', function(SharedData = {}) {
  SharedData.counter = 0;
  SharedData.increment = function() {
    SharedData.counter++;
  };
});

Doh.Module('ModuleB', ['ModuleA'], function(SharedData) {
  SharedData.increment();
  console.log(SharedData.counter); // 1
});

// Reuse ESM exports from an ancestor
Doh.Module('UsingESM_common', [
  'import { format, parse } from "date-fns"'
], function(format, parse) { /* both resolved by name */ });

Doh.Module('consumer', [
  'UsingESM_common'
], function(format) { /* resolved by name from ancestor producer list */ });

// Destructured repack variant
Doh.Module('Formats', [
  'import path from "path"',
  'import { format, parse } from "date-fns"'
], function(utils = { format, parse, path }) {
  // utils.format and utils.parse and utils.path are the references here
});

Dependency Management

The Auto-Packager builds and validates the dependency graph of your application:

  • Expands dependency trees to include transitive dependencies
  • Detects and reports cyclic dependencies
  • Resolves conflicts between multiple versions
  • Manages both local and remote dependencies

When a cyclic dependency is detected, the Auto-Packager will report it and fail, preventing potentially problematic code from running.

Environment-Specific Dependencies

The Auto-Packager handles environment-specific dependencies by:

  1. Parsing conditional decorators in load statements (e.g., browser??, nodejs??)
  2. Building separate dependency graphs for different environments
  3. Ensuring that environment-specific code is only included in the appropriate bundles
  4. Validating that environment-specific dependencies don't create conflicts across environments

Example:

// The Auto-Packager will ensure ui-lib is only included in browser bundles
// and fs-extra is only included in Node.js bundles
Doh.Module('FeatureModule', [
  'common-lib',                          // Included in all environments
  'browser?? ui-lib',                    // Only included in browser bundles
  'nodejs?? server-utilities',       // Only included in Node.js bundles
  'Doh.pod.debug?? debug-tools'       // Only included if Doh.pod.debug is true
], function() {
  // Module implementation
});

Manifest Generation

The Auto-Packager generates several important manifest files in two primary locations:

Private Manifests (/.doh/manifests/)

These manifests contain internal build information, caches, and potentially sensitive configuration. They are generally not distributed and are excluded from being served by all Doh systems by default.

  • CLI Manifest (cli_manifest.json): Maps registered CLI commands to their implementation files.
  • Pod Manifest (pod_manifest.json): Aggregated Pod configurations from Doh.Pod() declarations.
  • Node ESM Manifest (node_esm_manifest.json): Import map for Node.js environments, mapping package names to their local paths in node_modules. (CURRENTLY UNUSED)
  • AP Cache (ap_cache.json): Auto-Packager file cache. Stores file metadata (mtime, hash), parsed Doh definitions, and import information to speed up subsequent runs.
  • Autopackager Problems (autopackager_problems.json): Logs errors encountered during packaging.
  • Pattern Duplicates (pattern_duplicates.json): Lists patterns defined in multiple files.
  • Deprecated Features (deprecated_features.json): Logs usage of deprecated Doh features.
  • Compiled Dohball Manifest (compiled_dohball_manifest.json): Internal cache of manifests fetched from remote Dohball hosts.

Public Manifests (/doh_js/manifests/)

These manifests describe the public structure and dependencies of your application and are often used by the framework at runtime.

  • Package Manifest (package_manifest.json): The central manifest defining all discovered packages, their dependencies (load), files, and associated metadata.
  • Pattern Manifest (patterns_manifest.json): Maps pattern names to the module they belong to.
  • Core Patterns Manifest (core_patterns_manifest.json): A list of core Doh patterns provided by the framework itself.
  • Assets Manifest (assets_manifest.json): Maps modules to the static assets (DohPath.DohSlash() calls) they reference.
  • Browser ESM Manifest (browser_esm_manifest.json): Import map for browser environments, mapping package names to CDN URLs (typically esm.sh).
  • Dohball Manifest (dohball_manifest.json): If compile_manifest is true, this lists the locally baked Dohballs available for hosting, including version and update time. Used by remote Doh instances to discover available Dohballs on this host.
  • Module Dependency Graph (module_dep_graph.json): Represents the dependency relationships between packages/modules.

Dohball Tracking Manifest (/dohballs/dohballs.json)

  • Orphaned Dohballs (dohballs.json): Located in the root of the Dohball hosting directory (/dohballs/). Tracks Dohball archives (.tar.gz files) that exist in the hosting directory but no longer correspond to an actively exposed package according to the current pod.yaml configuration. This helps identify and manage potentially obsolete Dohballs.

ESM Import Management

The Auto-Packager automatically manages ESM imports for NPM packages used in your Doh code:

  1. Scans JavaScript files for import statements and Doh.load() calls referencing external packages.
  2. Resolves the package path and version using node_modules.
  3. For Node.js: Generates entries in node_esm_manifest.json mapping the package name to its local path.
  4. For Browsers: Generates browser-compatible URLs using available node_modules, otherwise esm.sh (e.g., https://esm.sh/react@18) and adds them to browser_esm_manifest.json. Packages listed in pod.yaml under esm_sh_external are excluded from esm.sh bundling.
  5. These manifests are used to create import maps, allowing the same import syntax (e.g., import React from 'react') to work seamlessly in both environments.

Auto-Installer: NPM Dependency Management

The Auto-Packager includes an intelligent Auto-Installer that automatically manages npm dependencies based on import statements in declarative load blocks (Doh.Module() and Doh.Package()). This eliminates the need for manual Doh.Install() declarations in most cases. Important: The Auto-Installer does NOT work with dynamic Doh.load() calls.

How the Auto-Installer Works

  1. Import Detection: Scans declarative load blocks in Doh.Module() and Doh.Package() declarations for import statements (NOT Doh.load() calls)
  2. Package Resolution: Identifies npm packages referenced in declarative import statements
  3. Version Analysis: Parses version specifiers from declarative import statements (e.g., react@^18.0.0)
  4. Installation: Automatically installs missing packages when doh upgrade is run (which first runs doh update to get current manifest info)
  5. Manifest Updates: Updates dependency manifests and runs doh update again after installations to refresh manifests

Import Statement Patterns

The Auto-Installer recognizes these import patterns in load blocks:

Doh.Module('my_module', [
  // Named imports with version pinning
  'import { useState, useEffect } from "react@^18.0.0"',

  // Default imports
  'import React from "react"',

  // Namespace imports
  'import * as utils from "date-fns@2.30.0"',

  // Side-effect only imports
  'import "normalize.css"',
], function(useState, useEffect, React, utils) {
  // Dependencies are automatically installed
});

Version Pinning

The Auto-Installer supports full semver version specifications:

  • import React from "react" - Installs latest version
  • import React from "react@^18.0.0" - Installs compatible with 18.0.0
  • import React from "react@~18.2.0" - Installs compatible within 18.2.x
  • import React from "react@18.2.0" - Installs exact version 18.2.0

Migration from Doh.Install()

The Auto-Installer makes most Doh.Install() statements obsolete:

// OLD WAY (deprecated but still works)
Doh.Install('my_module', {
  'npm:react': '^18.0.0',
  'npm:axios': '',
  'npm:date-fns': '~2.30.0'
});

// NEW WAY (recommended)
Doh.Module('my_module', [
  'import React from "react@^18.0.0"',
  'import axios from "axios"',
  'import * as dateFns from "date-fns@~2.30.0"'
], function(React, axios, datefns) {
  // Dependencies auto-installed by doh upgrade
});

Triggering the Auto-Installer

The Auto-Installer is triggered by the doh upgrade command:

# Scan for missing npm dependencies and install them
doh upgrade

# Or upgrade specific packages and install any missing npm deps
doh upgrade my_specific_package

Note: doh update only scans and reports - it does NOT install dependencies. doh upgrade provides complete dependency management by running doh update before and after installations to ensure manifests are always current.

Environment Branching Support

The Auto-Packager has special handling for environment-specific code:

1. Conditional Load Statements

Load statements with environment conditions (browser??, nodejs??, etc.) are processed to ensure they only apply in the appropriate environments:

// Auto-Packager processes these conditionals correctly
Doh.Module('CrossPlatformFeature', [
  'core-dependency',                // Always included
  'browser?? dom-utilities',         // Only included in browser bundles
  'nodejs?? server-utilities',       // Only included in Node.js bundles
  'Doh.pod.debug?? debug-tools'       // Only included if Doh.pod.debug is true
], function() {
  // Module implementation
});

2. Bifurcated Module Pattern

The Auto-Packager recognizes and optimizes for the common bifurcated module pattern:

// Main package with environment-specific branch loading
Doh.Package('feature_name', {
  load: [
    'feature_name_common',
    'browser?? feature_name_ui',
    'nodejs?? feature_name_server'
  ]
});

// Common shared functionality
Doh.Module('feature_name_common', [], function() {
  // Common implementation
});

// Browser UI implementation
Doh.Module('feature_name_ui', ['feature_name_common'], function() {
  // Browser-specific implementation
});

// Server API implementation
Doh.Module('feature_name_server', ['feature_name_common'], function() {
  // Server-specific implementation
});

The Auto-Packager ensures that:

  • Dependencies are correctly tracked across environment branches
  • Common code is properly shared between environments
  • Environment-specific code is only included when needed
  • The dependency graph remains acyclic across all environments

Dohball Creation

Dohballs are created ("baked") based on the dohball_deployment configuration in pod.yaml:

  1. Packages eligible for exposure are identified based on expose_packages, ignore_packages, and ignore_paths.
  2. If specific package names are provided via doh bake [names...] or doh rebake [names...], the list is filtered.
  3. Packages are grouped by their shared parent directory path (e.g., all packages under /modules/user/ might be baked into /dohballs/modules/user.tar.gz).
  4. The Auto-Packager checks for a dohball.json file within the source directory (e.g., /modules/user/dohball.json). The version field in this file determines the Dohball version.
  5. The packer compares the current source content hash against the hash stored in the cache (ap_cache.json) for the last bake. A Dohball is only baked if the content has changed or if rebake is forced (doh rebake or pod.yaml).
  6. The baking process (creating the .tar.gz archive) is parallelized using a worker pool (size configured by worker_pool_size).
  7. The resulting archive is placed in the /dohballs/ directory, mirroring the source structure (e.g., /modules/user/ becomes /dohballs/modules/user.tar.gz).
  8. If compile_manifest is true, /doh_js/manifests/dohball_manifest.json is updated with information about the baked Dohball (version, updated time).
  9. The /dohballs/dohballs.json manifest is updated to track any orphaned Dohballs (existing archives not matching current exposed packages).

Local vs Remote Dohball Handling

The Auto-Packager handles Dohballs differently depending on whether they are local or remote:

Local Dohballs (No Installation Required)

  • Automatic processing: Local code in your project is automatically discovered and made available by the Auto-Packager
  • No installation step: You simply put code in your project structure and it's immediately runnable
  • Real-time updates: Changes to local code are reflected immediately without any commands
  • Seamless workflow: The Auto-Packager runs automatically when Doh boots, making local development frictionless

Remote Dohballs (Require Installation)

Dohballs support two complementary distribution approaches for sharing code between different Doh instances:

1. Git-Based Distribution (Traditional)

  • Traditional method: Baked .tar.gz files are committed to Git repositories
  • Transport mechanism: Git handles distribution of baked artifacts between repositories
  • Installation required: Use doh install package_name to pull from remote hosts
  • Version tracking: Both source and baked artifacts are tracked in Git history
  • Best for: Teams already using Git workflows, historical tracking of all artifacts

2. HTTP-Based Distribution (Direct Hosting)

  • Modern method: Baked .tar.gz files are served directly via HTTP/HTTPS using the dohball_host module
  • Real-time delivery: Consumers install directly from running Doh hosts via doh install or doh upgrade
  • Installation required: Explicit installation step needed to pull from remote hosts
  • No Git required: Eliminates need for Git operations in the distribution chain
  • Best for: CI/CD pipelines, real-time updates, simplified workflows

Configuration for HTTP Hosting:

# In hosting instance pod.yaml
dohball_deployment:
  compile_manifest: true
host_load:
  - dohball_host

# In consuming instance pod.yaml
dohball_host:
  - https://your-host.com
  - http://localhost:3001

Performance Optimization

The Auto-Packager employs several techniques to ensure speed:

Caching

Utilizes /.doh/manifests/ap_cache.json to store file modification times, content hashes, and parsed Doh definitions (modules, packages, patterns, imports). On subsequent runs, only files that have changed since the last run are re-parsed, significantly speeding up the process.

Parallel Processing

Dohball creation (bake and rebake) uses a configurable worker pool (worker_pool_size in pod.yaml) to perform the CPU-intensive tasks of hashing, compressing, and archiving files in parallel.

Selective Scanning

The Auto-Packager can be configured to ignore specific directories to reduce unnecessary file processing.

Integration with Other Doh Systems

Pod System

The Auto-Packager integrates with the Pod system by:

  • Reading configuration from pod.yaml
  • Generating pod manifests
  • Processing Doh.Pod() declarations

Module System

Integration with the Module system includes:

  • Processing Doh.Module() definitions
  • Resolving module dependencies
  • Generating module-related manifests

Load System

The Auto-Packager uses the Load System for:

  • Parsing load statements and decorators
  • Handling conditional loading (browser??, nodejs??, etc.)
  • Resolving relative and absolute paths
  • Managing ES module imports

Pattern System

The Auto-Packager interacts with the Pattern system by:

  • Extracting pattern definitions
  • Generating pattern manifests
  • Tracking pattern inheritance

Real-World Examples

1. Cross-Platform Feature with Shared Code

// Define a cross-platform feature with environment branching
Doh.Package('user_management', {
  load: [
    // Common functionality
    'user_management_common',
    // Environment-specific implementations
    'browser?? user_management_ui',
    'nodejs?? user_management_server'
  ]
});

// The Auto-Packager:
// 1. Detects the environment branching pattern
// 2. Tracks dependencies for each branch
// 3. Includes common code in all environments
// 4. Bundles UI code only for browsers
// 5. Bundles server code only for Node.js

2. Configuration-Based Loading

// Define a module with configuration-based features
Doh.Module('admin_panel', [
  // Base functionality
  'admin_core',
  
  // Conditional features based on configuration
  'Doh.pod.features.analytics?? admin_analytics',
  'Doh.pod.features.permissions?? admin_permissions',
  
  // Environment-specific and config-specific
  'browser&&Doh.pod.features.dashboard?? admin_dashboard'
], function() {
  // Module implementation
});

// The Auto-Packager:
// 1. Parses the complex conditions
// 2. Tracks configuration-dependent features
// 3. Handles combined environment and config conditions

Debug Information

The Auto-Packager generates several diagnostic files within /.doh/manifests/:

  • autopackager_problems.json: Logs errors or inconsistencies found during scanning and packaging.
  • pattern_duplicates.json: Lists any patterns defined with the same name in multiple files.
  • deprecated_features.json: Records usage of deprecated Doh functions or parameters.
  • dohballs.json (in /dohballs/): Tracks orphaned Dohball archives.

Troubleshooting Common Issues

1. Cyclic Dependencies

If the Auto-Packager detects cyclic dependencies, it will report an error. To fix:

  1. Identify the cycle in the dependency graph
  2. Refactor one of the modules to break the cycle:
    • Move shared functionality to a common dependency
    • Use events or callbacks instead of direct dependencies
    • Use dynamic loading with Doh.load() instead of static dependencies

2. Missing Modules

If a module is referenced but not found:

  1. Check the module name and path
  2. Ensure the module is properly defined with Doh.Module()
  3. Check for typos in load statements
  4. Run doh update to refresh manifests

3. Environment-Specific Issues

If environment-specific code is not working correctly:

  1. Verify conditional decorators (browser??, nodejs??) are properly applied
  2. Check that environment detection is working (IsBrowser(), IsNode())
  3. Ensure common modules are loaded before environment-specific ones
  4. Verify the dependency order in bifurcated module patterns

Best Practices

  1. Organize Related Components

    • Keep related packages, modules, and patterns in the same directory
    • This optimizes Dohball generation and improves load performance
  2. Use Environment Branching Consistently

    • Follow the bifurcated pattern (common + environment-specific modules)
    • Keep environment-specific code clearly separated with conditional decorators
  3. Avoid Cyclic Dependencies

    • Design your module hierarchy to avoid circular dependencies
    • Use events or interfaces to break cycles when needed
  4. Leverage Parameter Sharing

    • Use consistent parameter names for modules that need to share state
    • Document shared parameters and their expected structure
  5. Regular Updates

    • Run doh update when adding new components
    • This ensures all manifests stay in sync with your code
  6. Manifest Awareness

    • Understand the manifests that describe your application
    • Use them for debugging and comprehending your application structure
  7. Maintain Clean Dependencies

    • Periodically review your dependencies
    • Remove unused packages to keep your application lean

Command-Line Reference

# Run the auto-packager to scan and generate manifests (no remote installation)
doh update

# Complete dependency management - runs update โ†’ installs โ†’ update again
doh upgrade

# Bake Dohballs whose content has changed since the last bake.
# Can optionally specify package names to only check those.
doh bake [package_name...]

# Force rebaking of Dohballs, regardless of content changes.
# Can optionally specify package names to only rebake those.
doh rebake [package_name...]

API Reference

Core Functions

  • Doh.Module(name, dependencies, callback): Define a module
  • Doh.Package(name, config): Define a package
  • Pattern(name, inherits, idea): Define a pattern in a Doh module
  • Doh.Install(name, assets, callback): Define installation requirements
  • Doh.CLI(package, commands): Register CLI commands
  • Doh.Pod(package, config): Register pod configuration

Advanced Features

  • Load decorators: See Load System for advanced import syntax (global, direct, etc.)
  • Path Substitution: Use ^/ in paths within load arrays for references relative to the file's location (see DohPath)
Last updated: 8/23/2025