universal-social-sdk 1.0.0 → 1.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.
@@ -0,0 +1,46 @@
1
+ # Copy this file to .env.test and fill only sandbox credentials.
2
+ # Tests load .env.test first, then .env as fallback.
3
+
4
+ # X
5
+ X_API_KEY=
6
+ X_API_SECRET=
7
+ X_ACCESS_TOKEN=
8
+ X_ACCESS_SECRET=
9
+ X_TEST_TWEET_ID=
10
+
11
+ # Facebook
12
+ FB_PAGE_ACCESS_TOKEN=
13
+ FB_PAGE_ID=
14
+
15
+ # Instagram
16
+ IG_ACCESS_TOKEN=
17
+ IG_USER_ID=
18
+
19
+ # LinkedIn
20
+ LINKEDIN_ACCESS_TOKEN=
21
+ LINKEDIN_ORG_URN=
22
+
23
+ # YouTube
24
+ YOUTUBE_ACCESS_TOKEN=
25
+ YOUTUBE_CHANNEL_ID=
26
+
27
+ # TikTok
28
+ TIKTOK_ACCESS_TOKEN=
29
+
30
+ # Pinterest
31
+ PINTEREST_ACCESS_TOKEN=
32
+ PINTEREST_BOARD_ID=
33
+
34
+ # Bluesky
35
+ BLUESKY_IDENTIFIER=
36
+ BLUESKY_APP_PASSWORD=
37
+ BLUESKY_TEST_ACTOR=
38
+
39
+ # Mastodon
40
+ MASTODON_BASE_URL=
41
+ MASTODON_ACCESS_TOKEN=
42
+ MASTODON_ACCOUNT_ID=
43
+
44
+ # Threads
45
+ THREADS_ACCESS_TOKEN=
46
+ THREADS_USER_ID=
package/CHANGELOG.md ADDED
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - Non-interactive updater mode for CI/automation (`--ci`, `--open-pr`, `--branch-prefix`, `--base`, `--artifacts-dir`).
13
+ - Structured updater artifacts (`.artifacts/update-plan.json`, `.artifacts/update-diff-summary.json`, `.artifacts/pr-title.txt`, `.artifacts/pr-body.md`).
14
+ - Strict Ollama patch-plan schema validation with typed `changes` metadata (platform, endpoint, change type, confidence).
15
+ - Scheduled PR automation workflow: `.github/workflows/auto-update-pr.yml`.
16
+ - Workflow-dispatch `dry_run` mode for updater automation (detect and generate artifacts without opening PRs).
17
+ - Unit tests covering updater plan validation and no-change detection behavior.
18
+
19
+ ### Changed
20
+
21
+ - Updater CI mode now enforces `npm run build` and `npm run test:unit` before PR automation proceeds.
22
+ - Auto-update PR workflow now excludes `.artifacts/*` from commits while still using artifacts for PR metadata.
23
+
24
+ ## [1.1.0] - 2026-03-08
25
+
26
+ ### Added
27
+
28
+ - `src/webhooks` module with:
29
+ - Meta and X signature verification helpers
30
+ - normalized webhook event parsing helpers
31
+ - `WebhookRouter` for typed and wildcard event dispatch
32
+ - Unit tests for webhook verification, normalization, and routing.
33
+ - `src/queue` module with:
34
+ - `QueueAdapter` interface
35
+ - `InMemoryQueueAdapter`
36
+ - skeleton adapters for BullMQ and SQS
37
+ - queue adapter registry (`setQueueAdapter`, `getQueueAdapter`, `resetQueueAdapter`)
38
+ - Scheduler integration to route scheduled jobs through the active queue adapter.
39
+ - Unit tests for queue adapter registry and scheduler behavior.
40
+ - Added typed response interfaces and explicit return contracts across all public platform methods.
41
+ - Refined response contracts with platform-specific action/delete/result aliases for stronger API clarity.
42
+ - Added internal normalized result helpers so action/delete/mutation/detail responses remain stable even if upstream provider payloads drift.
43
+ - Added `docs/RESPONSE_CONTRACTS.md` with stable contract reference and integration guidance.
44
+ - Exported response interfaces from package root.
45
+ - Unit test coverage for typed response shapes.
46
+
47
+ ## [1.0.1] - 2026-03-08
48
+
49
+ ### Added
50
+
51
+ - Runtime validation for public platform methods.
52
+ - Integration test scaffolding for all supported platforms.
53
+ - Repository governance files (`CODE_OF_CONDUCT.md`, `SECURITY.md`, `LICENSE`).
54
+ - Examples folder with runnable scripts.
55
+ - Package metadata fields (`homepage`, `bugs`, `funding`) in `package.json`.
56
+
57
+ ### Changed
58
+
59
+ - CI and release workflow gating behavior for clearer run outcomes.
60
+ - Documentation coverage for platform matrix, testing, and project structure.
61
+
62
+ ## [1.0.0] - 2026-03-08
63
+
64
+ ### Added
65
+
66
+ - Initial public release of `universal-social-sdk`.
67
+ - Unified static async APIs for:
68
+ - X
69
+ - Facebook
70
+ - Instagram
71
+ - LinkedIn
72
+ - YouTube
73
+ - TikTok
74
+ - Pinterest
75
+ - Bluesky
76
+ - Mastodon
77
+ - Threads
78
+ - CLI:
79
+ - `universal-social-sdk init`
80
+ - `universal-social-sdk update`
81
+ - Build + type declarations via TypeScript + tsup.
82
+ - Unit and integration test scaffolding.
83
+ - GitHub Actions CI and npm release automation.
84
+ - Comprehensive setup and usage documentation.
package/README.md CHANGED
@@ -9,9 +9,12 @@ TypeScript-first, ESM-only, zero-bloat Node.js SDK that provides one unified int
9
9
 
