perspectapi-ts-sdk 6.4.0 → 6.5.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.d.mts CHANGED
@@ -1967,7 +1967,7 @@ declare class SiteUsersV2Client extends BaseV2Client {
1967
1967
  /** Update the authenticated user's own fields. */
1968
1968
  updateMe(siteName: string, data: V2SiteUserMeUpdateParams): Promise<V2SiteUser>;
1969
1969
  /** Fetch the profile KV map as a dedicated `site_user_profile` envelope. */
1970
- getProfile(siteName: string): Promise<V2SiteUserProfile>;
1970
+ getProfile(siteName: string, cachePolicy?: CachePolicy): Promise<V2SiteUserProfile>;
1971
1971
  /**
1972
1972
  * Set a single profile key. The value is persisted verbatim — callers wanting
1973
1973
  * structured data should JSON-stringify their value first.
@@ -2104,7 +2104,7 @@ declare class WebhooksV2Client extends BaseV2Client {
2104
2104
 
2105
2105
  declare class SubscriptionsV2Client extends BaseV2Client {
2106
2106
  /** List all subscriptions for the authenticated user. */
2107
- listMySubscriptions(siteName: string): Promise<V2List<V2SiteUserSubscription>>;
2107
+ listMySubscriptions(siteName: string, cachePolicy?: CachePolicy): Promise<V2List<V2SiteUserSubscription>>;
2108
2108
  /** Pause a subscription. */
2109
2109
  pauseSubscription(siteName: string, subId: string, params?: V2SubscriptionPauseParams): Promise<V2SiteUserSubscription>;
2110
2110
  /** Resume a paused subscription. */
@@ -2114,7 +2114,7 @@ declare class SubscriptionsV2Client extends BaseV2Client {
2114
2114
  /** Change the plan (price) of a subscription. */
2115
2115
  changeSubscriptionPlan(siteName: string, subId: string, params: V2SubscriptionChangePlanParams): Promise<V2SiteUserSubscription>;
2116
2116
  /** List subscriptions for a specific user (admin). */
2117
- listUserSubscriptions(siteName: string, userId: string): Promise<V2List<V2SiteUserSubscription>>;
2117
+ listUserSubscriptions(siteName: string, userId: string, cachePolicy?: CachePolicy): Promise<V2List<V2SiteUserSubscription>>;
2118
2118
  /** Pause a user's subscription (admin). */
2119
2119
  pauseUserSubscription(siteName: string, userId: string, subId: string, params?: V2SubscriptionPauseParams): Promise<V2SiteUserSubscription>;
2120
2120
  /** Resume a user's paused subscription (admin). */
package/dist/index.d.ts CHANGED
@@ -1967,7 +1967,7 @@ declare class SiteUsersV2Client extends BaseV2Client {
1967
1967
  /** Update the authenticated user's own fields. */
1968
1968
  updateMe(siteName: string, data: V2SiteUserMeUpdateParams): Promise<V2SiteUser>;
1969
1969
  /** Fetch the profile KV map as a dedicated `site_user_profile` envelope. */
1970
- getProfile(siteName: string): Promise<V2SiteUserProfile>;
1970
+ getProfile(siteName: string, cachePolicy?: CachePolicy): Promise<V2SiteUserProfile>;
1971
1971
  /**
1972
1972
  * Set a single profile key. The value is persisted verbatim — callers wanting
1973
1973
  * structured data should JSON-stringify their value first.
@@ -2104,7 +2104,7 @@ declare class WebhooksV2Client extends BaseV2Client {
2104
2104
 
2105
2105
  declare class SubscriptionsV2Client extends BaseV2Client {
2106
2106
  /** List all subscriptions for the authenticated user. */
2107
- listMySubscriptions(siteName: string): Promise<V2List<V2SiteUserSubscription>>;
2107
+ listMySubscriptions(siteName: string, cachePolicy?: CachePolicy): Promise<V2List<V2SiteUserSubscription>>;
2108
2108
  /** Pause a subscription. */
2109
2109
  pauseSubscription(siteName: string, subId: string, params?: V2SubscriptionPauseParams): Promise<V2SiteUserSubscription>;
2110
2110
  /** Resume a paused subscription. */
@@ -2114,7 +2114,7 @@ declare class SubscriptionsV2Client extends BaseV2Client {
2114
2114
  /** Change the plan (price) of a subscription. */
2115
2115
  changeSubscriptionPlan(siteName: string, subId: string, params: V2SubscriptionChangePlanParams): Promise<V2SiteUserSubscription>;
2116
2116
  /** List subscriptions for a specific user (admin). */
2117
- listUserSubscriptions(siteName: string, userId: string): Promise<V2List<V2SiteUserSubscription>>;
2117
+ listUserSubscriptions(siteName: string, userId: string, cachePolicy?: CachePolicy): Promise<V2List<V2SiteUserSubscription>>;
2118
2118
  /** Pause a user's subscription (admin). */
2119
2119
  pauseUserSubscription(siteName: string, userId: string, subId: string, params?: V2SubscriptionPauseParams): Promise<V2SiteUserSubscription>;
2120
2120
  /** Resume a user's paused subscription (admin). */
package/dist/index.js CHANGED
@@ -1038,9 +1038,11 @@ var SiteUsersV2Client = class extends BaseV2Client {
1038
1038
  );
1039
1039
  }
1040
1040
  /** Fetch the profile KV map as a dedicated `site_user_profile` envelope. */
1041
- async getProfile(siteName) {
1041
+ async getProfile(siteName, cachePolicy) {
1042
1042
  return this.getOne(
1043
- this.sitePath(siteName, "users", "me/profile")
1043
+ this.sitePath(siteName, "users", "me/profile"),
1044
+ void 0,
1045
+ cachePolicy
1044
1046
  );
1045
1047
  }
1046
1048
  /**
@@ -1258,9 +1260,11 @@ var WebhooksV2Client = class extends BaseV2Client {
1258
1260
  var SubscriptionsV2Client = class extends BaseV2Client {
1259
1261
  // --- Authenticated "me" endpoints (site-user JWT) ---
1260
1262
  /** List all subscriptions for the authenticated user. */
1261
- async listMySubscriptions(siteName) {
1263
+ async listMySubscriptions(siteName, cachePolicy) {
1262
1264
  return this.getList(
1263
- this.sitePath(siteName, "users", "me/subscriptions")
1265
+ this.sitePath(siteName, "users", "me/subscriptions"),
1266
+ void 0,
1267
+ cachePolicy
1264
1268
  );
1265
1269
  }
1266
1270
  /** Pause a subscription. */
@@ -1292,9 +1296,11 @@ var SubscriptionsV2Client = class extends BaseV2Client {
1292
1296
  }
1293
1297
  // --- Admin endpoints (API key) ---
1294
1298
  /** List subscriptions for a specific user (admin). */
1295
- async listUserSubscriptions(siteName, userId) {
1299
+ async listUserSubscriptions(siteName, userId, cachePolicy) {
1296
1300
  return this.getList(
1297
- this.sitePath(siteName, "users", `${userId}/subscriptions`)
1301
+ this.sitePath(siteName, "users", `${userId}/subscriptions`),
1302
+ void 0,
1303
+ cachePolicy
1298
1304
  );
1299
1305
  }
1300
1306
  /** Pause a user's subscription (admin). */
@@ -4253,15 +4259,16 @@ function createPerspectAb(options) {
4253
4259
  `${VID_COOKIE}=${visitorId}; Path=/; Max-Age=${VID_COOKIE_MAX_AGE}; SameSite=Lax; Secure; HttpOnly`
4254
4260
  );
4255
4261
  }
4262
+ const isBot = classifyBotFromCfRequest(request);
4256
4263
  const config = await getConfig(options.cache, apiKey, siteName, baseUrl);
4257
- return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId), responseHeaders };
4264
+ return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId, isBot), responseHeaders };
4258
4265
  },
