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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@timbouc/cart

v0.2.3

Published

A flexible and fluent way to manage shopping carts.

Downloads

18

Readme

@timbouc/cart

A Shopping Cart Implementation for Node.js and browsers.

:yellow_heart: Features

  • Pluggable storage drivers
  • Manage vouchers, shipping and other conditional factors with Conditions
  • Sync frontend and backend instances with remote storage connection
  • Comes with a default local storage (Node.js)
  • Save miscellaneous data to cart (e.g. currency, purchase metadata)
  • Customise final items' and conditions' prices with hooks for complex (e.g. graduated pricing) use case

Getting Started

This package is available in the npm registry. It can easily be installed with npm or yarn.

$ npm i @timbouc/cart
# or
$ yarn add @timbouc/cart

Instantiate with a configuration.

import { Cart } from '@timbouc/cart';
const cart = new Cart(context.uudid, config);

Usage

const item = await cart.add({
    id: product.id,
    name: product.name,
    price: product.price,
});
await cart.apply([
    {
        name: 'Voucher 1',
        type: 'voucher',
        target: item.item_id,
        value: '-10%', // removes 10% of the value of product.price
    },
    {
        name: 'Shipping',
        type: 'shipping',
        target: 'subtotal', // add 10 to subtotal
        value: 10,
    }
]);

const subtotal = await cart.subtotal(),
      total = await cart.total();

Registering Storage

const { RedisStorage, PostgresStorage } from './StorageDrivers';

const session = context.uudid
const cart = new Cart(session, config)
cart.registerDriver('redis', RedisStorage)
cart.registerDriver('pg', PostgresStorage())

// use redis storage for different shopping carts
cart.driver('redis')
	.add(...)

// use postgres storage for wishlist
cart.driver('pg')
    .session(session + ':wishlist') // can also change session (user)
	.add(...)

See RedisStorage example from custom storage.

Response interface

Asynchronous methods will always return a Promise which resolves with a Response object.

Methods

// Set/switch cart session instance
cart.session(user_id)
    .add(...)

Add an item or an array of items to cart

// add one item to cart
const item = await cart.add({
	// item_id: 1,        // Manually set item id
    id: product.id,
    name: product.name,
    price: product.price,
    quantity: 3, // defaults to one
    conditions: conditions as Array<CartCondition>,
    options: options as Array<CartItemOption>,
})

// add multiple items to cart
const [item1, item2] = await cart.add([
    {
        id: product1.id,
        name: product1.name,
        price: product1.price,
        options: [{
            name: "Color",
            value: "pink",
        }]
    },
    {
        id: product2.id,
        name: product2.name,
        price: product2.price,
    },
])

// Add item with custom field(s)
// cannot be updated afterwords
const item = await cart.add({
    id: product.id,
    name: product.name,
    price: product.price,
    workspace: 'Timbouc',
})

Update a cart item. Accumulates quantity by default but override can be specified

// new item price, price can also be a string format like so: '98.67'
cart.update(5, {
    name: 'New Item Name',
    price: 99.99,
});

// update a product's quantity
cart.update(5, {
    quantity: 2, // if the current product has a quantity of 4, another 2 will be added so this will result to 6
});

// update a product by reducing its quantity
cart.update(5, {
    quantity: -1, // if the current product has a quantity of 4, another 1 will be subtracted so this will result to 3
});

// To totally replace the quantity instead of incrementing or decrementing its current quantity value
// pass an object
cart.update(5, {
    quantity: {
        relative: false,
        value: 5
    }
});

Remove an item or an array of items from cart

cart.remove(5);

// Remove multiple
cart.remove([2, 3, 4]);
// Get cart item
const item = await cart.get(item_id);

Apply a cart condition or an array of conditions. Conditions are used to account for discounts, taxes and other conditional factors. The field target specifies the entity the condition applies to. This value can be total, subtotal or an item ID.

const voucher1 = await cart.apply({
    name: 'Voucher 1',
    type: 'voucher',
    target: 1,  // cart item id
    value: -10, // removes the value `10` from i1
});

// apply multiple conditions
const [voucher1b, tax] = await cart.apply([
    {
        name: 'Voucher 1', // Replaces `Voucher 1` as it already exists (handy for managing tax, shipping and other standard conditions)
        type: 'voucher',
        target: 2,  // cart item id
        value: '-10%', // removes 10% of the value of item 2
    },
    {
        name: 'Tax',
        type: 'tax',
        target: 'subtotal',
        value: '10%', // adds 10% of subtotal to total
    }
]);
// List cart conditions
await cart.conditions()
// Get condition
await cart.condition('Voucher 2')
// Remove condition
await cart.removeCondition('Voucher 2')
// Clear all cart conditions
await cart.clearConditions()
// Save currency. Returns `AUD`
let d1 = await cart.data('currency', 'AUD')

// Get saved data
let d2 = await cart.data('currency')

// Use dot notation
await cart.data('customer.name', 'Johnn Doe')
await cart.data('customer.email', '[email protected]')
await cart.data('customer') // returns { name: 'Johnn Doe', email: '[email protected]' }
await cart.data('token', '1233')
await cart.data() // returns { currency: 'AUD', customer: { name: 'Johnn Doe', email: '[email protected]' }, token: '1233' }


// Alternatively, set the above data by passing an object
// Note that this will NOT override `token` field set above
await cart.data({
  currency: 'AUD',
  customer: { name: 'Johnn Doe', email: '[email protected]' }
})
// If cart is empty
await cart.empty()
// Count item entries in cart
await cart.count()

Return the cart content.

// Get cart contents
await cart.content()
// List cart items
await cart.items()
// Get cart subtotal
await cart.subtotal()
// Get cart total
await cart.total()
await cart.clear()

// Do not clear conditions and data
await cart.clear({ conditions: false, data: false })
const cart2 = await cart.copy(new_session_id)

// Do not copy conditions and data. Also pass a new config
const cart3 = await cart.copy(new_session_id, { conditions: false, data: false }, new_config)
// Get the storage instance
const storage = cart.storage()
// Get theunderlying data loader
const loader = cart.loader()

Contribution Guidelines

Any pull requests or discussions are welcome. Note that every pull request providing new feature or correcting a bug should be created with appropriate unit tests.