10
10
  - [Project Structure](./docs/PROJECT_STRUCTURE.md)
11
11
  - [NPM Package Guide](./docs/NPM_PACKAGE_GUIDE.md)
12
+ - [Response Contracts](./docs/RESPONSE_CONTRACTS.md)
12
13
  - [Contributing](./docs/CONTRIBUTING.md)
14
+ - [Roadmap v1.1.0](./docs/ROADMAP_v1.1.0.md)
13
15
  - [Code of Conduct](./CODE_OF_CONDUCT.md)
14
16
  - [Security Policy](./SECURITY.md)
17
+ - [Changelog](./CHANGELOG.md)
15
18
 
16
19
  ## Install
17
20
 
@@ -46,6 +49,77 @@ await Mastodon.createStatus({ text: "Hello Fediverse!" });
46
49
  await Threads.postText({ text: "Hello Threads!" });
47
50
  ```
48
51
 
52
+ ## Examples
53
+
54
+ Run bundled examples:
55
+
56
+ ```bash
57
+ npm run example:x
58
+ npm run example:instagram
59
+ npm run example:bluesky
60
+ npm run example:queue
61
+ ```
62
+
63
+ Files:
64
+
65
+ - `examples/x-post.mjs`
66
+ - `examples/instagram-reel.mjs`
67
+ - `examples/bluesky-post.mjs`
68
+ - `examples/queue-in-memory.mjs`
69
+
70
+ ## Queue Adapters
71
+
72
+ The scheduler uses a queue adapter. By default it uses an in-memory adapter.
73
+
74
+ ```ts
75
+ import { InMemoryQueueAdapter, setQueueAdapter } from "universal-social-sdk";
76
+
77
+ setQueueAdapter(new InMemoryQueueAdapter());
78
+ ```
79
+
80
+ Adapter exports:
81
+
82
+ - `InMemoryQueueAdapter` (default behavior)
83
+ - `BullMQAdapter` (skeleton)
84
+ - `SQSAdapter` (skeleton)
85
+
86
+ The scheduler APIs (for example `X.scheduleTweet`) will use the active adapter automatically.
87
+
88
+ ## Typed Responses
89
+
90
+ All public SDK methods now return concrete TypeScript interfaces, including platform-specific action/delete aliases for clearer contracts.
91
+ Action/delete/mutation/detail responses are normalized into stable contracts (`success`, `action`/`targetId`/`resourceId`, `raw`) so provider endpoint changes are isolated to SDK internals.
92
+
93
+ ```ts
94
+ import { X } from "universal-social-sdk";
95
+ import type { XPostResult } from "universal-social-sdk";
96
+
97
+ const result: XPostResult = await X.postTweet({ text: "typed response" });
98
+ console.log(result.data.id);
99
+ ```
100
+
101
+ ## Webhooks
102
+
103
+ The SDK includes webhook utilities for Meta-style and X-style signatures, normalized event parsing, and a lightweight router.
104
+
105
+ ```ts
106
+ import {
107
+ WebhookRouter,
108
+ verifyMetaWebhookSignature,
109
+ verifyXWebhookSignature
110
+ } from "universal-social-sdk";
111
+
112
+ const router = new WebhookRouter();
113
+
114
+ router.on("meta.feed", async (event) => {
115
+ console.log("Meta feed event", event.payload);
116
+ });
117
+
118
+ router.on("x.tweet_create_events", async (event) => {
119
+ console.log("X tweet event", event.payload);
120
+ });
121
+ ```
122
+
49
123
  ## Required Environment Variables
50
124
 
51
125
  `universal-social-sdk` auto-loads `.env` with `dotenv`.
@@ -145,6 +219,7 @@ npx universal-social-sdk update
145
219
  npx universal-social-sdk update --dry-run
146
220
  npx universal-social-sdk update --model llama3.2
147
221
  npx universal-social-sdk update --yes
222
+ npx universal-social-sdk update --ci --open-pr --base main --branch-prefix chore/updater
148
223
  ```
