@reorderjs/reorder 1.0.8 → 1.1.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/.medusa/server/e2e/auth.setup.js +26 -0
- package/.medusa/server/e2e/cancellation-retention.spec.js +133 -0
- package/.medusa/server/e2e/pages/CancellationCaseDetailPage.js +69 -0
- package/.medusa/server/e2e/pages/CancellationsListPage.js +34 -0
- package/.medusa/server/e2e/pages/PlanFormPage.js +89 -0
- package/.medusa/server/e2e/pages/RenewalDetailPage.js +101 -0
- package/.medusa/server/e2e/pages/SubscriptionDetailPage.js +102 -0
- package/.medusa/server/e2e/plans-offers.spec.js +96 -0
- package/.medusa/server/e2e/renewal-force.spec.js +154 -0
- package/.medusa/server/e2e/seed.setup.js +80 -0
- package/.medusa/server/e2e/subscription-status.spec.js +109 -0
- package/.medusa/server/e2e/subscriptions-list.spec.js +84 -0
- package/.medusa/server/playwright.config.js +37 -0
- package/.medusa/server/scripts/reset-subscriptions-test-data.js +279 -0
- package/.medusa/server/scripts/seed-subscriptions-test-data.js +2425 -0
- package/.medusa/server/scripts/wipe-test-data.js +44 -0
- package/.medusa/server/src/admin/index.js +11106 -9689
- package/.medusa/server/src/admin/index.mjs +11099 -9682
- package/.medusa/server/src/admin/types/analytics.js +2 -1
- package/.medusa/server/src/api/admin/cancellations/validators.js +2 -2
- package/.medusa/server/src/api/admin/dunning/validators.js +2 -2
- package/.medusa/server/src/api/admin/renewals/validators.js +2 -2
- package/.medusa/server/src/api/admin/subscription-analytics/validators.js +2 -2
- package/.medusa/server/src/api/admin/subscription-logs/validators.js +2 -2
- package/.medusa/server/src/api/admin/subscription-offers/validators.js +2 -2
- package/.medusa/server/src/api/admin/subscription-settings/validators.js +2 -2
- package/.medusa/server/src/api/admin/subscriptions/[id]/payment-method/route.js +19 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/payment-methods/route.js +10 -0
- package/.medusa/server/src/api/admin/subscriptions/middlewares.js +8 -1
- package/.medusa/server/src/api/admin/subscriptions/utils.js +5 -1
- package/.medusa/server/src/api/admin/subscriptions/validators.js +7 -3
- package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-method/route.js +26 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-methods/route.js +15 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/middlewares.js +8 -1
- package/.medusa/server/src/api/store/customers/me/subscriptions/utils.js +72 -1
- package/.medusa/server/src/api/store/customers/me/subscriptions/validators.js +7 -3
- package/.medusa/server/src/api/store/products/validators.js +2 -2
- package/.medusa/server/src/modules/activity-log/__tests__/create-subscription-log-event.spec.js +257 -0
- package/.medusa/server/src/modules/activity-log/__tests__/normalize-log-event.spec.js +231 -0
- package/.medusa/server/src/modules/activity-log/migrations/Migration20260818120000.js +16 -0
- package/.medusa/server/src/modules/activity-log/types/index.js +2 -1
- package/.medusa/server/src/modules/analytics/__tests__/admin-query.spec.js +560 -0
- package/.medusa/server/src/modules/analytics/index.js +2 -2
- package/.medusa/server/src/modules/analytics/utils/admin-query.js +157 -5
- package/.medusa/server/src/modules/plan-offer/__tests__/service.spec.js +94 -0
- package/.medusa/server/src/modules/renewal/__tests__/service.spec.js +89 -0
- package/.medusa/server/src/modules/settings/__tests__/normalize-settings.spec.js +86 -0
- package/.medusa/server/src/modules/settings/__tests__/service.spec.js +124 -0
- package/.medusa/server/src/modules/subscription/__tests__/payment-methods.spec.js +186 -0
- package/.medusa/server/src/modules/subscription/__tests__/service.spec.js +124 -0
- package/.medusa/server/src/modules/subscription/utils/admin-query.js +196 -14
- package/.medusa/server/src/modules/subscription/utils/payment-methods.js +146 -0
- package/.medusa/server/src/workflows/__tests__/cancel-subscription.spec.js +20 -0
- package/.medusa/server/src/workflows/__tests__/pause-subscription.spec.js +20 -0
- package/.medusa/server/src/workflows/__tests__/update-subscription-shipping-address.spec.js +49 -0
- package/.medusa/server/src/workflows/cancel-subscription.js +21 -1
- package/.medusa/server/src/workflows/index.js +6 -2
- package/.medusa/server/src/workflows/pause-subscription.js +21 -1
- package/.medusa/server/src/workflows/steps/rebuild-analytics-daily-snapshots.js +33 -10
- package/.medusa/server/src/workflows/steps/update-subscription-payment-method.js +110 -0
- package/.medusa/server/src/workflows/steps/validate-subscription-cart.js +7 -22
- package/.medusa/server/src/workflows/update-subscription-payment-method.js +65 -0
- package/.medusa/server/src/workflows/utils/analytics-incremental.js +1 -1
- package/README.md +89 -36
- package/package.json +25 -23
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateSubscriptionPaymentMethodWorkflow = void 0;
|
|
4
|
+
exports.toPaymentMethodLogState = toPaymentMethodLogState;
|
|
5
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
6
|
+
const create_subscription_log_event_1 = require("./steps/create-subscription-log-event");
|
|
7
|
+
const update_subscription_payment_method_1 = require("./steps/update-subscription-payment-method");
|
|
8
|
+
const normalize_log_event_1 = require("../modules/activity-log/utils/normalize-log-event");
|
|
9
|
+
const types_1 = require("../modules/activity-log/types");
|
|
10
|
+
const date_output_1 = require("./utils/date-output");
|
|
11
|
+
exports.updateSubscriptionPaymentMethodWorkflow = (0, workflows_sdk_1.createWorkflow)("update-subscription-payment-method", function (input) {
|
|
12
|
+
const subscriptionChange = (0, update_subscription_payment_method_1.updateSubscriptionPaymentMethodStep)(input);
|
|
13
|
+
const logInput = (0, workflows_sdk_1.transform)({ subscriptionChange, input }, function ({ subscriptionChange, input }) {
|
|
14
|
+
return {
|
|
15
|
+
log_event: (0, normalize_log_event_1.normalizeActivityLogEvent)({
|
|
16
|
+
subscription_id: subscriptionChange.current.id,
|
|
17
|
+
customer_id: subscriptionChange.current.customer_id,
|
|
18
|
+
event_type: types_1.ActivityLogEventType.SUBSCRIPTION_PAYMENT_METHOD_UPDATED,
|
|
19
|
+
actor_type: input.actor_type ?? types_1.ActivityLogActorType.USER,
|
|
20
|
+
actor_id: input.triggered_by ?? null,
|
|
21
|
+
display: {
|
|
22
|
+
subscription_reference: subscriptionChange.current.reference,
|
|
23
|
+
customer_name: subscriptionChange.current.customer_snapshot?.full_name ?? null,
|
|
24
|
+
product_title: subscriptionChange.current.product_snapshot?.product_title ?? null,
|
|
25
|
+
variant_title: subscriptionChange.current.product_snapshot?.variant_title ?? null,
|
|
26
|
+
},
|
|
27
|
+
previous_state: toPaymentMethodLogState(subscriptionChange.previous_payment_method),
|
|
28
|
+
new_state: toPaymentMethodLogState(subscriptionChange.current_payment_method),
|
|
29
|
+
metadata: {
|
|
30
|
+
source: input.actor_type === types_1.ActivityLogActorType.CUSTOMER
|
|
31
|
+
? "storefront"
|
|
32
|
+
: "admin",
|
|
33
|
+
},
|
|
34
|
+
dedupe: {
|
|
35
|
+
scope: "subscription",
|
|
36
|
+
target_id: subscriptionChange.current.id,
|
|
37
|
+
qualifier: (0, date_output_1.toISOStringOrNull)(subscriptionChange.current.updated_at),
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
(0, create_subscription_log_event_1.createSubscriptionLogEventStep)(logInput);
|
|
43
|
+
return new workflows_sdk_1.WorkflowResponse({
|
|
44
|
+
subscription: subscriptionChange.current,
|
|
45
|
+
payment_method: subscriptionChange.current_payment_method,
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
exports.default = exports.updateSubscriptionPaymentMethodWorkflow;
|
|
49
|
+
/**
|
|
50
|
+
* Only non-sensitive card identifiers are logged. Raw provider payloads never
|
|
51
|
+
* reach the activity log.
|
|
52
|
+
*/
|
|
53
|
+
function toPaymentMethodLogState(paymentMethod) {
|
|
54
|
+
if (!paymentMethod) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
payment_provider_id: paymentMethod.provider_id,
|
|
59
|
+
brand: paymentMethod.brand,
|
|
60
|
+
last4: paymentMethod.last4,
|
|
61
|
+
exp_month: paymentMethod.exp_month,
|
|
62
|
+
exp_year: paymentMethod.exp_year,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLXN1YnNjcmlwdGlvbi1wYXltZW50LW1ldGhvZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3MvdXBkYXRlLXN1YnNjcmlwdGlvbi1wYXltZW50LW1ldGhvZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFpRkEsMERBY0M7QUEvRkQscUVBSTBDO0FBQzFDLHlGQUFzRjtBQUN0RixtR0FHbUQ7QUFDbkQsMkZBQTZGO0FBQzdGLHlEQUdzQztBQUV0QyxxREFBdUQ7QUFPMUMsUUFBQSx1Q0FBdUMsR0FBRyxJQUFBLDhCQUFjLEVBQ25FLG9DQUFvQyxFQUNwQyxVQUFVLEtBQW1EO0lBQzNELE1BQU0sa0JBQWtCLEdBQUcsSUFBQSx3RUFBbUMsRUFBQyxLQUFLLENBQUMsQ0FBQTtJQUNyRSxNQUFNLFFBQVEsR0FBRyxJQUFBLHlCQUFTLEVBQ3hCLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLEVBQzdCLFVBQVUsRUFBRSxrQkFBa0IsRUFBRSxLQUFLLEVBQUU7UUFDckMsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFBLCtDQUF5QixFQUFDO2dCQUNuQyxlQUFlLEVBQUUsa0JBQWtCLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQzlDLFdBQVcsRUFBRSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsV0FBVztnQkFDbkQsVUFBVSxFQUFFLDRCQUFvQixDQUFDLG1DQUFtQztnQkFDcEUsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLElBQUksNEJBQW9CLENBQUMsSUFBSTtnQkFDekQsUUFBUSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSTtnQkFDcEMsT0FBTyxFQUFFO29CQUNQLHNCQUFzQixFQUFFLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxTQUFTO29CQUM1RCxhQUFhLEVBQ1gsa0JBQWtCLENBQUMsT0FBTyxDQUFDLGlCQUFpQixFQUFFLFNBQVMsSUFBSSxJQUFJO29CQUNqRSxhQUFhLEVBQ1gsa0JBQWtCLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLGFBQWEsSUFBSSxJQUFJO29CQUNwRSxhQUFhLEVBQ1gsa0JBQWtCLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLGFBQWEsSUFBSSxJQUFJO2lCQUNyRTtnQkFDRCxjQUFjLEVBQUUsdUJBQXVCLENBQ3JDLGtCQUFrQixDQUFDLHVCQUF1QixDQUMzQztnQkFDRCxTQUFTLEVBQUUsdUJBQXVCLENBQ2hDLGtCQUFrQixDQUFDLHNCQUFzQixDQUMxQztnQkFDRCxRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLEtBQUssQ0FBQyxVQUFVLEtBQUssNEJBQW9CLENBQUMsUUFBUTt3QkFDeEQsQ0FBQyxDQUFDLFlBQVk7d0JBQ2QsQ0FBQyxDQUFDLE9BQU87aUJBQ1o7Z0JBQ0QsTUFBTSxFQUFFO29CQUNOLEtBQUssRUFBRSxjQUFjO29CQUNyQixTQUFTLEVBQUUsa0JBQWtCLENBQUMsT0FBTyxDQUFDLEVBQUU7b0JBQ3hDLFNBQVMsRUFBRSxJQUFBLCtCQUFpQixFQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7aUJBQ3BFO2FBQ0YsQ0FBQztTQUNILENBQUE7SUFDSCxDQUFDLENBQ0YsQ0FBQTtJQUNELElBQUEsOERBQThCLEVBQUMsUUFBUSxDQUFDLENBQUE7SUFFeEMsT0FBTyxJQUFJLGdDQUFnQixDQUFDO1FBQzFCLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxPQUFPO1FBQ3hDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxzQkFBc0I7S0FDMUQsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFRCxrQkFBZSwrQ0FBdUMsQ0FBQTtBQUV0RDs7O0dBR0c7QUFDSCxTQUFnQix1QkFBdUIsQ0FDckMsYUFBc0Q7SUFFdEQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ25CLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVELE9BQU87UUFDTCxtQkFBbUIsRUFBRSxhQUFhLENBQUMsV0FBVztRQUM5QyxLQUFLLEVBQUUsYUFBYSxDQUFDLEtBQUs7UUFDMUIsS0FBSyxFQUFFLGFBQWEsQ0FBQyxLQUFLO1FBQzFCLFNBQVMsRUFBRSxhQUFhLENBQUMsU0FBUztRQUNsQyxRQUFRLEVBQUUsYUFBYSxDQUFDLFFBQVE7S0FDakMsQ0FBQTtBQUNILENBQUMifQ==
|
|
@@ -21,4 +21,4 @@ function buildAnalyticsIncrementalRebuildInput(input) {
|
|
|
21
21
|
: null,
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl0aWNzLWluY3JlbWVudGFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy91dGlscy9hbmFseXRpY3MtaW5jcmVtZW50YWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFvQ0Esc0ZBZUM7QUFyQ0QsU0FBUyxhQUFhLENBQUMsS0FBdUM7SUFDNUQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQTtJQUVuRCxPQUFPLElBQUksSUFBSSxDQUNiLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FDN0UsQ0FBQTtBQUNILENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxRQUFjO0lBQ2pDLE9BQU8sSUFBSSxJQUFJLENBQ2IsSUFBSSxDQUFDLEdBQUcsQ0FDTixRQUFRLENBQUMsY0FBYyxFQUFFLEVBQ3pCLFFBQVEsQ0FBQyxXQUFXLEVBQUUsRUFDdEIsUUFBUSxDQUFDLFVBQVUsRUFBRSxFQUNyQixFQUFFLEVBQ0YsRUFBRSxFQUNGLEVBQUUsRUFDRixHQUFHLENBQ0osQ0FDRixDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQWdCLHFDQUFxQyxDQUNuRCxLQUE0QztJQUU1QyxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBRWpELE9BQU87UUFDTCxTQUFTLEVBQUUsUUFBUTtRQUNuQixPQUFPLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQztRQUM5QixZQUFZLEVBQUUsYUFBYTtRQUMzQixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxJQUFJO1FBQ3hDLE1BQU0sRUFBRSxLQUFLLENBQUMsY0FBYztRQUM1QixjQUFjLEVBQUUsS0FBSyxDQUFDLGNBQWM7WUFDbEMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLGNBQWMsWUFBWTtZQUNyQyxDQUFDLENBQUMsSUFBSTtLQUNULENBQUE7QUFDSCxDQUFDIn0=
|
package/README.md
CHANGED
|
@@ -1,30 +1,55 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
<img alt="Reorder — Subscriptions for Medusa, done right." src="assets/screenshots/reorder-hero-new.png" />
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Open-source subscription plugin built on standard Medusa primitives</h1>
|
|
6
|
+
|
|
7
|
+
<div align="center">
|
|
8
|
+
<a href="https://medusajs.com/blog/reorder">
|
|
9
|
+
<img alt="Featured on Medusa Blog" src="https://img.shields.io/badge/Featured_on-Medusa_Blog-7C3AED.svg" />
|
|
8
10
|
</a>
|
|
9
|
-
<h1> Open Source Subscription Medusa Plugin </h1>
|
|
10
11
|
<a href="https://github.com/reorder-js/reorder?tab=MIT-1-ov-file">
|
|
11
12
|
<img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg" />
|
|
12
13
|
</a>
|
|
13
14
|
<a href="https://github.com/reorder-js/reorder/issues">
|
|
14
15
|
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="PRs welcome!" />
|
|
15
|
-
|
|
16
|
+
</a>
|
|
17
|
+
<a href="https://www.reorderjs.com/get-started">
|
|
16
18
|
<img alt="Support" src="https://img.shields.io/badge/support-contact%20author-blue.svg" />
|
|
17
19
|
</a>
|
|
18
20
|
</div>
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<div align="center">
|
|
25
|
+
<a href="https://medusajs.com/blog/reorder">
|
|
26
|
+
<img width="800" alt="Nicklas Gellner, Co-founder & COO Medusa — featured on the Medusa Blog" src="assets/screenshots/reorder-social.png" />
|
|
27
|
+
</a>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div align="center">
|
|
33
|
+
<a href="https://www.reorderjs.com">Website</a> ·
|
|
34
|
+
<a href="https://docs.reorderjs.com">Documentation</a> ·
|
|
35
|
+
<a href="https://www.youtube.com/watch?v=KY43_6Q3560">Video Demo</a>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Why Reorder?
|
|
41
|
+
|
|
42
|
+
- **Native Medusa plugin** — built entirely on Medusa modules, workflows, and Admin UI extensions. No second source of truth, no external subscription platform to sync with.
|
|
43
|
+
- **Open-source, MIT licensed** — no revenue cut, no per-transaction fees, no vendor lock-in.
|
|
44
|
+
- **AI-native** — every domain is mapped in `AGENTS.md`, documented with specs, and covered by HTTP integration tests. Designed for agentic development from day one.
|
|
45
|
+
- **Officially featured by Medusa** — recognized by the Medusa team as the reference example of how a Medusa plugin should be built.
|
|
46
|
+
- **Production-ready** — Roastloop launched coffee subscriptions in 7 days using Reorder. [See the full story →](https://medusajs.com/blog/reorder)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
<div align="center">
|
|
51
|
+
<img width="800" alt="Reorder Admin — subscriptions list" src="assets/screenshots/admin-subscriptions.png" />
|
|
52
|
+
</div>
|
|
28
53
|
|
|
29
54
|
|
|
30
55
|
|
|
@@ -40,33 +65,51 @@ It adds recurring commerce capabilities to a Medusa store, including subscriptio
|
|
|
40
65
|
|
|
41
66
|
## What it includes
|
|
42
67
|
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
68
|
+
- **Subscriptions** — Create, pause, resume, skip, and cancel subscriptions, with full lifecycle state tracked in the Admin.
|
|
69
|
+
- **Plans & Offers** — Configure frequencies, per-frequency discounts, trials, and minimum cycle rules per plan.
|
|
70
|
+
- **Renewals** — Scheduler-backed renewal execution with manual override, approval queues, and full attempt history.
|
|
71
|
+
- **Dunning** — Payment retry scheduling with configurable intervals and manual recovery tooling.
|
|
72
|
+
- **Cancellation & Retention** — Pause offers, discounts, and bonuses shown to subscribers before cancellation is final.
|
|
73
|
+
- **Activity Log** — A complete operational history of every subscription event, accessible in the Admin.
|
|
74
|
+
- **Analytics** — MRR, churn rate, LTV, and active subscription counts with filterable trend charts.
|
|
75
|
+
- **Self-service Store APIs** — Subscription checkout, offer selection, and customer portal endpoints for your storefront.
|
|
76
|
+
- **Storefront building blocks** — Cart, checkout, and customer portal integration guides for your own frontend.
|
|
50
77
|
|
|
51
78
|
|
|
52
79
|
|
|
53
|
-
|
|
80
|
+
<div align="center">
|
|
81
|
+
<img width="800" alt="Feature grid — everything the subscription lifecycle needs" src="assets/screenshots/feature-grid.png" />
|
|
82
|
+
</div>
|
|
54
83
|
|
|
55
|
-
|
|
84
|
+
|
|
56
85
|
|
|
57
|
-
|
|
86
|
+
<div align="center">
|
|
87
|
+
<img width="800" alt="Storefront subscribe & save" src="assets/screenshots/storefront-subscribe-save.png" />
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## AI-native
|
|
93
|
+
|
|
94
|
+
Every domain in `Reorder` is mapped in `AGENTS.md` — linking architecture, API contracts, workflow docs, and integration tests so an AI agent reads documented behavior before touching implementation files.
|
|
95
|
+
|
|
96
|
+
<div align="center">
|
|
97
|
+
<img width="800" alt="AI-native — optimized for agentic development" src="assets/screenshots/ai-native.png" />
|
|
98
|
+
</div>
|
|
58
99
|
|
|
59
100
|
|
|
60
101
|
|
|
61
|
-
##
|
|
102
|
+
## Medusa Cloud compatible
|
|
62
103
|
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
104
|
+
`Reorder` is compatible with Medusa Cloud. No self-hosting required — deploy your Medusa project to Medusa Cloud and install the plugin as you would locally.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## Current scope
|
|
109
|
+
|
|
110
|
+
`Reorder` currently focuses on recurring commerce operations managed from the Medusa Admin.
|
|
111
|
+
|
|
112
|
+
Today, the plugin provides strong Admin coverage across the implemented domains. Customer self-service flows will be introduced in the near future as a `Reorder Subscription Starter`.
|
|
70
113
|
|
|
71
114
|
|
|
72
115
|
|
|
@@ -104,13 +147,13 @@ plugins: [
|
|
|
104
147
|
|
|
105
148
|
With `npm`:
|
|
106
149
|
|
|
107
|
-
```bash
|
|
150
|
+
```bash
|
|
108
151
|
npx medusa db:migrate
|
|
109
152
|
```
|
|
110
153
|
|
|
111
154
|
With `yarn`:
|
|
112
155
|
|
|
113
|
-
```bash
|
|
156
|
+
```bash
|
|
114
157
|
yarn medusa db:migrate
|
|
115
158
|
```
|
|
116
159
|
|
|
@@ -118,6 +161,8 @@ yarn medusa db:migrate
|
|
|
118
161
|
|
|
119
162
|
After adding the plugin, run your normal Medusa setup flow in your store project.
|
|
120
163
|
|
|
164
|
+
|
|
165
|
+
|
|
121
166
|
## Local development
|
|
122
167
|
|
|
123
168
|
If you want to work on the plugin itself locally:
|
|
@@ -192,6 +237,14 @@ yarn dev
|
|
|
192
237
|
|
|
193
238
|
|
|
194
239
|
|
|
240
|
+
## Community & Support
|
|
241
|
+
|
|
242
|
+
- **GitHub Issues** — bug reports and feature requests: [github.com/reorder-js/reorder/issues](https://github.com/reorder-js/reorder/issues)
|
|
243
|
+
- **GitHub Discussions** — questions, ideas, and general help: [github.com/reorder-js/reorder/discussions](https://github.com/reorder-js/reorder/discussions)
|
|
244
|
+
- **Contact** — reach the author directly at [reorderjs.com/get-started](https://www.reorderjs.com/get-started)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
195
248
|
## Documentation
|
|
196
249
|
|
|
197
250
|
Project documentation lives in `docs/`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reorderjs/reorder",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Open Source Subscription Medusa Plugin.",
|
|
5
5
|
"author": "Reorder (https://reorderjs.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,43 +32,45 @@
|
|
|
32
32
|
"build": "medusa plugin:build",
|
|
33
33
|
"dev": "medusa plugin:develop",
|
|
34
34
|
"prepublishOnly": "medusa plugin:build",
|
|
35
|
-
"test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --
|
|
36
|
-
"test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit"
|
|
35
|
+
"test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --maxWorkers=2 --forceExit",
|
|
36
|
+
"test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
|
|
37
|
+
"test:e2e": "npx playwright test"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@medusajs/admin-sdk": "2.
|
|
40
|
-
"@medusajs/cli": "2.
|
|
41
|
-
"@medusajs/framework": "2.
|
|
42
|
-
"@medusajs/icons": "2.
|
|
43
|
-
"@medusajs/medusa": "2.
|
|
44
|
-
"@medusajs/test-utils": "2.
|
|
45
|
-
"@medusajs/ui": "4.
|
|
40
|
+
"@medusajs/admin-sdk": "2.19.0",
|
|
41
|
+
"@medusajs/cli": "2.19.0",
|
|
42
|
+
"@medusajs/framework": "2.19.0",
|
|
43
|
+
"@medusajs/icons": "2.19.0",
|
|
44
|
+
"@medusajs/medusa": "2.19.0",
|
|
45
|
+
"@medusajs/test-utils": "2.19.0",
|
|
46
|
+
"@medusajs/ui": "4.2.1",
|
|
47
|
+
"@playwright/test": "^1.62.1",
|
|
46
48
|
"@swc/core": "^1.7.28",
|
|
47
49
|
"@swc/jest": "^0.2.39",
|
|
48
50
|
"@types/jest": "^29.5.14",
|
|
49
|
-
"@types/node": "^20.
|
|
51
|
+
"@types/node": "^20.19.0",
|
|
50
52
|
"@types/react": "^18.3.2",
|
|
51
|
-
"@types/react-dom": "^18.
|
|
53
|
+
"@types/react-dom": "^18.3.0",
|
|
52
54
|
"jest": "^29.7.0",
|
|
53
55
|
"prop-types": "^15.8.1",
|
|
54
|
-
"react": "^18.
|
|
55
|
-
"react-dom": "^18.
|
|
56
|
+
"react": "^18.3.1",
|
|
57
|
+
"react-dom": "^18.3.1",
|
|
56
58
|
"ts-node": "^10.9.2",
|
|
57
59
|
"typescript": "^5.6.2",
|
|
58
|
-
"vite": "^
|
|
60
|
+
"vite": "^7.3.6",
|
|
59
61
|
"yalc": "^1.0.0-pre.53"
|
|
60
62
|
},
|
|
61
63
|
"peerDependencies": {
|
|
62
|
-
"@medusajs/admin-sdk": "2.
|
|
63
|
-
"@medusajs/cli": "2.
|
|
64
|
-
"@medusajs/framework": "2.
|
|
65
|
-
"@medusajs/icons": "2.
|
|
66
|
-
"@medusajs/medusa": "2.
|
|
67
|
-
"@medusajs/test-utils": "2.
|
|
68
|
-
"@medusajs/ui": "4.
|
|
64
|
+
"@medusajs/admin-sdk": "2.19.0",
|
|
65
|
+
"@medusajs/cli": "2.19.0",
|
|
66
|
+
"@medusajs/framework": "2.19.0",
|
|
67
|
+
"@medusajs/icons": "2.19.0",
|
|
68
|
+
"@medusajs/medusa": "2.19.0",
|
|
69
|
+
"@medusajs/test-utils": "2.19.0",
|
|
70
|
+
"@medusajs/ui": "4.2.1"
|
|
69
71
|
},
|
|
70
72
|
"engines": {
|
|
71
|
-
"node": ">=
|
|
73
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
72
74
|
},
|
|
73
75
|
"packageManager": "yarn@4.4.1"
|
|
74
76
|
}
|