A Transparent and Verifiable Way to Sync the AT Protocol's PLC Directory
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}