Home Doh Ref
Dohballs
  • 📁 doh_modules
    • 📦 dataforge
    • 📦 express
    • 📁 sso
    • 📁 user

Auto-Packager: Build-Time Analysis Engine

Auto-Packager

The Auto-Packager is Doh's build-time analysis engine. It performs analysis at build-time so the runtime can be simpler and faster. By understanding your code's structure, it generates manifests that handle application orchestration without runtime discovery.

The analysis happens every time your application runs. Dependency relationships, function signatures, and environmental conditions get analyzed and stored as data for the runtime to use.

Code Analysis Process

The Auto-Packager analyzes your code's structure through AST parsing rather than simple pattern matching. Understanding the code structure lets the system provide runtime orchestration without discovery overhead.

Phase 1: AST Analysis - Using Acorn, it parses JavaScript files into Abstract Syntax Trees, walking these structures to understand declarations, relationships, and dependencies. This analysis enables parameter resolution without runtime reflection.

Phase 2: Metadata Extraction - For each discovered declaration, it extracts metadata including:

  • Object literals with nested properties and relationships
  • Function signatures including destructuring patterns and defaults
  • Expressions, template literals, and computed values
  • Import/export statements (both static and dynamic)
  • Route registrations, asset references, and configuration calls
  • Cross-references and inheritance relationships

Phase 3: Manifest Encoding - This understanding is encoded into manifests—machine-readable artifacts that contain what the runtime needs to know about your application's structure, dependencies, and relationships.

The encoded information eliminates runtime discovery overhead by pre-solving dependency resolution, parameter injection, and resource orchestration. This transforms what could be runtime computation into data lookups.

Structural Understanding

The analysis captures JavaScript patterns, transforming code structures into reusable metadata:

// The Auto-Packager analyzes the complete AST, understanding:
// - Module declarations and their full structure
// - Pattern definitions and inheritance chains
// - Import/export statements (static and dynamic)
// - Function signatures and implementations
// - Route registrations, configuration calls
// - All Doh.Module, Doh.Package, and Pattern declarations

Doh.Module('advanced_example', [
  'import { useState, useEffect } from "react@^18.0.0"',
  'browser?? ui_components',
  '^/utils/helpers.js'
], function(useState, useEffect, { helper1, helper2 = 'default' }, ...rest) {
  // The AST captures:
  // - Destructuring parameters with defaults
  // - Rest parameters
  // - All function calls within the module
  // - Asset references, route definitions, etc.
  
  const config = { debug: Doh.pod.debug };
  Router.AddRoute('/api/test', handler);
  
  Pattern('ComplexComponent', ['BaseComponent'], {
    props: { title: 'Default', items: [] },
    computed: {
      displayItems: function() { return this.items.slice(0, 10); }
    }
  });
});

// Even complex Pod configurations with executable code:
Doh.Pod('my_module', {
  database: {
    host: 'localhost',
    protocol: `postgresql://`,
    user: 'user',
    password: 'pass',
    backupPath: DohPath('/mysql')
  }
});

This structure is captured in the build-time analysis and made available to the runtime system through manifests.

Note: For a higher-level view of how the Auto-Packager fits into the Two-Phase Architecture, see the Doh.js Core Architecture Overview.

Structural Elements: Encoding Organization

Package Structure Extraction

Packages represent organizational structure encoded as reusable metadata. The Auto-Packager extracts and encodes:

  • Unique identity relationships within the dependency graph
  • Complete dependency specifications with environmental conditions
  • Installation requirements and version constraints
  • Metadata relationships and inheritance patterns

Package definitions in JavaScript (Doh.Package()) or YAML (.doh.yaml) files become structured data. The Auto-Packager transforms these static declarations into organizational metadata without executing any JavaScript—it captures the structural relationships.

Module Structure Extraction

Modules serve both as build-time declarations and runtime executors:

Structure Capture: The Auto-Packager extracts complete module metadata—name, dependencies, parameter signatures, and internal structure—without executing any code.

Runtime Activation: The encoded structure enables precise dependency injection and execution when the module actually runs.

The extracted metadata includes:

  • Identity and dependency relationships within the application graph
  • Dependency specifications with conditions and decorators
  • Function signatures including destructuring patterns and defaults
  • Internal structure including pattern definitions and nested declarations

Pattern Structure Extraction

Patterns are component blueprints that become encoded structure. The Auto-Packager captures their inheritance relationships, property composition rules, and lifecycle definitions, transforming object-oriented designs into reusable structural metadata.

Standard Import Integration

The Auto-Packager handles cross-environment ESM compatibility. When it encounters standard import statements within dependency arrays, it extracts package names and versions (e.g., "react@^18.0.0") and encodes this into:

  1. Installation Requirements: Information that enables automatic package management during doh upgrade
  2. Environment Mapping: Cross-environment import maps that make standard ESM syntax work identically in browsers, Node.js, and Bun

This allows standard ESM packages to participate in Doh's integrated dependency management without modification.

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: #NOTE: this is largely unused now that imports auto-install
    'npm:yaml': '' # empty value for latest
    'npm:axios': ''

Parameter Resolution Analysis (SPR)

The Auto-Packager's role in Scoped Parameter Resolution (SPR) is to catalog callback parameters at build-time, enabling fast, deterministic dependency injection at runtime.

Build-Time Analysis: The Auto-Packager uses AST analysis to inspect function signatures and extract parameter metadata. This understands destructuring patterns, default values, rest parameters, and assignment patterns.

Parameter Analysis:

  1. AST-Based Function Parsing: Each Doh.Module callback function is parsed as an AST node, extracting its parameter structure
  2. Parameter Patterns: Handles destructuring ({ a, b = 'default' }), rest parameters (...args), and nested patterns
  3. Metadata Preservation: Parameter names, default values, destructuring patterns, and type hints are recorded in manifests
  4. Runtime Resolution Support: This catalog enables the runtime to perform parameter resolution without runtime introspection

Mental model: Load builds scope; params consume scope

  • Producers (load arrays) build layered scope trees at runtime
  • Consumers (callback parameters) resolve by name against that scope using build-time catalogs
  • Auto-Packager makes this tractable through manifest visibility and diagnostics

This enables suite patterns: Import once high up; descendants ask by name via scope tree resolution. The Auto-Packager's manifest visibility makes "mystery capture" detectable and fixable through build-time analysis.

// 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 manifest files in two primary locations:

Private Manifests (/.doh/manifests/)

These manifests contain internal build information, caches, and configuration. They are not distributed and are excluded from being served by 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 Auto-Installer that 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: 10/22/2025