Skip to content

Package Dependencies

Understanding the package dependency hierarchy is crucial for maintaining the monorepo and avoiding circular dependencies.

Dependency Hierarchy

The packages follow a strict layered architecture:

┌─────────────────────────────────────────────────────┐
│  Layer 6: Applications                              │
│  Backend App, Front App, Dashboard App              │
└──────────────────┬──────────────────────────────────┘
                   │ depends on
┌──────────────────▼──────────────────────────────────┐
│  Layer 5: Feature Modules & Widgets                 │
│  @barcoding/module-*, @barcoding/widget-*           │
└──────────────────┬──────────────────────────────────┘
                   │ depends on
┌──────────────────▼──────────────────────────────────┐
│  Layer 4: App Core Packages                         │
│  @barcoding/backend-core                            │
│  @barcoding/frontend-core                           │
│  @barcoding/dashboard-core                          │
└──────────────────┬──────────────────────────────────┘
                   │ depends on
┌──────────────────▼──────────────────────────────────┐
│  Layer 3: Gridster Core (CRITICAL)                  │
│  @barcoding/gridster-core                           │
└──────────────────┬──────────────────────────────────┘
                   │ depends on
┌──────────────────▼──────────────────────────────────┐
│  Layer 2: Auth & Core                               │
│  @barcoding/auth-core                               │
│  @barcoding/core                                    │
└──────────────────┬──────────────────────────────────┘
                   │ depends on
┌──────────────────▼──────────────────────────────────┐
│  Layer 1: SDK (Auto-generated)                      │
│  @barcoding/sdk                                     │
└─────────────────────────────────────────────────────┘

Dependency Rules

Rule 1: One-Way Dependencies

Dependencies always flow downward in the hierarchy. Higher layers can depend on lower layers, but never the reverse.

typescript
// ✅ Good: Higher layer depends on lower layer
// @barcoding/backend-core can depend on @barcoding/core
import { FormService } from '@barcoding/core';

// ❌ Bad: Lower layer depends on higher layer
// @barcoding/core CANNOT depend on @barcoding/backend-core
import { BackendService } from '@barcoding/backend-core'; // ERROR!

Rule 2: No Circular Dependencies

Never create circular dependencies between packages.

typescript
// ❌ Bad: Circular dependency
// Package A depends on Package B
// Package B depends on Package A

// ✅ Good: Extract shared code to a lower layer
// Package A depends on Package C
// Package B depends on Package C
// Package C is independent

Rule 3: Respect Layer Boundaries

Packages can only depend on packages in the same or lower layers.

typescript
// ✅ Good: Module depends on core packages
// @barcoding/module-ticket
import { CoreService } from '@barcoding/core';
import { AuthGuard } from '@barcoding/auth-core';

// ❌ Bad: Module depends on another module
// @barcoding/module-ticket
import { NcrService } from '@barcoding/module-ncr'; // ERROR!

Layer Details

Layer 1: SDK

Package: @barcoding/sdk

Purpose: Auto-generated API client

Dependencies: None (only Angular common and HttpClient)

Generated from: API OpenAPI spec at http://localhost:3000/openapi.json

