capdag 0.148.329 → 0.149.334

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/capdag.js CHANGED
@@ -3743,7 +3743,15 @@ class CartridgeRepoClient {
3743
3743
  }
3744
3744
 
3745
3745
  /**
3746
- * Update cache from registry data
3746
+ * Update cache from registry data.
3747
+ *
3748
+ * The cap-to-cartridges index keys on the *normalized* tagged-URN form
3749
+ * of each cap URN (parse via CapUrn.fromString, then take toString()).
3750
+ * This collapses textually different but canonically identical URNs
3751
+ * (different declared tag order) into the same bucket so that lookups
3752
+ * resolve regardless of how the requester phrased the URN. A cap URN
3753
+ * that fails to parse is a registry corruption: we throw rather than
3754
+ * silently keep the malformed string in the index.
3747
3755
  */
3748
3756
  updateCache(repoUrl, cartridges) {
3749
3757
  const cache = new CartridgeRepoCache(repoUrl);
@@ -3752,10 +3760,11 @@ class CartridgeRepoClient {
3752
3760
  cache.cartridges.set(cartridge.id, cartridge);
3753
3761
 
3754
3762
  for (const cap of cartridge.allCaps()) {
3755
- if (!cache.capToCartridges.has(cap.urn)) {
3756
- cache.capToCartridges.set(cap.urn, []);
3763
+ const normalized = CapUrn.fromString(cap.urn).toString();
3764
+ if (!cache.capToCartridges.has(normalized)) {
3765
+ cache.capToCartridges.set(normalized, []);
3757
3766
  }
3758
- cache.capToCartridges.get(cap.urn).push(cartridge.id);
3767
+ cache.capToCartridges.get(normalized).push(cartridge.id);
3759
3768
  }
3760
3769
  }
3761
3770
 
@@ -3798,20 +3807,36 @@ class CartridgeRepoClient {
3798
3807
  }
3799
3808
 
3800
3809
  /**
3801
- * Get cartridge suggestions for a cap URN
3810
+ * Get cartridge suggestions for a cap URN.
3811
+ *
3812
+ * `capUrn` is parsed via CapUrn.fromString; the parsed-and-
3813
+ * re-serialized form is the canonical key into the cap-to-cartridges
3814
+ * index. Inside each candidate cartridge we walk its caps via
3815
+ * `allCaps()` and match each one with `isEquivalent`, never with
3816
+ * string equality.
3802
3817
  */
3803
3818
  getSuggestionsForCap(capUrn) {
3819
+ const requested = CapUrn.fromString(capUrn);
3820
+ const normalized = requested.toString();
3804
3821
  const suggestions = [];
3805
3822
 
3806
3823
  for (const cache of this.caches.values()) {
3807
- const cartridgeIds = cache.capToCartridges.get(capUrn);
3824
+ const cartridgeIds = cache.capToCartridges.get(normalized);
3808
3825
  if (!cartridgeIds) continue;
3809
3826
 
3810
3827
  for (const cartridgeId of cartridgeIds) {
3811
3828
  const cartridge = cache.cartridges.get(cartridgeId);
3812
3829
  if (!cartridge) continue;
3813
3830
 
3814
- const capInfo = cartridge.allCaps().find(c => c.urn === capUrn);
3831
+ const capInfo = cartridge.allCaps().find(c => {
3832
+ let parsed;
3833
+ try {
3834
+ parsed = CapUrn.fromString(c.urn);
3835
+ } catch (_e) {
3836
+ return false;
3837
+ }
3838
+ return parsed.isEquivalent(requested);
3839
+ });
3815
3840
  if (!capInfo) continue;
3816
3841
 
3817
3842
  const pageUrl = cartridge.pageUrl || cache.repoUrl;
@@ -3820,7 +3845,7 @@ class CartridgeRepoClient {
3820
3845
  cartridgeId: cartridge.id,
3821
3846
  cartridgeName: cartridge.name,
3822
3847
  cartridgeDescription: cartridge.description,
3823
- capUrn: capUrn,
3848
+ capUrn: normalized,
3824
3849
  capTitle: capInfo.title,
3825
3850
  latestVersion: cartridge.version,
3826
3851
  repoUrl: cache.repoUrl,
@@ -4015,7 +4040,13 @@ class CartridgeRepoServer {
4015
4040
  }
4016
4041
 
4017
4042
  /**
4018
- * Search cartridges by query
4043
+ * Search cartridges by free-text query.
4044
+ *
4045
+ * Matches against cartridge name, description, tags, and cap titles.
4046
+ * Cap URN strings are not substring-matched: a cap URN is a tagged
4047
+ * identifier and substring matching against it is a category error.
4048
+ * Use `getCartridgesByCap` to look up cartridges that provide a
4049
+ * specific cap.
4019
4050
  */
4020
4051
  searchCartridges(query) {
4021
4052
  const cartridges = this.transformToCartridgeArray();
@@ -4026,7 +4057,7 @@ class CartridgeRepoServer {
4026
4057
  return p.name.toLowerCase().includes(lowerQuery) ||
4027
4058
  p.description.toLowerCase().includes(lowerQuery) ||
4028
4059
  p.tags.some(t => t.toLowerCase().includes(lowerQuery)) ||
4029
- allCaps.some(c => c.urn.toLowerCase().includes(lowerQuery) || c.title.toLowerCase().includes(lowerQuery));
4060
+ allCaps.some(c => c.title.toLowerCase().includes(lowerQuery));
4030
4061
  });
4031
4062
  }
4032
4063
 
@@ -4039,12 +4070,28 @@ class CartridgeRepoServer {
4039
4070
  }
4040
4071
 
4041
4072
  /**
4042
- * Get cartridges that provide a specific cap
4073
+ * Get cartridges that provide a specific cap.
4074
+ *
4075
+ * Both the request URN and each candidate cap URN are parsed via
4076
+ * CapUrn.fromString and matched with `isEquivalent` so caps declared
4077
+ * in any tag order resolve. A malformed input URN throws — there is
4078
+ * no fallback that compares the raw strings.
4043
4079
  */
4044
4080
  getCartridgesByCap(capUrn) {
4081
+ const requested = CapUrn.fromString(capUrn);
4045
4082
  const cartridges = this.transformToCartridgeArray();
4046
4083
  return cartridges.filter(p =>
4047
- (p.cap_groups || []).some(g => (g.caps || []).some(c => c.urn === capUrn))
4084
+ (p.cap_groups || []).some(g =>
4085
+ (g.caps || []).some(c => {
4086
+ let parsed;
4087
+ try {
4088
+ parsed = CapUrn.fromString(c.urn);
4089
+ } catch (_e) {
4090
+ return false;
4091
+ }
4092
+ return parsed.isEquivalent(requested);
4093
+ })
4094
+ )
4048
4095
  );
4049
4096
  }
4050
4097
  }
package/capdag.test.js CHANGED
@@ -1953,7 +1953,12 @@ function test331_cartridgeRepoClientGetSuggestions() {
1953
1953
 
1954
1954
  assert(suggestions.length === 1, 'Should find 1 suggestion');
1955
1955
  assert(suggestions[0].cartridgeId === 'pdfcartridge', 'Should suggest pdfcartridge');
1956
- assert(suggestions[0].capUrn === disbindCap, 'Should have correct cap URN');
1956
+ // The returned capUrn is the canonical (normalized) form. Compare via
1957
+ // tagged-URN equivalence rather than string equality so a tag-order
1958
+ // difference between the request and the canonical form is tolerated.
1959
+ const requested = CapUrn.fromString(disbindCap);
1960
+ const returned = CapUrn.fromString(suggestions[0].capUrn);
1961
+ assert(returned.isEquivalent(requested), 'Should have equivalent cap URN');
1957
1962
  assert(suggestions[0].capTitle === 'Disbind PDF', 'Should have cap title');
1958
1963
  }
1959
1964
 
package/package.json CHANGED
@@ -40,5 +40,5 @@
40
40
  "pretest": "npm run build:parser",
41
41
  "test": "node capdag.test.js"
42
42
  },
43
- "version": "0.148.329"
43
+ "version": "0.149.334"
44
44
  }