@usesocial/cli 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @usesocial/cli
2
2
 
3
+ ## 0.12.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#81](https://github.com/usesocial/monorepo/pull/81) [`f4ef94b`](https://github.com/usesocial/monorepo/commit/f4ef94ba089bf4d8bd4a0b42495be6f88608b85e) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Return a checkout URL from non-interactive account connect when a billing seat must be activated.
8
+
9
+ ## 0.12.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#73](https://github.com/usesocial/monorepo/pull/73) [`666b356`](https://github.com/usesocial/monorepo/commit/666b356706c40b7a3dc5e14ec53d76428b25f5c4) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Stop double-wrapping X list mutation output under nested data objects.
14
+
15
+ - [#73](https://github.com/usesocial/monorepo/pull/73) [`1cfedc9`](https://github.com/usesocial/monorepo/commit/1cfedc967b3fa82249bbca059856cc641c87868e) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Detect Bun-installed social CLI when printing update commands.
16
+
3
17
  ## 0.12.1
4
18
 
5
19
  ### Patch Changes
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from "node:module";
3
3
  import * as fs from "node:fs";
4
4
  import { createReadStream, existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
5
- import { basename, dirname, extname, join, resolve } from "node:path";
5
+ import { basename, delimiter, dirname, extname, join, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { homedir } from "node:os";
8
8
  import { parseArgs, styleText } from "node:util";
@@ -1598,7 +1598,7 @@ const LINKEDIN_COLLECTIONS = [
1598
1598
  parentCollection: "li_conversations",
1599
1599
  parentIdToken: ":chat_id",
1600
1600
  pagination: linkedinCursorPagination,
1601
- pageSize: 250,
1601
+ pageSize: 100,
1602
1602
  sinceField: "timestamp",
1603
1603
  lift: liftMessage
1604
1604
  },
@@ -12663,6 +12663,45 @@ looseObject({
12663
12663
  });
12664
12664
  h("ChatListParseError")();
12665
12665
  h("ChatParticipantsFetchError")();
12666
+ const dropLinkedinInmailEligibility = (value) => {
12667
+ if (Array.isArray(value)) {
12668
+ let changed = false;
12669
+ const items = value.map((item) => {
12670
+ const stripped = dropLinkedinInmailEligibility(item);
12671
+ changed ||= stripped.changed;
12672
+ return stripped.value;
12673
+ });
12674
+ return changed ? {
12675
+ value: items,
12676
+ changed
12677
+ } : {
12678
+ value,
12679
+ changed
12680
+ };
12681
+ }
12682
+ if (!(value && typeof value === "object")) return {
12683
+ value,
12684
+ changed: false
12685
+ };
12686
+ let changed = false;
12687
+ const next = {};
12688
+ for (const [key, child] of Object.entries(value)) {
12689
+ if (key === "can_send_inmail") {
12690
+ changed = true;
12691
+ continue;
12692
+ }
12693
+ const stripped = dropLinkedinInmailEligibility(child);
12694
+ changed ||= stripped.changed;
12695
+ next[key] = stripped.value;
12696
+ }
12697
+ return changed ? {
12698
+ value: next,
12699
+ changed
12700
+ } : {
12701
+ value,
12702
+ changed
12703
+ };
12704
+ };
12666
12705
  const linkedinProfileExtractors = {
12667
12706
  "GET /users/me": extractProfile$1,
12668
12707
  "GET /users/:identifier": extractProfile$1,
@@ -21189,14 +21228,23 @@ const listOutputSchema = object({
21189
21228
  includes: record(string(), unknown()).optional(),
21190
21229
  meta: record(string(), unknown()).optional()
21191
21230
  }).passthrough();
21192
- const listWriteAggregateOutputSchema = object({ data: object({
21231
+ const ListWriteOutput = record(string(), unknown());
21232
+ const ListWriteResponse = object({
21233
+ data: ListWriteOutput.optional(),
21234
+ errors: array(record(string(), unknown())).optional()
21235
+ }).passthrough();
21236
+ const ListWriteAggregateOutput = object({
21193
21237
  list_id: string(),
21194
21238
  results: array(object({
21195
21239
  input: string(),
21196
21240
  user_id: string(),
21197
21241
  response: unknown()
21198
21242
  }))
21199
- }) }).passthrough();
21243
+ }).passthrough();
21244
+ const listWriteDataFromResponse = async (response) => {
21245
+ const data = ListWriteResponse.parse(await response.json());
21246
+ return data.data ?? data;
21247
+ };
21200
21248
  const readCost = (category, opts) => {
21201
21249
  const usage = priceUsage(costBPSForCategory(category));
21202
21250
  return {
@@ -21270,7 +21318,7 @@ const listReadContract = (inputSchema, pagination) => manualSchemaContract({
21270
21318
  });
21271
21319
  const listWriteContract = (args) => manualSchemaContract({
21272
21320
  inputSchema: args.inputSchema,
21273
- outputSchema: args.outputSchema ?? listOutputSchema,
21321
+ outputSchema: args.outputSchema ?? ListWriteOutput,
21274
21322
  auth: {
21275
21323
  required: true,
21276
21324
  scopes: ["read", "write"]
@@ -21376,13 +21424,13 @@ const listDeleteContract = listWriteContract({
21376
21424
  const listMemberWriteContract = listWriteContract({
21377
21425
  inputSchema: ListMemberWriteInput,
21378
21426
  method: "POST",
21379
- outputSchema: listWriteAggregateOutputSchema,
21427
+ outputSchema: ListWriteAggregateOutput,
21380
21428
  pricing: "list_manage"
21381
21429
  });
21382
21430
  const listMemberRemoveContract = listWriteContract({
21383
21431
  inputSchema: ListMemberWriteInput,
21384
21432
  method: "DELETE",
21385
- outputSchema: listWriteAggregateOutputSchema,
21433
+ outputSchema: ListWriteAggregateOutput,
21386
21434
  destructive: true,
21387
21435
  pricing: "list_manage"
21388
21436
  });
@@ -21563,7 +21611,7 @@ const buildLists = (deps) => {
21563
21611
  await deps.printResult({
21564
21612
  account: own.account,
21565
21613
  contract: listCreateContract,
21566
- data: await response.json(),
21614
+ data: await listWriteDataFromResponse(response),
21567
21615
  responseHeaders: response.headers
21568
21616
  });
21569
21617
  }
@@ -21624,7 +21672,7 @@ const buildLists = (deps) => {
21624
21672
  await deps.printResult({
21625
21673
  account: own.account,
21626
21674
  contract: listUpdateContract,
21627
- data: await response.json(),
21675
+ data: await listWriteDataFromResponse(response),
21628
21676
  resolved: [target.record],
21629
21677
  responseHeaders: response.headers
21630
21678
  });
@@ -21660,7 +21708,7 @@ const buildLists = (deps) => {
21660
21708
  await deps.printResult({
21661
21709
  account: own.account,
21662
21710
  contract: listDeleteContract,
21663
- data: await response.json(),
21711
+ data: await listWriteDataFromResponse(response),
21664
21712
  resolved: [target.record],
21665
21713
  responseHeaders: response.headers
21666
21714
  });
@@ -21792,16 +21840,16 @@ const buildList = (deps) => {
21792
21840
  results.push({
21793
21841
  input: user,
21794
21842
  user_id: userResolved.id,
21795
- response: await response.json()
21843
+ response: await listWriteDataFromResponse(response)
21796
21844
  });
21797
21845
  }
21798
21846
  await deps.printResult({
21799
21847
  account: own.account,
21800
21848
  contract: kind === "add" ? listMemberWriteContract : listMemberRemoveContract,
21801
- data: { data: {
21849
+ data: {
21802
21850
  list_id: target.id,
21803
21851
  results
21804
- } },
21852
+ },
21805
21853
  resolved
21806
21854
  });
21807
21855
  }
@@ -23913,7 +23961,7 @@ function createEnv(opts) {
23913
23961
  }
23914
23962
  //#endregion
23915
23963
  //#region package.json
23916
- var version$1 = "0.12.1";
23964
+ var version$1 = "0.12.3";
23917
23965
  //#endregion
23918
23966
  //#region src/lib/env.ts
23919
23967
  const URLWithTrailingSlash = url().transform(ensureTrailingSlash);
@@ -25446,8 +25494,8 @@ const isArray = nativeIsArray || function(obj) {
25446
25494
  };
25447
25495
  const isObject = (x) => x === Object(x) && !isArray(x);
25448
25496
  const isUndefined = (x) => void 0 === x;
25449
- const isString = (x) => "[object String]" == type_utils_toString.call(x);
25450
- const isEmptyString = (x) => isString(x) && 0 === x.trim().length;
25497
+ const isString$1 = (x) => "[object String]" == type_utils_toString.call(x);
25498
+ const isEmptyString = (x) => isString$1(x) && 0 === x.trim().length;
25451
25499
  const isNumber = (x) => "[object Number]" == type_utils_toString.call(x) && x === x;
25452
25500
  const isPlainError = (x) => x instanceof Error;
25453
25501
  function isPrimitive(value) {
@@ -26272,7 +26320,7 @@ var ObjectCoercer = class {
26272
26320
  return `${className && "Object" !== className ? `'${className}'` : "Object"} captured as exception with keys: ${keys}`;
26273
26321
  }
26274
26322
  isSeverityLevel(x) {
26275
- return isString(x) && !isEmptyString(x) && severityLevels.indexOf(x) >= 0;
26323
+ return isString$1(x) && !isEmptyString(x) && severityLevels.indexOf(x) >= 0;
26276
26324
  }
26277
26325
  getErrorPropertyFromObject(obj) {
26278
26326
  for (const prop in obj) if (Object.prototype.hasOwnProperty.call(obj, prop)) {
@@ -31871,15 +31919,32 @@ const LifecycleAccountOutput = object({
31871
31919
  connectedAt: string().optional(),
31872
31920
  lastSeenAt: string().optional()
31873
31921
  }).passthrough();
31874
- const AccountConnectStateOutput = discriminatedUnion("status", [object({
31875
- status: literal("connected"),
31876
- platform: _enum(["linkedin", "x"]),
31877
- account: LifecycleAccountOutput
31878
- }), object({
31879
- status: literal("pending_approval"),
31880
- platform: _enum(["linkedin", "x"]),
31881
- connectURL: string()
31882
- })]);
31922
+ const AccountConnectStateOutput = discriminatedUnion("status", [
31923
+ object({
31924
+ status: literal("connected"),
31925
+ platform: _enum(["linkedin", "x"]),
31926
+ account: LifecycleAccountOutput
31927
+ }),
31928
+ object({
31929
+ status: literal("pending_billing"),
31930
+ platform: _enum(["linkedin", "x"]),
31931
+ paymentURL: string().nullable(),
31932
+ requiredAction: object({
31933
+ code: string(),
31934
+ reason: string()
31935
+ }).nullable(),
31936
+ seats: object({
31937
+ total: number().int().nonnegative(),
31938
+ used: number().int().nonnegative(),
31939
+ available: number().int().nonnegative()
31940
+ })
31941
+ }),
31942
+ object({
31943
+ status: literal("pending_approval"),
31944
+ platform: _enum(["linkedin", "x"]),
31945
+ connectURL: string()
31946
+ })
31947
+ ]);
31883
31948
  const AccountConnectOutput = union([string(), AccountConnectStateOutput]);
31884
31949
  const AccountDisconnectOutput = object({
31885
31950
  platform: _enum(["linkedin", "x"]),
@@ -32013,6 +32078,20 @@ const runConnectStep = async (deps, platform, listConnected, connectURL) => {
32013
32078
  });
32014
32079
  return;
32015
32080
  }
32081
+ const billing = await deps.client.billing.prepareAccountConnect();
32082
+ if (!billing.canConnect) {
32083
+ if (!billing.seats) throw new Error("billing_prepare_missing_seats");
32084
+ if (billing.paymentURL) writeText(deps, `Open this URL: ${billing.paymentURL}`);
32085
+ else if (billing.requiredAction) writeText(deps, billing.requiredAction.reason);
32086
+ await writeOutput(deps, {
32087
+ status: "pending_billing",
32088
+ platform,
32089
+ paymentURL: billing.paymentURL ?? null,
32090
+ requiredAction: billing.requiredAction ?? null,
32091
+ seats: billing.seats
32092
+ });
32093
+ return;
32094
+ }
32016
32095
  const url = await connectURL();
32017
32096
  writeText(deps, `Open this URL: ${url}`);
32018
32097
  await writeOutput(deps, {
@@ -38025,12 +38104,47 @@ const compareSemver = (left, right) => {
38025
38104
  }
38026
38105
  return 0;
38027
38106
  };
38028
- const detectPackageManager = (packageRoot) => {
38029
- const normalized = packageRoot.replaceAll("\\", "/");
38107
+ const normalizedPath = (path) => path.replaceAll("\\", "/");
38108
+ const managerFromPath = (path) => {
38109
+ const normalized = normalizedPath(path);
38030
38110
  if (normalized.includes("/Cellar/usesocial/") || normalized.includes("/Cellar/cli/") || normalized.includes("/Homebrew/")) return "brew";
38031
- if (normalized.includes("/.bun/install/global/")) return "bun";
38111
+ if (normalized.includes("/.bun/bin/") || normalized.includes("/.bun/install/global/")) return "bun";
38112
+ };
38113
+ const defaultRealpath = (path) => {
38114
+ try {
38115
+ return realpathSync(path);
38116
+ } catch {
38117
+ return;
38118
+ }
38119
+ };
38120
+ const isString = (value) => value !== void 0;
38121
+ const packageManagerPaths = (packageRoot, options) => {
38122
+ const pathExists = options.pathExists ?? existsSync;
38123
+ const realpath = options.realpath ?? defaultRealpath;
38124
+ const paths = [options.executablePath];
38125
+ if (options.pathEnv) for (const binDir of options.pathEnv.split(delimiter)) {
38126
+ if (!binDir) continue;
38127
+ for (const binary of ["social", "social.cmd"]) {
38128
+ const candidate = join(binDir, binary);
38129
+ if (pathExists(candidate)) paths.push(candidate);
38130
+ }
38131
+ }
38132
+ paths.push(packageRoot);
38133
+ return [...new Set(paths.flatMap((path) => path ? [path, realpath(path)] : []).filter(isString))];
38134
+ };
38135
+ const detectPackageManager = (packageRoot, options = {}) => {
38136
+ for (const path of packageManagerPaths(packageRoot, options)) {
38137
+ const manager = managerFromPath(path);
38138
+ if (manager) return manager;
38139
+ }
38032
38140
  return "npm";
38033
38141
  };
38142
+ const detectPackageManagerFor = (deps) => detectPackageManager(deps.packageRoot ?? internalPackageRoot(), {
38143
+ executablePath: deps.executablePath ?? process.argv[1],
38144
+ pathEnv: deps.pathEnv ?? process.env.PATH,
38145
+ pathExists: deps.pathExists,
38146
+ realpath: deps.realpath
38147
+ });
38034
38148
  const cliUpdateCommand = (manager) => {
38035
38149
  if (manager === "brew") return "brew upgrade usesocial/tap/cli";
38036
38150
  if (manager === "bun") return "bun install -g @usesocial/cli@latest";
@@ -38074,12 +38188,12 @@ const unknownCLIStatus = () => ({
38074
38188
  updateCommand: null
38075
38189
  });
38076
38190
  const checkCLIUpdate = async (deps = {}) => {
38077
- const packageRoot = deps.packageRoot ?? internalPackageRoot();
38191
+ const manager = detectPackageManagerFor(deps);
38078
38192
  const fetchImpl = deps.fetch ?? fetch;
38079
38193
  try {
38080
38194
  const response = await fetchImpl(NPM_REGISTRY_URL, { headers: { accept: "application/json" } });
38081
38195
  if (!response.ok) return unknownCLIStatus();
38082
- return parseNPMUpdateResult(await response.json(), VERSION, detectPackageManager(packageRoot));
38196
+ return parseNPMUpdateResult(await response.json(), VERSION, manager);
38083
38197
  } catch {
38084
38198
  return unknownCLIStatus();
38085
38199
  }
@@ -38243,7 +38357,7 @@ const unknownSkillStatus = () => ({
38243
38357
  updateCommand: null
38244
38358
  });
38245
38359
  const checkSkillUpdate = async (deps = {}) => {
38246
- const manager = detectPackageManager(deps.packageRoot ?? internalPackageRoot());
38360
+ const manager = detectPackageManagerFor(deps);
38247
38361
  const install = await installedSkillCandidate(deps);
38248
38362
  if (!install) return {
38249
38363
  scope: null,
@@ -38314,20 +38428,20 @@ const withNotice = (cache, key, now) => ({
38314
38428
  [key]: now
38315
38429
  }
38316
38430
  });
38317
- const noticeLinesFor = (cache, now) => {
38431
+ const noticeLinesFor = (cache, now, manager) => {
38318
38432
  const notices = [];
38319
- if (cache.cli.status === "update_available" && cache.cli.latestVersion && cache.cli.updateCommand) {
38433
+ if (cache.cli.status === "update_available" && cache.cli.currentVersion === VERSION && cache.cli.latestVersion && compareSemver(cache.cli.latestVersion, VERSION) > 0) {
38320
38434
  const key = `cli:${cache.cli.latestVersion}`;
38321
38435
  if (noticeDue(cache, key, now)) notices.push({
38322
38436
  key,
38323
- line: `Update available: social CLI ${cache.cli.latestVersion} (current ${cache.cli.currentVersion}). Run: ${cache.cli.updateCommand}`
38437
+ line: `Update available: social CLI ${cache.cli.latestVersion} (current ${cache.cli.currentVersion}). Run: ${cliUpdateCommand(manager)}`
38324
38438
  });
38325
38439
  }
38326
- if (cache.skill.status === "update_available" && cache.skill.scope && cache.skill.updateCommand && cache.skill.remoteTreeSHA) {
38440
+ if (cache.skill.status === "update_available" && cache.skill.scope && cache.skill.remoteTreeSHA) {
38327
38441
  const key = `skill:${cache.skill.scope}:${cache.skill.remoteTreeSHA}`;
38328
38442
  if (noticeDue(cache, key, now)) notices.push({
38329
38443
  key,
38330
- line: `Update available: social skill (${cache.skill.scope}). Run: ${cache.skill.updateCommand}`
38444
+ line: `Update available: social skill (${cache.skill.scope}). Run: ${skillUpdateCommand(cache.skill.scope, manager)}`
38331
38445
  });
38332
38446
  }
38333
38447
  return notices;
@@ -38351,8 +38465,9 @@ const maybeRunUpdateAwareness = async (deps = {}) => {
38351
38465
  const home = deps.home;
38352
38466
  const cache = await readCachedUpdateStatus(home);
38353
38467
  if (cache) {
38468
+ const manager = detectPackageManagerFor(deps);
38354
38469
  let next = cache;
38355
- for (const notice of noticeLinesFor(cache, now)) {
38470
+ for (const notice of noticeLinesFor(cache, now, manager)) {
38356
38471
  printStderrLine(notice.line);
38357
38472
  next = withNotice(next, notice.key, now);
38358
38473
  }