npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@unchainedshop/core

v4.6.2

Published

Core orchestration package for the Unchained Engine with business services and directors

Downloads

1,204

Readme

npm version License: EUPL-1.2

@unchainedshop/core

Core orchestration package for the Unchained Engine. Integrates all core-* modules, provides business services, directors for plugins, and bulk import functionality.

Installation

npm install @unchainedshop/core

Usage

import { initCore, type UnchainedCore } from '@unchainedshop/core';

const unchainedCore = await initCore({
  db,
  migrationRepository,
  options: {
    // Module-specific options
  },
});

// Access modules
const products = await unchainedCore.modules.products.findProducts({});

// Use services
const pricing = await unchainedCore.services.orders.pricingSheet(order);

// Bulk import
await unchainedCore.bulkImporter.prepare('PRODUCT');

API Overview

Initialization

| Export | Description | |--------|-------------| | initCore | Initialize the core with all modules and services | | getAllAdapters | Get all registered adapters across all directors |

Modules

The modules object provides access to all core-* module APIs:

| Module | Description | |--------|-------------| | products | Product management | | assortments | Category/assortment management | | filters | Product filtering and search | | orders | Order management | | users | User management | | payment | Payment providers | | delivery | Delivery providers | | warehousing | Inventory and stock | | enrollments | Subscriptions | | quotations | Quote management | | bookmarks | User bookmarks | | countries | Country management | | currencies | Currency management | | languages | Language management | | files | File management | | events | Event history | | worker | Background jobs |

Services

Business logic services that orchestrate multiple modules:

| Service | Description | |---------|-------------| | orders | Order pricing, checkout workflows | | products | Product pricing calculations | | users | User-related operations | | files | File operations with adapters |

Directors

Plugin directors provide extensibility through the Director/Adapter pattern. Each director manages a collection of adapters that implement specific behaviors.

| Director | Description | |----------|-------------| | PaymentDirector | Payment processing adapters | | DeliveryDirector | Delivery/shipping adapters | | WarehousingDirector | Inventory and stock adapters | | WorkerDirector | Background job workers | | FilterDirector | Product search and filtering | | EnrollmentDirector | Subscription plan handling | | QuotationDirector | Quote/RFQ processing | | ProductPricingDirector | Product price calculations | | OrderPricingDirector | Order total calculations | | DeliveryPricingDirector | Delivery fee calculations | | PaymentPricingDirector | Payment fee calculations | | ProductDiscountDirector | Product-level discounts | | OrderDiscountDirector | Order-level discounts | | MessagingDirector | Email/notification templates |

Director/Adapter Architecture

The Unchained Engine uses a Director/Adapter pattern for extensibility. Directors manage collections of adapters, and adapters implement specific behaviors.

Base Classes

import { BaseAdapter, BaseDirector } from '@unchainedshop/utils';
  • BaseDirector: Factory function that creates a generic director with methods to register, unregister, and retrieve adapters
  • BaseAdapter: Base implementation providing logging and utility methods for all adapters

Creating a Custom Adapter

All adapters extend from BaseAdapter and must implement:

const MyAdapter = {
  key: 'my-adapter',           // Unique identifier
  label: 'My Custom Adapter',  // Human-readable label
  version: '1.0.0',            // Adapter version

  // Adapter-specific methods...
};

// Register with the appropriate director
SomeDirector.registerAdapter(MyAdapter);

Payment Director

Manages payment processing and orchestrates payment adapters.

import { PaymentDirector, type IPaymentAdapter } from '@unchainedshop/core';

const MyPaymentAdapter: IPaymentAdapter = {
  key: 'my-payment',
  label: 'My Payment Gateway',
  version: '1.0.0',

  typeSupported(type) {
    return type === 'CARD';
  },

  actions(config, context) {
    return {
      configurationError() { return null; },
      isActive() { return true; },
      isPayLaterAllowed() { return false; },

      async charge() {
        // Process payment charge
        return { transactionId: '...' };
      },
      async confirm() {
        // Confirm payment
        return { transactionId: '...' };
      },
      async cancel() {
        // Cancel payment
        return true;
      },
      async register() {
        // Register payment method
        return { token: '...' };
      },
      async sign() {
        // Sign payment request
        return '...';
      },
      async validate(token) {
        // Validate payment token
        return true;
      },
    };
  },
};

PaymentDirector.registerAdapter(MyPaymentAdapter);

Delivery Director

Manages delivery operations and coordinates shipping adapters.

import { DeliveryDirector, type IDeliveryAdapter } from '@unchainedshop/core';

