A Transparent and Verifiable Way to Sync the AT Protocol's PLC Directory
at test-validate 148 lines 4.3 kB view raw
1package plcbundle 2 3import ( 4 "context" 5 "io" 6 "time" 7 8 "tangled.org/atscan.net/plcbundle/bundle" 9 "tangled.org/atscan.net/plcbundle/plc" 10) 11 12// Re-export commonly used types for convenience 13type ( 14 Bundle = bundle.Bundle 15 BundleMetadata = bundle.BundleMetadata 16 Index = bundle.Index 17 Manager = bundle.Manager 18 Config = bundle.Config 19 VerificationResult = bundle.VerificationResult 20 ChainVerificationResult = bundle.ChainVerificationResult 21 DirectoryScanResult = bundle.DirectoryScanResult 22 Logger = bundle.Logger 23 24 PLCOperation = plc.PLCOperation 25 PLCClient = plc.Client 26 ExportOptions = plc.ExportOptions 27) 28 29// Re-export constants 30const ( 31 BUNDLE_SIZE = bundle.BUNDLE_SIZE 32 INDEX_FILE = bundle.INDEX_FILE 33) 34 35// NewManager creates a new bundle manager (convenience wrapper) 36func NewManager(config *Config, plcClient *PLCClient) (*Manager, error) { 37 return bundle.NewManager(config, plcClient) 38} 39 40// NewPLCClient creates a new PLC client (convenience wrapper) 41func NewPLCClient(baseURL string, opts ...plc.ClientOption) *PLCClient { 42 return plc.NewClient(baseURL, opts...) 43} 44 45// DefaultConfig returns default configuration (convenience wrapper) 46func DefaultConfig(bundleDir string) *Config { 47 return bundle.DefaultConfig(bundleDir) 48} 49 50// NewIndex creates a new empty index (convenience wrapper) 51func NewIndex() *Index { 52 return bundle.NewIndex() 53} 54 55// LoadIndex loads an index from a file (convenience wrapper) 56func LoadIndex(path string) (*Index, error) { 57 return bundle.LoadIndex(path) 58} 59 60// BundleManager provides a high-level API for bundle operations 61type BundleManager struct { 62 mgr *Manager 63} 64 65// New creates a new BundleManager with default settings 66func New(bundleDir string, plcURL string) (*BundleManager, error) { 67 config := DefaultConfig(bundleDir) 68 var plcClient *PLCClient 69 if plcURL != "" { 70 plcClient = NewPLCClient(plcURL) 71 } 72 73 mgr, err := NewManager(config, plcClient) 74 if err != nil { 75 return nil, err 76 } 77 78 return &BundleManager{mgr: mgr}, nil 79} 80 81// Close closes the manager 82func (bm *BundleManager) Close() { 83 bm.mgr.Close() 84} 85 86// FetchNext fetches the next bundle from PLC 87func (bm *BundleManager) FetchNext(ctx context.Context) (*Bundle, error) { 88 b, err := bm.mgr.FetchNextBundle(ctx) 89 if err != nil { 90 return nil, err 91 } 92 return b, bm.mgr.SaveBundle(ctx, b) 93} 94 95// Load loads a bundle by number 96func (bm *BundleManager) Load(ctx context.Context, bundleNumber int) (*Bundle, error) { 97 return bm.mgr.LoadBundle(ctx, bundleNumber) 98} 99 100// Verify verifies a bundle 101func (bm *BundleManager) Verify(ctx context.Context, bundleNumber int) (*VerificationResult, error) { 102 return bm.mgr.VerifyBundle(ctx, bundleNumber) 103} 104 105// VerifyChain verifies the entire chain 106func (bm *BundleManager) VerifyChain(ctx context.Context) (*ChainVerificationResult, error) { 107 return bm.mgr.VerifyChain(ctx) 108} 109 110// GetIndex returns the index 111func (bm *BundleManager) GetIndex() *Index { 112 return bm.mgr.GetIndex() 113} 114 115// GetInfo returns manager info 116func (bm *BundleManager) GetInfo() map[string]interface{} { 117 return bm.mgr.GetInfo() 118} 119 120// Export exports operations from bundles 121func (bm *BundleManager) Export(ctx context.Context, afterTime time.Time, count int) ([]PLCOperation, error) { 122 return bm.mgr.ExportOperations(ctx, afterTime, count) 123} 124 125// Scan scans the directory and rebuilds the index 126func (bm *BundleManager) Scan() (*DirectoryScanResult, error) { 127 return bm.mgr.ScanDirectory() 128} 129 130// ScanBundle scans a single bundle file 131func (bm *BundleManager) ScanBundle(path string, bundleNumber int) (*BundleMetadata, error) { 132 return bm.mgr.ScanBundle(path, bundleNumber) 133} 134 135// IsBundleIndexed checks if a bundle is in the index 136func (bm *BundleManager) IsBundleIndexed(bundleNumber int) bool { 137 return bm.mgr.IsBundleIndexed(bundleNumber) 138} 139 140// StreamRaw streams raw compressed bundle data 141func (bm *BundleManager) StreamRaw(ctx context.Context, bundleNumber int) (io.ReadCloser, error) { 142 return bm.mgr.StreamBundleRaw(ctx, bundleNumber) 143} 144 145// StreamDecompressed streams decompressed bundle data 146func (bm *BundleManager) StreamDecompressed(ctx context.Context, bundleNumber int) (io.ReadCloser, error) { 147 return bm.mgr.StreamBundleDecompressed(ctx, bundleNumber) 148}