@granular-software/sdk 0.4.33 → 0.4.34

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.
@@ -10866,6 +10866,50 @@ function computeEffectKey(effect) {
10866
10866
  }
10867
10867
  return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
10868
10868
  }
10869
+ function computeEffectVersionSelectorSpecificity(selector) {
10870
+ if (!selector || selector.mode === "all") {
10871
+ return 0;
10872
+ }
10873
+ if (selector.mode === "exact") {
10874
+ return 2;
10875
+ }
10876
+ return 1;
10877
+ }
10878
+ function matchesEffectVersionSelector(selector, buildVersionNumber) {
10879
+ if (!selector || selector.mode === "all") {
10880
+ return true;
10881
+ }
10882
+ if (typeof buildVersionNumber !== "number" || !Number.isFinite(buildVersionNumber)) {
10883
+ return false;
10884
+ }
10885
+ if (selector.mode === "exact") {
10886
+ return buildVersionNumber === selector.versionNumber;
10887
+ }
10888
+ if (selector.mode === "before") {
10889
+ return buildVersionNumber < selector.versionNumber;
10890
+ }
10891
+ return buildVersionNumber > selector.versionNumber;
10892
+ }
10893
+ function selectRegisteredEffect(effectMap, effectKey, buildVersionNumber) {
10894
+ let bestEffect;
10895
+ let bestSpecificity = Number.NEGATIVE_INFINITY;
10896
+ for (const effect of effectMap.values()) {
10897
+ if (computeEffectKey(effect) !== effectKey) {
10898
+ continue;
10899
+ }
10900
+ if (!matchesEffectVersionSelector(effect.versionSelector, buildVersionNumber)) {
10901
+ continue;
10902
+ }
10903
+ const specificity = computeEffectVersionSelectorSpecificity(
10904
+ effect.versionSelector
10905
+ );
10906
+ if (!bestEffect || specificity > bestSpecificity) {
10907
+ bestEffect = effect;
10908
+ bestSpecificity = specificity;
10909
+ }
10910
+ }
10911
+ return bestEffect;
10912
+ }
10869
10913
  function normalizeEffectBehaviors(value) {
10870
10914
  return normalizeEffectBehaviorSummary(
10871
10915
  value
@@ -10886,9 +10930,17 @@ function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
10886
10930
  return void 0;
10887
10931
  }
10888
10932
  if (reverseHandler.includes(":")) {
10889
- return effectMap.get(reverseHandler);
10933
+ return selectRegisteredEffect(
10934
+ effectMap,
10935
+ reverseHandler,
10936
+ request.context?.buildVersionNumber
10937
+ );
10890
10938
  }
10891
- const directMatch = effectMap.get(reverseHandler);
10939
+ const directMatch = selectRegisteredEffect(
10940
+ effectMap,
10941
+ reverseHandler,
10942
+ request.context?.buildVersionNumber
10943
+ );
10892
10944
  if (directMatch) {
10893
10945
  return directMatch;
10894
10946
  }
@@ -10903,7 +10955,11 @@ function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
10903
10955
  })
10904
10956
  ];
