v2
CLI Documentation
Architecture
Path Mapping Generator

Path Mapping Generator

The Path Mapping Generator pre-computes all path mappings before blueprint execution, ensuring all paths are available during framework bootstrap.

Overview

The Path Mapping Generator:

  1. Loads path keys from marketplaces
  2. Generates paths for all path keys (even if apps don't exist yet)
  3. Applies user overrides
  4. Stores paths in PathService

Why Pre-Compute?

Problem: Frameworks need paths during bootstrap, but apps don't exist yet.

Solution: Generate paths for all path keys using default patterns, even if apps don't exist.

Example:

// Path key: apps.web.root
// App doesn't exist yet, but we generate: apps/web/
paths['apps.web.root'] = 'apps/web/'

Path Key Structure

Path keys are defined in path-keys.json:

{
  "pathKeys": [
    {
      "key": "apps.web.root",
      "description": "Web app root directory",
      "required": false,
      "structure": "both",
      "computed": true,
      "group": "web-app"
    }
  ]
}

Generation Strategy

1. Load Path Keys

const pathKeys = await adapter.loadPathKeys();
// pathKeys.pathKeys: Array of path key definitions

2. Generate Base Paths

Use marketplace adapter's resolvePathDefaults():

const basePaths = await adapter.resolvePathDefaults({
  genome,
  project: genome.project,
  apps: getProjectApps(genome),
  packages: genome.packages || {}
});
// basePaths: { 'apps.web.root': 'apps/web/', ... }

3. Compute Missing Paths

For path keys not in base paths, compute using default patterns:

// Key: apps.web.root
// Pattern: apps/{type}/
const computedPath = `apps/${appType}/`;
 
// Key: packages.auth.root
// Pattern: packages/{packageName}/
const computedPath = `packages/${packageName}/`;

4. Apply User Overrides

User overrides have highest priority:

// User override in genome
genome.project.paths = {
  'apps.web.root': 'custom/web/'
}
 
// Override applied
paths['apps.web.root'] = 'custom/web/'

Semantic Path Keys

Some path keys are "semantic" - they expand to multiple paths:

{
  "key": "apps.{appType}.src",
  "semantic": true,
  "resolveToApps": "all"
}

Expansion:

  • apps.web.srcapps/web/src/
  • apps.mobile.srcapps/mobile/src/
  • apps.api.srcapps/api/src/

Example

Path Keys

{
  "pathKeys": [
    { "key": "workspace.root", "defaultValue": "./" },
    { "key": "apps.web.root", "computed": true },
    { "key": "apps.web.src", "computed": true },
    { "key": "packages.auth.root", "computed": true }
  ]
}

Generated Paths

{
  'workspace.root': './',
  'apps.web.root': 'apps/web/',
  'apps.web.src': 'apps/web/src/',
  'packages.auth.root': 'packages/auth/'
}

Framework Bootstrap Context

During framework bootstrap, paths resolve relative to VFS root:

// VFS root: /project/apps/web
// Path resolution
if (vfsRoot === appDirectory) {
  paths['apps.web.root'] = './';  // Relative to VFS root
  paths['apps.web.src'] = './src/';
}

Why? Prevents nested directories like apps/web/apps/web/.

Path Service

Paths are stored in PathService for resolution:

PathService.set('apps.web.root', 'apps/web/');
const path = PathService.get('apps.web.root');  // 'apps/web/'

Benefits:

  • Single source of truth
  • Available during bootstrap
  • Type-safe resolution

Related