@rpcbase/auth 0.44.0 → 0.46.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.
Files changed (51) hide show
  1. package/dist/api/me/handler.d.ts +5 -0
  2. package/dist/api/me/handler.d.ts.map +1 -0
  3. package/dist/api/me/index.d.ts +16 -0
  4. package/dist/api/me/index.d.ts.map +1 -0
  5. package/dist/api/sign-in/handler.d.ts +2 -1
  6. package/dist/api/sign-in/handler.d.ts.map +1 -1
  7. package/dist/api/sign-in/index.d.ts +5 -1
  8. package/dist/api/sign-in/index.d.ts.map +1 -1
  9. package/dist/api/sign-out/handler.d.ts.map +1 -1
  10. package/dist/api/sign-up/handler.d.ts +2 -1
  11. package/dist/api/sign-up/handler.d.ts.map +1 -1
  12. package/dist/api/sign-up/index.d.ts +5 -2
  13. package/dist/api/sign-up/index.d.ts.map +1 -1
  14. package/dist/api/verify-otp/handler.d.ts +5 -0
  15. package/dist/api/verify-otp/handler.d.ts.map +1 -0
  16. package/dist/api/verify-otp/index.d.ts +16 -0
  17. package/dist/api/verify-otp/index.d.ts.map +1 -0
  18. package/dist/components/{EmailOrPhoneInput → EmailInput}/index.d.ts +1 -1
  19. package/dist/components/EmailInput/index.d.ts.map +1 -0
  20. package/dist/components/PasswordInput/index.d.ts +10 -0
  21. package/dist/components/PasswordInput/index.d.ts.map +1 -0
  22. package/dist/components/SignInForm/index.d.ts.map +1 -1
  23. package/dist/components/SignUpForm/index.d.ts +2 -1
  24. package/dist/components/SignUpForm/index.d.ts.map +1 -1
  25. package/dist/components/index.d.ts +2 -1
  26. package/dist/components/index.d.ts.map +1 -1
  27. package/dist/handler-Ba3pgtfZ.js +57 -0
  28. package/dist/handler-CE4lXc0G.js +64 -0
  29. package/dist/{handler-42q87FS8.js → handler-CNHucHrj.js} +4 -1
  30. package/dist/handler-DOnLMd-9.js +57 -0
  31. package/dist/handler-r4ZECW_z.js +48 -0
  32. package/dist/index-Bdcryyvv.js +17 -0
  33. package/dist/index-DwX0Y2YV.js +17 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +169 -16
  37. package/dist/middleware-BiMXO6Dq.js +21 -0
  38. package/dist/middleware.d.ts +6 -0
  39. package/dist/middleware.d.ts.map +1 -0
  40. package/dist/routes.js +1 -1
  41. package/dist/{schemas-7XFc7XYG.js → schemas-KL7REOdt.js} +1 -0
  42. package/dist/types.d.ts +7 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/package.json +8 -1
  45. package/dist/components/EmailOrPhoneInput/index.d.ts.map +0 -1
  46. package/dist/handler-BD2C82Z3.js +0 -17
  47. package/dist/handler-C7htSfmB.js +0 -32
  48. package/dist/index-Nc4R1TKZ.js +0 -25
  49. package/dist/index-oIC-DH2m.js +0 -21
  50. package/dist/isEmail-IG0hXiQk.js +0 -390
  51. package/dist/isValidNumber-6pMDGLRn.js +0 -1902
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useLocation, Link } from "@rpcbase/router";
2
+ import { useLocation, Link, useNavigate } from "@rpcbase/router";
3
3
  import clsx from "clsx";
4
4
  import { useFormContext, useForm, zodResolver, FormProvider } from "@rpcbase/form";