4259
4266
  async refreshConfig() {
4260
4267
  await fetchAndStoreConfig(options.cache, apiKey, siteName, baseUrl);
4261
4268
  }
4262
4269
  };
4263
4270
  }
4264
- function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4271
+ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId, isBot) {
4265
4272
  return {
4266
4273
  async getVariant(flagKey) {
4267
4274
  const flag = config.flags[flagKey];
@@ -4281,6 +4288,7 @@ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4281
4288
  version: flag.currentVersion,
4282
4289
  variant: assigned,
4283
4290
  visitorId,
4291
+ isBot,
4284
4292
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, "exposure"),
4285
4293
  ts: Math.floor(Date.now() / 1e3)
4286
4294
  });
@@ -4301,6 +4309,7 @@ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4301
4309
  version: flag.currentVersion,
4302
4310
  variant: assigned,
4303
4311
  visitorId,
4312
+ isBot,
4304
4313
  event,
4305
4314
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, event),
4306
4315
  ts: Math.floor(Date.now() / 1e3),
@@ -4339,6 +4348,13 @@ function emit(apiKey, baseUrl, ctx, body) {
4339
4348
  }).then(() => void 0).catch(() => void 0);
4340
4349
  if (ctx) ctx.waitUntil(task);
4341
4350
  }
4351
+ function classifyBotFromCfRequest(request) {
4352
+ const cf = request.cf;
4353
+ if (!cf?.botManagement) return false;
4354
+ if (cf.botManagement.verifiedBot) return true;
4355
+ if (typeof cf.botManagement.score === "number") return cf.botManagement.score < 30;
4356
+ return false;
4357
+ }
4342
4358
  function readOrMintVid(request) {
4343
4359
  const cookie = request.headers.get("cookie") ?? "";
4344
4360
  const match = cookie.match(/(?:^|; )perspect_vid=([^;]+)/);
package/dist/index.mjs CHANGED
@@ -962,9 +962,11 @@ var SiteUsersV2Client = class extends BaseV2Client {
962
962
  );
963
963
  }
