@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 +22 -2
- package/dist/index.d.ts +28 -4
- package/dist/index.js +252 -129
- package/dist/index.js.map +5 -5
- package/package.json +4 -4
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(
|
|
178
|
+
#### `search(options?): Promise<RXL[]>`
|
|
179
179
|
|
|
180
|
-
Search for resources
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1307
|
-
|
|
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
|
-
|
|
1332
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
1554
|
+
async get(location, params) {
|
|
1566
1555
|
const filePath = this.resolvePath(location);
|
|
1567
1556
|
try {
|
|
1568
|
-
|
|
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
|
|
1565
|
+
throw new TransportError(`File get error: ${err.code} - ${filePath}`, this.name, {
|
|
1572
1566
|
cause: err
|
|
1573
1567
|
});
|
|
1574
1568
|
}
|
|
1575
1569
|
}
|
|
1576
|
-
async
|
|
1577
|
-
const
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
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
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
const
|
|
1594
|
-
|
|
1595
|
-
|
|
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
|
-
|
|
1600
|
-
const
|
|
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(
|
|
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(`
|
|
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
|
|
1664
|
-
const url =
|
|
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
|
-
|
|
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
|
|
1689
|
-
|
|
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:
|
|
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,
|
|
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.
|
|
1719
|
-
|
|
1720
|
-
|
|
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
|
-
|
|
1726
|
-
|
|
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
|
|
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:
|
|
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:
|
|
1819
|
+
content: result.content,
|
|
1763
1820
|
meta
|
|
1764
1821
|
};
|
|
1765
1822
|
}
|
|
1766
|
-
async deposit(transport, location, data,
|
|
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.
|
|
1779
|
-
|
|
1780
|
-
|
|
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
|
-
|
|
1786
|
-
|
|
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(
|
|
1943
|
-
|
|
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=
|
|
2079
|
+
//# debugId=B15E14D1A3CBAC5164756E2164756E21
|