const MyDeliveryAdapter: IDeliveryAdapter = {
  key: 'my-delivery',
  label: 'My Shipping Provider',
  version: '1.0.0',

  typeSupported(type) {
    return type === 'SHIPPING';
  },

  actions(config, context) {
    return {
      configurationError() { return null; },
      isActive() { return true; },
      isAutoReleaseAllowed() { return false; },

      async send() {
        // Trigger delivery
        return { trackingNumber: '...' };
      },
      estimatedDeliveryThroughput(warehousingTime) {
        // Return estimated delivery time in ms
        return 3 * 24 * 60 * 60 * 1000; // 3 days
      },
      async pickUpLocations() {
        // Return available pickup locations
        return [];
      },
      async pickUpLocationById(locationId) {
        return null;
      },
    };
  },
};

DeliveryDirector.registerAdapter(MyDeliveryAdapter);

Warehousing Director

Manages inventory and stock operations, including NFT/token support.

import { WarehousingDirector, type IWarehousingAdapter } from '@unchainedshop/core';

const MyWarehousingAdapter: IWarehousingAdapter = {
  key: 'my-warehouse',
  label: 'My Inventory System',
  version: '1.0.0',

  typeSupported(type) {
    return type === 'PHYSICAL';
  },

  actions(config, context) {
    return {
      configurationError() { return null; },
      isActive() { return true; },

      async stock(referenceDate) {
        // Return current stock quantity
        return 100;
      },
      async productionTime(quantity) {
        // Return production time in ms
        return 0;
      },
      async commissioningTime(quantity) {
        // Return commissioning time in ms
        return 24 * 60 * 60 * 1000; // 1 day
      },
      async estimatedStock() {
        return 100;
      },
      async estimatedDispatch() {
        return new Date();
      },
      // For tokenized products (NFTs):
      async tokenize() { return []; },
      async tokenMetadata(serial, date) { return {}; },
      async isInvalidateable(serial, date) { return false; },
    };
  },
};

WarehousingDirector.registerAdapter(MyWarehousingAdapter);

Worker Director

Manages background job processing and scheduled tasks.

import { WorkerDirector, type IWorkerAdapter } from '@unchainedshop/core';

interface MyInput { email: string; subject: string; }
interface MyOutput { messageId: string; }

const MyWorkerAdapter: IWorkerAdapter<MyInput, MyOutput> = {
  key: 'my-worker',
  label: 'My Background Worker',
  version: '1.0.0',
  type: 'MY_WORK_TYPE',          // Work type identifier
  external: false,                // Runs in-process
  maxParallelAllocations: 10,     // Max concurrent executions

  async doWork(input, unchainedAPI, workId) {
    // Process the work item
    const { email, subject } = input;

    // Return result
    return {
      success: true,
      result: { messageId: 'msg-123' },
    };
  },
};

WorkerDirector.registerAdapter(MyWorkerAdapter);

// Schedule recurring work
WorkerDirector.configureAutoscheduling({
  type: 'MY_WORK_TYPE',
  input: { email: '[email protected]', subject: 'Test' },
  schedule: '0 * * * *', // Every hour (cron syntax)
});

Pricing Directors

Pricing directors calculate prices using a chain of adapters. Each adapter can add, modify, or discount prices.

import { ProductPricingDirector, type IProductPricingAdapter } from '@unchainedshop/core';

const MyPricingAdapter: IProductPricingAdapter = {
  key: 'my-pricing',
  label: 'My Pricing Logic',
  version: '1.0.0',
  orderIndex: 10, // Lower numbers run first

  isActivatedFor(context) {
    // Return true if this adapter should apply
    return true;
  },

  actions(params) {
    return {
      calculate() {
        // Add price calculations
        this.calculation.addItem({
          category: 'BASE',
          amount: 1000, // in smallest currency unit
        });
      },
    };
  },
};

ProductPricingDirector.registerAdapter(MyPricingAdapter);

Discount Directors

Discount directors manage coupon codes and automatic discounts.

import { OrderDiscountDirector, type IDiscountAdapter } from '@unchainedshop/core';

const MyDiscountAdapter: IDiscountAdapter = {
  key: 'my-discount',
  label: 'My Discount System',
  version: '1.0.0',
  orderIndex: 10,

  isManualAdditionAllowed(code) {
    return code.startsWith('PROMO');
  },
  isManualRemovalAllowed() {
    return true;
  },

  actions(context) {
    return {
      isValidForSystemTriggering() {
        // Auto-apply discount?
        return false;
      },
      isValidForCodeTriggering(code) {
        // Apply when code entered?
        return code === 'PROMO10';
      },
      discountForPricingAdapterKey(params) {
        // Return discount configuration for pricing adapter
        return {
          isNetPrice: false,
          rate: 0.1, // 10% off
        };
      },
      async reserve(code) {
        // Reserve discount (e.g., decrement coupon balance)
      },
      async release() {
        // Release reservation on order cancellation
      },
    };
  },
};

