@medusajs/loyalty-plugin 2.22.0-snapshot-20261020204851 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +64 -0
- package/README.md +59 -19
- package/package.json +24 -20
package/AGENTS.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @medusajs/loyalty-plugin
|
|
2
|
+
|
|
3
|
+
An official Medusa plugin that adds gift cards and store credit. It ships two modules (`loyalty`, `store_credit`), module links, admin and store API routes, workflows, workflow hook handlers, a subscriber, and admin UI. It's published from `.medusa/server` only.
|
|
4
|
+
|
|
5
|
+
## Using this package
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @medusajs/loyalty-plugin
|
|
9
|
+
npx medusa db:migrate
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
module.exports = defineConfig({
|
|
14
|
+
plugins: [
|
|
15
|
+
{
|
|
16
|
+
resolve: "@medusajs/loyalty-plugin",
|
|
17
|
+
options: {
|
|
18
|
+
prefix: "GC", // gift card code prefix, default "GIFT"
|
|
19
|
+
sections: 3, // 4-char code sections, default 4
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- Resolve modules by name (`PluginModule` in `src/types/modules.ts`): `container.resolve("loyalty")` (model `GiftCard`, table `loyalty_gift_card`) and `container.resolve("store_credit")` (models `StoreCreditAccount`, `AccountTransaction`).
|
|
27
|
+
- Import workflows from `@medusajs/loyalty-plugin/workflows` and types from `@medusajs/loyalty-plugin/types`. Exported workflows include `createGiftCardsWorkflow`, `updateGiftCardsWorkflow`, `deleteGiftCardWorkflow`, `redeemGiftCardWorkflow`, `claimGiftCardWorkflow`, `createStoreCreditAccountsWorkflow`, `creditAccountsWorkflow`, `debitAccountsWorkflow`, `creditStoreCreditAccountWorkflow`, `debitStoreCreditAccountWorkflow`, `claimStoreCreditAccountWorkflow`, plus the cart workflows (`addGiftCardToCartWorkflow`, `removeGiftCardFromCartWorkflow`, `addStoreCreditsToCartWorkflow`, ...).
|
|
28
|
+
- Store-credit service extras: `creditAccounts`, `debitAccounts`, `retrieveAccountStats({ account_id })` (returns `balance`, `credits`, `debits`). `listStoreCreditAccounts` also fills these fields on each account.
|
|
29
|
+
- Routes:
|
|
30
|
+
- Admin: `/admin/gift-cards`, `/admin/store-credit-accounts` (with `/:id/credit`, `/:id/debit`, `/:id/transactions`).
|
|
31
|
+
- Store: `GET /store/gift-cards/:idOrCode`, `POST|DELETE /store/carts/:id/gift-cards` (`{ code }`), `POST /store/carts/:id/store-credits` (`{ amount? }`, customer auth), `/store/store-credit-accounts` (customer auth) and its `/claim`.
|
|
32
|
+
- Docs: https://docs.medusajs.com/resources/commerce-modules/loyalty.md, https://docs.medusajs.com/resources/commerce-modules/loyalty/module-options.md, https://docs.medusajs.com/resources/commerce-modules/loyalty/gift-cards.md, https://docs.medusajs.com/resources/commerce-modules/loyalty/workflows.md
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
- A gift card is backed by an anonymous store credit account. `createGiftCardsWorkflow` creates the cards, creates and links accounts (`links/gift-card-store-credit.ts`), credits them, and marks the cards `redeemed`. Balances are never stored: they're computed from the transaction ledger.
|
|
37
|
+
- `src/subscribers/create-gift-card.ts`: on `order.placed`, creates one gift card per unit of each line item whose product has `is_giftcard`.
|
|
38
|
+
- `src/workflows/hooks/`: handlers on core hooks: `completeCartWorkflow.hooks.orderCreated` and `.beforePaymentAuthorization`, `createOrderCreditLinesWorkflow.hooks.creditLinesCreated`, `refreshCartItemsWorkflow.hooks.beforeRefreshingPaymentCollection`.
|
|
39
|
+
- `src/links/`: cart and order to gift cards (list links), gift card to store credit account, plus read-only links (account `customer_id` to customer; gift card `line_item_id` to `OrderLineItem`).
|
|
40
|
+
- `src/api/middlewares.ts`: aggregates route middlewares and uses `allowFields` so `gift_cards.*` can be requested on core `/store/carts` and `/store/orders` routes.
|
|
41
|
+
- `src/admin/`: routes (Gift Cards, Gift Card Products, Store Credits) and widgets in `customer.details.side.after`, `order.details.side.after`, and `sales_channel.details.after`.
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
yarn build:plugin # medusa plugin:build -> .medusa/server
|
|
47
|
+
yarn dev # medusa plugin:develop
|
|
48
|
+
yarn test # jest over src
|
|
49
|
+
../../../node_modules/.bin/jest src/utils/__tests__/code-generator.spec.ts
|
|
50
|
+
npx medusa plugin:db:generate # migrations for every src/modules/*; never hand-write them
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Integration tests live in `integration-tests/http/__tests__/loyalty/{admin,store}`; `integration-tests/http/medusa-config.js` registers the plugin. They load the built `.medusa/server` output, so run `yarn build:plugin` before running them.
|
|
54
|
+
- Plugin docs: https://docs.medusajs.com/learn/fundamentals/plugins.md
|
|
55
|
+
|
|
56
|
+
## Gotchas
|
|
57
|
+
|
|
58
|
+
- `jest.config.js` ignores `\\.medusa/` (escaped, because the repo path contains `medusa/`); otherwise the built output gets picked up as duplicate suites.
|
|
59
|
+
- The plugin owns the core hook handlers above. A workflow hook allows only one handler (`Cannot define multiple hook handlers`), so an app using this plugin can't register its own handlers for those hooks.
|
|
60
|
+
- `debitAccounts_` locks the account rows (`SELECT ... FOR UPDATE`, sorted ids) before the balance check to prevent double spend. It throws if called outside a transaction; keep debits inside `@InjectTransactionManager` methods.
|
|
61
|
+
- `deleteTransactions` is a forwarder to the generated `deleteAccountTransactions`. `MedusaService` names methods after the model, so the interface name doesn't exist unless you implement it.
|
|
62
|
+
- `updateStoreCreditAccounts` throws when a key is in its `["id", "metadata"]` whitelist (the check is inverted), so it currently rejects every update. Don't rely on it without fixing it.
|
|
63
|
+
- New store routes must define `allowed` fields in `query-config.ts` using `buildAllowedFields` from `@medusajs/medusa/api/store/utils/allowed-fields` (see `store/gift-cards/query-config.ts`).
|
|
64
|
+
- Source files mix semicolon and no-semicolon styles. Follow the repo prettier config in new code.
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</a>
|
|
9
9
|
</p>
|
|
10
10
|
<h1 align="center">
|
|
11
|
-
|
|
11
|
+
@medusajs/loyalty-plugin
|
|
12
12
|
</h1>
|
|
13
13
|
|
|
14
14
|
<h4 align="center">
|
|
@@ -20,10 +20,12 @@
|
|
|
20
20
|
Building blocks for digital commerce
|
|
21
21
|
</p>
|
|
22
22
|
<p align="center">
|
|
23
|
-
<a href="https://github.com/medusajs/medusa/blob/
|
|
23
|
+
<a href="https://github.com/medusajs/medusa/blob/develop/LICENSE">
|
|
24
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Medusa is released under the MIT license." />
|
|
25
|
+
</a>
|
|
26
|
+
<a href="https://github.com/medusajs/medusa/blob/develop/CONTRIBUTING.md">
|
|
24
27
|
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="PRs welcome!" />
|
|
25
28
|
</a>
|
|
26
|
-
<a href="https://www.producthunt.com/posts/medusa"><img src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-%23DA552E" alt="Product Hunt"></a>
|
|
27
29
|
<a href="https://discord.gg/xpCwq3Kfn8">
|
|
28
30
|
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
|
|
29
31
|
</a>
|
|
@@ -32,31 +34,69 @@
|
|
|
32
34
|
</a>
|
|
33
35
|
</p>
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
Loyalty Plugin for Medusa: adds gift cards and store credit to a Medusa application, including gift card products, redeeming gift cards and store credit at checkout, and store credit accounts for customers. It provides the Loyalty Module and Store Credit Module, Admin and Store API routes, workflows, and Medusa Admin pages. It isn't registered by default: install it and add it to `plugins` in `medusa-config.ts` (Medusa v2.14.0+).
|
|
38
|
+
|
|
39
|
+
## At a glance
|
|
40
|
+
|
|
41
|
+
| | |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| Package | `@medusajs/loyalty-plugin` |
|
|
44
|
+
| Type | Plugin |
|
|
45
|
+
| Modules | Loyalty Module (`"loyalty"`), Store Credit Module (`"store_credit"`) |
|
|
46
|
+
| Registered by default | No |
|
|
47
|
+
| Import from | `@medusajs/loyalty-plugin/workflows`, `@medusajs/loyalty-plugin/types` |
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- **Gift card products**: sell physical or digital gift cards; a gift card with a generated code is created for each one purchased when the order is placed.
|
|
52
|
+
- **Checkout**: apply gift cards and store credit to a cart as payment (`POST /store/carts/:id/gift-cards`, `POST /store/carts/:id/store-credits`).
|
|
53
|
+
- **Store credit accounts**: credit, debit, and view transactions (`/admin/store-credit-accounts`), and let customers view and claim accounts (`/store/store-credit-accounts`).
|
|
54
|
+
- **Admin API routes**: manage gift cards under `/admin/gift-cards`. **Store API routes**: look up a gift card with `GET /store/gift-cards/:idOrCode`.
|
|
55
|
+
- **Workflows** such as `createGiftCardsWorkflow`, `addGiftCardToCartWorkflow`, and `creditStoreCreditAccountWorkflow`, plus hooks into Medusa's cart completion, payment refresh, and order credit line flows.
|
|
56
|
+
- **Medusa Admin**: Gift Cards, Gift Card Products, and Store Credits pages, and widgets on the customer, order, and sales channel details pages.
|
|
36
57
|
|
|
37
|
-
|
|
58
|
+
## Installation
|
|
38
59
|
|
|
39
|
-
|
|
60
|
+
```bash
|
|
61
|
+
npm install @medusajs/loyalty-plugin
|
|
62
|
+
```
|
|
40
63
|
|
|
41
|
-
|
|
64
|
+
## Usage
|
|
42
65
|
|
|
43
|
-
|
|
66
|
+
Register the plugin in `medusa-config.ts`:
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
```ts
|
|
69
|
+
import { defineConfig } from "@medusajs/framework/utils"
|
|
46
70
|
|
|
47
|
-
|
|
71
|
+
module.exports = defineConfig({
|
|
72
|
+
// ...
|
|
73
|
+
plugins: [
|
|
74
|
+
{
|
|
75
|
+
resolve: "@medusajs/loyalty-plugin",
|
|
76
|
+
options: {},
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
})
|
|
80
|
+
```
|
|
48
81
|
|
|
49
|
-
|
|
82
|
+
Then run the migrations:
|
|
50
83
|
|
|
51
|
-
|
|
84
|
+
```bash
|
|
85
|
+
npx medusa db:migrate
|
|
86
|
+
```
|
|
52
87
|
|
|
53
|
-
|
|
88
|
+
## Configuration
|
|
54
89
|
|
|
55
|
-
|
|
90
|
+
| Option | Type | Description | Default |
|
|
91
|
+
| --- | --- | --- | --- |
|
|
92
|
+
| `prefix` | `string` | Prefix of generated gift card codes. For example, `"GC"` generates `GC-XXXX-XXXX-XXXX-XXXX`. | `"GIFT"` |
|
|
93
|
+
| `sections` | `number` | Number of 4-character sections in generated gift card codes. For example, `3` generates `GIFT-XXXX-XXXX-XXXX`. | `4` |
|
|
56
94
|
|
|
57
|
-
##
|
|
95
|
+
## Resources
|
|
58
96
|
|
|
59
|
-
- [
|
|
60
|
-
- [
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
97
|
+
- [Loyalty Module](https://docs.medusajs.com/resources/commerce-modules/loyalty)
|
|
98
|
+
- [Store Credit Module](https://docs.medusajs.com/resources/commerce-modules/store-credit)
|
|
99
|
+
- [Loyalty Plugin options](https://docs.medusajs.com/resources/commerce-modules/loyalty/module-options)
|
|
100
|
+
- [Gift cards](https://docs.medusajs.com/resources/commerce-modules/loyalty/gift-cards)
|
|
101
|
+
- [Loyalty workflows](https://docs.medusajs.com/resources/commerce-modules/loyalty/workflows)
|
|
102
|
+
- [Loyalty user guide](https://docs.medusajs.com/user-guide/loyalty)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@medusajs/loyalty-plugin",
|
|
3
|
-
"version": "2.22.0
|
|
3
|
+
"version": "2.22.0",
|
|
4
4
|
"description": "Medusa Plugin: Loyalty - Gift Cards",
|
|
5
5
|
"author": "Medusa (https://medusajs.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,8 +13,12 @@
|
|
|
13
13
|
"url": "https://github.com/medusajs/medusa/issues"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
".medusa/server"
|
|
16
|
+
".medusa/server",
|
|
17
|
+
"AGENTS.md"
|
|
17
18
|
],
|
|
19
|
+
"llms": "https://docs.medusajs.com/llms.txt",
|
|
20
|
+
"llmsFull": "https://docs.medusajs.com/llms-full.txt",
|
|
21
|
+
"mcpServer": "https://docs.medusajs.com/mcp",
|
|
18
22
|
"exports": {
|
|
19
23
|
"./package.json": "./package.json",
|
|
20
24
|
"./modules/loyalty/*": "./.medusa/server/src/modules/loyalty/index.js",
|
|
@@ -55,16 +59,16 @@
|
|
|
55
59
|
"watch": "medusa plugin:develop"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
58
|
-
"@medusajs/admin-sdk": "2.22.0
|
|
59
|
-
"@medusajs/cli": "2.22.0
|
|
60
|
-
"@medusajs/dashboard": "2.22.0
|
|
61
|
-
"@medusajs/framework": "2.22.0
|
|
62
|
-
"@medusajs/icons": "2.22.0
|
|
63
|
-
"@medusajs/medusa": "2.22.0
|
|
64
|
-
"@medusajs/test-utils": "2.22.0
|
|
65
|
-
"@medusajs/types": "2.22.0
|
|
66
|
-
"@medusajs/ui": "4.2.7
|
|
67
|
-
"@medusajs/ui-preset": "2.22.0
|
|
62
|
+
"@medusajs/admin-sdk": "2.22.0",
|
|
63
|
+
"@medusajs/cli": "2.22.0",
|
|
64
|
+
"@medusajs/dashboard": "2.22.0",
|
|
65
|
+
"@medusajs/framework": "2.22.0",
|
|
66
|
+
"@medusajs/icons": "2.22.0",
|
|
67
|
+
"@medusajs/medusa": "2.22.0",
|
|
68
|
+
"@medusajs/test-utils": "2.22.0",
|
|
69
|
+
"@medusajs/types": "2.22.0",
|
|
70
|
+
"@medusajs/ui": "4.2.7",
|
|
71
|
+
"@medusajs/ui-preset": "2.22.0",
|
|
68
72
|
"@swc/core": "1.5.7",
|
|
69
73
|
"@types/node": "^20.0.0",
|
|
70
74
|
"cross-env": "^7.0.3",
|
|
@@ -72,14 +76,14 @@
|
|
|
72
76
|
"typescript": "^5.7.3"
|
|
73
77
|
},
|
|
74
78
|
"peerDependencies": {
|
|
75
|
-
"@medusajs/admin-sdk": "2.22.0
|
|
76
|
-
"@medusajs/cli": "2.22.0
|
|
77
|
-
"@medusajs/dashboard": "2.22.0
|
|
78
|
-
"@medusajs/framework": "2.22.0
|
|
79
|
-
"@medusajs/icons": "2.22.0
|
|
80
|
-
"@medusajs/medusa": "2.22.0
|
|
81
|
-
"@medusajs/test-utils": "2.22.0
|
|
82
|
-
"@medusajs/ui": "4.2.7
|
|
79
|
+
"@medusajs/admin-sdk": "2.22.0",
|
|
80
|
+
"@medusajs/cli": "2.22.0",
|
|
81
|
+
"@medusajs/dashboard": "2.22.0",
|
|
82
|
+
"@medusajs/framework": "2.22.0",
|
|
83
|
+
"@medusajs/icons": "2.22.0",
|
|
84
|
+
"@medusajs/medusa": "2.22.0",
|
|
85
|
+
"@medusajs/test-utils": "2.22.0",
|
|
86
|
+
"@medusajs/ui": "4.2.7",
|
|
83
87
|
"react": "^18.3.1",
|
|
84
88
|
"react-dom": "^18.3.1",
|
|
85
89
|
"react-router-dom": "^6.30.4 || ^7.0.0"
|