964
964
  /** Fetch the profile KV map as a dedicated `site_user_profile` envelope. */
965
- async getProfile(siteName) {
965
+ async getProfile(siteName, cachePolicy) {
966
966
  return this.getOne(
967
- this.sitePath(siteName, "users", "me/profile")
967
+ this.sitePath(siteName, "users", "me/profile"),
968
+ void 0,
969
+ cachePolicy
968
970
  );
969
971
  }
970
972
  /**
@@ -1182,9 +1184,11 @@ var WebhooksV2Client = class extends BaseV2Client {
1182
1184
  var SubscriptionsV2Client = class extends BaseV2Client {
1183
1185
  // --- Authenticated "me" endpoints (site-user JWT) ---
1184
1186
  /** List all subscriptions for the authenticated user. */
1185
- async listMySubscriptions(siteName) {
1187
+ async listMySubscriptions(siteName, cachePolicy) {
1186
1188
  return this.getList(
1187
- this.sitePath(siteName, "users", "me/subscriptions")
1189
+ this.sitePath(siteName, "users", "me/subscriptions"),
1190
+ void 0,
1191
+ cachePolicy
1188
1192
  );
1189
1193
  }
1190
1194
  /** Pause a subscription. */
@@ -1216,9 +1220,11 @@ var SubscriptionsV2Client = class extends BaseV2Client {
1216
1220
  }
1217
1221
  // --- Admin endpoints (API key) ---
1218
1222
  /** List subscriptions for a specific user (admin). */
1219
- async listUserSubscriptions(siteName, userId) {
1223
+ async listUserSubscriptions(siteName, userId, cachePolicy) {
1220
1224
  return this.getList(
1221
- this.sitePath(siteName, "users", `${userId}/subscriptions`)
1225
+ this.sitePath(siteName, "users", `${userId}/subscriptions`),
1226
+ void 0,
1227
+ cachePolicy
1222
1228
  );
1223
1229
  }
1224
1230
  /** Pause a user's subscription (admin). */
@@ -4177,15 +4183,16 @@ function createPerspectAb(options) {
4177
4183
  `${VID_COOKIE}=${visitorId}; Path=/; Max-Age=${VID_COOKIE_MAX_AGE}; SameSite=Lax; Secure; HttpOnly`
4178
4184
  );
4179
4185
  }
4186
+ const isBot = classifyBotFromCfRequest(request);
4180
4187
  const config = await getConfig(options.cache, apiKey, siteName, baseUrl);
4181
- return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId), responseHeaders };
4188
+ return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId, isBot), responseHeaders };
4182
4189
  },
