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.
Files changed (122) hide show
  1. package/README.md +99 -34
  2. package/dist/auth/client.cjs.js +2 -2
  3. package/dist/auth/client.esm.js +2 -2
  4. package/dist/auth/email/client.cjs.js +2 -2
  5. package/dist/auth/email/client.esm.js +2 -2
  6. package/dist/auth/email/index.cjs.js +2 -2
  7. package/dist/auth/email/index.esm.js +2 -2
  8. package/dist/auth/email/next.cjs.js +2 -2
  9. package/dist/auth/email/next.esm.js +2 -2
  10. package/dist/auth/email/routes/delete.cjs.js +2 -2
  11. package/dist/auth/email/routes/delete.esm.js +2 -2
  12. package/dist/auth/email/routes/get.cjs.js +2 -2
  13. package/dist/auth/email/routes/get.esm.js +2 -2
  14. package/dist/auth/email/routes/post.cjs.js +2 -2
  15. package/dist/auth/email/routes/post.esm.js +2 -2
  16. package/dist/auth/email/routes/put.cjs.js +2 -2
  17. package/dist/auth/email/routes/put.esm.js +2 -2
  18. package/dist/auth/email/token.cjs.js +2 -2
  19. package/dist/auth/email/token.esm.js +2 -2
  20. package/dist/auth/email/utils.cjs.js +2 -2
  21. package/dist/auth/email/utils.esm.js +2 -2
  22. package/dist/auth/google/get.cjs.js +2 -2
  23. package/dist/auth/google/get.esm.js +2 -2
  24. package/dist/auth/google/index.cjs.js +2 -2
  25. package/dist/auth/google/index.esm.js +2 -2
  26. package/dist/auth/index.cjs.js +4 -306
  27. package/dist/auth/index.d.mts +0 -5
  28. package/dist/auth/index.d.ts +0 -5
  29. package/dist/auth/index.esm.js +3 -302
  30. package/dist/auth/token-store.cjs.js +2 -2
  31. package/dist/auth/token-store.esm.js +2 -2
  32. package/dist/env.cjs.js +3 -3
  33. package/dist/env.d.mts +3 -2
  34. package/dist/env.d.ts +3 -2
  35. package/dist/env.esm.js +3 -3
  36. package/dist/file/client.cjs.js +2 -2
  37. package/dist/file/client.esm.js +2 -2
  38. package/dist/file/index.cjs.js +2 -2
  39. package/dist/file/index.esm.js +2 -2
  40. package/dist/file/put.cjs.js +2 -2
  41. package/dist/file/put.esm.js +2 -2
  42. package/dist/file/setup.cjs.js +2 -2
  43. package/dist/file/setup.esm.js +2 -2
  44. package/dist/file/utils.cjs.js +2 -2
  45. package/dist/file/utils.esm.js +2 -2
  46. package/dist/graphql/client.cjs.js +2 -2
  47. package/dist/graphql/client.esm.js +2 -2
  48. package/dist/graphql/index.cjs.js +2 -2
  49. package/dist/graphql/index.esm.js +2 -2
  50. package/dist/graphql/init.cjs.js +2 -2
  51. package/dist/graphql/init.esm.js +2 -2
  52. package/dist/graphql/links.cjs.js +2 -2
  53. package/dist/graphql/links.esm.js +2 -2
  54. package/dist/graphql/next.cjs.js +2 -2
  55. package/dist/graphql/next.esm.js +2 -2
  56. package/dist/graphql/server.cjs.js +2 -2
  57. package/dist/graphql/server.esm.js +2 -2
  58. package/dist/graphql/utils.cjs.js +2 -2
  59. package/dist/graphql/utils.esm.js +2 -2
  60. package/dist/socials/connect.cjs.js +151 -0
  61. package/dist/socials/connect.d.mts +70 -0
  62. package/dist/socials/connect.d.ts +70 -0
  63. package/dist/socials/connect.esm.js +126 -0
  64. package/dist/socials/index.cjs.js +345 -21
  65. package/dist/socials/index.d.mts +8 -2
  66. package/dist/socials/index.d.ts +8 -2
  67. package/dist/socials/index.esm.js +335 -20
  68. package/dist/socials/instagram/adapter.cjs.js +276 -0
  69. package/dist/socials/instagram/adapter.d.mts +30 -0
  70. package/dist/socials/instagram/adapter.d.ts +30 -0
  71. package/dist/socials/instagram/adapter.esm.js +249 -0
  72. package/dist/{auth/instagram/utils.cjs.js → socials/instagram/auth.cjs.js} +43 -41
  73. package/dist/socials/instagram/auth.d.mts +52 -0
  74. package/dist/socials/instagram/auth.d.ts +52 -0
  75. package/dist/{auth/instagram/utils.esm.js → socials/instagram/auth.esm.js} +37 -35
  76. package/dist/socials/instagram/getters.d.mts +1 -0
  77. package/dist/socials/instagram/getters.d.ts +1 -0
  78. package/dist/socials/instagram/setters.cjs.js +33 -17
  79. package/dist/socials/instagram/setters.d.mts +1 -0
  80. package/dist/socials/instagram/setters.d.ts +1 -0
  81. package/dist/socials/instagram/setters.esm.js +33 -17
  82. package/dist/socials/instagram/types.d.mts +2 -1
  83. package/dist/socials/instagram/types.d.ts +2 -1
  84. package/dist/socials/meta/container.cjs.js +34 -16
  85. package/dist/socials/meta/container.d.mts +5 -27
  86. package/dist/socials/meta/container.d.ts +5 -27
  87. package/dist/socials/meta/container.esm.js +33 -17
  88. package/dist/socials/provider.cjs.js +18 -0
  89. package/dist/socials/provider.d.mts +54 -0
  90. package/dist/socials/provider.d.ts +54 -0
  91. package/dist/socials/provider.esm.js +0 -0
  92. package/dist/socials/threads/getters.d.mts +1 -0
  93. package/dist/socials/threads/getters.d.ts +1 -0
  94. package/dist/socials/threads/setters.cjs.js +33 -17
  95. package/dist/socials/threads/setters.d.mts +1 -0
  96. package/dist/socials/threads/setters.d.ts +1 -0
  97. package/dist/socials/threads/setters.esm.js +33 -17
  98. package/dist/socials/threads/types.d.mts +2 -1
  99. package/dist/socials/threads/types.d.ts +2 -1
  100. package/dist/socials/types.cjs.js +43 -0
  101. package/dist/socials/types.d.mts +99 -0
  102. package/dist/socials/types.d.ts +99 -0
  103. package/dist/socials/types.esm.js +17 -0
  104. package/dist/socials/utils/poll.cjs.js +59 -0
  105. package/dist/socials/utils/poll.d.mts +85 -0
  106. package/dist/socials/utils/poll.d.ts +85 -0
  107. package/dist/socials/utils/poll.esm.js +33 -0
  108. package/dist/utils/client/index.cjs.js +2 -2
  109. package/dist/utils/client/index.esm.js +2 -2
  110. package/dist/utils/client/seo.cjs.js +2 -2
  111. package/dist/utils/client/seo.esm.js +2 -2
  112. package/package.json +1 -1
  113. package/dist/auth/instagram/index.cjs.js +0 -388
  114. package/dist/auth/instagram/index.d.mts +0 -58
  115. package/dist/auth/instagram/index.d.ts +0 -58
  116. package/dist/auth/instagram/index.esm.js +0 -359
  117. package/dist/auth/instagram/route.cjs.js +0 -368
  118. package/dist/auth/instagram/route.d.mts +0 -15
  119. package/dist/auth/instagram/route.d.ts +0 -15
  120. package/dist/auth/instagram/route.esm.js +0 -343
  121. package/dist/auth/instagram/utils.d.mts +0 -57
  122. package/dist/auth/instagram/utils.d.ts +0 -57
