@monocloud/auth-nextjs 0.1.9 → 0.1.11

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 (97) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-C0xms8kb.cjs → _virtual/_rolldown/runtime.cjs} +1 -6
  3. package/dist/client/index.cjs +3 -2
  4. package/dist/client/index.d.mts +3 -203
  5. package/dist/client/index.mjs +2 -1
  6. package/dist/{protect-client-page-BdsnH8gs.cjs → client/protect-client-page.cjs} +9 -112
  7. package/dist/client/protect-client-page.cjs.map +1 -0
  8. package/dist/client/protect-client-page.d.mts +123 -0
  9. package/dist/{protect-client-page-BFVskb3X.mjs → client/protect-client-page.mjs} +5 -91
  10. package/dist/client/protect-client-page.mjs.map +1 -0
  11. package/dist/client/use-auth.cjs +96 -0
  12. package/dist/client/use-auth.cjs.map +1 -0
  13. package/dist/client/use-auth.d.mts +84 -0
  14. package/dist/client/use-auth.mjs +94 -0
  15. package/dist/client/use-auth.mjs.map +1 -0
  16. package/dist/components/client/index.cjs +4 -156
  17. package/dist/components/client/index.d.mts +3 -189
  18. package/dist/components/client/index.mjs +3 -153
  19. package/dist/components/client/protected.cjs +89 -0
  20. package/dist/components/client/protected.cjs.map +1 -0
  21. package/dist/components/client/protected.d.mts +114 -0
  22. package/dist/components/client/protected.mjs +87 -0
  23. package/dist/components/client/protected.mjs.map +1 -0
  24. package/dist/components/client/redirect-to-signin.cjs +77 -0
  25. package/dist/components/client/redirect-to-signin.cjs.map +1 -0
  26. package/dist/components/client/redirect-to-signin.d.mts +78 -0
  27. package/dist/components/client/redirect-to-signin.mjs +76 -0
  28. package/dist/components/client/redirect-to-signin.mjs.map +1 -0
  29. package/dist/components/index.cjs +6 -168
  30. package/dist/components/index.d.mts +4 -188
  31. package/dist/components/index.mjs +4 -164
  32. package/dist/components/signin.cjs +63 -0
  33. package/dist/components/signin.cjs.map +1 -0
  34. package/dist/components/signin.d.mts +72 -0
  35. package/dist/components/signin.mjs +61 -0
  36. package/dist/components/signin.mjs.map +1 -0
  37. package/dist/components/signout.cjs +49 -0
  38. package/dist/components/signout.cjs.map +1 -0
  39. package/dist/components/signout.d.mts +55 -0
  40. package/dist/components/signout.mjs +47 -0
  41. package/dist/components/signout.mjs.map +1 -0
  42. package/dist/components/signup.cjs +67 -0
  43. package/dist/components/signup.cjs.map +1 -0
  44. package/dist/components/signup.d.mts +70 -0
  45. package/dist/components/signup.mjs +65 -0
  46. package/dist/components/signup.mjs.map +1 -0
  47. package/dist/index.cjs +15 -1136
  48. package/dist/index.d.mts +5 -1681
  49. package/dist/index.mjs +4 -1125
  50. package/dist/initialize.cjs +284 -0
  51. package/dist/initialize.cjs.map +1 -0
  52. package/dist/initialize.d.mts +1383 -0
  53. package/dist/initialize.mjs +274 -0
  54. package/dist/initialize.mjs.map +1 -0
  55. package/dist/monocloud-next-client.cjs +600 -0
  56. package/dist/monocloud-next-client.cjs.map +1 -0
  57. package/dist/monocloud-next-client.d.mts +330 -0
  58. package/dist/monocloud-next-client.mjs +599 -0
  59. package/dist/monocloud-next-client.mjs.map +1 -0
  60. package/dist/requests/monocloud-app-router-request.cjs +32 -0
  61. package/dist/requests/monocloud-app-router-request.cjs.map +1 -0
  62. package/dist/requests/monocloud-app-router-request.mjs +31 -0
  63. package/dist/requests/monocloud-app-router-request.mjs.map +1 -0
  64. package/dist/requests/monocloud-cookie-request.cjs +22 -0
  65. package/dist/requests/monocloud-cookie-request.cjs.map +1 -0
  66. package/dist/requests/monocloud-cookie-request.mjs +21 -0
  67. package/dist/requests/monocloud-cookie-request.mjs.map +1 -0
  68. package/dist/requests/monocloud-page-router-request.cjs +37 -0
  69. package/dist/requests/monocloud-page-router-request.cjs.map +1 -0
  70. package/dist/requests/monocloud-page-router-request.mjs +36 -0
  71. package/dist/requests/monocloud-page-router-request.mjs.map +1 -0
  72. package/dist/responses/monocloud-app-router-response.cjs +67 -0
  73. package/dist/responses/monocloud-app-router-response.cjs.map +1 -0
  74. package/dist/responses/monocloud-app-router-response.mjs +66 -0
  75. package/dist/responses/monocloud-app-router-response.mjs.map +1 -0
  76. package/dist/responses/monocloud-cookie-response.cjs +20 -0
  77. package/dist/responses/monocloud-cookie-response.cjs.map +1 -0
  78. package/dist/responses/monocloud-cookie-response.mjs +19 -0
  79. package/dist/responses/monocloud-cookie-response.mjs.map +1 -0
  80. package/dist/responses/monocloud-page-router-response.cjs +54 -0
  81. package/dist/responses/monocloud-page-router-response.cjs.map +1 -0
  82. package/dist/responses/monocloud-page-router-response.mjs +53 -0
  83. package/dist/responses/monocloud-page-router-response.mjs.map +1 -0
  84. package/dist/{types-ClljFIvK.d.mts → types.d.mts} +2 -2
  85. package/dist/utils.cjs +89 -0
  86. package/dist/utils.cjs.map +1 -0
  87. package/dist/utils.mjs +80 -0
  88. package/dist/utils.mjs.map +1 -0
  89. package/package.json +3 -3
  90. package/dist/components/client/index.cjs.map +0 -1
  91. package/dist/components/client/index.mjs.map +0 -1
  92. package/dist/components/index.cjs.map +0 -1
  93. package/dist/components/index.mjs.map +0 -1
  94. package/dist/index.cjs.map +0 -1
  95. package/dist/index.mjs.map +0 -1
  96. package/dist/protect-client-page-BFVskb3X.mjs.map +0 -1
  97. package/dist/protect-client-page-BdsnH8gs.cjs.map +0 -1
