@resourcexjs/registry 1.1.0 → 1.3.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/README.md CHANGED
@@ -175,9 +175,29 @@ await registry.delete("localhost/my-prompt.text@1.0.0");
175
175
 
176
176
  Publish resource to remote registry (TODO: not yet implemented).
177
177
 
178
- #### `search(query: string): Promise<RXL[]>`
178
+ #### `search(options?): Promise<RXL[]>`
179
179
 
180
- Search for resources (TODO: not yet implemented).
180
+ Search for resources in local registry.
181
+
182
+ **Parameters:**
183
+
184
+ - `options?: SearchOptions`
185
+ - `query?: string` - Filter by locator substring
186
+ - `limit?: number` - Max results to return
187
+ - `offset?: number` - Skip first N results
188
+
189
+ **Returns**: `Promise<RXL[]>` - Array of matching locators
190
+
191
+ ```typescript
192
+ // Search by name
193
+ const results = await registry.search({ query: "assistant" });
194
+
195
+ // With pagination
196
+ const page = await registry.search({ query: "prompt", limit: 10, offset: 20 });
197
+
198
+ // List all resources
199
+ const all = await registry.search();
200
+ ```
181
201
 
182
202
  ## Storage Structure
183
203
 
package/dist/index.d.ts CHANGED
@@ -15,6 +15,23 @@ interface RegistryConfig {
15
15
  types?: ResourceType[];
16
16
  }
17
17
  /**
18
+ * Search options for querying resources.
19
+ */
20
+ interface SearchOptions {
21
+ /**
22
+ * Search query string (matches against name, domain, path).
23
+ */
24
+ query?: string;
25
+ /**
26
+ * Maximum number of results to return.
27
+ */
28
+ limit?: number;
29
+ /**
30
+ * Number of results to skip (for pagination).
31
+ */
32
+ offset?: number;
33
+ }
34
+ /**
18
35
  * Registry interface for resource storage and retrieval.
19
36
  */
20
37
  interface Registry {
@@ -40,9 +57,11 @@ interface Registry {
40
57
  */
41
58
  delete(locator: string): Promise<void>;
42
59
  /**
43
- * Search for resources matching query.
60
+ * Search for resources matching options.
61
+ * @param options - Search options (query, limit, offset)
62
+ * @returns Array of matching resource locators
44
63
  */
45
- search(query: string): Promise<RXL[]>;
64
+ search(options?: SearchOptions): Promise<RXL[]>;
46
65
  }
47
66
  import { ResourceXError } from "@resourcexjs/core";
48
67
  /**
@@ -70,11 +89,16 @@ declare class ARPRegistry implements Registry {
70
89
  resolve(locator: string): Promise<RXR2>;
71
90
  exists(locator: string): Promise<boolean>;
72
91
  delete(locator: string): Promise<void>;
73
- search(_query: string): Promise<RXL2[]>;
92
+ search(options?: SearchOptions): Promise<RXL2[]>;
93
+ /**
94
+ * Parse a file entry path to RXL.
95
+ * Entry format: {domain}/{path}/{name}.{type}@{version}/manifest.json
96
+ */
97
+ private parseEntryToRXL;
74
98
  }
75
99
  /**
76
100
  * Create a registry instance.
77
101
  * Uses ARP protocol for storage operations.
78
102
  */
79
103
  declare function createRegistry(config?: RegistryConfig): Registry;
80
- export { createRegistry, RegistryError, RegistryConfig, Registry, ARPRegistry };
104
+ export { createRegistry, SearchOptions, RegistryError, RegistryConfig, Registry, ARPRegistry };
package/dist/index.js CHANGED
@@ -1303,8 +1303,10 @@ var textSerializer = {
1303
1303
  };
1304
1304
  var textResolver = {
1305
1305
  async resolve(rxr) {
1306
- const buffer = await rxr.content.file("content");
1307
- return buffer.toString("utf-8");
1306
+ return async () => {
1307
+ const buffer = await rxr.content.file("content");
1308
+ return buffer.toString("utf-8");
1309
+ };
1308
1310
  }
1309
1311
  };
