customer-registration 0.0.50 → 0.0.102

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.
Files changed (44) hide show
  1. package/.medusa/server/src/api/store/customers/otp/send/route.js +36 -0
  2. package/.medusa/server/src/api/store/customers/otp/verify/route.js +75 -0
  3. package/.medusa/server/src/modules/customer-registration/index.js +8 -46
  4. package/.medusa/server/src/modules/customer-registration/migrations/Migration20250120000000AddCustomerVerificationColumns.js +42 -0
  5. package/.medusa/server/src/modules/customer-registration/service.js +11 -0
  6. package/.medusa/server/src/modules/otp-verification/index.js +29 -0
  7. package/.medusa/server/src/modules/otp-verification/migrations/Migration20250118001000CreateOtpVerificationTable.js +52 -0
  8. package/.medusa/server/src/modules/otp-verification/models/otp-verification.js +37 -0
  9. package/.medusa/server/src/modules/otp-verification/service.js +364 -0
  10. package/.medusa/server/src/modules/otp-verification/types.js +3 -0
  11. package/.medusa/server/src/modules/otp-verification/utils/template.js +78 -0
  12. package/.medusa/server/src/workflows/generate-password-reset-token.js +38 -0
  13. package/.medusa/server/src/workflows/send-otp-workflow.js +46 -0
  14. package/.medusa/server/src/workflows/steps/determine-contact-method-step.js +21 -0
  15. package/.medusa/server/src/workflows/steps/generate-otp-step.js +24 -0
  16. package/.medusa/server/src/workflows/steps/index.js +18 -0
  17. package/.medusa/server/src/workflows/steps/load-template-step.js +15 -0
  18. package/.medusa/server/src/workflows/steps/prepare-template-data-step.js +13 -0
  19. package/.medusa/server/src/workflows/steps/resolve-channel-config-step.js +18 -0
  20. package/.medusa/server/src/workflows/steps/retrieve-customer-step.js +16 -0
  21. package/.medusa/server/src/workflows/steps/send-notification-step.js +79 -0
  22. package/.medusa/server/src/workflows/verify-email.js +25 -0
  23. package/.medusa/server/src/workflows/verify-phone.js +25 -0
  24. package/README.md +140 -158
  25. package/package.json +6 -6
  26. package/.medusa/server/src/api/store/customers/email/otp/resend/route.js +0 -78
  27. package/.medusa/server/src/api/store/customers/email/otp/verify/route.js +0 -63
  28. package/.medusa/server/src/api/store/customers/forget-password/otp/resend/route.js +0 -52
  29. package/.medusa/server/src/api/store/customers/forget-password/otp/verify/route.js +0 -42
  30. package/.medusa/server/src/api/store/customers/phone/otp/resend/route.js +0 -81
  31. package/.medusa/server/src/api/store/customers/phone/otp/verify/route.js +0 -68
  32. package/.medusa/server/src/errors/otp-errors.js +0 -29
  33. package/.medusa/server/src/loaders/index.js +0 -32
  34. package/.medusa/server/src/modules/customer-registration/migrations/Migration20251122112915AddEmailPhoneVerifiedColumns.js +0 -67
  35. package/.medusa/server/src/modules/customer-registration/migrations/Migration20251122112916CreateCustomerOtpTable.js +0 -56
  36. package/.medusa/server/src/modules/customer-registration/models/customer-otp.js +0 -68
  37. package/.medusa/server/src/modules/customer-registration/services/otp-service.js +0 -236
  38. package/.medusa/server/src/services/notification-service.js +0 -81
  39. package/.medusa/server/src/subscribers/customer-created.js +0 -42
  40. package/.medusa/server/src/types/plugin-options.js +0 -30
  41. package/.medusa/server/src/utils/crypto.js +0 -52
  42. package/.medusa/server/src/utils/customer-update.js +0 -48
  43. package/.medusa/server/src/utils/otp-generator.js +0 -27
  44. package/.medusa/server/src/utils/token-generator.js +0 -11
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.OtpVerificationService = void 0;
19
+ const utils_1 = require("@medusajs/framework/utils");
20
+ const utils_2 = require("@medusajs/framework/utils");
21
+ const utils_3 = require("@medusajs/framework/utils");
22
+ const crypto_1 = __importDefault(require("crypto"));
23
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
24
+ const otp_verification_1 = require("./models/otp-verification");
25
+ class OtpVerificationService extends (0, utils_1.MedusaService)({
26
+ OtpVerification: otp_verification_1.OtpVerification,
27
+ }) {
28
+ constructor(container, moduleOptions, moduleDeclaration) {
29
+ super(container, moduleOptions, moduleDeclaration);
30
+ const resolvedOptions = moduleDeclaration?.options ?? moduleOptions ?? {};
31
+ this.config_ = {
32
+ otpLength: 6,
33
+ otpCharset: "numeric",
34
+ otpExpiryMinutes: 15,
35
+ maxAttempts: 5,
36
+ ...resolvedOptions,
37
+ };
38
+ }
39
+ /**
40
+ * Get the channel configuration for a specific purpose type
41
+ */
42
+ getChannelConfig(type) {
43
+ const config = this.config_[type];
44
+ // Debug logging in development
45
+ if (process.env.NODE_ENV !== "production" && !config) {
46
+ console.log(`[otp-verification] Config for type ${type} not found. Available keys:`, Object.keys(this.config_));
47
+ }
48
+ return config;
49
+ }
50
+ /**
51
+ * Find plugin entry in config module
52
+ */
53
+ findPluginEntry(plugins) {
54
+ return plugins.find((p) => p.resolve === "customer-registration");
55
+ }
56
+ /**
57
+ * Get channel config from plugin options
58
+ */
59
+ getChannelConfigFromPlugin(pluginEntry, type) {
60
+ if (pluginEntry &&
61
+ typeof pluginEntry === "object" &&
62
+ pluginEntry.options) {
63
+ return pluginEntry.options?.[type] || {};
64
+ }
65
+ return undefined;
66
+ }
67
+ /**
68
+ * Get channel config with fallback to config module
69
+ */
70
+ getChannelConfigWithFallback(type, configModule) {
71
+ let channelConfig = this.getChannelConfig(type);
72
+ if (channelConfig && channelConfig?.channel) {
73
+ return channelConfig;
74
+ }
75
+ // Try from projectConfig.plugins
76
+ const plugins = (configModule?.projectConfig?.plugins || []);
77
+ const pluginEntry = this.findPluginEntry(plugins);
78
+ channelConfig = this.getChannelConfigFromPlugin(pluginEntry, type);
79
+ if (channelConfig && channelConfig?.channel) {
80
+ return channelConfig;
81
+ }
82
+ // Try from direct config.plugins
83
+ if (configModule?.plugins) {
84
+ const directPlugins = (configModule?.plugins || []);
85
+ const directPluginEntry = this.findPluginEntry(directPlugins);
86
+ channelConfig = this.getChannelConfigFromPlugin(directPluginEntry, type);
87
+ }
88
+ return channelConfig;
89
+ }
90
+ /**
91
+ * Get the full configuration
92
+ */
93
+ getConfig() {
94
+ return this.config_;
95
+ }
96
+ /**
97
+ * Prepare template data for variable replacement
98
+ */
99
+ prepareTemplateData(customer, otpCode) {
100
+ return {
101
+ otp: otpCode,
102
+ customer: customer,
103
+ customer_name: customer.first_name || customer.email || "Customer",
104
+ customer_email: customer.email,
105
+ };
106
+ }
107
+ /**
108
+ * Check and handle existing OTP (throttle and invalidation)
109
+ */
110
+ async checkExistingOtp(customer_id, purpose) {
111
+ const [existingOtp] = await this.listOtpVerifications({
112
+ customer_id,
113
+ purpose,
114
+ expires_at: { $gt: new Date() },
115
+ verified_at: null,
116
+ });
117
+ if (!existingOtp) {
118
+ return;
119
+ }
120
+ const configKey = purpose;
121
+ const purposeConfig = this.config_[configKey];
122
+ const throttleSeconds = typeof purposeConfig === "object" &&
123
+ purposeConfig !== null &&
124
+ "resendThrottleSeconds" in purposeConfig
125
+ ? purposeConfig.resendThrottleSeconds ?? 90
126
+ : 90;
127
+ const timeSinceCreation = existingOtp.created_at
128
+ ? (new Date().getTime() - existingOtp.created_at.getTime()) / 1000
129
+ : 0;
130
+ if (timeSinceCreation < throttleSeconds) {
131
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, `Please wait ${Math.ceil(throttleSeconds - timeSinceCreation)} seconds before requesting a new OTP.`);
132
+ }
133
+ await this.updateOtpVerifications({
134
+ selector: { id: existingOtp.id },
135
+ data: { expires_at: new Date() },
136
+ });
137
+ }
138
+ /**
139
+ * Create OTP record in database
140
+ */
141
+ async createOtpRecord(customer_id, purpose, hashedCode, expiresAt) {
142
+ return await this.createOtpVerifications({
143
+ customer_id,
144
+ purpose,
145
+ hashed_code: hashedCode,
146
+ expires_at: expiresAt,
147
+ attempts: 0,
148
+ });
149
+ }
150
+ /**
151
+ * Generate JWT token for OTP
152
+ */
153
+ generateOtpToken(otp, type, jwtSecret) {
154
+ return jsonwebtoken_1.default.sign({
155
+ otp_id: otp.id,
156
+ customer_id: otp.customer_id,
157
+ type,
158
+ purpose: otp.purpose,
159
+ }, jwtSecret, {
160
+ expiresIn: `${this.config_.otpExpiryMinutes ?? 15}m`,
161
+ });
162
+ }
163
+ /**
164
+ * Decode and validate JWT token
165
+ */
166
+ decodeOtpToken(token, jwtSecret) {
167
+ try {
168
+ const decoded = jsonwebtoken_1.default.verify(token, jwtSecret);
169
+ const { otp_id, customer_id, type } = decoded;
170
+ if (!otp_id || !customer_id || !type) {
171
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invalid token format.");
172
+ }
173
+ return { otp_id, customer_id, type };
174
+ }
175
+ catch (error) {
176
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invalid or expired token. Please request a new OTP.");
177
+ }
178
+ }
179
+ /**
180
+ * Validate OTP record (existence, customer match, status, expiry, attempts)
181
+ */
182
+ async validateOtpRecord(otp_id, customer_id) {
183
+ const [otp] = await this.listOtpVerifications({ id: otp_id });
184
+ if (!otp) {
185
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, "OTP not found. Please request a new one.");
186
+ }
187
+ if (otp.customer_id !== customer_id) {
188
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Token does not match customer.");
189
+ }
190
+ if (otp.verified_at) {
191
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "OTP has already been verified.");
192
+ }
193
+ if (otp.expires_at < new Date()) {
194
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "OTP has expired. Please request a new one.");
195
+ }
196
+ if (otp.attempts >= (this.config_.maxAttempts ?? 5)) {
197
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Maximum verification attempts exceeded. Please request a new OTP.");
198
+ }
199
+ return otp;
200
+ }
201
+ /**
202
+ * Verify OTP code and increment attempts on failure
203
+ */
204
+ async verifyOtpCode(otp, code) {
205
+ const hashedInput = this.hashCode(code);
206
+ const isValid = hashedInput === otp.hashed_code;
207
+ if (!isValid) {
208
+ await this.updateOtpVerifications({
209
+ selector: { id: otp.id },
210
+ data: { attempts: otp.attempts + 1 },
211
+ });
212
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid OTP code. ${(this.config_.maxAttempts ?? 5) - (otp.attempts + 1)} attempts remaining.`);
213
+ }
214
+ }
215
+ /**
216
+ * Mark OTP as verified
217
+ */
218
+ async markOtpAsVerified(otp_id) {
219
+ await this.updateOtpVerifications({
220
+ selector: { id: otp_id },
221
+ data: { verified_at: new Date() },
222
+ });
223
+ }
224
+ /**
225
+ * Verify an OTP code using token
226
+ */
227
+ async verifyOtp(input, jwtSecret) {
228
+ const { token, code } = input;
229
+ const { otp_id, customer_id, type } = this.decodeOtpToken(token, jwtSecret);
230
+ const otp = await this.validateOtpRecord(otp_id, customer_id);
231
+ await this.verifyOtpCode(otp, code);
232
+ await this.markOtpAsVerified(otp.id);
233
+ return {
234
+ verified: true,
235
+ customer_id: otp.customer_id,
236
+ type: otp.purpose,
237
+ };
238
+ }
239
+ /**
240
+ * Get the latest OTP for a customer (for testing/debugging)
241
+ */
242
+ async getLatestOtp(customer_id, purpose) {
243
+ const otps = await this.listOtpVerifications({
244
+ customer_id,
245
+ purpose,
246
+ }, {
247
+ order: { created_at: "DESC" },
248
+ take: 1,
249
+ });
250
+ return otps[0] || null;
251
+ }
252
+ /**
253
+ * Generate OTP code and return it (for sending via notification)
254
+ * This is a helper that generates code, creates OTP record, and returns both code and token
255
+ */
256
+ async generateOtpWithCode(input, jwtSecret) {
257
+ const { customer_id, type } = input;
258
+ const purpose = type;
259
+ await this.checkExistingOtp(customer_id, purpose);
260
+ const code = this.generateCode();
261
+ const hashedCode = this.hashCode(code);
262
+ const expiresAt = new Date();
263
+ expiresAt.setMinutes(expiresAt.getMinutes() + (this.config_.otpExpiryMinutes ?? 15));
264
+ const otp = await this.createOtpRecord(customer_id, purpose, hashedCode, expiresAt);
265
+ const token = this.generateOtpToken(otp, type, jwtSecret);
266
+ return {
267
+ token,
268
+ expires_at: expiresAt,
269
+ code,
270
+ };
271
+ }
272
+ /**
273
+ * Generate a random OTP code
274
+ */
275
+ generateCode() {
276
+ const length = this.config_.otpLength ?? 6;
277
+ const charset = this.config_.otpCharset ?? "numeric";
278
+ if (charset === "numeric") {
279
+ const min = Math.pow(10, length - 1);
280
+ const max = Math.pow(10, length) - 1;
281
+ return Math.floor(Math.random() * (max - min + 1) + min).toString();
282
+ }
283
+ else {
284
+ // Alphanumeric: digits + consonants (excluding vowels and confusing characters)
285
+ const chars = "0123456789BCDFGHJKLMNPQRSTVWXYZ";
286
+ let code = "";
287
+ for (let i = 0; i < length; i++) {
288
+ code += chars.charAt(Math.floor(Math.random() * chars.length));
289
+ }
290
+ return code;
291
+ }
292
+ }
293
+ /**
294
+ * Hash an OTP code for storage
295
+ */
296
+ hashCode(code) {
297
+ return crypto_1.default.createHash("sha256").update(code).digest("hex");
298
+ }
299
+ /**
300
+ * Update customer email verification status
301
+ */
302
+ async updateEmailVerified(sharedContext, customerId) {
303
+ const knex = sharedContext.manager?.getKnex();
304
+ if (!knex) {
305
+ throw new Error("Database connection not available");
306
+ }
307
+ await knex.raw(`UPDATE customer
308
+ SET email_verified = ?, updated_at = NOW()
309
+ WHERE id = ?`, [true, customerId]);
310
+ }
311
+ /**
312
+ * Update customer phone verification status
313
+ */
314
+ async updatePhoneVerified(sharedContext, customerId) {
315
+ const knex = sharedContext.manager?.getKnex();
316
+ if (!knex) {
317
+ throw new Error("Database connection not available");
318
+ }
319
+ await knex.raw(`UPDATE customer
320
+ SET phone_verified = ?, updated_at = NOW()
321
+ WHERE id = ?`, [true, customerId]);
322
+ }
323
+ /**
324
+ * Get customer verification status
325
+ */
326
+ async getCustomerVerification(sharedContext, customerId) {
327
+ const knex = sharedContext.manager?.getKnex();
328
+ if (!knex) {
329
+ throw new Error("Database connection not available");
330
+ }
331
+ // Get verification status from database directly
332
+ const result = await knex.raw(`SELECT email_verified, phone_verified
333
+ FROM customer
334
+ WHERE id = ?`, [customerId]);
335
+ const row = result.rows?.[0] || result[0]?.[0];
336
+ return {
337
+ email_verified: row?.email_verified ?? false,
338
+ phone_verified: row?.phone_verified ?? false,
339
+ };
340
+ }
341
+ }
342
+ exports.OtpVerificationService = OtpVerificationService;
343
+ __decorate([
344
+ (0, utils_2.InjectManager)(),
345
+ __param(0, (0, utils_3.MedusaContext)()),
346
+ __metadata("design:type", Function),
347
+ __metadata("design:paramtypes", [Object, String]),
348
+ __metadata("design:returntype", Promise)
349
+ ], OtpVerificationService.prototype, "updateEmailVerified", null);
350
+ __decorate([
351
+ (0, utils_2.InjectManager)(),
352
+ __param(0, (0, utils_3.MedusaContext)()),
353
+ __metadata("design:type", Function),
354
+ __metadata("design:paramtypes", [Object, String]),
355
+ __metadata("design:returntype", Promise)
356
+ ], OtpVerificationService.prototype, "updatePhoneVerified", null);
357
+ __decorate([
358
+ (0, utils_2.InjectManager)(),
359
+ __param(0, (0, utils_3.MedusaContext)()),
360
+ __metadata("design:type", Function),
361
+ __metadata("design:paramtypes", [Object, String]),
362
+ __metadata("design:returntype", Promise)
363
+ ], OtpVerificationService.prototype, "getCustomerVerification", null);
364
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL290cC12ZXJpZmljYXRpb24vc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFBc0U7QUFDdEUscURBQXlEO0FBRXpELHFEQUF5RDtBQUV6RCxvREFBMkI7QUFDM0IsZ0VBQThCO0FBQzlCLGdFQUF1RTtBQVl2RSxNQUFhLHNCQUF1QixTQUFRLElBQUEscUJBQWEsRUFBQztJQUN4RCxlQUFlLEVBQWYsa0NBQWU7Q0FDaEIsQ0FBQztJQUdBLFlBQ0UsU0FBK0IsRUFDL0IsYUFBeUIsRUFDekIsaUJBQTJDO1FBRTNDLEtBQUssQ0FBQyxTQUFTLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixDQUFDLENBQUE7UUFFbEQsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLEVBQUUsT0FBTyxJQUFJLGFBQWEsSUFBSSxFQUFFLENBQUE7UUFDekUsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLFNBQVMsRUFBRSxDQUFDO1lBQ1osVUFBVSxFQUFFLFNBQVM7WUFDckIsZ0JBQWdCLEVBQUUsRUFBRTtZQUNwQixXQUFXLEVBQUUsQ0FBQztZQUNkLEdBQUcsZUFBZTtTQUNuQixDQUFBO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZ0JBQWdCLENBQUMsSUFBZ0I7UUFDL0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUF1QixDQUFDLENBQUE7UUFDcEQsK0JBQStCO1FBQy9CLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssWUFBWSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FDVCxzQ0FBc0MsSUFBSSw2QkFBNkIsRUFDdkUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQzFCLENBQUE7UUFDSCxDQUFDO1FB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
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9vdHAtdmVyaWZpY2F0aW9uL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadAndRenderTemplate = loadAndRenderTemplate;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Load and render template from file path
41
+ * Supports both HTML (for email) and text (for SMS) templates
42
+ */
43
+ function loadAndRenderTemplate(templatePath, data) {
44
+ try {
45
+ // Use the exact path provided (can be relative or absolute)
46
+ const fullPath = path.isAbsolute(templatePath)
47
+ ? templatePath
48
+ : path.join(process.cwd(), templatePath);
49
+ if (!fs.existsSync(fullPath)) {
50
+ throw new Error(`Template file not found: ${fullPath}`);
51
+ }
52
+ let templateContent = fs.readFileSync(fullPath, "utf-8");
53
+ // Replace template variables {{variable_name}} with actual values
54
+ Object.keys(data).forEach((key) => {
55
+ const value = data[key];
56
+ const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
57
+ if (value !== null && value !== undefined) {
58
+ if (typeof value === "object") {
59
+ templateContent = templateContent.replace(regex, JSON.stringify(value));
60
+ }
61
+ else {
62
+ templateContent = templateContent.replace(regex, String(value));
63
+ }
64
+ }
65
+ else {
66
+ templateContent = templateContent.replace(regex, "");
67
+ }
68
+ });
69
+ // Clean up any remaining placeholders
70
+ templateContent = templateContent.replace(/\{\{[\w]+\}\}/g, "");
71
+ return templateContent;
72
+ }
73
+ catch (error) {
74
+ console.error(`[customer-registration] Failed to load template from ${templatePath}:`, error);
75
+ return null;
76
+ }
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9vdHAtdmVyaWZpY2F0aW9uL3V0aWxzL3RlbXBsYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUEsc0RBMkNDO0FBMURELHVDQUF3QjtBQUN4QiwyQ0FBNEI7QUFVNUI7OztHQUdHO0FBQ0gsU0FBZ0IscUJBQXFCLENBQ25DLFlBQW9CLEVBQ3BCLElBQWtCO0lBRWxCLElBQUksQ0FBQztRQUNILDREQUE0RDtRQUM1RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztZQUM1QyxDQUFDLENBQUMsWUFBWTtZQUNkLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUUxQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLFFBQVEsRUFBRSxDQUFDLENBQUE7UUFDekQsQ0FBQztRQUVELElBQUksZUFBZSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBRXhELGtFQUFrRTtRQUNsRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ2hDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUF5QixDQUFDLENBQUE7WUFDN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxNQUFNLENBQUMsU0FBUyxHQUFHLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQTtZQUVuRCxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUM5QixlQUFlLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO2dCQUN6RSxDQUFDO3FCQUFNLENBQUM7b0JBQ04sZUFBZSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO2dCQUNqRSxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGVBQWUsR0FBRyxlQUFlLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUN0RCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUE7UUFFRixzQ0FBc0M7UUFDdEMsZUFBZSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFFL0QsT0FBTyxlQUFlLENBQUE7SUFDeEIsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLENBQUMsS0FBSyxDQUNYLHdEQUF3RCxZQUFZLEdBQUcsRUFDdkUsS0FBSyxDQUNOLENBQUE7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7QUFDSCxDQUFDIn0=
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generatePasswordResetTokenWorkflow = void 0;
7
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
8
+ const utils_1 = require("@medusajs/framework/utils");
9
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
10
+ const generatePasswordResetTokenStep = (0, workflows_sdk_1.createStep)("generate-password-reset-token", async ({ customer_id }, { container }) => {
11
+ const config = container.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
12
+ const jwtSecret = config?.projectConfig?.http?.jwtSecret || "supersecret";
13
+ const jwtExpiresIn = config?.projectConfig?.http?.jwtExpiresIn || "1h";
14
+ // Generate JWT token for password reset
15
+ // Token contains customer_id and purpose for password reset
16
+ const token = jsonwebtoken_1.default.sign({
17
+ customer_id,
18
+ purpose: "password_reset",
19
+ type: "forgot_password",
20
+ }, jwtSecret, {
21
+ expiresIn: jwtExpiresIn,
22
+ });
23
+ return new workflows_sdk_1.StepResponse({
24
+ customer_id,
25
+ token,
26
+ expires_in: jwtExpiresIn,
27
+ });
28
+ });
29
+ exports.generatePasswordResetTokenWorkflow = (0, workflows_sdk_1.createWorkflow)("generate-password-reset-token", (input) => {
30
+ const result = generatePasswordResetTokenStep(input);
31
+ return new workflows_sdk_1.WorkflowResponse({
32
+ customer_id: result.customer_id,
33
+ token: result.token,
34
+ expires_in: result.expires_in,
35
+ });
36
+ });
37
+ exports.default = exports.generatePasswordResetTokenWorkflow;
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtcGFzc3dvcmQtcmVzZXQtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2dlbmVyYXRlLXBhc3N3b3JkLXJlc2V0LXRva2VuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFFQUswQztBQUMxQyxxREFBcUU7QUFDckUsZ0VBQThCO0FBTTlCLE1BQU0sOEJBQThCLEdBQUcsSUFBQSwwQkFBVSxFQUMvQywrQkFBK0IsRUFDL0IsS0FBSyxFQUFFLEVBQUUsV0FBVyxFQUFtQyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUN4RSxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FBQyxDQUFBO0lBQ3pFLE1BQU0sU0FBUyxHQUFJLE1BQU0sRUFBRSxhQUFxQixFQUFFLElBQUksRUFBRSxTQUFTLElBQUksYUFBYSxDQUFBO0lBQ2xGLE1BQU0sWUFBWSxHQUFJLE1BQU0sRUFBRSxhQUFxQixFQUFFLElBQUksRUFBRSxZQUFZLElBQUksSUFBSSxDQUFBO0lBRS9FLHdDQUF3QztJQUN4Qyw0REFBNEQ7SUFDNUQsTUFBTSxLQUFLLEdBQUcsc0JBQUcsQ0FBQyxJQUFJLENBQ3BCO1FBQ0UsV0FBVztRQUNYLE9BQU8sRUFBRSxnQkFBZ0I7UUFDekIsSUFBSSxFQUFFLGlCQUFpQjtLQUN4QixFQUNELFNBQVMsRUFDVDtRQUNFLFNBQVMsRUFBRSxZQUFZO0tBQ3hCLENBQ0YsQ0FBQTtJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDO1FBQ3RCLFdBQVc7UUFDWCxLQUFLO1FBQ0wsVUFBVSxFQUFFLFlBQVk7S0FDekIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFRWSxRQUFBLGtDQUFrQyxHQUFHLElBQUEsOEJBQWMsRUFDOUQsK0JBQStCLEVBQy9CLENBQUMsS0FBc0MsRUFBc0QsRUFBRTtJQUM3RixNQUFNLE1BQU0sR0FBRyw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUVwRCxPQUFPLElBQUksZ0NBQWdCLENBQUM7UUFDMUIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1FBQy9CLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSztRQUNuQixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7S0FDOUIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFRCxrQkFBZSwwQ0FBa0MsQ0FBQSJ9
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendOtpWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const steps_1 = require("./steps");
6
+ exports.sendOtpWorkflow = (0, workflows_sdk_1.createWorkflow)("send-otp", (input) => {
7
+ // Step 1: Retrieve customer
8
+ const { customer } = (0, steps_1.retrieveCustomerStep)({ customer_id: input.customer_id });
9
+ // Step 2: Resolve channel configuration
10
+ const { channelConfig } = (0, steps_1.resolveChannelConfigStep)({ type: input.type });
11
+ // Step 3: Determine contact method (email/phone)
12
+ const { contactValue, contactType } = (0, steps_1.determineContactMethodStep)({
13
+ customer: customer,
14
+ channelConfig: channelConfig,
15
+ });
16
+ // Step 4: Generate OTP
17
+ const { token, expires_at, code } = (0, steps_1.generateOtpStep)({
18
+ customer_id: input.customer_id,
19
+ type: input.type,
20
+ });
21
+ // Step 5: Prepare template data
22
+ const { templateData } = (0, steps_1.prepareTemplateDataStep)({
23
+ customer: customer,
24
+ otpCode: code,
25
+ });
26
+ // Step 6: Load and render template if provided
27
+ const { renderedContent } = (0, steps_1.loadTemplateStep)({
28
+ templatePath: channelConfig.template || null,
29
+ templateData: templateData,
30
+ });
31
+ // Step 7: Send notification (unified step handles email/SMS)
32
+ (0, steps_1.sendNotificationStep)({
33
+ to: contactValue,
34
+ channel: channelConfig.channel,
35
+ channelConfig: channelConfig,
36
+ templateData: templateData,
37
+ renderedContent: renderedContent,
38
+ contactType: contactType,
39
+ });
40
+ return new workflows_sdk_1.WorkflowResponse({
41
+ token,
42
+ expires_at,
43
+ });
44
+ });
45
+ exports.default = exports.sendOtpWorkflow;
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1vdHAtd29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3NlbmQtb3RwLXdvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUcwQztBQUUxQyxtQ0FRZ0I7QUFZSCxRQUFBLGVBQWUsR0FBRyxJQUFBLDhCQUFjLEVBQzNDLFVBQVUsRUFDVixDQUFDLEtBQW1CLEVBQW1DLEVBQUU7SUFDdkQsNEJBQTRCO0lBQzVCLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxJQUFBLDRCQUFvQixFQUFDLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFBO0lBRTdFLHdDQUF3QztJQUN4QyxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsSUFBQSxnQ0FBd0IsRUFBQyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUV4RSxpREFBaUQ7SUFDakQsTUFBTSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFBLGtDQUEwQixFQUFDO1FBQy9ELFFBQVEsRUFBRSxRQUFRO1FBQ2xCLGFBQWEsRUFBRSxhQUFhO0tBQzdCLENBQUMsQ0FBQTtJQUVGLHVCQUF1QjtJQUN2QixNQUFNLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFBLHVCQUFlLEVBQUM7UUFDbEQsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXO1FBQzlCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtLQUNqQixDQUFDLENBQUE7SUFFRixnQ0FBZ0M7SUFDaEMsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUEsK0JBQXVCLEVBQUM7UUFDL0MsUUFBUSxFQUFFLFFBQVE7UUFDbEIsT0FBTyxFQUFFLElBQUk7S0FDZCxDQUFDLENBQUE7SUFFRiwrQ0FBK0M7SUFDL0MsTUFBTSxFQUFFLGVBQWUsRUFBRSxHQUFHLElBQUEsd0JBQWdCLEVBQUM7UUFDM0MsWUFBWSxFQUFFLGFBQWEsQ0FBQyxRQUFRLElBQUksSUFBSTtRQUM1QyxZQUFZLEVBQUUsWUFBWTtLQUMzQixDQUFDLENBQUE7SUFFRiw2REFBNkQ7SUFDN0QsSUFBQSw0QkFBb0IsRUFBQztRQUNuQixFQUFFLEVBQUUsWUFBWTtRQUNoQixPQUFPLEVBQUUsYUFBYSxDQUFDLE9BQU87UUFDOUIsYUFBYSxFQUFFLGFBQWE7UUFDNUIsWUFBWSxFQUFFLFlBQVk7UUFDMUIsZUFBZSxFQUFFLGVBQWU7UUFDaEMsV0FBVyxFQUFFLFdBQVc7S0FDekIsQ0FBQyxDQUFBO0lBRUYsT0FBTyxJQUFJLGdDQUFnQixDQUFDO1FBQzFCLEtBQUs7UUFDTCxVQUFVO0tBQ1gsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFRCxrQkFBZSx1QkFBZSxDQUFBIn0=
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.determineContactMethodStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ exports.determineContactMethodStep = (0, workflows_sdk_1.createStep)("determine-contact-method", async (input) => {
7
+ const { customer, channelConfig } = input;
8
+ const channelName = channelConfig.channel.toLowerCase();
9
+ const contactType = channelName === "email" ? "email" : "phone";
10
+ const contactValue = contactType === "email" ? customer.email : customer.phone;
11
+ if (!contactValue) {
12
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, contactType === "email"
13
+ ? "Customer email is required for this verification type"
14
+ : "Customer phone number is required for this verification type");
15
+ }
16
+ return new workflows_sdk_1.StepResponse({
17
+ contactValue,
18
+ contactType,
19
+ });
20
+ });
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0ZXJtaW5lLWNvbnRhY3QtbWV0aG9kLXN0ZXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL2RldGVybWluZS1jb250YWN0LW1ldGhvZC1zdGVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSxxREFBdUQ7QUFZMUMsUUFBQSwwQkFBMEIsR0FBRyxJQUFBLDBCQUFVLEVBQ2xELDBCQUEwQixFQUMxQixLQUFLLEVBQ0gsS0FBa0MsRUFDbUIsRUFBRTtJQUN2RCxNQUFNLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxHQUFHLEtBQUssQ0FBQTtJQUV6QyxNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQ3ZELE1BQU0sV0FBVyxHQUNmLFdBQVcsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFBO0lBQzdDLE1BQU0sWUFBWSxHQUNoQixXQUFXLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFBO0lBRTNELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixXQUFXLEtBQUssT0FBTztZQUNyQixDQUFDLENBQUMsdURBQXVEO1lBQ3pELENBQUMsQ0FBQyw4REFBOEQsQ0FDbkUsQ0FBQTtJQUNILENBQUM7SUFFRCxPQUFPLElBQUksNEJBQVksQ0FBK0I7UUFDcEQsWUFBWTtRQUNaLFdBQVc7S0FDWixDQUFDLENBQUE7QUFDSixDQUFDLENBQ0YsQ0FBQSJ9
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateOtpStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const otp_verification_1 = require("../../modules/otp-verification");
7
+ exports.generateOtpStep = (0, workflows_sdk_1.createStep)("generate-otp", async (input, { container }) => {
8
+ const config = container.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
9
+ const jwtSecret = config?.projectConfig?.http?.jwtSecret || "supersecret";
10
+ const otpService = container.resolve(otp_verification_1.OTP_VERIFICATION_MODULE);
11
+ const otpResult = await otpService.generateOtpWithCode({
12
+ customer_id: input.customer_id,
13
+ type: input.type,
14
+ }, jwtSecret);
15
+ if (!otpResult.code) {
16
+ throw new Error("Failed to generate OTP code");
17
+ }
18
+ return new workflows_sdk_1.StepResponse({
19
+ token: otpResult.token,
20
+ expires_at: otpResult.expires_at,
21
+ code: otpResult.code,
22
+ });
23
+ });
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtb3RwLXN0ZXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL2dlbmVyYXRlLW90cC1zdGVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSxxREFBcUU7QUFDckUscUVBQXdFO0FBZTNELFFBQUEsZUFBZSxHQUFHLElBQUEsMEJBQVUsRUFDdkMsY0FBYyxFQUNkLEtBQUssRUFBRSxLQUF1QixFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUMvQyxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FBQyxDQUFBO0lBQ3pFLE1BQU0sU0FBUyxHQUNaLE1BQU0sRUFBRSxhQUFxQixFQUFFLElBQUksRUFBRSxTQUFTLElBQUksYUFBYSxDQUFBO0lBRWxFLE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQ2xDLDBDQUF1QixDQUNFLENBQUE7SUFFM0IsTUFBTSxTQUFTLEdBQUcsTUFBTSxVQUFVLENBQUMsbUJBQW1CLENBQ3BEO1FBQ0UsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXO1FBQzlCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtLQUNqQixFQUNELFNBQVMsQ0FDVixDQUFBO0lBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUE7SUFDaEQsQ0FBQztJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFvQjtRQUN6QyxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7UUFDdEIsVUFBVSxFQUFFLFNBQVMsQ0FBQyxVQUFVO1FBQ2hDLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtLQUNyQixDQUFDLENBQUE7QUFDSixDQUFDLENBQ0YsQ0FBQSJ9
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareTemplateDataStep = exports.generateOtpStep = exports.determineContactMethodStep = exports.retrieveCustomerStep = exports.sendNotificationStep = exports.loadTemplateStep = exports.resolveChannelConfigStep = void 0;
4
+ var resolve_channel_config_step_1 = require("./resolve-channel-config-step");
5
+ Object.defineProperty(exports, "resolveChannelConfigStep", { enumerable: true, get: function () { return resolve_channel_config_step_1.resolveChannelConfigStep; } });
6
+ var load_template_step_1 = require("./load-template-step");
7
+ Object.defineProperty(exports, "loadTemplateStep", { enumerable: true, get: function () { return load_template_step_1.loadTemplateStep; } });
8
+ var send_notification_step_1 = require("./send-notification-step");
9
+ Object.defineProperty(exports, "sendNotificationStep", { enumerable: true, get: function () { return send_notification_step_1.sendNotificationStep; } });
10
+ var retrieve_customer_step_1 = require("./retrieve-customer-step");
11
+ Object.defineProperty(exports, "retrieveCustomerStep", { enumerable: true, get: function () { return retrieve_customer_step_1.retrieveCustomerStep; } });
12
+ var determine_contact_method_step_1 = require("./determine-contact-method-step");
13
+ Object.defineProperty(exports, "determineContactMethodStep", { enumerable: true, get: function () { return determine_contact_method_step_1.determineContactMethodStep; } });
14
+ var generate_otp_step_1 = require("./generate-otp-step");
15
+ Object.defineProperty(exports, "generateOtpStep", { enumerable: true, get: function () { return generate_otp_step_1.generateOtpStep; } });
16
+ var prepare_template_data_step_1 = require("./prepare-template-data-step");
17
+ Object.defineProperty(exports, "prepareTemplateDataStep", { enumerable: true, get: function () { return prepare_template_data_step_1.prepareTemplateDataStep; } });
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZFQUF3RTtBQUEvRCx1SUFBQSx3QkFBd0IsT0FBQTtBQUNqQywyREFBdUQ7QUFBOUMsc0hBQUEsZ0JBQWdCLE9BQUE7QUFDekIsbUVBQStEO0FBQXRELDhIQUFBLG9CQUFvQixPQUFBO0FBQzdCLG1FQUErRDtBQUF0RCw4SEFBQSxvQkFBb0IsT0FBQTtBQUM3QixpRkFBNEU7QUFBbkUsMklBQUEsMEJBQTBCLE9BQUE7QUFDbkMseURBQXFEO0FBQTVDLG9IQUFBLGVBQWUsT0FBQTtBQUN4QiwyRUFBc0U7QUFBN0QscUlBQUEsdUJBQXVCLE9BQUEifQ==
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadTemplateStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const template_1 = require("../../modules/otp-verification/utils/template");
6
+ exports.loadTemplateStep = (0, workflows_sdk_1.createStep)("load-template", async (input) => {
7
+ let renderedContent = null;
8
+ if (input.templatePath) {
9
+ renderedContent = (0, template_1.loadAndRenderTemplate)(input.templatePath, input.templateData);
10
+ }
11
+ return new workflows_sdk_1.StepResponse({
12
+ renderedContent,
13
+ });
14
+ });
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC10ZW1wbGF0ZS1zdGVwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9sb2FkLXRlbXBsYXRlLXN0ZXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTRFO0FBQzVFLDRFQUFtRztBQVd0RixRQUFBLGdCQUFnQixHQUFHLElBQUEsMEJBQVUsRUFDeEMsZUFBZSxFQUNmLEtBQUssRUFBRSxLQUF3QixFQUE2QyxFQUFFO0lBQzVFLElBQUksZUFBZSxHQUFrQixJQUFJLENBQUE7SUFFekMsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDdkIsZUFBZSxHQUFHLElBQUEsZ0NBQXFCLEVBQ3JDLEtBQUssQ0FBQyxZQUFZLEVBQ2xCLEtBQUssQ0FBQyxZQUFZLENBQ25CLENBQUE7SUFDSCxDQUFDO0lBRUQsT0FBTyxJQUFJLDRCQUFZLENBQXFCO1FBQzFDLGVBQWU7S0FDaEIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUEifQ==