@classytic/social 0.1.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.
Files changed (121) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +21 -0
  3. package/README.md +368 -0
  4. package/dist/base-Bw7e52V8.mjs +246 -0
  5. package/dist/base-Bw7e52V8.mjs.map +1 -0
  6. package/dist/base-DBtKFiSX.d.mts +226 -0
  7. package/dist/base-DBtKFiSX.d.mts.map +1 -0
  8. package/dist/chunk-DQk6qfdC.mjs +18 -0
  9. package/dist/client/index.d.mts +44 -0
  10. package/dist/client/index.d.mts.map +1 -0
  11. package/dist/client/index.mjs +154 -0
  12. package/dist/client/index.mjs.map +1 -0
  13. package/dist/common/index.d.mts +3 -0
  14. package/dist/common/index.mjs +7 -0
  15. package/dist/contracts-Cdwa4zlg.d.mts +121 -0
  16. package/dist/contracts-Cdwa4zlg.d.mts.map +1 -0
  17. package/dist/contracts-lCa069IK.mjs +221 -0
  18. package/dist/contracts-lCa069IK.mjs.map +1 -0
  19. package/dist/env-Bl0cwwjC.mjs +955 -0
  20. package/dist/env-Bl0cwwjC.mjs.map +1 -0
  21. package/dist/env-DxOZHf0p.d.mts +394 -0
  22. package/dist/env-DxOZHf0p.d.mts.map +1 -0
  23. package/dist/errors-Cm6LeKf7.mjs +32 -0
  24. package/dist/errors-Cm6LeKf7.mjs.map +1 -0
  25. package/dist/facebook-l_4CghaA.mjs +95 -0
  26. package/dist/facebook-l_4CghaA.mjs.map +1 -0
  27. package/dist/http-DpcLSR1M.mjs +197 -0
  28. package/dist/http-DpcLSR1M.mjs.map +1 -0
  29. package/dist/index.d.mts +42 -0
  30. package/dist/index.d.mts.map +1 -0
  31. package/dist/index.mjs +71 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/instagram-BGaeUFU2.mjs +90 -0
  34. package/dist/instagram-BGaeUFU2.mjs.map +1 -0
  35. package/dist/linkedin-70whtVKa.mjs +101 -0
  36. package/dist/linkedin-70whtVKa.mjs.map +1 -0
  37. package/dist/meta-D3vcJU1c.mjs +126 -0
  38. package/dist/meta-D3vcJU1c.mjs.map +1 -0
  39. package/dist/pkce-jq5II68b.mjs +72 -0
  40. package/dist/pkce-jq5II68b.mjs.map +1 -0
  41. package/dist/polling-DZ1apXtA.mjs +25 -0
  42. package/dist/polling-DZ1apXtA.mjs.map +1 -0
  43. package/dist/providers/facebook.d.mts +135 -0
  44. package/dist/providers/facebook.d.mts.map +1 -0
  45. package/dist/providers/facebook.mjs +450 -0
  46. package/dist/providers/facebook.mjs.map +1 -0
  47. package/dist/providers/instagram.d.mts +122 -0
  48. package/dist/providers/instagram.d.mts.map +1 -0
  49. package/dist/providers/instagram.mjs +496 -0
  50. package/dist/providers/instagram.mjs.map +1 -0
  51. package/dist/providers/linkedin.d.mts +145 -0
  52. package/dist/providers/linkedin.d.mts.map +1 -0
  53. package/dist/providers/linkedin.mjs +574 -0
  54. package/dist/providers/linkedin.mjs.map +1 -0
  55. package/dist/providers/reddit.d.mts +102 -0
  56. package/dist/providers/reddit.d.mts.map +1 -0
  57. package/dist/providers/reddit.mjs +657 -0
  58. package/dist/providers/reddit.mjs.map +1 -0
  59. package/dist/providers/telegram.d.mts +139 -0
  60. package/dist/providers/telegram.d.mts.map +1 -0
  61. package/dist/providers/telegram.mjs +517 -0
  62. package/dist/providers/telegram.mjs.map +1 -0
  63. package/dist/providers/tiktok.d.mts +116 -0
  64. package/dist/providers/tiktok.d.mts.map +1 -0
  65. package/dist/providers/tiktok.mjs +676 -0
  66. package/dist/providers/tiktok.mjs.map +1 -0
  67. package/dist/providers/twitter.d.mts +150 -0
  68. package/dist/providers/twitter.d.mts.map +1 -0
  69. package/dist/providers/twitter.mjs +628 -0
  70. package/dist/providers/twitter.mjs.map +1 -0
  71. package/dist/providers/whatsapp.d.mts +79 -0
  72. package/dist/providers/whatsapp.d.mts.map +1 -0
  73. package/dist/providers/whatsapp.mjs +376 -0
  74. package/dist/providers/whatsapp.mjs.map +1 -0
  75. package/dist/providers/youtube.d.mts +153 -0
  76. package/dist/providers/youtube.d.mts.map +1 -0
  77. package/dist/providers/youtube.mjs +902 -0
  78. package/dist/providers/youtube.mjs.map +1 -0
  79. package/dist/reddit-B10kS4Se.mjs +126 -0
  80. package/dist/reddit-B10kS4Se.mjs.map +1 -0
  81. package/dist/schemas/index.d.mts +819 -0
  82. package/dist/schemas/index.d.mts.map +1 -0
  83. package/dist/schemas/index.mjs +31 -0
  84. package/dist/schemas/index.mjs.map +1 -0
  85. package/dist/security-BXhfebWm.d.mts +338 -0
  86. package/dist/security-BXhfebWm.d.mts.map +1 -0
  87. package/dist/shared-Fvc6xQku.mjs +100 -0
  88. package/dist/shared-Fvc6xQku.mjs.map +1 -0
  89. package/dist/telegram-FaUHpZgB.mjs +107 -0
  90. package/dist/telegram-FaUHpZgB.mjs.map +1 -0
  91. package/dist/tiktok-B_bMk4G-.mjs +94 -0
  92. package/dist/tiktok-B_bMk4G-.mjs.map +1 -0
  93. package/dist/twitter-BC22zfuc.mjs +98 -0
  94. package/dist/twitter-BC22zfuc.mjs.map +1 -0
  95. package/dist/types-BFE4psYI.d.mts +102 -0
  96. package/dist/types-BFE4psYI.d.mts.map +1 -0
  97. package/dist/types-Bv27tcT0.d.mts +230 -0
  98. package/dist/types-Bv27tcT0.d.mts.map +1 -0
  99. package/dist/types-BwkKyqpi.d.mts +253 -0
  100. package/dist/types-BwkKyqpi.d.mts.map +1 -0
  101. package/dist/types-CJrHMDV9.mjs +27 -0
  102. package/dist/types-CJrHMDV9.mjs.map +1 -0
  103. package/dist/types-ClbVc2rc.d.mts +117 -0
  104. package/dist/types-ClbVc2rc.d.mts.map +1 -0
  105. package/dist/types-D91N16Ym.d.mts +242 -0
  106. package/dist/types-D91N16Ym.d.mts.map +1 -0
  107. package/dist/types-DfLp_ibQ.d.mts +178 -0
  108. package/dist/types-DfLp_ibQ.d.mts.map +1 -0
  109. package/dist/types-DfjDgEoJ.d.mts +88 -0
  110. package/dist/types-DfjDgEoJ.d.mts.map +1 -0
  111. package/dist/types-Dp5Z9VBr.mjs +23 -0
  112. package/dist/types-Dp5Z9VBr.mjs.map +1 -0
  113. package/dist/types-hriBJTsU.d.mts +129 -0
  114. package/dist/types-hriBJTsU.d.mts.map +1 -0
  115. package/dist/types-rn6UuLL8.d.mts +184 -0
  116. package/dist/types-rn6UuLL8.d.mts.map +1 -0
  117. package/dist/whatsapp-CFp7ryR4.mjs +101 -0
  118. package/dist/whatsapp-CFp7ryR4.mjs.map +1 -0
  119. package/dist/youtube-Bs0fdY7H.mjs +98 -0
  120. package/dist/youtube-Bs0fdY7H.mjs.map +1 -0
  121. package/package.json +148 -0
