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