4183
4190
  async refreshConfig() {
4184
4191
  await fetchAndStoreConfig(options.cache, apiKey, siteName, baseUrl);
4185
4192
  }
4186
4193
  };
4187
4194
  }
4188
- function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4195
+ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId, isBot) {
4189
4196
  return {
4190
4197
  async getVariant(flagKey) {
4191
4198
  const flag = config.flags[flagKey];
@@ -4205,6 +4212,7 @@ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4205
4212
  version: flag.currentVersion,
4206
4213
  variant: assigned,
4207
4214
  visitorId,
4215
+ isBot,
4208
4216
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, "exposure"),
4209
4217
  ts: Math.floor(Date.now() / 1e3)
4210
4218
  });
@@ -4225,6 +4233,7 @@ function buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId) {
4225
4233
  version: flag.currentVersion,
4226
4234
  variant: assigned,
4227
4235
  visitorId,
4236
+ isBot,
4228
4237
  event,
4229
4238
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, event),
4230
4239
  ts: Math.floor(Date.now() / 1e3),
@@ -4263,6 +4272,13 @@ function emit(apiKey, baseUrl, ctx, body) {
4263
4272
  }).then(() => void 0).catch(() => void 0);
4264
4273
  if (ctx) ctx.waitUntil(task);
4265
4274
  }
4275
+ function classifyBotFromCfRequest(request) {
4276
+ const cf = request.cf;
4277
+ if (!cf?.botManagement) return false;
4278
+ if (cf.botManagement.verifiedBot) return true;
4279
+ if (typeof cf.botManagement.score === "number") return cf.botManagement.score < 30;
4280
+ return false;
4281
+ }
4266
4282
  function readOrMintVid(request) {
4267
4283
  const cookie = request.headers.get("cookie") ?? "";
4268
4284
  const match = cookie.match(/(?:^|; )perspect_vid=([^;]+)/);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perspectapi-ts-sdk",
3
- "version": "6.4.0",
3
+ "version": "6.5.0",
4
4
  "description": "TypeScript SDK for PerspectAPI - Cloudflare Workers compatible",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -88,8 +88,9 @@ export function createPerspectAb(options: CreatePerspectAbOptions): PerspectAb {
88
88
  `${VID_COOKIE}=${visitorId}; Path=/; Max-Age=${VID_COOKIE_MAX_AGE}; SameSite=Lax; Secure; HttpOnly`,
89
89
  );
90
90
  }
91
+ const isBot = classifyBotFromCfRequest(request);
91
92
  const config = await getConfig(options.cache, apiKey, siteName, baseUrl);
92
- return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId), responseHeaders };
93
+ return { ab: buildAbClient(apiKey, siteName, baseUrl, ctx, config, visitorId, isBot), responseHeaders };
93
94
  },
94
95
 
