universal-social-sdk 1.0.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.
@@ -0,0 +1,546 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli/index.ts
4
+ import { Command } from "commander";
5
+ import chalk3 from "chalk";
6
+
7
+ // src/cli/commands/init.ts
8
+ import { access, copyFile, writeFile } from "fs/promises";
9
+ import path from "path";
10
+ import chalk from "chalk";
11
+ import inquirer from "inquirer";
12
+ import ora from "ora";
13
+ var ENV_TEMPLATE = `# X / Twitter
14
+ X_API_KEY=
15
+ X_API_SECRET=
16
+ X_ACCESS_TOKEN=
17
+ X_ACCESS_SECRET=
18
+ X_BEARER_TOKEN=
19
+ X_CLIENT_ID=
20
+ X_CLIENT_SECRET=
21
+
22
+ # Facebook Pages + Instagram Graph (Meta)
23
+ META_APP_ID=
24
+ META_APP_SECRET=
25
+ FB_PAGE_ACCESS_TOKEN=
26
+ FB_PAGE_ID=
27
+ IG_ACCESS_TOKEN=
28
+ IG_USER_ID=
29
+ META_GRAPH_VERSION=v21.0
30
+
31
+ # LinkedIn
32
+ LINKEDIN_ACCESS_TOKEN=
33
+ LINKEDIN_REFRESH_TOKEN=
34
+ LINKEDIN_CLIENT_ID=
35
+ LINKEDIN_CLIENT_SECRET=
36
+ LINKEDIN_ORG_URN=
37
+ LINKEDIN_PERSON_URN=
38
+ LINKEDIN_API_VERSION=202510
39
+
40
+ # YouTube
41
+ YOUTUBE_ACCESS_TOKEN=
42
+ YOUTUBE_CHANNEL_ID=
43
+
44
+ # TikTok
45
+ TIKTOK_ACCESS_TOKEN=
46
+ TIKTOK_OPEN_ID=
47
+ TIKTOK_ADVERTISER_ID=
48
+
49
+ # Pinterest
50
+ PINTEREST_ACCESS_TOKEN=
51
+ PINTEREST_BOARD_ID=
52
+
53
+ # Bluesky
54
+ BLUESKY_SERVICE_URL=https://bsky.social
55
+ BLUESKY_IDENTIFIER=
56
+ BLUESKY_APP_PASSWORD=
57
+ BLUESKY_ACCESS_JWT=
58
+ BLUESKY_REFRESH_JWT=
59
+
60
+ # Mastodon
61
+ MASTODON_BASE_URL=
62
+ MASTODON_ACCESS_TOKEN=
63
+ MASTODON_ACCOUNT_ID=
64
+
65
+ # Threads
66
+ THREADS_ACCESS_TOKEN=
67
+ THREADS_USER_ID=
68
+
69
+ # SDK behavior
70
+ SOCIAL_SDK_MAX_RETRIES=3
71
+ SOCIAL_SDK_RETRY_BASE_MS=500
72
+ OLLAMA_HOST=http://127.0.0.1:11434
73
+ OLLAMA_MODEL=llama3.2:3b
74
+ `;
75
+ var OAUTH_LINKS = [
76
+ {
77
+ platform: "X (Twitter)",
78
+ url: "https://developer.x.com/en/portal/dashboard"
79
+ },
80
+ {
81
+ platform: "Meta (Facebook + Instagram Graph)",
82
+ url: "https://developers.facebook.com/apps/"
83
+ },
84
+ {
85
+ platform: "LinkedIn",
86
+ url: "https://www.linkedin.com/developers/apps"
87
+ },
88
+ {
89
+ platform: "YouTube",
90
+ url: "https://console.cloud.google.com/apis/library/youtube.googleapis.com"
91
+ },
92
+ {
93
+ platform: "TikTok",
94
+ url: "https://developers.tiktok.com/"
95
+ },
96
+ {
97
+ platform: "Pinterest",
98
+ url: "https://developers.pinterest.com/"
99
+ },
100
+ {
101
+ platform: "Bluesky",
102
+ url: "https://bsky.app/settings/app-passwords"
103
+ },
104
+ {
105
+ platform: "Mastodon",
106
+ url: "https://docs.joinmastodon.org/client/token/"
107
+ },
108
+ {
109
+ platform: "Threads",
110
+ url: "https://developers.facebook.com/docs/threads"
111
+ }
112
+ ];
113
+ async function exists(targetPath) {
114
+ try {
115
+ await access(targetPath);
116
+ return true;
117
+ } catch {
118
+ return false;
119
+ }
120
+ }
121
+ async function runInitCommand(cwd) {
122
+ const spinner = ora("Preparing universal-social-sdk project bootstrap...").start();
123
+ const envExamplePath = path.join(cwd, ".env.example");
124
+ const envPath = path.join(cwd, ".env");
125
+ if (!await exists(envExamplePath)) {
126
+ await writeFile(envExamplePath, ENV_TEMPLATE, "utf8");
127
+ }
128
+ if (!await exists(envPath)) {
129
+ await copyFile(envExamplePath, envPath);
130
+ }
131
+ spinner.succeed("Environment files generated.");
132
+ console.log(chalk.bold("\nOAuth setup links"));
133
+ for (const link of OAUTH_LINKS) {
134
+ console.log(`- ${chalk.cyan(link.platform)}: ${chalk.underline(link.url)}`);
135
+ }
136
+ console.log(chalk.bold("\nSetup hints (screenshots to capture while configuring):"));
137
+ console.log("- X: app dashboard with OAuth 1.0a user tokens and callback URL.");
138
+ console.log("- Meta: App Review permissions screen + Page token debug screen.");
139
+ console.log("- LinkedIn: Products tab + OAuth 2.0 redirect URL + scopes list.");
140
+ console.log("- YouTube: OAuth consent screen + Data API enabled credentials.");
141
+ console.log("- TikTok/Pinterest: app scopes + redirect URI + long-lived token.");
142
+ console.log("- Bluesky/Mastodon/Threads: app password or token issuance screens.");
143
+ const answers = await inquirer.prompt([
144
+ {
145
+ type: "confirm",
146
+ name: "openLinks",
147
+ message: "Open OAuth setup links manually in your browser now?",
148
+ default: true
149
+ }
150
+ ]);
151
+ if (answers.openLinks) {
152
+ console.log(chalk.yellow("Open each URL above in your browser and fill `.env` values."));
153
+ }
154
+ console.log(chalk.green("\nInitialization complete."));
155
+ }
156
+
157
+ // src/cli/commands/update.ts
158
+ import { readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
159
+ import path3 from "path";
160
+ import chalk2 from "chalk";
161
+ import inquirer2 from "inquirer";
162
+ import ora2 from "ora";
163
+
164
+ // src/updater/docCrawler.ts
165
+ import axios from "axios";
166
+ import * as cheerio from "cheerio";
167
+ var DOC_URLS = {
168
+ x: [
169
+ "https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets",
170
+ "https://developer.x.com/en/docs/twitter-api/users/likes/api-reference/post-users-id-likes"
171
+ ],
172
+ facebook: [
173
+ "https://developers.facebook.com/docs/graph-api/reference/page/feed/",
174
+ "https://developers.facebook.com/docs/pages-api/getting-started/"
175
+ ],
176
+ instagram: [
177
+ "https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media",
178
+ "https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media_publish/"
179
+ ],
180
+ linkedin: [
181
+ "https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/posts-api?view=li-lms-2025-10",
182
+ "https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/comments-api?view=li-lms-2025-06"
183
+ ]
184
+ };
185
+ function cleanText(raw) {
186
+ return raw.replace(/\s+/g, " ").replace(/\u00a0/g, " ").trim();
187
+ }
188
+ function extractTables($) {
189
+ const rows = [];
190
+ $("table").each((_, table) => {
191
+ const headers = [];
192
+ $(table).find("thead th").each((_2, th) => {
193
+ headers.push(cleanText($(th).text()));
194
+ });
195
+ $(table).find("tbody tr").each((_2, tr) => {
196
+ const row = {};
197
+ $(tr).find("td").each((idx, td) => {
198
+ const key = headers[idx] || `column_${idx + 1}`;
199
+ row[key] = cleanText($(td).text());
200
+ });
201
+ if (Object.keys(row).length > 0) {
202
+ rows.push(row);
203
+ }
204
+ });
205
+ });
206
+ return rows;
207
+ }
208
+ async function crawlSingleDoc(url) {
209
+ const response = await axios.get(url, {
210
+ timeout: 3e4,
211
+ headers: {
212
+ "User-Agent": "universal-social-sdk-doc-crawler/1.0"
213
+ }
214
+ });
215
+ const $ = cheerio.load(response.data);
216
+ const title = cleanText($("title").first().text()) || "Untitled";
217
+ const text = cleanText($("main, article, body").text());
218
+ const endpointRows = extractTables($);
219
+ return {
220
+ url,
221
+ title,
222
+ text: text.slice(0, 25e4),
223
+ endpointRows
224
+ };
225
+ }
226
+ async function crawlAllDocs() {
227
+ const urls = [
228
+ ...DOC_URLS.x,
229
+ ...DOC_URLS.facebook,
230
+ ...DOC_URLS.instagram,
231
+ ...DOC_URLS.linkedin
232
+ ];
233
+ const results = await Promise.all(urls.map((url) => crawlSingleDoc(url)));
234
+ return results;
235
+ }
236
+
237
+ // src/updater/ollama.ts
238
+ import axios2 from "axios";
239
+
240
+ // src/config/env.ts
241
+ import dotenv from "dotenv";
242
+ dotenv.config();
243
+ function readNumberEnv(name, fallback) {
244
+ const value = process.env[name];
245
+ if (!value) {
246
+ return fallback;
247
+ }
248
+ const parsed = Number(value);
249
+ return Number.isFinite(parsed) ? parsed : fallback;
250
+ }
251
+ var env = {
252
+ x: {
253
+ apiKey: process.env.X_API_KEY ?? "",
254
+ apiSecret: process.env.X_API_SECRET ?? "",
255
+ accessToken: process.env.X_ACCESS_TOKEN ?? "",
256
+ accessSecret: process.env.X_ACCESS_SECRET ?? "",
257
+ bearerToken: process.env.X_BEARER_TOKEN ?? "",
258
+ clientId: process.env.X_CLIENT_ID ?? "",
259
+ clientSecret: process.env.X_CLIENT_SECRET ?? ""
260
+ },
261
+ meta: {
262
+ appId: process.env.META_APP_ID ?? "",
263
+ appSecret: process.env.META_APP_SECRET ?? "",
264
+ graphVersion: process.env.META_GRAPH_VERSION ?? "v21.0",
265
+ fbPageToken: process.env.FB_PAGE_ACCESS_TOKEN ?? "",
266
+ fbPageId: process.env.FB_PAGE_ID ?? "",
267
+ igToken: process.env.IG_ACCESS_TOKEN ?? "",
268
+ igUserId: process.env.IG_USER_ID ?? ""
269
+ },
270
+ linkedin: {
271
+ accessToken: process.env.LINKEDIN_ACCESS_TOKEN ?? "",
272
+ refreshToken: process.env.LINKEDIN_REFRESH_TOKEN ?? "",
273
+ clientId: process.env.LINKEDIN_CLIENT_ID ?? "",
274
+ clientSecret: process.env.LINKEDIN_CLIENT_SECRET ?? "",
275
+ orgUrn: process.env.LINKEDIN_ORG_URN ?? "",
276
+ personUrn: process.env.LINKEDIN_PERSON_URN ?? "",
277
+ apiVersion: process.env.LINKEDIN_API_VERSION ?? "202510"
278
+ },
279
+ youtube: {
280
+ accessToken: process.env.YOUTUBE_ACCESS_TOKEN ?? "",
281
+ channelId: process.env.YOUTUBE_CHANNEL_ID ?? ""
282
+ },
283
+ tiktok: {
284
+ accessToken: process.env.TIKTOK_ACCESS_TOKEN ?? "",
285
+ openId: process.env.TIKTOK_OPEN_ID ?? "",
286
+ advertiserId: process.env.TIKTOK_ADVERTISER_ID ?? ""
287
+ },
288
+ pinterest: {
289
+ accessToken: process.env.PINTEREST_ACCESS_TOKEN ?? "",
290
+ boardId: process.env.PINTEREST_BOARD_ID ?? ""
291
+ },
292
+ bluesky: {
293
+ serviceUrl: process.env.BLUESKY_SERVICE_URL ?? "https://bsky.social",
294
+ identifier: process.env.BLUESKY_IDENTIFIER ?? "",
295
+ appPassword: process.env.BLUESKY_APP_PASSWORD ?? "",
296
+ accessJwt: process.env.BLUESKY_ACCESS_JWT ?? "",
297
+ refreshJwt: process.env.BLUESKY_REFRESH_JWT ?? ""
298
+ },
299
+ mastodon: {
300
+ baseUrl: process.env.MASTODON_BASE_URL ?? "",
301
+ accessToken: process.env.MASTODON_ACCESS_TOKEN ?? "",
302
+ accountId: process.env.MASTODON_ACCOUNT_ID ?? ""
303
+ },
304
+ threads: {
305
+ accessToken: process.env.THREADS_ACCESS_TOKEN ?? "",
306
+ userId: process.env.THREADS_USER_ID ?? ""
307
+ },
308
+ retry: {
309
+ maxRetries: readNumberEnv("SOCIAL_SDK_MAX_RETRIES", 3),
310
+ baseDelayMs: readNumberEnv("SOCIAL_SDK_RETRY_BASE_MS", 500)
311
+ },
312
+ ollama: {
313
+ host: process.env.OLLAMA_HOST ?? "http://127.0.0.1:11434",
314
+ model: process.env.OLLAMA_MODEL ?? "llama3.2:3b"
315
+ }
316
+ };
317
+
318
+ // src/updater/ollama.ts
319
+ function buildPrompt(docs, existingMethodsJson) {
320
+ return [
321
+ "You are maintaining universal-social-sdk.",
322
+ "Compare the crawled docs with current methods and identify NEW or CHANGED endpoints.",
323
+ "Focus areas: content publishing, stories, reels, comments, DMs, analytics.",
324
+ "Output STRICT JSON with this shape only:",
325
+ '{"summary": string, "updatedMethods": Record<string,string[]>, "files": [{"path": string, "content": string}], "readmeTable": string}',
326
+ "Files must target src/platforms/*.ts and supported-methods.json updates when needed.",
327
+ "Each file.content must be complete TypeScript file content, not patch snippets.",
328
+ "Current supported-methods.json:",
329
+ existingMethodsJson,
330
+ "Crawled docs:",
331
+ JSON.stringify(docs)
332
+ ].join("\n");
333
+ }
334
+ function parseJsonOutput(raw) {
335
+ const cleaned = raw.replace(/```json|```/g, "").trim();
336
+ const start = cleaned.indexOf("{");
337
+ const end = cleaned.lastIndexOf("}");
338
+ if (start === -1 || end === -1 || end <= start) {
339
+ throw new Error("Ollama response did not contain a JSON object.");
340
+ }
341
+ const maybeJson = cleaned.slice(start, end + 1);
342
+ return JSON.parse(maybeJson);
343
+ }
344
+ async function askOllamaForPatchPlan(params) {
345
+ const model = params.model || env.ollama.model || "llama3.2:3b";
346
+ const prompt = buildPrompt(params.docs, params.existingMethodsJson);
347
+ const response = await axios2.post(
348
+ `${env.ollama.host}/api/generate`,
349
+ {
350
+ model,
351
+ prompt,
352
+ stream: false
353
+ },
354
+ {
355
+ timeout: 12e4
356
+ }
357
+ );
358
+ return parseJsonOutput(response.data.response);
359
+ }
360
+
361
+ // src/updater/patcher.ts
362
+ import { readFile, writeFile as writeFile2 } from "fs/promises";
363
+ import path2 from "path";
364
+ import { createPatch } from "diff";
365
+ var ALLOWED_TARGETS = /* @__PURE__ */ new Set([
366
+ "supported-methods.json",
367
+ "README.md"
368
+ ]);
369
+ function isAllowedPath(rootDir, filePath) {
370
+ if (path2.isAbsolute(filePath)) {
371
+ throw new Error(`Unsafe patch path (absolute not allowed): ${filePath}`);
372
+ }
373
+ const normalized = path2.normalize(filePath);
374
+ if (normalized.startsWith("..")) {
375
+ throw new Error(`Unsafe patch path (traversal): ${filePath}`);
376
+ }
377
+ const isPlatformSource = normalized.startsWith(`src${path2.sep}platforms${path2.sep}`) && normalized.endsWith(".ts");
378
+ const isAllowedTopLevel = ALLOWED_TARGETS.has(normalized);
379
+ if (!isPlatformSource && !isAllowedTopLevel) {
380
+ throw new Error(
381
+ `Patch path not allowed: ${filePath}. Allowed: src/platforms/*.ts, README.md, supported-methods.json.`
382
+ );
383
+ }
384
+ return path2.resolve(rootDir, normalized);
385
+ }
386
+ async function planDiffs(params) {
387
+ const plans = [];
388
+ for (const file of params.files) {
389
+ const absolutePath = isAllowedPath(params.rootDir, file.path);
390
+ let before = "";
391
+ try {
392
+ before = await readFile(absolutePath, "utf8");
393
+ } catch {
394
+ before = "";
395
+ }
396
+ const after = file.content;
397
+ const diff = createPatch(file.path, before, after, "before", "after");
398
+ plans.push({
399
+ path: file.path,
400
+ absolutePath,
401
+ before,
402
+ after,
403
+ diff
404
+ });
405
+ }
406
+ return plans;
407
+ }
408
+ async function applyPlannedDiffs(params) {
409
+ for (const plan of params.plans) {
410
+ await writeFile2(plan.absolutePath, plan.after, "utf8");
411
+ }
412
+ }
413
+
414
+ // src/cli/commands/update.ts
415
+ import { spawn } from "child_process";
416
+ function runBuild(cwd) {
417
+ return new Promise((resolve, reject) => {
418
+ const child = spawn("npm", ["run", "build"], {
419
+ cwd,
420
+ stdio: "inherit",
421
+ shell: true
422
+ });
423
+ child.on("close", (code) => {
424
+ if (code === 0) {
425
+ resolve();
426
+ } else {
427
+ reject(new Error(`Build failed with exit code ${code ?? -1}`));
428
+ }
429
+ });
430
+ });
431
+ }
432
+ function applyReadmeTable(readmeContent, tableMarkdown) {
433
+ const startMarker = "<!-- AUTO_METHODS_TABLE_START -->";
434
+ const endMarker = "<!-- AUTO_METHODS_TABLE_END -->";
435
+ const hasMarkers = readmeContent.includes(startMarker) && readmeContent.includes(endMarker);
436
+ if (!hasMarkers) {
437
+ return readmeContent;
438
+ }
439
+ const replacement = `${startMarker}
440
+ ${tableMarkdown.trim()}
441
+ ${endMarker}`;
442
+ return readmeContent.replace(
443
+ new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`, "m"),
444
+ replacement
445
+ );
446
+ }
447
+ async function runUpdateCommand(cwd, options = {}) {
448
+ const crawlSpinner = ora2("Crawling official social API docs...").start();
449
+ const docs = await crawlAllDocs();
450
+ crawlSpinner.succeed(`Crawled ${docs.length} documentation pages.`);
451
+ const methodsPath = path3.join(cwd, "supported-methods.json");
452
+ const methodsJson = await readFile2(methodsPath, "utf8");
453
+ const aiSpinner = ora2("Asking local Ollama model for SDK update plan...").start();
454
+ const plan = await askOllamaForPatchPlan({
455
+ docs,
456
+ existingMethodsJson: methodsJson,
457
+ model: options.model
458
+ });
459
+ aiSpinner.succeed("Ollama returned an update plan.");
460
+ const generatedFiles = [...plan.files];
461
+ const readmePath = path3.join(cwd, "README.md");
462
+ const readmeContent = await readFile2(readmePath, "utf8");
463
+ const updatedReadme = applyReadmeTable(readmeContent, plan.readmeTable);
464
+ if (updatedReadme !== readmeContent) {
465
+ generatedFiles.push({
466
+ path: "README.md",
467
+ content: updatedReadme
468
+ });
469
+ }
470
+ const diffs = await planDiffs({
471
+ rootDir: cwd,
472
+ files: generatedFiles
473
+ });
474
+ console.log(chalk2.bold("\nProposed changes"));
475
+ console.log(chalk2.dim(plan.summary));
476
+ for (const planned of diffs) {
477
+ console.log(chalk2.cyan(`
478
+ --- ${planned.path} ---`));
479
+ console.log(planned.diff.slice(0, 4e3));
480
+ if (planned.diff.length > 4e3) {
481
+ console.log(chalk2.dim("... diff truncated in terminal preview ..."));
482
+ }
483
+ }
484
+ const applyChanges = options.yes ? true : (await inquirer2.prompt([
485
+ {
486
+ type: "confirm",
487
+ name: "applyChanges",
488
+ message: "Apply these changes and rebuild package?",
489
+ default: false
490
+ }
491
+ ])).applyChanges;
492
+ if (!applyChanges) {
493
+ console.log(chalk2.yellow("Update cancelled. No files changed."));
494
+ return;
495
+ }
496
+ if (options.dryRun) {
497
+ console.log(chalk2.yellow("Dry-run mode enabled. No files changed."));
498
+ return;
499
+ }
500
+ const applySpinner = ora2("Applying generated patches...").start();
501
+ await applyPlannedDiffs({ plans: diffs });
502
+ await writeFile3(
503
+ methodsPath,
504
+ JSON.stringify(
505
+ {
506
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
507
+ platforms: plan.updatedMethods
508
+ },
509
+ null,
510
+ 2
511
+ ),
512
+ "utf8"
513
+ );
514
+ applySpinner.succeed("Patch files applied.");
515
+ const buildSpinner = ora2("Rebuilding package...").start();
516
+ await runBuild(cwd);
517
+ buildSpinner.succeed("Package rebuilt successfully.");
518
+ }
519
+
520
+ // src/cli/index.ts
521
+ var program = new Command();
522
+ program.name("universal-social-sdk").description("Universal social media SDK CLI").version("1.0.0");
523
+ program.command("init").description("Create .env.example and show OAuth setup links").action(async () => {
524
+ try {
525
+ await runInitCommand(process.cwd());
526
+ } catch (error) {
527
+ console.error(chalk3.red("Initialization failed."));
528
+ console.error(error);
529
+ process.exitCode = 1;
530
+ }
531
+ });
532
+ program.command("update").description("Crawl docs + run local Ollama + patch SDK sources").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Apply changes without confirmation prompt").option("--model <name>", "Override Ollama model for this run").action(async (options) => {
533
+ try {
534
+ await runUpdateCommand(process.cwd(), {
535
+ dryRun: options.dryRun,
536
+ yes: options.yes,
537
+ model: options.model
538
+ });
539
+ } catch (error) {
540
+ console.error(chalk3.red("Update failed."));
541
+ console.error(error);
542
+ process.exitCode = 1;
543
+ }
544
+ });
545
+ program.parse(process.argv);
546
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/commands/update.ts","../../src/updater/docCrawler.ts","../../src/updater/ollama.ts","../../src/config/env.ts","../../src/updater/patcher.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { runUpdateCommand } from \"./commands/update.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"universal-social-sdk\")\n .description(\"Universal social media SDK CLI\")\n .version(\"1.0.0\");\n\nprogram\n .command(\"init\")\n .description(\"Create .env.example and show OAuth setup links\")\n .action(async () => {\n try {\n await runInitCommand(process.cwd());\n } catch (error) {\n console.error(chalk.red(\"Initialization failed.\"));\n console.error(error);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"update\")\n .description(\"Crawl docs + run local Ollama + patch SDK sources\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .option(\"-y, --yes\", \"Apply changes without confirmation prompt\")\n .option(\"--model <name>\", \"Override Ollama model for this run\")\n .action(async (options: { dryRun?: boolean; yes?: boolean; model?: string }) => {\n try {\n await runUpdateCommand(process.cwd(), {\n dryRun: options.dryRun,\n yes: options.yes,\n model: options.model\n });\n } catch (error) {\n console.error(chalk.red(\"Update failed.\"));\n console.error(error);\n process.exitCode = 1;\n }\n });\n\nprogram.parse(process.argv);\n","import { access, copyFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport inquirer from \"inquirer\";\nimport ora from \"ora\";\n\nconst ENV_TEMPLATE = `# X / Twitter\nX_API_KEY=\nX_API_SECRET=\nX_ACCESS_TOKEN=\nX_ACCESS_SECRET=\nX_BEARER_TOKEN=\nX_CLIENT_ID=\nX_CLIENT_SECRET=\n\n# Facebook Pages + Instagram Graph (Meta)\nMETA_APP_ID=\nMETA_APP_SECRET=\nFB_PAGE_ACCESS_TOKEN=\nFB_PAGE_ID=\nIG_ACCESS_TOKEN=\nIG_USER_ID=\nMETA_GRAPH_VERSION=v21.0\n\n# LinkedIn\nLINKEDIN_ACCESS_TOKEN=\nLINKEDIN_REFRESH_TOKEN=\nLINKEDIN_CLIENT_ID=\nLINKEDIN_CLIENT_SECRET=\nLINKEDIN_ORG_URN=\nLINKEDIN_PERSON_URN=\nLINKEDIN_API_VERSION=202510\n\n# YouTube\nYOUTUBE_ACCESS_TOKEN=\nYOUTUBE_CHANNEL_ID=\n\n# TikTok\nTIKTOK_ACCESS_TOKEN=\nTIKTOK_OPEN_ID=\nTIKTOK_ADVERTISER_ID=\n\n# Pinterest\nPINTEREST_ACCESS_TOKEN=\nPINTEREST_BOARD_ID=\n\n# Bluesky\nBLUESKY_SERVICE_URL=https://bsky.social\nBLUESKY_IDENTIFIER=\nBLUESKY_APP_PASSWORD=\nBLUESKY_ACCESS_JWT=\nBLUESKY_REFRESH_JWT=\n\n# Mastodon\nMASTODON_BASE_URL=\nMASTODON_ACCESS_TOKEN=\nMASTODON_ACCOUNT_ID=\n\n# Threads\nTHREADS_ACCESS_TOKEN=\nTHREADS_USER_ID=\n\n# SDK behavior\nSOCIAL_SDK_MAX_RETRIES=3\nSOCIAL_SDK_RETRY_BASE_MS=500\nOLLAMA_HOST=http://127.0.0.1:11434\nOLLAMA_MODEL=llama3.2:3b\n`;\n\nconst OAUTH_LINKS = [\n {\n platform: \"X (Twitter)\",\n url: \"https://developer.x.com/en/portal/dashboard\"\n },\n {\n platform: \"Meta (Facebook + Instagram Graph)\",\n url: \"https://developers.facebook.com/apps/\"\n },\n {\n platform: \"LinkedIn\",\n url: \"https://www.linkedin.com/developers/apps\"\n },\n {\n platform: \"YouTube\",\n url: \"https://console.cloud.google.com/apis/library/youtube.googleapis.com\"\n },\n {\n platform: \"TikTok\",\n url: \"https://developers.tiktok.com/\"\n },\n {\n platform: \"Pinterest\",\n url: \"https://developers.pinterest.com/\"\n },\n {\n platform: \"Bluesky\",\n url: \"https://bsky.app/settings/app-passwords\"\n },\n {\n platform: \"Mastodon\",\n url: \"https://docs.joinmastodon.org/client/token/\"\n },\n {\n platform: \"Threads\",\n url: \"https://developers.facebook.com/docs/threads\"\n }\n];\n\nasync function exists(targetPath: string): Promise<boolean> {\n try {\n await access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function runInitCommand(cwd: string): Promise<void> {\n const spinner = ora(\"Preparing universal-social-sdk project bootstrap...\").start();\n const envExamplePath = path.join(cwd, \".env.example\");\n const envPath = path.join(cwd, \".env\");\n\n if (!(await exists(envExamplePath))) {\n await writeFile(envExamplePath, ENV_TEMPLATE, \"utf8\");\n }\n\n if (!(await exists(envPath))) {\n await copyFile(envExamplePath, envPath);\n }\n\n spinner.succeed(\"Environment files generated.\");\n\n console.log(chalk.bold(\"\\nOAuth setup links\"));\n for (const link of OAUTH_LINKS) {\n console.log(`- ${chalk.cyan(link.platform)}: ${chalk.underline(link.url)}`);\n }\n\n console.log(chalk.bold(\"\\nSetup hints (screenshots to capture while configuring):\"));\n console.log(\"- X: app dashboard with OAuth 1.0a user tokens and callback URL.\");\n console.log(\"- Meta: App Review permissions screen + Page token debug screen.\");\n console.log(\"- LinkedIn: Products tab + OAuth 2.0 redirect URL + scopes list.\");\n console.log(\"- YouTube: OAuth consent screen + Data API enabled credentials.\");\n console.log(\"- TikTok/Pinterest: app scopes + redirect URI + long-lived token.\");\n console.log(\"- Bluesky/Mastodon/Threads: app password or token issuance screens.\");\n\n const answers = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"openLinks\",\n message: \"Open OAuth setup links manually in your browser now?\",\n default: true\n }\n ]);\n\n if (answers.openLinks) {\n console.log(chalk.yellow(\"Open each URL above in your browser and fill `.env` values.\"));\n }\n\n console.log(chalk.green(\"\\nInitialization complete.\"));\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport inquirer from \"inquirer\";\nimport ora from \"ora\";\nimport { crawlAllDocs } from \"../../updater/docCrawler.js\";\nimport { askOllamaForPatchPlan } from \"../../updater/ollama.js\";\nimport { applyPlannedDiffs, planDiffs } from \"../../updater/patcher.js\";\nimport { spawn } from \"node:child_process\";\n\nexport interface UpdateCommandOptions {\n dryRun?: boolean;\n yes?: boolean;\n model?: string;\n}\n\nfunction runBuild(cwd: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"npm\", [\"run\", \"build\"], {\n cwd,\n stdio: \"inherit\",\n shell: true\n });\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Build failed with exit code ${code ?? -1}`));\n }\n });\n });\n}\n\nfunction applyReadmeTable(readmeContent: string, tableMarkdown: string): string {\n const startMarker = \"<!-- AUTO_METHODS_TABLE_START -->\";\n const endMarker = \"<!-- AUTO_METHODS_TABLE_END -->\";\n const hasMarkers =\n readmeContent.includes(startMarker) && readmeContent.includes(endMarker);\n\n if (!hasMarkers) {\n return readmeContent;\n }\n\n const replacement = `${startMarker}\\n${tableMarkdown.trim()}\\n${endMarker}`;\n return readmeContent.replace(\n new RegExp(`${startMarker}[\\\\s\\\\S]*?${endMarker}`, \"m\"),\n replacement\n );\n}\n\nexport async function runUpdateCommand(\n cwd: string,\n options: UpdateCommandOptions = {}\n): Promise<void> {\n const crawlSpinner = ora(\"Crawling official social API docs...\").start();\n const docs = await crawlAllDocs();\n crawlSpinner.succeed(`Crawled ${docs.length} documentation pages.`);\n\n const methodsPath = path.join(cwd, \"supported-methods.json\");\n const methodsJson = await readFile(methodsPath, \"utf8\");\n\n const aiSpinner = ora(\"Asking local Ollama model for SDK update plan...\").start();\n const plan = await askOllamaForPatchPlan({\n docs,\n existingMethodsJson: methodsJson,\n model: options.model\n });\n aiSpinner.succeed(\"Ollama returned an update plan.\");\n\n const generatedFiles = [...plan.files];\n const readmePath = path.join(cwd, \"README.md\");\n const readmeContent = await readFile(readmePath, \"utf8\");\n const updatedReadme = applyReadmeTable(readmeContent, plan.readmeTable);\n if (updatedReadme !== readmeContent) {\n generatedFiles.push({\n path: \"README.md\",\n content: updatedReadme\n });\n }\n\n const diffs = await planDiffs({\n rootDir: cwd,\n files: generatedFiles\n });\n\n console.log(chalk.bold(\"\\nProposed changes\"));\n console.log(chalk.dim(plan.summary));\n for (const planned of diffs) {\n console.log(chalk.cyan(`\\n--- ${planned.path} ---`));\n console.log(planned.diff.slice(0, 4000));\n if (planned.diff.length > 4000) {\n console.log(chalk.dim(\"... diff truncated in terminal preview ...\"));\n }\n }\n\n const applyChanges = options.yes\n ? true\n : (\n await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"applyChanges\",\n message: \"Apply these changes and rebuild package?\",\n default: false\n }\n ])\n ).applyChanges;\n\n if (!applyChanges) {\n console.log(chalk.yellow(\"Update cancelled. No files changed.\"));\n return;\n }\n\n if (options.dryRun) {\n console.log(chalk.yellow(\"Dry-run mode enabled. No files changed.\"));\n return;\n }\n\n const applySpinner = ora(\"Applying generated patches...\").start();\n await applyPlannedDiffs({ plans: diffs });\n await writeFile(\n methodsPath,\n JSON.stringify(\n {\n updatedAt: new Date().toISOString(),\n platforms: plan.updatedMethods\n },\n null,\n 2\n ),\n \"utf8\"\n );\n applySpinner.succeed(\"Patch files applied.\");\n\n const buildSpinner = ora(\"Rebuilding package...\").start();\n await runBuild(cwd);\n buildSpinner.succeed(\"Package rebuilt successfully.\");\n}\n","import axios from \"axios\";\nimport * as cheerio from \"cheerio\";\n\nexport interface CrawledDoc {\n url: string;\n title: string;\n text: string;\n endpointRows: Array<Record<string, string>>;\n}\n\nexport const DOC_URLS = {\n x: [\n \"https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets\",\n \"https://developer.x.com/en/docs/twitter-api/users/likes/api-reference/post-users-id-likes\"\n ],\n facebook: [\n \"https://developers.facebook.com/docs/graph-api/reference/page/feed/\",\n \"https://developers.facebook.com/docs/pages-api/getting-started/\"\n ],\n instagram: [\n \"https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media\",\n \"https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media_publish/\"\n ],\n linkedin: [\n \"https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/posts-api?view=li-lms-2025-10\",\n \"https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/comments-api?view=li-lms-2025-06\"\n ]\n} as const;\n\nfunction cleanText(raw: string): string {\n return raw.replace(/\\s+/g, \" \").replace(/\\u00a0/g, \" \").trim();\n}\n\nfunction extractTables($: cheerio.CheerioAPI): Array<Record<string, string>> {\n const rows: Array<Record<string, string>> = [];\n $(\"table\").each((_, table) => {\n const headers: string[] = [];\n $(table)\n .find(\"thead th\")\n .each((_, th) => {\n headers.push(cleanText($(th).text()));\n });\n\n $(table)\n .find(\"tbody tr\")\n .each((_, tr) => {\n const row: Record<string, string> = {};\n $(tr)\n .find(\"td\")\n .each((idx, td) => {\n const key = headers[idx] || `column_${idx + 1}`;\n row[key] = cleanText($(td).text());\n });\n if (Object.keys(row).length > 0) {\n rows.push(row);\n }\n });\n });\n return rows;\n}\n\nexport async function crawlSingleDoc(url: string): Promise<CrawledDoc> {\n const response = await axios.get<string>(url, {\n timeout: 30_000,\n headers: {\n \"User-Agent\": \"universal-social-sdk-doc-crawler/1.0\"\n }\n });\n const $ = cheerio.load(response.data);\n const title = cleanText($(\"title\").first().text()) || \"Untitled\";\n const text = cleanText($(\"main, article, body\").text());\n const endpointRows = extractTables($);\n\n return {\n url,\n title,\n text: text.slice(0, 250_000),\n endpointRows\n };\n}\n\nexport async function crawlAllDocs(): Promise<CrawledDoc[]> {\n const urls = [\n ...DOC_URLS.x,\n ...DOC_URLS.facebook,\n ...DOC_URLS.instagram,\n ...DOC_URLS.linkedin\n ];\n const results = await Promise.all(urls.map((url) => crawlSingleDoc(url)));\n return results;\n}\n","import axios from \"axios\";\nimport { env } from \"../config/env.js\";\nimport type { CrawledDoc } from \"./docCrawler.js\";\n\nexport interface OllamaPatchFile {\n path: string;\n content: string;\n}\n\nexport interface OllamaPatchPlan {\n summary: string;\n updatedMethods: Record<string, string[]>;\n files: OllamaPatchFile[];\n readmeTable: string;\n}\n\nfunction buildPrompt(docs: CrawledDoc[], existingMethodsJson: string): string {\n return [\n \"You are maintaining universal-social-sdk.\",\n \"Compare the crawled docs with current methods and identify NEW or CHANGED endpoints.\",\n \"Focus areas: content publishing, stories, reels, comments, DMs, analytics.\",\n \"Output STRICT JSON with this shape only:\",\n \"{\\\"summary\\\": string, \\\"updatedMethods\\\": Record<string,string[]>, \\\"files\\\": [{\\\"path\\\": string, \\\"content\\\": string}], \\\"readmeTable\\\": string}\",\n \"Files must target src/platforms/*.ts and supported-methods.json updates when needed.\",\n \"Each file.content must be complete TypeScript file content, not patch snippets.\",\n \"Current supported-methods.json:\",\n existingMethodsJson,\n \"Crawled docs:\",\n JSON.stringify(docs)\n ].join(\"\\n\");\n}\n\nfunction parseJsonOutput(raw: string): OllamaPatchPlan {\n const cleaned = raw.replace(/```json|```/g, \"\").trim();\n const start = cleaned.indexOf(\"{\");\n const end = cleaned.lastIndexOf(\"}\");\n if (start === -1 || end === -1 || end <= start) {\n throw new Error(\"Ollama response did not contain a JSON object.\");\n }\n const maybeJson = cleaned.slice(start, end + 1);\n return JSON.parse(maybeJson) as OllamaPatchPlan;\n}\n\nexport async function askOllamaForPatchPlan(params: {\n docs: CrawledDoc[];\n existingMethodsJson: string;\n model?: string;\n}): Promise<OllamaPatchPlan> {\n const model = params.model || env.ollama.model || \"llama3.2:3b\";\n const prompt = buildPrompt(params.docs, params.existingMethodsJson);\n\n const response = await axios.post<{ response: string }>(\n `${env.ollama.host}/api/generate`,\n {\n model,\n prompt,\n stream: false\n },\n {\n timeout: 120_000\n }\n );\n\n return parseJsonOutput(response.data.response);\n}\n","import dotenv from \"dotenv\";\n\ndotenv.config();\n\nfunction readNumberEnv(name: string, fallback: number): number {\n const value = process.env[name];\n if (!value) {\n return fallback;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : fallback;\n}\n\nexport const env = {\n x: {\n apiKey: process.env.X_API_KEY ?? \"\",\n apiSecret: process.env.X_API_SECRET ?? \"\",\n accessToken: process.env.X_ACCESS_TOKEN ?? \"\",\n accessSecret: process.env.X_ACCESS_SECRET ?? \"\",\n bearerToken: process.env.X_BEARER_TOKEN ?? \"\",\n clientId: process.env.X_CLIENT_ID ?? \"\",\n clientSecret: process.env.X_CLIENT_SECRET ?? \"\"\n },\n meta: {\n appId: process.env.META_APP_ID ?? \"\",\n appSecret: process.env.META_APP_SECRET ?? \"\",\n graphVersion: process.env.META_GRAPH_VERSION ?? \"v21.0\",\n fbPageToken: process.env.FB_PAGE_ACCESS_TOKEN ?? \"\",\n fbPageId: process.env.FB_PAGE_ID ?? \"\",\n igToken: process.env.IG_ACCESS_TOKEN ?? \"\",\n igUserId: process.env.IG_USER_ID ?? \"\"\n },\n linkedin: {\n accessToken: process.env.LINKEDIN_ACCESS_TOKEN ?? \"\",\n refreshToken: process.env.LINKEDIN_REFRESH_TOKEN ?? \"\",\n clientId: process.env.LINKEDIN_CLIENT_ID ?? \"\",\n clientSecret: process.env.LINKEDIN_CLIENT_SECRET ?? \"\",\n orgUrn: process.env.LINKEDIN_ORG_URN ?? \"\",\n personUrn: process.env.LINKEDIN_PERSON_URN ?? \"\",\n apiVersion: process.env.LINKEDIN_API_VERSION ?? \"202510\"\n },\n youtube: {\n accessToken: process.env.YOUTUBE_ACCESS_TOKEN ?? \"\",\n channelId: process.env.YOUTUBE_CHANNEL_ID ?? \"\"\n },\n tiktok: {\n accessToken: process.env.TIKTOK_ACCESS_TOKEN ?? \"\",\n openId: process.env.TIKTOK_OPEN_ID ?? \"\",\n advertiserId: process.env.TIKTOK_ADVERTISER_ID ?? \"\"\n },\n pinterest: {\n accessToken: process.env.PINTEREST_ACCESS_TOKEN ?? \"\",\n boardId: process.env.PINTEREST_BOARD_ID ?? \"\"\n },\n bluesky: {\n serviceUrl: process.env.BLUESKY_SERVICE_URL ?? \"https://bsky.social\",\n identifier: process.env.BLUESKY_IDENTIFIER ?? \"\",\n appPassword: process.env.BLUESKY_APP_PASSWORD ?? \"\",\n accessJwt: process.env.BLUESKY_ACCESS_JWT ?? \"\",\n refreshJwt: process.env.BLUESKY_REFRESH_JWT ?? \"\"\n },\n mastodon: {\n baseUrl: process.env.MASTODON_BASE_URL ?? \"\",\n accessToken: process.env.MASTODON_ACCESS_TOKEN ?? \"\",\n accountId: process.env.MASTODON_ACCOUNT_ID ?? \"\"\n },\n threads: {\n accessToken: process.env.THREADS_ACCESS_TOKEN ?? \"\",\n userId: process.env.THREADS_USER_ID ?? \"\"\n },\n retry: {\n maxRetries: readNumberEnv(\"SOCIAL_SDK_MAX_RETRIES\", 3),\n baseDelayMs: readNumberEnv(\"SOCIAL_SDK_RETRY_BASE_MS\", 500)\n },\n ollama: {\n host: process.env.OLLAMA_HOST ?? \"http://127.0.0.1:11434\",\n model: process.env.OLLAMA_MODEL ?? \"llama3.2:3b\"\n }\n};\n\nexport function requireEnv(name: string): string {\n const value = process.env[name];\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createPatch } from \"diff\";\nimport type { OllamaPatchFile } from \"./ollama.js\";\n\nexport interface PlannedDiff {\n path: string;\n absolutePath: string;\n before: string;\n after: string;\n diff: string;\n}\n\nconst ALLOWED_TARGETS = new Set<string>([\n \"supported-methods.json\",\n \"README.md\"\n]);\n\nfunction isAllowedPath(rootDir: string, filePath: string): string {\n if (path.isAbsolute(filePath)) {\n throw new Error(`Unsafe patch path (absolute not allowed): ${filePath}`);\n }\n\n const normalized = path.normalize(filePath);\n if (normalized.startsWith(\"..\")) {\n throw new Error(`Unsafe patch path (traversal): ${filePath}`);\n }\n\n const isPlatformSource =\n normalized.startsWith(`src${path.sep}platforms${path.sep}`) &&\n normalized.endsWith(\".ts\");\n const isAllowedTopLevel = ALLOWED_TARGETS.has(normalized);\n\n if (!isPlatformSource && !isAllowedTopLevel) {\n throw new Error(\n `Patch path not allowed: ${filePath}. Allowed: src/platforms/*.ts, README.md, supported-methods.json.`\n );\n }\n\n return path.resolve(rootDir, normalized);\n}\n\nexport async function planDiffs(params: {\n rootDir: string;\n files: OllamaPatchFile[];\n}): Promise<PlannedDiff[]> {\n const plans: PlannedDiff[] = [];\n for (const file of params.files) {\n const absolutePath = isAllowedPath(params.rootDir, file.path);\n let before = \"\";\n try {\n before = await readFile(absolutePath, \"utf8\");\n } catch {\n before = \"\";\n }\n const after = file.content;\n const diff = createPatch(file.path, before, after, \"before\", \"after\");\n plans.push({\n path: file.path,\n absolutePath,\n before,\n after,\n diff\n });\n }\n return plans;\n}\n\nexport async function applyPlannedDiffs(params: {\n plans: PlannedDiff[];\n}): Promise<void> {\n for (const plan of params.plans) {\n await writeFile(plan.absolutePath, plan.after, \"utf8\");\n }\n}\n"],"mappings":"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","names":["chalk","readFile","writeFile","path","chalk","inquirer","ora","_","axios","axios","writeFile","path","ora","path","readFile","chalk","inquirer","writeFile","chalk"]}