customer-registration 0.0.3
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/src/admin/index.js +23 -0
- package/.medusa/server/src/admin/index.mjs +24 -0
- package/.medusa/server/src/api/admin/plugin/route.js +7 -0
- package/.medusa/server/src/api/store/customers/route.js +50 -0
- package/.medusa/server/src/api/store/plugin/route.js +7 -0
- package/.medusa/server/src/migrations/Migration20250118000000AddEmailVerifiedColumn.js +21 -0
- package/.medusa/server/src/subscribers/customer-created.js +60 -0
- package/README.md +96 -0
- package/package.json +68 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18nTranslations0 = {};
|
|
3
|
+
const widgetModule = { widgets: [] };
|
|
4
|
+
const routeModule = {
|
|
5
|
+
routes: []
|
|
6
|
+
};
|
|
7
|
+
const menuItemModule = {
|
|
8
|
+
menuItems: []
|
|
9
|
+
};
|
|
10
|
+
const formModule = { customFields: {} };
|
|
11
|
+
const displayModule = {
|
|
12
|
+
displays: {}
|
|
13
|
+
};
|
|
14
|
+
const i18nModule = { resources: i18nTranslations0 };
|
|
15
|
+
const plugin = {
|
|
16
|
+
widgetModule,
|
|
17
|
+
routeModule,
|
|
18
|
+
menuItemModule,
|
|
19
|
+
formModule,
|
|
20
|
+
displayModule,
|
|
21
|
+
i18nModule
|
|
22
|
+
};
|
|
23
|
+
module.exports = plugin;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const i18nTranslations0 = {};
|
|
2
|
+
const widgetModule = { widgets: [] };
|
|
3
|
+
const routeModule = {
|
|
4
|
+
routes: []
|
|
5
|
+
};
|
|
6
|
+
const menuItemModule = {
|
|
7
|
+
menuItems: []
|
|
8
|
+
};
|
|
9
|
+
const formModule = { customFields: {} };
|
|
10
|
+
const displayModule = {
|
|
11
|
+
displays: {}
|
|
12
|
+
};
|
|
13
|
+
const i18nModule = { resources: i18nTranslations0 };
|
|
14
|
+
const plugin = {
|
|
15
|
+
widgetModule,
|
|
16
|
+
routeModule,
|
|
17
|
+
menuItemModule,
|
|
18
|
+
formModule,
|
|
19
|
+
displayModule,
|
|
20
|
+
i18nModule
|
|
21
|
+
};
|
|
22
|
+
export {
|
|
23
|
+
plugin as default
|
|
24
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = GET;
|
|
4
|
+
async function GET(req, res) {
|
|
5
|
+
res.sendStatus(200);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = POST;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
async function POST(req, res) {
|
|
6
|
+
const customerModuleService = req.scope.resolve(utils_1.Modules.CUSTOMER);
|
|
7
|
+
const body = req.body;
|
|
8
|
+
try {
|
|
9
|
+
// Extract customer data from request body
|
|
10
|
+
const { email, first_name, last_name, phone, company_name, metadata, email_verified: _incomingEmailVerified, phone_verified: _incomingPhoneVerified, ...rest } = body;
|
|
11
|
+
// Prepare customer data with verified flags forced to false
|
|
12
|
+
const customerData = {
|
|
13
|
+
...rest,
|
|
14
|
+
email,
|
|
15
|
+
first_name,
|
|
16
|
+
last_name,
|
|
17
|
+
phone,
|
|
18
|
+
company_name,
|
|
19
|
+
metadata: metadata ?? {},
|
|
20
|
+
email_verified: false,
|
|
21
|
+
phone_verified: false,
|
|
22
|
+
};
|
|
23
|
+
// Create the customer using the customer module service
|
|
24
|
+
// createCustomers expects an array
|
|
25
|
+
const customers = await customerModuleService.createCustomers([customerData]);
|
|
26
|
+
const customer = customers[0];
|
|
27
|
+
// Retrieve the created customer to return
|
|
28
|
+
const createdCustomer = await customerModuleService.retrieveCustomer(customer.id);
|
|
29
|
+
// Return the customer in the expected format
|
|
30
|
+
res.status(201).json({
|
|
31
|
+
customer: createdCustomer,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// Handle errors appropriately
|
|
36
|
+
if (error.message?.includes("already exists") || error.message?.includes("duplicate")) {
|
|
37
|
+
res.status(409).json({
|
|
38
|
+
message: "A customer with this email already exists",
|
|
39
|
+
type: "duplicate_error",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
res.status(400).json({
|
|
44
|
+
message: error.message || "Failed to create customer",
|
|
45
|
+
type: "invalid_data",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW1CQSxvQkE0REM7QUE3RUQscURBQW1EO0FBaUI1QyxLQUFLLFVBQVUsSUFBSSxDQUN4QixHQUFrQixFQUNsQixHQUFtQjtJQUVuQixNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNqRSxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsSUFBaUMsQ0FBQTtJQUVsRCxJQUFJLENBQUM7UUFDSCwwQ0FBMEM7UUFDMUMsTUFBTSxFQUNKLEtBQUssRUFDTCxVQUFVLEVBQ1YsU0FBUyxFQUNULEtBQUssRUFDTCxZQUFZLEVBQ1osUUFBUSxFQUNSLGNBQWMsRUFBRSxzQkFBc0IsRUFDdEMsY0FBYyxFQUFFLHNCQUFzQixFQUN0QyxHQUFHLElBQUksRUFDUixHQUFHLElBQUksQ0FBQTtRQUVSLDREQUE0RDtRQUM1RCxNQUFNLFlBQVksR0FBOEI7WUFDOUMsR0FBRyxJQUFJO1lBQ1AsS0FBSztZQUNMLFVBQVU7WUFDVixTQUFTO1lBQ1QsS0FBSztZQUNMLFlBQVk7WUFDWixRQUFRLEVBQUUsUUFBUSxJQUFJLEVBQUU7WUFDeEIsY0FBYyxFQUFFLEtBQUs7WUFDckIsY0FBYyxFQUFFLEtBQUs7U0FDdEIsQ0FBQTtRQUVELHdEQUF3RDtRQUN4RCxtQ0FBbUM7UUFDbkMsTUFBTSxTQUFTLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxlQUFlLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFBO1FBQzdFLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUU3QiwwQ0FBMEM7UUFDMUMsTUFBTSxlQUFlLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFakYsNkNBQTZDO1FBQzdDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25CLFFBQVEsRUFBRSxlQUFlO1NBQzFCLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1FBQ3BCLDhCQUE4QjtRQUM5QixJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUN0RixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDbkIsT0FBTyxFQUFFLDJDQUEyQztnQkFDcEQsSUFBSSxFQUFFLGlCQUFpQjthQUN4QixDQUFDLENBQUE7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNuQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sSUFBSSwyQkFBMkI7Z0JBQ3JELElBQUksRUFBRSxjQUFjO2FBQ3JCLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyJ9
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = GET;
|
|
4
|
+
async function GET(req, res) {
|
|
5
|
+
res.sendStatus(200);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Migration20250118000000 = void 0;
|
|
4
|
+
const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
|
|
5
|
+
const TABLE_NAME = "customer";
|
|
6
|
+
const EMAIL_COLUMN = "email_verified";
|
|
7
|
+
const PHONE_COLUMN = "phone_verified";
|
|
8
|
+
class Migration20250118000000 extends migrations_1.Migration {
|
|
9
|
+
async up() {
|
|
10
|
+
this.addSql(`alter table "${TABLE_NAME}"
|
|
11
|
+
add column if not exists "${EMAIL_COLUMN}" boolean not null default false,
|
|
12
|
+
add column if not exists "${PHONE_COLUMN}" boolean not null default false;`);
|
|
13
|
+
}
|
|
14
|
+
async down() {
|
|
15
|
+
this.addSql(`alter table "${TABLE_NAME}"
|
|
16
|
+
drop column if exists "${EMAIL_COLUMN}",
|
|
17
|
+
drop column if exists "${PHONE_COLUMN}";`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.Migration20250118000000 = Migration20250118000000;
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTAxMTgwMDAwMDBBZGRFbWFpbFZlcmlmaWVkQ29sdW1uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNTAxMTgwMDAwMDBBZGRFbWFpbFZlcmlmaWVkQ29sdW1uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlFQUFvRTtBQUVwRSxNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUE7QUFDN0IsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUE7QUFDckMsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUE7QUFFckMsTUFBYSx1QkFBd0IsU0FBUSxzQkFBUztJQUMzQyxLQUFLLENBQUMsRUFBRTtRQUNmLElBQUksQ0FBQyxNQUFNLENBQ1QsZ0JBQWdCLFVBQVU7b0NBQ0ksWUFBWTtvQ0FDWixZQUFZLG1DQUFtQyxDQUM5RSxDQUFBO0lBQ0gsQ0FBQztJQUVRLEtBQUssQ0FBQyxJQUFJO1FBQ2pCLElBQUksQ0FBQyxNQUFNLENBQ1QsZ0JBQWdCLFVBQVU7aUNBQ0MsWUFBWTtpQ0FDWixZQUFZLElBQUksQ0FDNUMsQ0FBQTtJQUNILENBQUM7Q0FDRjtBQWhCRCwwREFnQkMifQ==
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = handleCustomerCreated;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
const WELCOME_TEMPLATE_ID = process.env.CUSTOMER_REGISTRATION_WELCOME_TEMPLATE_ID ||
|
|
7
|
+
"customer-registration-success";
|
|
8
|
+
async function handleCustomerCreated({ event: { data }, container, }) {
|
|
9
|
+
const logger = container.hasRegistration(utils_1.ContainerRegistrationKeys.LOGGER)
|
|
10
|
+
? container.resolve(utils_1.ContainerRegistrationKeys.LOGGER)
|
|
11
|
+
: null;
|
|
12
|
+
if (!Array.isArray(data) || !data.length) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const customerIds = data
|
|
16
|
+
.map((payload) => payload?.id)
|
|
17
|
+
.filter((id) => typeof id === "string" && !!id);
|
|
18
|
+
if (!customerIds.length) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const customerModuleService = container.resolve(utils_1.Modules.CUSTOMER);
|
|
23
|
+
const customers = await customerModuleService.listCustomers({
|
|
24
|
+
id: customerIds,
|
|
25
|
+
});
|
|
26
|
+
if (!customers.length) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!container.hasRegistration(utils_1.Modules.NOTIFICATION)) {
|
|
30
|
+
logger?.warn?.("[customer-registration] Notification module is not configured. Skipping welcome email.");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const notificationModuleService = container.resolve(utils_1.Modules.NOTIFICATION);
|
|
34
|
+
await notificationModuleService.createNotifications(customers.map((customer) => ({
|
|
35
|
+
to: customer.email,
|
|
36
|
+
channel: "email",
|
|
37
|
+
template: WELCOME_TEMPLATE_ID,
|
|
38
|
+
resource_id: customer.id,
|
|
39
|
+
resource_type: "customer",
|
|
40
|
+
receiver_id: customer.id,
|
|
41
|
+
trigger_type: "customer-registration",
|
|
42
|
+
data: {
|
|
43
|
+
email: customer.email,
|
|
44
|
+
first_name: customer.first_name,
|
|
45
|
+
last_name: customer.last_name,
|
|
46
|
+
full_name: [customer.first_name, customer.last_name]
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.join(" ")
|
|
49
|
+
.trim(),
|
|
50
|
+
},
|
|
51
|
+
})));
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
logger?.error?.("[customer-registration] Failed to send welcome email", error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.config = {
|
|
58
|
+
event: utils_1.CustomerWorkflowEvents.CREATED,
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItY3JlYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9jdXN0b21lci1jcmVhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQW1CQSx3Q0FvRUM7QUFsRkQscURBSWtDO0FBTWxDLE1BQU0sbUJBQW1CLEdBQ3ZCLE9BQU8sQ0FBQyxHQUFHLENBQUMseUNBQXlDO0lBQ3JELCtCQUErQixDQUFBO0FBRWxCLEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxFQUNsRCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFDZixTQUFTLEdBQzhCO0lBQ3ZDLE1BQU0sTUFBTSxHQUFrQixTQUFTLENBQUMsZUFBZSxDQUNyRCxpQ0FBeUIsQ0FBQyxNQUFNLENBQ2pDO1FBQ0MsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsTUFBTSxDQUFDO1FBQ3JELENBQUMsQ0FBQyxJQUFJLENBQUE7SUFFUixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN6QyxPQUFNO0lBQ1IsQ0FBQztJQUVELE1BQU0sV0FBVyxHQUFHLElBQUk7U0FDckIsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1NBQzdCLE1BQU0sQ0FBQyxDQUFDLEVBQUUsRUFBZ0IsRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7SUFFL0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN4QixPQUFNO0lBQ1IsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILE1BQU0scUJBQXFCLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFakUsTUFBTSxTQUFTLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxhQUFhLENBQUM7WUFDMUQsRUFBRSxFQUFFLFdBQVc7U0FDaEIsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN0QixPQUFNO1FBQ1IsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLGVBQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ3JELE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FDWix3RkFBd0YsQ0FDekYsQ0FBQTtZQUNELE9BQU07UUFDUixDQUFDO1FBRUQsTUFBTSx5QkFBeUIsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtRQUV6RSxNQUFNLHlCQUF5QixDQUFDLG1CQUFtQixDQUNqRCxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNCLEVBQUUsRUFBRSxRQUFRLENBQUMsS0FBSztZQUNsQixPQUFPLEVBQUUsT0FBTztZQUNoQixRQUFRLEVBQUUsbUJBQW1CO1lBQzdCLFdBQVcsRUFBRSxRQUFRLENBQUMsRUFBRTtZQUN4QixhQUFhLEVBQUUsVUFBVTtZQUN6QixXQUFXLEVBQUUsUUFBUSxDQUFDLEVBQUU7WUFDeEIsWUFBWSxFQUFFLHVCQUF1QjtZQUNyQyxJQUFJLEVBQUU7Z0JBQ0osS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO2dCQUNyQixVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVU7Z0JBQy9CLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztnQkFDN0IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDO3FCQUNqRCxNQUFNLENBQUMsT0FBTyxDQUFDO3FCQUNmLElBQUksQ0FBQyxHQUFHLENBQUM7cUJBQ1QsSUFBSSxFQUFFO2FBQ1Y7U0FDRixDQUFDLENBQUMsQ0FDSixDQUFBO0lBQ0gsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLEVBQUUsS0FBSyxFQUFFLENBQ2Isc0RBQXNELEVBQ3RELEtBQUssQ0FDTixDQUFBO0lBQ0gsQ0FBQztBQUNILENBQUM7QUFFWSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFLDhCQUFzQixDQUFDLE9BQU87Q0FDdEMsQ0FBQSJ9
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Medusa Plugin: Customer Email Verified Registration Override
|
|
2
|
+
|
|
3
|
+
A Medusa v2 plugin that overrides the customer registration endpoint to set `email_verified = false` by default.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Overrides the `POST /store/customers` registration endpoint
|
|
8
|
+
- Forces `email_verified = false` and `phone_verified = false` for every new customer – no direct DB mutation required
|
|
9
|
+
- Emits a notification-driven welcome email every time a customer registers successfully
|
|
10
|
+
- Maintains all existing customer registration functionality
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### Local Development
|
|
15
|
+
|
|
16
|
+
1. Publish the plugin to local registry:
|
|
17
|
+
```bash
|
|
18
|
+
cd plugins/customer-registration
|
|
19
|
+
npx medusa plugin:publish
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. Install in your Medusa application:
|
|
23
|
+
```bash
|
|
24
|
+
cd ../../test-medusa
|
|
25
|
+
npx medusa plugin:add customer-registration
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. Register the plugin in `medusa-config.ts`:
|
|
29
|
+
```typescript
|
|
30
|
+
module.exports = defineConfig({
|
|
31
|
+
// ... other config
|
|
32
|
+
plugins: [
|
|
33
|
+
{
|
|
34
|
+
resolve: "customer-registration",
|
|
35
|
+
options: {},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. Start development mode (in plugin directory):
|
|
42
|
+
```bash
|
|
43
|
+
cd plugins/customer-registration
|
|
44
|
+
npx medusa plugin:develop
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
5. Start your Medusa application:
|
|
48
|
+
```bash
|
|
49
|
+
cd ../../test-medusa
|
|
50
|
+
yarn dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
### Registration
|
|
56
|
+
|
|
57
|
+
When a customer registers via `POST /store/customers`, the plugin automatically forces `email_verified = false` before persisting the customer with the Customer Module. No raw SQL access is required.
|
|
58
|
+
|
|
59
|
+
### Welcome email subscriber
|
|
60
|
+
|
|
61
|
+
- A subscriber listening on `customer.created` collects the newly created customer(s) and calls the Notification Module to dispatch an email using the template ID stored in `CUSTOMER_REGISTRATION_WELCOME_TEMPLATE_ID` (defaults to `customer-registration-success`).
|
|
62
|
+
- Configure the Notification Module in your Medusa project and ensure at least one provider handles the `email` channel for the template ID above.
|
|
63
|
+
- The notification payload includes the customer's `email`, `first_name`, `last_name`, and `full_name`, so templates can be fully personalized.
|
|
64
|
+
|
|
65
|
+
### Database migration
|
|
66
|
+
|
|
67
|
+
- The plugin ships with a Mikro-ORM migration (`Migration20250118000000AddEmailVerifiedColumn`) that adds both `email_verified BOOLEAN NOT NULL DEFAULT FALSE` and `phone_verified BOOLEAN NOT NULL DEFAULT FALSE` columns to the core `customer` table.
|
|
68
|
+
- After installing or updating the plugin, run `npx medusa db:migrate` (or the equivalent package manager command) in your Medusa project to apply the migration before handling registrations.
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
|
|
72
|
+
- Medusa v2.11.2 or higher
|
|
73
|
+
- Customer table must have `email_verified` and `phone_verified` boolean columns (default: `false`)
|
|
74
|
+
- Run the plugin-provided migration so the columns are created (`npx medusa db:migrate`)
|
|
75
|
+
- Notification Module configured with at least one provider that supports the `email` channel
|
|
76
|
+
- `CUSTOMER_REGISTRATION_WELCOME_TEMPLATE_ID` set in your `.env`/deployment (optional – falls back to `customer-registration-success`)
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
### Build
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm run build
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Watch for Changes
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx medusa plugin:develop
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This command watches for changes and automatically rebuilds and publishes the plugin to the local registry.
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "customer-registration",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Medusa plugin to override customer registration endpoint to set email_verified = false by default.",
|
|
5
|
+
"author": "Medusa (https://medusajs.com)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
".medusa/server"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
13
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
14
|
+
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
15
|
+
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|
|
16
|
+
"./*": "./.medusa/server/src/*.js",
|
|
17
|
+
"./admin": {
|
|
18
|
+
"import": "./.medusa/server/src/admin/index.mjs",
|
|
19
|
+
"require": "./.medusa/server/src/admin/index.js",
|
|
20
|
+
"default": "./.medusa/server/src/admin/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"medusa",
|
|
25
|
+
"plugin",
|
|
26
|
+
"medusa-plugin-other",
|
|
27
|
+
"medusa-plugin",
|
|
28
|
+
"medusa-v2"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "medusa plugin:build",
|
|
32
|
+
"dev": "medusa plugin:develop",
|
|
33
|
+
"prepublishOnly": "medusa plugin:build",
|
|
34
|
+
"publish": "npm version patch && npm publish"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@medusajs/admin-sdk": "2.11.2",
|
|
38
|
+
"@medusajs/cli": "2.11.2",
|
|
39
|
+
"@medusajs/framework": "2.11.2",
|
|
40
|
+
"@medusajs/medusa": "2.11.2",
|
|
41
|
+
"@medusajs/test-utils": "2.11.2",
|
|
42
|
+
"@medusajs/ui": "4.0.25",
|
|
43
|
+
"@medusajs/icons": "2.11.2",
|
|
44
|
+
"@swc/core": "1.5.7",
|
|
45
|
+
"@types/node": "^20.0.0",
|
|
46
|
+
"@types/react": "^18.3.2",
|
|
47
|
+
"@types/react-dom": "^18.2.25",
|
|
48
|
+
"prop-types": "^15.8.1",
|
|
49
|
+
"react": "^18.2.0",
|
|
50
|
+
"react-dom": "^18.2.0",
|
|
51
|
+
"ts-node": "^10.9.2",
|
|
52
|
+
"typescript": "^5.6.2",
|
|
53
|
+
"vite": "^5.2.11",
|
|
54
|
+
"yalc": "^1.0.0-pre.53"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@medusajs/admin-sdk": "2.11.2",
|
|
58
|
+
"@medusajs/cli": "2.11.2",
|
|
59
|
+
"@medusajs/framework": "2.11.2",
|
|
60
|
+
"@medusajs/test-utils": "2.11.2",
|
|
61
|
+
"@medusajs/medusa": "2.11.2",
|
|
62
|
+
"@medusajs/ui": "4.0.25",
|
|
63
|
+
"@medusajs/icons": "2.11.2"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=20"
|
|
67
|
+
}
|
|
68
|
+
}
|