naystack 1.5.9 → 1.5.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.
- package/README.md +646 -91
- package/dist/auth/constants.d.mts +4 -0
- package/dist/auth/constants.d.ts +4 -0
- package/dist/auth/email/client.d.mts +149 -0
- package/dist/auth/email/client.d.ts +149 -0
- package/dist/auth/email/index.cjs.js +2 -20
- package/dist/auth/email/index.d.mts +41 -1
- package/dist/auth/email/index.d.ts +41 -1
- package/dist/auth/email/index.esm.js +1 -17
- package/dist/auth/email/routes/delete.cjs.js +0 -1
- package/dist/auth/email/routes/delete.d.mts +5 -0
- package/dist/auth/email/routes/delete.d.ts +5 -0
- package/dist/auth/email/routes/delete.esm.js +0 -1
- package/dist/auth/email/routes/get.d.mts +5 -0
- package/dist/auth/email/routes/get.d.ts +5 -0
- package/dist/auth/email/routes/post.cjs.js +0 -1
- package/dist/auth/email/routes/post.d.mts +5 -0
- package/dist/auth/email/routes/post.d.ts +5 -0
- package/dist/auth/email/routes/post.esm.js +0 -1
- package/dist/auth/email/routes/put.cjs.js +0 -1
- package/dist/auth/email/routes/put.d.mts +5 -0
- package/dist/auth/email/routes/put.d.ts +5 -0
- package/dist/auth/email/routes/put.esm.js +0 -1
- package/dist/auth/email/token.d.mts +62 -0
- package/dist/auth/email/token.d.ts +62 -0
- package/dist/auth/email/types.d.mts +22 -0
- package/dist/auth/email/types.d.ts +22 -0
- package/dist/auth/email/utils.cjs.js +0 -18
- package/dist/auth/email/utils.d.mts +41 -3
- package/dist/auth/email/utils.d.ts +41 -3
- package/dist/auth/email/utils.esm.js +0 -16
- package/dist/auth/google/get.d.mts +5 -0
- package/dist/auth/google/get.d.ts +5 -0
- package/dist/auth/google/index.d.mts +39 -0
- package/dist/auth/google/index.d.ts +39 -0
- package/dist/auth/index.cjs.js +4 -22
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.esm.js +3 -19
- package/dist/auth/instagram/client.d.mts +19 -0
- package/dist/auth/instagram/client.d.ts +19 -0
- package/dist/auth/instagram/index.d.mts +37 -0
- package/dist/auth/instagram/index.d.ts +37 -0
- package/dist/auth/instagram/route.d.mts +5 -0
- package/dist/auth/instagram/route.d.ts +5 -0
- package/dist/auth/instagram/utils.d.mts +13 -0
- package/dist/auth/instagram/utils.d.ts +13 -0
- package/dist/auth/types.d.mts +24 -0
- package/dist/auth/types.d.ts +24 -0
- package/dist/auth/utils/errors.d.mts +10 -0
- package/dist/auth/utils/errors.d.ts +10 -0
- package/dist/auth/utils/token.d.mts +20 -0
- package/dist/auth/utils/token.d.ts +20 -0
- package/dist/client/hooks.d.mts +59 -0
- package/dist/client/hooks.d.ts +59 -0
- package/dist/client/seo.d.mts +46 -0
- package/dist/client/seo.d.ts +46 -0
- package/dist/env.d.mts +61 -0
- package/dist/env.d.ts +61 -0
- package/dist/file/client.d.mts +53 -1
- package/dist/file/client.d.ts +53 -1
- package/dist/file/index.cjs.js +0 -1
- package/dist/file/index.esm.js +0 -1
- package/dist/file/put.cjs.js +0 -1
- package/dist/file/put.d.mts +11 -0
- package/dist/file/put.d.ts +11 -0
- package/dist/file/put.esm.js +0 -1
- package/dist/file/setup.cjs.js +0 -1
- package/dist/file/setup.d.mts +48 -0
- package/dist/file/setup.d.ts +48 -0
- package/dist/file/setup.esm.js +0 -1
- package/dist/file/utils.d.mts +41 -0
- package/dist/file/utils.d.ts +41 -0
- package/dist/graphql/client.d.mts +113 -0
- package/dist/graphql/client.d.ts +113 -0
- package/dist/graphql/errors.d.mts +26 -0
- package/dist/graphql/errors.d.ts +26 -0
- package/dist/graphql/index.cjs.js +2 -3
- package/dist/graphql/index.esm.js +2 -3
- package/dist/graphql/init.cjs.js +0 -1
- package/dist/graphql/init.d.mts +33 -0
- package/dist/graphql/init.d.ts +33 -0
- package/dist/graphql/init.esm.js +0 -1
- package/dist/graphql/server.d.mts +88 -0
- package/dist/graphql/server.d.ts +88 -0
- package/dist/graphql/types.d.mts +21 -0
- package/dist/graphql/types.d.ts +21 -0
- package/dist/graphql/utils.d.mts +217 -0
- package/dist/graphql/utils.d.ts +217 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/socials/instagram/getters.d.mts +115 -0
- package/dist/socials/instagram/getters.d.ts +115 -0
- package/dist/socials/instagram/setters.d.mts +18 -0
- package/dist/socials/instagram/setters.d.ts +18 -0
- package/dist/socials/instagram/types.d.mts +46 -0
- package/dist/socials/instagram/types.d.ts +46 -0
- package/dist/socials/instagram/utils.d.mts +19 -0
- package/dist/socials/instagram/utils.d.ts +19 -0
- package/dist/socials/instagram/webhook.d.mts +31 -0
- package/dist/socials/instagram/webhook.d.ts +31 -0
- package/dist/socials/meta-webhook.d.mts +11 -0
- package/dist/socials/meta-webhook.d.ts +11 -0
- package/dist/socials/threads/getters.d.mts +57 -0
- package/dist/socials/threads/getters.d.ts +57 -0
- package/dist/socials/threads/setters.d.mts +59 -0
- package/dist/socials/threads/setters.d.ts +59 -0
- package/dist/socials/threads/types.d.mts +9 -0
- package/dist/socials/threads/types.d.ts +9 -0
- package/dist/socials/threads/utils.d.mts +19 -0
- package/dist/socials/threads/utils.d.ts +19 -0
- package/dist/socials/threads/webhook.d.mts +30 -0
- package/dist/socials/threads/webhook.d.ts +30 -0
- package/package.json +9 -5
package/dist/auth/index.esm.js
CHANGED
|
@@ -125,7 +125,6 @@ async function checkAuthStatus(redirectUnauthorizedURL) {
|
|
|
125
125
|
|
|
126
126
|
// src/auth/email/utils.ts
|
|
127
127
|
import { verify as verify2 } from "jsonwebtoken";
|
|
128
|
-
import { cookies as cookies2 } from "next/headers";
|
|
129
128
|
|
|
130
129
|
// src/auth/utils/errors.ts
|
|
131
130
|
import { NextResponse as NextResponse2 } from "next/server";
|
|
@@ -202,19 +201,6 @@ var getContext = (req) => {
|
|
|
202
201
|
}
|
|
203
202
|
return { userId: null };
|
|
204
203
|
};
|
|
205
|
-
async function logout(data) {
|
|
206
|
-
const Cookie = await cookies2();
|
|
207
|
-
Cookie.delete(REFRESH_COOKIE_NAME);
|
|
208
|
-
await fetch(getEnv("NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */), {
|
|
209
|
-
method: "DELETE",
|
|
210
|
-
credentials: "include",
|
|
211
|
-
body: JSON.stringify(data)
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
async function getCurrentRefreshToken() {
|
|
215
|
-
const Cookie = await cookies2();
|
|
216
|
-
return Cookie.get(REFRESH_COOKIE_NAME)?.value;
|
|
217
|
-
}
|
|
218
204
|
|
|
219
205
|
// src/auth/email/routes/delete.ts
|
|
220
206
|
var getDeleteRoute = (options) => async (req) => {
|
|
@@ -498,18 +484,16 @@ function initInstagramAuth(props) {
|
|
|
498
484
|
}
|
|
499
485
|
|
|
500
486
|
// src/auth/utils/token.ts
|
|
501
|
-
import { cookies as
|
|
487
|
+
import { cookies as cookies2 } from "next/headers";
|
|
502
488
|
async function getRefreshToken() {
|
|
503
|
-
const Cookie = await
|
|
489
|
+
const Cookie = await cookies2();
|
|
504
490
|
return Cookie.get(REFRESH_COOKIE_NAME)?.value || null;
|
|
505
491
|
}
|
|
506
492
|
export {
|
|
507
493
|
checkAuthStatus,
|
|
508
494
|
getContext,
|
|
509
|
-
getCurrentRefreshToken,
|
|
510
495
|
getEmailAuthRoutes,
|
|
511
496
|
getRefreshToken,
|
|
512
497
|
initGoogleAuth,
|
|
513
|
-
initInstagramAuth
|
|
514
|
-
logout
|
|
498
|
+
initInstagramAuth
|
|
515
499
|
};
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a function that builds the Instagram OAuth authorization URL for a given state token.
|
|
3
|
+
* The state token is typically the user's access token, used to link the Instagram account to the logged-in user.
|
|
4
|
+
*
|
|
5
|
+
* @param redirectURL - The OAuth redirect URI registered with Instagram (e.g. `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`).
|
|
6
|
+
* @returns A function `(stateToken: string) => string` that returns the full authorization URL.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { getInstagramAuthorizationURLSetup } from "naystack/auth/instagram/client";
|
|
11
|
+
*
|
|
12
|
+
* const getAuthURL = getInstagramAuthorizationURLSetup("/api/instagram");
|
|
13
|
+
* const url = getAuthURL(userAccessToken);
|
|
14
|
+
* // => "https://www.instagram.com/oauth/authorize?client_id=...&state=...&redirect_uri=..."
|
|
15
|
+
* window.location.href = url;
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @category Auth
|
|
19
|
+
*/
|
|
1
20
|
declare const getInstagramAuthorizationURLSetup: (redirectURL: string) => (token: string) => string;
|
|
2
21
|
|
|
3
22
|
export { getInstagramAuthorizationURLSetup };
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a function that builds the Instagram OAuth authorization URL for a given state token.
|
|
3
|
+
* The state token is typically the user's access token, used to link the Instagram account to the logged-in user.
|
|
4
|
+
*
|
|
5
|
+
* @param redirectURL - The OAuth redirect URI registered with Instagram (e.g. `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`).
|
|
6
|
+
* @returns A function `(stateToken: string) => string` that returns the full authorization URL.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { getInstagramAuthorizationURLSetup } from "naystack/auth/instagram/client";
|
|
11
|
+
*
|
|
12
|
+
* const getAuthURL = getInstagramAuthorizationURLSetup("/api/instagram");
|
|
13
|
+
* const url = getAuthURL(userAccessToken);
|
|
14
|
+
* // => "https://www.instagram.com/oauth/authorize?client_id=...&state=...&redirect_uri=..."
|
|
15
|
+
* window.location.href = url;
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @category Auth
|
|
19
|
+
*/
|
|
1
20
|
declare const getInstagramAuthorizationURLSetup: (redirectURL: string) => (token: string) => string;
|
|
2
21
|
|
|
3
22
|
export { getInstagramAuthorizationURLSetup };
|
|
@@ -2,12 +2,49 @@ import * as next_server from 'next/server';
|
|
|
2
2
|
import { getRefreshedAccessToken } from './utils.mjs';
|
|
3
3
|
import { InstagramUser } from '../../socials/instagram/types.mjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for initializing Instagram OAuth via {@link initInstagramAuth}.
|
|
7
|
+
*
|
|
8
|
+
* @property onUser - Called with `(instagramUser, appUserId, accessToken)` after successful OAuth. Return a string to show as error (redirects to `errorRedirectURL`); return `void` on success.
|
|
9
|
+
* @property successRedirectURL - Where to redirect after successful Instagram auth.
|
|
10
|
+
* @property errorRedirectURL - Where to redirect on error (with `?error=` query param).
|
|
11
|
+
* @property refreshKey - Your app secret (e.g. `REFRESH_KEY` env var) used in the flow.
|
|
12
|
+
*
|
|
13
|
+
* @category Auth
|
|
14
|
+
*/
|
|
5
15
|
interface InitInstagramAuthOptions {
|
|
6
16
|
onUser: (data: InstagramUser, id: number | null, accessToken: string) => Promise<string | void>;
|
|
7
17
|
successRedirectURL: string;
|
|
8
18
|
errorRedirectURL: string;
|
|
9
19
|
refreshKey: string;
|
|
10
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Initializes Instagram OAuth. Returns a GET handler for the OAuth callback and a helper to refresh long-lived tokens.
|
|
23
|
+
*
|
|
24
|
+
* Mount the GET handler on your Instagram auth route (e.g. `app/api/(auth)/instagram/route.ts`).
|
|
25
|
+
*
|
|
26
|
+
* Requires env vars: `INSTAGRAM_CLIENT_ID`, `INSTAGRAM_CLIENT_SECRET`, `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`.
|
|
27
|
+
*
|
|
28
|
+
* @param props - Options. See {@link InitInstagramAuthOptions}.
|
|
29
|
+
* @returns Object with `GET` (route handler) and `getRefreshedAccessToken` (refreshes a long-lived token).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // app/api/(auth)/instagram/route.ts
|
|
34
|
+
* import { initInstagramAuth } from "naystack/auth";
|
|
35
|
+
*
|
|
36
|
+
* export const { GET, getRefreshedAccessToken } = initInstagramAuth({
|
|
37
|
+
* onUser: async (igUser, appUserId, accessToken) => {
|
|
38
|
+
* await saveInstagramUser(appUserId, igUser, accessToken);
|
|
39
|
+
* },
|
|
40
|
+
* successRedirectURL: "/dashboard",
|
|
41
|
+
* errorRedirectURL: "/login",
|
|
42
|
+
* refreshKey: process.env.REFRESH_KEY!,
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @category Auth
|
|
47
|
+
*/
|
|
11
48
|
declare function initInstagramAuth(props: InitInstagramAuthOptions): {
|
|
12
49
|
GET: (req: next_server.NextRequest) => Promise<next_server.NextResponse<unknown>>;
|
|
13
50
|
getRefreshedAccessToken: typeof getRefreshedAccessToken;
|
|
@@ -2,12 +2,49 @@ import * as next_server from 'next/server';
|
|
|
2
2
|
import { getRefreshedAccessToken } from './utils.js';
|
|
3
3
|
import { InstagramUser } from '../../socials/instagram/types.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for initializing Instagram OAuth via {@link initInstagramAuth}.
|
|
7
|
+
*
|
|
8
|
+
* @property onUser - Called with `(instagramUser, appUserId, accessToken)` after successful OAuth. Return a string to show as error (redirects to `errorRedirectURL`); return `void` on success.
|
|
9
|
+
* @property successRedirectURL - Where to redirect after successful Instagram auth.
|
|
10
|
+
* @property errorRedirectURL - Where to redirect on error (with `?error=` query param).
|
|
11
|
+
* @property refreshKey - Your app secret (e.g. `REFRESH_KEY` env var) used in the flow.
|
|
12
|
+
*
|
|
13
|
+
* @category Auth
|
|
14
|
+
*/
|
|
5
15
|
interface InitInstagramAuthOptions {
|
|
6
16
|
onUser: (data: InstagramUser, id: number | null, accessToken: string) => Promise<string | void>;
|
|
7
17
|
successRedirectURL: string;
|
|
8
18
|
errorRedirectURL: string;
|
|
9
19
|
refreshKey: string;
|
|
10
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Initializes Instagram OAuth. Returns a GET handler for the OAuth callback and a helper to refresh long-lived tokens.
|
|
23
|
+
*
|
|
24
|
+
* Mount the GET handler on your Instagram auth route (e.g. `app/api/(auth)/instagram/route.ts`).
|
|
25
|
+
*
|
|
26
|
+
* Requires env vars: `INSTAGRAM_CLIENT_ID`, `INSTAGRAM_CLIENT_SECRET`, `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`.
|
|
27
|
+
*
|
|
28
|
+
* @param props - Options. See {@link InitInstagramAuthOptions}.
|
|
29
|
+
* @returns Object with `GET` (route handler) and `getRefreshedAccessToken` (refreshes a long-lived token).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // app/api/(auth)/instagram/route.ts
|
|
34
|
+
* import { initInstagramAuth } from "naystack/auth";
|
|
35
|
+
*
|
|
36
|
+
* export const { GET, getRefreshedAccessToken } = initInstagramAuth({
|
|
37
|
+
* onUser: async (igUser, appUserId, accessToken) => {
|
|
38
|
+
* await saveInstagramUser(appUserId, igUser, accessToken);
|
|
39
|
+
* },
|
|
40
|
+
* successRedirectURL: "/dashboard",
|
|
41
|
+
* errorRedirectURL: "/login",
|
|
42
|
+
* refreshKey: process.env.REFRESH_KEY!,
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @category Auth
|
|
47
|
+
*/
|
|
11
48
|
declare function initInstagramAuth(props: InitInstagramAuthOptions): {
|
|
12
49
|
GET: (req: next_server.NextRequest) => Promise<next_server.NextResponse<unknown>>;
|
|
13
50
|
getRefreshedAccessToken: typeof getRefreshedAccessToken;
|
|
@@ -3,6 +3,11 @@ import { InitInstagramAuthOptions } from './index.mjs';
|
|
|
3
3
|
import './utils.mjs';
|
|
4
4
|
import '../../socials/instagram/types.mjs';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Returns the GET route handler for Instagram OAuth callback.
|
|
8
|
+
* @param options - InitInstagramAuthOptions (onUser, redirect URLs)
|
|
9
|
+
* @returns Async route handler for the OAuth callback
|
|
10
|
+
*/
|
|
6
11
|
declare const getInstagramRoute: ({ successRedirectURL, errorRedirectURL, onUser, }: InitInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
7
12
|
|
|
8
13
|
export { getInstagramRoute };
|
|
@@ -3,6 +3,11 @@ import { InitInstagramAuthOptions } from './index.js';
|
|
|
3
3
|
import './utils.js';
|
|
4
4
|
import '../../socials/instagram/types.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Returns the GET route handler for Instagram OAuth callback.
|
|
8
|
+
* @param options - InitInstagramAuthOptions (onUser, redirect URLs)
|
|
9
|
+
* @returns Async route handler for the OAuth callback
|
|
10
|
+
*/
|
|
6
11
|
declare const getInstagramRoute: ({ successRedirectURL, errorRedirectURL, onUser, }: InitInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
7
12
|
|
|
8
13
|
export { getInstagramRoute };
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
3
|
+
* @param token - Current long-lived access token
|
|
4
|
+
* @returns New access token or undefined
|
|
5
|
+
*/
|
|
1
6
|
declare function getRefreshedAccessToken(token: string): Promise<string | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* Exchanges an OAuth code for a long-lived Instagram access token.
|
|
9
|
+
* @param code - OAuth authorization code from redirect
|
|
10
|
+
* @param redirectURL - Registered redirect URI
|
|
11
|
+
* @param clientId - Instagram app client id
|
|
12
|
+
* @param clientSecret - Instagram app client secret
|
|
13
|
+
* @returns Object with accessToken and userId, or undefined
|
|
14
|
+
*/
|
|
2
15
|
declare function getLongLivedToken(code: string, redirectURL: string, clientId: string, clientSecret: string): Promise<{
|
|
3
16
|
accessToken: string;
|
|
4
17
|
userId: string;
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
3
|
+
* @param token - Current long-lived access token
|
|
4
|
+
* @returns New access token or undefined
|
|
5
|
+
*/
|
|
1
6
|
declare function getRefreshedAccessToken(token: string): Promise<string | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* Exchanges an OAuth code for a long-lived Instagram access token.
|
|
9
|
+
* @param code - OAuth authorization code from redirect
|
|
10
|
+
* @param redirectURL - Registered redirect URI
|
|
11
|
+
* @param clientId - Instagram app client id
|
|
12
|
+
* @param clientSecret - Instagram app client secret
|
|
13
|
+
* @returns Object with accessToken and userId, or undefined
|
|
14
|
+
*/
|
|
2
15
|
declare function getLongLivedToken(code: string, redirectURL: string, clientId: string, clientSecret: string): Promise<{
|
|
3
16
|
accessToken: string;
|
|
4
17
|
userId: string;
|
package/dist/auth/types.d.mts
CHANGED
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Custom error handler for auth routes. Return a NextResponse to send a custom error; otherwise the default response is used.
|
|
5
|
+
*
|
|
6
|
+
* @param error - Object with `status` (HTTP code) and `message` (error text).
|
|
7
|
+
* @returns NextResponse to override the default error, or undefined to use the default.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const onError: ErrorHandler = ({ status, message }) => {
|
|
12
|
+
* if (status === 400) return NextResponse.json({ error: message }, { status: 400 });
|
|
13
|
+
* return undefined; // Use default handling
|
|
14
|
+
* };
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @category Auth
|
|
18
|
+
*/
|
|
3
19
|
type ErrorHandler = (error: {
|
|
4
20
|
status: number;
|
|
5
21
|
message: string;
|
|
6
22
|
}) => NextResponse;
|
|
23
|
+
/**
|
|
24
|
+
* Shape expected from `getUser` / `createUser` callbacks: at least `id` and optional `password` hash, plus any extra fields.
|
|
25
|
+
*
|
|
26
|
+
* @property id - User id (numeric primary key).
|
|
27
|
+
* @property password - Bcrypt-hashed password, or `null` for OAuth-only users.
|
|
28
|
+
*
|
|
29
|
+
* @category Auth
|
|
30
|
+
*/
|
|
7
31
|
type UserOutput = {
|
|
8
32
|
id: number;
|
|
9
33
|
password: string | null;
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Custom error handler for auth routes. Return a NextResponse to send a custom error; otherwise the default response is used.
|
|
5
|
+
*
|
|
6
|
+
* @param error - Object with `status` (HTTP code) and `message` (error text).
|
|
7
|
+
* @returns NextResponse to override the default error, or undefined to use the default.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const onError: ErrorHandler = ({ status, message }) => {
|
|
12
|
+
* if (status === 400) return NextResponse.json({ error: message }, { status: 400 });
|
|
13
|
+
* return undefined; // Use default handling
|
|
14
|
+
* };
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @category Auth
|
|
18
|
+
*/
|
|
3
19
|
type ErrorHandler = (error: {
|
|
4
20
|
status: number;
|
|
5
21
|
message: string;
|
|
6
22
|
}) => NextResponse;
|
|
23
|
+
/**
|
|
24
|
+
* Shape expected from `getUser` / `createUser` callbacks: at least `id` and optional `password` hash, plus any extra fields.
|
|
25
|
+
*
|
|
26
|
+
* @property id - User id (numeric primary key).
|
|
27
|
+
* @property password - Bcrypt-hashed password, or `null` for OAuth-only users.
|
|
28
|
+
*
|
|
29
|
+
* @category Auth
|
|
30
|
+
*/
|
|
7
31
|
type UserOutput = {
|
|
8
32
|
id: number;
|
|
9
33
|
password: string | null;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { ErrorHandler } from '../types.mjs';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Creates a NextResponse for an error, or delegates to a custom `onError` handler if provided.
|
|
6
|
+
* Used internally by auth routes for consistent error handling.
|
|
7
|
+
*
|
|
8
|
+
* @param status - HTTP status code.
|
|
9
|
+
* @param message - Error message body.
|
|
10
|
+
* @param onError - Optional custom handler; if it returns a Response, that is used instead of the default.
|
|
11
|
+
* @returns NextResponse with the given status and message, or the custom handler's response.
|
|
12
|
+
* @category Auth
|
|
13
|
+
*/
|
|
4
14
|
declare function handleError(status: number, message: string, onError?: ErrorHandler): NextResponse<unknown>;
|
|
5
15
|
|
|
6
16
|
export { handleError };
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { ErrorHandler } from '../types.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Creates a NextResponse for an error, or delegates to a custom `onError` handler if provided.
|
|
6
|
+
* Used internally by auth routes for consistent error handling.
|
|
7
|
+
*
|
|
8
|
+
* @param status - HTTP status code.
|
|
9
|
+
* @param message - Error message body.
|
|
10
|
+
* @param onError - Optional custom handler; if it returns a Response, that is used instead of the default.
|
|
11
|
+
* @returns NextResponse with the given status and message, or the custom handler's response.
|
|
12
|
+
* @category Auth
|
|
13
|
+
*/
|
|
4
14
|
declare function handleError(status: number, message: string, onError?: ErrorHandler): NextResponse<unknown>;
|
|
5
15
|
|
|
6
16
|
export { handleError };
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the refresh token from cookies (server-side only). Use this in Server Components, layouts,
|
|
3
|
+
* or Server Actions to check if the user is authenticated.
|
|
4
|
+
*
|
|
5
|
+
* @returns The refresh token string, or `null` if no refresh cookie is present.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { getRefreshToken } from "naystack/auth";
|
|
10
|
+
* import { redirect } from "next/navigation";
|
|
11
|
+
*
|
|
12
|
+
* export default async function ProtectedLayout({ children }: { children: React.ReactNode }) {
|
|
13
|
+
* const token = await getRefreshToken();
|
|
14
|
+
* if (!token) return redirect("/login");
|
|
15
|
+
* return <div>{children}</div>;
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @category Auth
|
|
20
|
+
*/
|
|
1
21
|
declare function getRefreshToken(): Promise<string | null>;
|
|
2
22
|
|
|
3
23
|
export { getRefreshToken };
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the refresh token from cookies (server-side only). Use this in Server Components, layouts,
|
|
3
|
+
* or Server Actions to check if the user is authenticated.
|
|
4
|
+
*
|
|
5
|
+
* @returns The refresh token string, or `null` if no refresh cookie is present.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { getRefreshToken } from "naystack/auth";
|
|
10
|
+
* import { redirect } from "next/navigation";
|
|
11
|
+
*
|
|
12
|
+
* export default async function ProtectedLayout({ children }: { children: React.ReactNode }) {
|
|
13
|
+
* const token = await getRefreshToken();
|
|
14
|
+
* if (!token) return redirect("/login");
|
|
15
|
+
* return <div>{children}</div>;
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @category Auth
|
|
20
|
+
*/
|
|
1
21
|
declare function getRefreshToken(): Promise<string | null>;
|
|
2
22
|
|
|
3
23
|
export { getRefreshToken };
|
package/dist/client/hooks.d.mts
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Tracks when a DOM element enters the viewport and calls a callback.
|
|
5
|
+
* Uses `IntersectionObserver` with `rootMargin: "100px"` and `threshold: 0.1`.
|
|
6
|
+
*
|
|
7
|
+
* Attach the returned ref to the element you want to observe.
|
|
8
|
+
*
|
|
9
|
+
* @param onVisible - Optional callback invoked once when the observed element becomes visible.
|
|
10
|
+
* @returns A ref object to attach to the observed element (e.g. `<div ref={ref}>`).
|
|
11
|
+
*
|
|
12
|
+
* @example Lazy-load content when a section enters the viewport:
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { useVisibility } from "naystack/client";
|
|
15
|
+
*
|
|
16
|
+
* function LazySection() {
|
|
17
|
+
* const [loaded, setLoaded] = useState(false);
|
|
18
|
+
* const ref = useVisibility(() => setLoaded(true));
|
|
19
|
+
*
|
|
20
|
+
* return (
|
|
21
|
+
* <section ref={ref}>
|
|
22
|
+
* {loaded ? <HeavyContent /> : <Placeholder />}
|
|
23
|
+
* </section>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Trigger analytics when an element is seen:
|
|
29
|
+
* ```tsx
|
|
30
|
+
* const ref = useVisibility(() => trackImpression("hero-banner"));
|
|
31
|
+
* return <div ref={ref}>...</div>;
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @category Client
|
|
35
|
+
*/
|
|
3
36
|
declare function useVisibility(onVisible?: () => void): React.RefObject<null>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns whether a CSS media query currently matches. Useful for responsive behavior in JS.
|
|
39
|
+
*
|
|
40
|
+
* Returns `null` during SSR / before the first client-side check (to avoid hydration mismatches).
|
|
41
|
+
*
|
|
42
|
+
* @param query - A valid CSS media query string (e.g. `"(min-width: 768px)"`, `"(prefers-color-scheme: dark)"`).
|
|
43
|
+
* @returns `true` if the query matches, `false` if it doesn't, or `null` during SSR.
|
|
44
|
+
*
|
|
45
|
+
* @example Responsive navigation:
|
|
46
|
+
* ```tsx
|
|
47
|
+
* import { useBreakpoint } from "naystack/client";
|
|
48
|
+
*
|
|
49
|
+
* function ResponsiveNav() {
|
|
50
|
+
* const isMobile = useBreakpoint("(max-width: 639px)");
|
|
51
|
+
* if (isMobile === null) return <Skeleton />; // SSR fallback
|
|
52
|
+
* return isMobile ? <MobileNav /> : <DesktopNav />;
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example Detect user preferences:
|
|
57
|
+
* ```tsx
|
|
58
|
+
* const prefersReducedMotion = useBreakpoint("(prefers-reduced-motion: reduce)");
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @category Client
|
|
62
|
+
*/
|
|
4
63
|
declare function useBreakpoint(query: string): boolean | null;
|
|
5
64
|
|
|
6
65
|
export { useBreakpoint, useVisibility };
|
package/dist/client/hooks.d.ts
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Tracks when a DOM element enters the viewport and calls a callback.
|
|
5
|
+
* Uses `IntersectionObserver` with `rootMargin: "100px"` and `threshold: 0.1`.
|
|
6
|
+
*
|
|
7
|
+
* Attach the returned ref to the element you want to observe.
|
|
8
|
+
*
|
|
9
|
+
* @param onVisible - Optional callback invoked once when the observed element becomes visible.
|
|
10
|
+
* @returns A ref object to attach to the observed element (e.g. `<div ref={ref}>`).
|
|
11
|
+
*
|
|
12
|
+
* @example Lazy-load content when a section enters the viewport:
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { useVisibility } from "naystack/client";
|
|
15
|
+
*
|
|
16
|
+
* function LazySection() {
|
|
17
|
+
* const [loaded, setLoaded] = useState(false);
|
|
18
|
+
* const ref = useVisibility(() => setLoaded(true));
|
|
19
|
+
*
|
|
20
|
+
* return (
|
|
21
|
+
* <section ref={ref}>
|
|
22
|
+
* {loaded ? <HeavyContent /> : <Placeholder />}
|
|
23
|
+
* </section>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Trigger analytics when an element is seen:
|
|
29
|
+
* ```tsx
|
|
30
|
+
* const ref = useVisibility(() => trackImpression("hero-banner"));
|
|
31
|
+
* return <div ref={ref}>...</div>;
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @category Client
|
|
35
|
+
*/
|
|
3
36
|
declare function useVisibility(onVisible?: () => void): React.RefObject<null>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns whether a CSS media query currently matches. Useful for responsive behavior in JS.
|
|
39
|
+
*
|
|
40
|
+
* Returns `null` during SSR / before the first client-side check (to avoid hydration mismatches).
|
|
41
|
+
*
|
|
42
|
+
* @param query - A valid CSS media query string (e.g. `"(min-width: 768px)"`, `"(prefers-color-scheme: dark)"`).
|
|
43
|
+
* @returns `true` if the query matches, `false` if it doesn't, or `null` during SSR.
|
|
44
|
+
*
|
|
45
|
+
* @example Responsive navigation:
|
|
46
|
+
* ```tsx
|
|
47
|
+
* import { useBreakpoint } from "naystack/client";
|
|
48
|
+
*
|
|
49
|
+
* function ResponsiveNav() {
|
|
50
|
+
* const isMobile = useBreakpoint("(max-width: 639px)");
|
|
51
|
+
* if (isMobile === null) return <Skeleton />; // SSR fallback
|
|
52
|
+
* return isMobile ? <MobileNav /> : <DesktopNav />;
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example Detect user preferences:
|
|
57
|
+
* ```tsx
|
|
58
|
+
* const prefersReducedMotion = useBreakpoint("(prefers-reduced-motion: reduce)");
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @category Client
|
|
62
|
+
*/
|
|
4
63
|
declare function useBreakpoint(query: string): boolean | null;
|
|
5
64
|
|
|
6
65
|
export { useBreakpoint, useVisibility };
|
package/dist/client/seo.d.mts
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
import { Metadata } from 'next';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a metadata factory for Next.js pages. Call once with your site's default SEO config,
|
|
5
|
+
* then call the returned function per-page to generate the `Metadata` object.
|
|
6
|
+
*
|
|
7
|
+
* The returned function supports page-specific `title`, `description`, and `image` overrides.
|
|
8
|
+
* When a page title is provided, it's formatted as `"Page Title • Site Name"`.
|
|
9
|
+
*
|
|
10
|
+
* @param SEO - Base defaults for the whole site.
|
|
11
|
+
* @param SEO.title - Default document title (used when no page-specific title is provided).
|
|
12
|
+
* @param SEO.description - Default meta description.
|
|
13
|
+
* @param SEO.siteName - Application/site name (used in openGraph, twitter, and as the separator in titles).
|
|
14
|
+
* @param SEO.themeColor - Theme color for mobile browsers (e.g. `"#000000"`).
|
|
15
|
+
* @returns A function `(title?, description?, image?) => Metadata`. Pass page-specific overrides; they fill in or replace the defaults.
|
|
16
|
+
*
|
|
17
|
+
* @example Setup in a utility file:
|
|
18
|
+
* ```ts
|
|
19
|
+
* // lib/utils/seo.ts
|
|
20
|
+
* import { setupSEO } from "naystack/client";
|
|
21
|
+
*
|
|
22
|
+
* export const getSEO = setupSEO({
|
|
23
|
+
* title: "Land Exchange Toolbox - Premium Real Estate Tools",
|
|
24
|
+
* description: "Empower your real estate business with advanced tools.",
|
|
25
|
+
* siteName: "Land Exchange Toolbox",
|
|
26
|
+
* themeColor: "#5b9364",
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Usage in a page:
|
|
31
|
+
* ```ts
|
|
32
|
+
* // app/dashboard/page.tsx
|
|
33
|
+
* import { getSEO } from "@/lib/utils/seo";
|
|
34
|
+
*
|
|
35
|
+
* export const metadata = getSEO("Dashboard", "Your personalized dashboard");
|
|
36
|
+
* // => title: "Dashboard • Land Exchange Toolbox", description: "Your personalized dashboard"
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Usage in generateMetadata:
|
|
40
|
+
* ```ts
|
|
41
|
+
* export async function generateMetadata({ params }) {
|
|
42
|
+
* const deal = await getDeal(params.id);
|
|
43
|
+
* return getSEO(deal.title, deal.description, deal.coverImage);
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @category Client
|
|
48
|
+
*/
|
|
3
49
|
declare const setupSEO: (SEO: {
|
|
4
50
|
title: string;
|
|
5
51
|
description: string;
|
package/dist/client/seo.d.ts
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
import { Metadata } from 'next';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a metadata factory for Next.js pages. Call once with your site's default SEO config,
|
|
5
|
+
* then call the returned function per-page to generate the `Metadata` object.
|
|
6
|
+
*
|
|
7
|
+
* The returned function supports page-specific `title`, `description`, and `image` overrides.
|
|
8
|
+
* When a page title is provided, it's formatted as `"Page Title • Site Name"`.
|
|
9
|
+
*
|
|
10
|
+
* @param SEO - Base defaults for the whole site.
|
|
11
|
+
* @param SEO.title - Default document title (used when no page-specific title is provided).
|
|
12
|
+
* @param SEO.description - Default meta description.
|
|
13
|
+
* @param SEO.siteName - Application/site name (used in openGraph, twitter, and as the separator in titles).
|
|
14
|
+
* @param SEO.themeColor - Theme color for mobile browsers (e.g. `"#000000"`).
|
|
15
|
+
* @returns A function `(title?, description?, image?) => Metadata`. Pass page-specific overrides; they fill in or replace the defaults.
|
|
16
|
+
*
|
|
17
|
+
* @example Setup in a utility file:
|
|
18
|
+
* ```ts
|
|
19
|
+
* // lib/utils/seo.ts
|
|
20
|
+
* import { setupSEO } from "naystack/client";
|
|
21
|
+
*
|
|
22
|
+
* export const getSEO = setupSEO({
|
|
23
|
+
* title: "Land Exchange Toolbox - Premium Real Estate Tools",
|
|
24
|
+
* description: "Empower your real estate business with advanced tools.",
|
|
25
|
+
* siteName: "Land Exchange Toolbox",
|
|
26
|
+
* themeColor: "#5b9364",
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Usage in a page:
|
|
31
|
+
* ```ts
|
|
32
|
+
* // app/dashboard/page.tsx
|
|
33
|
+
* import { getSEO } from "@/lib/utils/seo";
|
|
34
|
+
*
|
|
35
|
+
* export const metadata = getSEO("Dashboard", "Your personalized dashboard");
|
|
36
|
+
* // => title: "Dashboard • Land Exchange Toolbox", description: "Your personalized dashboard"
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Usage in generateMetadata:
|
|
40
|
+
* ```ts
|
|
41
|
+
* export async function generateMetadata({ params }) {
|
|
42
|
+
* const deal = await getDeal(params.id);
|
|
43
|
+
* return getSEO(deal.title, deal.description, deal.coverImage);
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @category Client
|
|
48
|
+
*/
|
|
3
49
|
declare const setupSEO: (SEO: {
|
|
4
50
|
title: string;
|
|
5
51
|
description: string;
|