@curviate/sdk 0.40.1 → 0.41.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.
package/dist/index.js CHANGED
@@ -79,6 +79,19 @@ var ERROR_CODES = [
79
79
  "CHECKPOINT_ALREADY_RESOLVED",
80
80
  "CHECKPOINT_UNSUPPORTED",
81
81
  "CONNECTION_IN_PROGRESS",
82
+ // Connection location (where LinkedIn sees the account connecting from).
83
+ // `CONNECTION_LOCATION_REQUIRED` (400): a new connect named no location, or
84
+ // a PATCH cleared your own proxy (`proxy: null`) without a `country`. Send
85
+ // exactly one of `country`, `ip` or `proxy`. user_fixable, never retryable
86
+ // as sent.
87
+ // `CONNECTION_LOCATION_UNAVAILABLE` (422): no connection is free in that
88
+ // country right now (strict), or the change landed elsewhere. When a change
89
+ // was applied, {@link CurviateError.connectionLocation} says where the
90
+ // account connects from now, which may mean your own proxy is already gone.
91
+ // Try a nearby country, or allow fallback. user_fixable, never retryable as
92
+ // sent.
93
+ "CONNECTION_LOCATION_REQUIRED",
94
+ "CONNECTION_LOCATION_UNAVAILABLE",
82
95
  // A reconnect whose seat-derived scope differs from the account's recorded
83
96
  // scope was attempted with cookie auth; a cookie replay cannot change
84
97
  // scope, so a full credentials re-authentication is required. user_fixable,
@@ -187,6 +200,7 @@ var CurviateError = class _CurviateError extends Error {
187
200
  this.safetyHint = init.safetyHint;
188
201
  this.safetyReason = init.safetyReason;
189
202
  this.blocked = init.blocked;
203
+ this.connectionLocation = init.connectionLocation;
190
204
  Object.setPrototypeOf(this, _CurviateError.prototype);
191
205
  }
192
206
  /**
@@ -211,6 +225,7 @@ var CurviateError = class _CurviateError extends Error {
211
225
  if (this.safetyHint !== void 0) json.safetyHint = this.safetyHint;
212
226
  if (this.safetyReason !== void 0) json.safetyReason = this.safetyReason;
213
227
  if (this.blocked !== void 0) json.blocked = this.blocked;
228
+ if (this.connectionLocation !== void 0) json.connectionLocation = this.connectionLocation;
214
229
  return json;
215
230
  }
216
231
  };
@@ -325,7 +340,8 @@ async function errorFromResponse(res) {
325
340
  ...typeof env?.reset_at === "string" || env?.reset_at === null ? { resetAt: env.reset_at } : {},
326
341
  ...safetyHint !== void 0 ? { safetyHint } : {},
327
342
  ...safetyReason !== void 0 ? { safetyReason } : {},
328
- ...typeof env?.blocked === "boolean" ? { blocked: env.blocked } : {}
343
+ ...typeof env?.blocked === "boolean" ? { blocked: env.blocked } : {},
344
+ ...env?.connection_location !== null && typeof env?.connection_location === "object" ? { connectionLocation: env.connection_location } : {}
329
345
  });
330
346
  return { err, refusesRetry: env?.retry_likely_to_succeed === false };
331
347
  }
@@ -543,7 +559,7 @@ var AccountsResource = class {
543
559
  * const { items } = await curviate.accounts.listSeats();
544
560
  * const free = items.find((seat) => !seat.occupied);
545
561
  * if (!free) throw new Error("No seat is free to connect to right now (add a seat, or check billing).");
546
- * await curviate.auth.intent({ seat_id: free.seat_id, auth_method: "cookie", cookie: { li_at }, user_agent });
562
+ * await curviate.auth.intent({ seat_id: free.seat_id, auth_method: "cookie", cookie: { li_at }, user_agent, country: "US" });
547
563
  */
548
564
  listSeats() {
549
565
  return this.ctx.request({ method: "GET", path: "/v1/accounts/seats" });
@@ -597,13 +613,30 @@ var AccountsResource = class {
597
613
  * `metadata` is a flat string->string map (at most 16 keys, key 40 chars,
598
614
  * value 500) that **replaces** the stored map wholesale; `null` clears it.
599
615
  * Both are stored by Curviate, read back on `get`/`list`, and a PATCH
600
- * carrying only them makes no LinkedIn call. `proxy` sets a custom egress
601
- * proxy, or clears it (reverting to automatic proxy protection) when passed
602
- * as `null`. The `proxy.password`, if given, is stored securely and never
603
- * returned.
616
+ * carrying only them makes no LinkedIn call.
617
+ *
618
+ * `country` moves the account's connection location to that supported ISO
619
+ * country. LinkedIn sees a new IP there and may ask the owner to verify, so
620
+ * change it only when the current location is wrong. Strict unless
621
+ * `allow_country_fallback: true`; `allow_country_fallback` alone changes the
622
+ * strictness of the configured country. `proxy` sets your own proxy; `null`
623
+ * returns to a managed location and **requires** a `country` in the same
624
+ * call (else `CONNECTION_LOCATION_REQUIRED`), and an account on your own
625
+ * proxy can only take a `country` together with `proxy: null`. The
626
+ * `proxy.password`, if given, is never returned.
627
+ *
628
+ * Returns the account (as `get` returns it, without `quotas` and
629
+ * `event_log`). After a location change its `connection_location` is re-read,
630
+ * so it shows where the account really connects from now. A change that did
631
+ * not land where asked throws `CONNECTION_LOCATION_UNAVAILABLE`, whose
632
+ * `connectionLocation` carries the actual location.
604
633
  *
605
634
  * @example
606
635
  * await curviate.accounts.update("acc_123", { external_id: "usr_42", metadata: { plan: "pro" } });
636
+ *
637
+ * @example
638
+ * const account = await curviate.accounts.update("acc_123", { country: "DE" });
639
+ * console.log(account.connection_location?.country); // "DE"
607
640
  */
608
641
  update(accountId, body) {
609
642
  return this.ctx.request({
@@ -623,7 +656,7 @@ var AccountsResource = class {
623
656
  }
624
657
  /**
625
658
  * Buy seats on the workspace's active subscription. Returns the new
626
- * `seat_ids`; connect an account into one with `auth.intent({ seat_id })`.
659
+ * `seat_ids`; connect an account into one with `auth.intent({ seat_id, country, ... })`.
627
660
  *
628
661
  * Every call buys the `qty` it asks for, so a repeated call buys again.
629
662
  * The SDK never retries it for you. A
@@ -728,8 +761,30 @@ var AuthResource = class {
728
761
  * LinkedIn account does not hold throws
729
762
  * `CurviateError(code: "LINKEDIN_FEATURE_NOT_SUBSCRIBED")` (403); the remedy
730
763
  * is to activate the subscription on LinkedIn or to point `linkedin_premium`
731
- * at the premium the account really has. Pin a managed proxy with the
732
- * optional `country`/`ip`, or supply `proxy` to override it entirely.
764
+ * at the premium the account really has.
765
+ *
766
+ * **Connection location.** A NEW connect must say where LinkedIn sees the
767
+ * account connecting from, with exactly one of: `country` (a supported ISO
768
+ * code such as `"US"`; pick the one the owner normally signs in from), `ip`
769
+ * (a public IPv4 whose country is used) or your own `proxy`. Without one the
770
+ * API throws `CurviateError(code: "CONNECTION_LOCATION_REQUIRED")`, and the
771
+ * {@link AuthIntentBody} type refuses it at compile time. `country` and `ip`
772
+ * are strict by default: the connect fails with
773
+ * `CONNECTION_LOCATION_UNAVAILABLE` rather than use another country, unless
774
+ * you send `allow_country_fallback: true`. A reconnect may omit the location
775
+ * to keep the account's configured one. The account's `connection_location`
776
+ * says where it connects from; when a connect re-attached an account you
777
+ * already had and moved it, `connection_location.previous_country` names
778
+ * where it was.
779
+ *
780
+ * @example
781
+ * const result = await curviate.auth.intent({
782
+ * seat_id: "YOUR_SEAT_ID",
783
+ * auth_method: "credentials",
784
+ * credentials: { email: "YOUR_EMAIL", password: "YOUR_PASSWORD" },
785
+ * country: "US",
786
+ * });
787
+ * console.log(result.account_id);
733
788
  */
734
789
  intent(body) {
735
790
  return this.ctx.request({
@@ -777,7 +832,7 @@ var AuthResource = class {
777
832
  * @param body - optional `{ challenge }` for a `challenge_selection` checkpoint.
778
833
  *
779
834
  * @example
780
- * const cp = await curviate.auth.intent({ seat_id, auth_method: "credentials", credentials });
835
+ * const cp = await curviate.auth.intent({ seat_id, auth_method: "credentials", credentials, country: "US" });
781
836
  * if (cp.object === "checkpoint" && cp.challenge_type === "challenge_selection") {
782
837
  * const next = await curviate.auth.requestCheckpoint(cp.account_id!, { challenge: cp.challenges![0]!.id });
783
838
  * }
@@ -1387,15 +1442,15 @@ var PostsResource = class {
1387
1442
  * Get a single post. `GET /v1/{account_id}/posts/{post_id}`
1388
1443
  *
1389
1444
  * @param postId - the post's `id` as returned by {@link listUserPosts} or
1390
- * {@link create}. A bare numeric id (`7332661864792854528`), a URN
1391
- * (`urn:li:activity:N`, `urn:li:ugcPost:N`, `urn:li:share:N`), and a full
1392
- * share URL (`https://www.linkedin.com/posts/...` or
1445
+ * {@link create}, or a post search result's `id`. A bare numeric id
1446
+ * (`7332661864792854528`), a URN (`urn:li:activity:N`, `urn:li:ugcPost:N`,
1447
+ * `urn:li:share:N`), and a full post URL (`https://www.linkedin.com/posts/...`
1448
+ * with an `activity-`, `ugcPost-` or `share-` slug, or
1393
1449
  * `https://www.linkedin.com/feed/update/urn:li:activity:N`) all resolve to
1394
1450
  * the same post. Pass the value as-is; it is percent-encoded into the path
1395
1451
  * for you, so do not encode it yourself.
1396
1452
  *
1397
- * {@link listComments} and the reaction operations are stricter: they take
1398
- * the opaque `id` form only.
1453
+ * {@link listComments} and the reaction operations accept the same forms.
1399
1454
  */
1400
1455
  get(postId) {
1401
1456
  return this.ctx.request({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curviate/sdk",
3
- "version": "0.40.1",
3
+ "version": "0.41.0",
4
4
  "private": false,
5
5
  "description": "TypeScript SDK for the Curviate API.",
6
6
  "license": "MIT",