Key Files:

  • services/*.service.ts - 604 API controller services
  • models/*.ts - API model interfaces
  • api.module.ts - SDK module

Important: Never manually edit SDK files. Always regenerate using yarn build-sdk.

Layer 2: Auth & Core

@barcoding/core

Purpose: Universal utilities used by all three instances

Dependencies: @barcoding/sdk, Angular common

Key Exports:

  • FormService - Form builders and validators
  • UtilityService - Helper functions
  • ModuleStore - NGXS module state
  • WidgetStore - NGXS widget state
  • Common models and interfaces

Who uses it: All three instances, all modules, all widgets

@barcoding/auth-core

Purpose: Authentication and authorization

Dependencies: @barcoding/core, @barcoding/sdk

Key Exports:

  • AuthService - Authentication service
  • AuthGuard - Route protection
  • AuthInterceptor - HTTP interceptor
  • AuthState - NGXS auth state
  • AclService - Access control

Who uses it: All three instances, protected modules

Layer 3: Gridster Core

Package: @barcoding/gridster-core

Purpose: Dynamic widget system (CRITICAL - used by all three instances)

Dependencies: @barcoding/auth-core, @barcoding/core, @barcoding/sdk

Key Exports:

  • GridsterComponent - Main gridster component
  • WidgetHostDirective - Widget host directive
  • GridsterService - Widget management service
  • Widget interfaces and models

Who uses it: All three instances (Backend, Front, Dashboard)

Why it's critical:

  • Widget definitions are stored in the database
  • Handles dynamic widget loading and positioning
  • Manages user-specific widget configurations

Layer 4: App Core Packages

@barcoding/backend-core

Purpose: Backend app-specific utilities

Dependencies: @barcoding/gridster-core, @barcoding/auth-core, @barcoding/core, @barcoding/sdk

Who uses it: Backend app, backend-specific modules

@barcoding/frontend-core

Purpose: Frontend app-specific utilities

Dependencies: @barcoding/gridster-core, @barcoding/auth-core, @barcoding/core, @barcoding/sdk

Who uses it: Front app, frontend-specific modules

@barcoding/dashboard-core

Purpose: Dashboard app-specific utilities

Dependencies: @barcoding/gridster-core, @barcoding/auth-core, @barcoding/core, @barcoding/sdk

Who uses it: Dashboard app, dashboard-specific modules

Layer 5: Feature Modules & Widgets

Feature Modules

Examples: @barcoding/module-ticket, @barcoding/module-ncr, @barcoding/module-hr

Dependencies: App cores, gridster-core, auth-core, core, sdk

Key Pattern:

typescript
// module-ticket/package.json
{
  "dependencies": {
    "@barcoding/core": "*",
    "@barcoding/sdk": "*",
    "@barcoding/auth-core": "*",
    "@barcoding/backend-core": "*"  // If used by Backend app
  }
}

Widgets

Examples: @barcoding/widget-calendar, @barcoding/widget-chart

Dependencies: gridster-core, core, sdk

Key Pattern:

typescript
// widget-calendar/package.json
{
  "dependencies": {
    "@barcoding/core": "*",
    "@barcoding/sdk": "*",
    "@barcoding/gridster-core": "*"
  }
}

Layer 6: Applications

Packages: Backend app, Front app, Dashboard app

Dependencies: Any package from layers 1-5

Key Pattern:

typescript
// backend/project.json
{
  "dependencies": {
    "@barcoding/core": "*",
    "@barcoding/sdk": "*",
    "@barcoding/auth-core": "*",
    "@barcoding/gridster-core": "*",
    "@barcoding/backend-core": "*",
    "@barcoding/module-ticket": "*",
    "@barcoding/widget-calendar": "*"
  }
}

Build Order

Due to dependencies, packages must be built in order:

bash
# 1. Layer 1: SDK (no dependencies)
ng build @barcoding/sdk

# 2. Layer 2: Core packages
ng build @barcoding/core
ng build @barcoding/auth-core

# 3. Layer 3: Gridster
ng build @barcoding/gridster-core

# 4. Layer 4: App cores (can be parallel)
ng build @barcoding/backend-core
ng build @barcoding/frontend-core
ng build @barcoding/dashboard-core

# 5. Layer 5: Modules and widgets (can be parallel)
ng build @barcoding/module-ticket
ng build @barcoding/module-ncr
ng build @barcoding/widget-calendar

# 6. Layer 6: Applications
yarn build:back:prod
yarn build:front:prod
yarn build:dash:prod

Or simply run yarn build which handles the order automatically.

Checking Dependencies

View Package Dependencies

bash
cd web/projects/packages/@barcoding/<package-name>
cat package.json | grep -A 20 '"dependencies"'

Find Who Depends on a Package

bash
cd web
grep -r "@barcoding/core" projects/*/package.json

Visualize Dependency Graph

bash
cd web
npx nx graph

Common Dependency Issues

Issue 1: Circular Dependencies

Symptom: Build errors or runtime errors about circular dependencies

Solution: Extract shared code to a lower-layer package

typescript
// ❌ Bad: Package A and B depend on each other
// A → B, B → A

// ✅ Good: Extract to package C
// A → C, B → C

Issue 2: Missing Peer Dependencies

Symptom: TypeScript errors about missing types

Solution: Add peer dependencies to package.json

json
{
  "peerDependencies": {
    "@angular/core": "^17.3.0",
    "@barcoding/core": "*"
  }
}

Issue 3: Version Mismatches

Symptom: Runtime errors or type incompatibilities

Solution: Use consistent versions across packages

bash
# Update all @barcoding packages to latest
cd web
yarn upgrade-interactive --latest

Best Practices

1. Keep Dependencies Minimal

Only depend on what you actually use:

typescript
// ❌ Bad: Importing entire package for one function
import * as core from '@barcoding/core';

// ✅ Good: Import only what you need
import { FormService } from '@barcoding/core';

2. Use Peer Dependencies for Angular

Angular packages should be peer dependencies:

json
{
  "peerDependencies": {
    "@angular/core": "^17.3.0",
    "@angular/common": "^17.3.0"
  }
}

3. Document Major Dependencies

In your package README, document major dependencies:

markdown
## Dependencies

This package depends on:
- `@barcoding/core` - For form services
- `@barcoding/sdk` - For API calls
- `@barcoding/auth-core` - For authentication

4. Avoid Deep Imports

Import from the package barrel, not deep paths:

typescript
// ❌ Bad: Deep import
import { FormService } from '@barcoding/core/src/lib/services/form.service';

// ✅ Good: Barrel import
import { FormService } from '@barcoding/core';

Next Steps

Syneo/Barcoding Documentation