open-index/open-npm huggingface dataset:
npm package: @pinefile/pinex
Description: Experimental version of Pine
Author: Fredrik Forsmo
Latest version: 1.0.1

<div align="center">
  <a href="https://github.com/pinefile/pine">
    <img src="https://avatars.githubusercontent.com/u/70938295?s=200&v=4" width="100px" height="100px" />
  </a>
</div>

# Pinex

[![Build Status](https://img.shields.io/github/workflow/status/pinefile/pinex/build?color=049668&style=flat-square)](https://github.com/pinefile/pinex/actions) [![NPM](https://img.shields.io/npm/v/@pinefile/pinex?color=049668&style=flat-square)](https://www.npmjs.com/package/@pinefile/pinex)

Experimental version of [Pine](https://pinefile.github.io)

## License

MIT © [Fredrik Forsmo](https://github.com/frozzare)
npm package: @pinegrow/astro-module
Description: Pinegrow Astro Module
Author: Pinegrow
Latest version: 3.0.70

<!-- [![@pinegrow/astro-module](https://tailwindcss.nuxtjs.org/social-card.png)](https://tailwindcss.nuxtjs.org) -->

# Pinegrow Astro Module

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]

[Astro](https://astro.build/) module for [Pinegrow](https://pinegrow.com) ⚡️

Pinegrow Astro Module enables connection and interaction between your Vite Dev-Server and Pinegrow apps (currently only Vue Designer).

-   [&nbsp;Learn more about Vue Designer](https://vuedesigner.com)

## Features

-   🎨&nbsp; Visually live-design your Vite-powered Astro apps (currently only Vue components are supported)
-   ⚙️&nbsp; Smartly integrates into your Astro workflow in dev-mode only
-   ✨&nbsp; Clean code 😃, No lock-in - You are in control of your projects and development workflow ❤️

## Quick Setup

1. Install: Add `@pinegrow/astro-module` to your project

```bash
# Using npm
npm install -D @pinegrow/astro-module

# Using pnpm
pnpm add -D @pinegrow/astro-module
```

2. Configure: Add `@pinegrow/astro-module` to your Astro Integrations array `astro.config.{mjs,ts}`

```js
//astro.config.mjs (or) astro.config.ts

import { defineConfig } from 'astro/config'

import vue from '@astrojs/vue'
import Pinegrow from '@pinegrow/astro-module'

export default defineConfig({
	integrations: [
		vue(),
		Pinegrow({
			liveDesigner: {
				// For options, refer to https://www.npmjs.com/package/@pinegrow/vite-plugin
				//...
			},
		}),
		//...
	],
	//...
})
```

Now, open your project in your Pinegrow app (currently only Vue Designer). ✨

## License

[MIT License](./LICENSE)

Copyright (c) Pinegrow

<!-- Badges -->

[npm-version-src]: https://img.shields.io/npm/v/@pinegrow/astro-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-href]: https://npmjs.com/package/@pinegrow/astro-module
[npm-downloads-src]: https://img.shields.io/npm/dm/@pinegrow/astro-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-downloads-href]: https://npmjs.com/package/@pinegrow/astro-module
[license-src]: https://img.shields.io/npm/l/@pinegrow/astro-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[license-href]: https://npmjs.com/package/@pinegrow/astro-module
npm package: @pinegrow/iles-module
Description: Pinegrow Iles Module
Author: Pinegrow
Latest version: 3.0.70

<!-- [![@pinegrow/iles-module](https://tailwindcss.nuxtjs.org/social-card.png)](https://tailwindcss.nuxtjs.org) -->

# Pinegrow Iles Module

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]

[Iles](https://iles.pages.dev/) module for [Pinegrow](https://pinegrow.com) ⚡️

Pinegrow Iles Module enables connection and interaction between your Vite Dev-Server and Pinegrow apps (currently only Vue Designer).

-   [&nbsp;Learn more about Vue Designer](https://vuedesigner.com)

## Features

-   🎨&nbsp; Visually live-design your Vite-powered Iles apps
-   ⚙️&nbsp; Smartly integrates into your Iles workflow in dev-mode only
-   ✨&nbsp; Clean code 😃, No lock-in - You are in control of your projects and development workflow ❤️

## Quick Setup

1. Install: Add `@pinegrow/iles-module` to your project

```bash
# Using npm
npm install -D @pinegrow/iles-module

# Using pnpm
pnpm add -D @pinegrow/iles-module
```

2. Configure: Add `@pinegrow/iles-module` to your Iles Integrations array `iles.config.{js,ts}`

```js
//iles.config.js (or) iles.config.ts

import { defineConfig } from 'iles'

export default defineConfig({
	modules: [
		[
			'@pinegrow/iles-module',
			{
				liveDesigner: {
					// For options, refer to https://www.npmjs.com/package/@pinegrow/vite-plugin
					//...
				},
			},
		],
		//...
	],
	//...
})
```

Now, open your project in your Pinegrow app (currently only Vue Designer). ✨

## License

[MIT License](./LICENSE)

Copyright (c) Pinegrow

<!-- Badges -->

[npm-version-src]: https://img.shields.io/npm/v/@pinegrow/iles-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-href]: https://npmjs.com/package/@pinegrow/iles-module
[npm-downloads-src]: https://img.shields.io/npm/dm/@pinegrow/iles-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-downloads-href]: https://npmjs.com/package/@pinegrow/iles-module
[license-src]: https://img.shields.io/npm/l/@pinegrow/iles-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[license-href]: https://npmjs.com/package/@pinegrow/iles-module
npm package: @pinegrow/nuxt-module
Description: Pinegrow Nuxt Module
Author: Pinegrow
Latest version: 3.0.70

<!-- [![@pinegrow/nuxt-module](https://tailwindcss.nuxtjs.org/social-card.png)](https://tailwindcss.nuxtjs.org) -->

# Pinegrow Nuxt Module

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]

[Nuxt](https://nuxt.com/) module for [Pinegrow](https://pinegrow.com) ⚡️

Pinegrow Nuxt Module enables connection and interaction between your Vite Dev-Server and Pinegrow apps (currently only Vue Designer).

-   [&nbsp;Learn more about Vue Designer](https://vuedesigner.com)

## Features

-   🎨&nbsp; Visually live-design your Vite-powered Nuxt apps
-   ⚙️&nbsp; Smartly integrates into your Nuxt workflow in dev-mode only
-   ✨&nbsp; Clean code 😃, No lock-in - You are in control of your projects and development workflow ❤️

## Quick Setup

1. Install: Add `@pinegrow/nuxt-module` to your project

```bash
# Using npm
npm install -D @pinegrow/nuxt-module

# Using pnpm
pnpm add -D @pinegrow/nuxt-module
```

2. Configure: Add `@pinegrow/nuxt-module` to your Nuxt Integrations array `nuxt.config.{js,ts}`

```js
//nuxt.config.js (or) nuxt.config.ts

export default defineNuxtConfig({
	modules: [
		'@pinegrow/nuxt-module',
		//...
	],
	pinegrow: {
		liveDesigner: {
			// For options, refer to https://www.npmjs.com/package/@pinegrow/vite-plugin
			//...
		},
	},
	//...
})
```

Now, open your project in your Pinegrow app (currently only Vue Designer). ✨

## License

[MIT License](./LICENSE)

Copyright (c) Pinegrow

<!-- Badges -->

[npm-version-src]: https://img.shields.io/npm/v/@pinegrow/nuxt-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-href]: https://npmjs.com/package/@pinegrow/nuxt-module
[npm-downloads-src]: https://img.shields.io/npm/dm/@pinegrow/nuxt-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-downloads-href]: https://npmjs.com/package/@pinegrow/nuxt-module
[license-src]: https://img.shields.io/npm/l/@pinegrow/nuxt-module.svg?style=flat&colorA=18181B&colorB=28CF8D
[license-href]: https://npmjs.com/package/@pinegrow/nuxt-module
npm package: @pinegrow/tailwind-plugin
Description: Pinegrow Tailwind Plugin
Author: Pinegrow
Latest version: 3.0.0-beta.19
Deprecated: Please install @pinegrow/tailwindcss-plugin instead. This package is no longer maintained

# @pinegrow/postcss-tailwind

## PostCSS Tailwind plugin for Pinegrow

http://www.pinegrow.com
npm package: @pinejs/ng-app
Description: This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.
Latest version: 2.0.0

# NgApp

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.

## Code scaffolding

Run `ng generate component component-name --project ng-app` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-app`.
> Note: Don't forget to add `--project ng-app` or else it will be added to the default project in your `angular.json` file. 

## Build

Run `ng build ng-app` to build the project. The build artifacts will be stored in the `dist/` directory.

## Publishing

After building your library with `ng build ng-app`, go to the dist folder `cd dist/ng-app` and run `npm publish`.

## Running unit tests

Run `ng test ng-app` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
npm package: @pinejs/ng-auth
Description: This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.
Latest version: 1.0.11

# NgAuth

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.

## Code scaffolding

Run `ng generate component component-name --project ng-auth` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-auth`.
> Note: Don't forget to add `--project ng-auth` or else it will be added to the default project in your `angular.json` file. 

## Build

Run `ng build ng-auth` to build the project. The build artifacts will be stored in the `dist/` directory.

## Publishing

After building your library with `ng build ng-auth`, go to the dist folder `cd dist/ng-auth` and run `npm publish`.

## Running unit tests

Run `ng test ng-auth` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
npm package: @pinejs/ng-common
Description: This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.
Latest version: 0.3.2

# NgCommon

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.0.

## Code scaffolding

Run `ng generate component component-name --project ng-common` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-common`.
> Note: Don't forget to add `--project ng-common` or else it will be added to the default project in your `angular.json` file. 

## Build

Run `ng build ng-common` to build the project. The build artifacts will be stored in the `dist/` directory.

## Publishing

After building your library with `ng build ng-common`, go to the dist folder `cd dist/ng-common` and run `npm publish`.

## Running unit tests

Run `ng test ng-common` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
npm package: @pinejs/ng-styles
Description: Provides common material-related styles for Pine.JS frontends
Latest version: 0.3.7

# Pine.JS / Angular styles

Provides common material-related styles for Pine.JS frontends

## _pine_colors.scss
Contains full Material Design color palette 

## _pine_defaults.scss
Contains some generally useful style defaults 

## _pine_material.scss
Contains some material-specific style defaults 

## _pine_mixins.scss
Contains common layout mixins 

## _pine_variables.scss
Contains common size variables
npm package: @pinelab/remote-asset-downloader
Description: Utility to download assets from remote servers and store locally for static site builds.
Author: Martijn van de Brug
Latest version: 0.1.0

# Remote Asset Downloader

This util helps you download assets from a remote source to your local filesystem. We, at Pinelab, use it primarily to download transformed and optimized assets from Vendure and Directus for our static sites.

```ts
import { RemoteAssetDownloader } from '@pinelab/remote-asset-downloader';
const asssetDownloader = new RemoteAssetDownloader({
  publicAssetDirectory: './static/', // "static" is the folder where images should remain in Gridsome for example
  subDirectory: '/img/', // The subdirectory can be anything you want
  cacheDirectory: './node_modules/.cache', // The cache directory is used to store the downloaded assets. Netlify caches node_modules by default
  getRemoteUrl: (assetId) => `${directusUrl}/assets/${assetId}`,
  downloadRemoteAsset: true,
});

// This example creates two new properties on a project: "project.featured_image.small"
// and "project.featured_image.medium"
for (const project of projects) {
  const mediumImage = await asssetDownloader.getAsset(
    project.featured_image.id,
    {
      // Download the preset `medium-webp` which is configure in Directus
      fileName: `${project.title}_medium.webp`,
      transformationArguments: '?key=medium-webp',
    }
  );
  project.featured_image.medium = mediumImage;
  const smallImage = await asssetDownloader.getAsset(
    project.featured_image.id,
    {
      fileName: `${project.title}_small.webp`,
      transformationArguments: '?key=small-webp',
    }
  );
  project.featured_image.small = smallImage;
}
```

## AstroJS Example

For use with Astro JS, you would use `/public/` instead of `/static/`:

```ts
const asssetDownloader = new RemoteAssetDownloader({
  publicAssetDirectory: './public/',
  subDirectory: '/img/',
  cacheDirectory: './node_modules/.cache' // Astro should be caching this dir
  getRemoteUrl: (assetId) => `https://your-directus.io/assets/${assetId}`,
  // Or process.env.NODE_ENV === 'production' to only download in production
  downloadRemoteAsset: true,
});
```

With Astro, the copying of files from `public` to `dist` happens before the JS build, so you need to manually copy the downloaded files to dist after build: `npm run build && cp -r public/* dist/`
npm package: @pinelab/vendure-plugin-admin-social-auth
Description: Plugin to allow authentication for administrators with socials like Google
Author: Martijn van de Brug
Latest version: 2.2.0

# Vendure Social Authentication for Administrators

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-admin-social-auth)

Allow admins to login with social accounts like Google.

> **Note:** This plugin (v2.0.0+) only works with the React Dashboard. For the Angular Admin UI, use [v1.4.0](https://www.npmjs.com/package/@pinelab/vendure-plugin-admin-social-auth/v/1.4.0).

The plugin setup allows for easy extension of other auth providers. Contributions welcome: Contact us via Discord or Github and we'll help you get started on contributing.

You will be able to login if an administrator with your email address already exists in Vendure. Roles and permissions are still handled in Vendure. This plugin disables the native authentication method, so you will only be able to login via Google.

![image](https://plugins.pinelab.studio/plugin-images/admin-google.png)

## Set up Google login

First, you need to get your Google Client id using these steps: https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid.
This should give you a client id that looks something like `xxxxx.apps.googleusercontent.com`

1. Install `google-auth-library`: `npm install google-auth-library`

2. In your `vendure-config.ts`, add the plugin:

```ts
import { AdminSocialAuthPlugin } from '@pinelab/vendure-plugin-admin-social-auth';

...
plugins: [
      AdminSocialAuthPlugin.init({
        google: {
          oAuthClientId: process.env.GOOGLE_OAUTH_CLIENT_ID!,
        },
      }),
]
```

3. Run `npx vite build`

4. Start the server and navigate to `localhost:3000/dashboard/`
5. Login with your Google account
6. If an administrator exists with the same email address, you will be redirected to your dashboard.

## Managing administrators

Administrators are managed via the default Vendure Admin UI. Just create an administrator with the same email address as the social account.
When an admin logs in with a social account for the first time, the social auth method will be added to the `user.authenticationMethods`.
npm package: @pinelab/vendure-plugin-admin-ui-helpers
Description: Vendure plugin for various admin ui helpers. Cancel button, complete order button etc.
Author: Martijn van de Brug
Latest version: 1.5.0

# Admin UI helper buttons for Vendure

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-admin-ui-helpers)

Cancel and complete order buttons for easier completion and cancellation of orders.

## Getting started

Add the buttons you want to the AdminUiPlugin config:

```ts
import {
  cancelOrderButton,
  completeOrderButton,
} from '@pinelab/vendure-plugin-admin-ui-helpers';

AdminUiPlugin.init({
  port: 3002,
  route: 'admin',
  app: compileUiExtensions({
    outputPath: path.join(__dirname, '__admin-ui'),
    extensions: [
      /**
       * Adds a 'Complete order' to the order detail overview.
       * This transitions the order to the `Delivered` state.
       */
      completeOrderButton,
      /**
       * Adds a 'Cancel order' to the order detail overview.
       * Cancels and refunds the order.
       */
      cancelOrderButton,
    ],
  }),
});
```
npm package: @pinelab/vendure-plugin-anonymized-order
Description: This plugin facilitates the retrieval of anonymized customer orders
Author: Surafel Tariku
Latest version: 1.5.0

# Vendure Anonymized Order

This plugin enables the retrieval of an anonymized customer order. By default, the `anonymizedOrder` query omits the fields `customer`, `billingAddress`, and `shippingAddress` from the order details. However, users have the flexibility to further customize this process by adding a callback, allowing the removal of additional fields as needed.

## Getting started

Add the plugin to your config:

```ts
import { AnonymizedOrderPlugin } from '@pinelab/vendure-plugin-anonymized-order';
plugins: [AnonymizedOrderPlugin.init({})];
```

## Displaying placed order without requiring the customer to log in

The `anonymizedOrder` query can be used to display a customers' placed order permanently, instead of for a limited time only, like the built-in `orderByCode` query. This can be used to show a placed order via a link in email for example.

In the order confirmation email, you could have a link like `https://my-storefront.io/order/GX83VCD73?emailAddress=the-customer@email.com`. On your storefront, you'd then use the following query to display the order:

```graphql
    anonymizedOrder(orderCode: "GX83VCD73", emailAddress: "the-customer@email.com") {
      id
      code
      totalWithTax
      lines {
        id
        linePriceWithTax
      }
    }
```

This will then return the order without `shippingAddress`, `billingAddress` and `customer` fields.

## Customizing what data is removed

You can supply your own strategy for anonymizing a given order. In that case, **the plugin will not remove any data from the order** for you.

The example below will only remove the customer, but still expose shipping and billing address:

```ts
import { AnonymizedOrderPlugin } from '@pinelab/vendure-plugin-anonymized-order';
plugins: [
  AnonymizedOrderPlugin.init({
    anonymizeOrderFn: (order) => {
      order.customer = {};
    },
  }),
];
```

You should be cautious about what to return, because of the relational nature of GraphQL. For example, exposing the `order.customer`, will also allow the client to query `order.customer.orders`, thus exposing all orders of that customer.
npm package: @pinelab/vendure-plugin-campaign-tracker
Description: Compare different campaign and ads sources with server side revenue tracking.
Author: Martijn van de Brug
Latest version: 0.1.0

# Vendure Campaign Tracker plugin

### [Official documentation here](https://pinelab-plugins.com/plugin/vendure-plugin-campaign-tracker)

Vendure plugin to track revenue per campaign server side, so that you can compare different campaigns from different sources.
To track campaigns:

- Create a campaign via the Vendure admin UI
- Pass the created campaign code in the url, e.g. `my-website.com?ref=summer-sale-ad`. This URL is then included in your ads or email campaigns.
- Make your storefront send the campaign code to Vendure with the `addCampaign` mutation

![image](https://pinelab-plugins.com/plugin-images/campaigns.jpeg)

## Getting started

Add the plugin to your `vendure-config.ts`

```ts
import { CampaignTrackerPlugin, LastInteractionAttribution } from '@pinelab/vendure-plugin-campaign-tracker';

...
plugins: [
  CampaignTrackerPlugin.init({
    // Pick an attribution model. Choose from `LastInteractionAttribution`, `FirstInteractionAttribution`, `LinearAttribution`
    // Or, implement your own by implementing the AttributionModel interface.
    // See JsDoc of each model for more information
    attributionModel: new LastInteractionAttribution()
  }),
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [
        CampaignTrackerPlugin.ui,
        ... // your other plugin UI extensions
      ],
    }),
  }),
... // your other plugins
]
```

1. Run a database migration.
2. Rebuild the admin UI
3. Start Vendure, and navigate to 'Campaign' (below Promotions)
4. Create a campaign, e.g. `my-first-campaign`.
5. Make sure that every page on your storefront includes the following code:

```ts
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
const ref = params.get('ref');

const activeOrder = await yourGraphqlClient.query(
  gql`
    mutation addCampaignToOrder($campaignCode: String!) {
      addCampaignToOrder(campaignCode: $campaignCode) {
        id
        code
        total
      }
    }
  `,
  { campaignCode: ref }
);
```

This will add any visits to your website with `?ref=my-first-campaign` campaign to the order. This mutation will create a new active order if none exists yet.

If `my-first-campaign` doesn't exists as campaign in Vendure, the call is ignored and no active order is returned (or created).
npm package: @pinelab/vendure-plugin-change-order-customer
Description: This plugin allows you to change the customer of an order
Author: Surafel Tariku
Latest version: 1.1.0
Deprecated: This functionality is now included in Vendure core

# Change Order Customer Plugin

### [Official documentation here](https://pinelab-plugins.com/plugin/vendure-plugin-change-order-customer)

This plugin allows you to change the customer of an order. This can be useful for when a customer accidentally used a wrong email address for example.

![image](https://pinelab-plugins.com/plugin-images/set-customer-for-order.png)

## Getting started

Add this plugin to your list of plugins in your `vendure-config.ts`

```ts
import { ChangeOrderCustomerPlugin } from '@pinelab/vendure-plugin-change-order-customer';

plugins: [
  ...ChangeOrderCustomerPlugin,
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [ChangeOrderCustomerPlugin.ui],
    }),
  }),
];
```

## Caveats

1. The plugin just assigns the new customer to the order, no re-applying promotions or recalculating of any prices. This could mean that promotions stay applied to the order that are actually not valid for the new customer.
2. The plugin only assigns the customer, it doesn't change the shipping address or billing address.
npm package: @pinelab/vendure-plugin-coinbase
Description: Vendure plugin for Coinbase payments
Author: Martijn van de Brug
Latest version: 1.5.0

# Vendure Coinbase plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-coinbase)

Accept crypto payments via Coinbase Commerce in Vendure.

## Getting started

Add the plugin to your `vendure-config.ts`:

```ts
import { CoinbasePlugin } from "@pinelab/vendure-plugin-coinbase"


plugins: [
  CoinbasePlugin,
  ...
  ];
```

### 2. Set API key in Vendure

1. Start your server
2. Go to the Admin UI > Settings > Payment methods and add a payment method with handler `coinbase-payment-handler`
3. Set your Coinbase API key. You can find your API key at https://beta.commerce.coinbase.com/settings/security
4. Set your desired storefront redirectUrl, something like `https://storefront/order/`. Your customer will be redirected
   to this page + order code: `https://storefront/order/897HH7HG7`
5. Save the payment method

### 3. Set webhook in Coinbase

1. Go to https://beta.commerce.coinbase.com/settings/notifications
2. Add a new webhook with endpoint `https://<your-vendure-server>/payments/coinbase`

### 4. Storefront usage

You can now call the mutation `createCoinbasePaymentIntent` to get a redirectUrl to the Coinbase hosted checkout page.
You can redirect your customer to this URL, so your customer can continue making a payment on the Coinbase platform.
After payment the customer will be redirected to `https://storefront/order/897HH7HG7`

## Notes

- Orders are NOT transitioned to `PaymentSettled` directly after Coinbase redirects the customer to the confirmation page, because
  crypto transactions can take some time to confirm. You should notify your customer with a message that the order will be
  handled when their transaction is confirmed. This can take a few minutes.

- Refunds are not supported. If you want to refund a payment done via Coinbase you need to manually do so. This plugin will not do refunds via
  Coinbase.
npm package: @pinelab/vendure-plugin-e-boekhouden
Description: Vendure plugin for integration with the e-boekhouden accounting platform
Author: Martijn van de Brug
Latest version: 2.1.0

# Vendure E-boekhouden plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-e-boekhouden)

Plugin for syncing orders to the Dutch accounting platform E-boekhouden.nl.

## Getting started

Send orders to e-Boekhouden as `GeldOntvangen` mutation and configured `account` and `contraAccount` numbers. Creates a
mutation line for each taxrate of the order's tax summary.

1. Add this to your plugin in `vendure-config.ts`:

```ts
import { EboekhoudenPlugin } from '@pinelab/vendure-plugin-e-boekhouden'

plugins: [
  EboekhoudenPlugin.init({
    getTaxCode: (ctx, order, taxRate) => {
      if (order.customFields.VatID && taxRate == 0) {
        return 'VERL_VERK'; // Reverse charge for EU sales
      } else if (taxRate == 21) {
        return 'HOOG_VERK_21';
      } else if (taxRate == 9) {
        return 'LAAG_VERK_9';
      } else {
        Logger.error(`Unknown tax rate ${taxRate} for order ${order.code}`);
        return 'GEEN';
      }
    },
  }),
  ...
]
```

2. Run a database migration to add the config entity to your database.
3. Add this plugin to the Vendure admin ui plugin to add the configuration screen to Vendure.

```ts
plugins: [
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [EboekhoudenPlugin.ui],
    }),
  }),
];
```

You can read more about Admin UI compilation in the Vendure
[docs](https://www.vendure.io/docs/plugins/extending-the-admin-ui/#compiling-as-a-deployment-step)

4. Start the server and set your credentials via `Settings > E-boekhouden`

### Development - generate new client

1. Go to https://soap.e-boekhouden.nl/soap.asmx?wsdl and save the wsdl file in `src/client/e-boekhouden-wsdl.xml`.
2. Run `yarn generate-soap-client`.
3. `src/client` will now have an updated and typed soap client for e-Boekhouden.
npm package: @pinelab/vendure-plugin-facet-suggestions
Description: A vendure plugin that allows you to define suggested facets for all products, or suggested facets based on other facets.
Author: Surafel Tariku
Latest version: 1.4.0

# Vendure Facets Suggestion Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-facet-suggestions)

This plugin allows you to define facets that will show as suggestions on a product detail page. You can set facets to always show on every product detail, or dependant on other facet values.
This feature is based on one of [Michael Bromley's (Co-founder of Vendure) tutorials](https://www.youtube.com/watch?v=nfIlBvbMcJ8).

![image](https://plugins.pinelab.studio/plugin-images/facet-suggestions_product-detail.png)

## Getting started

1. Add the plugin to your `vendure-config.ts`:

```ts
    ...
     plugins: [
      FacetSuggestionsPlugin,
      AdminUiPlugin.init({
        port: 3002,
        route: 'admin',
        app: compileUiExtensions({
          outputPath: path.join(__dirname, '__admin-ui'),
          extensions: [FacetSuggestionsPlugin.ui],
        }),
      }),
    ...
     ]
     ...
```

2. Run a DB migration to add the new custom fields: https://docs.vendure.io/guides/developer-guide/migrations/#migration-workflow
3. Start the server and login to the admin UI and go to `facets`
4. On the facet detail page, check the box `Show on product detail page`
5. Update the facet
6. Go to a product detail page
7. You should now see a facet value selector for your facet right below the name/description block

There are two ways to show facets on the product detail page:

1. `Show on product detail page` - Always show for every product
2. `Show if product has facets` - Only show if a product already has selected facets. For example, you can use this to create product types: "If product has `category:laptop`, it should also have a facet value from the `memory` facet"
npm package: @pinelab/vendure-plugin-frequently-bought-together
Description: Increase average order value by suggesting frequently bought together products based on past orders. Also known as related products or product recommendations.
Author: Martijn van de Brug
Latest version: 0.0.2

# Frequently Bought Together Plugin

### [Official documentation here](https://pinelab-plugins.com/plugin/vendure-plugin-frequently-bought-together)
npm package: @pinelab/vendure-plugin-google-sheet-loader
Description: Vendure plugin for loading data from a Google Sheet
Author: Martijn van de Brug
Latest version: 1.1.0

# Vendure Google Sheet Loader plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-google-sheet-loader)

This plugin allows you to load data from a Google Sheet and handle the data in Vendure. For example, to load products and prices into Vendure.
You can define a single action per channel. This means each channel can have it's own sheet, and it's own way of handling the data from that sheet.

## Getting started

You need to have a Google API key to use this plugin. You can get one [here](https://support.google.com/googleapi/answer/6158862?hl=en).

1. Add this to your plugin in `vendure-config.ts`:

```ts
import { GoogleSheetLoaderPlugin } from '@pinelab/vendure-plugin-google-sheet-loader';

plugins: [
  GoogleSheetLoaderPlugin.init({
    strategies: [new MyDataLoadingStrategy()],
    googleApiKey: 'test-api-key',
  }),
  ...
]
```

2. Add this plugin to your Admin UI and compile.

```ts
plugins: [
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [GoogleSheetLoaderPlugin.ui],
    }),
  }),
];
```

Read more about Admin UI compilation in the Vendure
[docs](https://www.vendure.io/docs/plugins/extending-the-admin-ui/#compiling-as-a-deployment-step)

Before you can use this plugin, you need to implement your own data loading strategy. This strategy determines what will be done with the data from the sheet.

```ts
import { RequestContext, Injector } from '@vendure/core';
import {
  GoogleSheetDataStrategy,
  SheetContent,
} from '@pinelab/vendure-plugin-google-sheet-loader';

export class MyDataLoadingStrategy implements GoogleSheetDataStrategy {
  code = 'MyDataLoadingStrategy';

  getSheetMetadata() {
    return {
      sheets: ['My tab'],
      spreadSheetId: '1gqZpM-Ksxc-xxKJAKNALAFNLLkksdalakml',
    };
  }

  validateSheetData(
    ctx: RequestContext,
    sheets: SheetContent[]
  ): boolean | string {
    // Single sheet example
    const sheet = sheets[0];
    const headerRow = sheet.data[0];
    if (headerRow[0] !== 'My Header Column') {
      return 'Expected "My Header Column" for column 1';
    }
    return true;
  }

  async handleSheetData(
    ctx: RequestContext,
    injector: Injector,
    sheets: SheetContent[]
  ): Promise<string> {
    // Do whatever you want with the data here
    // This part is executed in the worker
    return `Successfully processed ${sheets[0].data.length} rows`;
  }
}
```

## How it works

When the data loading is triggered from the product overview page in the admin UI, the plugin will:

1. Get the sheet metadata from the strategy
2. Fetch the content of the sheets
3. Validate the data, and give feedback to the admin user
4. If valid, a job will be created to handle the data
npm package: @pinelab/vendure-plugin-limit-variant-per-order
Description: Vendure plugin to limit the amount of a specific product that can be ordered, or only allow purchases in bulk
Author: Martijn van de Brug
Latest version: 2.2.0

# Vendure Plugin for limiting the amount of specific product variants per order

### [Official documentation here](https://pinelab-plugins.com/plugin/vendure-plugin-limit-product-per-order)

This plugin allows you to:

1. Limit the amount of a specific product variant per order. I.E. A customer is only allowed to
   buy 1 of product "Limited art t-shirt X" per order.
2. Only allow a product to be purchased in multiples of X. E.g. only per 4.

## Getting started

1. Add the following config to your `vendure-config.ts`:

```ts
plugins: [LimitVariantPerOrderPlugin];
```

2. Start Vendure, login and go to the product you want to limit.
3. Set the custom field `Maximum amount per order` and `Multiple of per order` on a variant and update the product
4. Customers can now only buy X amount of the variant per order. The same customer can still order the product again in
   a new order.
npm package: @pinelab/vendure-plugin-limited-products
Description: Limit the maximum quantity of a product that can be ordered at a time, or require that purchases be made in bulk quantities, such as in multiples of 6 items.
Author: Martijn van de Brug
Latest version: 3.3.0

# Vendure Limited Products Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-limit-product-per-order)

This plugin allows you to:

1. Limit the amount of a specific product per order. I.E. A customer is only allowed to
   buy 1 of product "Limited art t-shirt X" per order.
2. Only allow a product to be purchased in multiples of X. E.g. only per 4 items.

## Getting started

1. Add the following config to your `vendure-config.ts`:

```ts
import { LimitedProductsPlugin } from "@pinelab/vendure-plugin-limited-products"

plugins: [
   LimitedProductsPlugin,
   AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [
         // Include the admin UI extensions of this plugin
         LimitedProductsPlugin.uiExtensions
      ],
   }),
];

```

2. Run a database migration to add the custom fields.
3. Start Vendure, login and go to the product you want to limit.
4. Set the custom field `Maximum amount per order` and `Multiple of per order` on a variant and update the product
5. Customers can now only buy X amount of the variant per order. The same customer can still order the product again in
   a new order.

You can fetch `product.limitPurchasePerMultipleOf` and `product.maxQuantityPerOrder` via the Shop API to display messages on your storefront accordingly.

## Migrating to V3.x

V3 removes the fields from the variant and places them on a Product, in a different format. This plugin isn't used much, so there is no migration script available. We do it manually:

1. Back up all values of the variants before installing the plugin.
2. Install V4 of this plugin, and run a database migration.
3. Start the server and set the values on the parent products via the Admin UI
npm package: @pinelab/vendure-plugin-modify-customer-orders
Description: Vendure plugin for converting Active orders to Draft
Author: Martijn van de Brug
Latest version: 1.7.0

# Modify Customer Orders plugin

This plugin allows you to convert an active order from a customer to a Draft order, edit it, and connect it back to the customer.

1. Login as administrator and go to 'Orders' and then the 'Active' tab
2. Click the 'Convert order to Draft'
3. The order can now be edited as admin under 'Drafts'
4. Click `Complete draft` to connect the order as active order to a customer. (This behaviour can be disabled, see `autoAssignDraftOrdersToCustomer` below)

When you connect a Draft order to a customer, the customers existing active order will be made a Draft.

## Getting started

```ts
// vendure-config.ts
import { ModifyCustomerOrdersPlugin } from '@pinelab/vendure-plugin-modify-customer-orders';

plugins: [
  ModifyCustomerOrdersPlugin.init({
    /**
     * Automatically make completed draft orders active orders for the connected customer
     */
    autoAssignDraftOrdersToCustomer: true,
  }),
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [ModifyCustomerOrdersPlugin.ui], // Add the "Convert to draft" button
      devMode: true,
    }),
  }),
];
```
npm package: @pinelab/vendure-plugin-multiserver-db-sessioncache
Description: An implementation of Vendure's SessionCacheStrategy that caches session in the database
Author: Surafel Melese Tariku
Latest version: 1.5.0

# Multi-Server Session Cache Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-multiserver-db-sessioncache)

This plugin implements a multi-server proof session cache, using the existing database as cache. Vendure's built-in (default) InMemoryCache can cause conflicts on multi-server environment, and setting up Redis only for session caching might be overkill for most shops.

## Getting started

Add the plugin to your config:

```ts
plugins: [MultiServerDbSessionCachePlugin];
```
npm package: @pinelab/vendure-plugin-order-cleanup
Description: [Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-order-cleanup)
Latest version: 1.2.0

# Vendure Order Cleanup Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-order-cleanup)

This plugin provides functionality to automatically cleanup orders after a specified delay period. It's useful for scenarios where you want to automatically cleanup orders that haven't been settled after a certain period of time.

This prevents issues with stale orders that have out of stock items in them, or items that are no longer available.

## Getting started

Add the plugin to your `vendure-config.ts`

```ts
import { OrderCleanupPlugin } from '@pinelab/vendure-plugin-order-cleanup';

plugins: [
  OrderCleanupPlugin.init({
    olderThanDays: 30,
  }),
],
```

Manually call `/order-cleanup/trigger` or create a cronjob that periodically calls this endpoint.

- Only deletes up to 10 000 orders per job run
- Only cancels orders that are in `AddingItems`, `Created` or `ArrangingPayment` state
- Check your logs for uncancellable orders. These issues, if any, should be fixed manually, to prevent them from being processed infinitely by this plugin.
npm package: @pinelab/vendure-plugin-order-export
Description: Vendure plugin for exporting orders to a file
Author: Martijn van de Brug
Latest version: 1.6.0

# Vendure Order Export Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-order-export)

This plugin allows administrators to export orders to a file. The default exports orders and their totals to a csv file.
You can implement your own strategy to determine what and how data is exported.

## Getting started

1. Add the server and admin UI extensions in your `vendure-config.ts`

```ts
import { OrderExportPlugin } from '@pinelab/vendure-plugin-order-export';

// Server plugin
plugins: [
  OrderExportPlugin.init({
    // Optionally add your own strategies here
    exportStrategies: [],
  }),
   AdminUiPlugin.init({
      port: 3002,
      route: 'admin',
      app: compileUiExtensions({
         outputPath: path.join(__dirname, '__admin-ui'),
         extensions: [OrderExportPlugin.ui],
      }),
   }),
   ...
];
```

2. Make sure your user has the permission `ExportOrders`
3. After starting your server, you should be able to see the `Export orders` in the menu on the left side, under '
   sales.'
4. Select a date range, select an export strategy and click export!

### Custom export strategies

You can easily implement your own export strategy and pass it to the plugin:

```ts
import { ExportStrategy } from '@pinelab/vendure-plugin-order-export';
import { promises as fs } from 'fs';
import { createObjectCsvWriter } from 'csv-writer';

export class MyCustomExport implements ExportStrategy {
  // Name as shown in the admin UI
  readonly name = 'my-custom-export';
  // Content-type of your export file
  readonly contentType = 'text/csv';
  // File extension of your export file
  readonly fileExtension = 'csv';

  async createExportFile({
    ctx,
    startDate,
    endDate,
    orderService,
  }: ExportInput): Promise<string> {
    const orders = await orderService.findAll(
      ctx,
      {
        filter: {
          orderPlacedAt: {
            between: {
              start: startDate,
              end: endDate,
            },
          },
        },
      },
      ['lines.productVariant']
    );
    // Do your magic with the order data here
    const filePath = '/tmp/your-temp-file.csv';
    const csvWriter = createObjectCsvWriter({ path: filePath });
    await csvWriter.writeRecords({ data: 'your custom data' });
    return filePath;
  }
}
```

Don't forget to add the strategy to your plugin:

```ts
plugins: [
  OrderExportPlugin.init({
    exportStrategies: [new MyCustomExport()],
  }),
];
```
npm package: @pinelab/vendure-plugin-payment-extensions
Description: Vendure plugin for allowing customers to 'pay' for an order without actually paying
Author: Martijn van de Brug
Latest version: 0.3.0

# Vendure Payment Extensions

## [Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-payment-extensions)

This `Vendure` plugin allows an `Order` to be settled without upfront payment.

- `isCustomerInGroupPaymentChecker`: Verifies if the customer attached to an order belongs to a specified group to allow configured payment method.
- `settleWithoutPaymentHandler`: This handler simply transitions the `Payment` to settled state.

Have a payment extension in mind? Create a Pull Request on our repository and we will maintain your feature in this plugin!

## Getting started

1. Add the plugin to your `vendure-config.ts`

```ts
import { PaymentExtensionsPlugin } from '@pinelab/vendure-plugin-payment-extensions';

...
plugins: [
  PaymentExtensionsPlugin
... // your other plugins
]

```

2. Start Vendure, log in, and navigate to Settings > Payment Methods
3. Choose `isCustomerInGroupPaymentChecker` as the `Payment eligibility checker`, and then select the `CustomerGroup` whose members are expected to be eligible for this `PaymentMethod`.

4. Choose `settleWithoutPaymentHandler` as `Payment handler`
5. Click `Save`

### Test the plugin

1. Place a test order. The `PaymentMethod` you created in the `Getting Started` section should be listed under `eligiblePaymentMethods` for `Customers` who belong to the designated `CustomerGroup`. For other customers, it should not be available.
npm package: @pinelab/vendure-plugin-picklist
Description: Vendure plugin that provides picklists per order that won't be saved in the database
Author: Surafel Tariku
Latest version: 1.3.0
Deprecated: Moved to @pinelab/vendure-plugin-order-pdfs

# Vendure Picklist Plugin

A plugin for generating PDF picklists for orders.

## Getting started

Add the following config to your `vendure-config.ts`:

```ts
import {PicklistPlugin} from '@pinelab/vendure-plugin-picklist';
    plugins: [
        PicklistPlugin,
        AdminUiPlugin.init({
            port: 3002,
            route: 'admin',
            app: compileUiExtensions({
            outputPath: path.join(__dirname, '__admin-ui'),
            extensions: [
                PicklistPlugin.ui
            ],
        }),
        }),
    ],
```

## Increase picklist template DB storage

By default, the plugin uses TypeOrm's `text` to store the template in the DB. This might not be enough, for example when you'd like to add base64 encoded images to your picklists. This will result in the error `ER_DATA_TOO_LONG: Data too long for column 'templateString'`. You can specify your DB engine with an env variable, and the plugin will resolve the correct column type:

```shell
# E.g. For mysql the column type 'longtext' will be used, which supports up to 4gb
PICKLISTS_PLUGIN_DB_ENGINE=mysql
```
npm package: @pinelab/vendure-plugin-primary-collection
Description: Adds a primary collection to all Products by extending Vendure's graphql api
Author: Surafel Melese Tariku
Latest version: 2.3.0

# Vendure Primary Collection Plugin

[Official documentation here](https://plugins.pinelab.studio/plugin/vendure-plugin-primary-collection)

To construct breadcrumbs and URL's it's useful to have a primary collection for each product, in case a product is part of multiple collections. This plugin extends Vendure's `Product` graphql type, adding a `primaryCollection` field that points to the primary collection of a product.

Primary collections can be selected in the Admin UI's product detail view.

This Plugin also exports `PrimaryCollectionHelperService` which can be used to assign `primaryCollection`'s to products without existing values by running `PrimaryCollectionHelperService.setPrimaryCollectionForAllProducts`.

## Getting started

Add the plugin to your `vendure-config.ts`:

```ts
plugins: [
  PrimaryCollectionPlugin.init({
    customFieldUITabName: 'Primary Collection',
  }),
  AdminUiPlugin.init({
    port: 3002,
    route: 'admin',
    app: compileUiExtensions({
      outputPath: path.join(__dirname, '__admin-ui'),
      extensions: [PrimaryCollectionPlugin.ui],
    }),
  }),
];
```

And your good to go with just that.

## Migrating from `1.6.0` to `2.0.0`

1. Always create a backup of your database
2. Install the plugin and generate a migration
3. In your migration file, add the function `exportCurrentPrimaryCollections(queryRunner)` to the top and `savePrimaryCollection(queryRunner)` to the bottom of the `up` function in your migration file, like so

```ts
import { exportCurrentPrimaryCollections, savePrimaryCollection } from "@pinelab/vendure-plugin-primary-collection";

   public async up(queryRunner: QueryRunner): Promise<any> {
        // add this line
        await exportCurrentPrimaryCollections(queryRunner)
        await queryRunner.query("ALTER TABLE `product` DROP FOREIGN KEY `FK_5e6c3c845407ccaa497eca1a865`", undefined);
        await queryRunner.query("ALTER TABLE `product` CHANGE `customFieldsPrimarycollectionid` `customFieldsPrimarycollection` int NULL", undefined);
        await queryRunner.query("ALTER TABLE `product` DROP COLUMN `customFieldsPrimarycollection`", undefined);
        await queryRunner.query("ALTER TABLE `product` ADD `customFieldsPrimarycollection` varchar(255) NULL", undefined);
        //...and this line
        await savePrimaryCollection(queryRunner)
   }
```

4. Run the migration.