package/README.md CHANGED
@@ -29,7 +29,7 @@ This SDK is designed specifically for **Next.js**, providing first-class integra
29
29
 
30
30
  - **Documentation:** [https://www.monocloud.com/docs](https://www.monocloud.com/docs?utm_source=github&utm_medium=auth_js)
31
31
  - **Quickstart:** [https://www.monocloud.com/docs/quickstarts/nextjs-app-router](https://www.monocloud.com/docs/quickstarts/nextjs-app-router?utm_source=github&utm_medium=auth_js)
32
- - **SDK Reference:** [https://www.monocloud.com/docs/sdk-reference/nextjs](https://www.monocloud.com/docs/sdk-reference/nextjs/index?utm_source=github&utm_medium=auth_js)
32
+ - **SDK Reference:** [https://www.monocloud.com/docs/sdks/nextjs](https://www.monocloud.com/docs/sdks/nextjs/index?utm_source=github&utm_medium=auth_js)
33
33
  - **API Reference:** [https://monocloud.github.io/auth-js](https://monocloud.github.io/auth-js?utm_source=github&utm_medium=auth_js)
34
34
 
35
35
  ## Supported Platforms
@@ -26,9 +26,4 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
 
27
27
  //#endregion
28
28
 
29
- Object.defineProperty(exports, '__toESM', {
30
- enumerable: true,
31
- get: function () {
32
- return __toESM;
33
- }
34
- });
29
+ exports.__toESM = __toESM;
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_protect_client_page = require('../protect-client-page-BdsnH8gs.cjs');
2
+ const require_use_auth = require('./use-auth.cjs');
3
+ const require_protect_client_page = require('./protect-client-page.cjs');
3
4
 
4
5
  exports.protectClientPage = require_protect_client_page.protectClientPage;
5
- exports.useAuth = require_protect_client_page.useAuth;
6
+ exports.useAuth = require_use_auth.useAuth;
@@ -1,203 +1,3 @@
1
- import { c as ExtraAuthParams, l as GroupOptions } from "../types-ClljFIvK.mjs";
2
- import { MonoCloudUser } from "@monocloud/auth-node-core";
3
- import React, { ComponentType } from "react";
4
-
5
- //#region src/client/use-auth.d.ts
6
- /**
7
- * Authentication State returned by `useAuth` hook.
8
- *
9
- * @category Types
10
- */
11
- interface AuthenticationState {
12
- /**
13
- * Flag indicating if the authentication state is still loading.
14
- */
15
- isLoading: boolean;
16
- /**
17
- * Flag indicating if the user is authenticated.
18
- */
19
- isAuthenticated: boolean;
20
- /**
21
- * Error encountered during authentication, if any.
22
- */
23
- error?: Error;
24
- /**
25
- * The authenticated user's information, if available.
26
- */
27
- user?: MonoCloudUser;
28
- /**
29
- * Function to refetch the authentication state.
30
- *
31
- */
32
- refetch: (refresh?: boolean) => void;
33
- }
34
- /**
35
- *
36
- * `useAuth()` is a client-side hook that provides access to the current authentication state.
37
- *
38
- * It can only be used inside **Client Components**.
39
- *
40
- * @example Basic Usage
41
- * ```tsx title="Basic Usage"
42
- * "use client";
43
- *
44
- * import { useAuth } from "@monocloud/auth-nextjs/client";
45
- *
46
- * export default function Home() {
47
- * const { user, isAuthenticated } = useAuth();
48
- *
49
- * if (!isAuthenticated) {
50
- * return <>Not signed in</>;
51
- * }
52
- *
53
- * return <>User Id: {user?.sub}</>;
54
- * }
55
- * ```
56
- *
57
- * @example Refetch user
58
- *
59
- * Calling `refetch(true)` forces a refresh of the user profile from the `UserInfo` endpoint.
60
- * Calling `refetch()` refreshes authentication state without forcing a `UserInfo` request.
61
- *
62
- * ```tsx title="Refetch User"
63
- * "use client";
64
- *
65
- * import { useAuth } from "@monocloud/auth-nextjs/client";
66
- *
67
- * export default function Home() {
68
- * const { user, refetch } = useAuth();
69
- *
70
- * return (
71
- * <>
72
- * <pre>{JSON.stringify(user, null, 2)}</pre>
73
- * <button onClick={() => refetch(true)}>Refresh Profile</button>
74
- * </>
75
- * );
76
- * }
77
- * ```
78
- *
79
- * @returns
80
- *
81
- * @category Hooks
82
- */
83
- declare const useAuth: () => AuthenticationState;
84
- //#endregion
85
- //#region src/client/protect-client-page.d.ts
86
- /**
87
- * Options for configuring page protection.
88
- *
89
- * @category Types
90
- */
91
- interface ProtectClientPageOptions extends GroupOptions {
92
- /**
93
- * The URL where the user will be redirected to after sign in.
94
- */
95
- returnUrl?: string;
96
- /**
97
- * A custom react element to render when the user is not authenticated.
98
- */
99
- onAccessDenied?: () => React.ReactNode;
100
- /**
101
- * A custom react element to render when the user is authenticated but does not belong to the required groups.
102
- */
103
- onGroupAccessDenied?: (user: MonoCloudUser) => React.ReactNode;
104
- /**
105
- * Authorization parameters to be used during authentication.
106
- */
107
- authParams?: ExtraAuthParams;
108
- /**
109
- * Callback function to handle errors.
110
- * If not provided, errors will be thrown.
111
- *
112
- * @param error - The error object.
113
- * @returns JSX element to handle the error.
114
- */
115
- onError?: (error: Error) => React.ReactNode;
116
- }
117
- /**
118
- * `protectClientPage()` wraps a **client-rendered page component** and ensures that only authenticated users can access it.
119
- *
120
- * If the user is authenticated, the wrapped component receives a `user` prop.
121
- *
122
- * > This function runs on the client and controls rendering only.
123
- * > To enforce access before rendering (server-side), use the server {@link MonoCloudNextClient.protectPage | protectPage()} method on {@link MonoCloudNextClient}.
124
- *
125
- * @example Basic Usage
126
- *
127
- * ```tsx title="Basic Usage"
128
- * "use client";
129
- *
130
- * import { protectClientPage } from "@monocloud/auth-nextjs/client";
131
- *
132
- * export default protectClientPage(function Home({ user }) {
133
- * return <>Signed in as {user.email}</>;
134
- * });
135
- * ```
136
- *
137
- * @example With Options
138
- *
139
- * ```tsx title="With Options"
140
- * "use client";
141
- *
142
- * import { protectClientPage } from "@monocloud/auth-nextjs/client";
143
- *
144
- * export default protectClientPage(
145
- * function Home({ user }) {
146
- * return <>Signed in as {user.email}</>;
147
- * },
148
- * {
149
- * returnUrl: "/dashboard",
150
- * authParams: { loginHint: "user@example.com" }
151
- * }
152
- * );
153
- * ```
154
- *
155
- * @example Custom access denied UI
156
- *
157
- * ```tsx title="Custom access denied UI"
158
- * "use client";
159
- *
160
- * import { protectClientPage } from "@monocloud/auth-nextjs/client";
161
- *
162
- * export default protectClientPage(
163
- * function Home({ user }) {
164
- * return <>Signed in as {user.email}</>;
165
- * },
166
- * {
167
- * onAccessDenied: () => <div>Please sign in to continue</div>
168
- * }
169
- * );
170
- * ```
171
- *
172
- * @example Group protection
173
- *
174
- * ```tsx title="Group protection"
175
- * "use client";
176
- *
177
- * import { protectClientPage } from "@monocloud/auth-nextjs/client";
178
- *
179
- * export default protectClientPage(
180
- * function Home({ user }) {
181
- * return <>Welcome Admin {user.email}</>;
182
- * },
183
- * {
184
- * groups: ["admin"],
185
- * onGroupAccessDenied: (user) => <div>User {user.email} is not an admin</div>
186
- * }
187
- * );
188
- * ```
189
- *
190
- * @param Component - The page component to protect
191
- * @typeParam P - Props of the protected component (excluding `user`).
192
- * @param options - Optional configuration
193
- * @returns A protected React component.
194
- *
195
- * @category Functions
196
- *
197
- */
198
- declare const protectClientPage: <P extends object>(Component: ComponentType<P & {
199
- user: MonoCloudUser;
200
- }>, options?: ProtectClientPageOptions) => React.FC<P>;
201
- //#endregion
202
- export { type AuthenticationState, type ProtectClientPageOptions, protectClientPage, useAuth };
203
- //# sourceMappingURL=index.d.mts.map
1
+ import { AuthenticationState, useAuth } from "./use-auth.mjs";
2
+ import { ProtectClientPageOptions, protectClientPage } from "./protect-client-page.mjs";
3
+ export { type AuthenticationState, type ProtectClientPageOptions, protectClientPage, useAuth };
@@ -1,3 +1,4 @@
1
- import { r as useAuth, t as protectClientPage } from "../protect-client-page-BFVskb3X.mjs";
1
+ import { useAuth } from "./use-auth.mjs";
2
+ import { protectClientPage } from "./protect-client-page.mjs";
2
3
 
3
4
  export { protectClientPage, useAuth };
@@ -1,98 +1,11 @@
1
- const require_chunk = require('./chunk-C0xms8kb.cjs');
1
+ 'use client';
2
+
3
+ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
4
+ const require_use_auth = require('./use-auth.cjs');
2
5
  let _monocloud_auth_node_core_utils = require("@monocloud/auth-node-core/utils");
3
- let swr = require("swr");
4
- swr = require_chunk.__toESM(swr);
5
6
  let react = require("react");
6
- react = require_chunk.__toESM(react);
7
+ react = require_runtime.__toESM(react);
7
8
 
8
- //#region src/client/use-auth.tsx
9
- const fetchUser = async (url) => {
10
- const res = await fetch(url, { credentials: "include" });
11
- if (res.status === 204) return;
12
- if (res.ok) return res.json();
13
- throw new Error("Failed to fetch user");
14
- };
15
- /**
16
- *
17
- * `useAuth()` is a client-side hook that provides access to the current authentication state.
18
- *
19
- * It can only be used inside **Client Components**.
20
- *
21
- * @example Basic Usage
22
- * ```tsx title="Basic Usage"
23
- * "use client";
24
- *
25
- * import { useAuth } from "@monocloud/auth-nextjs/client";
26
- *
27
- * export default function Home() {
28
- * const { user, isAuthenticated } = useAuth();
29
- *
30
- * if (!isAuthenticated) {
31
- * return <>Not signed in</>;
32
- * }
33
- *
34
- * return <>User Id: {user?.sub}</>;
35
- * }
36
- * ```
37
- *
38
- * @example Refetch user
39
- *
40
- * Calling `refetch(true)` forces a refresh of the user profile from the `UserInfo` endpoint.
41
- * Calling `refetch()` refreshes authentication state without forcing a `UserInfo` request.
42
- *
43
- * ```tsx title="Refetch User"
44
- * "use client";
45
- *
46
- * import { useAuth } from "@monocloud/auth-nextjs/client";
47
- *
48
- * export default function Home() {
49
- * const { user, refetch } = useAuth();
50
- *
51
- * return (
52
- * <>
53
- * <pre>{JSON.stringify(user, null, 2)}</pre>
54
- * <button onClick={() => refetch(true)}>Refresh Profile</button>
55
- * </>
56
- * );
57
- * }
58
- * ```
59
- *
60
- * @returns
61
- *
62
- * @category Hooks
63
- */
64
- const useAuth = () => {
65
- const key = process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/userinfo`;
66
- const { data, error, isLoading, mutate } = (0, swr.default)(key, fetchUser);
67
- const refetch = (refresh) => {
68
- const url = new URL(key, "https://dummy");
69
- if (refresh) url.searchParams.set("refresh", "true");
70
- mutate(async () => await fetchUser(url.pathname + url.search), { revalidate: false });
71
- };
72
- if (error) return {
73
- user: void 0,
74
- isLoading: false,
75
- isAuthenticated: false,
76
- error,
77
- refetch
78
- };
79
- if (data) return {
80
- user: data,
81
- isLoading,
82
- isAuthenticated: !!data && Object.keys(data).length > 0,
83
- error: void 0,
84
- refetch
85
- };
86
- return {
87
- user: void 0,
88
- isLoading,
89
- isAuthenticated: false,
90
- error: void 0,
91
- refetch: () => {}
92
- };
93
- };
94
-
95
- //#endregion
96
9
  //#region src/client/protect-client-page.tsx
97
10
  const redirectToSignIn = (options) => {
98
11
  const searchParams = new URLSearchParams(window.location.search);
@@ -197,7 +110,7 @@ const handlePageError = (error, options) => {
197
110
  */
198
111
  const protectClientPage = (Component, options) => {
199
112
  return (props) => {
200
- const { user, error, isLoading } = useAuth();
113
+ const { user, error, isLoading } = require_use_auth.useAuth();
201
114
  (0, react.useEffect)(() => {
202
115
  if (!user && !isLoading && !error) {
203
116
  if (options === null || options === void 0 ? void 0 : options.onAccessDenied) return;
@@ -229,22 +142,6 @@ const protectClientPage = (Component, options) => {
229
142
  };
230
143
 
231
144
  //#endregion
232
- Object.defineProperty(exports, 'protectClientPage', {
233
- enumerable: true,
234
- get: function () {
235
- return protectClientPage;
236
- }
237
- });
238
- Object.defineProperty(exports, 'redirectToSignIn', {
239
- enumerable: true,
240
- get: function () {
241
- return redirectToSignIn;
242
- }
243
- });
244
- Object.defineProperty(exports, 'useAuth', {
245
- enumerable: true,
246
- get: function () {
247
- return useAuth;
248
- }
249
- });
250
- //# sourceMappingURL=protect-client-page-BdsnH8gs.cjs.map
145
+ exports.protectClientPage = protectClientPage;
146
+ exports.redirectToSignIn = redirectToSignIn;
147
+ //# sourceMappingURL=protect-client-page.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protect-client-page.cjs","names":["useAuth"],"sources":["../../src/client/protect-client-page.tsx"],"sourcesContent":["/* eslint-disable react/display-name */\n'use client';\n\nimport React, { ComponentType, useEffect } from 'react';\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport { useAuth } from './use-auth';\nimport { ExtraAuthParams, GroupOptions } from '../types';\nimport type { MonoCloudNextClient } from '../monocloud-next-client';\n\n/**\n * Options for configuring page protection.\n *\n * @category Types\n */\nexport interface ProtectClientPageOptions extends GroupOptions {\n /**\n * The URL where the user will be redirected to after sign in.\n */\n returnUrl?: string;\n\n /**\n * A custom react element to render when the user is not authenticated.\n */\n onAccessDenied?: () => React.ReactNode;\n\n /**\n * A custom react element to render when the user is authenticated but does not belong to the required groups.\n */\n onGroupAccessDenied?: (user: MonoCloudUser) => React.ReactNode;\n\n /**\n * Authorization parameters to be used during authentication.\n */\n authParams?: ExtraAuthParams;\n\n /**\n * Callback function to handle errors.\n * If not provided, errors will be thrown.\n *\n * @param error - The error object.\n * @returns JSX element to handle the error.\n */\n onError?: (error: Error) => React.ReactNode;\n}\n\nexport const redirectToSignIn = (\n options: { returnUrl?: string } & ExtraAuthParams\n): void => {\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.set(\n 'return_url',\n options.returnUrl ?? window.location.toString()\n );\n\n if (options?.scopes) {\n searchParams.set('scope', options.scopes);\n }\n if (options?.resource) {\n searchParams.set('resource', options.resource);\n }\n\n if (options?.acrValues) {\n searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.display) {\n searchParams.set('display', options.display);\n }\n\n if (options?.prompt) {\n searchParams.set('prompt', options.prompt);\n }\n\n if (options?.authenticatorHint) {\n searchParams.set('authenticator_hint', options.authenticatorHint);\n }\n\n if (options?.uiLocales) {\n searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (options?.maxAge) {\n searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.loginHint) {\n searchParams.set('login_hint', options.loginHint);\n }\n\n window.location.assign(\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/signin`}?${searchParams.toString()}`\n );\n};\n\nconst handlePageError = (\n error: Error,\n options?: ProtectClientPageOptions\n): React.ReactNode => {\n /* v8 ignore else -- @preserve */\n if (options?.onError) {\n return options.onError(error);\n }\n\n /* v8 ignore next -- @preserve */\n throw error;\n};\n\n/**\n * `protectClientPage()` wraps a **client-rendered page component** and ensures that only authenticated users can access it.\n *\n * If the user is authenticated, the wrapped component receives a `user` prop.\n *\n * > This function runs on the client and controls rendering only.\n * > To enforce access before rendering (server-side), use the server {@link MonoCloudNextClient.protectPage | protectPage()} method on {@link MonoCloudNextClient}.\n *\n * @example Basic Usage\n *\n * ```tsx title=\"Basic Usage\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * });\n * ```\n *\n * @example With Options\n *\n * ```tsx title=\"With Options\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * },\n * {\n * returnUrl: \"/dashboard\",\n * authParams: { loginHint: \"user@example.com\" }\n * }\n * );\n * ```\n *\n * @example Custom access denied UI\n *\n * ```tsx title=\"Custom access denied UI\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * },\n * {\n * onAccessDenied: () => <div>Please sign in to continue</div>\n * }\n * );\n * ```\n *\n * @example Group protection\n *\n * ```tsx title=\"Group protection\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Welcome Admin {user.email}</>;\n * },\n * {\n * groups: [\"admin\"],\n * onGroupAccessDenied: (user) => <div>User {user.email} is not an admin</div>\n * }\n * );\n * ```\n *\n * @param Component - The page component to protect\n * @typeParam P - Props of the protected component (excluding `user`).\n * @param options - Optional configuration\n * @returns A protected React component.\n *\n * @category Functions\n *\n */\nexport const protectClientPage = <P extends object>(\n Component: ComponentType<P & { user: MonoCloudUser }>,\n options?: ProtectClientPageOptions\n): React.FC<P> => {\n return props => {\n const { user, error, isLoading } = useAuth();\n\n useEffect(() => {\n if (!user && !isLoading && !error) {\n if (options?.onAccessDenied) {\n return;\n }\n\n const authParams = options?.authParams ?? {};\n redirectToSignIn({\n returnUrl: options?.returnUrl,\n ...authParams,\n });\n }\n }, [user, isLoading, error]);\n\n if (error) {\n return handlePageError(error, options);\n }\n\n if (!user && !isLoading && options?.onAccessDenied) {\n return options.onAccessDenied();\n }\n\n if (user) {\n if (\n options?.groups &&\n !isUserInGroup(\n user,\n options.groups,\n options.groupsClaim ??\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const {\n onGroupAccessDenied = (): React.ReactNode => <div>Access Denied</div>,\n } = options;\n return onGroupAccessDenied(user);\n }\n\n return <Component user={user} {...props} />;\n }\n\n return null;\n };\n};\n"],"mappings":";;;;;;;;;AA8CA,MAAa,oBACX,YACS;CACT,MAAM,eAAe,IAAI,gBAAgB,OAAO,SAAS,OAAO;AAChE,cAAa,IACX,cACA,QAAQ,aAAa,OAAO,SAAS,UAAU,CAChD;AAED,uDAAI,QAAS,OACX,cAAa,IAAI,SAAS,QAAQ,OAAO;AAE3C,uDAAI,QAAS,SACX,cAAa,IAAI,YAAY,QAAQ,SAAS;AAGhD,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU,KAAK,IAAI,CAAC;AAG7D,uDAAI,QAAS,QACX,cAAa,IAAI,WAAW,QAAQ,QAAQ;AAG9C,uDAAI,QAAS,OACX,cAAa,IAAI,UAAU,QAAQ,OAAO;AAG5C,uDAAI,QAAS,kBACX,cAAa,IAAI,sBAAsB,QAAQ,kBAAkB;AAGnE,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU;AAGnD,uDAAI,QAAS,OACX,cAAa,IAAI,WAAW,QAAQ,OAAO,UAAU,CAAC;AAGxD,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU;AAGnD,QAAO,SAAS,OAEd,GAAG,QAAQ,IAAI,yCAAyC,GAAG,QAAQ,IAAI,0BAA0B,GAAG,kBAAkB,GAAG,aAAa,UAAU,GACjJ;;AAGH,MAAM,mBACJ,OACA,YACoB;;AAEpB,uDAAI,QAAS,QACX,QAAO,QAAQ,QAAQ,MAAM;;AAI/B,OAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFR,MAAa,qBACX,WACA,YACgB;AAChB,SAAO,UAAS;EACd,MAAM,EAAE,MAAM,OAAO,cAAcA,0BAAS;AAE5C,6BAAgB;AACd,OAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO;AACjC,0DAAI,QAAS,eACX;IAGF,MAAM,gEAAa,QAAS,eAAc,EAAE;AAC5C,qBAAiB;KACf,6DAAW,QAAS;KACpB,GAAG;KACJ,CAAC;;KAEH;GAAC;GAAM;GAAW;GAAM,CAAC;AAE5B,MAAI,MACF,QAAO,gBAAgB,OAAO,QAAQ;AAGxC,MAAI,CAAC,QAAQ,CAAC,gEAAa,QAAS,gBAClC,QAAO,QAAQ,gBAAgB;AAGjC,MAAI,MAAM;AACR,0DACE,QAAS,WACT,oDACE,MACA,QAAQ,QACR,QAAQ,eACN,QAAQ,IAAI,yCACd,QAAQ,SACT,EACD;IACA,MAAM,EACJ,4BAA6C,4CAAC,aAAI,gBAAmB,KACnE;AACJ,WAAO,oBAAoB,KAAK;;AAGlC,UAAO,4CAAC;IAAgB;IAAM,GAAI;KAAS;;AAG7C,SAAO"}
@@ -0,0 +1,123 @@
1
+ import { ExtraAuthParams, GroupOptions } from "../types.mjs";
2
+ import { MonoCloudUser } from "@monocloud/auth-node-core";
3
+ import React, { ComponentType } from "react";
4
+
5
+ //#region src/client/protect-client-page.d.ts
6
+ /**
7
+ * Options for configuring page protection.
8
+ *
9
+ * @category Types
10
+ */
11
+ interface ProtectClientPageOptions extends GroupOptions {
12
+ /**
13
+ * The URL where the user will be redirected to after sign in.
14
+ */
15
+ returnUrl?: string;
16
+ /**
17
+ * A custom react element to render when the user is not authenticated.
18
+ */
19
+ onAccessDenied?: () => React.ReactNode;
20
+ /**
21
+ * A custom react element to render when the user is authenticated but does not belong to the required groups.
22
+ */
23
+ onGroupAccessDenied?: (user: MonoCloudUser) => React.ReactNode;
24
+ /**
25
+ * Authorization parameters to be used during authentication.
26
+ */
27
+ authParams?: ExtraAuthParams;
28
+ /**
29
+ * Callback function to handle errors.
30
+ * If not provided, errors will be thrown.
31
+ *
32
+ * @param error - The error object.
33
+ * @returns JSX element to handle the error.
34
+ */
35
+ onError?: (error: Error) => React.ReactNode;
36
+ }
37
+ /**
38
+ * `protectClientPage()` wraps a **client-rendered page component** and ensures that only authenticated users can access it.
39
+ *
40
+ * If the user is authenticated, the wrapped component receives a `user` prop.
41
+ *
42
+ * > This function runs on the client and controls rendering only.
43
+ * > To enforce access before rendering (server-side), use the server {@link MonoCloudNextClient.protectPage | protectPage()} method on {@link MonoCloudNextClient}.
44
+ *
45
+ * @example Basic Usage
46
+ *
47
+ * ```tsx title="Basic Usage"
48
+ * "use client";
49
+ *
50
+ * import { protectClientPage } from "@monocloud/auth-nextjs/client";
51
+ *
52
+ * export default protectClientPage(function Home({ user }) {
53
+ * return <>Signed in as {user.email}</>;
54
+ * });
55
+ * ```
56
+ *
57
+ * @example With Options
58
+ *
59
+ * ```tsx title="With Options"
60
+ * "use client";
61
+ *
62
+ * import { protectClientPage } from "@monocloud/auth-nextjs/client";
63
+ *
64
+ * export default protectClientPage(
65
+ * function Home({ user }) {
66
+ * return <>Signed in as {user.email}</>;
67
+ * },
68
+ * {
69
+ * returnUrl: "/dashboard",
70
+ * authParams: { loginHint: "user@example.com" }
71
+ * }
72
+ * );
73
+ * ```
74
+ *
75
+ * @example Custom access denied UI
76
+ *
77
+ * ```tsx title="Custom access denied UI"
78
+ * "use client";
79
+ *
80
+ * import { protectClientPage } from "@monocloud/auth-nextjs/client";
81
+ *
82
+ * export default protectClientPage(
83
+ * function Home({ user }) {
84
+ * return <>Signed in as {user.email}</>;
85
+ * },
86
+ * {
87
+ * onAccessDenied: () => <div>Please sign in to continue</div>
88
+ * }
89
+ * );
90
+ * ```
91
+ *
92
+ * @example Group protection
93
+ *
94
+ * ```tsx title="Group protection"
95
+ * "use client";
96
+ *
97
+ * import { protectClientPage } from "@monocloud/auth-nextjs/client";
98
+ *
99
+ * export default protectClientPage(
100
+ * function Home({ user }) {
101
+ * return <>Welcome Admin {user.email}</>;
102
+ * },
103
+ * {
104
+ * groups: ["admin"],
105
+ * onGroupAccessDenied: (user) => <div>User {user.email} is not an admin</div>
106
+ * }
107
+ * );
108
+ * ```
109
+ *
110
+ * @param Component - The page component to protect
111
+ * @typeParam P - Props of the protected component (excluding `user`).
112
+ * @param options - Optional configuration
113
+ * @returns A protected React component.
114
+ *
115
+ * @category Functions
116
+ *
117
+ */
118
+ declare const protectClientPage: <P extends object>(Component: ComponentType<P & {
119
+ user: MonoCloudUser;
120
+ }>, options?: ProtectClientPageOptions) => React.FC<P>;
121
+ //#endregion
122
+ export { ProtectClientPageOptions, protectClientPage };
123
+ //# sourceMappingURL=protect-client-page.d.mts.map
@@ -1,95 +1,9 @@
1
+ 'use client';
2
+
3
+ import { useAuth } from "./use-auth.mjs";
1
4
  import { isUserInGroup } from "@monocloud/auth-node-core/utils";
2
- import useSWR from "swr";
3
5
  import React, { useEffect } from "react";
4
6
 
5
- //#region src/client/use-auth.tsx
6
- const fetchUser = async (url) => {
7
- const res = await fetch(url, { credentials: "include" });
8
- if (res.status === 204) return;
9
- if (res.ok) return res.json();
10
- throw new Error("Failed to fetch user");
11
- };
12
- /**
13
- *
14
- * `useAuth()` is a client-side hook that provides access to the current authentication state.
15
- *
16
- * It can only be used inside **Client Components**.
17
- *
18
- * @example Basic Usage
19
- * ```tsx title="Basic Usage"
20
- * "use client";
21
- *
22
- * import { useAuth } from "@monocloud/auth-nextjs/client";
23
- *
24
- * export default function Home() {
25
- * const { user, isAuthenticated } = useAuth();
26
- *
27
- * if (!isAuthenticated) {
28
- * return <>Not signed in</>;
29
- * }
30
- *
31
- * return <>User Id: {user?.sub}</>;
32
- * }
33
- * ```
34
- *
35
- * @example Refetch user
36
- *
37
- * Calling `refetch(true)` forces a refresh of the user profile from the `UserInfo` endpoint.
38
- * Calling `refetch()` refreshes authentication state without forcing a `UserInfo` request.
39
- *
40
- * ```tsx title="Refetch User"
41
- * "use client";
42
- *
43
- * import { useAuth } from "@monocloud/auth-nextjs/client";
44
- *
45
- * export default function Home() {
46
- * const { user, refetch } = useAuth();
47
- *
48
- * return (
49
- * <>
50
- * <pre>{JSON.stringify(user, null, 2)}</pre>
51
- * <button onClick={() => refetch(true)}>Refresh Profile</button>
52
- * </>
53
- * );
54
- * }
55
- * ```
56
- *
57
- * @returns
58
- *
59
- * @category Hooks
60
- */
61
- const useAuth = () => {
62
- const key = process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/userinfo`;
63
- const { data, error, isLoading, mutate } = useSWR(key, fetchUser);
64
- const refetch = (refresh) => {
65
- const url = new URL(key, "https://dummy");
66
- if (refresh) url.searchParams.set("refresh", "true");
67
- mutate(async () => await fetchUser(url.pathname + url.search), { revalidate: false });
68
- };
69
- if (error) return {
70
- user: void 0,
71
- isLoading: false,
72
- isAuthenticated: false,
73
- error,
74
- refetch
75
- };
76
- if (data) return {
77
- user: data,
78
- isLoading,
79
- isAuthenticated: !!data && Object.keys(data).length > 0,
80
- error: void 0,
81
- refetch
82
- };
83
- return {
84
- user: void 0,
85
- isLoading,
86
- isAuthenticated: false,
87
- error: void 0,
88
- refetch: () => {}
89
- };
90
- };
91
-
92
- //#endregion
93
7
  //#region src/client/protect-client-page.tsx
94
8
  const redirectToSignIn = (options) => {
95
9
  const searchParams = new URLSearchParams(window.location.search);
@@ -226,5 +140,5 @@ const protectClientPage = (Component, options) => {
226
140
  };
227
141
 
228
142
  //#endregion
229
- export { redirectToSignIn as n, useAuth as r, protectClientPage as t };
230
- //# sourceMappingURL=protect-client-page-BFVskb3X.mjs.map
143
+ export { protectClientPage, redirectToSignIn };
144
+ //# sourceMappingURL=protect-client-page.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protect-client-page.mjs","names":[],"sources":["../../src/client/protect-client-page.tsx"],"sourcesContent":["/* eslint-disable react/display-name */\n'use client';\n\nimport React, { ComponentType, useEffect } from 'react';\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport { useAuth } from './use-auth';\nimport { ExtraAuthParams, GroupOptions } from '../types';\nimport type { MonoCloudNextClient } from '../monocloud-next-client';\n\n/**\n * Options for configuring page protection.\n *\n * @category Types\n */\nexport interface ProtectClientPageOptions extends GroupOptions {\n /**\n * The URL where the user will be redirected to after sign in.\n */\n returnUrl?: string;\n\n /**\n * A custom react element to render when the user is not authenticated.\n */\n onAccessDenied?: () => React.ReactNode;\n\n /**\n * A custom react element to render when the user is authenticated but does not belong to the required groups.\n */\n onGroupAccessDenied?: (user: MonoCloudUser) => React.ReactNode;\n\n /**\n * Authorization parameters to be used during authentication.\n */\n authParams?: ExtraAuthParams;\n\n /**\n * Callback function to handle errors.\n * If not provided, errors will be thrown.\n *\n * @param error - The error object.\n * @returns JSX element to handle the error.\n */\n onError?: (error: Error) => React.ReactNode;\n}\n\nexport const redirectToSignIn = (\n options: { returnUrl?: string } & ExtraAuthParams\n): void => {\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.set(\n 'return_url',\n options.returnUrl ?? window.location.toString()\n );\n\n if (options?.scopes) {\n searchParams.set('scope', options.scopes);\n }\n if (options?.resource) {\n searchParams.set('resource', options.resource);\n }\n\n if (options?.acrValues) {\n searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.display) {\n searchParams.set('display', options.display);\n }\n\n if (options?.prompt) {\n searchParams.set('prompt', options.prompt);\n }\n\n if (options?.authenticatorHint) {\n searchParams.set('authenticator_hint', options.authenticatorHint);\n }\n\n if (options?.uiLocales) {\n searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (options?.maxAge) {\n searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.loginHint) {\n searchParams.set('login_hint', options.loginHint);\n }\n\n window.location.assign(\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/signin`}?${searchParams.toString()}`\n );\n};\n\nconst handlePageError = (\n error: Error,\n options?: ProtectClientPageOptions\n): React.ReactNode => {\n /* v8 ignore else -- @preserve */\n if (options?.onError) {\n return options.onError(error);\n }\n\n /* v8 ignore next -- @preserve */\n throw error;\n};\n\n/**\n * `protectClientPage()` wraps a **client-rendered page component** and ensures that only authenticated users can access it.\n *\n * If the user is authenticated, the wrapped component receives a `user` prop.\n *\n * > This function runs on the client and controls rendering only.\n * > To enforce access before rendering (server-side), use the server {@link MonoCloudNextClient.protectPage | protectPage()} method on {@link MonoCloudNextClient}.\n *\n * @example Basic Usage\n *\n * ```tsx title=\"Basic Usage\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * });\n * ```\n *\n * @example With Options\n *\n * ```tsx title=\"With Options\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * },\n * {\n * returnUrl: \"/dashboard\",\n * authParams: { loginHint: \"user@example.com\" }\n * }\n * );\n * ```\n *\n * @example Custom access denied UI\n *\n * ```tsx title=\"Custom access denied UI\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Signed in as {user.email}</>;\n * },\n * {\n * onAccessDenied: () => <div>Please sign in to continue</div>\n * }\n * );\n * ```\n *\n * @example Group protection\n *\n * ```tsx title=\"Group protection\"\n * \"use client\";\n *\n * import { protectClientPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectClientPage(\n * function Home({ user }) {\n * return <>Welcome Admin {user.email}</>;\n * },\n * {\n * groups: [\"admin\"],\n * onGroupAccessDenied: (user) => <div>User {user.email} is not an admin</div>\n * }\n * );\n * ```\n *\n * @param Component - The page component to protect\n * @typeParam P - Props of the protected component (excluding `user`).\n * @param options - Optional configuration\n * @returns A protected React component.\n *\n * @category Functions\n *\n */\nexport const protectClientPage = <P extends object>(\n Component: ComponentType<P & { user: MonoCloudUser }>,\n options?: ProtectClientPageOptions\n): React.FC<P> => {\n return props => {\n const { user, error, isLoading } = useAuth();\n\n useEffect(() => {\n if (!user && !isLoading && !error) {\n if (options?.onAccessDenied) {\n return;\n }\n\n const authParams = options?.authParams ?? {};\n redirectToSignIn({\n returnUrl: options?.returnUrl,\n ...authParams,\n });\n }\n }, [user, isLoading, error]);\n\n if (error) {\n return handlePageError(error, options);\n }\n\n if (!user && !isLoading && options?.onAccessDenied) {\n return options.onAccessDenied();\n }\n\n if (user) {\n if (\n options?.groups &&\n !isUserInGroup(\n user,\n options.groups,\n options.groupsClaim ??\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const {\n onGroupAccessDenied = (): React.ReactNode => <div>Access Denied</div>,\n } = options;\n return onGroupAccessDenied(user);\n }\n\n return <Component user={user} {...props} />;\n }\n\n return null;\n };\n};\n"],"mappings":";;;;;;;AA8CA,MAAa,oBACX,YACS;CACT,MAAM,eAAe,IAAI,gBAAgB,OAAO,SAAS,OAAO;AAChE,cAAa,IACX,cACA,QAAQ,aAAa,OAAO,SAAS,UAAU,CAChD;AAED,uDAAI,QAAS,OACX,cAAa,IAAI,SAAS,QAAQ,OAAO;AAE3C,uDAAI,QAAS,SACX,cAAa,IAAI,YAAY,QAAQ,SAAS;AAGhD,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU,KAAK,IAAI,CAAC;AAG7D,uDAAI,QAAS,QACX,cAAa,IAAI,WAAW,QAAQ,QAAQ;AAG9C,uDAAI,QAAS,OACX,cAAa,IAAI,UAAU,QAAQ,OAAO;AAG5C,uDAAI,QAAS,kBACX,cAAa,IAAI,sBAAsB,QAAQ,kBAAkB;AAGnE,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU;AAGnD,uDAAI,QAAS,OACX,cAAa,IAAI,WAAW,QAAQ,OAAO,UAAU,CAAC;AAGxD,uDAAI,QAAS,UACX,cAAa,IAAI,cAAc,QAAQ,UAAU;AAGnD,QAAO,SAAS,OAEd,GAAG,QAAQ,IAAI,yCAAyC,GAAG,QAAQ,IAAI,0BAA0B,GAAG,kBAAkB,GAAG,aAAa,UAAU,GACjJ;;AAGH,MAAM,mBACJ,OACA,YACoB;;AAEpB,uDAAI,QAAS,QACX,QAAO,QAAQ,QAAQ,MAAM;;AAI/B,OAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFR,MAAa,qBACX,WACA,YACgB;AAChB,SAAO,UAAS;EACd,MAAM,EAAE,MAAM,OAAO,cAAc,SAAS;AAE5C,kBAAgB;AACd,OAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO;AACjC,0DAAI,QAAS,eACX;IAGF,MAAM,gEAAa,QAAS,eAAc,EAAE;AAC5C,qBAAiB;KACf,6DAAW,QAAS;KACpB,GAAG;KACJ,CAAC;;KAEH;GAAC;GAAM;GAAW;GAAM,CAAC;AAE5B,MAAI,MACF,QAAO,gBAAgB,OAAO,QAAQ;AAGxC,MAAI,CAAC,QAAQ,CAAC,gEAAa,QAAS,gBAClC,QAAO,QAAQ,gBAAgB;AAGjC,MAAI,MAAM;AACR,0DACE,QAAS,WACT,CAAC,cACC,MACA,QAAQ,QACR,QAAQ,eACN,QAAQ,IAAI,yCACd,QAAQ,SACT,EACD;IACA,MAAM,EACJ,4BAA6C,oCAAC,aAAI,gBAAmB,KACnE;AACJ,WAAO,oBAAoB,KAAK;;AAGlC,UAAO,oCAAC;IAAgB;IAAM,GAAI;KAAS;;AAG7C,SAAO"}