# @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/ # Executable scripts │ ├── prebuild-ior-types.js # Pre-build script for type generation │ └── NodeImportLoader.ts # Node.js loader implementation ├── lib/ # Core library files │ ├── ior-core.js # Shared core functions │ ├── metro-ior-resolver.js # Metro resolver implementation │ └── fetch-remote-component.js # Remote fetching utility ├── 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 ### 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) ### Cache Persistence Metro resolver maintains a persistent cache mapping in `.ior-cache/mappings.json` for faster startup times. ## 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 This design eliminates code duplication and ensures consistency across different environments. ## 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. Run tests: `npm test` ### 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 ## Support For issues and feature requests, please use the [GitHub issue tracker](https://github.com/metatrom/ior-resolver/issues).