Initial commit
This commit is contained in:
349
README.md
Normal file
349
README.md
Normal file
@@ -0,0 +1,349 @@
|
||||
# @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).
|
||||
Reference in New Issue
Block a user