@@ -0,0 +1,101 @@
1
+ import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
2
+ import { i as OAuthTokensSchema, r as NonEmptyString } from "./shared-Fvc6xQku.mjs";
3
+ import { z } from "zod";
4
+
5
+ //#region src/schemas/linkedin.ts
6
+ /**
7
+ * LinkedIn zod v4 schemas.
8
+ */
9
+ var linkedin_exports = /* @__PURE__ */ __exportAll({
10
+ LinkedInArticlePostSchema: () => LinkedInArticlePostSchema,
11
+ LinkedInCredentialDataSchema: () => LinkedInCredentialDataSchema,
12
+ LinkedInCredentialsSchema: () => LinkedInCredentialsSchema,
13
+ LinkedInImagePostSchema: () => LinkedInImagePostSchema,
14
+ LinkedInLifecycleState: () => LinkedInLifecycleState,
15
+ LinkedInTextPostSchema: () => LinkedInTextPostSchema,
16
+ LinkedInUrn: () => LinkedInUrn,
17
+ LinkedInVideoUploadSchema: () => LinkedInVideoUploadSchema,
18
+ LinkedInVisibility: () => LinkedInVisibility,
19
+ linkedinCapabilities: () => linkedinCapabilities,
20
+ linkedinInfo: () => linkedinInfo
21
+ });
22
+ const LinkedInCredentialsSchema = z.object({
23
+ clientId: NonEmptyString.describe("LinkedIn app client ID"),
24
+ clientSecret: NonEmptyString.describe("LinkedIn app client secret"),
25
+ redirectUri: z.url().optional()
26
+ });
27
+ const LinkedInCredentialDataSchema = LinkedInCredentialsSchema.extend({ oauthTokenData: z.union([z.string(), OAuthTokensSchema]).optional() });
28
+ const LinkedInVisibility = z.enum([
29
+ "PUBLIC",
30
+ "CONNECTIONS",
31
+ "LOGGED_IN",
32
+ "CONTAINER"
33
+ ]);
34
+ const LinkedInLifecycleState = z.enum([
35
+ "DRAFT",
36
+ "PUBLISHED",
37
+ "PUBLISHED_EDITED"
38
+ ]);
39
+ const LinkedInUrn = z.string().regex(/^urn:li:(person|organization|share|ugcPost):[A-Za-z0-9_-]+$/, "Must be a LinkedIn URN (e.g., urn:li:person:abc123)");
40
+ const LinkedInTextPostSchema = z.object({
41
+ authorUrn: LinkedInUrn,
42
+ text: z.string().min(1).max(3e3),
43
+ visibility: LinkedInVisibility.optional().default("PUBLIC")
44
+ });
45
+ const LinkedInArticlePostSchema = z.object({
46
+ authorUrn: LinkedInUrn,
47
+ text: z.string().max(3e3).optional(),
48
+ url: z.url(),
49
+ title: z.string().max(400).optional(),
50
+ description: z.string().max(4096).optional(),
51
+ visibility: LinkedInVisibility.optional().default("PUBLIC")
52
+ });
53
+ const LinkedInImagePostSchema = z.object({
54
+ authorUrn: LinkedInUrn,
55
+ text: z.string().max(3e3),
56
+ imageBuffer: z.instanceof(Uint8Array).optional().describe("Raw image bytes — provider downloads from imageUrl if absent"),
57
+ imageUrl: z.url().optional(),
58
+ visibility: LinkedInVisibility.optional().default("PUBLIC")
59
+ }).refine((d) => d.imageBuffer || d.imageUrl, { message: "Provide either imageBuffer or imageUrl" });
60
+ const LinkedInVideoUploadSchema = z.object({
61
+ authorUrn: LinkedInUrn,
62
+ text: z.string().max(3e3).optional(),
63
+ videoUrl: z.url(),
64
+ visibility: LinkedInVisibility.optional().default("PUBLIC")
65
+ });
66
+ const linkedinCapabilities = {
67
+ auth: "oauth2",
68
+ posting: true,
69
+ upload: true,
70
+ messaging: false,
71
+ scheduling: false,
72
+ deletion: true,
73
+ listing: false,
74
+ analytics: true,
75
+ environments: false,
76
+ pkce: false
77
+ };
78
+ const linkedinInfo = {
79
+ name: "linkedin",
80
+ displayName: "LinkedIn",
81
+ scopes: [
82
+ "openid",
83
+ "profile",
84
+ "email",
85
+ "w_member_social",
86
+ "w_organization_social"
87
+ ],
88
+ rateLimits: { perDay: 100 },
89
+ fileLimits: {
90
+ image: { maxSizeBytes: 5 * 1024 * 1024 },
91
+ video: {
92
+ maxSizeBytes: 5 * 1024 ** 3,
93
+ maxDurationSec: 1800
94
+ }
95
+ },
96
+ docsUrl: "https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/posts-api"
97
+ };
98
+
99
+ //#endregion
100
+ export { linkedin_exports as i, linkedinCapabilities as n, linkedinInfo as r, LinkedInCredentialsSchema as t };
101
+ //# sourceMappingURL=linkedin-70whtVKa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linkedin-70whtVKa.mjs","names":[],"sources":["../src/schemas/linkedin.ts"],"sourcesContent":["/**\n * LinkedIn zod v4 schemas.\n */\n\nimport { z } from 'zod';\nimport type { ProviderCapabilities } from '../common/contracts.js';\nimport { NonEmptyString, OAuthTokensSchema } from './shared.js';\n\n// ─── Credentials ────────────────────────────────────────────────────────────\n\nexport const LinkedInCredentialsSchema = z.object({\n clientId: NonEmptyString.describe('LinkedIn app client ID'),\n clientSecret: NonEmptyString.describe('LinkedIn app client secret'),\n redirectUri: z.url().optional(),\n});\nexport type LinkedInCredentialsInput = z.infer<typeof LinkedInCredentialsSchema>;\n\nexport const LinkedInCredentialDataSchema = LinkedInCredentialsSchema.extend({\n oauthTokenData: z.union([z.string(), OAuthTokensSchema]).optional(),\n});\n\n// ─── Post visibility / lifecycle ────────────────────────────────────────────\n\nexport const LinkedInVisibility = z.enum(['PUBLIC', 'CONNECTIONS', 'LOGGED_IN', 'CONTAINER']);\nexport const LinkedInLifecycleState = z.enum(['DRAFT', 'PUBLISHED', 'PUBLISHED_EDITED']);\n\n// LinkedIn URN — `urn:li:person:xxx` or `urn:li:organization:xxx`.\nexport const LinkedInUrn = z.string().regex(\n /^urn:li:(person|organization|share|ugcPost):[A-Za-z0-9_-]+$/,\n 'Must be a LinkedIn URN (e.g., urn:li:person:abc123)',\n);\n\n// ─── Post creation ──────────────────────────────────────────────────────────\n\nexport const LinkedInTextPostSchema = z.object({\n authorUrn: LinkedInUrn,\n text: z.string().min(1).max(3000),\n visibility: LinkedInVisibility.optional().default('PUBLIC'),\n});\n\nexport const LinkedInArticlePostSchema = z.object({\n authorUrn: LinkedInUrn,\n text: z.string().max(3000).optional(),\n url: z.url(),\n title: z.string().max(400).optional(),\n description: z.string().max(4096).optional(),\n visibility: LinkedInVisibility.optional().default('PUBLIC'),\n});\n\nexport const LinkedInImagePostSchema = z.object({\n authorUrn: LinkedInUrn,\n text: z.string().max(3000),\n imageBuffer: z.instanceof(Uint8Array).optional()\n .describe('Raw image bytes — provider downloads from imageUrl if absent'),\n imageUrl: z.url().optional(),\n visibility: LinkedInVisibility.optional().default('PUBLIC'),\n}).refine(d => d.imageBuffer || d.imageUrl, {\n message: 'Provide either imageBuffer or imageUrl',\n});\n\nexport const LinkedInVideoUploadSchema = z.object({\n authorUrn: LinkedInUrn,\n text: z.string().max(3000).optional(),\n videoUrl: z.url(),\n visibility: LinkedInVisibility.optional().default('PUBLIC'),\n});\n\n// ─── Capabilities ───────────────────────────────────────────────────────────\n\nexport const linkedinCapabilities: ProviderCapabilities = {\n auth: 'oauth2',\n posting: true,\n upload: true,\n messaging: false,\n scheduling: false,\n deletion: true,\n listing: false,\n analytics: true,\n environments: false,\n pkce: false,\n};\n\nexport const linkedinInfo = {\n name: 'linkedin' as const,\n displayName: 'LinkedIn',\n scopes: ['openid', 'profile', 'email', 'w_member_social', 'w_organization_social'],\n rateLimits: { perDay: 100 },\n fileLimits: {\n image: { maxSizeBytes: 5 * 1024 * 1024 },\n video: { maxSizeBytes: 5 * 1024 ** 3, maxDurationSec: 30 * 60 },\n },\n docsUrl: 'https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/posts-api',\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAUA,MAAa,4BAA4B,EAAE,OAAO;CAChD,UAAU,eAAe,SAAS,yBAAyB;CAC3D,cAAc,eAAe,SAAS,6BAA6B;CACnE,aAAa,EAAE,KAAK,CAAC,UAAU;CAChC,CAAC;AAGF,MAAa,+BAA+B,0BAA0B,OAAO,EAC3E,gBAAgB,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,UAAU,EACpE,CAAC;AAIF,MAAa,qBAAqB,EAAE,KAAK;CAAC;CAAU;CAAe;CAAa;CAAY,CAAC;AAC7F,MAAa,yBAAyB,EAAE,KAAK;CAAC;CAAS;CAAa;CAAmB,CAAC;AAGxF,MAAa,cAAc,EAAE,QAAQ,CAAC,MACpC,+DACA,sDACD;AAID,MAAa,yBAAyB,EAAE,OAAO;CAC7C,WAAW;CACX,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CACjC,YAAY,mBAAmB,UAAU,CAAC,QAAQ,SAAS;CAC5D,CAAC;AAEF,MAAa,4BAA4B,EAAE,OAAO;CAChD,WAAW;CACX,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,UAAU;CACrC,KAAK,EAAE,KAAK;CACZ,OAAO,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU;CACrC,aAAa,EAAE,QAAQ,CAAC,IAAI,KAAK,CAAC,UAAU;CAC5C,YAAY,mBAAmB,UAAU,CAAC,QAAQ,SAAS;CAC5D,CAAC;AAEF,MAAa,0BAA0B,EAAE,OAAO;CAC9C,WAAW;CACX,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAK;CAC1B,aAAa,EAAE,WAAW,WAAW,CAAC,UAAU,CAC7C,SAAS,+DAA+D;CAC3E,UAAU,EAAE,KAAK,CAAC,UAAU;CAC5B,YAAY,mBAAmB,UAAU,CAAC,QAAQ,SAAS;CAC5D,CAAC,CAAC,QAAO,MAAK,EAAE,eAAe,EAAE,UAAU,EAC1C,SAAS,0CACV,CAAC;AAEF,MAAa,4BAA4B,EAAE,OAAO;CAChD,WAAW;CACX,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,UAAU;CACrC,UAAU,EAAE,KAAK;CACjB,YAAY,mBAAmB,UAAU,CAAC,QAAQ,SAAS;CAC5D,CAAC;AAIF,MAAa,uBAA6C;CACxD,MAAM;CACN,SAAS;CACT,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,UAAU;CACV,SAAS;CACT,WAAW;CACX,cAAc;CACd,MAAM;CACP;AAED,MAAa,eAAe;CAC1B,MAAM;CACN,aAAa;CACb,QAAQ;EAAC;EAAU;EAAW;EAAS;EAAmB;EAAwB;CAClF,YAAY,EAAE,QAAQ,KAAK;CAC3B,YAAY;EACV,OAAO,EAAE,cAAc,IAAI,OAAO,MAAM;EACxC,OAAO;GAAE,cAAc,IAAI,QAAQ;GAAG,gBAAgB;GAAS;EAChE;CACD,SAAS;CACV"}
@@ -0,0 +1,126 @@
1
+ import { t as SocialError } from "./errors-Cm6LeKf7.mjs";
2
+ import { t as httpRequest } from "./http-DpcLSR1M.mjs";
3
+
4
+ //#region src/common/meta.ts
5
+ /**
6
+ * Shared Meta Graph API constants for Facebook, Instagram, and WhatsApp.
7
+ * Update META_GRAPH_VERSION here to upgrade all three providers at once.
8
+ *
9
+ * @see packages/social/wiki/facebook.md
10
+ * @see packages/social/wiki/instagram.md
11
+ * @see packages/social/wiki/whatsapp.md
12
+ */
13
+ const META_GRAPH_VERSION = "v25.0";
14
+ const META_GRAPH_BASE = `https://graph.facebook.com/${META_GRAPH_VERSION}`;
15
+ const META_GRAPH_VIDEO_BASE = `https://graph-video.facebook.com/${META_GRAPH_VERSION}`;
16
+ const META_AUTH_URL = `https://www.facebook.com/${META_GRAPH_VERSION}/dialog/oauth`;
17
+ const META_TOKEN_URL = `https://graph.facebook.com/${META_GRAPH_VERSION}/oauth/access_token`;
18
+
19
+ //#endregion
20
+ //#region src/common/oauth/meta.ts
21
+ const FB_TOKEN_URL_TEMPLATE = (version) => `https://graph.facebook.com/${version}/oauth/access_token`;
22
+ const IG_REFRESH_URL = "https://graph.instagram.com/refresh_access_token";
23
+ /**
24
+ * Two-step Meta token exchange: code → short-lived → long-lived.
25
+ *
26
+ * @param provider — `'facebook'` or `'instagram'` (used for error attribution).
27
+ * @returns Long-lived OAuth tokens. `refresh_token` is set to `access_token`
28
+ * because Meta uses the access token itself for refresh.
29
+ */
30
+ async function metaExchangeLongLived(provider, params) {
31
+ const tokenUrl = FB_TOKEN_URL_TEMPLATE(params.graphVersion);
32
+ const { data: shortData } = await httpRequest(provider, {
33
+ method: "GET",
34
+ url: tokenUrl,
35
+ query: {
36
+ client_id: params.clientId,
37
+ client_secret: params.clientSecret,
38
+ redirect_uri: params.redirectUri,
39
+ code: params.code
40
+ },
41
+ parseError: parseGraphError
42
+ });
43
+ const shortToken = shortData.access_token;
44
+ if (!shortToken) throw new SocialError(provider, "Meta token exchange returned no access_token", { statusCode: 502 });
45
+ const { data: longData } = await httpRequest(provider, {
46
+ method: "GET",
47
+ url: tokenUrl,
48
+ query: {
49
+ grant_type: "fb_exchange_token",
50
+ client_id: params.clientId,
51
+ client_secret: params.clientSecret,
52
+ fb_exchange_token: shortToken
53
+ },
54
+ parseError: parseGraphError
55
+ });
56
+ return {
57
+ access_token: longData.access_token,
58
+ refresh_token: longData.access_token,
59
+ expires_in: longData.expires_in,
60
+ token_type: longData.token_type ?? "Bearer"
61
+ };
62
+ }
63
+ /**
64
+ * Refresh a long-lived Facebook user token.
65
+ * Page tokens derived from the long-lived user token never expire.
66
+ */
67
+ async function metaRefreshLongLivedFacebook(params) {
68
+ const { data } = await httpRequest("facebook", {
69
+ method: "GET",
70
+ url: FB_TOKEN_URL_TEMPLATE(params.graphVersion),
71
+ query: {
72
+ grant_type: "fb_exchange_token",
73
+ client_id: params.clientId,
74
+ client_secret: params.clientSecret,
75
+ fb_exchange_token: params.refreshToken
76
+ },
77
+ parseError: parseGraphError
78
+ });
79
+ return {
80
+ access_token: data.access_token,
81
+ refresh_token: data.access_token,
82
+ expires_in: data.expires_in,
83
+ token_type: data.token_type ?? "Bearer"
84
+ };
85
+ }
86
+ /**
87
+ * Refresh a long-lived Instagram token (must be ≥24h old, not yet expired).
88
+ */
89
+ async function metaRefreshLongLivedInstagram(params) {
90
+ const { data } = await httpRequest("instagram", {
91
+ method: "GET",
92
+ url: IG_REFRESH_URL,
93
+ query: {
94
+ grant_type: "ig_refresh_token",
95
+ access_token: params.refreshToken
96
+ },
97
+ parseError: parseGraphError
98
+ });
99
+ return {
100
+ access_token: data.access_token,
101
+ refresh_token: data.access_token,
102
+ expires_in: data.expires_in,
103
+ token_type: data.token_type ?? "Bearer"
104
+ };
105
+ }
106
+ /**
107
+ * Parser for Graph API error envelope: `{ error: { message, code, error_subcode, type, fbtrace_id } }`.
108
+ */
109
+ function parseGraphError(raw) {
110
+ if (!raw || typeof raw !== "object") return null;
111
+ const err = raw.error;
112
+ if (!err) return null;
113
+ return {
114
+ message: err.message || `Graph API error (${err.code ?? "unknown"})`,
115
+ errorCode: err.code ?? null,
116
+ extras: {
117
+ errorSubcode: err.error_subcode,
118
+ errorType: err.type,
119
+ fbtraceId: err.fbtrace_id
120
+ }
121
+ };
122
+ }
123
+
124
+ //#endregion
125
+ export { parseGraphError as a, META_GRAPH_VERSION as c, metaRefreshLongLivedInstagram as i, META_GRAPH_VIDEO_BASE as l, metaExchangeLongLived as n, META_AUTH_URL as o, metaRefreshLongLivedFacebook as r, META_GRAPH_BASE as s, IG_REFRESH_URL as t, META_TOKEN_URL as u };
126
+ //# sourceMappingURL=meta-D3vcJU1c.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-D3vcJU1c.mjs","names":[],"sources":["../src/common/meta.ts","../src/common/oauth/meta.ts"],"sourcesContent":["/**\n * Shared Meta Graph API constants for Facebook, Instagram, and WhatsApp.\n * Update META_GRAPH_VERSION here to upgrade all three providers at once.\n *\n * @see packages/social/wiki/facebook.md\n * @see packages/social/wiki/instagram.md\n * @see packages/social/wiki/whatsapp.md\n */\n\nexport const META_GRAPH_VERSION = 'v25.0';\n\nexport const META_GRAPH_BASE = `https://graph.facebook.com/${META_GRAPH_VERSION}`;\nexport const META_GRAPH_VIDEO_BASE = `https://graph-video.facebook.com/${META_GRAPH_VERSION}`;\nexport const META_AUTH_URL = `https://www.facebook.com/${META_GRAPH_VERSION}/dialog/oauth`;\nexport const META_TOKEN_URL = `https://graph.facebook.com/${META_GRAPH_VERSION}/oauth/access_token`;\n","/**\n * Meta (Facebook / Instagram) OAuth helpers.\n *\n * Meta's token flow is non-standard:\n * - Step 1: code → short-lived token (~1 hour)\n * - Step 2: short-lived → long-lived token (~60 days)\n * - Refresh: re-exchange the long-lived token (FB) or hit graph.instagram.com (IG)\n *\n * Both Facebook and Instagram share Step 1; the only difference is the refresh URL.\n */\n\nimport type { OAuthTokens } from '../../base.js';\nimport { httpRequest } from '../http.js';\nimport { SocialError } from '../../errors.js';\n\nconst FB_TOKEN_URL_TEMPLATE = (version: string) =>\n `https://graph.facebook.com/${version}/oauth/access_token`;\n\nexport const IG_REFRESH_URL = 'https://graph.instagram.com/refresh_access_token';\n\nexport interface MetaExchangeParams {\n graphVersion: string;\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n code: string;\n}\n\n/**\n * Two-step Meta token exchange: code → short-lived → long-lived.\n *\n * @param provider — `'facebook'` or `'instagram'` (used for error attribution).\n * @returns Long-lived OAuth tokens. `refresh_token` is set to `access_token`\n * because Meta uses the access token itself for refresh.\n */\nexport async function metaExchangeLongLived(\n provider: 'facebook' | 'instagram',\n params: MetaExchangeParams,\n): Promise<OAuthTokens> {\n const tokenUrl = FB_TOKEN_URL_TEMPLATE(params.graphVersion);\n\n // Step 1: code → short-lived token\n const { data: shortData } = await httpRequest<Record<string, unknown>>(provider, {\n method: 'GET',\n url: tokenUrl,\n query: {\n client_id: params.clientId,\n client_secret: params.clientSecret,\n redirect_uri: params.redirectUri,\n code: params.code,\n },\n parseError: parseGraphError,\n });\n\n const shortToken = shortData.access_token as string | undefined;\n if (!shortToken) {\n throw new SocialError(provider, 'Meta token exchange returned no access_token', { statusCode: 502 });\n }\n\n // Step 2: short-lived → long-lived\n const { data: longData } = await httpRequest<Record<string, unknown>>(provider, {\n method: 'GET',\n url: tokenUrl,\n query: {\n grant_type: 'fb_exchange_token',\n client_id: params.clientId,\n client_secret: params.clientSecret,\n fb_exchange_token: shortToken,\n },\n parseError: parseGraphError,\n });\n\n return {\n access_token: longData.access_token as string,\n refresh_token: longData.access_token as string,\n expires_in: longData.expires_in as number | undefined,\n token_type: (longData.token_type as string) ?? 'Bearer',\n };\n}\n\n/**\n * Refresh a long-lived Facebook user token.\n * Page tokens derived from the long-lived user token never expire.\n */\nexport async function metaRefreshLongLivedFacebook(params: {\n graphVersion: string;\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n}): Promise<OAuthTokens> {\n const tokenUrl = FB_TOKEN_URL_TEMPLATE(params.graphVersion);\n const { data } = await httpRequest<Record<string, unknown>>('facebook', {\n method: 'GET',\n url: tokenUrl,\n query: {\n grant_type: 'fb_exchange_token',\n client_id: params.clientId,\n client_secret: params.clientSecret,\n fb_exchange_token: params.refreshToken,\n },\n parseError: parseGraphError,\n });\n return {\n access_token: data.access_token as string,\n refresh_token: data.access_token as string,\n expires_in: data.expires_in as number | undefined,\n token_type: (data.token_type as string) ?? 'Bearer',\n };\n}\n\n/**\n * Refresh a long-lived Instagram token (must be ≥24h old, not yet expired).\n */\nexport async function metaRefreshLongLivedInstagram(params: {\n refreshToken: string;\n}): Promise<OAuthTokens> {\n const { data } = await httpRequest<Record<string, unknown>>('instagram', {\n method: 'GET',\n url: IG_REFRESH_URL,\n query: {\n grant_type: 'ig_refresh_token',\n access_token: params.refreshToken,\n },\n parseError: parseGraphError,\n });\n return {\n access_token: data.access_token as string,\n refresh_token: data.access_token as string,\n expires_in: data.expires_in as number | undefined,\n token_type: (data.token_type as string) ?? 'Bearer',\n };\n}\n\n/**\n * Parser for Graph API error envelope: `{ error: { message, code, error_subcode, type, fbtrace_id } }`.\n */\nexport function parseGraphError(raw: unknown): ReturnType<NonNullable<Parameters<typeof httpRequest>[1]['parseError']>> {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const err = r.error as Record<string, unknown> | undefined;\n if (!err) return null;\n return {\n message: (err.message as string) || `Graph API error (${err.code ?? 'unknown'})`,\n errorCode: (err.code as number | string | null) ?? null,\n extras: {\n errorSubcode: err.error_subcode,\n errorType: err.type,\n fbtraceId: err.fbtrace_id,\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AASA,MAAa,qBAAqB;AAElC,MAAa,kBAAkB,8BAA8B;AAC7D,MAAa,wBAAwB,oCAAoC;AACzE,MAAa,gBAAgB,4BAA4B,mBAAmB;AAC5E,MAAa,iBAAiB,8BAA8B,mBAAmB;;;;ACC/E,MAAM,yBAAyB,YAC7B,8BAA8B,QAAQ;AAExC,MAAa,iBAAiB;;;;;;;;AAiB9B,eAAsB,sBACpB,UACA,QACsB;CACtB,MAAM,WAAW,sBAAsB,OAAO,aAAa;CAG3D,MAAM,EAAE,MAAM,cAAc,MAAM,YAAqC,UAAU;EAC/E,QAAQ;EACR,KAAK;EACL,OAAO;GACL,WAAW,OAAO;GAClB,eAAe,OAAO;GACtB,cAAc,OAAO;GACrB,MAAM,OAAO;GACd;EACD,YAAY;EACb,CAAC;CAEF,MAAM,aAAa,UAAU;AAC7B,KAAI,CAAC,WACH,OAAM,IAAI,YAAY,UAAU,gDAAgD,EAAE,YAAY,KAAK,CAAC;CAItG,MAAM,EAAE,MAAM,aAAa,MAAM,YAAqC,UAAU;EAC9E,QAAQ;EACR,KAAK;EACL,OAAO;GACL,YAAY;GACZ,WAAW,OAAO;GAClB,eAAe,OAAO;GACtB,mBAAmB;GACpB;EACD,YAAY;EACb,CAAC;AAEF,QAAO;EACL,cAAc,SAAS;EACvB,eAAe,SAAS;EACxB,YAAY,SAAS;EACrB,YAAa,SAAS,cAAyB;EAChD;;;;;;AAOH,eAAsB,6BAA6B,QAK1B;CAEvB,MAAM,EAAE,SAAS,MAAM,YAAqC,YAAY;EACtE,QAAQ;EACR,KAHe,sBAAsB,OAAO,aAAa;EAIzD,OAAO;GACL,YAAY;GACZ,WAAW,OAAO;GAClB,eAAe,OAAO;GACtB,mBAAmB,OAAO;GAC3B;EACD,YAAY;EACb,CAAC;AACF,QAAO;EACL,cAAc,KAAK;EACnB,eAAe,KAAK;EACpB,YAAY,KAAK;EACjB,YAAa,KAAK,cAAyB;EAC5C;;;;;AAMH,eAAsB,8BAA8B,QAE3B;CACvB,MAAM,EAAE,SAAS,MAAM,YAAqC,aAAa;EACvE,QAAQ;EACR,KAAK;EACL,OAAO;GACL,YAAY;GACZ,cAAc,OAAO;GACtB;EACD,YAAY;EACb,CAAC;AACF,QAAO;EACL,cAAc,KAAK;EACnB,eAAe,KAAK;EACpB,YAAY,KAAK;EACjB,YAAa,KAAK,cAAyB;EAC5C;;;;;AAMH,SAAgB,gBAAgB,KAAwF;AACtH,KAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;CAE5C,MAAM,MADI,IACI;AACd,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO;EACL,SAAU,IAAI,WAAsB,oBAAoB,IAAI,QAAQ,UAAU;EAC9E,WAAY,IAAI,QAAmC;EACnD,QAAQ;GACN,cAAc,IAAI;GAClB,WAAW,IAAI;GACf,WAAW,IAAI;GAChB;EACF"}
@@ -0,0 +1,72 @@
1
+ //#region src/common/oauth/pkce.ts
2
+ /**
3
+ * PKCE (Proof Key for Code Exchange) helpers for OAuth 2.0.
4
+ *
5
+ * @see https://datatracker.ietf.org/doc/html/rfc7636
6
+ */
7
+ /**
8
+ * Generate a cryptographically random code verifier.
9
+ * Length: 43 characters (RFC 7636 §4.1 allows 43-128).
10
+ */
11
+ function generateCodeVerifier(length = 64) {
12
+ const bytes = new Uint8Array(length);
13
+ crypto.getRandomValues(bytes);
14
+ return base64UrlEncode(bytes).slice(0, length);
15
+ }
16
+ /**
17
+ * Generate the SHA-256 challenge for a verifier (PKCE method `S256`).
18
+ */
19
+ async function generateCodeChallenge(verifier) {
20
+ const encoder = new TextEncoder();
21
+ const digest = await crypto.subtle.digest("SHA-256", encoder.encode(verifier));
22
+ return base64UrlEncode(new Uint8Array(digest));
23
+ }
24
+ function base64UrlEncode(bytes) {
25
+ let bin = "";
26
+ for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
27
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
28
+ }
29
+ /**
30
+ * Default in-memory verifier store with TTL-based eviction.
31
+ *
32
+ * **Note:** This is a single-process default. In multi-instance deployments,
33
+ * persist verifiers alongside `state` (e.g., in a session, Redis, or DB) and
34
+ * pass them back to `exchangeCode`. Do NOT rely on this store across servers.
35
+ */
36
+ var PkceStore = class {
37
+ entries = /* @__PURE__ */ new Map();
38
+ constructor(ttlMs = 600 * 1e3) {
39
+ this.ttlMs = ttlMs;
40
+ }
41
+ set(state, verifier) {
42
+ this.evictExpired();
43
+ this.entries.set(state, {
44
+ verifier,
45
+ expiresAt: Date.now() + this.ttlMs
46
+ });
47
+ }
48
+ /** Returns and removes the verifier (single-use semantics). */
49
+ take(state) {
50
+ this.evictExpired();
51
+ const entry = this.entries.get(state);
52
+ if (!entry) return void 0;
53
+ this.entries.delete(state);
54
+ if (Date.now() > entry.expiresAt) return void 0;
55
+ return entry.verifier;
56
+ }
57
+ delete(state) {
58
+ this.entries.delete(state);
59
+ }
60
+ size() {
61
+ this.evictExpired();
62
+ return this.entries.size;
63
+ }
64
+ evictExpired() {
65
+ const now = Date.now();
66
+ for (const [k, v] of this.entries) if (now > v.expiresAt) this.entries.delete(k);
67
+ }
68
+ };
69
+
70
+ //#endregion
71
+ export { generateCodeChallenge as n, generateCodeVerifier as r, PkceStore as t };
72
+ //# sourceMappingURL=pkce-jq5II68b.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce-jq5II68b.mjs","names":[],"sources":["../src/common/oauth/pkce.ts"],"sourcesContent":["/**\n * PKCE (Proof Key for Code Exchange) helpers for OAuth 2.0.\n *\n * @see https://datatracker.ietf.org/doc/html/rfc7636\n */\n\n/**\n * Generate a cryptographically random code verifier.\n * Length: 43 characters (RFC 7636 §4.1 allows 43-128).\n */\nexport function generateCodeVerifier(length = 64): string {\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n return base64UrlEncode(bytes).slice(0, length);\n}\n\n/**\n * Generate the SHA-256 challenge for a verifier (PKCE method `S256`).\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const digest = await crypto.subtle.digest('SHA-256', encoder.encode(verifier));\n return base64UrlEncode(new Uint8Array(digest));\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let bin = '';\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]!);\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Default in-memory verifier store with TTL-based eviction.\n *\n * **Note:** This is a single-process default. In multi-instance deployments,\n * persist verifiers alongside `state` (e.g., in a session, Redis, or DB) and\n * pass them back to `exchangeCode`. Do NOT rely on this store across servers.\n */\nexport class PkceStore {\n private entries = new Map<string, { verifier: string; expiresAt: number }>();\n\n constructor(private ttlMs: number = 10 * 60 * 1000) {}\n\n set(state: string, verifier: string): void {\n this.evictExpired();\n this.entries.set(state, { verifier, expiresAt: Date.now() + this.ttlMs });\n }\n\n /** Returns and removes the verifier (single-use semantics). */\n take(state: string): string | undefined {\n this.evictExpired();\n const entry = this.entries.get(state);\n if (!entry) return undefined;\n this.entries.delete(state);\n if (Date.now() > entry.expiresAt) return undefined;\n return entry.verifier;\n }\n\n delete(state: string): void {\n this.entries.delete(state);\n }\n\n size(): number {\n this.evictExpired();\n return this.entries.size;\n }\n\n private evictExpired(): void {\n const now = Date.now();\n for (const [k, v] of this.entries) {\n if (now > v.expiresAt) this.entries.delete(k);\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,qBAAqB,SAAS,IAAY;CACxD,MAAM,QAAQ,IAAI,WAAW,OAAO;AACpC,QAAO,gBAAgB,MAAM;AAC7B,QAAO,gBAAgB,MAAM,CAAC,MAAM,GAAG,OAAO;;;;;AAMhD,eAAsB,sBAAsB,UAAmC;CAC7E,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,QAAQ,OAAO,SAAS,CAAC;AAC9E,QAAO,gBAAgB,IAAI,WAAW,OAAO,CAAC;;AAGhD,SAAS,gBAAgB,OAA2B;CAClD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,QAAO,OAAO,aAAa,MAAM,GAAI;AAC5E,QAAO,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG;;;;;;;;;AAU7E,IAAa,YAAb,MAAuB;CACrB,AAAQ,0BAAU,IAAI,KAAsD;CAE5E,YAAY,AAAQ,QAAgB,MAAU,KAAM;EAAhC;;CAEpB,IAAI,OAAe,UAAwB;AACzC,OAAK,cAAc;AACnB,OAAK,QAAQ,IAAI,OAAO;GAAE;GAAU,WAAW,KAAK,KAAK,GAAG,KAAK;GAAO,CAAC;;;CAI3E,KAAK,OAAmC;AACtC,OAAK,cAAc;EACnB,MAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,MAAI,CAAC,MAAO,QAAO;AACnB,OAAK,QAAQ,OAAO,MAAM;AAC1B,MAAI,KAAK,KAAK,GAAG,MAAM,UAAW,QAAO;AACzC,SAAO,MAAM;;CAGf,OAAO,OAAqB;AAC1B,OAAK,QAAQ,OAAO,MAAM;;CAG5B,OAAe;AACb,OAAK,cAAc;AACnB,SAAO,KAAK,QAAQ;;CAGtB,AAAQ,eAAqB;EAC3B,MAAM,MAAM,KAAK,KAAK;AACtB,OAAK,MAAM,CAAC,GAAG,MAAM,KAAK,QACxB,KAAI,MAAM,EAAE,UAAW,MAAK,QAAQ,OAAO,EAAE"}
@@ -0,0 +1,25 @@
1
+ //#region src/utils/polling.ts
2
+ /**
3
+ * Poll an async function until a completion or failure condition is met.
4
+ *
5
+ * @returns The data from `fn()` when `isComplete` returns true, or null on timeout.
6
+ * @throws Whatever `getError` returns (wrapped in Error if string).
7
+ */
8
+ async function pollUntilComplete({ fn, isComplete, getError, maxAttempts = 30, intervalMs = 5e3, label = "polling" }) {
9
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
10
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
11
+ const data = await fn(attempt);
12
+ if (isComplete(data)) return data;
13
+ const failure = getError(data);
14
+ if (failure) {
15
+ if (failure instanceof Error) throw failure;
16
+ throw new Error(failure);
17
+ }
18
+ }
19
+ console.warn(`[${label}] Status polling timed out after ${maxAttempts} attempts`);
20
+ return null;
21
+ }
22
+
23
+ //#endregion
24
+ export { pollUntilComplete as t };
25
+ //# sourceMappingURL=polling-DZ1apXtA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polling-DZ1apXtA.mjs","names":[],"sources":["../src/utils/polling.ts"],"sourcesContent":["/**\n * Generic Polling Utility\n * =======================\n * Reusable poll-until-complete pattern for platform API status checks.\n *\n * Used by Instagram (container status) and TikTok (publish status).\n *\n * Usage:\n * import { pollUntilComplete } from '../utils/polling.js';\n *\n * const result = await pollUntilComplete({\n * fn: () => fetchStatus(id),\n * isComplete: (data) => data.status === 'FINISHED',\n * getError: (data) => data.status === 'FAILED' ? data.reason : null,\n * label: 'Instagram container',\n * });\n */\n\nexport interface PollOptions<T> {\n /** Async function to call each iteration. Receives attempt index. */\n fn: (attempt: number) => Promise<T>;\n /** Predicate: return true when the operation is complete. */\n isComplete: (data: T) => boolean;\n /** Return an Error, string message, or null to keep polling. */\n getError: (data: T) => Error | string | null;\n /** Max polling iterations before timeout (default 30). */\n maxAttempts?: number;\n /** Delay between polls in milliseconds (default 5000). */\n intervalMs?: number;\n /** Label for timeout warning logs (default 'polling'). */\n label?: string;\n}\n\n/**\n * Poll an async function until a completion or failure condition is met.\n *\n * @returns The data from `fn()` when `isComplete` returns true, or null on timeout.\n * @throws Whatever `getError` returns (wrapped in Error if string).\n */\nexport async function pollUntilComplete<T>({\n fn,\n isComplete,\n getError,\n maxAttempts = 30,\n intervalMs = 5000,\n label = 'polling',\n}: PollOptions<T>): Promise<T | null> {\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n await new Promise(resolve => setTimeout(resolve, intervalMs));\n\n const data = await fn(attempt);\n\n if (isComplete(data)) {\n return data;\n }\n\n const failure = getError(data);\n if (failure) {\n if (failure instanceof Error) throw failure;\n throw new Error(failure);\n }\n\n // Still in progress -- keep polling\n }\n\n // Timeout -- not necessarily a failure, the operation may still be processing\n console.warn(`[${label}] Status polling timed out after ${maxAttempts} attempts`);\n return null;\n}\n"],"mappings":";;;;;;;AAuCA,eAAsB,kBAAqB,EACzC,IACA,YACA,UACA,cAAc,IACd,aAAa,KACb,QAAQ,aAC4B;AACpC,MAAK,IAAI,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,QAAM,IAAI,SAAQ,YAAW,WAAW,SAAS,WAAW,CAAC;EAE7D,MAAM,OAAO,MAAM,GAAG,QAAQ;AAE9B,MAAI,WAAW,KAAK,CAClB,QAAO;EAGT,MAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,SAAS;AACX,OAAI,mBAAmB,MAAO,OAAM;AACpC,SAAM,IAAI,MAAM,QAAQ;;;AAO5B,SAAQ,KAAK,IAAI,MAAM,mCAAmC,YAAY,WAAW;AACjF,QAAO"}
@@ -0,0 +1,135 @@
1
+ import { d as ProviderMetadata, g as UploadResult, i as CredentialField, l as ProviderConfig, o as OAuthTokens, r as AuthUrlOptions, s as PlatformProvider } from "../base-DBtKFiSX.mjs";
2
+ import { a as CreatePostOptions, c as FacebookCredentialData, d as FacebookPage, f as FacebookPost, h as GraphApiErrorResponse, i as CreatePhotoPostResult, l as FacebookCredentials, m as FacebookUploadParams, n as CreateLinkPostResult, o as CreatePostResult, p as FacebookTestResult, r as CreatePhotoPostOptions, s as FacebookAccountInfo, t as CreateLinkPostOptions, u as FacebookInsightsPeriod } from "../types-ClbVc2rc.mjs";
3
+ import { z } from "zod";
4
+
5
+ //#region src/providers/facebook/index.d.ts
6
+ declare class FacebookProvider extends PlatformProvider {
7
+ defaultRedirectUri: string;
8
+ scopes: string[];
9
+ constructor(cfg?: ProviderConfig);
10
+ /**
11
+ * Unified Graph API request — used by all GET / POST / DELETE call sites.
12
+ * Delegates to the shared `httpRequest` helper for retry, timeout, and 429 handling.
13
+ *
14
+ * @param method HTTP method
15
+ * @param path Graph API path (e.g. `/me/accounts`)
16
+ * @param accessToken Access token (sent as `access_token` query for GET/DELETE; body field for POST)
17
+ * @param body POST body (merged with `access_token`); ignored for GET/DELETE
18
+ * @param query Extra query params for GET
19
+ * @param baseUrl Optional base URL override (video uploads use graph-video.facebook.com)
20
+ */
21
+ private _graph;
22
+ private _graphGet;
23
+ private _graphPost;
24
+ private _graphDelete;
25
+ /**
26
+ * Get Facebook OAuth authorization URL
27
+ */
28
+ getAuthUrl(state: string, credentials?: Partial<FacebookCredentials>, _options?: AuthUrlOptions): string;
29
+ /**
30
+ * Exchange authorization code for tokens (two-step).
31
+ *
32
+ * Step 1: code → short-lived token (1 hour)
33
+ * Step 2: short-lived → long-lived token (60 days)
34
+ */
35
+ exchangeCode(code: string, credentials?: Partial<FacebookCredentials>): Promise<OAuthTokens>;
36
+ /**
37
+ * Refresh long-lived user token. Facebook long-lived tokens can be refreshed
38
+ * before expiry by re-exchanging them via `fb_exchange_token`.
39
+ */
40
+ refreshToken(refreshToken: string, credentials?: Partial<FacebookCredentials>): Promise<OAuthTokens>;
41
+ /**
42
+ * Get user's Facebook Pages with page-level access tokens
43
+ * Each page has its own never-expiring token (when derived from long-lived user token)
44
+ *
45
+ * @param userAccessToken - Long-lived user access token
46
+ * @returns List of pages with { id, name, access_token, category, ... }
47
+ */
48
+ getPages(userAccessToken: string): Promise<FacebookPage[]>;
49
+ /**
50
+ * Get account information -- returns the first managed page
51
+ */
52
+ getAccountInfo(accessToken: string): Promise<FacebookAccountInfo>;
53
+ /**
54
+ * Test credential validity
55
+ */
56
+ testCredential(credentialData: Record<string, any>): Promise<FacebookTestResult>;
57
+ /**
58
+ * Get the page-level access token for a specific page
59
+ * Page tokens derived from long-lived user tokens never expire.
60
+ *
61
+ * @param userAccessToken - Long-lived user access token
62
+ * @param pageId - Facebook Page ID
63
+ * @returns Page access token
64
+ */
65
+ getPageAccessToken(userAccessToken: string, pageId: string): Promise<string>;
66
+ /**
67
+ * Publish a text post to a Facebook Page
68
+ * @param pageAccessToken - Page-level access token
69
+ * @param pageId - Facebook Page ID
70
+ * @param message - Post text
71
+ * @param options
72
+ */
73
+ createPost(pageAccessToken: string, pageId: string, message: string, options?: CreatePostOptions): Promise<CreatePostResult>;
74
+ /**
75
+ * Publish a link/article share to a Facebook Page
76
+ * @param pageAccessToken
77
+ * @param pageId
78
+ * @param link - URL to share
79
+ * @param options
80
+ */
81
+ createLinkPost(pageAccessToken: string, pageId: string, link: string, options?: CreateLinkPostOptions): Promise<CreateLinkPostResult>;
82
+ /**
83
+ * Publish a photo to a Facebook Page (via public URL)
84
+ * @param pageAccessToken
85
+ * @param pageId
86
+ * @param photoUrl - Publicly accessible photo URL
87
+ * @param options
88
+ */
89
+ createPhotoPost(pageAccessToken: string, pageId: string, photoUrl: string, options?: CreatePhotoPostOptions): Promise<CreatePhotoPostResult>;
90
+ /**
91
+ * Upload a video to a Facebook Page (via public URL)
92
+ * Uses graph-video.facebook.com for video uploads.
93
+ */
94
+ uploadVideo(params: FacebookUploadParams): Promise<UploadResult>;
95
+ /**
96
+ * Get a post by ID
97
+ * @param pageAccessToken
98
+ * @param postId
99
+ * @param fields - Comma-separated fields
100
+ */
101
+ getPost(pageAccessToken: string, postId: string, fields?: string): Promise<any>;
102
+ /**
103
+ * Update a post's message
104
+ * @param pageAccessToken
105
+ * @param postId
106
+ * @param message - New message text
107
+ */
108
+ updatePost(pageAccessToken: string, postId: string, message: string): Promise<any>;
109
+ /**
110
+ * Delete a post
111
+ * @param pageAccessToken
112
+ * @param postId
113
+ */
114
+ deletePost(pageAccessToken: string, postId: string): Promise<any>;
115
+ /**
116
+ * Get page feed (recent posts)
117
+ * @param pageAccessToken
118
+ * @param pageId
119
+ * @param limit
120
+ */
121
+ getPageFeed(pageAccessToken: string, pageId: string, limit?: number): Promise<any>;
122
+ /**
123
+ * Get page insights (basic analytics)
124
+ * @param pageAccessToken
125
+ * @param pageId
126
+ * @param period - 'day' | 'week' | 'days_28'
127
+ */
128
+ getPageInsights(pageAccessToken: string, pageId: string, period?: 'day' | 'week' | 'days_28'): Promise<any>;
129
+ getCredentialZodSchema(): z.ZodType;
130
+ getCredentialSchema(): CredentialField[];
131
+ getMetadata(): ProviderMetadata;
132
+ }
133
+ //#endregion
134
+ export { type CreateLinkPostOptions, type CreateLinkPostResult, type CreatePhotoPostOptions, type CreatePhotoPostResult, type CreatePostOptions, type CreatePostResult, type FacebookAccountInfo, type FacebookCredentialData, type FacebookCredentials, type FacebookInsightsPeriod, type FacebookPage, type FacebookPost, FacebookProvider, type FacebookTestResult, type FacebookUploadParams, type GraphApiErrorResponse };
135
+ //# sourceMappingURL=facebook.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facebook.d.mts","names":[],"sources":["../../src/providers/facebook/index.ts"],"mappings":";;;;;cAiGa,gBAAA,SAAyB,gBAAA;EAC7B,kBAAA;EACA,MAAA;cAEK,GAAA,GAAK,cAAA;EAkUgC;;;;;;;;;;;EAAA,QAlSnC,MAAA;EAAA,QAsBA,SAAA;EAAA,QAGA,UAAA;EAAA,QAGA,YAAA;;;;EASd,UAAA,CAAW,KAAA,UAAe,WAAA,GAAa,OAAA,CAAQ,mBAAA,GAA2B,QAAA,GAAW,cAAA;EAfvE;;;;;;EAiCR,YAAA,CAAa,IAAA,UAAc,WAAA,GAAa,OAAA,CAAQ,mBAAA,IAA4B,OAAA,CAAQ,WAAA;EAlBhE;;;;EAgCpB,YAAA,CAAa,YAAA,UAAsB,WAAA,GAAa,OAAA,CAAQ,mBAAA,IAA4B,OAAA,CAAQ,WAAA;EAdpD;;;;;;;EAgCxC,QAAA,CAAS,eAAA,WAA0B,OAAA,CAAQ,YAAA;EAlBa;;;EA8BxD,cAAA,CAAe,WAAA,WAAsB,OAAA,CAAQ,mBAAA;EAZ7C;;;EA2CA,cAAA,CAAe,cAAA,EAAgB,MAAA,gBAAsB,OAAA,CAAQ,kBAAA;EA/B7D;;;;;;;;EAgFA,kBAAA,CAAmB,eAAA,UAAyB,MAAA,WAAiB,OAAA;EAA7D;;;;;;;EAuBA,UAAA,CACJ,eAAA,UACA,MAAA,UACA,OAAA,UACA,OAAA,GAAS,iBAAA,GACR,OAAA,CAAQ,gBAAA;EADA;;;;;;;EA0BL,cAAA,CACJ,eAAA,UACA,MAAA,UACA,IAAA,UACA,OAAA,GAAS,qBAAA,GACR,OAAA,CAAQ,oBAAA;EADA;;;;;;;EA0BL,eAAA,CACJ,eAAA,UACA,MAAA,UACA,QAAA,UACA,OAAA,GAAS,sBAAA,GACR,OAAA,CAAQ,qBAAA;EADA;;;;EAwBL,WAAA,CAAY,MAAA,EAAQ,oBAAA,GAAuB,OAAA,CAAQ,YAAA;EAA/B;;;;;;EAmEpB,OAAA,CACJ,eAAA,UACA,MAAA,UACA,MAAA,YACC,OAAA;EADD;;;;;;EAWI,UAAA,CAAW,eAAA,UAAyB,MAAA,UAAgB,OAAA,WAAkB,OAAA;EAStE;;;;;EAAA,UAAA,CAAW,eAAA,UAAyB,MAAA,WAAiB,OAAA;EAUhB;;;;;;EAArC,WAAA,CAAY,eAAA,UAAyB,MAAA,UAAgB,KAAA,YAAqB,OAAA;EAkB7E;;;;;;EAJG,eAAA,CACJ,eAAA,UACA,MAAA,UACA,MAAA,gCACC,OAAA;EAaH,sBAAA,CAAA,GAA0B,CAAA,CAAE,OAAA;EAI5B,mBAAA,CAAA,GAAuB,eAAA;EAmBvB,WAAA,CAAA,GAAe,gBAAA;AAAA"}