# @metatrom/ior-resolver IOR (Interoperable Object Reference) resolver for Metro bundler and Node.js with support for local and remote component fetching. ## Features - 🚀 **Metro Bundler Support** - Seamlessly integrate IOR resolution with React Native projects - 🌐 **Remote Component Fetching** - Load components from GitHub, Gitea, IPFS, and P2P networks - 📦 **Local Component Resolution** - Resolve local components using package.json metadata - 🔄 **Hot Reload Support** - Automatic mapping updates during development - 📝 **TypeScript Support** - Auto-generate type declarations for IOR components - ⚡ **Caching** - Intelligent caching of remote components for better performance - 🛠️ **Pre-build Script** - Generate types before development starts - 🎯 **Shared Core** - Consolidated functions to avoid duplication ## Installation ```bash npm install @metatrom/ior-resolver ``` ## Project Structure ``` @metatrom/ior-resolver/ ├── bin/ # Compiled executable scripts │ ├── prebuild-ior-types.js # Pre-build script for type generation │ └── NodeImportLoader.js # Compiled Node.js loader ├── docs/ # Documentation │ └── IOR_RESOLVER.md # Detailed IOR resolver documentation ├── lib/ # Core library files │ ├── ior-core.js # Shared core functions │ ├── metro-ior-resolver.js # Metro resolver implementation │ └── fetch-remote-component.js # Remote fetching utility ├── plugins/ # Babel and bundler plugins │ └── babel-plugin-ior.js # Babel plugin for IOR imports ├── src/ # Source files │ └── loaders/ │ └── NodeImportLoader.ts # Node.js loader TypeScript source ├── index.js # Main entry point ├── index.d.ts # TypeScript definitions └── package.json ``` ## Usage ### Metro Configuration (React Native) In your `metro.config.js`: ```javascript const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const { createHotReloadableResolver } = require('@metatrom/ior-resolver'); const defaultConfig = getDefaultConfig(__dirname); const config = { resolver: { resolveRequest: createHotReloadableResolver(__dirname), }, }; module.exports = mergeConfig(defaultConfig, config); ``` ### Node.js Loader For Node.js projects using TypeScript and IOR imports: ```javascript // In your loader file import { resolve, load } from '@metatrom/ior-resolver/node'; // Or register the loader import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('@metatrom/ior-resolver/node', pathToFileURL('./')); ``` ### Pre-build Script Add to your `package.json` scripts to generate TypeScript declarations before development: ```json { "scripts": { "prebuild": "prebuild-ior-types", "dev": "npm run prebuild && npm start" } } ``` Or run directly: ```bash npx prebuild-ior-types ``` ## IOR Format IOR (Interoperable Object Reference) provides a unified way to reference components across different sources: ### Local Components ```javascript import Logger from 'ior:esm:com.metatrom.examples.logger@1.0.0'; ``` ### Remote Components #### GitHub ```javascript import Component from 'ior:github:owner/repo:componentname@version'; ``` #### Gitea ```javascript import Component from 'ior:gitea:instance.com:owner/repo:componentname@version'; // Alternative format for repos with slashes in name: import Component from 'ior:gitea:instance.com:owner/repo/componentname@version'; ``` #### IPFS ```javascript import Component from 'ior:ipfs:QmHash:componentname@version'; ``` #### P2P (Coming Soon) ```javascript import Component from 'ior:p2p:peer-id:componentname@version'; ``` ## Component Structure Local components should follow this structure: ``` src/components/ └── componentname/ └── version/ ├── package.json ├── index.ts (or componentname.ts) └── componentname.d.ts (optional) ``` ### package.json Example ```json { "name": "logger", "version": "1.0.0", "main": "index.ts", "metatrom": { "ior": "com.metatrom.examples.logger@1.0.0" } } ``` ## API Reference ### Core Functions (ior-core.js) The shared core module provides common functionality used by both Metro and Node.js implementations: - `parseRemoteIOR(ior)` - Parse remote IOR strings - `parsePackageJson(path)` - Synchronously parse package.json - `parsePackageJsonAsync(path)` - Asynchronously parse package.json - `fetchUrl(url)` - Fetch content from URL - `fetchUrlBuffer(url)` - Fetch URL as Buffer - `fetchFromGitHub(config)` - Fetch from GitHub - `fetchFromGitea(config)` - Fetch from Gitea - `fetchFromIPFS(config)` - Fetch from IPFS - `extractArchive(buffer, dir)` - Extract tar.gz archives - `findEntryPoint(dir, name)` - Find component entry point - `generateCacheHash(ior)` - Generate SHA256 hash for caching - `buildLocalIORMappings(root)` - Build local component mappings ### Metro Resolver Functions #### `createIORResolver(projectRoot: string)` Creates a basic IOR resolver for Metro. #### `createHotReloadableResolver(projectRoot: string)` Creates an IOR resolver with hot reload support that watches for package.json changes. #### `fetchRemoteComponent(ior: string)` Fetches and caches a remote component. #### `clearRemoteCache()` Clears all cached remote components. ### Node.js Loader Functions #### `resolve(specifier, context, defaultResolve)` Node.js loader resolve hook for IOR imports. #### `load(url, context, defaultLoad)` Node.js loader load hook for TypeScript transpilation. #### `clearCache(ior?: string)` Clears cache for a specific IOR or all cached components. #### `setCacheTTL(ttl: number)` Sets the cache time-to-live for remote components. #### `preloadComponent(ior: string)` Pre-fetches a remote component for faster access. ## Configuration ### Environment Variables - `DEBUG=true` - Enable debug logging for the Node.js loader - `NODE_ENV=development` - Enable hot reload for Metro resolver - `IOR_CACHE_TTL` - Control cache duration in milliseconds - `IOR_CACHE_TTL=0` - Disable caching (always fetch fresh) - `IOR_CACHE_TTL=60000` - 1 minute cache (useful during development) - Default: 3600000 (1 hour) ### Cache Configuration The resolver uses different cache locations for different environments: - **Metro**: `.ior-cache/remote/` in project root - **Node.js**: OS temp directory under `metatrom-components/remote/` - **Default TTL**: 1 hour (3600000ms) - configurable via `IOR_CACHE_TTL` ### Cache Persistence Metro resolver maintains a persistent cache mapping in `.ior-cache/mappings.json` for faster startup times. ### Cache Management During Development When working with frequently changing remote components: ```bash # Disable cache completely (always fetch fresh) IOR_CACHE_TTL=0 npm start # Use short cache duration (1 minute) IOR_CACHE_TTL=60000 npm start # Clear cache manually rm -rf .ior-cache/remote/* # Or add to package.json scripts: "scripts": { "dev:no-cache": "IOR_CACHE_TTL=0 npm start", "dev:short-cache": "IOR_CACHE_TTL=60000 npm start", "clear-cache": "rm -rf .ior-cache/remote/*" } ``` ## Architecture The package is designed with a shared core architecture: 1. **ior-core.js** - Contains all shared functionality for parsing, fetching, and caching 2. **metro-ior-resolver.js** - Metro-specific implementation using the shared core 3. **NodeImportLoader.ts** - Node.js-specific implementation using the shared core (TypeScript source compiled to JavaScript) This design eliminates code duplication and ensures consistency across different environments. The Node.js loader is written in TypeScript and compiled to JavaScript during the build process. ## Migration from Direct Implementation If you're migrating from having these files directly in your project: 1. Install the package: ```bash npm install @metatrom/ior-resolver ``` 2. Update `metro.config.js` to use the package import: ```javascript const { createHotReloadableResolver } = require('@metatrom/ior-resolver'); ``` 3. Update `package.json` scripts: ```json { "scripts": { "prebuild": "prebuild-ior-types" } } ``` 4. Remove the old files from your project: - `metro-ior-resolver.js` - `scripts/prebuild-ior-types.js` - `fetch-remote-component.js` - `NodeImportLoader.ts` ## TypeScript Support The package automatically generates TypeScript declarations for IOR components: - Local components: Types are read from `.d.ts` files in the component directory - Remote components: Types are fetched from the remote repository - Auto-generated types are saved to `src/types/auto-generated.d.ts` ## Security Considerations - Remote components are fetched over HTTPS - Components are cached locally with SHA256 hash verification - Cache TTL ensures components are refreshed periodically - No automatic code execution - components must be explicitly imported ## Performance - **Caching**: Components are cached locally to avoid repeated network requests - **Parallel fetching**: Multiple components can be fetched in parallel - **Hot reload**: Development mode watches for changes without restart - **Type generation**: Types are generated asynchronously without blocking ## Troubleshooting ### Common Issues 1. **"Cannot resolve IOR module"** - Ensure the component exists in the expected location - Check the IOR format is correct - Verify network connectivity for remote components 2. **"Failed to fetch remote component"** - Check network connectivity - Verify the repository exists and is accessible - Ensure the version tag exists 3. **Types not generating** - Run `npx prebuild-ior-types` manually - Check for `.d.ts` files in component directories - Verify `src/types/` directory exists ### Debug Mode Enable debug logging: ```bash DEBUG=true npm start ``` ### Clear Cache If you encounter stale cache issues: ```javascript // In your code const { clearRemoteCache } = require('@metatrom/ior-resolver'); clearRemoteCache(); ``` Or manually delete: ```bash rm -rf .ior-cache rm -rf /tmp/metatrom-components # Node.js cache ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ### Development Setup 1. Clone the repository 2. Install dependencies: `npm install` 3. Build TypeScript: `npm run build` 4. Build Node.js loader: `npm run build:loader` 5. Run tests: `npm test` Note: The `prepublishOnly` script automatically runs both build commands before publishing. ### Code Structure - Keep shared functionality in `lib/ior-core.js` - Environment-specific code in respective files - Maintain TypeScript types for all exports - Follow existing code style ## License MIT ## TODO: Missing Features The following features are documented in `docs/IOR_RESOLVER.md` but not yet implemented in the codebase: ### High Priority - [ ] **Authentication for Private Repositories** - [ ] GitHub authentication via `GITHUB_TOKEN` environment variable - [ ] Gitea authentication with instance-specific tokens - [ ] Add Authorization headers to fetch requests - *Impact: Currently cannot access private repositories* - [ ] **Error Recovery & Resilience** - [ ] Implement retry logic with exponential backoff for network failures - [ ] Add `IORResolutionError` class for better error categorization - [ ] Implement fallback strategies for failed fetches - *Impact: Single network failures cause immediate errors* ### Medium Priority - [ ] **Security Enhancements** - [ ] HTTPS certificate validation for Git sources - [ ] Content sanitization and pattern scanning - [ ] Component signature verification - [ ] Sandboxing options with configurable restrictions: - Allowed protocols whitelist - Allowed domains whitelist - Maximum component size limits - *Impact: Limited security validation of fetched components* ### Low Priority - [ ] **Advanced Features** - [ ] Per-source cache TTL configuration - [ ] Component dependency resolution - [ ] Version conflict resolution - [ ] Cross-platform compatibility checks - [ ] Progress reporting for large downloads ### Future Roadmap (from docs) - [ ] P2P protocol implementation (libp2p) - [ ] Decentralized component registry - [ ] Smart contract integration for Web3 - [ ] Component marketplace - [ ] AI-assisted component discovery ## Support For issues and feature requests, please use the [GitHub issue tracker](https://github.com/metatrom/ior-resolver/issues).