1310
1312
  var textType = {
@@ -1328,8 +1330,10 @@ var jsonSerializer = {
1328
1330
  };
1329
1331
  var jsonResolver = {
1330
1332
  async resolve(rxr) {
1331
- const buffer = await rxr.content.file("content");
1332
- return JSON.parse(buffer.toString("utf-8"));
1333
+ return async () => {
1334
+ const buffer = await rxr.content.file("content");
1335
+ return JSON.parse(buffer.toString("utf-8"));
1336
+ };
1333
1337
  }
1334
1338
  };
1335
1339
  var jsonType = {
@@ -1353,7 +1357,9 @@ var binarySerializer = {
1353
1357
  };
1354
1358
  var binaryResolver = {
1355
1359
  async resolve(rxr) {
1356
- return rxr.content.file("content");
1360
+ return async () => {
1361
+ return rxr.content.file("content");
1362
+ };
1357
1363
  }
1358
1364
  };
1359
1365
  var binaryType = {
@@ -1444,8 +1450,8 @@ class TypeHandlerChain {
1444
1450
  var globalTypeHandlerChain = TypeHandlerChain.getInstance();
1445
1451
 
1446
1452
  // ../arp/dist/index.js
1447
- import { readFile, writeFile, readdir, mkdir, rm, access, stat as fsStat } from "node:fs/promises";
1448
- import { resolve, dirname } from "node:path";
1453
+ import { readFile, writeFile, readdir, mkdir, rm, access, stat } from "node:fs/promises";
1454
+ import { resolve, dirname, join } from "node:path";
1449
1455
 
1450
1456
  class ARPError extends Error {
1451
1457
  constructor(message, options) {
@@ -1492,25 +1498,26 @@ class ARL {
1492
1498
  this.location = location;
1493
1499
  this.resolver = resolver;
1494
1500
  }
1495
- createContext() {
1501
+ createContext(params) {
1496
1502
  return {
1497
1503
  url: this.toString(),
1498
1504
  semantic: this.semantic,
1499
1505
  transport: this.transport,
1500
1506
  location: this.location,
1501
- timestamp: new Date
1507
+ timestamp: new Date,
1508
+ params
1502
1509
  };
1503
1510
  }
1504
- async resolve() {
1511
+ async resolve(params) {
1505
1512
  const transport = this.resolver.getTransportHandler(this.transport);
1506
1513
  const semantic = this.resolver.getSemanticHandler(this.semantic);
1507
- const context = this.createContext();
1514
+ const context = this.createContext(params);
1508
1515
  return semantic.resolve(transport, this.location, context);
1509
1516
  }
1510
- async deposit(data) {
1517
+ async deposit(data, params) {
1511
1518
  const transport = this.resolver.getTransportHandler(this.transport);
1512
1519
  const semantic = this.resolver.getSemanticHandler(this.semantic);
1513
- const context = this.createContext();
1520
+ const context = this.createContext(params);
1514
1521
  if (!semantic.deposit) {
1515
1522
  throw new SemanticError(`Semantic "${semantic.name}" does not support deposit operation`, this.semantic);
1516
1523
  }
@@ -1523,15 +1530,7 @@ class ARL {
1523
1530
  if (semantic.exists) {
1524
1531
  return semantic.exists(transport, this.location, context);
1525
1532
  }
1526
- if (transport.exists) {
1527
- return transport.exists(this.location);
1528
- }
1529
- try {
1530
- await transport.read(this.location);
1531
- return true;
1532
- } catch {
1533
- return false;
1534
- }
1533
+ return transport.exists(this.location);
1535
1534
  }
1536
1535
  async delete() {
1537
1536
  const transport = this.resolver.getTransportHandler(this.transport);
@@ -1540,9 +1539,6 @@ class ARL {
1540
1539
  if (semantic.delete) {
1541
1540
  return semantic.delete(transport, this.location, context);
1542
1541
  }
1543
- if (!transport.delete) {
1544
- throw new SemanticError(`Neither semantic "${semantic.name}" nor transport "${transport.name}" supports delete operation`, this.semantic);
1545
- }
1546
1542
  await transport.delete(this.location);
1547
1543
  }
1548
1544
  toString() {
@@ -1552,57 +1548,88 @@ class ARL {
1552
1548
 
1553
1549
  class FileTransportHandler {
1554
1550
  name = "file";
1555
- capabilities = {
1556
- canRead: true,
1557
- canWrite: true,
1558
- canList: true,
1559
- canDelete: true,
1560
- canStat: true
1561
- };
1562
1551
  resolvePath(location) {
1563
1552
  return resolve(process.cwd(), location);
1564
1553
  }
1565
- async read(location) {
1554
+ async get(location, params) {
1566
1555
  const filePath = this.resolvePath(location);
1567
1556
  try {
1568
- return await readFile(filePath);
1557
+ const stats = await stat(filePath);
1558
+ if (stats.isDirectory()) {
1559
+ return this.getDirectory(filePath, stats, params);
1560
+ } else {
1561
+ return this.getFile(filePath, stats);
1562
+ }
1569
1563
  } catch (error) {
1570
1564
  const err = error;
1571
- throw new TransportError(`File read error: ${err.code} - ${filePath}`, this.name, {
1565
+ throw new TransportError(`File get error: ${err.code} - ${filePath}`, this.name, {
1572
1566
  cause: err
1573
1567
  });
1574
1568
  }
1575
1569
  }
1576
- async write(location, content) {
1577
- const filePath = this.resolvePath(location);
1578
- try {
1579
- await mkdir(dirname(filePath), { recursive: true });
1580
- await writeFile(filePath, content);
1581
- } catch (error) {
1582
- const err = error;
1583
- throw new TransportError(`File write error: ${err.code} - ${filePath}`, this.name, {
1584
- cause: err
1585
- });
1570
+ async getFile(filePath, stats) {
1571
+ const content = await readFile(filePath);
1572
+ return {
1573
+ content,
1574
+ metadata: {
1575
+ type: "file",
1576
+ size: Number(stats.size),
1577
+ modifiedAt: stats.mtime
1578
+ }
1579
+ };
1580
+ }
1581
+ async getDirectory(dirPath, stats, params) {
1582
+ const recursive = params?.recursive === "true";
1583
+ const pattern = params?.pattern;
1584
+ let entries;
1585
+ if (recursive) {
1586
+ entries = await this.listRecursive(dirPath, dirPath);
1587
+ } else {
1588
+ entries = await readdir(dirPath);
1589
+ }
1590
+ if (pattern) {
1591
+ entries = this.filterByPattern(entries, pattern);
1586
1592
  }
1593
+ const content = Buffer.from(JSON.stringify(entries));
1594
+ return {
1595
+ content,
1596
+ metadata: {
1597
+ type: "directory",
1598
+ modifiedAt: stats.mtime
1599
+ }
1600
+ };
1587
1601
  }
1588
- async list(location) {
1589
- const dirPath = this.resolvePath(location);
1590
- try {
1591
- return await readdir(dirPath);
1592
- } catch (error) {
1593
- const err = error;
1594
- throw new TransportError(`Directory list error: ${err.code} - ${dirPath}`, this.name, {
1595
- cause: err
1596
- });
1602
+ async listRecursive(basePath, currentPath) {
1603
+ const entries = await readdir(currentPath, { withFileTypes: true });
1604
+ const results = [];
1605
+ for (const entry of entries) {
1606
+ const fullPath = join(currentPath, entry.name);
1607
+ const relativePath = fullPath.substring(basePath.length + 1);
1608
+ if (entry.isDirectory()) {
1609
+ const subEntries = await this.listRecursive(basePath, fullPath);
1610
+ results.push(...subEntries);
1611
+ } else {
1612
+ results.push(relativePath);
1613
+ }
1597
1614
  }
1615
+ return results;
1598
1616
  }
1599
- async mkdir(location) {
1600
- const dirPath = this.resolvePath(location);
1617
+ filterByPattern(entries, pattern) {
1618
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
1619
+ const regex = new RegExp(`^${regexPattern}$`);
1620
+ return entries.filter((entry) => {
1621
+ const filename = entry.split("/").pop() || entry;
1622
+ return regex.test(filename);
1623
+ });
1624
+ }
1625
+ async set(location, content, _params) {
1626
+ const filePath = this.resolvePath(location);
1601
1627
  try {
1602
- await mkdir(dirPath, { recursive: true });
1628
+ await mkdir(dirname(filePath), { recursive: true });
1629
+ await writeFile(filePath, content);
1603
1630
  } catch (error) {
1604
1631
  const err = error;
1605
- throw new TransportError(`Directory create error: ${err.code} - ${dirPath}`, this.name, {
1632
+ throw new TransportError(`File set error: ${err.code} - ${filePath}`, this.name, {
1606
1633
  cause: err
1607
1634
  });
1608
1635
  }
@@ -1616,28 +1643,15 @@ class FileTransportHandler {
1616
1643
  return false;
1617
1644
  }
1618
1645
  }
1619
- async stat(location) {
1620
- const filePath = this.resolvePath(location);
1621
- try {
1622
- const stats = await fsStat(filePath);
1623
- return {
1624
- size: stats.size,
1625
- modifiedAt: stats.mtime,
1626
- isDirectory: stats.isDirectory()
1627
- };
1628
- } catch (error) {
1629
- const err = error;
1630
- throw new TransportError(`File stat error: ${err.code} - ${filePath}`, this.name, {
1631
- cause: err
1632
- });
1633
- }
1634
- }
1635
1646
  async delete(location) {
1636
1647
  const filePath = this.resolvePath(location);
1637
1648
  try {
1638
1649
  await rm(filePath, { recursive: true });
1639
1650
  } catch (error) {
1640
1651
  const err = error;
1652
+ if (err.code === "ENOENT") {
1653
+ return;
1654
+ }
1641
1655
  throw new TransportError(`File delete error: ${err.code} - ${filePath}`, this.name, {
1642
1656
  cause: err
1643
1657
  });
@@ -1649,26 +1663,31 @@ var fileTransport = new FileTransportHandler;
1649
1663
  class HttpTransportHandler {
1650
1664
  name;
1651
1665
  protocol;
1652
- capabilities = {
1653
- canRead: true,
1654
- canWrite: false,
1655
- canList: false,
1656
- canDelete: false,
1657
- canStat: false
1658
- };
1659
1666
  constructor(protocol = "https") {
1660
1667
  this.protocol = protocol;
1661
1668
  this.name = protocol;
1662
1669
  }
1663
- async read(location) {
1664
- const url = `${this.protocol}://${location}`;
1670
+ async get(location, params) {
1671
+ const url = this.buildUrl(location, params);
1665
1672
  try {
1666
1673
  const response = await fetch(url);
1667
1674
  if (!response.ok) {
1668
1675
  throw new TransportError(`HTTP ${response.status}: ${response.statusText} - ${url}`, this.name);
1669
1676
  }
1670
1677
  const arrayBuffer = await response.arrayBuffer();
1671
- return Buffer.from(arrayBuffer);
1678
+ const content = Buffer.from(arrayBuffer);
1679
+ const contentType = response.headers.get("content-type");
1680
+ const contentLength = response.headers.get("content-length");
1681
+ const lastModified = response.headers.get("last-modified");
1682
+ return {
1683
+ content,
1684
+ metadata: {
1685
+ type: "file",
1686
+ size: contentLength ? parseInt(contentLength, 10) : content.length,
1687
+ modifiedAt: lastModified ? new Date(lastModified) : undefined,
1688
+ contentType
1689
+ }
1690
+ };
1672
1691
  } catch (error) {
1673
1692
  if (error instanceof TransportError) {
1674
1693
  throw error;
@@ -1678,6 +1697,30 @@ class HttpTransportHandler {
1678
1697
  });
1679
1698
  }
1680
1699
  }
1700
+ buildUrl(location, params) {
1701
+ const url = new URL(`${this.protocol}://${location}`);
1702
+ if (params) {
1703
+ for (const [key, value] of Object.entries(params)) {
1704
+ url.searchParams.set(key, value);
1705
+ }
1706
+ }
1707
+ return url.toString();
1708
+ }
1709
+ async set(_location, _content, _params) {
1710
+ throw new TransportError("HTTP transport is read-only, set not supported", this.name);
1711
+ }
1712
+ async exists(location) {
1713
+ const url = `${this.protocol}://${location}`;
1714
+ try {
1715
+ const response = await fetch(url, { method: "HEAD" });
1716
+ return response.ok;
1717
+ } catch {
1718
+ return false;
1719
+ }
1720
+ }
1721
+ async delete(_location) {
1722
+ throw new TransportError("HTTP transport is read-only, delete not supported", this.name);
1723
+ }
1681
1724
  }
1682
1725
  var httpsTransport = new HttpTransportHandler("https");
1683
1726
  var httpTransport = new HttpTransportHandler("http");
@@ -1685,17 +1728,36 @@ var httpTransport = new HttpTransportHandler("http");
1685
1728
  class TextSemanticHandler {
1686
1729
  name = "text";
1687
1730
  async resolve(transport, location, context) {
1688
- const buffer = await transport.read(location);
1689
- const text = buffer.toString("utf-8");
1731
+ const result = await transport.get(location, context.params);
1732
+ if (result.metadata?.type === "directory") {
1733
+ const meta2 = {
1734
+ url: context.url,
1735
+ semantic: context.semantic,
1736
+ transport: context.transport,
1737
+ location: context.location,
1738
+ size: result.content.length,
1739
+ encoding: "utf-8",
1740
+ mimeType: "application/json",
1741
+ resolvedAt: context.timestamp.toISOString(),
1742
+ type: "directory"
1743
+ };
1744
+ return {
1745
+ type: "text",
1746
+ content: result.content.toString("utf-8"),
1747
+ meta: meta2
1748
+ };
1749
+ }
1750
+ const text = result.content.toString("utf-8");
1690
1751
  const meta = {
1691
1752
  url: context.url,
1692
1753
  semantic: context.semantic,
1693
1754
  transport: context.transport,
1694
1755
  location: context.location,
1695
- size: buffer.length,
1756
+ size: result.metadata?.size ?? result.content.length,
1696
1757
  encoding: "utf-8",
1697
1758
  mimeType: "text/plain",
1698
- resolvedAt: context.timestamp.toISOString()
1759
+ resolvedAt: context.timestamp.toISOString(),
1760
+ type: "file"
1699
1761
  };
1700
1762
  return {
1701
1763
  type: "text",
@@ -1703,29 +1765,23 @@ class TextSemanticHandler {
1703
1765
  meta
1704
1766
  };
1705
1767
  }
1706
- async deposit(transport, location, data, _context) {
1707
- if (!transport.write) {
1708
- throw new SemanticError(`Transport "${transport.name}" does not support write operation`, this.name);
1709
- }
1768
+ async deposit(transport, location, data, context) {
1710
1769
  const buffer = Buffer.from(data, "utf-8");
1711
- await transport.write(location, buffer);
1712
- }
1713
- async exists(transport, location, _context) {
1714
- if (transport.exists) {
1715
- return transport.exists(location);
1716
- }
1717
1770
  try {
1718
- await transport.read(location);
1719
- return true;
1720
- } catch {
1721
- return false;
1771
+ await transport.set(location, buffer, context.params);
1772
+ } catch (error) {
1773
+ throw new SemanticError(`Failed to deposit text to "${location}": ${error.message}`, this.name, { cause: error });
1722
1774
  }
1723
1775
  }
1776
+ async exists(transport, location, _context) {
1777
+ return transport.exists(location);
1778
+ }
1724
1779
  async delete(transport, location, _context) {
1725
- if (!transport.delete) {
1726
- throw new SemanticError(`Transport "${transport.name}" does not support delete operation`, this.name);
1780
+ try {
1781
+ await transport.delete(location);
1782
+ } catch (error) {
1783
+ throw new SemanticError(`Failed to delete "${location}": ${error.message}`, this.name, { cause: error });
1727
1784
  }
1728
- await transport.delete(location);
1729
1785
  }
1730
1786
  }
1731
1787
  var textSemantic = new TextSemanticHandler;
@@ -1748,44 +1804,39 @@ function toBuffer(data) {
1748
1804
  class BinarySemanticHandler {
1749
1805
  name = "binary";
1750
1806
  async resolve(transport, location, context) {
1751
- const buffer = await transport.read(location);
1807
+ const result = await transport.get(location, context.params);
1752
1808
  const meta = {
1753
1809
  url: context.url,
1754
1810
  semantic: context.semantic,
1755
1811
  transport: context.transport,
1756
1812
  location: context.location,
1757
- size: buffer.length,
1758
- resolvedAt: context.timestamp.toISOString()
1813
+ size: result.metadata?.size ?? result.content.length,
1814
+ resolvedAt: context.timestamp.toISOString(),
1815
+ type: result.metadata?.type
1759
1816
  };
1760
1817
  return {
1761
1818
  type: "binary",
1762
- content: buffer,
1819
+ content: result.content,
1763
1820
  meta
1764
1821
  };
1765
1822
  }
1766
- async deposit(transport, location, data, _context) {
1767
- if (!transport.write) {
1768
- throw new SemanticError(`Transport "${transport.name}" does not support write operation`, this.name);
1769
- }
1823
+ async deposit(transport, location, data, context) {
1770
1824
  const buffer = toBuffer(data);
1771
- await transport.write(location, buffer);
1772
- }
1773
- async exists(transport, location, _context) {
1774
- if (transport.exists) {
1775
- return transport.exists(location);
1776
- }
1777
1825
  try {
1778
- await transport.read(location);
1779
- return true;
1780
- } catch {
1781
- return false;
1826
+ await transport.set(location, buffer, context.params);
1827
+ } catch (error) {
1828
+ throw new SemanticError(`Failed to deposit binary to "${location}": ${error.message}`, this.name, { cause: error });
1782
1829
  }
1783
1830
  }
1831
+ async exists(transport, location, _context) {
1832
+ return transport.exists(location);
1833
+ }
1784
1834
  async delete(transport, location, _context) {
1785
- if (!transport.delete) {
1786
- throw new SemanticError(`Transport "${transport.name}" does not support delete operation`, this.name);
1835
+ try {
1836
+ await transport.delete(location);
1837
+ } catch (error) {
1838
+ throw new SemanticError(`Failed to delete "${location}": ${error.message}`, this.name, { cause: error });
1787
1839
  }
1788
- await transport.delete(location);
1789
1840
  }
1790
1841
  }
1791
1842
  var binarySemantic = new BinarySemanticHandler;
@@ -1939,8 +1990,80 @@ class ARPRegistry {
1939
1990
  const contentArl = this.arp.parse(contentUrl);
1940
1991
  await contentArl.delete();
1941
1992
  }
1942
- async search(_query) {
1943
- throw new RegistryError("Search not implemented yet");
1993
+ async search(options) {
1994
+ const { query, limit, offset = 0 } = options ?? {};
1995
+ const baseUrl = `arp:text:file://${this.basePath}`;
1996
+ const baseArl = this.arp.parse(baseUrl);
1997
+ let entries;
1998
+ try {
1999
+ const result2 = await baseArl.resolve({ recursive: "true" });
2000
+ entries = JSON.parse(result2.content);
2001
+ } catch {
2002
+ return [];
2003
+ }
2004
+ const locators = [];
2005
+ for (const entry of entries) {
2006
+ if (!entry.endsWith("/manifest.json")) {
2007
+ continue;
2008
+ }
2009
+ const rxl = this.parseEntryToRXL(entry);
2010
+ if (rxl) {
2011
+ locators.push(rxl);
2012
+ }
2013
+ }
2014
+ let filtered = locators;
2015
+ if (query) {
2016
+ const lowerQuery = query.toLowerCase();
2017
+ filtered = locators.filter((rxl) => {
2018
+ const searchText = `${rxl.domain ?? ""} ${rxl.path ?? ""} ${rxl.name} ${rxl.type ?? ""}`.toLowerCase();
2019
+ return searchText.includes(lowerQuery);
2020
+ });
2021
+ }
2022
+ let result = filtered.slice(offset);
2023
+ if (limit !== undefined) {
2024
+ result = result.slice(0, limit);
2025
+ }
2026
+ return result;
2027
+ }
2028
+ parseEntryToRXL(entry) {
2029
+ const dirPath = entry.replace(/\/manifest\.json$/, "");
2030
+ const parts = dirPath.split("/");
2031
+ if (parts.length < 2) {
2032
+ return null;
2033
+ }
2034
+ const resourceDir = parts.pop();
2035
+ const domain = parts.shift();
2036
+ const path = parts.length > 0 ? parts.join("/") : undefined;
2037
+ const atIndex = resourceDir.lastIndexOf("@");
2038
+ if (atIndex === -1) {
2039
+ return null;
2040
+ }
2041
+ const nameTypePart = resourceDir.substring(0, atIndex);
2042
+ const version = resourceDir.substring(atIndex + 1);
2043
+ const dotIndex = nameTypePart.lastIndexOf(".");
2044
+ let name;
2045
+ let type;
2046
+ if (dotIndex !== -1) {
2047
+ name = nameTypePart.substring(0, dotIndex);
2048
+ type = nameTypePart.substring(dotIndex + 1);
2049
+ } else {
2050
+ name = nameTypePart;
2051
+ type = undefined;
2052
+ }
2053
+ let locatorStr = domain;
2054
+ if (path) {
2055
+ locatorStr += `/${path}`;
2056
+ }
2057
+ locatorStr += `/${name}`;
2058
+ if (type) {
2059
+ locatorStr += `.${type}`;
2060
+ }
2061
+ locatorStr += `@${version}`;
2062
+ try {
2063
+ return parseRXL(locatorStr);
2064
+ } catch {
2065
+ return null;
2066
+ }
1944
2067
  }
1945
2068
  }
1946
2069
  // src/createRegistry.ts
@@ -1953,4 +2076,4 @@ export {
1953
2076
  ARPRegistry
1954
2077
  };
1955
2078
 
1956
- //# debugId=6B85BCB12D2565AC64756E2164756E21
2079
+ //# debugId=B15E14D1A3CBAC5164756E2164756E21