149
224
 
150
225
  Flow:
@@ -156,6 +231,13 @@ Flow:
156
231
  5. Shows git-style diffs and asks for confirmation.
157
232
  6. Applies patches and rebuilds package.
158
233
 
234
+ CI/PR mode writes deterministic artifacts in `.artifacts/`:
235
+
236
+ - `update-plan.json`
237
+ - `update-diff-summary.json`
238
+ - `pr-title.txt`
239
+ - `pr-body.md`
240
+
159
241
  ## Supported Methods
160
242
 
161
243
  Method coverage by platform:
@@ -296,6 +378,12 @@ This repo includes:
296
378
 
297
379
  - `.github/workflows/ci.yml` for build + unit tests on every push/PR.
298
380
  - `.github/workflows/release.yml` for npm publish on tag (`v*`) or manual dispatch.
381
+ - `.github/workflows/auto-update-pr.yml` for scheduled doc crawling + updater PR generation.
382
+ - Generates `.artifacts/*` for PR metadata during the run but does not commit artifact files.
383
+
384
+ Manual dry-run option for updater workflow:
385
+
386
+ - In **Actions -> Auto Update PR -> Run workflow**, set `dry_run=true` to run detection and artifact generation only (no branch/PR).
299
387
 
300
388
  Configure these repository secrets to enable integration CI:
301
389
 
@@ -327,3 +415,8 @@ Configure these repository secrets to enable integration CI:
327
415
  Configure this repository secret for publishing:
328
416
 
329
417
  - `NPM_TOKEN`
418
+
419
+ Configure this repository secret for scheduled updater PRs:
420
+
421
+ - `OLLAMA_HOST` (required; endpoint reachable from GitHub Actions runner)
422
+ - `OLLAMA_MODEL` (optional override)
package/dist/cli/index.js CHANGED
@@ -155,7 +155,7 @@ async function runInitCommand(cwd) {
155
155
  }
156
156
 
157
157
  // src/cli/commands/update.ts
