@draftlab/auth 0.12.0 → 0.13.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.
@@ -174,22 +174,49 @@ interface PasswordConfig {
174
174
  * Callback for sending verification codes to users via email.
175
175
  * Implement this to integrate with your email service provider.
176
176
  *
177
+ * The context parameter indicates why the code is being sent:
178
+ * - "register": User is registering for the first time
179
+ * - "register:resend": User requested to resend registration code
180
+ * - "reset": User is resetting their password
181
+ * - "reset:resend": User requested to resend password reset code
182
+ *
177
183
  * @param email - The recipient's email address
178
184
  * @param code - The verification code to send
185
+ * @param context - The context of why the code is being sent
179
186
  * @returns Promise that resolves when email is sent
180
187
  *
181
188
  * @example
182
189
  * ```ts
183
- * sendCode: async (email, code) => {
190
+ * sendCode: async (email, code, context) => {
191
+ * const templates = {
192
+ * "register": {
193
+ * subject: "Welcome! Verify your email",
194
+ * body: `Welcome! Your verification code is: ${code}`
195
+ * },
196
+ * "register:resend": {
197
+ * subject: "Your verification code (resent)",
198
+ * body: `Here's your code again: ${code}`
199
+ * },
200
+ * "reset": {
201
+ * subject: "Reset your password",
202
+ * body: `Your password reset code is: ${code}`
203
+ * },
204
+ * "reset:resend": {
205
+ * subject: "Password reset code (resent)",
206
+ * body: `Here's your reset code again: ${code}`
207
+ * }
208
+ * }
209
+ *
210
+ * const template = templates[context]
184
211
  * await emailService.send({
185
212
  * to: email,
186
- * subject: 'Your verification code',
187
- * text: `Your verification code is: ${code}`
213
+ * subject: template.subject,
214
+ * text: template.body
188
215
  * })
189
216
  * }
190
217
  * ```
191
218
  */
192
- sendCode: (email: string, code: string) => Promise<void>;
219
+ sendCode: (email: string, code: string, context: "register" | "register:resend" | "reset" | "reset:resend") => Promise<void>;
193
220
  /**
194
221
  * Optional password validation function or schema.
195
222
  * Can be either a validation function or a standard-schema validator.
@@ -129,7 +129,7 @@ const PasswordProvider = (config) => {
129
129
  "password"
130
130
  ])) return transition(provider, { type: "email_taken" });
131
131
  const code = generateCode();
132
- await config.sendCode(email, code);
132
+ await config.sendCode(email, code, "register");
133
133
  return transition({
134
134
  type: "code",
135
135
  code,
@@ -139,7 +139,7 @@ const PasswordProvider = (config) => {
139
139
  }
140
140
  if (action === "register" && provider.type === "code") {
141
141
  const code = generateCode();
142
- await config.sendCode(provider.email, code);
142
+ await config.sendCode(provider.email, code, "register:resend");
143
143
  return transition({
144
144
  type: "code",
145
145
  code,
@@ -170,7 +170,7 @@ const PasswordProvider = (config) => {
170
170
  routes.get("/change", async (c) => {
171
171
  const state = {
172
172
  type: "start",
173
- redirect: c.query("redirect_uri") || getRelativeUrl(c, "/authorize")
173
+ redirect: c.query("redirect_uri") || getRelativeUrl(c, "./authorize")
174
174
  };
175
175
  await ctx.set(c, "provider", 3600 * 24, state);
176
176
  return ctx.forward(c, await config.change(c.request, state));
@@ -194,7 +194,8 @@ const PasswordProvider = (config) => {
194
194
  redirect: provider.redirect
195
195
  }, { type: "invalid_email" });
196
196
  const code = generateCode();
197
- await config.sendCode(email, code);
197
+ const context = provider.type === "code" && provider.email === email ? "reset:resend" : "reset";
198
+ await config.sendCode(email, code, context);
198
199
  return transition({
199
200
  type: "code",
200
201
  code,
@@ -159,7 +159,7 @@ const PasswordUI = (options) => {
159
159
  ] })
160
160
  })
161
161
  ]
162
- }) : /* @__PURE__ */ jsxs("form", {
162
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("form", {
163
163
  "data-component": "form",
164
164
  method: "post",
165
165
  children: [
@@ -188,7 +188,47 @@ const PasswordUI = (options) => {
188
188
  children: copy.button_continue
189
189
  })
190
190
  ]
191
- }) });
191
+ }), /* @__PURE__ */ jsxs("form", {
192
+ method: "post",
193
+ children: [
194
+ /* @__PURE__ */ jsx("input", {
195
+ name: "action",
196
+ type: "hidden",
197
+ value: "register"
198
+ }),
199
+ /* @__PURE__ */ jsx("input", {
200
+ name: "email",
201
+ type: "hidden",
202
+ value: state.email
203
+ }),
204
+ /* @__PURE__ */ jsx("input", {
205
+ name: "password",
206
+ type: "hidden",
207
+ value: ""
208
+ }),
209
+ /* @__PURE__ */ jsx("input", {
210
+ name: "repeat",
211
+ type: "hidden",
212
+ value: ""
213
+ }),
214
+ /* @__PURE__ */ jsxs("div", {
215
+ "data-component": "form-footer",
216
+ children: [/* @__PURE__ */ jsxs("span", { children: [
217
+ copy.code_return,
218
+ " ",
219
+ /* @__PURE__ */ jsx("a", {
220
+ "data-component": "link",
221
+ href: "./authorize",
222
+ children: copy.login
223
+ })
224
+ ] }), /* @__PURE__ */ jsx("button", {
225
+ type: "submit",
226
+ "data-component": "link",
227
+ children: copy.code_resend
228
+ })]
229
+ })
230
+ ]
231
+ })] }) });
192
232
  };
193
233
  /**
194
234
  * Renders the password change form based on current state
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draftlab/auth",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "description": "Core implementation for @draftlab/auth",
6
6
  "author": "Matheus Pergoli",