OrderDiscountDirector.registerAdapter(MyDiscountAdapter);

Filter Director

Manages product filtering and search functionality.

import { FilterDirector, type IFilterAdapter } from '@unchainedshop/core';

const MyFilterAdapter: IFilterAdapter = {
  key: 'my-filter',
  label: 'My Search Filter',
  version: '1.0.0',
  orderIndex: 10,

  actions(context) {
    return {
      async aggregateProductIds(params) {
        // Return product IDs matching filter
        return ['product-1', 'product-2'];
      },
      async searchProducts(params, options) {
        // Search products
        return { productIds: [], totalCount: 0 };
      },
      async searchAssortments(params, options) {
        // Search assortments
        return { assortmentIds: [], totalCount: 0 };
      },
      transformProductSelector(selector, options) {
        // Modify MongoDB product selector
        return selector;
      },
      transformFilterSelector(selector, options) {
        // Modify MongoDB filter selector
        return selector;
      },
      transformSortStage(sort, options) {
        // Modify MongoDB sort stage
        return sort;
      },
    };
  },
};

FilterDirector.registerAdapter(MyFilterAdapter);

Messaging Director

The Messaging Director uses a template resolver pattern instead of traditional adapters.

import { MessagingDirector } from '@unchainedshop/core';

// Register a message template
MessagingDirector.registerTemplate('ORDER_CONFIRMATION', async (context) => {
  const { order, user } = context;

  return [
    {
      type: 'EMAIL',
      input: {
        to: user.email,
        subject: `Order Confirmation #${order.orderNumber}`,
        html: '<h1>Thank you for your order!</h1>',
      },
    },
    {
      type: 'SMS',
      input: {
        to: user.phone,
        text: `Order #${order.orderNumber} confirmed!`,
      },
    },
  ];
});

Quotation Director

Handles quotation/RFQ (Request for Quote) operations.

import { QuotationDirector, type IQuotationAdapter } from '@unchainedshop/core';

const MyQuotationAdapter: IQuotationAdapter = {
  key: 'my-quotation',
  label: 'My Quote System',
  version: '1.0.0',

  isActivatedFor(quotationContext, unchainedAPI) {
    return true;
  },

  actions(context) {
    return {
      configurationError() { return null; },
      isManualProposalRequired() { return true; },
      isManualRequestVerificationRequired() { return false; },

      async quote() {
        // Generate quote
        return { price: 1000, currency: 'CHF' };
      },
      async submitRequest(quotationContext) {
        // Submit RFQ
      },
      async verifyRequest(quotationContext) {
        // Verify RFQ
      },
      async rejectRequest(quotationContext) {
        // Reject RFQ
      },
      transformItemConfiguration(params) {
        return params.configuration;
      },
    };
  },
};

QuotationDirector.registerAdapter(MyQuotationAdapter);

Enrollment Director

Manages subscription/enrollment plans and recurring billing.

import { EnrollmentDirector, type IEnrollmentAdapter } from '@unchainedshop/core';

const MyEnrollmentAdapter: IEnrollmentAdapter = {
  key: 'my-enrollment',
  label: 'My Subscription System',
  version: '1.0.0',

  isActivatedFor(productPlan) {
    return productPlan.type === 'PLAN_PRODUCT';
  },

  transformOrderItemToEnrollmentPlan(orderPosition, unchainedAPI) {
    return {
      configuration: orderPosition.configuration,
    };
  },

  actions(context) {
    return {
      async nextPeriod() {
        // Calculate next billing period
        return {
          start: new Date(),
          end: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
        };
      },
      isValidForActivation() {
        return true;
      },
      isOverdue() {
        return false;
      },
      async configurationForOrder(period) {
        // Return order configuration for period
        return {};
      },
    };
  },
};

EnrollmentDirector.registerAdapter(MyEnrollmentAdapter);

Bulk Importer

| Method | Description | |--------|-------------| | bulkImporter.prepare | Prepare bulk import for entity type | | bulkImporter.process | Process prepared import data |

Types

| Export | Description | |--------|-------------| | UnchainedCore | Core instance type | | UnchainedCoreOptions | Initialization options | | Modules | All modules type | | Services | All services type | | BulkImporter | Bulk importer type |

Configuration

const core = await initCore({
  db,
  migrationRepository,
  modules: {
    // Custom modules
  },
  services: {
    // Custom services
  },
  bulkImporter: {
    handlers: {
      // Custom import handlers
    },
  },
  options: {
    // Module-specific options
  },
});

License

EUPL-1.2