naystack 1.8.19 → 1.9.1
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 +99 -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 -306
- package/dist/auth/index.d.mts +0 -5
- package/dist/auth/index.d.ts +0 -5
- package/dist/auth/index.esm.js +3 -302
- 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 +345 -21
- package/dist/socials/index.d.mts +8 -2
- package/dist/socials/index.d.ts +8 -2
- package/dist/socials/index.esm.js +335 -20
- package/dist/socials/instagram/adapter.cjs.js +276 -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 +249 -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 +33 -17
- 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 +33 -17
- 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 +34 -16
- package/dist/socials/meta/container.d.mts +5 -27
- package/dist/socials/meta/container.d.ts +5 -27
- package/dist/socials/meta/container.esm.js +33 -17
- package/dist/socials/provider.cjs.js +18 -0
- package/dist/socials/provider.d.mts +54 -0
- package/dist/socials/provider.d.ts +54 -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 +33 -17
- 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 +33 -17
- 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 -388
- 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 -359
- package/dist/auth/instagram/route.cjs.js +0 -368
- 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 -343
- package/dist/auth/instagram/utils.d.mts +0 -57
- package/dist/auth/instagram/utils.d.ts +0 -57
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
// src/auth/instagram/route.ts
|
|
2
|
-
import { NextResponse as NextResponse3 } 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_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */:
|
|
22
|
-
return process.env.NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT || EXTRA_ENV.INSTAGRAM_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/auth/instagram/utils.ts
|
|
76
|
-
async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
|
|
77
|
-
const formData = new FormData();
|
|
78
|
-
formData.set("client_id", clientId);
|
|
79
|
-
formData.set("client_secret", clientSecret);
|
|
80
|
-
formData.set("grant_type", "authorization_code");
|
|
81
|
-
formData.set("redirect_uri", redirectURL);
|
|
82
|
-
formData.set("code", code);
|
|
83
|
-
const shortRes = await fetch("https://api.instagram.com/oauth/access_token", {
|
|
84
|
-
method: "POST",
|
|
85
|
-
body: formData
|
|
86
|
-
});
|
|
87
|
-
if (shortRes.ok) {
|
|
88
|
-
const shortResData = await shortRes.json();
|
|
89
|
-
if (shortResData.access_token) {
|
|
90
|
-
const shortLivedToken = shortResData.access_token;
|
|
91
|
-
const longRes = await fetch(
|
|
92
|
-
`https://graph.instagram.com/access_token?grant_type=ig_exchange_token&access_token=${shortLivedToken}&client_secret=${getEnv("INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */)}`
|
|
93
|
-
);
|
|
94
|
-
if (longRes.ok) {
|
|
95
|
-
const longResData = await longRes.json();
|
|
96
|
-
return {
|
|
97
|
-
accessToken: longResData.access_token,
|
|
98
|
-
userId: shortResData.user_id
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
var getInstagramAuthorizationURL = (token, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
105
|
-
"INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
|
|
106
|
-
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}#weblink`;
|
|
107
|
-
|
|
108
|
-
// src/socials/meta/request.ts
|
|
109
|
-
function createGraphClient(baseURL) {
|
|
110
|
-
const buildURL = (token, path, params = {}) => {
|
|
111
|
-
const search = new URLSearchParams();
|
|
112
|
-
for (const [key, value] of Object.entries(params)) {
|
|
113
|
-
if (value !== void 0) search.set(key, String(value));
|
|
114
|
-
}
|
|
115
|
-
search.set("access_token", token);
|
|
116
|
-
return `${baseURL}/${path}?${search.toString()}`;
|
|
117
|
-
};
|
|
118
|
-
const request = async (token, path, options = {}) => {
|
|
119
|
-
const response = await fetch(buildURL(token, path, options.params), {
|
|
120
|
-
method: options.method || (options.body ? "POST" : "GET"),
|
|
121
|
-
headers: {
|
|
122
|
-
Authorization: `Bearer ${token}`,
|
|
123
|
-
...options.body ? { "Content-Type": "application/json" } : {}
|
|
124
|
-
},
|
|
125
|
-
...options.body ? { body: JSON.stringify(options.body) } : {}
|
|
126
|
-
});
|
|
127
|
-
return response.json().catch(() => null);
|
|
128
|
-
};
|
|
129
|
-
return { buildURL, request };
|
|
130
|
-
}
|
|
131
|
-
function readGraphID(label, result) {
|
|
132
|
-
if (result?.error) {
|
|
133
|
-
console.error(`[naystack] ${label} failed: ${result.error.message}`);
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
return result?.id || null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// src/socials/instagram/utils.ts
|
|
140
|
-
var client = createGraphClient("https://graph.instagram.com/v23.0");
|
|
141
|
-
var getInstagramData = client.request;
|
|
142
|
-
|
|
143
|
-
// src/socials/instagram/getters.ts
|
|
144
|
-
var getInstagramUser = (token, id, fields) => {
|
|
145
|
-
return getInstagramData(token, id || "me", {
|
|
146
|
-
params: {
|
|
147
|
-
fields: fields ? fields.join(",") : "username,followers_count,media_count"
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
var getInstagramContainerStatus = async (token, id) => {
|
|
152
|
-
const result = await getInstagramData(token, id, { params: { fields: "status_code,status" } });
|
|
153
|
-
if (!result?.status_code) return null;
|
|
154
|
-
return {
|
|
155
|
-
status: result.status_code,
|
|
156
|
-
error: result.status_code === "ERROR" ? result.status : void 0
|
|
157
|
-
};
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// src/socials/meta/container.ts
|
|
161
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
162
|
-
async function waitForContainer(getState, { intervalMS = 5e3, timeoutMS = 3e5 } = {}) {
|
|
163
|
-
const deadline = Date.now() + timeoutMS;
|
|
164
|
-
let state = await getState();
|
|
165
|
-
if (!state) {
|
|
166
|
-
await sleep(2e3);
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
while (state?.status === "IN_PROGRESS" && Date.now() < deadline) {
|
|
170
|
-
await sleep(intervalMS);
|
|
171
|
-
state = await getState();
|
|
172
|
-
}
|
|
173
|
-
return state;
|
|
174
|
-
}
|
|
175
|
-
function createPublisher(platform) {
|
|
176
|
-
const isReady = async (token, id, label, wait) => {
|
|
177
|
-
const state = await waitForContainer(
|
|
178
|
-
() => platform.getStatus(token, id),
|
|
179
|
-
wait
|
|
180
|
-
);
|
|
181
|
-
if (state && state.status !== "FINISHED" && state.status !== "PUBLISHED") {
|
|
182
|
-
console.error(
|
|
183
|
-
`[naystack] ${platform.name} ${label} ${id} is ${state.status}${state.error ? `: ${state.error}` : ""}`
|
|
184
|
-
);
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
return true;
|
|
188
|
-
};
|
|
189
|
-
const createReady = async (token, params, label, wait, retry) => {
|
|
190
|
-
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
191
|
-
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
192
|
-
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
193
|
-
const id = await platform.createContainer(token, params);
|
|
194
|
-
if (id && await isReady(token, id, label, wait)) return id;
|
|
195
|
-
if (attempt < attempts) {
|
|
196
|
-
const delay = backoffMS * 2 ** (attempt - 1);
|
|
197
|
-
console.warn(
|
|
198
|
-
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
199
|
-
);
|
|
200
|
-
await sleep(delay);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return null;
|
|
204
|
-
};
|
|
205
|
-
return {
|
|
206
|
-
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
207
|
-
publish: async (token, params, wait, retry) => {
|
|
208
|
-
const containerID = await createReady(
|
|
209
|
-
token,
|
|
210
|
-
params,
|
|
211
|
-
"container",
|
|
212
|
-
wait,
|
|
213
|
-
retry
|
|
214
|
-
);
|
|
215
|
-
if (!containerID) return null;
|
|
216
|
-
return platform.publish(token, containerID);
|
|
217
|
-
},
|
|
218
|
-
/**
|
|
219
|
-
* Creates and awaits every carousel child **in parallel**, resolving to
|
|
220
|
-
* their ids in input order — or `null` if any failed.
|
|
221
|
-
*
|
|
222
|
-
* Parallel because each child is an independent create-then-poll and Meta
|
|
223
|
-
* spends ~5s accepting a single container, so ten sequential children cost
|
|
224
|
-
* ~50s of mostly waiting — past what a serverless caller can fit in its
|
|
225
|
-
* timeout. `Promise.all` preserves input order, which the carousel's slide
|
|
226
|
-
* order depends on.
|
|
227
|
-
*/
|
|
228
|
-
createChildren: async (token, items, wait, retry) => {
|
|
229
|
-
const children = await Promise.all(
|
|
230
|
-
items.map(
|
|
231
|
-
(item) => createReady(
|
|
232
|
-
token,
|
|
233
|
-
{ ...item, is_carousel_item: true },
|
|
234
|
-
"carousel item",
|
|
235
|
-
wait,
|
|
236
|
-
retry
|
|
237
|
-
)
|
|
238
|
-
)
|
|
239
|
-
);
|
|
240
|
-
const created = children.filter((childID) => childID !== null);
|
|
241
|
-
return created.length === children.length ? created : null;
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// src/socials/instagram/setters.ts
|
|
247
|
-
var publisher = createPublisher({
|
|
248
|
-
name: "Instagram",
|
|
249
|
-
getStatus: getInstagramContainerStatus,
|
|
250
|
-
createContainer: async (token, params) => readGraphID(
|
|
251
|
-
"Instagram media container",
|
|
252
|
-
await getInstagramData(token, "me/media", {
|
|
253
|
-
params,
|
|
254
|
-
method: "POST"
|
|
255
|
-
})
|
|
256
|
-
),
|
|
257
|
-
publish: async (token, creationID) => readGraphID(
|
|
258
|
-
"Instagram publish",
|
|
259
|
-
await getInstagramData(token, "me/media_publish", {
|
|
260
|
-
params: { creation_id: creationID },
|
|
261
|
-
method: "POST"
|
|
262
|
-
})
|
|
263
|
-
)
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
// src/socials/meta/webhook.ts
|
|
267
|
-
import { NextResponse as NextResponse2 } from "next/server";
|
|
268
|
-
|
|
269
|
-
// src/socials/threads/utils.ts
|
|
270
|
-
var client2 = createGraphClient("https://graph.threads.net/v1.0");
|
|
271
|
-
var getThreadsData = client2.request;
|
|
272
|
-
|
|
273
|
-
// src/socials/threads/getters.ts
|
|
274
|
-
var getThreadsContainerStatus = async (token, id) => {
|
|
275
|
-
const result = await getThreadsData(token, id, { params: { fields: "status,error_message" } });
|
|
276
|
-
if (!result?.status) return null;
|
|
277
|
-
return { status: result.status, error: result.error_message };
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// src/socials/threads/setters.ts
|
|
281
|
-
var publisher2 = createPublisher({
|
|
282
|
-
name: "Threads",
|
|
283
|
-
getStatus: getThreadsContainerStatus,
|
|
284
|
-
createContainer: async (token, params) => readGraphID(
|
|
285
|
-
"Threads container",
|
|
286
|
-
await getThreadsData(token, "me/threads", {
|
|
287
|
-
params,
|
|
288
|
-
method: "POST"
|
|
289
|
-
})
|
|
290
|
-
),
|
|
291
|
-
publish: async (token, creationID) => readGraphID(
|
|
292
|
-
"Threads publish",
|
|
293
|
-
await getThreadsData(token, "me/threads_publish", {
|
|
294
|
-
params: { creation_id: creationID },
|
|
295
|
-
method: "POST"
|
|
296
|
-
})
|
|
297
|
-
)
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// src/auth/instagram/route.ts
|
|
301
|
-
var getInstagramRoute = ({
|
|
302
|
-
redirectURL,
|
|
303
|
-
errorRedirectURL,
|
|
304
|
-
onUser,
|
|
305
|
-
scopes
|
|
306
|
-
}) => {
|
|
307
|
-
const handleError = (message) => NextResponse3.redirect(`${errorRedirectURL}?error=${message}`);
|
|
308
|
-
return async (req) => {
|
|
309
|
-
const accessCode = req.nextUrl.searchParams.get("code");
|
|
310
|
-
const error = req.nextUrl.searchParams.get("error");
|
|
311
|
-
const stateToken = req.nextUrl.searchParams.get("state");
|
|
312
|
-
if (error) return handleError(error);
|
|
313
|
-
if (!accessCode) {
|
|
314
|
-
if (!stateToken) return handleError("Invalid request");
|
|
315
|
-
return NextResponse3.redirect(
|
|
316
|
-
getInstagramAuthorizationURL(stateToken, scopes),
|
|
317
|
-
302
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
if (!stateToken) return handleError("Invalid request");
|
|
321
|
-
const instagramData = await getLongLivedToken(
|
|
322
|
-
accessCode,
|
|
323
|
-
getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */),
|
|
324
|
-
getEnv("INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */),
|
|
325
|
-
getEnv("INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */)
|
|
326
|
-
);
|
|
327
|
-
if (!instagramData?.accessToken)
|
|
328
|
-
return handleError("Unable to reach Instagram");
|
|
329
|
-
const personalInfo = await getInstagramUser(instagramData.accessToken);
|
|
330
|
-
if (!personalInfo?.username) return handleError("You are not logged in");
|
|
331
|
-
const loggedInUserID = getUserIdFromAccessToken(stateToken);
|
|
332
|
-
const errorMessage = await onUser(
|
|
333
|
-
personalInfo,
|
|
334
|
-
loggedInUserID,
|
|
335
|
-
instagramData.accessToken
|
|
336
|
-
);
|
|
337
|
-
if (errorMessage) return handleError(errorMessage);
|
|
338
|
-
return NextResponse3.redirect(redirectURL);
|
|
339
|
-
};
|
|
340
|
-
};
|
|
341
|
-
export {
|
|
342
|
-
getInstagramRoute
|
|
343
|
-
};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permissions requestable during Instagram Login OAuth. `instagram_business_basic`
|
|
3
|
-
* is enough to read a profile; publishing needs `instagram_business_content_publish`.
|
|
4
|
-
*
|
|
5
|
-
* Widening the scopes only affects users who authorize afterwards — tokens already
|
|
6
|
-
* stored keep the permissions they were granted, so existing users must reconnect.
|
|
7
|
-
*
|
|
8
|
-
* @category Auth
|
|
9
|
-
*/
|
|
10
|
-
type InstagramScope = "instagram_business_basic" | "instagram_business_content_publish" | "instagram_business_manage_messages" | "instagram_business_manage_comments" | "instagram_business_manage_insights";
|
|
11
|
-
/**
|
|
12
|
-
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
13
|
-
* @param token - Current long-lived access token
|
|
14
|
-
* @returns New access token or undefined
|
|
15
|
-
*/
|
|
16
|
-
declare function getRefreshedInstagramAccessToken(token: string): Promise<string | undefined>;
|
|
17
|
-
/**
|
|
18
|
-
* Exchanges an OAuth code for a long-lived Instagram access token.
|
|
19
|
-
* @param code - OAuth authorization code from redirect
|
|
20
|
-
* @param redirectURL - Registered redirect URI
|
|
21
|
-
* @param clientId - Instagram app client id
|
|
22
|
-
* @param clientSecret - Instagram app client secret
|
|
23
|
-
* @returns Object with accessToken and userId, or undefined
|
|
24
|
-
*/
|
|
25
|
-
declare function getLongLivedToken(code: string, redirectURL: string, clientId: string, clientSecret: string): Promise<{
|
|
26
|
-
accessToken: string;
|
|
27
|
-
userId: string;
|
|
28
|
-
} | undefined>;
|
|
29
|
-
/**
|
|
30
|
-
* Builds the Instagram OAuth authorization URL for the given state token.
|
|
31
|
-
* The state token is passed back by Instagram after authorization and is used to link
|
|
32
|
-
* the Instagram account to the logged-in user.
|
|
33
|
-
*
|
|
34
|
-
* Reads `INSTAGRAM_CLIENT_ID` and `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT` from the environment.
|
|
35
|
-
*
|
|
36
|
-
* **Server-only** — reads the non-public `INSTAGRAM_CLIENT_ID`, so it must be
|
|
37
|
-
* called from server code (e.g. the Instagram auth route), not the client. The
|
|
38
|
-
* OAuth `client_id` still ends up in the redirect URL the browser follows; it is
|
|
39
|
-
* simply built on the server instead of shipped in the client bundle.
|
|
40
|
-
*
|
|
41
|
-
* @param token - The state token to embed in the authorization URL (typically the user's session or access token).
|
|
42
|
-
* @param scopes - Permissions to request. Default: `["instagram_business_basic"]`.
|
|
43
|
-
* @returns The full Instagram OAuth authorization URL.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* // In a server route handler:
|
|
48
|
-
* import { getInstagramAuthorizationURL } from "naystack/auth";
|
|
49
|
-
*
|
|
50
|
-
* return NextResponse.redirect(getInstagramAuthorizationURL(state), 302);
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @category Auth
|
|
54
|
-
*/
|
|
55
|
-
declare const getInstagramAuthorizationURL: (token: string, scopes?: InstagramScope[]) => string;
|
|
56
|
-
|
|
57
|
-
export { type InstagramScope, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permissions requestable during Instagram Login OAuth. `instagram_business_basic`
|
|
3
|
-
* is enough to read a profile; publishing needs `instagram_business_content_publish`.
|
|
4
|
-
*
|
|
5
|
-
* Widening the scopes only affects users who authorize afterwards — tokens already
|
|
6
|
-
* stored keep the permissions they were granted, so existing users must reconnect.
|
|
7
|
-
*
|
|
8
|
-
* @category Auth
|
|
9
|
-
*/
|
|
10
|
-
type InstagramScope = "instagram_business_basic" | "instagram_business_content_publish" | "instagram_business_manage_messages" | "instagram_business_manage_comments" | "instagram_business_manage_insights";
|
|
11
|
-
/**
|
|
12
|
-
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
13
|
-
* @param token - Current long-lived access token
|
|
14
|
-
* @returns New access token or undefined
|
|
15
|
-
*/
|
|
16
|
-
declare function getRefreshedInstagramAccessToken(token: string): Promise<string | undefined>;
|
|
17
|
-
/**
|
|
18
|
-
* Exchanges an OAuth code for a long-lived Instagram access token.
|
|
19
|
-
* @param code - OAuth authorization code from redirect
|
|
20
|
-
* @param redirectURL - Registered redirect URI
|
|
21
|
-
* @param clientId - Instagram app client id
|
|
22
|
-
* @param clientSecret - Instagram app client secret
|
|
23
|
-
* @returns Object with accessToken and userId, or undefined
|
|
24
|
-
*/
|
|
25
|
-
declare function getLongLivedToken(code: string, redirectURL: string, clientId: string, clientSecret: string): Promise<{
|
|
26
|
-
accessToken: string;
|
|
27
|
-
userId: string;
|
|
28
|
-
} | undefined>;
|
|
29
|
-
/**
|
|
30
|
-
* Builds the Instagram OAuth authorization URL for the given state token.
|
|
31
|
-
* The state token is passed back by Instagram after authorization and is used to link
|
|
32
|
-
* the Instagram account to the logged-in user.
|
|
33
|
-
*
|
|
34
|
-
* Reads `INSTAGRAM_CLIENT_ID` and `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT` from the environment.
|
|
35
|
-
*
|
|
36
|
-
* **Server-only** — reads the non-public `INSTAGRAM_CLIENT_ID`, so it must be
|
|
37
|
-
* called from server code (e.g. the Instagram auth route), not the client. The
|
|
38
|
-
* OAuth `client_id` still ends up in the redirect URL the browser follows; it is
|
|
39
|
-
* simply built on the server instead of shipped in the client bundle.
|
|
40
|
-
*
|
|
41
|
-
* @param token - The state token to embed in the authorization URL (typically the user's session or access token).
|
|
42
|
-
* @param scopes - Permissions to request. Default: `["instagram_business_basic"]`.
|
|
43
|
-
* @returns The full Instagram OAuth authorization URL.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* // In a server route handler:
|
|
48
|
-
* import { getInstagramAuthorizationURL } from "naystack/auth";
|
|
49
|
-
*
|
|
50
|
-
* return NextResponse.redirect(getInstagramAuthorizationURL(state), 302);
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @category Auth
|
|
54
|
-
*/
|
|
55
|
-
declare const getInstagramAuthorizationURL: (token: string, scopes?: InstagramScope[]) => string;
|
|
56
|
-
|
|
57
|
-
export { type InstagramScope, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|