5
- import { useEffect } from "react";
6
- import { r as requestSchema } from "./index-oIC-DH2m.js";
7
- import { r as requestSchema$1 } from "./index-Nc4R1TKZ.js";
5
+ import * as React from "react";
6
+ import { useEffect, useState } from "react";
7
+ import { r as requestSchema } from "./index-Bdcryyvv.js";
8
+ import { r as requestSchema$1 } from "./index-DwX0Y2YV.js";
9
+ import { b, a, r } from "./middleware-BiMXO6Dq.js";
8
10
  const LINKS_REDIRECTION_MAP = {
9
11
  "/auth/sign-in": {
10
12
  "title": "Sign Up",
@@ -77,13 +79,13 @@ const AppleSignInButton = ({
77
79
  }
78
80
  );
79
81
  };
80
- const EmailOrPhoneInput = ({
82
+ const EmailInput = ({
81
83
  id,
82
84
  className,
83
85
  placeholder
84
86
  }) => {
85
87
  const { register, formState } = useFormContext();
86
- const error = formState.errors.email_or_phone;
88
+ const error = formState.errors.email;
87
89
  let errorMessage;
88
90
  if (typeof error === "string") {
89
91
  errorMessage = error;
@@ -95,12 +97,12 @@ const EmailOrPhoneInput = ({
95
97
  "input",
96
98
  {
97
99
  id,
98
- type: "text",
100
+ type: "email",
99
101
  required: true,
100
- autoComplete: "on",
102
+ autoComplete: "email",
101
103
  className,
102
104
  placeholder,
103
- ...register("email_or_phone")
105
+ ...register("email")
104
106
  }
105
107
  ),
106
108
  errorMessage ? /* @__PURE__ */ jsx("p", { className: "mt-1 -mb-2 text-sm/6 text-red-500", children: errorMessage }) : null
@@ -112,13 +114,30 @@ const SignInForm = ({
112
114
  }) => {
113
115
  const methods = useForm({
114
116
  defaultValues: {
115
- email_or_phone: "",
117
+ email: "",
118
+ password: "",
116
119
  remember_me: true
117
120
  },
118
121
  resolver: zodResolver(requestSchema)
119
122
  });
120
123
  const onSubmit = async (data) => {
121
124
  console.log("SUBMIT SIGNIN", data);
125
+ try {
126
+ const res = await fetch("/api/rb/auth/sign-in", {
127
+ method: "POST",
128
+ headers: {
129
+ "Content-Type": "application/json"
130
+ },
131
+ body: JSON.stringify(data)
132
+ });
133
+ const json = await res.json();
134
+ console.log("SIGN IN RESPONSE", json);
135
+ if (!res.ok) {
136
+ console.error("Sign-in failed", json);
137
+ }
138
+ } catch (err) {
139
+ console.error("Sign-in request error", err);
140
+ }
122
141
  };
123
142
  useEffect(() => {
124
143
  console.log(methods.formState.errors);
@@ -127,23 +146,62 @@ const SignInForm = ({
127
146
  };
128
147
  const SignUpForm = ({
129
148
  children,
130
- className
149
+ className,
150
+ otpNextPath
131
151
  }) => {
152
+ const navigate = useNavigate();
153
+ const [serverMessage, setServerMessage] = useState(null);
132
154
  const methods = useForm({
133
155
  defaultValues: {
134
- email_or_phone: "",
156
+ email: "",
135
157
  password: "",
136
- password_confirmation: ""
158
+ remember_me: true
137
159
  },
138
160
  resolver: zodResolver(requestSchema$1)
139
161
  });
140
162
  const onSubmit = async (data) => {
163
+ setServerMessage(null);
164
+ methods.clearErrors("root");
141
165
  console.log("SUBMIT SIGNUp", data);
166
+ try {
167
+ const res = await fetch("/api/rb/auth/sign-up", {
168
+ method: "POST",
169
+ headers: {
170
+ "Content-Type": "application/json"
171
+ },
172
+ body: JSON.stringify(data)
173
+ });
174
+ const json = await res.json();
175
+ console.log("SIGN UP RESPONSE", json);
176
+ if (!res.ok) {
177
+ console.error("Sign-up failed", json);
178
+ const message = json.error === "user_exists" ? "An account already exists with this email." : "Sign-up failed. Please try again.";
179
+ methods.setError("root", { type: "server", message });
180
+ return;
181
+ }
182
+ if (!json.success) {
183
+ methods.setError("root", { type: "server", message: "Sign-up failed. Please try again." });
184
+ return;
185
+ }
186
+ const search = new URLSearchParams({ email: data.email });
187
+ if (otpNextPath) {
188
+ search.set("next", otpNextPath);
189
+ }
190
+ navigate(`/auth/sign-up-otp?${search.toString()}`);
191
+ setServerMessage("Account created. Check your inbox to verify your email.");
192
+ } catch (err) {
193
+ console.error("Sign-up request error", err);
194
+ methods.setError("root", { type: "server", message: "Network error. Please try again." });
195
+ }
142
196
  };
143
197
  useEffect(() => {
144
198
  console.log(methods.formState.errors);
145
199
  }, [methods.formState.errors]);
146
- return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsx("form", { method: "post", noValidate: true, className, onSubmit: methods.handleSubmit(onSubmit), children }) });
200
+ return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsxs("form", { method: "post", noValidate: true, className, onSubmit: methods.handleSubmit(onSubmit), children: [
201
+ children,
202
+ methods.formState.errors.root?.message && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-red-600", role: "alert", children: methods.formState.errors.root.message }),
203
+ serverMessage && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-green-700", role: "status", children: serverMessage })
204
+ ] }) });
147
205
  };
148
206
  const RememberMeCheckbox = ({
149
207
  label,
@@ -168,11 +226,106 @@ const RememberMeCheckbox = ({
168
226
  )
169
227
  ] });
170
228
  };
229
+ function EyeSlashIcon({
230
+ title,
231
+ titleId,
232
+ ...props
233
+ }, svgRef) {
234
+ return /* @__PURE__ */ React.createElement("svg", Object.assign({
235
+ xmlns: "http://www.w3.org/2000/svg",
236
+ fill: "none",
237
+ viewBox: "0 0 24 24",
238
+ strokeWidth: 1.5,
239
+ stroke: "currentColor",
240
+ "aria-hidden": "true",
241
+ "data-slot": "icon",
242
+ ref: svgRef,
243
+ "aria-labelledby": titleId
244
+ }, props), title ? /* @__PURE__ */ React.createElement("title", {
245
+ id: titleId
246
+ }, title) : null, /* @__PURE__ */ React.createElement("path", {
247
+ strokeLinecap: "round",
248
+ strokeLinejoin: "round",
249
+ d: "M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"
250
+ }));
251
+ }
252
+ const ForwardRef$1 = /* @__PURE__ */ React.forwardRef(EyeSlashIcon);
253
+ function EyeIcon({
254
+ title,
255
+ titleId,
256
+ ...props
257
+ }, svgRef) {
258
+ return /* @__PURE__ */ React.createElement("svg", Object.assign({
259
+ xmlns: "http://www.w3.org/2000/svg",
260
+ fill: "none",
261
+ viewBox: "0 0 24 24",
262
+ strokeWidth: 1.5,
263
+ stroke: "currentColor",
264
+ "aria-hidden": "true",
265
+ "data-slot": "icon",
266
+ ref: svgRef,
267
+ "aria-labelledby": titleId
268
+ }, props), title ? /* @__PURE__ */ React.createElement("title", {
269
+ id: titleId
270
+ }, title) : null, /* @__PURE__ */ React.createElement("path", {
271
+ strokeLinecap: "round",
272
+ strokeLinejoin: "round",
273
+ d: "M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
274
+ }), /* @__PURE__ */ React.createElement("path", {
275
+ strokeLinecap: "round",
276
+ strokeLinejoin: "round",
277
+ d: "M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
278
+ }));
279
+ }
280
+ const ForwardRef = /* @__PURE__ */ React.forwardRef(EyeIcon);
281
+ const PasswordInput = ({
282
+ id,
283
+ name = "password",
284
+ className,
285
+ placeholder,
286
+ autoComplete = "current-password"
287
+ }) => {
288
+ const [showPassword, setShowPassword] = useState(false);
289
+ const { register, formState } = useFormContext();
290
+ const fieldError = formState.errors[name];
291
+ const errorMessage = typeof fieldError === "string" ? fieldError : typeof fieldError?.message === "string" ? fieldError.message : void 0;
292
+ const inputClassName = className ? `${className} pr-11` : "pr-11";
293
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
294
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
295
+ /* @__PURE__ */ jsx(
296
+ "input",
297
+ {
298
+ id,
299
+ type: showPassword ? "text" : "password",
300
+ autoComplete,
301
+ className: inputClassName,
302
+ placeholder,
303
+ ...register(name)
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsx(
307
+ "button",
308
+ {
309
+ type: "button",
310
+ className: "absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500",
311
+ onClick: () => setShowPassword((prev) => !prev),
312
+ "aria-label": showPassword ? "Hide characters" : "Show characters",
313
+ children: showPassword ? /* @__PURE__ */ jsx(ForwardRef$1, { className: "h-5 w-5", "aria-hidden": true }) : /* @__PURE__ */ jsx(ForwardRef, { className: "h-5 w-5", "aria-hidden": true })
314
+ }
315
+ )
316
+ ] }),
317
+ errorMessage ? /* @__PURE__ */ jsx("p", { className: "mt-1 -mb-2 text-sm/6 text-red-500", children: errorMessage }) : null
318
+ ] });
319
+ };
171
320
  export {
172
321
  AppleSignInButton,
173
322
  AuthLayout,
174
- EmailOrPhoneInput,
323
+ EmailInput,
324
+ PasswordInput,
175
325
  RememberMeCheckbox,
176
326
  SignInForm,
177
- SignUpForm
327
+ SignUpForm,
328
+ b as redirectAuthMiddleware,
329
+ a as requireSession,
330
+ r as restrictSessionMiddleware
178
331
  };
@@ -0,0 +1,21 @@
1
+ const isAuthenticated = (req) => {
2
+ return Boolean(req.session?.user?.id);
3
+ };
4
+ const restrictSessionMiddleware = (req, res, next) => {
5
+ if (isAuthenticated(req)) {
6
+ return next();
7
+ }
8
+ res.status(401).json({ error: "unauthorized" });
9
+ };
10
+ const requireSession = restrictSessionMiddleware;
11
+ const redirectAuthMiddleware = (req, res, next) => {
12
+ if (req.path.startsWith("/app") && !isAuthenticated(req)) {
13
+ return res.redirect("/auth/sign-in");
14
+ }
15
+ next();
16
+ };
17
+ export {
18
+ requireSession as a,
19
+ redirectAuthMiddleware as b,
20
+ restrictSessionMiddleware as r
21
+ };
@@ -0,0 +1,6 @@
1
+ import { Middleware } from '../../api/src';
2
+ import { AuthSessionUser } from './types';
3
+ export declare const restrictSessionMiddleware: Middleware<AuthSessionUser>;
4
+ export declare const requireSession: Middleware<AuthSessionUser>;
5
+ export declare const redirectAuthMiddleware: Middleware<AuthSessionUser>;
6
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,eAAO,MAAM,yBAAyB,EAAE,UAAU,CAAC,eAAe,CAMjE,CAAA;AAED,eAAO,MAAM,cAAc,6BAA4B,CAAA;AAEvD,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,eAAe,CAM9D,CAAA"}
package/dist/routes.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const routes = Object.entries({
2
- .../* @__PURE__ */ Object.assign({ "./api/sign-in/handler.ts": () => import("./handler-BD2C82Z3.js"), "./api/sign-out/handler.ts": () => import("./handler-42q87FS8.js"), "./api/sign-up/handler.ts": () => import("./handler-C7htSfmB.js") })
2
+ .../* @__PURE__ */ Object.assign({ "./api/me/handler.ts": () => import("./handler-Ba3pgtfZ.js"), "./api/sign-in/handler.ts": () => import("./handler-r4ZECW_z.js"), "./api/sign-out/handler.ts": () => import("./handler-CNHucHrj.js"), "./api/sign-up/handler.ts": () => import("./handler-CE4lXc0G.js"), "./api/verify-otp/handler.ts": () => import("./handler-DOnLMd-9.js") })
3
3
  }).reduce((acc, [path, mod]) => {
4
4
  acc[path.replace("./api/", "@rpcbase/auth/api/")] = mod;
5
5
  return acc;
@@ -2975,6 +2975,7 @@ function superRefine(fn) {
2975
2975
  return _superRefine(fn);
2976
2976
  }
2977
2977
  export {
2978
+ array as a,
2978
2979
  boolean as b,
2979
2980
  object as o,
2980
2981
  string as s
@@ -0,0 +1,7 @@
1
+ export type AuthSessionUser = {
2
+ id: string;
3
+ current_tenant_id: string;
4
+ signed_in_tenants: string[];
5
+ is_entry_gate_authorized: boolean;
6
+ };
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,wBAAwB,EAAE,OAAO,CAAA;CAClC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/auth",
3
- "version": "0.44.0",
3
+ "version": "0.46.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -38,6 +38,13 @@
38
38
  "dist/"
39
39
  ]
40
40
  },
41
+ "build-watch": {
42
+ "command": "../../node_modules/.bin/vite build --watch",
43
+ "service": true,
44
+ "dependencies": [
45
+ "build"
46
+ ]
47
+ },
41
48
  "release": {
42
49
  "command": "../../scripts/publish.js",
43
50
  "dependencies": [
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/EmailOrPhoneInput/index.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,GAAI,iCAI/B;IACD,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,4CA6BA,CAAA"}
@@ -1,17 +0,0 @@
1
- import { i as isEmail } from "./isEmail-IG0hXiQk.js";
2
- import { R as Route, r as requestSchema } from "./index-oIC-DH2m.js";
3
- const signIn = async (payload, ctx) => {
4
- const { email_or_phone } = requestSchema.parse(payload);
5
- if (isEmail(email_or_phone)) {
6
- console.log("is valid email");
7
- } else {
8
- console.log("is not valid email");
9
- }
10
- return { success: true };
11
- };
12
- const handler = (api) => {
13
- api.post(Route, signIn);
14
- };
15
- export {
16
- handler as default
17
- };
@@ -1,32 +0,0 @@
1
- import crypto from "crypto";
2
- import { i as isEmail } from "./isEmail-IG0hXiQk.js";
3
- import { loadModel } from "@rpcbase/api";
4
- import { hashPassword } from "@rpcbase/server";
5
- import { R as Route, r as requestSchema } from "./index-Nc4R1TKZ.js";
6
- const signUp = async (payload, ctx) => {
7
- const User = await loadModel("User", ctx);
8
- const { email_or_phone, password } = requestSchema.parse(payload);
9
- const is_email = isEmail(email_or_phone);
10
- const query = is_email ? { email: email_or_phone } : { phone: email_or_phone };
11
- const existingUser = await User.findOne(query);
12
- if (existingUser) {
13
- console.log("user with email or phone already exists", email_or_phone);
14
- return { success: false };
15
- }
16
- const salt = crypto.randomBytes(16).toString("hex");
17
- const derivedKey = await hashPassword(password, salt);
18
- const hashedPassword = `${salt}:${derivedKey.toString("hex")}`;
19
- const user = new User({
20
- ...query,
21
- password: hashedPassword
22
- });
23
- await user.save();
24
- console.log("created new user", user._id.toString());
25
- return { success: true };
26
- };
27
- const handler = (api) => {
28
- api.post(Route, signUp);
29
- };
30
- export {
31
- handler as default
32
- };
@@ -1,25 +0,0 @@
1
- import { i as isValidNumber } from "./isValidNumber-6pMDGLRn.js";
2
- import { o as object, s as string, b as boolean } from "./schemas-7XFc7XYG.js";
3
- const Route = "/api/rb/auth/sign-up";
4
- const requestSchema = object({
5
- email_or_phone: string().nonempty("Email or phone number is required").refine(
6
- (value) => {
7
- const isEmail = string().email().safeParse(value).success;
8
- const isPhone = isValidNumber(value);
9
- return isEmail || isPhone;
10
- },
11
- "Please enter a valid email address or phone number"
12
- ),
13
- password: string().min(8, { message: "Password must be at least 8 characters long." }),
14
- password_confirmation: string().nonempty({ message: "Please confirm your password." })
15
- }).refine((data) => data.password === data.password_confirmation, {
16
- message: "Passwords do not match.",
17
- path: ["password_confirmation"]
18
- });
19
- object({
20
- success: boolean()
21
- });
22
- export {
23
- Route as R,
24
- requestSchema as r
25
- };
@@ -1,21 +0,0 @@
1
- import { i as isValidNumber } from "./isValidNumber-6pMDGLRn.js";
2
- import { o as object, b as boolean, s as string } from "./schemas-7XFc7XYG.js";
3
- const Route = "/api/rb/auth/sign-in";
4
- const requestSchema = object({
5
- email_or_phone: string().nonempty("Email or phone number is required").default("").refine(
6
- (value) => {
7
- const isEmail = string().email().safeParse(value).success;
8
- const isPhone = isValidNumber(value);
9
- return isEmail || isPhone;
10
- },
11
- "Please enter a valid email address or phone number"
12
- ),
13
- remember_me: boolean().default(true)
14
- });
15
- object({
16
- success: boolean()
17
- });
18
- export {
19
- Route as R,
20
- requestSchema as r
21
- };