naystack 1.8.18 → 1.9.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.
- package/README.md +94 -34
- package/dist/auth/client.cjs.js +2 -2
- package/dist/auth/client.esm.js +2 -2
- package/dist/auth/email/client.cjs.js +2 -2
- package/dist/auth/email/client.esm.js +2 -2
- package/dist/auth/email/index.cjs.js +2 -2
- package/dist/auth/email/index.esm.js +2 -2
- package/dist/auth/email/next.cjs.js +2 -2
- package/dist/auth/email/next.esm.js +2 -2
- package/dist/auth/email/routes/delete.cjs.js +2 -2
- package/dist/auth/email/routes/delete.esm.js +2 -2
- package/dist/auth/email/routes/get.cjs.js +2 -2
- package/dist/auth/email/routes/get.esm.js +2 -2
- package/dist/auth/email/routes/post.cjs.js +2 -2
- package/dist/auth/email/routes/post.esm.js +2 -2
- package/dist/auth/email/routes/put.cjs.js +2 -2
- package/dist/auth/email/routes/put.esm.js +2 -2
- package/dist/auth/email/token.cjs.js +2 -2
- package/dist/auth/email/token.esm.js +2 -2
- package/dist/auth/email/utils.cjs.js +2 -2
- package/dist/auth/email/utils.esm.js +2 -2
- package/dist/auth/google/get.cjs.js +2 -2
- package/dist/auth/google/get.esm.js +2 -2
- package/dist/auth/google/index.cjs.js +2 -2
- package/dist/auth/google/index.esm.js +2 -2
- package/dist/auth/index.cjs.js +4 -297
- package/dist/auth/index.d.mts +0 -5
- package/dist/auth/index.d.ts +0 -5
- package/dist/auth/index.esm.js +3 -293
- package/dist/auth/token-store.cjs.js +2 -2
- package/dist/auth/token-store.esm.js +2 -2
- package/dist/env.cjs.js +3 -3
- package/dist/env.d.mts +3 -2
- package/dist/env.d.ts +3 -2
- package/dist/env.esm.js +3 -3
- package/dist/file/client.cjs.js +2 -2
- package/dist/file/client.esm.js +2 -2
- package/dist/file/index.cjs.js +2 -2
- package/dist/file/index.esm.js +2 -2
- package/dist/file/put.cjs.js +2 -2
- package/dist/file/put.esm.js +2 -2
- package/dist/file/setup.cjs.js +2 -2
- package/dist/file/setup.esm.js +2 -2
- package/dist/file/utils.cjs.js +2 -2
- package/dist/file/utils.esm.js +2 -2
- package/dist/graphql/client.cjs.js +2 -2
- package/dist/graphql/client.esm.js +2 -2
- package/dist/graphql/index.cjs.js +2 -2
- package/dist/graphql/index.esm.js +2 -2
- package/dist/graphql/init.cjs.js +2 -2
- package/dist/graphql/init.esm.js +2 -2
- package/dist/graphql/links.cjs.js +2 -2
- package/dist/graphql/links.esm.js +2 -2
- package/dist/graphql/next.cjs.js +2 -2
- package/dist/graphql/next.esm.js +2 -2
- package/dist/graphql/server.cjs.js +2 -2
- package/dist/graphql/server.esm.js +2 -2
- package/dist/graphql/utils.cjs.js +2 -2
- package/dist/graphql/utils.esm.js +2 -2
- package/dist/socials/connect.cjs.js +151 -0
- package/dist/socials/connect.d.mts +70 -0
- package/dist/socials/connect.d.ts +70 -0
- package/dist/socials/connect.esm.js +126 -0
- package/dist/socials/index.cjs.js +367 -35
- package/dist/socials/index.d.mts +8 -2
- package/dist/socials/index.d.ts +8 -2
- package/dist/socials/index.esm.js +357 -34
- package/dist/socials/instagram/adapter.cjs.js +275 -0
- package/dist/socials/instagram/adapter.d.mts +30 -0
- package/dist/socials/instagram/adapter.d.ts +30 -0
- package/dist/socials/instagram/adapter.esm.js +248 -0
- package/dist/{auth/instagram/utils.cjs.js → socials/instagram/auth.cjs.js} +43 -41
- package/dist/socials/instagram/auth.d.mts +52 -0
- package/dist/socials/instagram/auth.d.ts +52 -0
- package/dist/{auth/instagram/utils.esm.js → socials/instagram/auth.esm.js} +37 -35
- package/dist/socials/instagram/getters.d.mts +1 -0
- package/dist/socials/instagram/getters.d.ts +1 -0
- package/dist/socials/instagram/setters.cjs.js +56 -31
- package/dist/socials/instagram/setters.d.mts +1 -0
- package/dist/socials/instagram/setters.d.ts +1 -0
- package/dist/socials/instagram/setters.esm.js +56 -31
- package/dist/socials/instagram/types.d.mts +2 -1
- package/dist/socials/instagram/types.d.ts +2 -1
- package/dist/socials/meta/container.cjs.js +57 -30
- package/dist/socials/meta/container.d.mts +15 -28
- package/dist/socials/meta/container.d.ts +15 -28
- package/dist/socials/meta/container.esm.js +56 -31
- package/dist/socials/provider.cjs.js +18 -0
- package/dist/socials/provider.d.mts +52 -0
- package/dist/socials/provider.d.ts +52 -0
- package/dist/socials/provider.esm.js +0 -0
- package/dist/socials/threads/getters.d.mts +1 -0
- package/dist/socials/threads/getters.d.ts +1 -0
- package/dist/socials/threads/setters.cjs.js +56 -31
- package/dist/socials/threads/setters.d.mts +1 -0
- package/dist/socials/threads/setters.d.ts +1 -0
- package/dist/socials/threads/setters.esm.js +56 -31
- package/dist/socials/threads/types.d.mts +2 -1
- package/dist/socials/threads/types.d.ts +2 -1
- package/dist/socials/types.cjs.js +43 -0
- package/dist/socials/types.d.mts +99 -0
- package/dist/socials/types.d.ts +99 -0
- package/dist/socials/types.esm.js +17 -0
- package/dist/socials/utils/poll.cjs.js +59 -0
- package/dist/socials/utils/poll.d.mts +85 -0
- package/dist/socials/utils/poll.d.ts +85 -0
- package/dist/socials/utils/poll.esm.js +33 -0
- package/dist/utils/client/index.cjs.js +2 -2
- package/dist/utils/client/index.esm.js +2 -2
- package/dist/utils/client/seo.cjs.js +2 -2
- package/dist/utils/client/seo.esm.js +2 -2
- package/package.json +1 -1
- package/dist/auth/instagram/index.cjs.js +0 -379
- package/dist/auth/instagram/index.d.mts +0 -58
- package/dist/auth/instagram/index.d.ts +0 -58
- package/dist/auth/instagram/index.esm.js +0 -350
- package/dist/auth/instagram/route.cjs.js +0 -359
- package/dist/auth/instagram/route.d.mts +0 -15
- package/dist/auth/instagram/route.d.ts +0 -15
- package/dist/auth/instagram/route.esm.js +0 -334
- package/dist/auth/instagram/utils.d.mts +0 -57
- package/dist/auth/instagram/utils.d.ts +0 -57
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { SocialProvider } from './provider.js';
|
|
3
|
+
import { SocialPlatform, SocialProfile, SocialTokens } from './types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A freshly connected account, handed to `onConnect`.
|
|
7
|
+
*
|
|
8
|
+
* @property userId - Your app's user id from the state token; `null` when that token was invalid or expired.
|
|
9
|
+
*
|
|
10
|
+
* @category Socials
|
|
11
|
+
*/
|
|
12
|
+
interface SocialConnection {
|
|
13
|
+
platform: SocialPlatform;
|
|
14
|
+
profile: SocialProfile;
|
|
15
|
+
tokens: SocialTokens;
|
|
16
|
+
userId: number | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Options for {@link setupSocialAuth}.
|
|
20
|
+
*
|
|
21
|
+
* @property endpoint - Base URL this route is mounted at, e.g. `"https://yourapp.com/api/social"`. Each provider's redirect URI is `<endpoint>/<platform>` and must be registered with that platform verbatim.
|
|
22
|
+
* @property onConnect - Return a string to show as an error (redirects to `errorRedirectURL`); return `void` on success.
|
|
23
|
+
* @property scopes - Per-platform permissions; each provider has its own default.
|
|
24
|
+
*
|
|
25
|
+
* @category Socials
|
|
26
|
+
*/
|
|
27
|
+
interface SetupSocialAuthOptions {
|
|
28
|
+
providers: SocialProvider[];
|
|
29
|
+
endpoint: string;
|
|
30
|
+
onConnect: (connection: SocialConnection) => Promise<string | void>;
|
|
31
|
+
redirectURL: string;
|
|
32
|
+
errorRedirectURL: string;
|
|
33
|
+
scopes?: Partial<Record<SocialPlatform, string[]>>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One OAuth route for every platform a user can connect.
|
|
37
|
+
*
|
|
38
|
+
* Mount the GET handler on a dynamic segment — `app/api/social/[platform]/route.ts`
|
|
39
|
+
* — and `/api/social/instagram`, `/api/social/youtube`, … are the same handler. It
|
|
40
|
+
* serves both the connect entry point (`?state`, no code → 302 to the platform's
|
|
41
|
+
* authorize URL) and the callback (`?code`).
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // app/api/social/[platform]/route.ts
|
|
46
|
+
* import { InstagramProvider, setupSocialAuth } from "naystack/socials";
|
|
47
|
+
*
|
|
48
|
+
* export const { GET } = setupSocialAuth({
|
|
49
|
+
* providers: [InstagramProvider],
|
|
50
|
+
* endpoint: "https://yourapp.com/api/social",
|
|
51
|
+
* redirectURL: "/profile",
|
|
52
|
+
* errorRedirectURL: "/signup",
|
|
53
|
+
* onConnect: async ({ platform, profile, tokens, userId }) => {
|
|
54
|
+
* if (!userId) return "You are not logged in";
|
|
55
|
+
* await saveSocialAccount(userId, platform, profile, tokens);
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @category Socials
|
|
61
|
+
*/
|
|
62
|
+
declare function setupSocialAuth({ providers, endpoint, onConnect, redirectURL, errorRedirectURL, scopes, }: SetupSocialAuthOptions): {
|
|
63
|
+
GET: (req: NextRequest, ctx: {
|
|
64
|
+
params: Promise<{
|
|
65
|
+
platform: string;
|
|
66
|
+
}>;
|
|
67
|
+
}) => Promise<NextResponse<unknown>>;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { type SetupSocialAuthOptions, type SocialConnection, setupSocialAuth };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// src/socials/connect.ts
|
|
2
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
3
|
+
|
|
4
|
+
// src/auth/email/token.ts
|
|
5
|
+
import { compare } from "bcryptjs";
|
|
6
|
+
import { JsonWebTokenError, sign, verify } from "jsonwebtoken";
|
|
7
|
+
import { cookies } from "next/headers";
|
|
8
|
+
import { redirect } from "next/navigation";
|
|
9
|
+
import { NextResponse } from "next/server";
|
|
10
|
+
|
|
11
|
+
// src/env.ts
|
|
12
|
+
var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
|
|
13
|
+
var getEnvValue = (key) => {
|
|
14
|
+
switch (key) {
|
|
15
|
+
case "NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */:
|
|
16
|
+
return process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || EXTRA_ENV.GRAPHQL_ENDPOINT;
|
|
17
|
+
case "NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */:
|
|
18
|
+
return process.env.NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT || EXTRA_ENV.EMAIL_AUTH_ENDPOINT;
|
|
19
|
+
case "NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT" /* NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT */:
|
|
20
|
+
return process.env.NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT || EXTRA_ENV.GOOGLE_AUTH_ENDPOINT;
|
|
21
|
+
case "NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT" /* NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT */:
|
|
22
|
+
return process.env.NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT || EXTRA_ENV.SOCIAL_AUTH_ENDPOINT;
|
|
23
|
+
case "NEXT_PUBLIC_FILE_ENDPOINT" /* NEXT_PUBLIC_FILE_ENDPOINT */:
|
|
24
|
+
return process.env.NEXT_PUBLIC_FILE_ENDPOINT || EXTRA_ENV.FILE_ENDPOINT;
|
|
25
|
+
case "NEXT_PUBLIC_BASE_URL" /* NEXT_PUBLIC_BASE_URL */:
|
|
26
|
+
return process.env.NEXT_PUBLIC_BASE_URL || EXTRA_ENV.BASE_URL;
|
|
27
|
+
case "REFRESH_KEY" /* REFRESH_KEY */:
|
|
28
|
+
return process.env.REFRESH_KEY;
|
|
29
|
+
case "SIGNING_KEY" /* SIGNING_KEY */:
|
|
30
|
+
return process.env.SIGNING_KEY;
|
|
31
|
+
case "INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */:
|
|
32
|
+
return process.env.INSTAGRAM_CLIENT_SECRET;
|
|
33
|
+
case "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */:
|
|
34
|
+
return process.env.INSTAGRAM_CLIENT_ID;
|
|
35
|
+
case "GOOGLE_CLIENT_SECRET" /* GOOGLE_CLIENT_SECRET */:
|
|
36
|
+
return process.env.GOOGLE_CLIENT_SECRET;
|
|
37
|
+
case "GOOGLE_CLIENT_ID" /* GOOGLE_CLIENT_ID */:
|
|
38
|
+
return process.env.GOOGLE_CLIENT_ID;
|
|
39
|
+
case "TURNSTILE_KEY" /* TURNSTILE_KEY */:
|
|
40
|
+
return process.env.TURNSTILE_KEY;
|
|
41
|
+
case "S3_ACCESS_KEY_ID" /* S3_ACCESS_KEY_ID */:
|
|
42
|
+
return process.env.S3_ACCESS_KEY_ID;
|
|
43
|
+
case "S3_ACCESS_KEY_SECRET" /* S3_ACCESS_KEY_SECRET */:
|
|
44
|
+
return process.env.S3_ACCESS_KEY_SECRET;
|
|
45
|
+
case "S3_REGION" /* S3_REGION */:
|
|
46
|
+
return process.env.S3_REGION;
|
|
47
|
+
case "S3_BUCKET" /* S3_BUCKET */:
|
|
48
|
+
return process.env.S3_BUCKET;
|
|
49
|
+
case "NODE_ENV" /* NODE_ENV */:
|
|
50
|
+
return process.env.NODE_ENV;
|
|
51
|
+
default:
|
|
52
|
+
return process.env[key];
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function getEnv(key, skipCheck) {
|
|
56
|
+
const value = getEnvValue(key);
|
|
57
|
+
if (!skipCheck && !value) throw new Error(`${key} is not defined`);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/auth/email/token.ts
|
|
62
|
+
function getUserIdFromAccessToken(accessToken) {
|
|
63
|
+
if (accessToken)
|
|
64
|
+
try {
|
|
65
|
+
const decoded = verify(accessToken, getEnv("SIGNING_KEY" /* SIGNING_KEY */));
|
|
66
|
+
if (typeof decoded !== "string" && typeof decoded.id === "number")
|
|
67
|
+
return decoded.id;
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (!(e instanceof JsonWebTokenError)) console.error(e, "errors");
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/socials/connect.ts
|
|
76
|
+
function setupSocialAuth({
|
|
77
|
+
providers,
|
|
78
|
+
endpoint,
|
|
79
|
+
onConnect,
|
|
80
|
+
redirectURL,
|
|
81
|
+
errorRedirectURL,
|
|
82
|
+
scopes
|
|
83
|
+
}) {
|
|
84
|
+
const handleError = (message) => NextResponse2.redirect(`${errorRedirectURL}?error=${message}`);
|
|
85
|
+
const GET = async (req, ctx) => {
|
|
86
|
+
const { platform } = await ctx.params;
|
|
87
|
+
const provider = providers.find((p) => p.platform === platform);
|
|
88
|
+
if (!provider) return handleError("Unsupported platform");
|
|
89
|
+
const code = req.nextUrl.searchParams.get("code");
|
|
90
|
+
const error = req.nextUrl.searchParams.get("error");
|
|
91
|
+
const state = req.nextUrl.searchParams.get("state");
|
|
92
|
+
if (error) return handleError(error);
|
|
93
|
+
if (!state) return handleError("Invalid request");
|
|
94
|
+
const redirectURI = `${endpoint}/${provider.platform}`;
|
|
95
|
+
if (!code) {
|
|
96
|
+
return NextResponse2.redirect(
|
|
97
|
+
provider.auth.authorizationURL({
|
|
98
|
+
state,
|
|
99
|
+
redirectURI,
|
|
100
|
+
scopes: scopes?.[provider.platform]
|
|
101
|
+
}),
|
|
102
|
+
302
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const exchanged = await provider.auth.exchangeCode({ code, redirectURI });
|
|
106
|
+
if (!exchanged) return handleError("Couldn't connect your account");
|
|
107
|
+
const { platformUserId, ...tokens } = exchanged;
|
|
108
|
+
const profile = await provider.fetchProfile(tokens.accessToken);
|
|
109
|
+
if (!profile) return handleError("Couldn't read your profile");
|
|
110
|
+
const errorMessage = await onConnect({
|
|
111
|
+
platform: provider.platform,
|
|
112
|
+
profile: {
|
|
113
|
+
...profile,
|
|
114
|
+
platformUserId: profile.platformUserId ?? platformUserId
|
|
115
|
+
},
|
|
116
|
+
tokens,
|
|
117
|
+
userId: getUserIdFromAccessToken(state)
|
|
118
|
+
});
|
|
119
|
+
if (errorMessage) return handleError(errorMessage);
|
|
120
|
+
return NextResponse2.redirect(redirectURL);
|
|
121
|
+
};
|
|
122
|
+
return { GET };
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
setupSocialAuth
|
|
126
|
+
};
|