10905
10957
  for (const candidateKey of candidateKeys) {
10906
- const candidate = effectMap.get(candidateKey);
10958
+ const candidate = selectRegisteredEffect(
10959
+ effectMap,
10960
+ candidateKey,
10961
+ request.context?.buildVersionNumber
10962
+ );
10907
10963
  if (candidate) {
10908
10964
  return candidate;
10909
10965
  }
@@ -10939,7 +10995,11 @@ function resolveHandlerForMode(effectMap, effect, request) {
10939
10995
  return { effect, mode, handler: effect.handler };
10940
10996
  }
10941
10997
  async function invokeRegisteredEffect(effectMap, request) {
10942
- const effect = effectMap.get(request.effectKey);
10998
+ const effect = selectRegisteredEffect(
10999
+ effectMap,
11000
+ request.effectKey,
11001
+ request.context?.buildVersionNumber
11002
+ );
10943
11003
  if (!effect) {
10944
11004
  throw new Error(`Effect handler not found: ${request.effectKey}`);
10945
11005
  }
@@ -12198,6 +12258,17 @@ function computeEffectKey2(effect) {
12198
12258
  }
12199
12259
  return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
12200
12260
  }
12261
+ function computeEffectVersionSelectorKey(selector) {
12262
+ if (!selector || selector.mode === "all") {
12263
+ return "all";
12264
+ }
12265
+ return `${selector.mode}:${selector.versionNumber}`;
12266
+ }
12267
+ function computeEffectRegistrationKey(effect) {
12268
+ return `${computeEffectKey2(effect)}@${computeEffectVersionSelectorKey(
12269
+ effect.versionSelector
12270
+ )}`;
12271
+ }
12201
12272
  function buildEffectHostUrl(apiUrl, sandboxId, effectClientId, clientId) {
12202
12273
  const url = new URL(apiUrl);
12203
12274
  if (url.pathname.endsWith("/granular/ws/connect")) {
@@ -13719,7 +13790,7 @@ var Granular = class _Granular {
13719
13790
  onUnexpectedClose;
13720
13791
  onReconnectError;
13721
13792
  debugHttp = process.env.GRANULAR_DEBUG_HTTP === "1";
13722
- /** Sandbox-level effect registry: sandboxId → (effectKey → ToolWithHandler) */
13793
+ /** Sandbox-level effect registry: sandboxId → (effectKey@selector → ToolWithHandler) */
13723
13794
  sandboxEffects = /* @__PURE__ */ new Map();
13724
13795
  /** Live sandbox-scoped effect hosts keyed by sandboxId */
13725
13796
  sandboxEffectHosts = /* @__PURE__ */ new Map();
@@ -14138,7 +14209,8 @@ var Granular = class _Granular {
14138
14209
  provenance: effect.provenance || { source: "custom" },
14139
14210
  tags: effect.tags,
14140
14211
  className: effect.className,
14141
- static: effect.static
14212
+ static: effect.static,
14213
+ versionSelector: effect.versionSelector
14142
14214
  };
14143
14215
  }
14144
14216
  async publishSandboxEffectCatalog(host) {
@@ -14326,7 +14398,10 @@ var Granular = class _Granular {
14326
14398
  async registerEffect(sandboxNameOrId, effect) {
14327
14399
  const sandbox = await this.findOrCreateSandbox(sandboxNameOrId);
14328
14400
  const sandboxId = sandbox.sandboxId;
14329
- this.getSandboxEffectMap(sandboxId).set(computeEffectKey2(effect), effect);
14401
+ this.getSandboxEffectMap(sandboxId).set(
14402
+ computeEffectRegistrationKey(effect),
14403
+ effect
14404
+ );
14330
14405
  await this.syncSandboxEffectCatalog(sandboxId);
14331
14406
  }
14332
14407
  /**
@@ -14339,7 +14414,7 @@ var Granular = class _Granular {
14339
14414
  const sandboxId = sandbox.sandboxId;
14340
14415
  const map = this.getSandboxEffectMap(sandboxId);
14341
14416
  for (const effect of effects) {
14342
- map.set(computeEffectKey2(effect), effect);
14417
+ map.set(computeEffectRegistrationKey(effect), effect);
14343
14418
  }
14344
14419
  await this.syncSandboxEffectCatalog(sandboxId);
14345
14420
  }
@@ -14357,7 +14432,7 @@ var Granular = class _Granular {
14357
14432
  return;
14358
14433
  }
14359
14434
  const nextEntries = Array.from(currentMap.entries()).filter(
14360
- ([effectKey, effect]) => effectKey !== name && effect.name !== name
14435
+ ([, effect]) => computeEffectKey2(effect) !== name && effect.name !== name
14361
14436
  );
14362
14437
  if (nextEntries.length === currentMap.size) {
14363
14438
  return;