@aiqa/sdk 1.5.0-develop.2 → 1.5.0-develop.4

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.
@@ -257,7 +257,7 @@ declare abstract class IAiqaSdk {
257
257
  abstract connect(): void;
258
258
  abstract disconnect(): void;
259
259
  abstract on(eventName: string, callback: (...args: any[]) => any): void;
260
- abstract off(eventName: string): void;
260
+ abstract off(eventName: string, callback?: (...args: any[]) => any): void;
261
261
  abstract getApplication(): Promise<Application>;
262
262
  abstract addFact(fact: ApplicationFactInput): Promise<AddFactResult>;
263
263
  abstract flagFact(factId: string): Promise<FlagFactResult>;
@@ -274,6 +274,7 @@ declare class AiQaSdk implements IAiqaSdk {
274
274
  cachedApplication?: Application;
275
275
  internalListeners: Map<SdkEvent, Set<(...args: any[]) => void>>;
276
276
  internalEvents: Set<SdkEvent>;
277
+ private wrappersByEvent;
277
278
  constructor(applicationId: string, applicationSecret: string, url?: string);
278
279
  on(name: SdkEvent, callback: (...args: any[]) => any): void;
279
280
  off(name: SdkEvent, callback?: (...args: any[]) => any): void;
@@ -3396,7 +3396,7 @@ var compareVersions = (left, right) => {
3396
3396
  // package.json
3397
3397
  var package_default = {
3398
3398
  name: "@aiqa/sdk",
3399
- version: "1.5.0-develop.1",
3399
+ version: "1.5.0-develop.3",
3400
3400
  main: "dist/node/node.js",
3401
3401
  module: "dist/node/node.js",
3402
3402
  types: "dist/node/node.d.ts",
@@ -3478,9 +3478,43 @@ var package_default = {
3478
3478
  var SDK_VERSION = package_default.version ?? "0.0.1";
3479
3479
  var DEFAULT_URL = "ws://localhost:3025/ws";
3480
3480
  var DEFAULT_TIMEOUT_MS = 6e4;
3481
+ var RUNTIME = typeof window !== "undefined" && typeof window.document !== "undefined" ? "browser" : "node";
3482
+ var USER_AGENT = RUNTIME === "browser" ? typeof navigator !== "undefined" ? navigator.userAgent : "browser/unknown" : typeof process !== "undefined" ? `node ${process.version} ${process.platform}` : "node/unknown";
3483
+ function isThenable(value2) {
3484
+ return value2 !== null && typeof value2 === "object" && typeof value2.then === "function";
3485
+ }
3486
+ function wrapAckHandler(callback) {
3487
+ return (...args) => {
3488
+ const last = args[args.length - 1];
3489
+ const hasAck = typeof last === "function";
3490
+ const payload = hasAck ? args.slice(0, -1) : args;
3491
+ try {
3492
+ const handlerResult = callback(...payload);
3493
+ if (isThenable(handlerResult)) {
3494
+ handlerResult.then(void 0, (err) => {
3495
+ console.error("[AiQaSdk] async event handler rejected:", err);
3496
+ });
3497
+ }
3498
+ } catch (err) {
3499
+ console.error("[AiQaSdk] event handler threw:", err);
3500
+ } finally {
3501
+ if (hasAck) {
3502
+ try {
3503
+ last();
3504
+ } catch {
3505
+ }
3506
+ }
3507
+ }
3508
+ };
3509
+ }
3481
3510
  var AiQaSdk = class {
3482
3511
  constructor(applicationId, applicationSecret, url2) {
3483
3512
  this.socket = null;
3513
+ // event → originalCallback → Set<wrappedCallback> registered on
3514
+ // socket.io. A Set per (event, callback) so that subscribing the
3515
+ // same fn twice registers two wrappers and two off() calls clear
3516
+ // both.
3517
+ this.wrappersByEvent = /* @__PURE__ */ new Map();
3484
3518
  this.url = url2 ?? DEFAULT_URL;
3485
3519
  this.internalListeners = /* @__PURE__ */ new Map();
3486
3520
  this.internalEvents = /* @__PURE__ */ new Set(["authenticated"]);
@@ -3505,7 +3539,19 @@ var AiQaSdk = class {
3505
3539
  if (this.isManagerEvent(name)) {
3506
3540
  this.socket.io.on(name, callback);
3507
3541
  } else {
3508
- this.socket.on(name, callback);
3542
+ const wrapped = wrapAckHandler(callback);
3543
+ let wrappersByCallback = this.wrappersByEvent.get(name);
3544
+ if (!wrappersByCallback) {
3545
+ wrappersByCallback = /* @__PURE__ */ new Map();
3546
+ this.wrappersByEvent.set(name, wrappersByCallback);
3547
+ }
3548
+ let wrappers = wrappersByCallback.get(callback);
3549
+ if (!wrappers) {
3550
+ wrappers = /* @__PURE__ */ new Set();
3551
+ wrappersByCallback.set(callback, wrappers);
3552
+ }
3553
+ wrappers.add(wrapped);
3554
+ this.socket.on(name, wrapped);
3509
3555
  }
3510
3556
  }
3511
3557
  off(name, callback) {
@@ -3528,6 +3574,25 @@ var AiQaSdk = class {
3528
3574
  }
3529
3575
  if (this.isManagerEvent(name)) {
3530
3576
  this.socket.io.off(name, callback);
3577
+ return;
3578
+ }
3579
+ if (!callback) {
3580
+ this.socket.off(name);
3581
+ this.wrappersByEvent.delete(name);
3582
+ return;
3583
+ }
3584
+ const wrappersByCallback = this.wrappersByEvent.get(name);
3585
+ const wrappers = wrappersByCallback?.get(callback);
3586
+ if (wrappers && wrappers.size > 0) {
3587
+ const wrapped = wrappers.values().next().value;
3588
+ wrappers.delete(wrapped);
3589
+ this.socket.off(name, wrapped);
3590
+ if (wrappers.size === 0) {
3591
+ wrappersByCallback.delete(callback);
3592
+ if (wrappersByCallback.size === 0) {
3593
+ this.wrappersByEvent.delete(name);
3594
+ }
3595
+ }
3531
3596
  } else {
3532
3597
  this.socket.off(name, callback);
3533
3598
  }
@@ -3545,34 +3610,38 @@ var AiQaSdk = class {
3545
3610
  this.socket.on("connect", () => {
3546
3611
  this.authenticate();
3547
3612
  });
3548
- this.socket.on("app_version", (payload) => {
3549
- let versionRange = payload;
3550
- if (typeof payload === "string") {
3551
- try {
3552
- versionRange = JSON.parse(payload);
3553
- } catch (error) {
3554
- versionRange = payload;
3613
+ this.socket.on(
3614
+ "app_version",
3615
+ wrapAckHandler((payload) => {
3616
+ let versionRange = payload;
3617
+ if (typeof payload === "string") {
3618
+ try {
3619
+ versionRange = JSON.parse(payload);
3620
+ } catch (error) {
3621
+ versionRange = payload;
3622
+ }
3555
3623
  }
3556
- }
3557
- const minVersion = versionRange?.min;
3558
- const maxVersion = versionRange?.max;
3559
- if (minVersion || maxVersion) {
3560
- const tooLow = minVersion ? compareVersions(SDK_VERSION, minVersion) < 0 : false;
3561
- const tooHigh = maxVersion ? compareVersions(SDK_VERSION, maxVersion) > 0 : false;
3562
- if (tooLow || tooHigh) {
3563
- const error = new Error(
3564
- `SDK version ${SDK_VERSION} is not supported. Supported range: ${minVersion || "-"} to ${maxVersion || "-"}.`
3565
- );
3566
- this.socket.disconnect();
3567
- this.socket.emit("error", error);
3624
+ const minVersion = versionRange?.min;
3625
+ const maxVersion = versionRange?.max;
3626
+ if (minVersion || maxVersion) {
3627
+ const tooLow = minVersion ? compareVersions(SDK_VERSION, minVersion) < 0 : false;
3628
+ const tooHigh = maxVersion ? compareVersions(SDK_VERSION, maxVersion) > 0 : false;
3629
+ if (tooLow || tooHigh) {
3630
+ const error = new Error(
3631
+ `SDK version ${SDK_VERSION} is not supported. Supported range: ${minVersion || "-"} to ${maxVersion || "-"}.`
3632
+ );
3633
+ this.socket.disconnect();
3634
+ this.socket.emit("error", error);
3635
+ }
3568
3636
  }
3569
- }
3570
- });
3637
+ })
3638
+ );
3571
3639
  }
3572
3640
  disconnect() {
3573
3641
  if (this.socket) {
3574
3642
  this.socket.disconnect();
3575
3643
  }
3644
+ this.wrappersByEvent.clear();
3576
3645
  }
3577
3646
  sendMessage(method, data) {
3578
3647
  return new Promise((resolve, reject) => {
@@ -3669,7 +3738,10 @@ var AiQaSdk = class {
3669
3738
  try {
3670
3739
  const result = await this.sendMessage("AUTHENTICATE" /* AUTHENTICATE */, {
3671
3740
  applicationId: this.applicationId,
3672
- applicationSecretKey: this.applicationSecretKey
3741
+ applicationSecretKey: this.applicationSecretKey,
3742
+ sdkVersion: SDK_VERSION,
3743
+ runtime: RUNTIME,
3744
+ userAgent: USER_AGENT
3673
3745
  });
3674
3746
  const application = result && result.data !== void 0 ? result.data : result;
3675
3747
  this.cachedApplication = application;