158
- import { readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
158
+ import { mkdir, readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
159
159
  import path3 from "path";
160
160
  import chalk2 from "chalk";
161
161
  import inquirer2 from "inquirer";
@@ -236,6 +236,7 @@ async function crawlAllDocs() {
236
236
 
237
237
  // src/updater/ollama.ts
238
238
  import axios2 from "axios";
239
+ import { z } from "zod";
239
240
 
240
241
  // src/config/env.ts
241
242
  import dotenv from "dotenv";
@@ -316,13 +317,33 @@ var env = {
316
317
  };
317
318
 
318
319
  // src/updater/ollama.ts
320
+ var ollamaPatchPlanSchema = z.object({
321
+ summary: z.string().min(1),
322
+ updatedMethods: z.record(z.array(z.string())),
323
+ changes: z.array(
324
+ z.object({
325
+ platform: z.string().min(1),
326
+ endpoint: z.string().min(1),
327
+ changeType: z.enum(["added", "modified", "deprecated", "removed"]),
328
+ confidence: z.number().min(0).max(1),
329
+ notes: z.string().optional()
330
+ })
331
+ ).default([]),
332
+ files: z.array(
333
+ z.object({
334
+ path: z.string().min(1),
335
+ content: z.string()
336
+ })
337
+ ),
338
+ readmeTable: z.string()
339
+ });
319
340
  function buildPrompt(docs, existingMethodsJson) {
320
341
  return [
321
342
  "You are maintaining universal-social-sdk.",
322
343
  "Compare the crawled docs with current methods and identify NEW or CHANGED endpoints.",
323
344
  "Focus areas: content publishing, stories, reels, comments, DMs, analytics.",
324
345
  "Output STRICT JSON with this shape only:",
325
- '{"summary": string, "updatedMethods": Record<string,string[]>, "files": [{"path": string, "content": string}], "readmeTable": string}',
346
+ '{"summary": string, "updatedMethods": Record<string,string[]>, "changes": [{"platform": string, "endpoint": string, "changeType": "added|modified|deprecated|removed", "confidence": number, "notes"?: string}], "files": [{"path": string, "content": string}], "readmeTable": string}',
326
347
  "Files must target src/platforms/*.ts and supported-methods.json updates when needed.",
327
348
  "Each file.content must be complete TypeScript file content, not patch snippets.",
328
349
  "Current supported-methods.json:",
@@ -339,7 +360,14 @@ function parseJsonOutput(raw) {
339
360
  throw new Error("Ollama response did not contain a JSON object.");
340
361
  }
341
362
  const maybeJson = cleaned.slice(start, end + 1);
342
- return JSON.parse(maybeJson);
363
+ const parsed = JSON.parse(maybeJson);
364
+ const result = ollamaPatchPlanSchema.safeParse(parsed);
365
+ if (!result.success) {
366
+ throw new Error(
367
+ `Ollama patch plan schema validation failed: ${result.error.message}`
368
+ );
369
+ }
370
+ return result.data;
343
371
  }
344
372
  async function askOllamaForPatchPlan(params) {
345
373
  const model = params.model || env.ollama.model || "llama3.2:3b";
@@ -413,9 +441,9 @@ async function applyPlannedDiffs(params) {
413
441
 
414
442
  // src/cli/commands/update.ts
415
443
  import { spawn } from "child_process";
416
- function runBuild(cwd) {
444
+ function runNpmScript(cwd, script) {
417
445
  return new Promise((resolve, reject) => {
418
- const child = spawn("npm", ["run", "build"], {
446
+ const child = spawn("npm", ["run", script], {
419
447
  cwd,
420
448
  stdio: "inherit",
421
449
  shell: true
@@ -424,7 +452,9 @@ function runBuild(cwd) {
424
452
  if (code === 0) {
425
453
  resolve();
426
454
  } else {
427
- reject(new Error(`Build failed with exit code ${code ?? -1}`));
455
+ reject(
456
+ new Error(`npm run ${script} failed with exit code ${code ?? -1}`)
457
+ );
428
458
  }
429
459
  });
430
460
  });
@@ -444,19 +474,134 @@ ${endMarker}`;
444
474
  replacement
445
475
  );
446
476
  }
477
+ function normalizeMethods(methods) {
478
+ return Object.fromEntries(
479
+ Object.entries(methods).sort(([a], [b]) => a.localeCompare(b)).map(([platform, items]) => [platform, [...items].sort()])
480
+ );
481
+ }
482
+ function parseExistingMethods(methodsJson) {
483
+ try {
484
+ const parsed = JSON.parse(methodsJson);
485
+ return parsed.platforms ?? {};
486
+ } catch {
487
+ return {};
488
+ }
489
+ }
490
+ function hasMaterialChanges(params) {
491
+ const hasFileChanges = params.diffs.some((diff) => diff.before !== diff.after);
492
+ const methodsChanged = JSON.stringify(normalizeMethods(params.existingMethods)) !== JSON.stringify(normalizeMethods(params.updatedMethods));
493
+ return {
494
+ hasChanges: hasFileChanges || methodsChanged,
495
+ hasFileChanges,
496
+ methodsChanged
497
+ };
498
+ }
499
+ function inferRisk(params) {
500
+ const text = params.summary.toLowerCase();
501
+ if (text.includes("breaking") || text.includes("deprecat") || text.includes("remove")) {
502
+ return "high";
503
+ }
504
+ if (params.diffs.some((diff) => diff.path.startsWith("src/platforms/"))) {
505
+ return "medium";
506
+ }
507
+ return "low";
508
+ }
509
+ function buildPrArtifacts(params) {
510
+ const changedPlatforms = /* @__PURE__ */ new Set();
511
+ for (const file of params.plan.files) {
512
+ const parts = file.path.split("/");
513
+ if (parts[0] === "src" && parts[1] === "platforms" && parts[2]) {
514
+ changedPlatforms.add(parts[2].replace(/\.ts$/, ""));
515
+ }
516
+ }
517
+ const changeTypeCounts = params.plan.changes.reduce(
518
+ (acc, change) => {
519
+ acc[change.changeType] = (acc[change.changeType] ?? 0) + 1;
520
+ return acc;
521
+ },
522
+ {}
523
+ );
524
+ const branchName = `${params.branchPrefix}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
525
+ const title = "chore(updater): sync social API documentation changes";
526
+ const body = [
527
+ "## Summary",
528
+ `- ${params.plan.summary}`,
529
+ `- Risk classification: **${params.risk}**`,
530
+ `- Changed files: ${params.diffs.length}`,
531
+ `- Changed platforms: ${changedPlatforms.size > 0 ? [...changedPlatforms].sort().join(", ") : "none"}`,
532
+ `- Endpoint deltas: ${Object.keys(changeTypeCounts).length > 0 ? Object.entries(changeTypeCounts).map(([type, count]) => `${type}=${count}`).join(", ") : "none"}`,
533
+ "",
534
+ "## Validation",
535
+ "- [x] `npm run build`",
536
+ "- [x] `npm run test:unit`",
537
+ "",
538
+ "## Review checklist",
539
+ "- [ ] Confirm endpoint/scope changes match official docs",
540
+ "- [ ] Confirm method signatures are backward compatible",
541
+ "- [ ] Confirm normalized response contracts remain stable"
542
+ ].join("\n");
543
+ return {
544
+ title,
545
+ body,
546
+ base: params.base,
547
+ branchName,
548
+ changedPlatforms: [...changedPlatforms].sort()
549
+ };
550
+ }
551
+ async function writeUpdaterArtifacts(params) {
552
+ const outDir = path3.join(params.cwd, params.artifactsDir);
553
+ await mkdir(outDir, { recursive: true });
554
+ await writeFile3(
555
+ path3.join(outDir, "update-plan.json"),
556
+ JSON.stringify(
557
+ {
558
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
559
+ docsCount: params.docsCount,
560
+ summary: params.plan.summary,
561
+ changes: params.plan.changes,
562
+ updatedMethods: params.plan.updatedMethods,
563
+ files: params.plan.files.map((file) => file.path)
564
+ },
565
+ null,
566
+ 2
567
+ ),
568
+ "utf8"
569
+ );
570
+ await writeFile3(
571
+ path3.join(outDir, "update-diff-summary.json"),
572
+ JSON.stringify(
573
+ {
574
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
575
+ hasChanges: params.hasChanges,
576
+ risk: params.risk,
577
+ changes: params.plan.changes,
578
+ changedFiles: params.diffs.filter((diff) => diff.before !== diff.after).map((diff) => diff.path),
579
+ pr: params.pr
580
+ },
581
+ null,
582
+ 2
583
+ ),
584
+ "utf8"
585
+ );
586
+ await writeFile3(path3.join(outDir, "pr-title.txt"), `${params.pr.title}
587
+ `, "utf8");
588
+ await writeFile3(path3.join(outDir, "pr-body.md"), `${params.pr.body}
589
+ `, "utf8");
590
+ }
447
591
  async function runUpdateCommand(cwd, options = {}) {
448
592
  const crawlSpinner = ora2("Crawling official social API docs...").start();
449
593
  const docs = await crawlAllDocs();
450
594
  crawlSpinner.succeed(`Crawled ${docs.length} documentation pages.`);
451
595
  const methodsPath = path3.join(cwd, "supported-methods.json");
452
596
  const methodsJson = await readFile2(methodsPath, "utf8");
453
- const aiSpinner = ora2("Asking local Ollama model for SDK update plan...").start();
597
+ const existingMethods = parseExistingMethods(methodsJson);
598
+ const planSpinner = ora2("Generating SDK update plan from crawled docs...").start();
454
599
  const plan = await askOllamaForPatchPlan({
455
600
  docs,
456
601
  existingMethodsJson: methodsJson,
457
602
  model: options.model
458
603
  });
459
- aiSpinner.succeed("Ollama returned an update plan.");
604
+ planSpinner.succeed("Update plan generated.");
460
605
  const generatedFiles = [...plan.files];
461
606
  const readmePath = path3.join(cwd, "README.md");
462
607
  const readmeContent = await readFile2(readmePath, "utf8");
@@ -471,6 +616,20 @@ async function runUpdateCommand(cwd, options = {}) {
471
616
  rootDir: cwd,
472
617
  files: generatedFiles
473
618
  });
619
+ const changeStats = hasMaterialChanges({
620
+ diffs,
621
+ existingMethods,
622
+ updatedMethods: plan.updatedMethods
623
+ });
624
+ const hasChanges = changeStats.hasChanges;
625
+ const risk = inferRisk({ summary: plan.summary, diffs });
626
+ const prArtifacts = buildPrArtifacts({
627
+ plan,
628
+ diffs,
629
+ risk,
630
+ base: options.base ?? "main",
631
+ branchPrefix: options.branchPrefix ?? "chore/updater"
632
+ });
474
633
  console.log(chalk2.bold("\nProposed changes"));
475
634
  console.log(chalk2.dim(plan.summary));
476
635
  for (const planned of diffs) {
@@ -481,7 +640,24 @@ async function runUpdateCommand(cwd, options = {}) {
481
640
  console.log(chalk2.dim("... diff truncated in terminal preview ..."));
482
641
  }
483
642
  }
484
- const applyChanges = options.yes ? true : (await inquirer2.prompt([
643
+ if (options.openPr || options.ci) {
644
+ await writeUpdaterArtifacts({
645
+ cwd,
646
+ artifactsDir: options.artifactsDir ?? ".artifacts",
647
+ docsCount: docs.length,
648
+ plan,
649
+ diffs,
650
+ hasChanges,
651
+ risk,
652
+ pr: prArtifacts
653
+ });
654
+ }
655
+ if (!hasChanges) {
656
+ console.log(chalk2.green("No material documentation changes detected."));
657
+ return;
658
+ }
659
+ const nonInteractive = options.ci || options.openPr;
660
+ const applyChanges = options.yes ? true : nonInteractive ? true : (await inquirer2.prompt([
485
661
  {
486
662
  type: "confirm",
487
663
  name: "applyChanges",
@@ -513,13 +689,18 @@ async function runUpdateCommand(cwd, options = {}) {
513
689
  );
514
690
  applySpinner.succeed("Patch files applied.");
515
691
  const buildSpinner = ora2("Rebuilding package...").start();
516
- await runBuild(cwd);
692
+ await runNpmScript(cwd, "build");
517
693
  buildSpinner.succeed("Package rebuilt successfully.");
694
+ if (options.ci || options.openPr) {
695
+ const testSpinner = ora2("Running unit tests...").start();
696
+ await runNpmScript(cwd, "test:unit");
697
+ testSpinner.succeed("Unit tests passed.");
698
+ }
518
699
  }
519
700
 
520
701
  // src/cli/index.ts
521
702
  var program = new Command();
522
- program.name("universal-social-sdk").description("Universal social media SDK CLI").version("1.0.0");
703
+ program.name("universal-social-sdk").description("Universal social media SDK CLI").version("1.1.0");
523
704
  program.command("init").description("Create .env.example and show OAuth setup links").action(async () => {
524
705
  try {
525
706
  await runInitCommand(process.cwd());
@@ -529,18 +710,33 @@ program.command("init").description("Create .env.example and show OAuth setup li
529
710
  process.exitCode = 1;
530
711
  }
531
712
  });
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;
713
+ 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").option("--ci", "Run in non-interactive CI mode").option("--open-pr", "Prepare PR artifacts for workflow automation").option(
714
+ "--branch-prefix <prefix>",
715
+ "Branch prefix for updater PR metadata",
716
+ "chore/updater"
717
+ ).option("--base <branch>", "Base branch for PR metadata", "main").option(
718
+ "--artifacts-dir <path>",
719
+ "Directory for generated updater artifacts",
720
+ ".artifacts"
721
+ ).action(
722
+ async (options) => {
723
+ try {
724
+ await runUpdateCommand(process.cwd(), {
725
+ dryRun: options.dryRun,
726
+ yes: options.yes,
727
+ model: options.model,
728
+ ci: options.ci,
729
+ openPr: options.openPr,
730
+ branchPrefix: options.branchPrefix,
731
+ base: options.base,
732
+ artifactsDir: options.artifactsDir
733
+ });
734
+ } catch (error) {
735
+ console.error(chalk3.red("Update failed."));
736
+ console.error(error);
737
+ process.exitCode = 1;
738
+ }
543
739
  }
544
- });
740
+ );
545
741
  program.parse(process.argv);
546
742
  //# sourceMappingURL=index.js.map