95
96
  async refreshConfig(): Promise<void> {
@@ -109,6 +110,7 @@ function buildAbClient(
109
110
  ctx: { waitUntil(p: Promise<unknown>): void } | undefined,
110
111
  config: AbConfigBlob,
111
112
  visitorId: string,
113
+ isBot: boolean,
112
114
  ): AbClient {
113
115
  return {
114
116
  async getVariant(flagKey: string): Promise<AbVariantResult> {
@@ -129,6 +131,7 @@ function buildAbClient(
129
131
  version: flag.currentVersion,
130
132
  variant: assigned,
131
133
  visitorId,
134
+ isBot,
132
135
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, 'exposure'),
133
136
  ts: Math.floor(Date.now() / 1000),
134
137
  });
@@ -150,6 +153,7 @@ function buildAbClient(
150
153
  version: flag.currentVersion,
151
154
  variant: assigned,
152
155
  visitorId,
156
+ isBot,
153
157
  event,
154
158
  dedup: await dedupFor(visitorId, flagKey, flag.currentVersion, assigned, event),
155
159
  ts: Math.floor(Date.now() / 1000),
@@ -209,6 +213,7 @@ interface EventBody {
209
213
  version: number;
210
214
  variant: string;
211
215
  visitorId: string;
216
+ isBot: boolean;
212
217
  dedup: string;
213
218
  ts: number;
214
219
  event?: string;
@@ -231,6 +236,21 @@ function emit(
231
236
  if (ctx) ctx.waitUntil(task);
232
237
  }
233
238
 
239
+ // ---------------------------------------------------------------------------
240
+ // Bot classification from CF request metadata
241
+ // ---------------------------------------------------------------------------
242
+
243
+ // CF Workers attach botManagement to the request object at runtime. The SDK
244
+ // uses the standard Request type, so we access it via an unsafe cast rather
245
+ // than importing CF-specific types as a peer dependency.
246
+ function classifyBotFromCfRequest(request: Request): boolean {
247
+ const cf = (request as unknown as { cf?: { botManagement?: { score?: number; verifiedBot?: boolean } } }).cf;
248
+ if (!cf?.botManagement) return false;
249
+ if (cf.botManagement.verifiedBot) return true;
250
+ if (typeof cf.botManagement.score === 'number') return cf.botManagement.score < 30;
251
+ return false;
252
+ }
253
+
234
254
  // ---------------------------------------------------------------------------
235
255
  // Visitor ID
236
256
  // ---------------------------------------------------------------------------
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import { BaseV2Client } from './base-v2-client';
12
+ import type { CachePolicy } from '../../cache/types';
12
13
  import type {
13
14
  V2SiteUser,
14
15
  V2SiteUserUpdateParams,
@@ -91,9 +92,11 @@ export class SiteUsersV2Client extends BaseV2Client {
91
92
  }
92
93
 
93
94
  /** Fetch the profile KV map as a dedicated `site_user_profile` envelope. */
94
- async getProfile(siteName: string): Promise<V2SiteUserProfile> {
95
+ async getProfile(siteName: string, cachePolicy?: CachePolicy): Promise<V2SiteUserProfile> {
95
96
  return this.getOne<V2SiteUserProfile>(
96
97
  this.sitePath(siteName, 'users', 'me/profile'),
98
+ undefined,
99
+ cachePolicy,
97
100
  );
98
101
  }
99
102
 
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { BaseV2Client } from './base-v2-client';
10
+ import type { CachePolicy } from '../../cache/types';
10
11
  import type {
11
12
  V2SiteUserSubscription,
12
13
  V2SubscriptionPauseParams,
@@ -23,9 +24,12 @@ export class SubscriptionsV2Client extends BaseV2Client {
23
24
  /** List all subscriptions for the authenticated user. */
24
25
  async listMySubscriptions(
25
26
  siteName: string,
27
+ cachePolicy?: CachePolicy,
26
28
  ): Promise<V2List<V2SiteUserSubscription>> {
27
29
  return this.getList<V2SiteUserSubscription>(
28
30
  this.sitePath(siteName, 'users', 'me/subscriptions'),
31
+ undefined,
32
+ cachePolicy,
29
33
  );
30
34
  }
31
35
 
@@ -81,9 +85,12 @@ export class SubscriptionsV2Client extends BaseV2Client {
81
85
  async listUserSubscriptions(
82
86
  siteName: string,
83
87
  userId: string,
88
+ cachePolicy?: CachePolicy,
84
89
  ): Promise<V2List<V2SiteUserSubscription>> {
85
90
  return this.getList<V2SiteUserSubscription>(
86
91
  this.sitePath(siteName, 'users', `${userId}/subscriptions`),
92
+ undefined,
93
+ cachePolicy,
87
94
  );
88
95
  }
89
96