@noosphere/registry 0.1.0-alpha.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 ADDED
@@ -0,0 +1,304 @@
1
+ # @noosphere/registry
2
+
3
+ Container and Verifier registry manager for Noosphere SDK.
4
+
5
+ ## Features
6
+
7
+ - **Local Registry**: JSON-based local registry (`.noosphere/registry.json`)
8
+ - **Remote Sync**: Automatically sync from GitHub public registry
9
+ - **Container Discovery**: Find and search compute containers
10
+ - **Verifier Discovery**: Find proof verifiers by contract address
11
+ - **Custom Entries**: Add your own containers and verifiers
12
+ - **Cache Management**: Configurable TTL for remote sync
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @noosphere/registry
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Basic Usage
23
+
24
+ ```typescript
25
+ import { RegistryManager } from '@noosphere/registry';
26
+
27
+ // Create registry manager
28
+ const registry = new RegistryManager({
29
+ localPath: './.noosphere/registry.json', // Optional
30
+ remotePath: 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json', // Optional
31
+ autoSync: true, // Sync from remote on load
32
+ cacheTTL: 3600000, // 1 hour cache
33
+ });
34
+
35
+ // Load registry
36
+ await registry.load();
37
+
38
+ // Get container by ID
39
+ const container = registry.getContainer('0x123...');
40
+ console.log(container.name); // "stable-diffusion-xl"
41
+ console.log(container.imageName); // "runpod/stable-diffusion"
42
+ console.log(container.requirements); // { gpu: true, memory: "16GB" }
43
+
44
+ // Search containers
45
+ const aiContainers = registry.searchContainers('ai');
46
+
47
+ // List all active containers
48
+ const containers = registry.listContainers();
49
+
50
+ // Get verifier by contract address
51
+ const verifier = registry.getVerifier('0x0165878A594ca255338adfa4d48449f69242Eb8F');
52
+ console.log(verifier.name); // "Immediate Finalize Verifier"
53
+
54
+ // Check if proof generation is required
55
+ if (verifier.requiresProof && verifier.proofService) {
56
+ console.log('Proof service:', verifier.proofService.imageName);
57
+ console.log('Proof service port:', verifier.proofService.port);
58
+ }
59
+ ```
60
+
61
+ ### Adding Custom Containers
62
+
63
+ ```typescript
64
+ await registry.addContainer({
65
+ id: '0xabc...',
66
+ name: 'my-custom-model',
67
+ imageName: 'myrepo/my-model',
68
+ port: 8000,
69
+ requirements: {
70
+ gpu: true,
71
+ memory: '8GB',
72
+ cpu: 4,
73
+ },
74
+ statusCode: 'ACTIVE',
75
+ description: 'My custom AI model',
76
+ tags: ['ai', 'custom'],
77
+ });
78
+ ```
79
+
80
+ ### Adding Custom Verifiers
81
+
82
+ ```typescript
83
+ // Verifier with integrated proof generation service
84
+ await registry.addVerifier({
85
+ id: 'custom-verifier-id',
86
+ name: 'My Custom Verifier',
87
+ verifierAddress: '0x222...', // Onchain verifier contract address
88
+ requiresProof: true,
89
+ proofService: {
90
+ imageName: 'myrepo/my-proof-service',
91
+ port: 3000,
92
+ command: 'npm start',
93
+ env: {
94
+ RPC_URL: 'https://...',
95
+ VERIFIER_ADDRESS: '0x222...',
96
+ },
97
+ requirements: {
98
+ memory: '2GB',
99
+ cpu: 2,
100
+ },
101
+ },
102
+ statusCode: 'ACTIVE',
103
+ description: 'Custom proof verification with integrated proof generation',
104
+ });
105
+
106
+ // Simple verifier without proof generation
107
+ await registry.addVerifier({
108
+ id: 'simple-verifier-id',
109
+ name: 'Simple Verifier',
110
+ verifierAddress: '0x333...',
111
+ requiresProof: false,
112
+ statusCode: 'ACTIVE',
113
+ description: 'Simple verification without proof generation',
114
+ });
115
+ ```
116
+
117
+ ### Registry Statistics
118
+
119
+ ```typescript
120
+ const stats = registry.getStats();
121
+ console.log(stats);
122
+ // {
123
+ // totalContainers: 10,
124
+ // activeContainers: 8,
125
+ // totalVerifiers: 2,
126
+ // activeVerifiers: 2,
127
+ // lastSync: '2024-12-26T00:00:00.000Z'
128
+ // }
129
+ ```
130
+
131
+ ## Registry Format
132
+
133
+ ### Container Metadata
134
+
135
+ ```typescript
136
+ interface ContainerMetadata {
137
+ id: string; // Unique ID (keccak256 hash)
138
+ name: string; // Human-readable name
139
+ imageName: string; // Docker image name
140
+ port?: number; // Exposed port
141
+ command?: string; // Docker command
142
+ env?: Record<string, string>; // Environment variables
143
+ volumes?: string[]; // Volume mounts
144
+ requirements?: {
145
+ gpu?: boolean;
146
+ memory?: string; // "16GB"
147
+ cpu?: number;
148
+ };
149
+ payments?: {
150
+ basePrice: string; // "0.01"
151
+ token: string; // "ETH"
152
+ per: string; // "inference"
153
+ };
154
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
155
+ verified?: boolean; // Community verified
156
+ description?: string;
157
+ tags?: string[];
158
+ createdAt?: string;
159
+ updatedAt?: string;
160
+ }
161
+ ```
162
+
163
+ ### Verifier Metadata
164
+
165
+ ```typescript
166
+ interface ProofServiceConfig {
167
+ imageName: string; // Docker image for proof generation service
168
+ port: number; // Exposed port
169
+ command?: string; // Docker command
170
+ env?: Record<string, string>; // Environment variables
171
+ volumes?: string[]; // Volume mounts
172
+ requirements?: {
173
+ memory?: string; // "2GB"
174
+ cpu?: number;
175
+ gpu?: boolean;
176
+ };
177
+ }
178
+
179
+ interface VerifierMetadata {
180
+ id: string; // UUID
181
+ name: string;
182
+ verifierAddress: string; // Onchain contract address (used as key)
183
+ requiresProof?: boolean; // Whether this verifier requires proof generation
184
+ proofService?: ProofServiceConfig; // Proof generation service configuration
185
+
186
+ // Deprecated: Use proofService instead
187
+ imageName?: string; // Docker image for proof generation
188
+ port?: number;
189
+ command?: string;
190
+ env?: Record<string, string>;
191
+ volumes?: string[];
192
+
193
+ payments?: {
194
+ basePrice: string;
195
+ token: string;
196
+ per: string;
197
+ };
198
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
199
+ verified?: boolean;
200
+ description?: string;
201
+ createdAt?: string;
202
+ updatedAt?: string;
203
+ }
204
+ ```
205
+
206
+ ## Working with Proof Generation
207
+
208
+ When a verifier requires proof generation, you'll need to start the proof service container and interact with it:
209
+
210
+ ```typescript
211
+ import { RegistryManager } from '@noosphere/registry';
212
+
213
+ // Load registry
214
+ const registry = new RegistryManager();
215
+ await registry.load();
216
+
217
+ // Get verifier for a subscription
218
+ const verifier = registry.getVerifier('0x0165878A594ca255338adfa4d48449f69242Eb8F');
219
+
220
+ // Check if proof generation is required
221
+ if (verifier.requiresProof && verifier.proofService) {
222
+ // Start proof service container
223
+ const proofContainer = await containerManager.start({
224
+ imageName: verifier.proofService.imageName,
225
+ port: verifier.proofService.port,
226
+ command: verifier.proofService.command,
227
+ env: {
228
+ ...verifier.proofService.env,
229
+ RPC_URL: process.env.RPC_URL,
230
+ CHAIN_ID: process.env.CHAIN_ID,
231
+ VERIFIER_ADDRESS: verifier.verifierAddress,
232
+ },
233
+ });
234
+
235
+ // Generate proof
236
+ const proof = await fetch(`http://localhost:${verifier.proofService.port}/generate-proof`, {
237
+ method: 'POST',
238
+ headers: { 'Content-Type': 'application/json' },
239
+ body: JSON.stringify({
240
+ requestId,
241
+ subscriptionId,
242
+ interval: commitment.interval,
243
+ output: computeResult,
244
+ }),
245
+ }).then(r => r.json());
246
+
247
+ console.log('Proof generated:', proof);
248
+ // Proof service typically handles on-chain submission automatically
249
+ }
250
+ ```
251
+
252
+ See the [community registry integration guide](https://github.com/hpp-io/noosphere-registry/blob/main/VERIFIER_INTEGRATION.md) for complete examples.
253
+
254
+ ## Local Registry Path
255
+
256
+ Default: `.noosphere/registry.json`
257
+
258
+ The registry file is automatically created with example entries if it doesn't exist.
259
+
260
+ ## Remote Registry
261
+
262
+ Default: `https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json`
263
+
264
+ The remote registry is a community-maintained list of verified containers and verifiers.
265
+
266
+ ### Merge Strategy
267
+
268
+ - Remote entries are added to local registry
269
+ - **Local entries take precedence** (not overwritten by remote)
270
+ - Manual additions are saved locally only
271
+
272
+ ## Registry Priority
273
+
274
+ 1. **Local registry** (highest priority)
275
+ 2. **Remote registry** (synced from GitHub)
276
+
277
+ This allows you to:
278
+ - Use community-verified containers
279
+ - Override remote entries locally
280
+ - Add private/custom containers
281
+
282
+ ## Example Registry
283
+
284
+ See `examples/registry-example.json` for a complete example with:
285
+ - Echo service (for testing)
286
+ - Stable Diffusion XL (image generation)
287
+ - Llama 3 8B (text generation)
288
+ - Whisper Large V3 (speech-to-text)
289
+ - ZK-SNARK verifiers
290
+
291
+ ## Contributing
292
+
293
+ To contribute containers/verifiers to the public registry:
294
+
295
+ 1. Fork `hpp-io/noosphere-registry`
296
+ 2. Add your entry to `registry.json`
297
+ 3. Submit a pull request with:
298
+ - Container/Verifier metadata
299
+ - Verification that it works
300
+ - Documentation
301
+
302
+ ## License
303
+
304
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ RegistryManager: () => RegistryManager
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/RegistryManager.ts
38
+ var import_promises = __toESM(require("fs/promises"));
39
+ var import_path = __toESM(require("path"));
40
+ var import_node_fetch = __toESM(require("node-fetch"));
41
+ var RegistryManager = class {
42
+ constructor(config = {}) {
43
+ this.containers = /* @__PURE__ */ new Map();
44
+ this.verifiers = /* @__PURE__ */ new Map();
45
+ this.lastSync = 0;
46
+ this.config = {
47
+ localPath: config.localPath || import_path.default.join(process.cwd(), ".noosphere", "registry.json"),
48
+ remotePath: config.remotePath || "https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json",
49
+ autoSync: config.autoSync ?? true,
50
+ cacheTTL: config.cacheTTL || 36e5
51
+ // 1 hour default
52
+ };
53
+ }
54
+ /**
55
+ * Load registry from local and optionally sync from remote
56
+ */
57
+ async load() {
58
+ await this.loadLocal();
59
+ if (this.config.autoSync) {
60
+ try {
61
+ await this.sync();
62
+ } catch (error) {
63
+ console.warn("Failed to sync remote registry:", error);
64
+ console.log("Continuing with local registry only");
65
+ }
66
+ }
67
+ console.log(`\u2713 Loaded ${this.containers.size} containers and ${this.verifiers.size} verifiers`);
68
+ }
69
+ /**
70
+ * Load local registry file
71
+ */
72
+ async loadLocal() {
73
+ try {
74
+ const data = await import_promises.default.readFile(this.config.localPath, "utf-8");
75
+ const registry = JSON.parse(data);
76
+ Object.entries(registry.containers || {}).forEach(([id, metadata]) => {
77
+ this.containers.set(id, metadata);
78
+ });
79
+ Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {
80
+ this.verifiers.set(id, metadata);
81
+ });
82
+ console.log(`\u2713 Loaded local registry from ${this.config.localPath}`);
83
+ } catch (error) {
84
+ if (error.code === "ENOENT") {
85
+ console.log("No local registry found, will create default");
86
+ await this.createDefaultRegistry();
87
+ } else {
88
+ throw error;
89
+ }
90
+ }
91
+ }
92
+ /**
93
+ * Sync registry from remote GitHub repository
94
+ */
95
+ async sync() {
96
+ const now = Date.now();
97
+ if (now - this.lastSync < this.config.cacheTTL) {
98
+ console.log("Registry cache is fresh, skipping sync");
99
+ return;
100
+ }
101
+ console.log(`Syncing registry from ${this.config.remotePath}...`);
102
+ try {
103
+ const response = await (0, import_node_fetch.default)(this.config.remotePath);
104
+ if (!response.ok) {
105
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
106
+ }
107
+ const registry = await response.json();
108
+ Object.entries(registry.containers || {}).forEach(([id, metadata]) => {
109
+ if (!this.containers.has(id)) {
110
+ this.containers.set(id, metadata);
111
+ }
112
+ });
113
+ Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {
114
+ if (!this.verifiers.has(id)) {
115
+ this.verifiers.set(id, metadata);
116
+ }
117
+ });
118
+ this.lastSync = now;
119
+ console.log(`\u2713 Synced registry (version: ${registry.version})`);
120
+ } catch (error) {
121
+ console.error("Failed to sync remote registry:", error);
122
+ throw error;
123
+ }
124
+ }
125
+ /**
126
+ * Get container by ID
127
+ */
128
+ getContainer(id) {
129
+ return this.containers.get(id);
130
+ }
131
+ /**
132
+ * Get all containers
133
+ */
134
+ listContainers() {
135
+ return Array.from(this.containers.values()).filter((c) => c.statusCode === "ACTIVE");
136
+ }
137
+ /**
138
+ * Search containers by name or tag
139
+ */
140
+ searchContainers(query) {
141
+ const lowerQuery = query.toLowerCase();
142
+ return this.listContainers().filter(
143
+ (c) => c.name.toLowerCase().includes(lowerQuery) || c.description?.toLowerCase().includes(lowerQuery) || c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))
144
+ );
145
+ }
146
+ /**
147
+ * Get verifier by contract address
148
+ */
149
+ getVerifier(verifierAddress) {
150
+ return this.verifiers.get(verifierAddress);
151
+ }
152
+ /**
153
+ * Get verifier by ID
154
+ */
155
+ getVerifierById(id) {
156
+ return Array.from(this.verifiers.values()).find((v) => v.id === id);
157
+ }
158
+ /**
159
+ * Get all verifiers
160
+ */
161
+ listVerifiers() {
162
+ return Array.from(this.verifiers.values()).filter((v) => v.statusCode === "ACTIVE");
163
+ }
164
+ /**
165
+ * Add custom container to local registry
166
+ */
167
+ async addContainer(container) {
168
+ this.containers.set(container.id, container);
169
+ await this.saveLocal();
170
+ console.log(`\u2713 Added container: ${container.name} (${container.id})`);
171
+ }
172
+ /**
173
+ * Add custom verifier to local registry
174
+ */
175
+ async addVerifier(verifier) {
176
+ this.verifiers.set(verifier.verifierAddress, verifier);
177
+ await this.saveLocal();
178
+ console.log(`\u2713 Added verifier: ${verifier.name} (${verifier.verifierAddress})`);
179
+ }
180
+ /**
181
+ * Remove container from local registry
182
+ */
183
+ async removeContainer(id) {
184
+ if (this.containers.delete(id)) {
185
+ await this.saveLocal();
186
+ console.log(`\u2713 Removed container: ${id}`);
187
+ }
188
+ }
189
+ /**
190
+ * Remove verifier from local registry
191
+ */
192
+ async removeVerifier(verifierAddress) {
193
+ if (this.verifiers.delete(verifierAddress)) {
194
+ await this.saveLocal();
195
+ console.log(`\u2713 Removed verifier: ${verifierAddress}`);
196
+ }
197
+ }
198
+ /**
199
+ * Save local registry to disk
200
+ */
201
+ async saveLocal() {
202
+ const registry = {
203
+ containers: Object.fromEntries(this.containers),
204
+ verifiers: Object.fromEntries(this.verifiers),
205
+ version: "1.0.0",
206
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
207
+ };
208
+ await import_promises.default.mkdir(import_path.default.dirname(this.config.localPath), { recursive: true });
209
+ await import_promises.default.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));
210
+ }
211
+ /**
212
+ * Create default registry with example entries
213
+ */
214
+ async createDefaultRegistry() {
215
+ await this.saveLocal();
216
+ console.log("\u2713 Created empty local registry (will sync from remote)");
217
+ }
218
+ /**
219
+ * Get registry statistics
220
+ */
221
+ getStats() {
222
+ return {
223
+ totalContainers: this.containers.size,
224
+ activeContainers: this.listContainers().length,
225
+ totalVerifiers: this.verifiers.size,
226
+ activeVerifiers: this.listVerifiers().length,
227
+ lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : "Never"
228
+ };
229
+ }
230
+ };
231
+ // Annotate the CommonJS export names for ESM import in node:
232
+ 0 && (module.exports = {
233
+ RegistryManager
234
+ });
235
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/RegistryManager.ts"],"sourcesContent":["export { RegistryManager } from './RegistryManager';\nexport * from './types';\n","import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n */\n async load(): Promise<void> {\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers and ${this.verifiers.size} verifiers`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n this.lastSync = now;\n console.log(`✓ Synced registry (version: ${registry.version})`);\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":"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","names":["path","fs","fetch"]}
@@ -0,0 +1,151 @@
1
+ interface ContainerMetadata {
2
+ id: string;
3
+ name: string;
4
+ imageName: string;
5
+ port?: number;
6
+ command?: string;
7
+ env?: Record<string, string>;
8
+ volumes?: string[];
9
+ payments?: {
10
+ basePrice: string;
11
+ token: string;
12
+ per: string;
13
+ };
14
+ requirements?: {
15
+ memory?: string;
16
+ cpu?: number;
17
+ gpu?: boolean;
18
+ };
19
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
20
+ verified?: boolean;
21
+ createdAt?: string;
22
+ updatedAt?: string;
23
+ description?: string;
24
+ tags?: string[];
25
+ }
26
+ interface ProofServiceConfig {
27
+ imageName: string;
28
+ port: number;
29
+ command?: string;
30
+ env?: Record<string, string>;
31
+ volumes?: string[];
32
+ requirements?: {
33
+ memory?: string;
34
+ cpu?: number;
35
+ gpu?: boolean;
36
+ };
37
+ }
38
+ interface VerifierMetadata {
39
+ id: string;
40
+ name: string;
41
+ verifierAddress: string;
42
+ requiresProof?: boolean;
43
+ proofService?: ProofServiceConfig;
44
+ imageName?: string;
45
+ port?: number;
46
+ command?: string;
47
+ env?: Record<string, string>;
48
+ volumes?: string[];
49
+ payments?: {
50
+ basePrice: string;
51
+ token: string;
52
+ per: string;
53
+ };
54
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
55
+ verified?: boolean;
56
+ createdAt?: string;
57
+ updatedAt?: string;
58
+ description?: string;
59
+ }
60
+ interface RegistryConfig {
61
+ localPath?: string;
62
+ remotePath?: string;
63
+ autoSync?: boolean;
64
+ cacheTTL?: number;
65
+ }
66
+ interface RegistryIndex {
67
+ containers: Record<string, ContainerMetadata>;
68
+ verifiers: Record<string, VerifierMetadata>;
69
+ version: string;
70
+ updatedAt: string;
71
+ }
72
+
73
+ declare class RegistryManager {
74
+ private containers;
75
+ private verifiers;
76
+ private config;
77
+ private lastSync;
78
+ constructor(config?: RegistryConfig);
79
+ /**
80
+ * Load registry from local and optionally sync from remote
81
+ */
82
+ load(): Promise<void>;
83
+ /**
84
+ * Load local registry file
85
+ */
86
+ private loadLocal;
87
+ /**
88
+ * Sync registry from remote GitHub repository
89
+ */
90
+ sync(): Promise<void>;
91
+ /**
92
+ * Get container by ID
93
+ */
94
+ getContainer(id: string): ContainerMetadata | undefined;
95
+ /**
96
+ * Get all containers
97
+ */
98
+ listContainers(): ContainerMetadata[];
99
+ /**
100
+ * Search containers by name or tag
101
+ */
102
+ searchContainers(query: string): ContainerMetadata[];
103
+ /**
104
+ * Get verifier by contract address
105
+ */
106
+ getVerifier(verifierAddress: string): VerifierMetadata | undefined;
107
+ /**
108
+ * Get verifier by ID
109
+ */
110
+ getVerifierById(id: string): VerifierMetadata | undefined;
111
+ /**
112
+ * Get all verifiers
113
+ */
114
+ listVerifiers(): VerifierMetadata[];
115
+ /**
116
+ * Add custom container to local registry
117
+ */
118
+ addContainer(container: ContainerMetadata): Promise<void>;
119
+ /**
120
+ * Add custom verifier to local registry
121
+ */
122
+ addVerifier(verifier: VerifierMetadata): Promise<void>;
123
+ /**
124
+ * Remove container from local registry
125
+ */
126
+ removeContainer(id: string): Promise<void>;
127
+ /**
128
+ * Remove verifier from local registry
129
+ */
130
+ removeVerifier(verifierAddress: string): Promise<void>;
131
+ /**
132
+ * Save local registry to disk
133
+ */
134
+ private saveLocal;
135
+ /**
136
+ * Create default registry with example entries
137
+ */
138
+ private createDefaultRegistry;
139
+ /**
140
+ * Get registry statistics
141
+ */
142
+ getStats(): {
143
+ totalContainers: number;
144
+ activeContainers: number;
145
+ totalVerifiers: number;
146
+ activeVerifiers: number;
147
+ lastSync: string;
148
+ };
149
+ }
150
+
151
+ export { type ContainerMetadata, type ProofServiceConfig, type RegistryConfig, type RegistryIndex, RegistryManager, type VerifierMetadata };
@@ -0,0 +1,151 @@
1
+ interface ContainerMetadata {
2
+ id: string;
3
+ name: string;
4
+ imageName: string;
5
+ port?: number;
6
+ command?: string;
7
+ env?: Record<string, string>;
8
+ volumes?: string[];
9
+ payments?: {
10
+ basePrice: string;
11
+ token: string;
12
+ per: string;
13
+ };
14
+ requirements?: {
15
+ memory?: string;
16
+ cpu?: number;
17
+ gpu?: boolean;
18
+ };
19
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
20
+ verified?: boolean;
21
+ createdAt?: string;
22
+ updatedAt?: string;
23
+ description?: string;
24
+ tags?: string[];
25
+ }
26
+ interface ProofServiceConfig {
27
+ imageName: string;
28
+ port: number;
29
+ command?: string;
30
+ env?: Record<string, string>;
31
+ volumes?: string[];
32
+ requirements?: {
33
+ memory?: string;
34
+ cpu?: number;
35
+ gpu?: boolean;
36
+ };
37
+ }
38
+ interface VerifierMetadata {
39
+ id: string;
40
+ name: string;
41
+ verifierAddress: string;
42
+ requiresProof?: boolean;
43
+ proofService?: ProofServiceConfig;
44
+ imageName?: string;
45
+ port?: number;
46
+ command?: string;
47
+ env?: Record<string, string>;
48
+ volumes?: string[];
49
+ payments?: {
50
+ basePrice: string;
51
+ token: string;
52
+ per: string;
53
+ };
54
+ statusCode: 'ACTIVE' | 'INACTIVE' | 'DEPRECATED';
55
+ verified?: boolean;
56
+ createdAt?: string;
57
+ updatedAt?: string;
58
+ description?: string;
59
+ }
60
+ interface RegistryConfig {
61
+ localPath?: string;
62
+ remotePath?: string;
63
+ autoSync?: boolean;
64
+ cacheTTL?: number;
65
+ }
66
+ interface RegistryIndex {
67
+ containers: Record<string, ContainerMetadata>;
68
+ verifiers: Record<string, VerifierMetadata>;
69
+ version: string;
70
+ updatedAt: string;
71
+ }
72
+
73
+ declare class RegistryManager {
74
+ private containers;
75
+ private verifiers;
76
+ private config;
77
+ private lastSync;
78
+ constructor(config?: RegistryConfig);
79
+ /**
80
+ * Load registry from local and optionally sync from remote
81
+ */
82
+ load(): Promise<void>;
83
+ /**
84
+ * Load local registry file
85
+ */
86
+ private loadLocal;
87
+ /**
88
+ * Sync registry from remote GitHub repository
89
+ */
90
+ sync(): Promise<void>;
91
+ /**
92
+ * Get container by ID
93
+ */
94
+ getContainer(id: string): ContainerMetadata | undefined;
95
+ /**
96
+ * Get all containers
97
+ */
98
+ listContainers(): ContainerMetadata[];
99
+ /**
100
+ * Search containers by name or tag
101
+ */
102
+ searchContainers(query: string): ContainerMetadata[];
103
+ /**
104
+ * Get verifier by contract address
105
+ */
106
+ getVerifier(verifierAddress: string): VerifierMetadata | undefined;
107
+ /**
108
+ * Get verifier by ID
109
+ */
110
+ getVerifierById(id: string): VerifierMetadata | undefined;
111
+ /**
112
+ * Get all verifiers
113
+ */
114
+ listVerifiers(): VerifierMetadata[];
115
+ /**
116
+ * Add custom container to local registry
117
+ */
118
+ addContainer(container: ContainerMetadata): Promise<void>;
119
+ /**
120
+ * Add custom verifier to local registry
121
+ */
122
+ addVerifier(verifier: VerifierMetadata): Promise<void>;
123
+ /**
124
+ * Remove container from local registry
125
+ */
126
+ removeContainer(id: string): Promise<void>;
127
+ /**
128
+ * Remove verifier from local registry
129
+ */
130
+ removeVerifier(verifierAddress: string): Promise<void>;
131
+ /**
132
+ * Save local registry to disk
133
+ */
134
+ private saveLocal;
135
+ /**
136
+ * Create default registry with example entries
137
+ */
138
+ private createDefaultRegistry;
139
+ /**
140
+ * Get registry statistics
141
+ */
142
+ getStats(): {
143
+ totalContainers: number;
144
+ activeContainers: number;
145
+ totalVerifiers: number;
146
+ activeVerifiers: number;
147
+ lastSync: string;
148
+ };
149
+ }
150
+
151
+ export { type ContainerMetadata, type ProofServiceConfig, type RegistryConfig, type RegistryIndex, RegistryManager, type VerifierMetadata };
package/dist/index.js ADDED
@@ -0,0 +1,198 @@
1
+ // src/RegistryManager.ts
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ import fetch from "node-fetch";
5
+ var RegistryManager = class {
6
+ constructor(config = {}) {
7
+ this.containers = /* @__PURE__ */ new Map();
8
+ this.verifiers = /* @__PURE__ */ new Map();
9
+ this.lastSync = 0;
10
+ this.config = {
11
+ localPath: config.localPath || path.join(process.cwd(), ".noosphere", "registry.json"),
12
+ remotePath: config.remotePath || "https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json",
13
+ autoSync: config.autoSync ?? true,
14
+ cacheTTL: config.cacheTTL || 36e5
15
+ // 1 hour default
16
+ };
17
+ }
18
+ /**
19
+ * Load registry from local and optionally sync from remote
20
+ */
21
+ async load() {
22
+ await this.loadLocal();
23
+ if (this.config.autoSync) {
24
+ try {
25
+ await this.sync();
26
+ } catch (error) {
27
+ console.warn("Failed to sync remote registry:", error);
28
+ console.log("Continuing with local registry only");
29
+ }
30
+ }
31
+ console.log(`\u2713 Loaded ${this.containers.size} containers and ${this.verifiers.size} verifiers`);
32
+ }
33
+ /**
34
+ * Load local registry file
35
+ */
36
+ async loadLocal() {
37
+ try {
38
+ const data = await fs.readFile(this.config.localPath, "utf-8");
39
+ const registry = JSON.parse(data);
40
+ Object.entries(registry.containers || {}).forEach(([id, metadata]) => {
41
+ this.containers.set(id, metadata);
42
+ });
43
+ Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {
44
+ this.verifiers.set(id, metadata);
45
+ });
46
+ console.log(`\u2713 Loaded local registry from ${this.config.localPath}`);
47
+ } catch (error) {
48
+ if (error.code === "ENOENT") {
49
+ console.log("No local registry found, will create default");
50
+ await this.createDefaultRegistry();
51
+ } else {
52
+ throw error;
53
+ }
54
+ }
55
+ }
56
+ /**
57
+ * Sync registry from remote GitHub repository
58
+ */
59
+ async sync() {
60
+ const now = Date.now();
61
+ if (now - this.lastSync < this.config.cacheTTL) {
62
+ console.log("Registry cache is fresh, skipping sync");
63
+ return;
64
+ }
65
+ console.log(`Syncing registry from ${this.config.remotePath}...`);
66
+ try {
67
+ const response = await fetch(this.config.remotePath);
68
+ if (!response.ok) {
69
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
70
+ }
71
+ const registry = await response.json();
72
+ Object.entries(registry.containers || {}).forEach(([id, metadata]) => {
73
+ if (!this.containers.has(id)) {
74
+ this.containers.set(id, metadata);
75
+ }
76
+ });
77
+ Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {
78
+ if (!this.verifiers.has(id)) {
79
+ this.verifiers.set(id, metadata);
80
+ }
81
+ });
82
+ this.lastSync = now;
83
+ console.log(`\u2713 Synced registry (version: ${registry.version})`);
84
+ } catch (error) {
85
+ console.error("Failed to sync remote registry:", error);
86
+ throw error;
87
+ }
88
+ }
89
+ /**
90
+ * Get container by ID
91
+ */
92
+ getContainer(id) {
93
+ return this.containers.get(id);
94
+ }
95
+ /**
96
+ * Get all containers
97
+ */
98
+ listContainers() {
99
+ return Array.from(this.containers.values()).filter((c) => c.statusCode === "ACTIVE");
100
+ }
101
+ /**
102
+ * Search containers by name or tag
103
+ */
104
+ searchContainers(query) {
105
+ const lowerQuery = query.toLowerCase();
106
+ return this.listContainers().filter(
107
+ (c) => c.name.toLowerCase().includes(lowerQuery) || c.description?.toLowerCase().includes(lowerQuery) || c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))
108
+ );
109
+ }
110
+ /**
111
+ * Get verifier by contract address
112
+ */
113
+ getVerifier(verifierAddress) {
114
+ return this.verifiers.get(verifierAddress);
115
+ }
116
+ /**
117
+ * Get verifier by ID
118
+ */
119
+ getVerifierById(id) {
120
+ return Array.from(this.verifiers.values()).find((v) => v.id === id);
121
+ }
122
+ /**
123
+ * Get all verifiers
124
+ */
125
+ listVerifiers() {
126
+ return Array.from(this.verifiers.values()).filter((v) => v.statusCode === "ACTIVE");
127
+ }
128
+ /**
129
+ * Add custom container to local registry
130
+ */
131
+ async addContainer(container) {
132
+ this.containers.set(container.id, container);
133
+ await this.saveLocal();
134
+ console.log(`\u2713 Added container: ${container.name} (${container.id})`);
135
+ }
136
+ /**
137
+ * Add custom verifier to local registry
138
+ */
139
+ async addVerifier(verifier) {
140
+ this.verifiers.set(verifier.verifierAddress, verifier);
141
+ await this.saveLocal();
142
+ console.log(`\u2713 Added verifier: ${verifier.name} (${verifier.verifierAddress})`);
143
+ }
144
+ /**
145
+ * Remove container from local registry
146
+ */
147
+ async removeContainer(id) {
148
+ if (this.containers.delete(id)) {
149
+ await this.saveLocal();
150
+ console.log(`\u2713 Removed container: ${id}`);
151
+ }
152
+ }
153
+ /**
154
+ * Remove verifier from local registry
155
+ */
156
+ async removeVerifier(verifierAddress) {
157
+ if (this.verifiers.delete(verifierAddress)) {
158
+ await this.saveLocal();
159
+ console.log(`\u2713 Removed verifier: ${verifierAddress}`);
160
+ }
161
+ }
162
+ /**
163
+ * Save local registry to disk
164
+ */
165
+ async saveLocal() {
166
+ const registry = {
167
+ containers: Object.fromEntries(this.containers),
168
+ verifiers: Object.fromEntries(this.verifiers),
169
+ version: "1.0.0",
170
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
171
+ };
172
+ await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });
173
+ await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));
174
+ }
175
+ /**
176
+ * Create default registry with example entries
177
+ */
178
+ async createDefaultRegistry() {
179
+ await this.saveLocal();
180
+ console.log("\u2713 Created empty local registry (will sync from remote)");
181
+ }
182
+ /**
183
+ * Get registry statistics
184
+ */
185
+ getStats() {
186
+ return {
187
+ totalContainers: this.containers.size,
188
+ activeContainers: this.listContainers().length,
189
+ totalVerifiers: this.verifiers.size,
190
+ activeVerifiers: this.listVerifiers().length,
191
+ lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : "Never"
192
+ };
193
+ }
194
+ };
195
+ export {
196
+ RegistryManager
197
+ };
198
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/RegistryManager.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n */\n async load(): Promise<void> {\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers and ${this.verifiers.size} verifiers`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n this.lastSync = now;\n console.log(`✓ Synced registry (version: ${registry.version})`);\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@noosphere/registry",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Container and Verifier registry for Noosphere SDK",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "require": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.cjs"
13
+ },
14
+ "import": {
15
+ "types": "./dist/index.d.mts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "test": "jest",
26
+ "test:watch": "jest --watch",
27
+ "clean": "rm -rf dist",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "keywords": [
31
+ "noosphere",
32
+ "registry",
33
+ "container",
34
+ "verifier"
35
+ ],
36
+ "author": "Noosphere Team",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/hpp-io/noosphere-sdk.git",
41
+ "directory": "packages/registry"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/hpp-io/noosphere-sdk/issues"
45
+ },
46
+ "homepage": "https://github.com/hpp-io/noosphere-sdk/tree/main/packages/registry#readme",
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "dependencies": {
51
+ "node-fetch": "^3.3.2"
52
+ },
53
+ "devDependencies": {
54
+ "@types/jest": "^29.5.0",
55
+ "@types/node": "^20.10.0",
56
+ "jest": "^29.7.0",
57
+ "ts-jest": "^29.1.0",
58
+ "typescript": "^5.3.0"
59
+ }
60
+ }