@resourcexjs/registry 2.2.0 → 2.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/dist/index.d.ts +69 -112
- package/dist/index.js +573 -127
- package/dist/index.js.map +13 -12
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -23447,13 +23447,6 @@ var require_ours = __commonJS((exports, module) => {
|
|
|
23447
23447
|
module.exports.default = module.exports;
|
|
23448
23448
|
});
|
|
23449
23449
|
|
|
23450
|
-
// src/types.ts
|
|
23451
|
-
function isRemoteConfig(config) {
|
|
23452
|
-
return config !== undefined && "endpoint" in config;
|
|
23453
|
-
}
|
|
23454
|
-
function isGitConfig(config) {
|
|
23455
|
-
return config !== undefined && "type" in config && config.type === "git";
|
|
23456
|
-
}
|
|
23457
23450
|
// ../core/dist/index.js
|
|
23458
23451
|
import { gzip, gunzip } from "node:zlib";
|
|
23459
23452
|
import { promisify } from "node:util";
|
|
@@ -24679,9 +24672,81 @@ async function unpackTar(archive, options = {}) {
|
|
|
24679
24672
|
var gzipAsync2 = promisify2(gzip2);
|
|
24680
24673
|
var gunzipAsync2 = promisify2(gunzip2);
|
|
24681
24674
|
|
|
24682
|
-
class
|
|
24675
|
+
class RXPImpl {
|
|
24676
|
+
_files;
|
|
24677
|
+
_pathsCache = null;
|
|
24678
|
+
_treeCache = null;
|
|
24679
|
+
constructor(files) {
|
|
24680
|
+
this._files = files;
|
|
24681
|
+
}
|
|
24682
|
+
paths() {
|
|
24683
|
+
if (this._pathsCache) {
|
|
24684
|
+
return this._pathsCache;
|
|
24685
|
+
}
|
|
24686
|
+
this._pathsCache = Array.from(this._files.keys()).sort();
|
|
24687
|
+
return this._pathsCache;
|
|
24688
|
+
}
|
|
24689
|
+
tree() {
|
|
24690
|
+
if (this._treeCache) {
|
|
24691
|
+
return this._treeCache;
|
|
24692
|
+
}
|
|
24693
|
+
const root = new Map;
|
|
24694
|
+
for (const path of this._files.keys()) {
|
|
24695
|
+
const parts = path.split("/");
|
|
24696
|
+
let currentLevel = root;
|
|
24697
|
+
for (let i = 0;i < parts.length; i++) {
|
|
24698
|
+
const part = parts[i];
|
|
24699
|
+
const isFile = i === parts.length - 1;
|
|
24700
|
+
if (!currentLevel.has(part)) {
|
|
24701
|
+
const treeNode2 = {
|
|
24702
|
+
node: {
|
|
24703
|
+
name: part,
|
|
24704
|
+
type: isFile ? "file" : "directory",
|
|
24705
|
+
children: isFile ? undefined : []
|
|
24706
|
+
},
|
|
24707
|
+
children: new Map
|
|
24708
|
+
};
|
|
24709
|
+
currentLevel.set(part, treeNode2);
|
|
24710
|
+
}
|
|
24711
|
+
const treeNode = currentLevel.get(part);
|
|
24712
|
+
if (!isFile) {
|
|
24713
|
+
currentLevel = treeNode.children;
|
|
24714
|
+
}
|
|
24715
|
+
}
|
|
24716
|
+
}
|
|
24717
|
+
const convertToPathNodes = (level) => {
|
|
24718
|
+
return Array.from(level.values()).map((treeNode) => {
|
|
24719
|
+
if (treeNode.node.type === "directory" && treeNode.children.size > 0) {
|
|
24720
|
+
treeNode.node.children = convertToPathNodes(treeNode.children);
|
|
24721
|
+
}
|
|
24722
|
+
return treeNode.node;
|
|
24723
|
+
});
|
|
24724
|
+
};
|
|
24725
|
+
this._treeCache = convertToPathNodes(root);
|
|
24726
|
+
return this._treeCache;
|
|
24727
|
+
}
|
|
24728
|
+
async file(path) {
|
|
24729
|
+
const content = this._files.get(path);
|
|
24730
|
+
if (!content) {
|
|
24731
|
+
throw new ContentError(`file not found: ${path}`);
|
|
24732
|
+
}
|
|
24733
|
+
return content;
|
|
24734
|
+
}
|
|
24735
|
+
async files() {
|
|
24736
|
+
return new Map(this._files);
|
|
24737
|
+
}
|
|
24738
|
+
async pack() {
|
|
24739
|
+
const filesRecord = {};
|
|
24740
|
+
for (const [path, content] of this._files) {
|
|
24741
|
+
filesRecord[path] = content;
|
|
24742
|
+
}
|
|
24743
|
+
return createRXA(filesRecord);
|
|
24744
|
+
}
|
|
24745
|
+
}
|
|
24746
|
+
|
|
24747
|
+
class RXAImpl {
|
|
24683
24748
|
_buffer;
|
|
24684
|
-
|
|
24749
|
+
_rxpCache = null;
|
|
24685
24750
|
constructor(buffer) {
|
|
24686
24751
|
this._buffer = buffer;
|
|
24687
24752
|
}
|
|
@@ -24697,17 +24762,9 @@ class RXCImpl {
|
|
|
24697
24762
|
async buffer() {
|
|
24698
24763
|
return this._buffer;
|
|
24699
24764
|
}
|
|
24700
|
-
async
|
|
24701
|
-
|
|
24702
|
-
|
|
24703
|
-
if (!content) {
|
|
24704
|
-
throw new ContentError(`file not found: ${path}`);
|
|
24705
|
-
}
|
|
24706
|
-
return content;
|
|
24707
|
-
}
|
|
24708
|
-
async files() {
|
|
24709
|
-
if (this._filesCache) {
|
|
24710
|
-
return this._filesCache;
|
|
24765
|
+
async extract() {
|
|
24766
|
+
if (this._rxpCache) {
|
|
24767
|
+
return this._rxpCache;
|
|
24711
24768
|
}
|
|
24712
24769
|
const tarBuffer = await gunzipAsync2(this._buffer);
|
|
24713
24770
|
const entries = await unpackTar(tarBuffer);
|
|
@@ -24717,16 +24774,16 @@ class RXCImpl {
|
|
|
24717
24774
|
filesMap.set(entry.header.name, Buffer.from(entry.data));
|
|
24718
24775
|
}
|
|
24719
24776
|
}
|
|
24720
|
-
this.
|
|
24721
|
-
return
|
|
24777
|
+
this._rxpCache = new RXPImpl(filesMap);
|
|
24778
|
+
return this._rxpCache;
|
|
24722
24779
|
}
|
|
24723
24780
|
}
|
|
24724
|
-
function
|
|
24725
|
-
return "
|
|
24781
|
+
function isBufferInput(input) {
|
|
24782
|
+
return "buffer" in input && Buffer.isBuffer(input.buffer);
|
|
24726
24783
|
}
|
|
24727
|
-
async function
|
|
24728
|
-
if (
|
|
24729
|
-
return new
|
|
24784
|
+
async function createRXA(input) {
|
|
24785
|
+
if (isBufferInput(input)) {
|
|
24786
|
+
return new RXAImpl(input.buffer);
|
|
24730
24787
|
}
|
|
24731
24788
|
const entries = Object.entries(input).map(([name, content]) => {
|
|
24732
24789
|
const body = typeof content === "string" ? content : content instanceof Uint8Array ? content : new Uint8Array(content);
|
|
@@ -24738,7 +24795,7 @@ async function createRXC(input) {
|
|
|
24738
24795
|
});
|
|
24739
24796
|
const tarBuffer = await packTar(entries);
|
|
24740
24797
|
const gzipBuffer = await gzipAsync2(Buffer.from(tarBuffer));
|
|
24741
|
-
return new
|
|
24798
|
+
return new RXAImpl(gzipBuffer);
|
|
24742
24799
|
}
|
|
24743
24800
|
|
|
24744
24801
|
class ResourceTypeError extends ResourceXError2 {
|
|
@@ -24749,13 +24806,13 @@ class ResourceTypeError extends ResourceXError2 {
|
|
|
24749
24806
|
}
|
|
24750
24807
|
var textSerializer = {
|
|
24751
24808
|
async serialize(rxr) {
|
|
24752
|
-
return rxr.
|
|
24809
|
+
return rxr.archive.buffer();
|
|
24753
24810
|
},
|
|
24754
24811
|
async deserialize(data, manifest) {
|
|
24755
24812
|
return {
|
|
24756
24813
|
locator: parseRXL2(manifest.toLocator()),
|
|
24757
24814
|
manifest,
|
|
24758
|
-
|
|
24815
|
+
archive: await createRXA({ buffer: data })
|
|
24759
24816
|
};
|
|
24760
24817
|
}
|
|
24761
24818
|
};
|
|
@@ -24766,7 +24823,8 @@ var textResolver = {
|
|
|
24766
24823
|
resource: rxr,
|
|
24767
24824
|
schema: undefined,
|
|
24768
24825
|
execute: async () => {
|
|
24769
|
-
const
|
|
24826
|
+
const pkg = await rxr.archive.extract();
|
|
24827
|
+
const buffer = await pkg.file("content");
|
|
24770
24828
|
return buffer.toString("utf-8");
|
|
24771
24829
|
}
|
|
24772
24830
|
};
|
|
@@ -24781,13 +24839,13 @@ var textType = {
|
|
|
24781
24839
|
};
|
|
24782
24840
|
var jsonSerializer = {
|
|
24783
24841
|
async serialize(rxr) {
|
|
24784
|
-
return rxr.
|
|
24842
|
+
return rxr.archive.buffer();
|
|
24785
24843
|
},
|
|
24786
24844
|
async deserialize(data, manifest) {
|
|
24787
24845
|
return {
|
|
24788
24846
|
locator: parseRXL2(manifest.toLocator()),
|
|
24789
24847
|
manifest,
|
|
24790
|
-
|
|
24848
|
+
archive: await createRXA({ buffer: data })
|
|
24791
24849
|
};
|
|
24792
24850
|
}
|
|
24793
24851
|
};
|
|
@@ -24798,7 +24856,8 @@ var jsonResolver = {
|
|
|
24798
24856
|
resource: rxr,
|
|
24799
24857
|
schema: undefined,
|
|
24800
24858
|
execute: async () => {
|
|
24801
|
-
const
|
|
24859
|
+
const pkg = await rxr.archive.extract();
|
|
24860
|
+
const buffer = await pkg.file("content");
|
|
24802
24861
|
return JSON.parse(buffer.toString("utf-8"));
|
|
24803
24862
|
}
|
|
24804
24863
|
};
|
|
@@ -24813,13 +24872,13 @@ var jsonType = {
|
|
|
24813
24872
|
};
|
|
24814
24873
|
var binarySerializer = {
|
|
24815
24874
|
async serialize(rxr) {
|
|
24816
|
-
return rxr.
|
|
24875
|
+
return rxr.archive.buffer();
|
|
24817
24876
|
},
|
|
24818
24877
|
async deserialize(data, manifest) {
|
|
24819
24878
|
return {
|
|
24820
24879
|
locator: parseRXL2(manifest.toLocator()),
|
|
24821
24880
|
manifest,
|
|
24822
|
-
|
|
24881
|
+
archive: await createRXA({ buffer: data })
|
|
24823
24882
|
};
|
|
24824
24883
|
}
|
|
24825
24884
|
};
|
|
@@ -24830,7 +24889,8 @@ var binaryResolver = {
|
|
|
24830
24889
|
resource: rxr,
|
|
24831
24890
|
schema: undefined,
|
|
24832
24891
|
execute: async () => {
|
|
24833
|
-
|
|
24892
|
+
const pkg = await rxr.archive.extract();
|
|
24893
|
+
return pkg.file("content");
|
|
24834
24894
|
}
|
|
24835
24895
|
};
|
|
24836
24896
|
}
|
|
@@ -26563,9 +26623,81 @@ async function unpackTar2(archive, options = {}) {
|
|
|
26563
26623
|
var gzipAsync3 = promisify3(gzip3);
|
|
26564
26624
|
var gunzipAsync3 = promisify3(gunzip3);
|
|
26565
26625
|
|
|
26566
|
-
class
|
|
26626
|
+
class RXPImpl2 {
|
|
26627
|
+
_files;
|
|
26628
|
+
_pathsCache = null;
|
|
26629
|
+
_treeCache = null;
|
|
26630
|
+
constructor(files) {
|
|
26631
|
+
this._files = files;
|
|
26632
|
+
}
|
|
26633
|
+
paths() {
|
|
26634
|
+
if (this._pathsCache) {
|
|
26635
|
+
return this._pathsCache;
|
|
26636
|
+
}
|
|
26637
|
+
this._pathsCache = Array.from(this._files.keys()).sort();
|
|
26638
|
+
return this._pathsCache;
|
|
26639
|
+
}
|
|
26640
|
+
tree() {
|
|
26641
|
+
if (this._treeCache) {
|
|
26642
|
+
return this._treeCache;
|
|
26643
|
+
}
|
|
26644
|
+
const root = new Map;
|
|
26645
|
+
for (const path of this._files.keys()) {
|
|
26646
|
+
const parts = path.split("/");
|
|
26647
|
+
let currentLevel = root;
|
|
26648
|
+
for (let i = 0;i < parts.length; i++) {
|
|
26649
|
+
const part = parts[i];
|
|
26650
|
+
const isFile = i === parts.length - 1;
|
|
26651
|
+
if (!currentLevel.has(part)) {
|
|
26652
|
+
const treeNode2 = {
|
|
26653
|
+
node: {
|
|
26654
|
+
name: part,
|
|
26655
|
+
type: isFile ? "file" : "directory",
|
|
26656
|
+
children: isFile ? undefined : []
|
|
26657
|
+
},
|
|
26658
|
+
children: new Map
|
|
26659
|
+
};
|
|
26660
|
+
currentLevel.set(part, treeNode2);
|
|
26661
|
+
}
|
|
26662
|
+
const treeNode = currentLevel.get(part);
|
|
26663
|
+
if (!isFile) {
|
|
26664
|
+
currentLevel = treeNode.children;
|
|
26665
|
+
}
|
|
26666
|
+
}
|
|
26667
|
+
}
|
|
26668
|
+
const convertToPathNodes = (level) => {
|
|
26669
|
+
return Array.from(level.values()).map((treeNode) => {
|
|
26670
|
+
if (treeNode.node.type === "directory" && treeNode.children.size > 0) {
|
|
26671
|
+
treeNode.node.children = convertToPathNodes(treeNode.children);
|
|
26672
|
+
}
|
|
26673
|
+
return treeNode.node;
|
|
26674
|
+
});
|
|
26675
|
+
};
|
|
26676
|
+
this._treeCache = convertToPathNodes(root);
|
|
26677
|
+
return this._treeCache;
|
|
26678
|
+
}
|
|
26679
|
+
async file(path) {
|
|
26680
|
+
const content = this._files.get(path);
|
|
26681
|
+
if (!content) {
|
|
26682
|
+
throw new ContentError2(`file not found: ${path}`);
|
|
26683
|
+
}
|
|
26684
|
+
return content;
|
|
26685
|
+
}
|
|
26686
|
+
async files() {
|
|
26687
|
+
return new Map(this._files);
|
|
26688
|
+
}
|
|
26689
|
+
async pack() {
|
|
26690
|
+
const filesRecord = {};
|
|
26691
|
+
for (const [path, content] of this._files) {
|
|
26692
|
+
filesRecord[path] = content;
|
|
26693
|
+
}
|
|
26694
|
+
return createRXA2(filesRecord);
|
|
26695
|
+
}
|
|
26696
|
+
}
|
|
26697
|
+
|
|
26698
|
+
class RXAImpl2 {
|
|
26567
26699
|
_buffer;
|
|
26568
|
-
|
|
26700
|
+
_rxpCache = null;
|
|
26569
26701
|
constructor(buffer) {
|
|
26570
26702
|
this._buffer = buffer;
|
|
26571
26703
|
}
|
|
@@ -26581,17 +26713,9 @@ class RXCImpl2 {
|
|
|
26581
26713
|
async buffer() {
|
|
26582
26714
|
return this._buffer;
|
|
26583
26715
|
}
|
|
26584
|
-
async
|
|
26585
|
-
|
|
26586
|
-
|
|
26587
|
-
if (!content) {
|
|
26588
|
-
throw new ContentError2(`file not found: ${path}`);
|
|
26589
|
-
}
|
|
26590
|
-
return content;
|
|
26591
|
-
}
|
|
26592
|
-
async files() {
|
|
26593
|
-
if (this._filesCache) {
|
|
26594
|
-
return this._filesCache;
|
|
26716
|
+
async extract() {
|
|
26717
|
+
if (this._rxpCache) {
|
|
26718
|
+
return this._rxpCache;
|
|
26595
26719
|
}
|
|
26596
26720
|
const tarBuffer = await gunzipAsync3(this._buffer);
|
|
26597
26721
|
const entries = await unpackTar2(tarBuffer);
|
|
@@ -26601,16 +26725,16 @@ class RXCImpl2 {
|
|
|
26601
26725
|
filesMap.set(entry.header.name, Buffer.from(entry.data));
|
|
26602
26726
|
}
|
|
26603
26727
|
}
|
|
26604
|
-
this.
|
|
26605
|
-
return
|
|
26728
|
+
this._rxpCache = new RXPImpl2(filesMap);
|
|
26729
|
+
return this._rxpCache;
|
|
26606
26730
|
}
|
|
26607
26731
|
}
|
|
26608
|
-
function
|
|
26609
|
-
return "
|
|
26732
|
+
function isBufferInput2(input) {
|
|
26733
|
+
return "buffer" in input && Buffer.isBuffer(input.buffer);
|
|
26610
26734
|
}
|
|
26611
|
-
async function
|
|
26612
|
-
if (
|
|
26613
|
-
return new
|
|
26735
|
+
async function createRXA2(input) {
|
|
26736
|
+
if (isBufferInput2(input)) {
|
|
26737
|
+
return new RXAImpl2(input.buffer);
|
|
26614
26738
|
}
|
|
26615
26739
|
const entries = Object.entries(input).map(([name, content]) => {
|
|
26616
26740
|
const body = typeof content === "string" ? content : content instanceof Uint8Array ? content : new Uint8Array(content);
|
|
@@ -26622,7 +26746,7 @@ async function createRXC2(input) {
|
|
|
26622
26746
|
});
|
|
26623
26747
|
const tarBuffer = await packTar2(entries);
|
|
26624
26748
|
const gzipBuffer = await gzipAsync3(Buffer.from(tarBuffer));
|
|
26625
|
-
return new
|
|
26749
|
+
return new RXAImpl2(gzipBuffer);
|
|
26626
26750
|
}
|
|
26627
26751
|
|
|
26628
26752
|
class FolderLoader {
|
|
@@ -26673,12 +26797,12 @@ class FolderLoader {
|
|
|
26673
26797
|
if (Object.keys(files).length === 0) {
|
|
26674
26798
|
throw new ResourceXError3("No content files found in resource folder");
|
|
26675
26799
|
}
|
|
26676
|
-
const
|
|
26800
|
+
const archive = await createRXA2(files);
|
|
26677
26801
|
const locator = parseRXL3(manifest.toLocator());
|
|
26678
26802
|
return {
|
|
26679
26803
|
locator,
|
|
26680
26804
|
manifest,
|
|
26681
|
-
|
|
26805
|
+
archive
|
|
26682
26806
|
};
|
|
26683
26807
|
}
|
|
26684
26808
|
async readFolderFiles(folderPath, basePath = folderPath) {
|
|
@@ -26786,7 +26910,7 @@ class LocalRegistry {
|
|
|
26786
26910
|
const manifestContent = manifestResource.content.toString("utf-8");
|
|
26787
26911
|
const manifestData = JSON.parse(manifestContent);
|
|
26788
26912
|
const manifest = createRXM(manifestData);
|
|
26789
|
-
const contentPath = join3(resourcePath, "
|
|
26913
|
+
const contentPath = join3(resourcePath, "archive.tar.gz");
|
|
26790
26914
|
const contentArl = this.arp.parse(this.toArpUrl(contentPath));
|
|
26791
26915
|
const contentResource = await contentArl.resolve();
|
|
26792
26916
|
const data = contentResource.content;
|
|
@@ -26822,7 +26946,7 @@ class LocalRegistry {
|
|
|
26822
26946
|
const manifestArl = this.arp.parse(this.toArpUrl(manifestPath));
|
|
26823
26947
|
const manifestContent = Buffer.from(JSON.stringify(resource.manifest.toJSON(), null, 2), "utf-8");
|
|
26824
26948
|
await manifestArl.deposit(manifestContent);
|
|
26825
|
-
const contentPath = join3(resourcePath, "
|
|
26949
|
+
const contentPath = join3(resourcePath, "archive.tar.gz");
|
|
26826
26950
|
const contentArl = this.arp.parse(this.toArpUrl(contentPath));
|
|
26827
26951
|
const serialized = await this.typeHandler.serialize(resource);
|
|
26828
26952
|
await contentArl.deposit(serialized);
|
|
@@ -26966,6 +27090,12 @@ class LocalRegistry {
|
|
|
26966
27090
|
}
|
|
26967
27091
|
// src/RemoteRegistry.ts
|
|
26968
27092
|
class RemoteRegistry {
|
|
27093
|
+
static canHandle(url) {
|
|
27094
|
+
return url.startsWith("https://") || url.startsWith("http://");
|
|
27095
|
+
}
|
|
27096
|
+
static create(config) {
|
|
27097
|
+
return new RemoteRegistry({ endpoint: config.url });
|
|
27098
|
+
}
|
|
26969
27099
|
endpoint;
|
|
26970
27100
|
typeHandler;
|
|
26971
27101
|
constructor(config) {
|
|
@@ -27061,6 +27191,20 @@ async function discoverRegistry(domain) {
|
|
|
27061
27191
|
throw new RegistryError(`Failed to discover registry for ${domain}: ${error.message}`);
|
|
27062
27192
|
}
|
|
27063
27193
|
}
|
|
27194
|
+
// src/types.ts
|
|
27195
|
+
function isUrlConfig(config) {
|
|
27196
|
+
return config !== undefined && "url" in config && !("type" in config) && !("endpoint" in config);
|
|
27197
|
+
}
|
|
27198
|
+
function isRemoteConfig(config) {
|
|
27199
|
+
return config !== undefined && "endpoint" in config;
|
|
27200
|
+
}
|
|
27201
|
+
function isGitConfig(config) {
|
|
27202
|
+
return config !== undefined && "type" in config && config.type === "git";
|
|
27203
|
+
}
|
|
27204
|
+
function isGitHubConfig(config) {
|
|
27205
|
+
return config !== undefined && "type" in config && config.type === "github";
|
|
27206
|
+
}
|
|
27207
|
+
|
|
27064
27208
|
// src/GitRegistry.ts
|
|
27065
27209
|
var import_isomorphic_git = __toESM(require_isomorphic_git(), 1);
|
|
27066
27210
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -27224,6 +27368,71 @@ async function request({
|
|
|
27224
27368
|
var index = { request };
|
|
27225
27369
|
var node_default = index;
|
|
27226
27370
|
|
|
27371
|
+
// src/middleware/RegistryMiddleware.ts
|
|
27372
|
+
class RegistryMiddleware {
|
|
27373
|
+
inner;
|
|
27374
|
+
constructor(inner) {
|
|
27375
|
+
this.inner = inner;
|
|
27376
|
+
}
|
|
27377
|
+
supportType(type) {
|
|
27378
|
+
this.inner.supportType(type);
|
|
27379
|
+
}
|
|
27380
|
+
link(path) {
|
|
27381
|
+
return this.inner.link(path);
|
|
27382
|
+
}
|
|
27383
|
+
add(source) {
|
|
27384
|
+
return this.inner.add(source);
|
|
27385
|
+
}
|
|
27386
|
+
pull(locator, options) {
|
|
27387
|
+
return this.inner.pull(locator, options);
|
|
27388
|
+
}
|
|
27389
|
+
publish(source, options) {
|
|
27390
|
+
return this.inner.publish(source, options);
|
|
27391
|
+
}
|
|
27392
|
+
get(locator) {
|
|
27393
|
+
return this.inner.get(locator);
|
|
27394
|
+
}
|
|
27395
|
+
resolve(locator) {
|
|
27396
|
+
return this.inner.resolve(locator);
|
|
27397
|
+
}
|
|
27398
|
+
exists(locator) {
|
|
27399
|
+
return this.inner.exists(locator);
|
|
27400
|
+
}
|
|
27401
|
+
delete(locator) {
|
|
27402
|
+
return this.inner.delete(locator);
|
|
27403
|
+
}
|
|
27404
|
+
search(options) {
|
|
27405
|
+
return this.inner.search(options);
|
|
27406
|
+
}
|
|
27407
|
+
}
|
|
27408
|
+
|
|
27409
|
+
// src/middleware/DomainValidation.ts
|
|
27410
|
+
class DomainValidation extends RegistryMiddleware {
|
|
27411
|
+
trustedDomain;
|
|
27412
|
+
constructor(inner, trustedDomain) {
|
|
27413
|
+
super(inner);
|
|
27414
|
+
this.trustedDomain = trustedDomain;
|
|
27415
|
+
}
|
|
27416
|
+
validateDomain(rxr) {
|
|
27417
|
+
if (rxr.manifest.domain !== this.trustedDomain) {
|
|
27418
|
+
throw new RegistryError(`Untrusted domain: resource claims "${rxr.manifest.domain}" but registry only trusts "${this.trustedDomain}"`);
|
|
27419
|
+
}
|
|
27420
|
+
}
|
|
27421
|
+
async get(locator) {
|
|
27422
|
+
const rxr = await this.inner.get(locator);
|
|
27423
|
+
this.validateDomain(rxr);
|
|
27424
|
+
return rxr;
|
|
27425
|
+
}
|
|
27426
|
+
async resolve(locator) {
|
|
27427
|
+
const rxr = await this.inner.get(locator);
|
|
27428
|
+
this.validateDomain(rxr);
|
|
27429
|
+
return this.inner.resolve(locator);
|
|
27430
|
+
}
|
|
27431
|
+
}
|
|
27432
|
+
function withDomainValidation(registry, trustedDomain) {
|
|
27433
|
+
return new DomainValidation(registry, trustedDomain);
|
|
27434
|
+
}
|
|
27435
|
+
|
|
27227
27436
|
// src/GitRegistry.ts
|
|
27228
27437
|
var DEFAULT_GIT_CACHE = `${homedir2()}/.resourcex/.git-cache`;
|
|
27229
27438
|
var MAX_RETRIES = 2;
|
|
@@ -27232,6 +27441,19 @@ function isLocalPath(url) {
|
|
|
27232
27441
|
}
|
|
27233
27442
|
|
|
27234
27443
|
class GitRegistry {
|
|
27444
|
+
static canHandle(url) {
|
|
27445
|
+
return url.startsWith("git@") || url.endsWith(".git");
|
|
27446
|
+
}
|
|
27447
|
+
static create(config) {
|
|
27448
|
+
const registry = new GitRegistry({
|
|
27449
|
+
type: "git",
|
|
27450
|
+
url: config.url,
|
|
27451
|
+
ref: config.ref,
|
|
27452
|
+
basePath: config.basePath,
|
|
27453
|
+
domain: config.domain
|
|
27454
|
+
});
|
|
27455
|
+
return config.domain ? withDomainValidation(registry, config.domain) : registry;
|
|
27456
|
+
}
|
|
27235
27457
|
url;
|
|
27236
27458
|
ref;
|
|
27237
27459
|
basePath;
|
|
@@ -27364,7 +27586,7 @@ class GitRegistry {
|
|
|
27364
27586
|
const manifestContent = manifestResource.content.toString("utf-8");
|
|
27365
27587
|
const manifestData = JSON.parse(manifestContent);
|
|
27366
27588
|
const manifest = createRXM(manifestData);
|
|
27367
|
-
const contentPath = join4(resourcePath, "
|
|
27589
|
+
const contentPath = join4(resourcePath, "archive.tar.gz");
|
|
27368
27590
|
const contentArl = this.arp.parse(this.toArpUrl(contentPath));
|
|
27369
27591
|
const contentResource = await contentArl.resolve();
|
|
27370
27592
|
const data = contentResource.content;
|
|
@@ -27465,109 +27687,333 @@ class GitRegistry {
|
|
|
27465
27687
|
throw new RegistryError("GitRegistry is read-only - use LocalRegistry.delete()");
|
|
27466
27688
|
}
|
|
27467
27689
|
}
|
|
27468
|
-
|
|
27469
|
-
|
|
27470
|
-
|
|
27471
|
-
|
|
27472
|
-
|
|
27690
|
+
|
|
27691
|
+
// src/GitHubRegistry.ts
|
|
27692
|
+
import { homedir as homedir3 } from "node:os";
|
|
27693
|
+
import { join as join5 } from "node:path";
|
|
27694
|
+
import { gunzipSync } from "node:zlib";
|
|
27695
|
+
var DEFAULT_GITHUB_CACHE = `${homedir3()}/.resourcex/.github-cache`;
|
|
27696
|
+
function parseGitHubUrl(url) {
|
|
27697
|
+
if (!url.startsWith("https://github.com/")) {
|
|
27698
|
+
throw new RegistryError(`Invalid GitHub URL: ${url}. Expected format: https://github.com/owner/repo`);
|
|
27699
|
+
}
|
|
27700
|
+
const path = url.slice("https://github.com/".length);
|
|
27701
|
+
const parts = path.split("/");
|
|
27702
|
+
if (parts.length < 2) {
|
|
27703
|
+
throw new RegistryError(`Invalid GitHub URL: ${url}. Expected format: https://github.com/owner/repo`);
|
|
27704
|
+
}
|
|
27705
|
+
const owner = parts[0];
|
|
27706
|
+
const repo = parts[1];
|
|
27707
|
+
let branch = "main";
|
|
27708
|
+
if (parts.length >= 4 && parts[2] === "tree") {
|
|
27709
|
+
branch = parts[3];
|
|
27710
|
+
}
|
|
27711
|
+
return { owner, repo, branch };
|
|
27712
|
+
}
|
|
27713
|
+
function isGitHubUrl(url) {
|
|
27714
|
+
return url.startsWith("https://github.com/");
|
|
27715
|
+
}
|
|
27716
|
+
|
|
27717
|
+
class GitHubRegistry {
|
|
27718
|
+
static canHandle(url) {
|
|
27719
|
+
return isGitHubUrl(url);
|
|
27720
|
+
}
|
|
27721
|
+
static create(config) {
|
|
27722
|
+
const registry = new GitHubRegistry({
|
|
27723
|
+
url: config.url,
|
|
27724
|
+
ref: config.ref,
|
|
27725
|
+
basePath: config.basePath
|
|
27726
|
+
});
|
|
27727
|
+
return config.domain ? withDomainValidation(registry, config.domain) : registry;
|
|
27473
27728
|
}
|
|
27474
|
-
|
|
27475
|
-
|
|
27729
|
+
url;
|
|
27730
|
+
owner;
|
|
27731
|
+
repo;
|
|
27732
|
+
ref;
|
|
27733
|
+
basePath;
|
|
27734
|
+
cacheDir;
|
|
27735
|
+
typeHandler;
|
|
27736
|
+
arp;
|
|
27737
|
+
tarballDownloaded = false;
|
|
27738
|
+
constructor(config) {
|
|
27739
|
+
this.url = config.url;
|
|
27740
|
+
const parsed = parseGitHubUrl(config.url);
|
|
27741
|
+
this.owner = parsed.owner;
|
|
27742
|
+
this.repo = parsed.repo;
|
|
27743
|
+
this.ref = config.ref ?? parsed.branch;
|
|
27744
|
+
this.basePath = config.basePath ?? ".resourcex";
|
|
27745
|
+
this.typeHandler = TypeHandlerChain.create();
|
|
27746
|
+
this.arp = createARP();
|
|
27747
|
+
this.cacheDir = this.buildCacheDir();
|
|
27476
27748
|
}
|
|
27477
|
-
|
|
27478
|
-
|
|
27749
|
+
buildCacheDir() {
|
|
27750
|
+
const dirName = `github.com-${this.owner}-${this.repo}`;
|
|
27751
|
+
return join5(DEFAULT_GITHUB_CACHE, dirName);
|
|
27479
27752
|
}
|
|
27480
|
-
|
|
27481
|
-
|
|
27753
|
+
supportType(type) {
|
|
27754
|
+
this.typeHandler.register(type);
|
|
27482
27755
|
}
|
|
27483
|
-
|
|
27484
|
-
return
|
|
27756
|
+
toArpUrl(filePath) {
|
|
27757
|
+
return `arp:binary:file://${filePath}`;
|
|
27485
27758
|
}
|
|
27486
|
-
|
|
27487
|
-
return this.
|
|
27759
|
+
getTarballUrl() {
|
|
27760
|
+
return `https://github.com/${this.owner}/${this.repo}/archive/refs/heads/${this.ref}.tar.gz`;
|
|
27488
27761
|
}
|
|
27489
|
-
|
|
27490
|
-
|
|
27762
|
+
async ensureDownloaded() {
|
|
27763
|
+
if (this.tarballDownloaded) {
|
|
27764
|
+
return;
|
|
27765
|
+
}
|
|
27766
|
+
const tarballUrl = this.getTarballUrl();
|
|
27767
|
+
const response = await fetch(tarballUrl, {
|
|
27768
|
+
headers: {
|
|
27769
|
+
"User-Agent": "ResourceX/1.0"
|
|
27770
|
+
}
|
|
27771
|
+
});
|
|
27772
|
+
if (!response.ok) {
|
|
27773
|
+
throw new RegistryError(`Failed to download tarball from ${tarballUrl}: ${response.status} ${response.statusText}`);
|
|
27774
|
+
}
|
|
27775
|
+
const tarballBuffer = Buffer.from(await response.arrayBuffer());
|
|
27776
|
+
await this.extractTarball(tarballBuffer);
|
|
27777
|
+
this.tarballDownloaded = true;
|
|
27778
|
+
}
|
|
27779
|
+
async extractTarball(tarballBuffer) {
|
|
27780
|
+
const tarBuffer = gunzipSync(tarballBuffer);
|
|
27781
|
+
const files = this.parseTar(tarBuffer);
|
|
27782
|
+
const cacheArl = this.arp.parse(this.toArpUrl(this.cacheDir));
|
|
27783
|
+
await cacheArl.mkdir();
|
|
27784
|
+
for (const [path, content] of files) {
|
|
27785
|
+
const parts = path.split("/");
|
|
27786
|
+
if (parts.length < 2)
|
|
27787
|
+
continue;
|
|
27788
|
+
const relativePath = parts.slice(1).join("/");
|
|
27789
|
+
if (!relativePath)
|
|
27790
|
+
continue;
|
|
27791
|
+
const fullPath = join5(this.cacheDir, relativePath);
|
|
27792
|
+
const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
|
|
27793
|
+
if (parentDir) {
|
|
27794
|
+
const parentArl = this.arp.parse(this.toArpUrl(parentDir));
|
|
27795
|
+
await parentArl.mkdir();
|
|
27796
|
+
}
|
|
27797
|
+
const fileArl = this.arp.parse(this.toArpUrl(fullPath));
|
|
27798
|
+
await fileArl.deposit(content);
|
|
27799
|
+
}
|
|
27491
27800
|
}
|
|
27492
|
-
|
|
27493
|
-
|
|
27801
|
+
parseTar(tarBuffer) {
|
|
27802
|
+
const files = new Map;
|
|
27803
|
+
let offset = 0;
|
|
27804
|
+
while (offset < tarBuffer.length) {
|
|
27805
|
+
const header = tarBuffer.subarray(offset, offset + 512);
|
|
27806
|
+
if (header[0] === 0) {
|
|
27807
|
+
break;
|
|
27808
|
+
}
|
|
27809
|
+
let filename = "";
|
|
27810
|
+
for (let i = 0;i < 100 && header[i] !== 0; i++) {
|
|
27811
|
+
filename += String.fromCharCode(header[i]);
|
|
27812
|
+
}
|
|
27813
|
+
let prefix = "";
|
|
27814
|
+
for (let i = 345;i < 500 && header[i] !== 0; i++) {
|
|
27815
|
+
prefix += String.fromCharCode(header[i]);
|
|
27816
|
+
}
|
|
27817
|
+
if (prefix) {
|
|
27818
|
+
filename = prefix + "/" + filename;
|
|
27819
|
+
}
|
|
27820
|
+
let sizeStr = "";
|
|
27821
|
+
for (let i = 124;i < 136 && header[i] !== 0 && header[i] !== 32; i++) {
|
|
27822
|
+
sizeStr += String.fromCharCode(header[i]);
|
|
27823
|
+
}
|
|
27824
|
+
const size = parseInt(sizeStr, 8) || 0;
|
|
27825
|
+
const typeFlag = header[156];
|
|
27826
|
+
offset += 512;
|
|
27827
|
+
if (typeFlag === 48 || typeFlag === 0) {
|
|
27828
|
+
if (size > 0) {
|
|
27829
|
+
const content = tarBuffer.subarray(offset, offset + size);
|
|
27830
|
+
files.set(filename, Buffer.from(content));
|
|
27831
|
+
}
|
|
27832
|
+
}
|
|
27833
|
+
offset += Math.ceil(size / 512) * 512;
|
|
27834
|
+
}
|
|
27835
|
+
return files;
|
|
27494
27836
|
}
|
|
27495
|
-
|
|
27496
|
-
|
|
27837
|
+
buildResourcePath(locator) {
|
|
27838
|
+
const rxl = parseRXL(locator);
|
|
27839
|
+
const domain = rxl.domain ?? "localhost";
|
|
27840
|
+
const version = rxl.version ?? "latest";
|
|
27841
|
+
let path = join5(this.cacheDir, this.basePath, domain);
|
|
27842
|
+
if (rxl.path) {
|
|
27843
|
+
path = join5(path, rxl.path);
|
|
27844
|
+
}
|
|
27845
|
+
const resourceName = rxl.type ? `${rxl.name}.${rxl.type}` : rxl.name;
|
|
27846
|
+
return join5(path, resourceName, version);
|
|
27497
27847
|
}
|
|
27498
|
-
|
|
27499
|
-
|
|
27848
|
+
async get(locator) {
|
|
27849
|
+
await this.ensureDownloaded();
|
|
27850
|
+
const resourcePath = this.buildResourcePath(locator);
|
|
27851
|
+
const manifestPath = join5(resourcePath, "manifest.json");
|
|
27852
|
+
const manifestArl = this.arp.parse(this.toArpUrl(manifestPath));
|
|
27853
|
+
if (!await manifestArl.exists()) {
|
|
27854
|
+
throw new RegistryError(`Resource not found: ${locator}`);
|
|
27855
|
+
}
|
|
27856
|
+
const manifestResource = await manifestArl.resolve();
|
|
27857
|
+
const manifestContent = manifestResource.content.toString("utf-8");
|
|
27858
|
+
const manifestData = JSON.parse(manifestContent);
|
|
27859
|
+
const manifest = createRXM(manifestData);
|
|
27860
|
+
const contentPath = join5(resourcePath, "archive.tar.gz");
|
|
27861
|
+
const contentArl = this.arp.parse(this.toArpUrl(contentPath));
|
|
27862
|
+
const contentResource = await contentArl.resolve();
|
|
27863
|
+
const data = contentResource.content;
|
|
27864
|
+
return this.typeHandler.deserialize(data, manifest);
|
|
27500
27865
|
}
|
|
27501
|
-
|
|
27502
|
-
|
|
27866
|
+
async resolve(locator) {
|
|
27867
|
+
const rxr = await this.get(locator);
|
|
27868
|
+
return this.typeHandler.resolve(rxr);
|
|
27503
27869
|
}
|
|
27504
|
-
|
|
27505
|
-
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27511
|
-
|
|
27870
|
+
async exists(locator) {
|
|
27871
|
+
try {
|
|
27872
|
+
await this.ensureDownloaded();
|
|
27873
|
+
const resourcePath = this.buildResourcePath(locator);
|
|
27874
|
+
const manifestPath = join5(resourcePath, "manifest.json");
|
|
27875
|
+
const manifestArl = this.arp.parse(this.toArpUrl(manifestPath));
|
|
27876
|
+
return await manifestArl.exists();
|
|
27877
|
+
} catch {
|
|
27878
|
+
return false;
|
|
27879
|
+
}
|
|
27512
27880
|
}
|
|
27513
|
-
|
|
27514
|
-
|
|
27515
|
-
|
|
27881
|
+
async search(options) {
|
|
27882
|
+
await this.ensureDownloaded();
|
|
27883
|
+
const { query, limit, offset = 0 } = options ?? {};
|
|
27884
|
+
const locators = [];
|
|
27885
|
+
const baseDir = join5(this.cacheDir, this.basePath);
|
|
27886
|
+
try {
|
|
27887
|
+
const baseArl = this.arp.parse(this.toArpUrl(baseDir));
|
|
27888
|
+
const entries = await baseArl.list({ recursive: true, pattern: "*.json" });
|
|
27889
|
+
for (const entry of entries) {
|
|
27890
|
+
if (!entry.endsWith("manifest.json"))
|
|
27891
|
+
continue;
|
|
27892
|
+
const rxl = this.parseEntryToRXL(entry);
|
|
27893
|
+
if (rxl)
|
|
27894
|
+
locators.push(rxl);
|
|
27895
|
+
}
|
|
27896
|
+
} catch {
|
|
27897
|
+
return [];
|
|
27898
|
+
}
|
|
27899
|
+
let filtered = locators;
|
|
27900
|
+
if (query) {
|
|
27901
|
+
const lowerQuery = query.toLowerCase();
|
|
27902
|
+
filtered = locators.filter((rxl) => {
|
|
27903
|
+
const searchText = `${rxl.domain ?? ""} ${rxl.path ?? ""} ${rxl.name} ${rxl.type ?? ""}`.toLowerCase();
|
|
27904
|
+
return searchText.includes(lowerQuery);
|
|
27905
|
+
});
|
|
27906
|
+
}
|
|
27907
|
+
let result = filtered.slice(offset);
|
|
27908
|
+
if (limit !== undefined) {
|
|
27909
|
+
result = result.slice(0, limit);
|
|
27516
27910
|
}
|
|
27911
|
+
return result;
|
|
27517
27912
|
}
|
|
27518
|
-
|
|
27519
|
-
const
|
|
27520
|
-
|
|
27521
|
-
|
|
27913
|
+
parseEntryToRXL(entry) {
|
|
27914
|
+
const dirPath = entry.replace(/[/\\]manifest\.json$/, "");
|
|
27915
|
+
const parts = dirPath.split(/[/\\]/);
|
|
27916
|
+
if (parts.length < 3)
|
|
27917
|
+
return null;
|
|
27918
|
+
const version = parts.pop();
|
|
27919
|
+
const nameTypePart = parts.pop();
|
|
27920
|
+
const domain = parts.shift();
|
|
27921
|
+
const path = parts.length > 0 ? parts.join("/") : undefined;
|
|
27922
|
+
const dotIndex = nameTypePart.lastIndexOf(".");
|
|
27923
|
+
let name;
|
|
27924
|
+
let type;
|
|
27925
|
+
if (dotIndex !== -1) {
|
|
27926
|
+
name = nameTypePart.substring(0, dotIndex);
|
|
27927
|
+
type = nameTypePart.substring(dotIndex + 1);
|
|
27928
|
+
} else {
|
|
27929
|
+
name = nameTypePart;
|
|
27930
|
+
type = undefined;
|
|
27931
|
+
}
|
|
27932
|
+
let locatorStr = domain;
|
|
27933
|
+
if (path)
|
|
27934
|
+
locatorStr += `/${path}`;
|
|
27935
|
+
locatorStr += `/${name}`;
|
|
27936
|
+
if (type)
|
|
27937
|
+
locatorStr += `.${type}`;
|
|
27938
|
+
locatorStr += `@${version}`;
|
|
27939
|
+
try {
|
|
27940
|
+
return parseRXL(locatorStr);
|
|
27941
|
+
} catch {
|
|
27942
|
+
return null;
|
|
27943
|
+
}
|
|
27522
27944
|
}
|
|
27523
|
-
async
|
|
27524
|
-
|
|
27525
|
-
|
|
27526
|
-
|
|
27945
|
+
async link(_path) {
|
|
27946
|
+
throw new RegistryError("GitHubRegistry is read-only - use LocalRegistry.link()");
|
|
27947
|
+
}
|
|
27948
|
+
async add(_source) {
|
|
27949
|
+
throw new RegistryError("GitHubRegistry is read-only - use LocalRegistry.add()");
|
|
27950
|
+
}
|
|
27951
|
+
async pull(_locator, _options) {
|
|
27952
|
+
throw new RegistryError("GitHubRegistry is read-only - use LocalRegistry.pull()");
|
|
27953
|
+
}
|
|
27954
|
+
async publish(_source, _options) {
|
|
27955
|
+
throw new RegistryError("GitHubRegistry is read-only - use LocalRegistry.publish()");
|
|
27956
|
+
}
|
|
27957
|
+
async delete(_locator) {
|
|
27958
|
+
throw new RegistryError("GitHubRegistry is read-only - use LocalRegistry.delete()");
|
|
27527
27959
|
}
|
|
27528
|
-
}
|
|
27529
|
-
function withDomainValidation(registry, trustedDomain) {
|
|
27530
|
-
return new DomainValidation(registry, trustedDomain);
|
|
27531
27960
|
}
|
|
27532
27961
|
|
|
27533
27962
|
// src/createRegistry.ts
|
|
27534
|
-
|
|
27963
|
+
var URL_HANDLERS = [
|
|
27964
|
+
GitHubRegistry,
|
|
27965
|
+
GitRegistry,
|
|
27966
|
+
RemoteRegistry
|
|
27967
|
+
];
|
|
27968
|
+
function isRemoteUrl(url) {
|
|
27535
27969
|
return url.startsWith("git@") || url.startsWith("https://") || url.startsWith("http://");
|
|
27536
27970
|
}
|
|
27537
27971
|
function createRegistry(config) {
|
|
27538
27972
|
if (isRemoteConfig(config)) {
|
|
27539
27973
|
return new RemoteRegistry(config);
|
|
27540
27974
|
}
|
|
27975
|
+
if (isGitHubConfig(config)) {
|
|
27976
|
+
const registry = new GitHubRegistry(config);
|
|
27977
|
+
return config.domain ? withDomainValidation(registry, config.domain) : registry;
|
|
27978
|
+
}
|
|
27541
27979
|
if (isGitConfig(config)) {
|
|
27542
|
-
if (
|
|
27980
|
+
if (isRemoteUrl(config.url) && !config.domain) {
|
|
27543
27981
|
throw new RegistryError(`Remote git registry requires a trusted domain.
|
|
27544
27982
|
|
|
27545
|
-
` + `
|
|
27546
|
-
` + `
|
|
27547
|
-
` + `2. Explicitly set domain: createRegistry({ type: "git", url: "...", domain: "your-domain.com" })
|
|
27548
|
-
|
|
27549
|
-
` + `This ensures resources from untrusted sources cannot impersonate your domain.`);
|
|
27550
|
-
}
|
|
27551
|
-
const gitRegistry = new GitRegistry(config);
|
|
27552
|
-
if (config.domain) {
|
|
27553
|
-
return withDomainValidation(gitRegistry, config.domain);
|
|
27983
|
+
` + `Use discoverRegistry() or explicitly set domain:
|
|
27984
|
+
` + `createRegistry({ type: "git", url: "...", domain: "your-domain.com" })`);
|
|
27554
27985
|
}
|
|
27555
|
-
|
|
27986
|
+
const registry = new GitRegistry(config);
|
|
27987
|
+
return config.domain ? withDomainValidation(registry, config.domain) : registry;
|
|
27988
|
+
}
|
|
27989
|
+
if (isUrlConfig(config)) {
|
|
27990
|
+
return createFromUrl(config);
|
|
27556
27991
|
}
|
|
27557
27992
|
return new LocalRegistry(config);
|
|
27558
27993
|
}
|
|
27994
|
+
function createFromUrl(config) {
|
|
27995
|
+
const { url, domain } = config;
|
|
27996
|
+
if (isRemoteUrl(url) && !domain) {
|
|
27997
|
+
throw new RegistryError(`Remote registry URL requires a trusted domain.
|
|
27998
|
+
|
|
27999
|
+
` + `Use discoverRegistry() or explicitly set domain:
|
|
28000
|
+
` + `createRegistry({ url: "...", domain: "your-domain.com" })`);
|
|
28001
|
+
}
|
|
28002
|
+
for (const Handler of URL_HANDLERS) {
|
|
28003
|
+
if (Handler.canHandle(url)) {
|
|
28004
|
+
return Handler.create(config);
|
|
28005
|
+
}
|
|
28006
|
+
}
|
|
28007
|
+
throw new RegistryError(`No handler found for URL: ${url}`);
|
|
28008
|
+
}
|
|
27559
28009
|
export {
|
|
27560
28010
|
withDomainValidation,
|
|
27561
|
-
isRemoteConfig,
|
|
27562
|
-
isGitConfig,
|
|
27563
28011
|
discoverRegistry,
|
|
27564
28012
|
createRegistry,
|
|
27565
|
-
RemoteRegistry,
|
|
27566
28013
|
RegistryMiddleware,
|
|
27567
28014
|
RegistryError,
|
|
27568
28015
|
LocalRegistry,
|
|
27569
|
-
GitRegistry,
|
|
27570
28016
|
DomainValidation
|
|
27571
28017
|
};
|
|
27572
28018
|
|
|
27573
|
-
//# debugId=
|
|
28019
|
+
//# debugId=4521F4F0C842396664756E2164756E21
|