@@ -20,11 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/socials/index.ts
21
21
  var socials_exports = {};
22
22
  __export(socials_exports, {
23
+ InstagramProvider: () => InstagramProvider,
23
24
  MetaMediaType: () => MetaMediaType,
25
+ SocialMediaKind: () => SocialMediaKind,
26
+ SocialPlatform: () => SocialPlatform,
24
27
  canPublishToInstagram: () => canPublishToInstagram,
25
28
  createInstagramPost: () => createInstagramPost,
26
29
  createThread: () => createThread,
27
30
  createThreadsPost: () => createThreadsPost,
31
+ getInstagramAuthorizationURL: () => getInstagramAuthorizationURL,
28
32
  getInstagramConversation: () => getInstagramConversation,
29
33
  getInstagramConversationByUser: () => getInstagramConversationByUser,
30
34
  getInstagramConversations: () => getInstagramConversations,
@@ -33,18 +37,203 @@ __export(socials_exports, {
33
37
  getInstagramMedia: () => getInstagramMedia,
34
38
  getInstagramMessage: () => getInstagramMessage,
35
39
  getInstagramUser: () => getInstagramUser,
40
+ getLongLivedInstagramToken: () => getLongLivedInstagramToken,
36
41
  getThread: () => getThread,
37
42
  getThreads: () => getThreads,
38
43
  getThreadsData: () => getThreadsData,
39
44
  getThreadsReplies: () => getThreadsReplies,
45
+ pollUntilReady: () => pollUntilReady,
40
46
  readGraphID: () => readGraphID,
47
+ refreshInstagramAccessToken: () => refreshInstagramAccessToken,
41
48
  replyToInstagramComment: () => replyToInstagramComment,
42
49
  sendInstagramMessage: () => sendInstagramMessage,
43
50
  setupInstagramWebhook: () => setupInstagramWebhook,
44
- setupThreadsWebhook: () => setupThreadsWebhook
51
+ setupSocialAuth: () => setupSocialAuth,
52
+ setupThreadsWebhook: () => setupThreadsWebhook,
53
+ withRetry: () => withRetry
45
54
  });
46
55
  module.exports = __toCommonJS(socials_exports);
47
56
 
57
+ // src/socials/connect.ts
58
+ var import_server2 = require("next/server");
59
+
60
+ // src/auth/email/token.ts
61
+ var import_bcryptjs = require("bcryptjs");
62
+ var import_jsonwebtoken = require("jsonwebtoken");
63
+ var import_headers = require("next/headers");
64
+ var import_navigation = require("next/navigation");
65
+ var import_server = require("next/server");
66
+
67
+ // src/env.ts
68
+ var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
69
+ var getEnvValue = (key) => {
70
+ switch (key) {
71
+ case "NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */:
72
+ return process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || EXTRA_ENV.GRAPHQL_ENDPOINT;
73
+ case "NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */:
74
+ return process.env.NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT || EXTRA_ENV.EMAIL_AUTH_ENDPOINT;
75
+ case "NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT" /* NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT */:
76
+ return process.env.NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT || EXTRA_ENV.GOOGLE_AUTH_ENDPOINT;
77
+ case "NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT" /* NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT */:
78
+ return process.env.NEXT_PUBLIC_SOCIAL_AUTH_ENDPOINT || EXTRA_ENV.SOCIAL_AUTH_ENDPOINT;
79
+ case "NEXT_PUBLIC_FILE_ENDPOINT" /* NEXT_PUBLIC_FILE_ENDPOINT */:
80
+ return process.env.NEXT_PUBLIC_FILE_ENDPOINT || EXTRA_ENV.FILE_ENDPOINT;
81
+ case "NEXT_PUBLIC_BASE_URL" /* NEXT_PUBLIC_BASE_URL */:
82
+ return process.env.NEXT_PUBLIC_BASE_URL || EXTRA_ENV.BASE_URL;
83
+ case "REFRESH_KEY" /* REFRESH_KEY */:
84
+ return process.env.REFRESH_KEY;
85
+ case "SIGNING_KEY" /* SIGNING_KEY */:
86
+ return process.env.SIGNING_KEY;
87
+ case "INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */:
88
+ return process.env.INSTAGRAM_CLIENT_SECRET;
89
+ case "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */:
90
+ return process.env.INSTAGRAM_CLIENT_ID;
91
+ case "GOOGLE_CLIENT_SECRET" /* GOOGLE_CLIENT_SECRET */:
92
+ return process.env.GOOGLE_CLIENT_SECRET;
93
+ case "GOOGLE_CLIENT_ID" /* GOOGLE_CLIENT_ID */:
94
+ return process.env.GOOGLE_CLIENT_ID;
95
+ case "TURNSTILE_KEY" /* TURNSTILE_KEY */:
96
+ return process.env.TURNSTILE_KEY;
97
+ case "S3_ACCESS_KEY_ID" /* S3_ACCESS_KEY_ID */:
98
+ return process.env.S3_ACCESS_KEY_ID;
99
+ case "S3_ACCESS_KEY_SECRET" /* S3_ACCESS_KEY_SECRET */:
100
+ return process.env.S3_ACCESS_KEY_SECRET;
101
+ case "S3_REGION" /* S3_REGION */:
102
+ return process.env.S3_REGION;
103
+ case "S3_BUCKET" /* S3_BUCKET */:
104
+ return process.env.S3_BUCKET;
105
+ case "NODE_ENV" /* NODE_ENV */:
106
+ return process.env.NODE_ENV;
107
+ default:
108
+ return process.env[key];
109
+ }
110
+ };
111
+ function getEnv(key, skipCheck) {
112
+ const value = getEnvValue(key);
113
+ if (!skipCheck && !value) throw new Error(`${key} is not defined`);
114
+ return value;
115
+ }
116
+
117
+ // src/auth/email/token.ts
118
+ function getUserIdFromAccessToken(accessToken) {
119
+ if (accessToken)
120
+ try {
121
+ const decoded = (0, import_jsonwebtoken.verify)(accessToken, getEnv("SIGNING_KEY" /* SIGNING_KEY */));
122
+ if (typeof decoded !== "string" && typeof decoded.id === "number")
123
+ return decoded.id;
124
+ } catch (e) {
125
+ if (!(e instanceof import_jsonwebtoken.JsonWebTokenError)) console.error(e, "errors");
126
+ return null;
127
+ }
128
+ return null;
129
+ }
130
+
131
+ // src/socials/connect.ts
132
+ function setupSocialAuth({
133
+ providers,
134
+ endpoint,
135
+ onConnect,
136
+ redirectURL,
137
+ errorRedirectURL,
138
+ scopes
139
+ }) {
140
+ const handleError = (message) => import_server2.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
141
+ const GET = async (req, ctx) => {
142
+ const { platform } = await ctx.params;
143
+ const provider = providers.find((p) => p.platform === platform);
144
+ if (!provider) return handleError("Unsupported platform");
145
+ const code = req.nextUrl.searchParams.get("code");
146
+ const error = req.nextUrl.searchParams.get("error");
147
+ const state = req.nextUrl.searchParams.get("state");
148
+ if (error) return handleError(error);
149
+ if (!state) return handleError("Invalid request");
150
+ const redirectURI = `${endpoint}/${provider.platform}`;
151
+ if (!code) {
152
+ return import_server2.NextResponse.redirect(
153
+ provider.auth.authorizationURL({
154
+ state,
155
+ redirectURI,
156
+ scopes: scopes?.[provider.platform]
157
+ }),
158
+ 302
159
+ );
160
+ }
161
+ const exchanged = await provider.auth.exchangeCode({ code, redirectURI });
162
+ if (!exchanged) return handleError("Couldn't connect your account");
163
+ const { platformUserId, ...tokens } = exchanged;
164
+ const profile = await provider.fetchProfile(tokens.accessToken);
165
+ if (!profile) return handleError("Couldn't read your profile");
166
+ const errorMessage = await onConnect({
167
+ platform: provider.platform,
168
+ profile: {
169
+ ...profile,
170
+ platformUserId: profile.platformUserId ?? platformUserId
171
+ },
172
+ tokens,
173
+ userId: getUserIdFromAccessToken(state)
174
+ });
175
+ if (errorMessage) return handleError(errorMessage);
176
+ return import_server2.NextResponse.redirect(redirectURL);
177
+ };
178
+ return { GET };
179
+ }
180
+
181
+ // src/socials/types.ts
182
+ var SocialPlatform = /* @__PURE__ */ ((SocialPlatform2) => {
183
+ SocialPlatform2["Instagram"] = "instagram";
184
+ SocialPlatform2["YouTube"] = "youtube";
185
+ SocialPlatform2["TikTok"] = "tiktok";
186
+ return SocialPlatform2;
187
+ })(SocialPlatform || {});
188
+ var SocialMediaKind = /* @__PURE__ */ ((SocialMediaKind2) => {
189
+ SocialMediaKind2["Image"] = "image";
190
+ SocialMediaKind2["Video"] = "video";
191
+ SocialMediaKind2["Carousel"] = "carousel";
192
+ return SocialMediaKind2;
193
+ })(SocialMediaKind || {});
194
+
195
+ // src/socials/instagram/auth.ts
196
+ var getInstagramAuthorizationURL = (state, redirectURI, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
197
+ "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
198
+ )}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${state}&redirect_uri=${redirectURI}#weblink`;
199
+ async function getLongLivedInstagramToken(code, redirectURI) {
200
+ const formData = new FormData();
201
+ formData.set("client_id", getEnv("INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */));
202
+ formData.set("client_secret", getEnv("INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */));
203
+ formData.set("grant_type", "authorization_code");
204
+ formData.set("redirect_uri", redirectURI);
205
+ formData.set("code", code);
206
+ const shortRes = await fetch("https://api.instagram.com/oauth/access_token", {
207
+ method: "POST",
208
+ body: formData
209
+ });
210
+ if (!shortRes.ok) return void 0;
211
+ const shortResData = await shortRes.json();
212
+ if (!shortResData.access_token) return void 0;
213
+ const longRes = await fetch(
214
+ `https://graph.instagram.com/access_token?grant_type=ig_exchange_token&access_token=${shortResData.access_token}&client_secret=${getEnv("INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */)}`
215
+ );
216
+ if (!longRes.ok) return void 0;
217
+ const longResData = await longRes.json();
218
+ return {
219
+ accessToken: longResData.access_token,
220
+ userId: shortResData.user_id,
221
+ expiresIn: longResData.expires_in,
222
+ permissions: shortResData.permissions
223
+ };
224
+ }
225
+ async function refreshInstagramAccessToken(token) {
226
+ const request = await fetch(
227
+ `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
228
+ );
229
+ const response = await request.json();
230
+ if (!response.access_token) return void 0;
231
+ return {
232
+ accessToken: response.access_token,
233
+ expiresIn: response.expires_in
234
+ };
235
+ }
236
+
48
237
  // src/socials/meta/request.ts
49
238
  function createGraphClient(baseURL) {
50
239
  const buildURL = (token, path, params = {}) => {
@@ -177,25 +366,152 @@ var canPublishToInstagram = async (token) => {
177
366
  return true;
178
367
  };
179
368
 
180
- // src/socials/meta/container.ts
369
+ // src/socials/instagram/adapter.ts
370
+ var PROFILE_FIELDS = [
371
+ "id",
372
+ "user_id",
373
+ "username",
374
+ "name",
375
+ "profile_picture_url",
376
+ "followers_count",
377
+ "media_count"
378
+ ];
379
+ var MEDIA_FIELDS = [
380
+ "id",
381
+ "caption",
382
+ "media_type",
383
+ "media_url",
384
+ "permalink",
385
+ "thumbnail_url",
386
+ "timestamp",
387
+ "like_count",
388
+ "comments_count"
389
+ ];
390
+ var expiresAt = (seconds) => seconds ? new Date(Date.now() + seconds * 1e3) : void 0;
391
+ function toKind(mediaType) {
392
+ if (mediaType === "VIDEO") return "video" /* Video */;
393
+ if (mediaType === "CAROUSEL_ALBUM") return "carousel" /* Carousel */;
394
+ return "image" /* Image */;
395
+ }
396
+ function toPost(media) {
397
+ const kind = toKind(media.media_type);
398
+ return {
399
+ platform: "instagram" /* Instagram */,
400
+ platformMediaId: media.id,
401
+ permalink: media.permalink,
402
+ // A video's `media_url` is the .mp4 itself, so it is never a stand-in for a
403
+ // missing poster frame — better no thumbnail than one that can't render.
404
+ thumbnail: media.thumbnail_url ?? (kind === "video" /* Video */ ? null : media.media_url ?? null),
405
+ mediaURL: media.media_url ?? null,
406
+ caption: media.caption ?? null,
407
+ kind,
408
+ publishedAt: media.timestamp,
409
+ likes: media.like_count ?? null,
410
+ comments: media.comments_count ?? null,
411
+ // Both need the Insights API; the basic media fields carry neither.
412
+ views: null,
413
+ shares: null,
414
+ metadata: {}
415
+ };
416
+ }
417
+ var InstagramProvider = {
418
+ platform: "instagram" /* Instagram */,
419
+ auth: {
420
+ authorizationURL: ({ state, redirectURI, scopes }) => getInstagramAuthorizationURL(
421
+ state,
422
+ redirectURI,
423
+ scopes
424
+ ),
425
+ exchangeCode: async ({ code, redirectURI }) => {
426
+ const result = await getLongLivedInstagramToken(code, redirectURI);
427
+ if (!result) {
428
+ console.error("[naystack] Instagram code exchange returned no token");
429
+ return null;
430
+ }
431
+ return {
432
+ accessToken: result.accessToken,
433
+ platformUserId: result.userId || null,
434
+ expiresAt: expiresAt(result.expiresIn),
435
+ scopes: result.permissions
436
+ };
437
+ },
438
+ refresh: async ({ accessToken }) => {
439
+ const refreshed = await refreshInstagramAccessToken(accessToken);
440
+ if (!refreshed) return null;
441
+ return {
442
+ accessToken: refreshed.accessToken,
443
+ expiresAt: expiresAt(refreshed.expiresIn)
444
+ };
445
+ }
446
+ },
447
+ profileURL: (username) => `https://instagram.com/${username}`,
448
+ fetchProfile: async (accessToken) => {
449
+ const user = await getInstagramUser(
450
+ accessToken,
451
+ void 0,
452
+ PROFILE_FIELDS
453
+ );
454
+ if (!user?.username) return null;
455
+ return {
456
+ platform: "instagram" /* Instagram */,
457
+ // `user_id` is what the OAuth exchange hands back, so preferring it keeps
458
+ // one account's id identical however it was read.
459
+ platformUserId: user.user_id || user.id || null,
460
+ username: user.username,
461
+ displayName: user.name ?? null,
462
+ avatar: user.profile_picture_url ?? null,
463
+ followers: user.followers_count ?? 0,
464
+ contentCount: user.media_count ?? 0,
465
+ metadata: {}
466
+ };
467
+ },
468
+ fetchMedia: async (accessToken, options) => {
469
+ const result = await getInstagramMedia(
470
+ accessToken,
471
+ MEDIA_FIELDS,
472
+ options?.limit
473
+ );
474
+ if (!result?.data) return [];
475
+ return result.data.map(toPost);
476
+ }
477
+ };
478
+
479
+ // src/socials/utils/poll.ts
181
480
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
182
- async function waitForContainer(getState, { intervalMS = 5e3, timeoutMS = 3e5 } = {}) {
481
+ async function pollUntilReady(read, isPending, { intervalMS = 5e3, timeoutMS = 3e5 } = {}) {
183
482
  const deadline = Date.now() + timeoutMS;
184
- let state = await getState();
483
+ let state = await read();
185
484
  if (!state) {
186
485
  await sleep(2e3);
187
486
  return null;
188
487
  }
189
- while (state?.status === "IN_PROGRESS" && Date.now() < deadline) {
488
+ while (state && isPending(state) && Date.now() < deadline) {
190
489
  await sleep(intervalMS);
191
- state = await getState();
490
+ state = await read();
192
491
  }
193
492
  return state;
194
493
  }
494
+ async function withRetry(run, options = {}) {
495
+ const attempts = Math.max(1, options.attempts ?? 3);
496
+ const backoffMS = options.backoffMS ?? 2e3;
497
+ for (let attempt = 1; attempt <= attempts; attempt++) {
498
+ const result = await run(attempt);
499
+ if (result) return result;
500
+ if (attempt < attempts) {
501
+ const delayMS = backoffMS * 2 ** (attempt - 1);
502
+ options.onRetry?.(attempt, attempts, delayMS);
503
+ await sleep(delayMS);
504
+ }
505
+ }
506
+ return null;
507
+ }
508
+
509
+ // src/socials/meta/container.ts
195
510
  function createPublisher(platform) {
196
511
  const isReady = async (token, id, label, wait) => {
197
- const state = await waitForContainer(
512
+ const state = await pollUntilReady(
198
513
  () => platform.getStatus(token, id),
514
+ (current) => current.status === "IN_PROGRESS",
199
515
  wait
200
516
  );
201
517
  if (state && state.status !== "FINISHED" && state.status !== "PUBLISHED") {
@@ -206,22 +522,21 @@ function createPublisher(platform) {
206
522
  }
207
523
  return true;
208
524
  };
209
- const createReady = async (token, params, label, wait, retry) => {
210
- const attempts = Math.max(1, retry?.attempts ?? 3);
211
- const backoffMS = retry?.backoffMS ?? 2e3;
212
- for (let attempt = 1; attempt <= attempts; attempt++) {
525
+ const createReady = (token, params, label, wait, retry) => withRetry(
526
+ async () => {
213
527
  const id = await platform.createContainer(token, params);
214
- if (id && await isReady(token, id, label, wait)) return id;
215
- if (attempt < attempts) {
216
- const delay = backoffMS * 2 ** (attempt - 1);
528
+ if (!id || !await isReady(token, id, label, wait)) return null;
529
+ return id;
530
+ },
531
+ {
532
+ ...retry,
533
+ onRetry: (attempt, attempts, delayMS) => {
217
534
  console.warn(
218
- `[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
535
+ `[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delayMS}ms`
219
536
  );
220
- await sleep(delay);
221
537
  }
222
538
  }
223
- return null;
224
- };
539
+ );
225
540
  return {
226
541
  /** Creates a container, waits for it to finish processing, then publishes it. */
227
542
  publish: async (token, params, wait, retry) => {
@@ -384,11 +699,11 @@ var sendInstagramMessage = (token, to, text) => {
384
699
  };
385
700
 
386
701
  // src/socials/meta/webhook.ts
387
- var import_server = require("next/server");
702
+ var import_server3 = require("next/server");
388
703
  var verifyWebhook = (secret) => (req) => {
389
704
  const params = req.nextUrl.searchParams;
390
705
  if (params.get("hub.verify_token") === secret) {
391
- return new import_server.NextResponse(params.get("hub.challenge"));
706
+ return new import_server3.NextResponse(params.get("hub.challenge"));
392
707
  }
393
708
  };
394
709
 
@@ -522,11 +837,15 @@ var setupThreadsWebhook = (options) => {
522
837
  };
523
838
  // Annotate the CommonJS export names for ESM import in node:
524
839
  0 && (module.exports = {
840
+ InstagramProvider,
525
841
  MetaMediaType,
842
+ SocialMediaKind,
843
+ SocialPlatform,
526
844
  canPublishToInstagram,
527
845
  createInstagramPost,
528
846
  createThread,
529
847
  createThreadsPost,
848
+ getInstagramAuthorizationURL,
530
849
  getInstagramConversation,
531
850
  getInstagramConversationByUser,
532
851
  getInstagramConversations,
@@ -535,13 +854,18 @@ var setupThreadsWebhook = (options) => {
535
854
  getInstagramMedia,
536
855
  getInstagramMessage,
537
856
  getInstagramUser,
857
+ getLongLivedInstagramToken,
538
858
  getThread,
539
859
  getThreads,
540
860
  getThreadsData,
541
861
  getThreadsReplies,
862
+ pollUntilReady,
542
863
  readGraphID,
864
+ refreshInstagramAccessToken,
543
865
  replyToInstagramComment,
544
866
  sendInstagramMessage,
545
867
  setupInstagramWebhook,
546
- setupThreadsWebhook
868
+ setupSocialAuth,
869
+ setupThreadsWebhook,
870
+ withRetry
547
871
  });
@@ -1,14 +1,20 @@
1
+ export { SetupSocialAuthOptions, SocialConnection, setupSocialAuth } from './connect.mjs';
2
+ export { InstagramProvider } from './instagram/adapter.mjs';
3
+ export { InstagramScope, getInstagramAuthorizationURL, getLongLivedInstagramToken, refreshInstagramAccessToken } from './instagram/auth.mjs';
1
4
  export { canPublishToInstagram, getInstagramConversation, getInstagramConversationByUser, getInstagramConversations, getInstagramConversationsByUser, getInstagramMedia, getInstagramMessage, getInstagramUser } from './instagram/getters.mjs';
2
5
  export { createInstagramPost, replyToInstagramComment, sendInstagramMessage } from './instagram/setters.mjs';
3
6
  export { InstagramConversation, InstagramMedia, InstagramMessage, InstagramPostInput, InstagramPostMedia, InstagramUser } from './instagram/types.mjs';
4
7
  export { getInstagramData } from './instagram/utils.mjs';
5
8
  export { setupInstagramWebhook } from './instagram/webhook.mjs';
6
- export { RetryOptions, WaitForContainerOptions } from './meta/container.mjs';
9
+ export { WaitForContainerOptions } from './meta/container.mjs';
7
10
  export { GraphClient, GraphRequestOptions, readGraphID } from './meta/request.mjs';
8
11
  export { GraphError, GraphParams, MetaMediaType } from './meta/types.mjs';
12
+ export { SocialProvider } from './provider.mjs';
9
13
  export { getThread, getThreads, getThreadsReplies } from './threads/getters.mjs';
10
14
  export { createThread, createThreadsPost } from './threads/setters.mjs';
11
- export { getThreadsData } from './threads/utils.mjs';
12
15
  export { ThreadsPost, ThreadsPostInput, ThreadsPostMedia } from './threads/types.mjs';
16
+ export { getThreadsData } from './threads/utils.mjs';
13
17
  export { setupThreadsWebhook } from './threads/webhook.mjs';
18
+ export { SocialMediaKind, SocialPlatform, SocialPost, SocialProfile, SocialTokens } from './types.mjs';
19
+ export { PollOptions, RetryOptions, pollUntilReady, withRetry } from './utils/poll.mjs';
14
20
  import 'next/server';
@@ -1,14 +1,20 @@
1
+ export { SetupSocialAuthOptions, SocialConnection, setupSocialAuth } from './connect.js';
2
+ export { InstagramProvider } from './instagram/adapter.js';
3
+ export { InstagramScope, getInstagramAuthorizationURL, getLongLivedInstagramToken, refreshInstagramAccessToken } from './instagram/auth.js';
1
4
  export { canPublishToInstagram, getInstagramConversation, getInstagramConversationByUser, getInstagramConversations, getInstagramConversationsByUser, getInstagramMedia, getInstagramMessage, getInstagramUser } from './instagram/getters.js';
2
5
  export { createInstagramPost, replyToInstagramComment, sendInstagramMessage } from './instagram/setters.js';
3
6
  export { InstagramConversation, InstagramMedia, InstagramMessage, InstagramPostInput, InstagramPostMedia, InstagramUser } from './instagram/types.js';
4
7
  export { getInstagramData } from './instagram/utils.js';
5
8
  export { setupInstagramWebhook } from './instagram/webhook.js';
6
- export { RetryOptions, WaitForContainerOptions } from './meta/container.js';
9
+ export { WaitForContainerOptions } from './meta/container.js';
7
10
  export { GraphClient, GraphRequestOptions, readGraphID } from './meta/request.js';
8
11
  export { GraphError, GraphParams, MetaMediaType } from './meta/types.js';
12
+ export { SocialProvider } from './provider.js';
9
13
  export { getThread, getThreads, getThreadsReplies } from './threads/getters.js';
10
14
  export { createThread, createThreadsPost } from './threads/setters.js';
11
- export { getThreadsData } from './threads/utils.js';
12
15
  export { ThreadsPost, ThreadsPostInput, ThreadsPostMedia } from './threads/types.js';
16
+ export { getThreadsData } from './threads/utils.js';
13
17
  export { setupThreadsWebhook } from './threads/webhook.js';
18
+ export { SocialMediaKind, SocialPlatform, SocialPost, SocialProfile, SocialTokens } from './types.js';
19
+ export { PollOptions, RetryOptions, pollUntilReady, withRetry } from './utils/poll.js';
14
20
  import 'next/server';