[DEPRECATED] Go implementation of plcbundle

Compare changes

Choose any two refs to compare.

+3 -3
Dockerfile
··· 18 18 RUN CGO_ENABLED=1 go build \ 19 19 -ldflags="-w -s -X 'main.version=${VERSION}' -X 'main.gitCommit=${GIT_COMMIT}' -X 'main.buildDate=${BUILD_DATE}'" \ 20 20 -trimpath \ 21 - -o plcbundle \ 21 + -o plcbundle-go \ 22 22 ./cmd/plcbundle 23 23 24 24 FROM alpine:3.19 25 25 26 26 RUN apk add --no-cache ca-certificates zstd-libs 27 27 28 - COPY --from=builder /build/plcbundle /usr/local/bin/plcbundle 28 + COPY --from=builder /build/plcbundle-go /usr/local/bin/plcbundle-go 29 29 30 30 WORKDIR /data 31 31 32 - ENTRYPOINT ["plcbundle"] 32 + ENTRYPOINT ["plcbundle-go"]
+8 -8
Makefile
··· 2 2 .PHONY: docker-build docker-buildx docker-push docker-run docker-clean docker-shell compose-up compose-down compose-logs 3 3 4 4 # Binary name 5 - BINARY_NAME=plcbundle 5 + BINARY_NAME=plcbundle-go 6 6 INSTALL_PATH=$(GOPATH)/bin 7 7 8 8 # Docker configuration 9 - DOCKER_IMAGE=plcbundle 9 + DOCKER_IMAGE=plcbundle-go 10 10 DOCKER_TAG=$(VERSION) 11 11 DOCKER_REGISTRY?=atscan 12 12 DOCKER_FULL_IMAGE=$(if $(DOCKER_REGISTRY),$(DOCKER_REGISTRY)/,)$(DOCKER_IMAGE):$(DOCKER_TAG) ··· 45 45 # Install the CLI tool globally 46 46 install: 47 47 @echo "Installing $(BINARY_NAME) ..." 48 - $(GOINSTALL) $(LDFLAGS) ./cmd/plcbundle 48 + $(GOBUILD) $(LDFLAGS) -o $(INSTALL_PATH)/$(BINARY_NAME) ./cmd/plcbundle 49 49 50 50 # Run tests 51 51 test: ··· 157 157 158 158 # Run Docker container as CLI 159 159 docker-run: 160 - @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle $(CMD) 160 + @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle-go $(CMD) 161 161 162 162 # Shortcuts 163 163 docker-info: 164 - @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle info 164 + @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle-go info 165 165 166 166 docker-fetch: 167 - @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle fetch 167 + @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle-go fetch 168 168 169 169 docker-verify: 170 - @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle verify 170 + @docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle-go verify 171 171 172 172 # Run as server 173 173 docker-serve: 174 - docker run --rm -it -p 8080:8080 -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle serve --host 0.0.0.0 174 + docker run --rm -it -p 8080:8080 -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) plcbundle-go serve --host 0.0.0.0 175 175 176 176 # Open shell 177 177 docker-shell:
+9 -9
README.md
··· 70 70 71 71 ```bash 72 72 # CLI tool 73 - go install tangled.org/atscan.net/plcbundle/cmd/plcbundle@latest 73 + go install tangled.org/atscan.net/plcbundle-go/cmd/plcbundle@latest 74 74 75 75 # Library 76 - go get tangled.org/atscan.net/plcbundle 76 + go get tangled.org/atscan.net/plcbundle-go 77 77 ``` 78 78 79 79 ### Docker ··· 87 87 docker pull atscan/plcbundle:latest 88 88 89 89 # Run CLI 90 - docker run --rm -v $(pwd)/data:/data atscan/plcbundle info 90 + docker run --rm -v $(pwd)/data:/data atscan/plcbundle-go info 91 91 92 92 # Run as server 93 - docker run -d -p 8080:8080 -v $(pwd)/data:/data atscan/plcbundle serve --host 0.0.0.0 93 + docker run -d -p 8080:8080 -v $(pwd)/data:/data atscan/plcbundle-go serve --host 0.0.0.0 94 94 95 95 # Or use docker compose 96 96 curl -O https://tangled.org/@atscan.net/plcbundle/raw/main/docker-compose.yaml ··· 111 111 ### As a Library 112 112 113 113 ```go 114 - import plcbundle "tangled.org/atscan.net/plcbundle" 114 + import plcbundle "tangled.org/atscan.net/plcbundle-go" 115 115 116 116 mgr, _ := plcbundle.New("./plc_data", "https://plc.directory") 117 117 defer mgr.Close() ··· 126 126 127 127 ```bash 128 128 # Fetch bundles from plc.directory 129 - plcbundle sync 129 + plcbundle-go sync 130 130 131 131 # Clone from remote 132 - plcbundle clone https://plc.example.com 132 + plcbundle-go clone https://plc.example.com 133 133 134 134 # Verify integrity 135 - plcbundle verify 135 + plcbundle-go verify 136 136 ``` 137 137 138 138 [See full CLI reference โ†’](./docs/cli.md) ··· 141 141 142 142 ```bash 143 143 # CLI usage 144 - docker run --rm -v $(pwd)/data:/data plcbundle info 144 + docker run --rm -v $(pwd)/data:/data plcbundle-go info 145 145 146 146 # Server mode 147 147 docker-compose up -d
+6 -6
bundle/bundle_test.go
··· 5 5 "testing" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/bundle" 9 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 10 - "tangled.org/atscan.net/plcbundle/internal/mempool" 11 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 12 - "tangled.org/atscan.net/plcbundle/internal/storage" 13 - "tangled.org/atscan.net/plcbundle/internal/types" 8 + "tangled.org/atscan.net/plcbundle-go/bundle" 9 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 10 + "tangled.org/atscan.net/plcbundle-go/internal/mempool" 11 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 12 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 13 + "tangled.org/atscan.net/plcbundle-go/internal/types" 14 14 ) 15 15 16 16 var (
+56 -33
bundle/manager.go
··· 15 15 "sync/atomic" 16 16 "time" 17 17 18 - plcbundle "tangled.org/atscan.net/plcbundle-rs/bindings/go" 19 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 20 - "tangled.org/atscan.net/plcbundle/internal/didindex" 21 - "tangled.org/atscan.net/plcbundle/internal/handleresolver" 22 - "tangled.org/atscan.net/plcbundle/internal/mempool" 23 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 24 - "tangled.org/atscan.net/plcbundle/internal/storage" 25 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 26 - "tangled.org/atscan.net/plcbundle/internal/types" 18 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 19 + "tangled.org/atscan.net/plcbundle-go/internal/didindex" 20 + "tangled.org/atscan.net/plcbundle-go/internal/handleresolver" 21 + "tangled.org/atscan.net/plcbundle-go/internal/mempool" 22 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 23 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 24 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 25 + "tangled.org/atscan.net/plcbundle-go/internal/types" 27 26 ) 28 27 29 28 // defaultLogger is a simple logger implementation ··· 76 75 recentIdx int 77 76 recentSize int 78 77 } 79 - 80 - // Rust-based bundle manager for high-performance operations 81 - rsManager *plcbundle.BundleManager 82 - rsManagerOnce sync.Once 83 - rsManagerErr error 84 78 } 85 79 86 80 // NewManager creates a new bundle manager ··· 353 347 return m, nil 354 348 } 355 349 356 - // getRSManager lazily initializes the Rust bundle manager 357 - func (m *Manager) getRSManager() (*plcbundle.BundleManager, error) { 358 - m.rsManagerOnce.Do(func() { 359 - rsMgr, err := plcbundle.NewBundleManager(m.config.BundleDir) 360 - if err != nil { 361 - m.rsManagerErr = fmt.Errorf("failed to create Rust bundle manager: %w", err) 362 - return 363 - } 364 - m.rsManager = rsMgr 365 - }) 366 - return m.rsManager, m.rsManagerErr 367 - } 368 - 369 350 // Close cleans up resources 370 351 func (m *Manager) Close() { 371 - if m.rsManager != nil { 372 - m.rsManager.Close() 373 - } 374 352 if m.operations != nil { 375 353 m.operations.Close() 376 354 } ··· 731 709 return stats 732 710 } 733 711 734 - // GetRSManager returns the Rust bundle manager (proxy method) 735 - func (m *Manager) GetRSManager() (*plcbundle.BundleManager, error) { 736 - return m.getRSManager() 712 + // ExportOperations exports operations from bundles 713 + func (m *Manager) ExportOperations(ctx context.Context, afterTime time.Time, count int) ([]plcclient.PLCOperation, error) { 714 + if count <= 0 { 715 + count = 1000 716 + } 717 + 718 + var result []plcclient.PLCOperation 719 + seenCIDs := make(map[string]bool) 720 + 721 + bundles := m.index.GetBundles() 722 + 723 + for _, meta := range bundles { 724 + if result != nil && len(result) >= count { 725 + break 726 + } 727 + 728 + // Skip bundles before afterTime 729 + if !afterTime.IsZero() && meta.EndTime.Before(afterTime) { 730 + continue 731 + } 732 + 733 + // Load bundle 734 + bundle, err := m.LoadBundle(ctx, meta.BundleNumber) 735 + if err != nil { 736 + m.logger.Printf("Warning: failed to load bundle %d: %v", meta.BundleNumber, err) 737 + continue 738 + } 739 + 740 + // Add operations 741 + for _, op := range bundle.Operations { 742 + if !afterTime.IsZero() && op.CreatedAt.Before(afterTime) { 743 + continue 744 + } 745 + 746 + if seenCIDs[op.CID] { 747 + continue 748 + } 749 + 750 + seenCIDs[op.CID] = true 751 + result = append(result, op) 752 + 753 + if len(result) >= count { 754 + break 755 + } 756 + } 757 + } 758 + 759 + return result, nil 737 760 } 738 761 739 762 // IsBundleIndexed checks if a bundle is already in the index
+3 -3
bundle/metadata.go
··· 7 7 "os" 8 8 "time" 9 9 10 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 11 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 12 - "tangled.org/atscan.net/plcbundle/internal/storage" 10 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 11 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 12 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 13 13 ) 14 14 15 15 // CalculateBundleMetadata calculates complete metadata for a bundle
+1 -1
bundle/scanner.go
··· 9 9 "sync" 10 10 "time" 11 11 12 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 12 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 13 13 ) 14 14 15 15 // ScanDirectory scans the bundle directory and rebuilds the index
+3 -3
bundle/types.go
··· 5 5 "path/filepath" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 9 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 10 - "tangled.org/atscan.net/plcbundle/internal/types" 8 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 9 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 10 + "tangled.org/atscan.net/plcbundle-go/internal/types" 11 11 ) 12 12 13 13 // Bundle represents a PLC bundle
+1 -1
bundle.go
··· 4 4 "context" 5 5 "io" 6 6 7 - "tangled.org/atscan.net/plcbundle/bundle" 7 + "tangled.org/atscan.net/plcbundle-go/bundle" 8 8 ) 9 9 10 10 // Manager is the main entry point for plcbundle operations
+7 -7
cmd/plcbundle/commands/clone.go
··· 12 12 "time" 13 13 14 14 "github.com/spf13/cobra" 15 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 16 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 15 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 16 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 17 17 ) 18 18 19 19 func NewCloneCommand() *cobra.Command { ··· 43 43 Args: cobra.RangeArgs(1, 2), 44 44 45 45 Example: ` # Clone into default 'bundles' directory 46 - plcbundle clone https://plc.example.com 46 + plcbundle-go clone https://plc.example.com 47 47 48 48 # Clone into specific directory 49 - plcbundle clone https://plc.example.com my-plc-data 49 + plcbundle-go clone https://plc.example.com my-plc-data 50 50 51 51 # Clone with more parallel workers (faster) 52 - plcbundle clone https://plc.example.com --workers 8 52 + plcbundle-go clone https://plc.example.com --workers 8 53 53 54 54 # Resume interrupted clone 55 - plcbundle clone https://plc.example.com --resume 55 + plcbundle-go clone https://plc.example.com --resume 56 56 57 57 # Verbose output (shows each bundle) 58 - plcbundle clone https://plc.example.com my-bundles -v`, 58 + plcbundle-go clone https://plc.example.com my-bundles -v`, 59 59 60 60 RunE: func(cmd *cobra.Command, args []string) error { 61 61 remoteURL := strings.TrimSuffix(args[0], "/")
+6 -13
cmd/plcbundle/commands/common.go
··· 9 9 "time" 10 10 11 11 "github.com/spf13/cobra" 12 - "tangled.org/atscan.net/plcbundle/bundle" 13 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 14 - "tangled.org/atscan.net/plcbundle/internal/didindex" 15 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 16 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 17 - "tangled.org/atscan.net/plcbundle/internal/types" 12 + "tangled.org/atscan.net/plcbundle-go/bundle" 13 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 14 + "tangled.org/atscan.net/plcbundle-go/internal/didindex" 15 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 16 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 17 + "tangled.org/atscan.net/plcbundle-go/internal/types" 18 18 ) 19 19 20 20 // BundleManager interface (for testing/mocking) ··· 291 291 } 292 292 return b 293 293 } 294 - 295 - // getVerboseQuiet extracts verbose and quiet flags from command 296 - func getVerboseQuiet(cmd *cobra.Command) (verbose, quiet bool) { 297 - verbose, _ = cmd.Root().PersistentFlags().GetBool("verbose") 298 - quiet, _ = cmd.Root().PersistentFlags().GetBool("quiet") 299 - return verbose, quiet 300 - }
+33 -33
cmd/plcbundle/commands/detector.go
··· 15 15 16 16 "github.com/goccy/go-json" 17 17 "github.com/spf13/cobra" 18 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 19 - "tangled.org/atscan.net/plcbundle/detector" 20 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 18 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 19 + "tangled.org/atscan.net/plcbundle-go/detector" 20 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 21 21 ) 22 22 23 23 func NewDetectorCommand() *cobra.Command { ··· 41 41 Load JavaScript detectors from .js files with a detect() function.`, 42 42 43 43 Example: ` # List available detectors 44 - plcbundle detector list 44 + plcbundle-go detector list 45 45 46 46 # Run detector on bundles 47 - plcbundle detector run invalid_handle --bundles 1-100 47 + plcbundle-go detector run invalid_handle --bundles 1-100 48 48 49 49 # Run with parallel processing 50 - plcbundle detector run invalid_handle --bundles 1-100 --workers 8 50 + plcbundle-go detector run invalid_handle --bundles 1-100 --workers 8 51 51 52 52 # Run custom detector script 53 - plcbundle detector run ./my_detector.js --bundles 1-100 53 + plcbundle-go detector run ./my_detector.js --bundles 1-100 54 54 55 55 # Run multiple detectors 56 - plcbundle detector run invalid_handle aka_spam --bundles 1-100 56 + plcbundle-go detector run invalid_handle aka_spam --bundles 1-100 57 57 58 58 # Run all detectors 59 - plcbundle detector run all --bundles 1-100 59 + plcbundle-go detector run all --bundles 1-100 60 60 61 61 # Filter JSONL from stdin 62 - cat ops.jsonl | plcbundle detector filter invalid_handle > clean.jsonl 62 + cat ops.jsonl | plcbundle-go detector filter invalid_handle > clean.jsonl 63 63 64 64 # Get detector info 65 - plcbundle detector info invalid_handle`, 65 + plcbundle-go detector info invalid_handle`, 66 66 } 67 67 68 68 // Add subcommands ··· 86 86 Long: `List all available built-in and loaded detectors`, 87 87 88 88 Example: ` # List all detectors 89 - plcbundle detector list`, 89 + plcbundle-go detector list`, 90 90 91 91 RunE: func(cmd *cobra.Command, args []string) error { 92 92 registry := detector.DefaultRegistry() ··· 100 100 for _, d := range detectors { 101 101 fmt.Printf(" %-20s %s (v%s)\n", d.Name(), d.Description(), d.Version()) 102 102 } 103 - fmt.Printf("\nUse 'plcbundle detector info <name>' for details\n") 103 + fmt.Printf("\nUse 'plcbundle-go detector info <name>' for details\n") 104 104 105 105 return nil 106 106 }, ··· 124 124 Long: `Test a detector on a specific bundle and show results`, 125 125 126 126 Example: ` # Test on bundle 42 127 - plcbundle detector test invalid_handle --bundle 42 127 + plcbundle-go detector test invalid_handle --bundle 42 128 128 129 129 # Verbose output with samples 130 - plcbundle detector test aka_spam --bundle 100 -v 130 + plcbundle-go detector test aka_spam --bundle 100 -v 131 131 132 132 # Custom confidence threshold 133 - plcbundle detector test spam_pds --bundle 50 --confidence 0.85`, 133 + plcbundle-go detector test spam_pds --bundle 50 --confidence 0.85`, 134 134 135 135 Args: cobra.ExactArgs(1), 136 136 ··· 234 234 โ€ข Special keyword 'all' to run all built-in detectors`, 235 235 236 236 Example: ` # Run single detector 237 - plcbundle detector run invalid_handle --bundles 1-100 237 + plcbundle-go detector run invalid_handle --bundles 1-100 238 238 239 239 # Run with 8 parallel workers (faster) 240 - plcbundle detector run invalid_handle --bundles 1-1000 --workers 8 240 + plcbundle-go detector run invalid_handle --bundles 1-1000 --workers 8 241 241 242 242 # Run multiple detectors in parallel 243 - plcbundle detector run invalid_handle aka_spam --bundles 1-100 -w 4 243 + plcbundle-go detector run invalid_handle aka_spam --bundles 1-100 -w 4 244 244 245 245 # Run custom script 246 - plcbundle detector run ./my_detector.js --bundles 1-100 246 + plcbundle-go detector run ./my_detector.js --bundles 1-100 247 247 248 248 # Run all built-in detectors 249 - plcbundle detector run all --bundles 1-100 --workers 8 249 + plcbundle-go detector run all --bundles 1-100 --workers 8 250 250 251 251 # Save results to file 252 - plcbundle detector run all --bundles 1-100 -w 8 > results.csv 252 + plcbundle-go detector run all --bundles 1-100 -w 8 > results.csv 253 253 254 254 # Disable progress bar (for scripting) 255 - plcbundle detector run spam --bundles 1-100 --no-progress 255 + plcbundle-go detector run spam --bundles 1-100 --no-progress 256 256 257 257 # Enable profiling 258 - plcbundle detector run all --bundles 1-100 --pprof :6060`, 258 + plcbundle-go detector run all --bundles 1-100 --pprof :6060`, 259 259 260 260 Args: cobra.MinimumNArgs(1), 261 261 ··· 344 344 Perfect for cleaning datasets or pre-processing.`, 345 345 346 346 Example: ` # Filter with built-in detector 347 - cat ops.jsonl | plcbundle detector filter invalid_handle > clean.jsonl 347 + cat ops.jsonl | plcbundle-go detector filter invalid_handle > clean.jsonl 348 348 349 349 # Filter with custom script 350 - plcbundle export --all | plcbundle detector filter ./spam.js > clean.jsonl 350 + plcbundle export --all | plcbundle-go detector filter ./spam.js > clean.jsonl 351 351 352 352 # Chain multiple detectors 353 - cat ops.jsonl | plcbundle detector filter invalid_handle aka_spam > clean.jsonl 353 + cat ops.jsonl | plcbundle-go detector filter invalid_handle aka_spam > clean.jsonl 354 354 355 355 # Custom confidence 356 - cat ops.jsonl | plcbundle detector filter spam_pds --confidence 0.95 > clean.jsonl`, 356 + cat ops.jsonl | plcbundle-go detector filter spam_pds --confidence 0.95 > clean.jsonl`, 357 357 358 358 Args: cobra.MinimumNArgs(1), 359 359 ··· 388 388 Long: `Show detailed information about a specific detector`, 389 389 390 390 Example: ` # Show detector info 391 - plcbundle detector info invalid_handle 392 - plcbundle detector info aka_spam`, 391 + plcbundle-go detector info invalid_handle 392 + plcbundle-go detector info aka_spam`, 393 393 394 394 Args: cobra.ExactArgs(1), 395 395 ··· 408 408 409 409 fmt.Printf("Usage examples:\n") 410 410 fmt.Printf(" # Test on single bundle\n") 411 - fmt.Printf(" plcbundle detector test %s --bundle 42\n\n", d.Name()) 411 + fmt.Printf(" plcbundle-go detector test %s --bundle 42\n\n", d.Name()) 412 412 fmt.Printf(" # Run on range and save\n") 413 - fmt.Printf(" plcbundle detector run %s --bundles 1-100 > results.csv\n\n", d.Name()) 413 + fmt.Printf(" plcbundle-go detector run %s --bundles 1-100 > results.csv\n\n", d.Name()) 414 414 fmt.Printf(" # Filter JSONL stream\n") 415 - fmt.Printf(" cat ops.jsonl | plcbundle detector filter %s > clean.jsonl\n\n", d.Name()) 415 + fmt.Printf(" cat ops.jsonl | plcbundle-go detector filter %s > clean.jsonl\n\n", d.Name()) 416 416 417 417 return nil 418 418 },
+36 -36
cmd/plcbundle/commands/did.go
··· 11 11 12 12 "github.com/goccy/go-json" 13 13 "github.com/spf13/cobra" 14 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 15 - "tangled.org/atscan.net/plcbundle/internal/didindex" 16 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 14 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 15 + "tangled.org/atscan.net/plcbundle-go/internal/didindex" 16 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 17 17 ) 18 18 19 19 func NewDIDCommand() *cobra.Command { ··· 27 27 require a DID index to be built for optimal performance.`, 28 28 29 29 Example: ` # Lookup all operations for a DID 30 - plcbundle did lookup did:plc:524tuhdhh3m7li5gycdn6boe 30 + plcbundle-go did lookup did:plc:524tuhdhh3m7li5gycdn6boe 31 31 32 32 # Resolve to current DID document 33 - plcbundle did resolve did:plc:524tuhdhh3m7li5gycdn6boe 33 + plcbundle-go did resolve did:plc:524tuhdhh3m7li5gycdn6boe 34 34 35 35 # Show complete audit log 36 - plcbundle did history did:plc:524tuhdhh3m7li5gycdn6boe 36 + plcbundle-go did history did:plc:524tuhdhh3m7li5gycdn6boe 37 37 38 38 # Show DID statistics 39 - plcbundle did stats did:plc:524tuhdhh3m7li5gycdn6boe 39 + plcbundle-go did stats did:plc:524tuhdhh3m7li5gycdn6boe 40 40 41 41 # Batch process from file 42 - plcbundle did batch dids.txt`, 42 + plcbundle-go did batch dids.txt`, 43 43 } 44 44 45 45 // Add subcommands ··· 76 76 Requires DID index to be built.`, 77 77 78 78 Example: ` # Lookup by DID 79 - plcbundle did lookup did:plc:524tuhdhh3m7li5gycdn6boe 79 + plcbundle-go did lookup did:plc:524tuhdhh3m7li5gycdn6boe 80 80 81 81 # Lookup by handle 82 - plcbundle did lookup tree.fail 83 - plcbundle did lookup ngerakines.me 82 + plcbundle-go did lookup tree.fail 83 + plcbundle-go did lookup ngerakines.me 84 84 85 85 # With non-default handle resolver configured 86 86 plcbundle --handle-resolver https://quickdid.smokesignal.tools did lookup tree.fail`, ··· 105 105 106 106 stats := mgr.GetDIDIndexStats() 107 107 if !stats["exists"].(bool) { 108 - fmt.Fprintf(os.Stderr, "โš ๏ธ DID index not found. Run: plcbundle index build\n") 108 + fmt.Fprintf(os.Stderr, "โš ๏ธ DID index not found. Run: plcbundle-go index build\n") 109 109 fmt.Fprintf(os.Stderr, " Falling back to full scan (slow)...\n\n") 110 110 } 111 111 ··· 175 175 O(1) lookup of latest operation.`, 176 176 177 177 Example: ` # Resolve DID 178 - plcbundle did resolve did:plc:524tuhdhh3m7li5gycdn6boe 178 + plcbundle-go did resolve did:plc:524tuhdhh3m7li5gycdn6boe 179 179 180 180 # Show timings and other details 181 - plcbundle did resolve did:plc:524tuhdhh3m7li5gycdn6boe --verbose 181 + plcbundle-go did resolve did:plc:524tuhdhh3m7li5gycdn6boe --verbose 182 182 183 183 # Get raw PLC state (not W3C format) 184 - plcbundle did resolve did:plc:524tuhdhh3m7li5gycdn6boe --raw 184 + plcbundle-go did resolve did:plc:524tuhdhh3m7li5gycdn6boe --raw 185 185 186 186 # Pipe to jq 187 - plcbundle did resolve did:plc:524tuhdhh3m7li5gycdn6boe | jq .service 187 + plcbundle-go did resolve did:plc:524tuhdhh3m7li5gycdn6boe | jq .service 188 188 189 189 # Resolve by handle 190 - plcbundle did resolve tree.fail`, 190 + plcbundle-go did resolve tree.fail`, 191 191 192 192 Args: cobra.ExactArgs(1), 193 193 ··· 272 272 This provides a full audit trail of all changes to the DID.`, 273 273 274 274 Example: ` # Show full history 275 - plcbundle did history did:plc:524tuhdhh3m7li5gycdn6boe 275 + plcbundle-go did history did:plc:524tuhdhh3m7li5gycdn6boe 276 276 277 277 # Include nullified operations 278 - plcbundle did history did:plc:524tuhdhh3m7li5gycdn6boe --include-nullified 278 + plcbundle-go did history did:plc:524tuhdhh3m7li5gycdn6boe --include-nullified 279 279 280 280 # Compact one-line format 281 - plcbundle did history did:plc:524tuhdhh3m7li5gycdn6boe --compact 281 + plcbundle-go did history did:plc:524tuhdhh3m7li5gycdn6boe --compact 282 282 283 283 # JSON output 284 - plcbundle did history did:plc:524tuhdhh3m7li5gycdn6boe --json`, 284 + plcbundle-go did history did:plc:524tuhdhh3m7li5gycdn6boe --json`, 285 285 286 286 Args: cobra.ExactArgs(1), 287 287 ··· 360 360 - Omit file + use --stdin: reads from stdin`, 361 361 362 362 Example: ` # Batch lookup from file 363 - plcbundle did batch dids.txt --action lookup 363 + plcbundle-go did batch dids.txt --action lookup 364 364 365 365 # Read from stdin 366 - cat dids.txt | plcbundle did batch --stdin --action lookup 367 - cat dids.txt | plcbundle did batch - --action resolve 366 + cat dids.txt | plcbundle-go did batch --stdin --action lookup 367 + cat dids.txt | plcbundle-go did batch - --action resolve 368 368 369 369 # Export operations for DIDs from stdin 370 - echo "did:plc:524tuhdhh3m7li5gycdn6boe" | plcbundle did batch - --action export 370 + echo "did:plc:524tuhdhh3m7li5gycdn6boe" | plcbundle-go did batch - --action export 371 371 372 372 # Pipe results 373 - plcbundle did batch dids.txt --action resolve -o resolved.jsonl 373 + plcbundle-go did batch dids.txt --action resolve -o resolved.jsonl 374 374 375 375 # Parallel processing 376 - cat dids.txt | plcbundle did batch --stdin --action lookup --workers 8 376 + cat dids.txt | plcbundle-go did batch --stdin --action lookup --workers 8 377 377 378 378 # Chain commands 379 - grep "did:plc:" some_file.txt | plcbundle did batch - --action export > ops.jsonl`, 379 + grep "did:plc:" some_file.txt | plcbundle-go did batch - --action export > ops.jsonl`, 380 380 381 381 Args: cobra.MaximumNArgs(1), 382 382 ··· 392 392 } else if !fromStdin { 393 393 return fmt.Errorf("either provide filename or use --stdin flag\n" + 394 394 "Examples:\n" + 395 - " plcbundle did batch dids.txt\n" + 396 - " plcbundle did batch --stdin\n" + 397 - " cat dids.txt | plcbundle did batch -") 395 + " plcbundle-go did batch dids.txt\n" + 396 + " plcbundle-go did batch --stdin\n" + 397 + " cat dids.txt | plcbundle-go did batch -") 398 398 } 399 399 400 400 mgr, _, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 441 441 Without DID: shows global index statistics`, 442 442 443 443 Example: ` # Stats for specific DID 444 - plcbundle did stats did:plc:524tuhdhh3m7li5gycdn6boe 444 + plcbundle-go did stats did:plc:524tuhdhh3m7li5gycdn6boe 445 445 446 446 # Global index stats 447 - plcbundle did stats --global 448 - plcbundle did stats 447 + plcbundle-go did stats --global 448 + plcbundle-go did stats 449 449 450 450 # JSON output 451 - plcbundle did stats did:plc:524tuhdhh3m7li5gycdn6boe --json`, 451 + plcbundle-go did stats did:plc:524tuhdhh3m7li5gycdn6boe --json`, 452 452 453 453 Args: cobra.MaximumNArgs(1), 454 454 ··· 573 573 574 574 if !stats["exists"].(bool) { 575 575 fmt.Printf("DID index does not exist\n") 576 - fmt.Printf("Run: plcbundle index build\n") 576 + fmt.Printf("Run: plcbundle-go index build\n") 577 577 return nil 578 578 } 579 579
+10 -10
cmd/plcbundle/commands/diff.go
··· 11 11 12 12 "github.com/goccy/go-json" 13 13 "github.com/spf13/cobra" 14 - "tangled.org/atscan.net/plcbundle/bundle" 15 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 16 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 14 + "tangled.org/atscan.net/plcbundle-go/bundle" 15 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 16 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 17 17 ) 18 18 19 19 func NewDiffCommand() *cobra.Command { ··· 45 45 โ€ข Local file path (e.g., /path/to/plc_bundles.json)`, 46 46 47 47 Example: ` # High-level comparison 48 - plcbundle diff https://plc.example.com 48 + plcbundle-go diff https://plc.example.com 49 49 50 50 # Show all differences (verbose) 51 - plcbundle diff https://plc.example.com -v 51 + plcbundle-go diff https://plc.example.com -v 52 52 53 53 # Deep dive into specific bundle 54 - plcbundle diff https://plc.example.com --bundle 23 54 + plcbundle-go diff https://plc.example.com --bundle 23 55 55 56 56 # Compare bundle with operation samples 57 - plcbundle diff https://plc.example.com --bundle 23 --show-operations 57 + plcbundle-go diff https://plc.example.com --bundle 23 --show-operations 58 58 59 59 # Show first 50 operations 60 - plcbundle diff https://plc.example.com --bundle 23 --sample 50 60 + plcbundle-go diff https://plc.example.com --bundle 23 --sample 50 61 61 62 62 # Using alias 63 - plcbundle compare https://plc.example.com`, 63 + plcbundle-go compare https://plc.example.com`, 64 64 65 65 Args: cobra.ExactArgs(1), 66 66 ··· 116 116 // If there are hash mismatches, suggest deep dive 117 117 if len(comparison.HashMismatches) > 0 { 118 118 fmt.Printf("\n๐Ÿ’ก Tip: Use --bundle flag to investigate specific mismatches:\n") 119 - fmt.Printf(" plcbundle diff %s --bundle %d --show-operations\n", 119 + fmt.Printf(" plcbundle-go diff %s --bundle %d --show-operations\n", 120 120 target, comparison.HashMismatches[0].BundleNumber) 121 121 } 122 122
+153 -333
cmd/plcbundle/commands/export.go
··· 3 3 import ( 4 4 "context" 5 5 "fmt" 6 - "io" 7 6 "os" 8 7 "time" 9 8 10 9 "github.com/goccy/go-json" 11 10 "github.com/spf13/cobra" 12 - plcbundle "tangled.org/atscan.net/plcbundle-rs/bindings/go" 13 - "tangled.org/atscan.net/plcbundle/bundle" 14 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 11 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 15 12 ) 16 13 17 14 func NewExportCommand() *cobra.Command { ··· 39 36 Supports filtering by count and timestamp for selective exports.`, 40 37 41 38 Example: ` # Export all existing bundles 42 - plcbundle export --all 39 + plcbundle-go export --all 43 40 44 41 # Export and sync new bundles 45 - plcbundle export --all --sync 42 + plcbundle-go export --all --sync 46 43 47 44 # Export specific range (existing only) 48 - plcbundle export --range 1-100 45 + plcbundle-go export --range 1-100 49 46 50 47 # Export with limit 51 - plcbundle export --all --count 50000 48 + plcbundle-go export --all --count 50000 52 49 53 50 # Export after timestamp 54 - plcbundle export --all --after 2024-01-01T00:00:00Z 51 + plcbundle-go export --all --after 2024-01-01T00:00:00Z 55 52 56 53 # Combine filters 57 - plcbundle export --range 1-100 --count 10000 --after 2024-01-01T00:00:00Z 54 + plcbundle-go export --range 1-100 --count 10000 --after 2024-01-01T00:00:00Z 58 55 59 56 # Export from specific PLC directory 60 - plcbundle export --all --sync --plc https://plc.directory 57 + plcbundle-go export --all --sync --plc https://plc.directory 61 58 62 59 # Pipe to file 63 - plcbundle export --all > operations.jsonl 60 + plcbundle-go export --all > operations.jsonl 64 61 65 62 # Process with jq 66 - plcbundle export --all | jq -r .did | sort | uniq -c 63 + plcbundle-go export --all | jq -r .did | sort | uniq -c 67 64 68 65 # Sync and filter with detector 69 - plcbundle export --all --sync | plcbundle detector filter spam 66 + plcbundle-go export --all --sync | plcbundle-go detector filter spam 70 67 71 68 # Using aliases (backwards compatible) 72 - plcbundle stream --all --sync 73 - plcbundle backfill --all`, 69 + plcbundle-go stream --all --sync 70 + plcbundle-go backfill --all`, 74 71 75 72 RunE: func(cmd *cobra.Command, args []string) error { 73 + verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose") 74 + quiet, _ := cmd.Root().PersistentFlags().GetBool("quiet") 75 + 76 76 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd, PLCURL: plcURL}) 77 77 if err != nil { 78 78 return err 79 79 } 80 80 defer mgr.Close() 81 81 82 - verbose, quiet := getVerboseQuiet(cmd) 83 - return runExport(cmd.Context(), mgr, dir, exportFlags{ 84 - all: all, 85 - rangeStr: rangeStr, 86 - sync: sync, 87 - count: count, 88 - after: after, 89 - verbose: verbose, 90 - quiet: quiet, 91 - }) 92 - }, 93 - } 82 + if !quiet { 83 + fmt.Fprintf(os.Stderr, "Exporting from: %s\n", dir) 84 + } 94 85 95 - cmd.Flags().BoolVar(&all, "all", false, "Export all bundles") 96 - cmd.Flags().StringVarP(&rangeStr, "range", "r", "", "Export bundle range (e.g., '1-100')") 97 - cmd.Flags().BoolVar(&sync, "sync", false, "Also fetch new bundles from PLC (until caught up)") 98 - cmd.Flags().StringVar(&plcURL, "plc", "https://plc.directory", "PLC directory URL (for --sync)") 99 - cmd.Flags().IntVarP(&count, "count", "n", 0, "Limit number of operations (0 = unlimited)") 100 - cmd.Flags().StringVar(&after, "after", "", "Only export operations after this timestamp (RFC3339)") 86 + // Parse after timestamp if provided 87 + var afterTime time.Time 88 + if after != "" { 89 + afterTime, err = time.Parse(time.RFC3339, after) 90 + if err != nil { 91 + return fmt.Errorf("invalid --after timestamp (use RFC3339 format): %w", err) 92 + } 93 + } 101 94 102 - return cmd 103 - } 95 + // Determine bundle range 96 + var start, end int 104 97 105 - type exportFlags struct { 106 - all bool 107 - rangeStr string 108 - sync bool 109 - count int 110 - after string 111 - verbose bool 112 - quiet bool 113 - } 98 + if all { 99 + index := mgr.GetIndex() 100 + bundles := index.GetBundles() 114 101 115 - type exportOptions struct { 116 - start int 117 - end int 118 - exportAll bool 119 - sync bool 120 - count int 121 - afterTimestamp string 122 - verbose bool 123 - quiet bool 124 - } 102 + if len(bundles) == 0 { 103 + if sync { 104 + // No bundles but sync enabled - start from 1 105 + start = 1 106 + end = 0 // Will be updated after sync 107 + } else { 108 + if !quiet { 109 + fmt.Fprintf(os.Stderr, "No bundles available (use --sync to fetch)\n") 110 + } 111 + return nil 112 + } 113 + } else { 114 + start = bundles[0].BundleNumber 115 + end = bundles[len(bundles)-1].BundleNumber 116 + } 125 117 126 - // runExport performs the export operation 127 - func runExport(ctx context.Context, mgr BundleManager, dir string, flags exportFlags) error { 128 - // Parse after timestamp if provided 129 - var afterTimestamp string 130 - if flags.after != "" { 131 - afterTime, err := time.Parse(time.RFC3339, flags.after) 132 - if err != nil { 133 - return fmt.Errorf("invalid --after timestamp (use RFC3339 format): %w", err) 134 - } 135 - afterTimestamp = afterTime.Format(time.RFC3339) 136 - } 118 + } else if rangeStr != "" { 119 + var err error 120 + start, end, err = parseBundleRange(rangeStr) 121 + if err != nil { 122 + return err 123 + } 137 124 138 - // Determine bundle range 139 - var start, end uint32 140 - var exportAll bool 125 + } else { 126 + return fmt.Errorf("either --all or --range required") 127 + } 141 128 142 - if flags.all { 143 - index := mgr.GetIndex() 144 - bundles := index.GetBundles() 129 + if !quiet { 130 + if sync { 131 + fmt.Fprintf(os.Stderr, "Mode: export existing + sync new bundles\n") 132 + } else { 133 + fmt.Fprintf(os.Stderr, "Mode: export existing only\n") 134 + } 145 135 146 - if len(bundles) == 0 { 147 - if flags.sync { 148 - // No bundles but sync enabled - start from 1 149 - start = 1 150 - end = 0 // Will be updated after sync 151 - exportAll = false 152 - } else { 153 - if !flags.quiet { 154 - fmt.Fprintf(os.Stderr, "No bundles available (use --sync to fetch)\n") 136 + if count > 0 { 137 + fmt.Fprintf(os.Stderr, "Limit: %d operations\n", count) 138 + } 139 + if after != "" { 140 + fmt.Fprintf(os.Stderr, "After: %s\n", after) 155 141 } 156 - return nil 142 + fmt.Fprintf(os.Stderr, "\n") 157 143 } 158 - } else { 159 - if flags.sync { 160 - // Export existing bundles, then sync 161 - start = uint32(bundles[0].BundleNumber) 162 - end = uint32(bundles[len(bundles)-1].BundleNumber) 163 - exportAll = false 164 - } else { 165 - // For export only, use export_all flag 166 - exportAll = true 167 - start = 0 168 - end = 0 169 - } 170 - } 171 144 172 - } else if flags.rangeStr != "" { 173 - var err error 174 - startInt, endInt, err := parseBundleRange(flags.rangeStr) 175 - if err != nil { 176 - return err 177 - } 178 - start = uint32(startInt) 179 - end = uint32(endInt) 180 - exportAll = false 181 - 182 - } else { 183 - return fmt.Errorf("either --all or --range required") 184 - } 185 - 186 - opts := exportOptions{ 187 - start: int(start), 188 - end: int(end), 189 - exportAll: exportAll, 190 - sync: flags.sync, 191 - count: flags.count, 192 - afterTimestamp: afterTimestamp, 193 - verbose: flags.verbose, 194 - quiet: flags.quiet, 195 - } 196 - 197 - if !flags.quiet { 198 - fmt.Fprintf(os.Stderr, "Exporting from: %s\n", dir) 199 - if flags.sync { 200 - fmt.Fprintf(os.Stderr, "Mode: export existing + sync new bundles\n") 201 - } else { 202 - fmt.Fprintf(os.Stderr, "Mode: export existing only (using Rust library)\n") 203 - } 204 - 205 - if flags.count > 0 { 206 - fmt.Fprintf(os.Stderr, "Limit: %d operations\n", flags.count) 207 - } 208 - if flags.after != "" { 209 - fmt.Fprintf(os.Stderr, "After: %s\n", flags.after) 210 - } 211 - fmt.Fprintf(os.Stderr, "\n") 145 + return exportBundles(cmd.Context(), mgr, exportOptions{ 146 + start: start, 147 + end: end, 148 + sync: sync, 149 + count: count, 150 + afterTime: afterTime, 151 + verbose: verbose, 152 + quiet: quiet, 153 + }) 154 + }, 212 155 } 213 156 214 - return exportBundles(ctx, mgr, opts) 215 - } 157 + cmd.Flags().BoolVar(&all, "all", false, "Export all bundles") 158 + cmd.Flags().StringVarP(&rangeStr, "range", "r", "", "Export bundle range (e.g., '1-100')") 159 + cmd.Flags().BoolVar(&sync, "sync", false, "Also fetch new bundles from PLC (until caught up)") 160 + cmd.Flags().StringVar(&plcURL, "plc", "https://plc.directory", "PLC directory URL (for --sync)") 161 + cmd.Flags().IntVarP(&count, "count", "n", 0, "Limit number of operations (0 = unlimited)") 162 + cmd.Flags().StringVar(&after, "after", "", "Only export operations after this timestamp (RFC3339)") 216 163 217 - // ExportSpec defines export parameters 218 - type ExportSpec struct { 219 - BundleStart uint32 220 - BundleEnd uint32 221 - ExportAll bool 222 - CountLimit uint64 223 - AfterTimestamp string 224 - DIDFilter string 225 - OpTypeFilter string 164 + return cmd 226 165 } 227 166 228 - // ExportStats contains export statistics 229 - type ExportStats struct { 230 - RecordsWritten uint64 231 - BytesWritten uint64 232 - BundlesProcessed int 167 + type exportOptions struct { 168 + start int 169 + end int 170 + sync bool 171 + count int 172 + afterTime time.Time 173 + verbose bool 174 + quiet bool 233 175 } 234 176 235 - // exportBundles exports bundles using the Rust library via Manager proxy 236 177 func exportBundles(ctx context.Context, mgr BundleManager, opts exportOptions) error { 237 - // Phase 1: Export existing bundles 238 - var exported uint64 239 - var existingCount int 240 - 241 - if opts.exportAll || opts.end > 0 { 242 - // Build export spec 243 - spec := ExportSpec{ 244 - BundleStart: uint32(opts.start), 245 - BundleEnd: uint32(opts.end), 246 - ExportAll: opts.exportAll, 247 - CountLimit: uint64(opts.count), 248 - AfterTimestamp: opts.afterTimestamp, 249 - DIDFilter: "", // Not supported in current flags 250 - OpTypeFilter: "", // Not supported in current flags 251 - } 252 - 253 - // Progress callback 254 - var progressCallback func(records, bytes uint64) 255 - if !opts.quiet { 256 - progressCallback = func(records, bytes uint64) { 257 - if opts.verbose { 258 - fmt.Fprintf(os.Stderr, "Progress: %d records, %s\r", records, formatBytes(int64(bytes))) 259 - } else if records%10000 == 0 { 260 - fmt.Fprintf(os.Stderr, "Exported: %d records\r", records) 261 - } 262 - } 263 - } 264 - 265 - // Get Rust manager from bundle manager 266 - concreteMgr := mgr.(*bundle.Manager) 267 - rsMgr, err := concreteMgr.GetRSManager() 268 - if err != nil { 269 - // Fallback to Go implementation if Rust manager unavailable 270 - return exportToWriterGo(ctx, concreteMgr, spec, os.Stdout, progressCallback, &exported, &existingCount) 271 - } 272 - 273 - // Convert to Rust export spec 274 - rsSpec := plcbundle.ExportSpec{ 275 - BundleStart: spec.BundleStart, 276 - BundleEnd: spec.BundleEnd, 277 - ExportAll: spec.ExportAll, 278 - Format: 0, // 0 = jsonl 279 - CountLimit: spec.CountLimit, 280 - AfterTimestamp: spec.AfterTimestamp, 281 - DIDFilter: spec.DIDFilter, 282 - OpTypeFilter: spec.OpTypeFilter, 283 - } 284 - 285 - // Export options 286 - rsOpts := &plcbundle.ExportOptions{ 287 - Writer: os.Stdout, 288 - Progress: progressCallback, 289 - } 290 - 291 - // Perform export using Rust library 292 - rsStats, err := rsMgr.Export(rsSpec, rsOpts) 293 - if err != nil { 294 - return fmt.Errorf("export failed: %w", err) 295 - } 296 - 297 - exported = rsStats.RecordsWritten 178 + operationCount := 0 179 + exported := 0 298 180 299 - // Calculate bundle count 300 - if !spec.ExportAll && spec.BundleEnd >= spec.BundleStart { 301 - existingCount = int(spec.BundleEnd - spec.BundleStart + 1) 302 - } else if spec.ExportAll { 303 - index := mgr.GetIndex() 304 - bundles := index.GetBundles() 305 - existingCount = len(bundles) 306 - } 181 + // Phase 1: Export existing bundles 182 + existingCount := 0 183 + if opts.end > 0 { 184 + existingCount, exported = exportExistingBundles( 185 + ctx, mgr, opts.start, opts.end, 186 + &operationCount, opts.count, opts.afterTime, 187 + opts.verbose, opts.quiet, 188 + ) 307 189 } 308 190 309 191 // Check if we hit the count limit 310 - if opts.count > 0 && exported >= uint64(opts.count) { 192 + if opts.count > 0 && exported >= opts.count { 311 193 if !opts.quiet { 312 194 fmt.Fprintf(os.Stderr, "\nโœ“ Export complete (limit reached)\n") 313 - if existingCount > 0 { 314 - fmt.Fprintf(os.Stderr, " Bundles: %d\n", existingCount) 315 - } 195 + fmt.Fprintf(os.Stderr, " Bundles: %d\n", existingCount) 316 196 fmt.Fprintf(os.Stderr, " Operations: %d\n", exported) 317 197 } 318 198 return nil ··· 320 200 321 201 // Phase 2: Sync and export new bundles (if enabled and not at limit) 322 202 fetchedCount := 0 323 - if opts.sync && (opts.count == 0 || exported < uint64(opts.count)) { 203 + if opts.sync && (opts.count == 0 || exported < opts.count) { 324 204 if !opts.quiet { 325 205 fmt.Fprintf(os.Stderr, "\nSyncing new bundles from PLC...\n") 326 206 } ··· 335 215 if bundle, err := mgr.LoadBundle(ctx, bundleNum); err == nil { 336 216 for _, op := range bundle.Operations { 337 217 // Apply filters 338 - if opts.afterTimestamp != "" { 339 - opTime := op.CreatedAt.Format(time.RFC3339) 340 - if opTime < opts.afterTimestamp { 341 - continue 342 - } 218 + if !opts.afterTime.IsZero() && op.CreatedAt.Before(opts.afterTime) { 219 + continue 343 220 } 344 221 345 - if opts.count > 0 && exported >= uint64(opts.count) { 222 + if opts.count > 0 && exported >= opts.count { 346 223 return // Stop when limit reached 347 224 } 348 225 ··· 354 231 fmt.Println(string(data)) 355 232 } 356 233 exported++ 234 + operationCount++ 357 235 } 358 236 } 359 237 }, ··· 375 253 existingCount+fetchedCount, existingCount, fetchedCount) 376 254 } else if opts.sync { 377 255 fmt.Fprintf(os.Stderr, " Bundles: %d (already up to date)\n", existingCount) 378 - } else if existingCount > 0 { 256 + } else { 379 257 fmt.Fprintf(os.Stderr, " Bundles: %d\n", existingCount) 380 258 } 381 259 ··· 389 267 return nil 390 268 } 391 269 392 - // exportToWriterGo is the fallback Go implementation 393 - func exportToWriterGo(ctx context.Context, mgr *bundle.Manager, spec ExportSpec, writer io.Writer, progress func(records, bytes uint64), exported *uint64, existingCount *int) error { 394 - var recordsWritten uint64 395 - var bytesWritten uint64 396 - var bundlesProcessed int 270 + func exportExistingBundles( 271 + ctx context.Context, 272 + mgr BundleManager, 273 + start, end int, 274 + operationCount *int, 275 + limit int, 276 + afterTime time.Time, 277 + verbose bool, 278 + quiet bool, 279 + ) (bundleCount int, exported int) { 397 280 398 - bundles := mgr.GetIndex().GetBundles() 399 - if len(bundles) == 0 { 400 - *exported = 0 401 - *existingCount = 0 402 - return nil 403 - } 281 + processedCount := 0 282 + exportedOps := 0 404 283 405 - // Determine bundle range 406 - startBundle := 0 407 - endBundle := len(bundles) - 1 408 - 409 - if spec.ExportAll { 410 - startBundle = 0 411 - endBundle = len(bundles) - 1 412 - } else { 413 - // Find start and end indices 414 - startBundle = -1 415 - endBundle = -1 416 - for i, b := range bundles { 417 - if startBundle == -1 && b.BundleNumber >= int(spec.BundleStart) { 418 - startBundle = i 419 - } 420 - if b.BundleNumber <= int(spec.BundleEnd) { 421 - endBundle = i 422 - } 423 - } 424 - if startBundle == -1 || endBundle == -1 || startBundle > endBundle { 425 - *exported = 0 426 - *existingCount = 0 427 - return nil 428 - } 429 - } 430 - 431 - // Parse after timestamp 432 - var afterTime time.Time 433 - if spec.AfterTimestamp != "" { 434 - var err error 435 - afterTime, err = time.Parse(time.RFC3339, spec.AfterTimestamp) 436 - if err != nil { 437 - return fmt.Errorf("invalid after timestamp: %w", err) 438 - } 439 - } 440 - 441 - // Export bundles 442 - for i := startBundle; i <= endBundle; i++ { 284 + for bundleNum := start; bundleNum <= end; bundleNum++ { 443 285 select { 444 286 case <-ctx.Done(): 445 - *exported = recordsWritten 446 - *existingCount = bundlesProcessed 447 - return ctx.Err() 287 + return processedCount, exportedOps 448 288 default: 449 289 } 450 290 451 - meta := bundles[i] 452 - bundle, err := mgr.LoadBundle(ctx, meta.BundleNumber) 291 + bundle, err := mgr.LoadBundle(ctx, bundleNum) 453 292 if err != nil { 293 + if verbose { 294 + fmt.Fprintf(os.Stderr, "Bundle %06d: not found (skipped)\n", bundleNum) 295 + } 454 296 continue 455 297 } 456 298 457 - // Export operations 299 + // Export operations with filters 458 300 for _, op := range bundle.Operations { 459 - // Apply filters 301 + // Filter by timestamp 460 302 if !afterTime.IsZero() && op.CreatedAt.Before(afterTime) { 461 303 continue 462 304 } 463 - if spec.DIDFilter != "" && op.DID != spec.DIDFilter { 464 - continue 465 - } 466 - if spec.OpTypeFilter != "" { 467 - // Operation type is inside the parsed operation data 468 - opData, err := op.GetOperationData() 469 - if err == nil && opData != nil { 470 - if opType, ok := opData["type"].(string); ok && opType != spec.OpTypeFilter { 471 - continue 472 - } else if !ok { 473 - continue // Skip if no type field 474 - } 475 - } else { 476 - continue // Skip if can't parse 305 + 306 + // Check count limit 307 + if limit > 0 && exportedOps >= limit { 308 + if verbose { 309 + fmt.Fprintf(os.Stderr, "Bundle %06d: limit reached, stopping\n", bundleNum) 477 310 } 478 - } 479 - if spec.CountLimit > 0 && recordsWritten >= spec.CountLimit { 480 - *exported = recordsWritten 481 - *existingCount = bundlesProcessed 482 - return nil 311 + return processedCount, exportedOps 483 312 } 484 313 485 - // Write operation 486 - var data []byte 314 + // Output operation to stdout (JSONL) 487 315 if len(op.RawJSON) > 0 { 488 - data = op.RawJSON 316 + fmt.Println(string(op.RawJSON)) 489 317 } else { 490 - var err error 491 - data, err = json.Marshal(op) 492 - if err != nil { 493 - continue 494 - } 495 - } 496 - data = append(data, '\n') 497 - 498 - if _, err := writer.Write(data); err != nil { 499 - return fmt.Errorf("write failed: %w", err) 318 + data, _ := json.Marshal(op) 319 + fmt.Println(string(data)) 500 320 } 321 + exportedOps++ 322 + } 501 323 502 - recordsWritten++ 503 - bytesWritten += uint64(len(data)) 324 + *operationCount += len(bundle.Operations) 325 + processedCount++ 504 326 505 - if progress != nil && recordsWritten%1000 == 0 { 506 - progress(recordsWritten, bytesWritten) 507 - } 327 + if verbose { 328 + fmt.Fprintf(os.Stderr, "Bundle %06d: โœ“ (%d ops, %d exported)\n", 329 + bundleNum, len(bundle.Operations), exportedOps) 330 + } else if !quiet && processedCount%100 == 0 { 331 + fmt.Fprintf(os.Stderr, "Exported: %d bundles, %d ops\r", processedCount, exportedOps) 508 332 } 509 - 510 - bundlesProcessed++ 511 333 } 512 334 513 - if progress != nil { 514 - progress(recordsWritten, bytesWritten) 335 + if !quiet && !verbose && processedCount > 0 { 336 + fmt.Fprintf(os.Stderr, "Existing: %d bundles, %d ops\n", processedCount, exportedOps) 515 337 } 516 338 517 - *exported = recordsWritten 518 - *existingCount = bundlesProcessed 519 - return nil 339 + return processedCount, exportedOps 520 340 } 521 341 522 342 type exportLogger struct {
+16 -16
cmd/plcbundle/commands/index.go
··· 7 7 8 8 "github.com/goccy/go-json" 9 9 "github.com/spf13/cobra" 10 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 10 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 11 11 ) 12 12 13 13 func NewIndexCommand() *cobra.Command { ··· 21 21 resolution and query operations.`, 22 22 23 23 Example: ` # Build DID position index 24 - plcbundle index build 24 + plcbundle-go index build 25 25 26 26 # Repair DID index (rebuild from bundles) 27 - plcbundle index repair 27 + plcbundle-go index repair 28 28 29 29 # Show DID index statistics 30 - plcbundle index stats 30 + plcbundle-go index stats 31 31 32 32 # Verify DID index integrity 33 - plcbundle index verify`, 33 + plcbundle-go index verify`, 34 34 } 35 35 36 36 cmd.AddCommand(newIndexBuildCommand()) ··· 60 60 are added. Use --force to rebuild from scratch.`, 61 61 62 62 Example: ` # Build index 63 - plcbundle index build 63 + plcbundle-go index build 64 64 65 65 # Force rebuild from scratch 66 - plcbundle index build --force`, 66 + plcbundle-go index build --force`, 67 67 68 68 RunE: func(cmd *cobra.Command, args []string) error { 69 69 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 141 141 โ€ข Upgrade to new index version`, 142 142 143 143 Example: ` # Repair DID index 144 - plcbundle index repair 144 + plcbundle-go index repair 145 145 146 146 # Verbose output 147 - plcbundle index repair -v`, 147 + plcbundle-go index repair -v`, 148 148 149 149 RunE: func(cmd *cobra.Command, args []string) error { 150 150 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose") ··· 158 158 stats := mgr.GetDIDIndexStats() 159 159 if !stats["exists"].(bool) { 160 160 fmt.Printf("DID index does not exist\n") 161 - fmt.Printf("Use: plcbundle index build\n") 161 + fmt.Printf("Use: plcbundle-go index build\n") 162 162 return nil 163 163 } 164 164 ··· 237 237 shard distribution, cache statistics, and coverage.`, 238 238 239 239 Example: ` # Show statistics 240 - plcbundle index stats 240 + plcbundle-go index stats 241 241 242 242 # JSON output 243 - plcbundle index stats --json`, 243 + plcbundle-go index stats --json`, 244 244 245 245 RunE: func(cmd *cobra.Command, args []string) error { 246 246 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 259 259 260 260 if !stats["exists"].(bool) { 261 261 fmt.Printf("DID index does not exist\n") 262 - fmt.Printf("Run: plcbundle index build\n") 262 + fmt.Printf("Run: plcbundle-go index build\n") 263 263 return nil 264 264 } 265 265 ··· 332 332 Automatically repairs minor issues.`, 333 333 334 334 Example: ` # Verify DID index 335 - plcbundle index verify 335 + plcbundle-go index verify 336 336 337 337 # Verbose output 338 - plcbundle index verify -v`, 338 + plcbundle-go index verify -v`, 339 339 340 340 RunE: func(cmd *cobra.Command, args []string) error { 341 341 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 348 348 349 349 if !stats["exists"].(bool) { 350 350 fmt.Printf("DID index does not exist\n") 351 - fmt.Printf("Run: plcbundle index build\n") 351 + fmt.Printf("Run: plcbundle-go index build\n") 352 352 return nil 353 353 } 354 354
+8 -8
cmd/plcbundle/commands/inspect.go
··· 11 11 12 12 "github.com/goccy/go-json" 13 13 "github.com/spf13/cobra" 14 - "tangled.org/atscan.net/plcbundle/internal/storage" 14 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 15 15 ) 16 16 17 17 // ============================================================================ ··· 178 178 Can inspect either by bundle number (from repository) or direct file path.`, 179 179 180 180 Example: ` # Inspect from repository 181 - plcbundle inspect 42 181 + plcbundle-go inspect 42 182 182 183 183 # Inspect specific file 184 - plcbundle inspect /path/to/000042.jsonl.zst 185 - plcbundle inspect 000042.jsonl.zst 184 + plcbundle-go inspect /path/to/000042.jsonl.zst 185 + plcbundle-go inspect 000042.jsonl.zst 186 186 187 187 # Skip certain analysis sections 188 - plcbundle inspect 42 --skip-patterns --skip-crypto 188 + plcbundle-go inspect 42 --skip-patterns --skip-crypto 189 189 190 190 # Show sample operations 191 - plcbundle inspect 42 --samples --sample-count 20 191 + plcbundle-go inspect 42 --samples --sample-count 20 192 192 193 193 # Verify all hashes 194 - plcbundle inspect 42 --verify 194 + plcbundle-go inspect 42 --verify 195 195 196 196 # JSON output (for scripting) 197 - plcbundle inspect 42 --json`, 197 + plcbundle-go inspect 42 --json`, 198 198 199 199 Args: cobra.ExactArgs(1), 200 200
+12 -12
cmd/plcbundle/commands/log.go
··· 10 10 11 11 "github.com/spf13/cobra" 12 12 "golang.org/x/term" 13 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 13 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 14 14 ) 15 15 16 16 func NewLogCommand() *cobra.Command { ··· 43 43 is a terminal, just like 'git log'. Use --no-pager to disable.`, 44 44 45 45 Example: ` # Show all bundles (newest first, auto-paged) 46 - plcbundle log 46 + plcbundle-go log 47 47 48 48 # Show last 10 bundles 49 - plcbundle log --last 10 50 - plcbundle log -n 10 49 + plcbundle-go log --last 10 50 + plcbundle-go log -n 10 51 51 52 52 # One-line format 53 - plcbundle log --oneline 53 + plcbundle-go log --oneline 54 54 55 55 # Hide hashes 56 - plcbundle log --no-hashes 56 + plcbundle-go log --no-hashes 57 57 58 58 # Oldest first (ascending order) 59 - plcbundle log --reverse 59 + plcbundle-go log --reverse 60 60 61 61 # Disable pager (direct output) 62 - plcbundle log --no-pager 62 + plcbundle-go log --no-pager 63 63 64 64 # Combination 65 - plcbundle log -n 20 --oneline 65 + plcbundle-go log -n 20 --oneline 66 66 67 67 # Using alias 68 - plcbundle history -n 5`, 68 + plcbundle-go history -n 5`, 69 69 70 70 RunE: func(cmd *cobra.Command, args []string) error { 71 71 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 110 110 fmt.Printf("No bundles in repository\n") 111 111 fmt.Printf("Directory: %s\n\n", dir) 112 112 fmt.Printf("Get started:\n") 113 - fmt.Printf(" plcbundle clone <url> Clone from remote\n") 114 - fmt.Printf(" plcbundle sync Fetch from PLC directory\n") 113 + fmt.Printf(" plcbundle-go clone <url> Clone from remote\n") 114 + fmt.Printf(" plcbundle-go sync Fetch from PLC directory\n") 115 115 return nil 116 116 } 117 117
+11 -11
cmd/plcbundle/commands/ls.go
··· 6 6 "time" 7 7 8 8 "github.com/spf13/cobra" 9 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 9 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 10 10 ) 11 11 12 12 func NewLsCommand() *cobra.Command { ··· 30 30 shell scripts and automation.`, 31 31 32 32 Example: ` # List all bundles 33 - plcbundle ls 33 + plcbundle-go ls 34 34 35 35 # Last 10 bundles 36 - plcbundle ls -n 10 36 + plcbundle-go ls -n 10 37 37 38 38 # Oldest first 39 - plcbundle ls --reverse 39 + plcbundle-go ls --reverse 40 40 41 41 # Custom format 42 - plcbundle ls --format "bundle,hash,date,size" 42 + plcbundle-go ls --format "bundle,hash,date,size" 43 43 44 44 # CSV format 45 - plcbundle ls --separator "," 45 + plcbundle-go ls --separator "," 46 46 47 47 # Scripting examples 48 - plcbundle ls | awk '{print $1}' # Just bundle numbers 49 - plcbundle ls | grep 000150 # Find specific bundle 50 - plcbundle ls -n 5 | cut -f1,4 # First and 4th columns 51 - plcbundle ls --format bundle,hash # Custom columns 52 - plcbundle ls --separator "," > bundles.csv # Export to CSV`, 48 + plcbundle-go ls | awk '{print $1}' # Just bundle numbers 49 + plcbundle-go ls | grep 000150 # Find specific bundle 50 + plcbundle-go ls -n 5 | cut -f1,4 # First and 4th columns 51 + plcbundle-go ls --format bundle,hash # Custom columns 52 + plcbundle-go ls --separator "," > bundles.csv # Export to CSV`, 53 53 54 54 RunE: func(cmd *cobra.Command, args []string) error { 55 55 mgr, _, err := getManager(&ManagerOptions{Cmd: cmd})
+19 -19
cmd/plcbundle/commands/mempool.go
··· 9 9 10 10 "github.com/goccy/go-json" 11 11 "github.com/spf13/cobra" 12 - "tangled.org/atscan.net/plcbundle/internal/types" 12 + "tangled.org/atscan.net/plcbundle-go/internal/types" 13 13 ) 14 14 15 15 func NewMempoolCommand() *cobra.Command { ··· 23 23 strict chronological order and automatically validates consistency.`, 24 24 25 25 Example: ` # Show mempool status 26 - plcbundle mempool 27 - plcbundle mempool status 26 + plcbundle-go mempool 27 + plcbundle-go mempool status 28 28 29 29 # Clear all operations 30 - plcbundle mempool clear 30 + plcbundle-go mempool clear 31 31 32 32 # Export operations as JSONL 33 - plcbundle mempool dump 34 - plcbundle mempool dump > operations.jsonl 33 + plcbundle-go mempool dump 34 + plcbundle-go mempool dump > operations.jsonl 35 35 36 36 # Using alias 37 - plcbundle mp status`, 37 + plcbundle-go mp status`, 38 38 39 39 RunE: func(cmd *cobra.Command, args []string) error { 40 40 // Default to status subcommand ··· 67 67 next bundle, validation status, and memory usage.`, 68 68 69 69 Example: ` # Show status 70 - plcbundle mempool status 71 - plcbundle mempool 70 + plcbundle-go mempool status 71 + plcbundle-go mempool 72 72 73 73 # Verbose output with samples 74 - plcbundle mempool status -v`, 74 + plcbundle-go mempool status -v`, 75 75 76 76 RunE: func(cmd *cobra.Command, args []string) error { 77 77 return mempoolStatus(cmd, args) ··· 123 123 โ€ข Force fresh start`, 124 124 125 125 Example: ` # Clear with confirmation 126 - plcbundle mempool clear 126 + plcbundle-go mempool clear 127 127 128 128 # Force clear without confirmation 129 - plcbundle mempool clear --force 130 - plcbundle mempool clear -f`, 129 + plcbundle-go mempool clear --force 130 + plcbundle-go mempool clear -f`, 131 131 132 132 RunE: func(cmd *cobra.Command, args []string) error { 133 133 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 188 188 Perfect for backup, analysis, or piping to other tools.`, 189 189 190 190 Example: ` # Dump to stdout 191 - plcbundle mempool dump 191 + plcbundle-go mempool dump 192 192 193 193 # Save to file 194 - plcbundle mempool dump > mempool.jsonl 195 - plcbundle mempool dump -o mempool.jsonl 194 + plcbundle-go mempool dump > mempool.jsonl 195 + plcbundle-go mempool dump -o mempool.jsonl 196 196 197 197 # Pipe to jq 198 - plcbundle mempool dump | jq -r .did 198 + plcbundle-go mempool dump | jq -r .did 199 199 200 200 # Count operations 201 - plcbundle mempool dump | wc -l 201 + plcbundle-go mempool dump | wc -l 202 202 203 203 # Using alias 204 - plcbundle mempool export`, 204 + plcbundle-go mempool export`, 205 205 206 206 RunE: func(cmd *cobra.Command, args []string) error { 207 207 mgr, _, err := getManager(&ManagerOptions{Cmd: cmd})
+8 -8
cmd/plcbundle/commands/migrate.go
··· 8 8 "time" 9 9 10 10 "github.com/spf13/cobra" 11 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 12 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 13 - "tangled.org/atscan.net/plcbundle/internal/storage" 11 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 12 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 13 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 14 14 ) 15 15 16 16 func NewMigrateCommand() *cobra.Command { ··· 41 41 Original files are replaced atomically. Use --dry-run to preview.`, 42 42 43 43 Example: ` # Preview migration (recommended first) 44 - plcbundle migrate --dry-run 44 + plcbundle-go migrate --dry-run 45 45 46 46 # Migrate all legacy bundles 47 - plcbundle migrate 47 + plcbundle-go migrate 48 48 49 49 # Force migration even if .idx files exist 50 - plcbundle migrate --force 50 + plcbundle-go migrate --force 51 51 52 52 # Parallel migration (faster) 53 - plcbundle migrate --workers 8 53 + plcbundle-go migrate --workers 8 54 54 55 55 # Verbose output 56 - plcbundle migrate -v`, 56 + plcbundle-go migrate -v`, 57 57 58 58 RunE: func(cmd *cobra.Command, args []string) error { 59 59 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose")
+17 -17
cmd/plcbundle/commands/op.go
··· 10 10 11 11 "github.com/goccy/go-json" 12 12 "github.com/spf13/cobra" 13 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 14 - "tangled.org/atscan.net/plcbundle/internal/types" 13 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 14 + "tangled.org/atscan.net/plcbundle-go/internal/types" 15 15 ) 16 16 17 17 func NewOpCommand() *cobra.Command { ··· 29 29 Example: 88410345 = bundle 8841, position 345`, 30 30 31 31 Example: ` # Get operation as JSON 32 - plcbundle op get 42 1337 33 - plcbundle op get 420000 32 + plcbundle-go op get 42 1337 33 + plcbundle-go op get 420000 34 34 35 35 # Show operation (formatted) 36 - plcbundle op show 42 1337 37 - plcbundle op show 88410345 36 + plcbundle-go op show 42 1337 37 + plcbundle-go op show 88410345 38 38 39 39 # Find by CID 40 - plcbundle op find bafyreig3...`, 40 + plcbundle-go op find bafyreig3...`, 41 41 } 42 42 43 43 // Add subcommands ··· 69 69 Use -v/--verbose to see detailed timing breakdown.`, 70 70 71 71 Example: ` # By bundle + position 72 - plcbundle op get 42 1337 72 + plcbundle-go op get 42 1337 73 73 74 74 # By global position 75 - plcbundle op get 88410345 75 + plcbundle-go op get 88410345 76 76 77 77 # With timing metrics 78 - plcbundle op get 42 1337 -v 79 - plcbundle op get 88410345 --verbose 78 + plcbundle-go op get 42 1337 -v 79 + plcbundle-go op get 88410345 --verbose 80 80 81 81 # Pipe to jq 82 - plcbundle op get 42 1337 | jq .did`, 82 + plcbundle-go op get 42 1337 | jq .did`, 83 83 84 84 Args: cobra.RangeArgs(1, 2), 85 85 ··· 154 154 โ€ข Performance metrics (with -v)`, 155 155 156 156 Example: ` # By bundle + position 157 - plcbundle op show 42 1337 157 + plcbundle-go op show 42 1337 158 158 159 159 # By global position 160 - plcbundle op show 88410345 160 + plcbundle-go op show 88410345 161 161 162 162 # Verbose with timing and full JSON 163 - plcbundle op show 42 1337 -v`, 163 + plcbundle-go op show 42 1337 -v`, 164 164 165 165 Args: cobra.RangeArgs(1, 2), 166 166 ··· 218 218 Note: This performs a full scan and can be slow on large repositories.`, 219 219 220 220 Example: ` # Find by CID 221 - plcbundle op find bafyreig3tg4k... 221 + plcbundle-go op find bafyreig3tg4k... 222 222 223 223 # Pipe to op get 224 - plcbundle op find bafyreig3... | awk '{print $3, $5}' | xargs plcbundle op get`, 224 + plcbundle-go op find bafyreig3... | awk '{print $3, $5}' | xargs plcbundle-go op get`, 225 225 226 226 Args: cobra.ExactArgs(1), 227 227
+1 -1
cmd/plcbundle/commands/progress_helper.go
··· 1 1 package commands 2 2 3 3 import ( 4 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 4 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 5 5 ) 6 6 7 7 // NewBundleProgressBar creates a progress bar with auto-calculated bytes from bundles
+1 -1
cmd/plcbundle/commands/query.go
··· 15 15 "github.com/goccy/go-json" 16 16 "github.com/jmespath-community/go-jmespath" // Correct import 17 17 "github.com/spf13/cobra" 18 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 18 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 19 19 ) 20 20 21 21 func NewQueryCommand() *cobra.Command {
+9 -9
cmd/plcbundle/commands/rollback.go
··· 8 8 "strings" 9 9 10 10 "github.com/spf13/cobra" 11 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 12 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 11 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 12 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 13 13 ) 14 14 15 15 func NewRollbackCommand() *cobra.Command { ··· 46 46 7. Optionally rebuilds DID index`, 47 47 48 48 Example: ` # Rollback TO bundle 100 (keeps 1-100, removes 101+) 49 - plcbundle rollback --to 100 49 + plcbundle-go rollback --to 100 50 50 51 51 # Remove last 5 bundles 52 - plcbundle rollback --last 5 52 + plcbundle-go rollback --last 5 53 53 54 54 # Rollback without confirmation 55 - plcbundle rollback --to 50 --force 55 + plcbundle-go rollback --to 50 --force 56 56 57 57 # Rollback and rebuild DID index 58 - plcbundle rollback --to 100 --rebuild-did-index 58 + plcbundle-go rollback --to 100 --rebuild-did-index 59 59 60 60 # Rollback but keep bundle files (index-only) 61 - plcbundle rollback --to 100 --keep-files`, 61 + plcbundle-go rollback --to 100 --keep-files`, 62 62 63 63 RunE: func(cmd *cobra.Command, args []string) error { 64 64 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose") ··· 464 464 fmt.Printf(" Index has bundle %06d, but repository now at %06d\n", 465 465 config.LastBundle, plan.targetBundle) 466 466 } 467 - fmt.Printf(" Run: plcbundle index build\n") 467 + fmt.Printf(" Run: plcbundle-go index build\n") 468 468 } 469 469 470 470 return nil ··· 524 524 if !opts.rebuildDIDIndex && plan.hasDIDIndex { 525 525 fmt.Printf("๐Ÿ’ก Next Steps\n") 526 526 fmt.Printf(" DID index is out of date. Rebuild with:\n") 527 - fmt.Printf(" plcbundle index build\n\n") 527 + fmt.Printf(" plcbundle-go index build\n\n") 528 528 } 529 529 }
+14 -14
cmd/plcbundle/commands/server.go
··· 9 9 "time" 10 10 11 11 "github.com/spf13/cobra" 12 - "tangled.org/atscan.net/plcbundle/bundle" 13 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 14 - "tangled.org/atscan.net/plcbundle/server" 12 + "tangled.org/atscan.net/plcbundle-go/bundle" 13 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 14 + "tangled.org/atscan.net/plcbundle-go/server" 15 15 ) 16 16 17 17 func NewServerCommand() *cobra.Command { ··· 43 43 - Live mempool (in sync mode) 44 44 45 45 Sync mode (--sync) runs as a daemon, continuously fetching new bundles. 46 - For one-time sync, use 'plcbundle sync' command instead.`, 46 + For one-time sync, use 'plcbundle-go sync' command instead.`, 47 47 48 48 Example: ` # Basic server (read-only, current directory) 49 - plcbundle server 49 + plcbundle-go server 50 50 51 51 # Server with specific directory 52 - plcbundle server --dir ./my-bundles 52 + plcbundle-go server --dir ./my-bundles 53 53 54 54 # Live syncing server (daemon mode) 55 - plcbundle server --sync 56 - plcbundle server -s 55 + plcbundle-go server --sync 56 + plcbundle-go server -s 57 57 58 58 # Using alias 59 - plcbundle serve -s 59 + plcbundle-go serve -s 60 60 61 61 # Custom port and host 62 - plcbundle server --port 3000 --host 0.0.0.0 62 + plcbundle-go server --port 3000 --host 0.0.0.0 63 63 64 64 # Full featured server 65 - plcbundle server -s --websocket --resolver 65 + plcbundle-go server -s --websocket --resolver 66 66 67 67 # Fast sync interval 68 - plcbundle server -s --interval 30s 68 + plcbundle-go server -s --interval 30s 69 69 70 70 # Sync with limit (stop after 1000 bundles) 71 - plcbundle server -s --max-bundles 1000 71 + plcbundle-go server -s --max-bundles 1000 72 72 73 73 # Public server with all features 74 - plcbundle serve -s --websocket --resolver --host 0.0.0.0 --port 80`, 74 + plcbundle-go serve -s --websocket --resolver --host 0.0.0.0 --port 80`, 75 75 76 76 RunE: func(cmd *cobra.Command, args []string) error { 77 77 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose")
+6 -6
cmd/plcbundle/commands/status.go
··· 6 6 "time" 7 7 8 8 "github.com/spf13/cobra" 9 - "tangled.org/atscan.net/plcbundle/bundle" 10 - "tangled.org/atscan.net/plcbundle/internal/types" 9 + "tangled.org/atscan.net/plcbundle-go/bundle" 10 + "tangled.org/atscan.net/plcbundle-go/internal/types" 11 11 ) 12 12 13 13 func NewStatusCommand() *cobra.Command { ··· 21 21 storage, timeline, mempool, and DID index status.`, 22 22 23 23 Example: ` # Show status 24 - plcbundle status 24 + plcbundle-go status 25 25 26 26 # Using alias 27 - plcbundle info`, 27 + plcbundle-go info`, 28 28 29 29 RunE: func(cmd *cobra.Command, args []string) error { 30 30 mgr, dir, err := getManager(&ManagerOptions{Cmd: cmd}) ··· 61 61 if bundleCount == 0 { 62 62 fmt.Printf("โš ๏ธ Empty repository (no bundles)\n\n") 63 63 fmt.Printf("Get started:\n") 64 - fmt.Printf(" plcbundle clone <url> Clone from remote\n") 65 - fmt.Printf(" plcbundle sync Fetch from PLC directory\n\n") 64 + fmt.Printf(" plcbundle-go clone <url> Clone from remote\n") 65 + fmt.Printf(" plcbundle-go sync Fetch from PLC directory\n\n") 66 66 return nil 67 67 } 68 68
+9 -9
cmd/plcbundle/commands/sync.go
··· 9 9 "time" 10 10 11 11 "github.com/spf13/cobra" 12 - "tangled.org/atscan.net/plcbundle/bundle" 13 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 12 + "tangled.org/atscan.net/plcbundle-go/bundle" 13 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 14 14 ) 15 15 16 16 func NewSyncCommand() *cobra.Command { ··· 34 34 that continuously syncs at regular intervals.`, 35 35 36 36 Example: ` # Fetch new bundles once 37 - plcbundle sync 37 + plcbundle-go sync 38 38 39 39 # Fetch from specific directory 40 - plcbundle sync --dir ./my-bundles 40 + plcbundle-go sync --dir ./my-bundles 41 41 42 42 # Run continuously (daemon mode) 43 - plcbundle sync --continuous 43 + plcbundle-go sync --continuous 44 44 45 45 # Custom sync interval 46 - plcbundle sync --continuous --interval 30s 46 + plcbundle-go sync --continuous --interval 30s 47 47 48 48 # Fetch maximum 10 bundles then stop 49 - plcbundle sync --max-bundles 10 49 + plcbundle-go sync --max-bundles 10 50 50 51 51 # Continuous with limit 52 - plcbundle sync --continuous --max-bundles 100 --interval 1m 52 + plcbundle-go sync --continuous --max-bundles 100 --interval 1m 53 53 54 54 # Verbose output 55 - plcbundle sync --continuous -v`, 55 + plcbundle-go sync --continuous -v`, 56 56 57 57 RunE: func(cmd *cobra.Command, args []string) error { 58 58 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose")
+8 -8
cmd/plcbundle/commands/verify.go
··· 7 7 "time" 8 8 9 9 "github.com/spf13/cobra" 10 - "tangled.org/atscan.net/plcbundle/bundle" 11 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui" 10 + "tangled.org/atscan.net/plcbundle-go/bundle" 11 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/ui" 12 12 ) 13 13 14 14 func NewVerifyCommand() *cobra.Command { ··· 37 37 โ€ข Chain hash calculations are valid`, 38 38 39 39 Example: ` # Verify entire chain 40 - plcbundle verify 41 - plcbundle verify --chain 40 + plcbundle-go verify 41 + plcbundle-go verify --chain 42 42 43 43 # Verify specific bundle 44 - plcbundle verify --bundle 42 44 + plcbundle-go verify --bundle 42 45 45 46 46 # Verify range of bundles 47 - plcbundle verify --range 1-100 47 + plcbundle-go verify --range 1-100 48 48 49 49 # Verbose output 50 - plcbundle verify --chain -v 50 + plcbundle-go verify --chain -v 51 51 52 52 # Parallel verification (faster for ranges) 53 - plcbundle verify --range 1-1000 --parallel --workers 8`, 53 + plcbundle-go verify --range 1-1000 --parallel --workers 8`, 54 54 55 55 RunE: func(cmd *cobra.Command, args []string) error { 56 56 verbose, _ := cmd.Root().PersistentFlags().GetBool("verbose")
+15 -15
cmd/plcbundle/main.go
··· 5 5 "os" 6 6 7 7 "github.com/spf13/cobra" 8 - "tangled.org/atscan.net/plcbundle/cmd/plcbundle/commands" 8 + "tangled.org/atscan.net/plcbundle-go/cmd/plcbundle/commands" 9 9 ) 10 10 11 11 func main() { ··· 20 20 21 21 func newRootCommand() *cobra.Command { 22 22 cmd := &cobra.Command{ 23 - Use: "plcbundle", 23 + Use: "plcbundle-go", 24 24 Short: "DID PLC Bundle Management Tool", 25 - Long: `plcbundle - DID PLC Bundle Management Tool 25 + Long: `plcbundle-go - DID PLC Bundle Management Tool 26 26 27 27 Tool for archiving AT Protocol's DID PLC Directory operations 28 28 into immutable, cryptographically-chained bundles of 10,000 ··· 89 89 Use: "version", 90 90 Short: "Show version information", 91 91 Run: func(cmd *cobra.Command, args []string) { 92 - cmd.Printf("plcbundle version %s\n", GetVersion()) 92 + cmd.Printf("plcbundle-go version %s\n", GetVersion()) 93 93 cmd.Printf(" commit: %s\n", getGitCommit()) 94 94 cmd.Printf(" built: %s\n", getBuildDate()) 95 95 }, ··· 105 105 To load completions: 106 106 107 107 Bash: 108 - $ source <(plcbundle completion bash) 108 + $ source <(plcbundle-go completion bash) 109 109 110 110 # To load automatically: 111 - $ plcbundle completion bash > /etc/bash_completion.d/plcbundle 111 + $ plcbundle-go completion bash > /etc/bash_completion.d/plcbundle-go 112 112 113 113 Zsh: 114 - $ plcbundle completion zsh > ~/.zsh/completion/_plcbundle 114 + $ plcbundle-go completion zsh > ~/.zsh/completion/_plcbundle-go 115 115 116 116 # Add to ~/.zshrc: 117 117 fpath=(~/.zsh/completion $fpath) 118 118 119 119 Fish: 120 - $ plcbundle completion fish > ~/.config/fish/completions/plcbundle.fish`, 120 + $ plcbundle-go completion fish > ~/.config/fish/completions/plcbundle-go.fish`, 121 121 122 122 Args: cobra.ExactArgs(1), 123 123 ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, ··· 140 140 } 141 141 142 142 func printRootHelp() { 143 - fmt.Print(`plcbundle ` + GetVersion() + ` - DID PLC Bundle Management 143 + fmt.Print(`plcbundle-go ` + GetVersion() + ` - DID PLC Bundle Management 144 144 145 - Usage: plcbundle <command> [options] 145 + Usage: plcbundle-go <command> [options] 146 146 147 147 Main Commands: 148 148 sync Fetch new bundles from PLC ··· 160 160 Tools: watch, heal, clean, mempool, detector 161 161 162 162 Getting Started: 163 - plcbundle clone https://plc.example.com 164 - plcbundle sync 165 - plcbundle status 163 + plcbundle-go clone https://plc.example.com 164 + plcbundle-go sync 165 + plcbundle-go status 166 166 167 - Run 'plcbundle help' for full documentation 168 - Run 'plcbundle <command> --help' for command help 167 + Run 'plcbundle-go help' for full documentation 168 + Run 'plcbundle-go <command> --help' for command help 169 169 `) 170 170 }
+1 -1
detector/builtin.go
··· 6 6 "regexp" 7 7 "strings" 8 8 9 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 9 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 10 10 ) 11 11 12 12 // NoOpDetector is an empty detector for speed testing
+1 -1
detector/detector.go
··· 5 5 "context" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 8 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 9 9 ) 10 10 11 11 // Detector represents a spam detection algorithm
+2 -2
detector/runner.go
··· 7 7 "sync" 8 8 "time" 9 9 10 - "tangled.org/atscan.net/plcbundle/bundle" 11 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 10 + "tangled.org/atscan.net/plcbundle-go/bundle" 11 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 12 12 ) 13 13 14 14 // Runner executes detectors against operations
+1 -1
detector/script.go
··· 14 14 "time" 15 15 16 16 "github.com/goccy/go-json" 17 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 17 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 18 18 ) 19 19 20 20 // ScriptDetector runs a JavaScript detector via Unix socket
+2 -5
go.mod
··· 1 - module tangled.org/atscan.net/plcbundle 1 + module tangled.org/atscan.net/plcbundle-go 2 2 3 - go 1.25.3 3 + go 1.25 4 4 5 5 require ( 6 6 github.com/goccy/go-json v0.10.5 ··· 10 10 github.com/valyala/gozstd v1.23.2 11 11 golang.org/x/sys v0.38.0 12 12 golang.org/x/term v0.36.0 13 - tangled.org/atscan.net/plcbundle-rs/bindings/go v0.0.0 14 13 ) 15 - 16 - replace tangled.org/atscan.net/plcbundle-rs/bindings/go => ../plcbundle-rs/bindings/go 17 14 18 15 require ( 19 16 github.com/inconshreveable/mousetrap v1.1.0 // indirect
+2 -2
internal/bundleindex/index_test.go
··· 8 8 "testing" 9 9 "time" 10 10 11 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 12 - "tangled.org/atscan.net/plcbundle/internal/types" 11 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 12 + "tangled.org/atscan.net/plcbundle-go/internal/types" 13 13 ) 14 14 15 15 type testLogger struct {
+1 -1
internal/didindex/bundle.go
··· 4 4 "context" 5 5 "time" 6 6 7 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 7 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 8 8 ) 9 9 10 10 // BundleProvider is an interface to avoid circular dependencies
+1 -1
internal/didindex/lookup.go
··· 6 6 "sort" 7 7 "sync" 8 8 9 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 9 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 10 10 ) 11 11 12 12 // GetDIDOperations retrieves all operations for a DID WITH location metadata
+1 -1
internal/didindex/manager.go
··· 13 13 14 14 "github.com/goccy/go-json" 15 15 "golang.org/x/sys/unix" 16 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 16 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 17 17 ) 18 18 19 19 // NewManager creates a new DID index manager
+1 -1
internal/didindex/manager_test.go
··· 3 3 import ( 4 4 "testing" 5 5 6 - "tangled.org/atscan.net/plcbundle/internal/didindex" 6 + "tangled.org/atscan.net/plcbundle-go/internal/didindex" 7 7 ) 8 8 9 9 func TestOpLocationPacking(t *testing.T) {
+1 -1
internal/didindex/types.go
··· 4 4 "sync" 5 5 "time" 6 6 7 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 7 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 8 8 ) 9 9 10 10 const (
+2 -2
internal/mempool/mempool.go
··· 10 10 "time" 11 11 12 12 "github.com/goccy/go-json" 13 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 14 - "tangled.org/atscan.net/plcbundle/internal/types" 13 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 14 + "tangled.org/atscan.net/plcbundle-go/internal/types" 15 15 ) 16 16 17 17 const MEMPOOL_FILE_PREFIX = "plc_mempool_"
+3 -3
internal/mempool/mempool_test.go
··· 8 8 "testing" 9 9 "time" 10 10 11 - "tangled.org/atscan.net/plcbundle/internal/mempool" 12 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 13 - "tangled.org/atscan.net/plcbundle/internal/types" 11 + "tangled.org/atscan.net/plcbundle-go/internal/mempool" 12 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 13 + "tangled.org/atscan.net/plcbundle-go/internal/types" 14 14 ) 15 15 16 16 type testLogger struct {
+2 -2
internal/plcclient/plc_test.go
··· 8 8 "testing" 9 9 "time" 10 10 11 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 12 - "tangled.org/atscan.net/plcbundle/internal/storage" 11 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 12 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 13 13 ) 14 14 15 15 // TestPLCOperation tests operation parsing and methods
+1 -1
internal/storage/storage.go
··· 13 13 "time" 14 14 15 15 "github.com/goccy/go-json" 16 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 16 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 17 17 ) 18 18 19 19 const (
+2 -2
internal/storage/storage_test.go
··· 10 10 "testing" 11 11 "time" 12 12 13 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 14 - "tangled.org/atscan.net/plcbundle/internal/storage" 13 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 14 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 15 15 ) 16 16 17 17 type testLogger struct {
+2 -2
internal/sync/bundler.go
··· 3 3 import ( 4 4 "time" 5 5 6 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 7 - "tangled.org/atscan.net/plcbundle/internal/storage" 6 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 7 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 8 8 ) 9 9 10 10 // CreateBundle creates a bundle structure from operations
+3 -3
internal/sync/cloner.go
··· 12 12 "time" 13 13 14 14 "github.com/goccy/go-json" 15 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 16 - "tangled.org/atscan.net/plcbundle/internal/storage" 17 - "tangled.org/atscan.net/plcbundle/internal/types" 15 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 16 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 17 + "tangled.org/atscan.net/plcbundle-go/internal/types" 18 18 ) 19 19 20 20 // Cloner handles cloning bundles from remote endpoints
+3 -3
internal/sync/fetcher.go
··· 5 5 "fmt" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 9 - "tangled.org/atscan.net/plcbundle/internal/storage" 10 - "tangled.org/atscan.net/plcbundle/internal/types" 8 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 9 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 10 + "tangled.org/atscan.net/plcbundle-go/internal/types" 11 11 ) 12 12 13 13 // Fetcher handles fetching operations from PLC directory
+4 -4
internal/sync/sync_test.go
··· 11 11 "time" 12 12 13 13 "github.com/goccy/go-json" 14 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 15 - "tangled.org/atscan.net/plcbundle/internal/storage" 16 - internalsync "tangled.org/atscan.net/plcbundle/internal/sync" 17 - "tangled.org/atscan.net/plcbundle/internal/types" 14 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 15 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 16 + internalsync "tangled.org/atscan.net/plcbundle-go/internal/sync" 17 + "tangled.org/atscan.net/plcbundle-go/internal/types" 18 18 ) 19 19 20 20 type testLogger struct {
+1 -1
internal/sync/syncer.go
··· 5 5 "context" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/internal/types" 8 + "tangled.org/atscan.net/plcbundle-go/internal/types" 9 9 ) 10 10 11 11 // SyncLoopConfig configures continuous syncing
+1 -1
internal/types/types_test.go
··· 5 5 "fmt" 6 6 "testing" 7 7 8 - "tangled.org/atscan.net/plcbundle/internal/types" 8 + "tangled.org/atscan.net/plcbundle-go/internal/types" 9 9 ) 10 10 11 11 // ====================================================================================
+2 -2
options.go
··· 1 1 package plcbundle 2 2 3 3 import ( 4 - "tangled.org/atscan.net/plcbundle/bundle" 5 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 4 + "tangled.org/atscan.net/plcbundle-go/bundle" 5 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 6 6 ) 7 7 8 8 type config struct {
+2 -2
server/handlers.go
··· 11 11 "time" 12 12 13 13 "github.com/goccy/go-json" 14 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 15 - "tangled.org/atscan.net/plcbundle/internal/types" 14 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 15 + "tangled.org/atscan.net/plcbundle-go/internal/types" 16 16 ) 17 17 18 18 func (s *Server) handleRoot() http.HandlerFunc {
+1 -1
server/helpers.go
··· 5 5 "net/http" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/bundle" 8 + "tangled.org/atscan.net/plcbundle-go/bundle" 9 9 ) 10 10 11 11 // getScheme determines the HTTP scheme
+1 -1
server/server.go
··· 5 5 "net/http" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/bundle" 8 + "tangled.org/atscan.net/plcbundle-go/bundle" 9 9 ) 10 10 11 11 // New creates a new HTTP server
+5 -5
server/server_test.go
··· 15 15 "time" 16 16 17 17 "github.com/gorilla/websocket" 18 - "tangled.org/atscan.net/plcbundle/bundle" 19 - "tangled.org/atscan.net/plcbundle/internal/bundleindex" 20 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 21 - "tangled.org/atscan.net/plcbundle/internal/storage" 22 - "tangled.org/atscan.net/plcbundle/server" 18 + "tangled.org/atscan.net/plcbundle-go/bundle" 19 + "tangled.org/atscan.net/plcbundle-go/internal/bundleindex" 20 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 21 + "tangled.org/atscan.net/plcbundle-go/internal/storage" 22 + "tangled.org/atscan.net/plcbundle-go/server" 23 23 ) 24 24 25 25 type testLogger struct {
+1 -1
server/types.go
··· 4 4 "net/http" 5 5 "time" 6 6 7 - "tangled.org/atscan.net/plcbundle/bundle" 7 + "tangled.org/atscan.net/plcbundle-go/bundle" 8 8 ) 9 9 10 10 // Server serves bundle data over HTTP
+1 -1
server/types_test.go
··· 5 5 "testing" 6 6 "time" 7 7 8 - "tangled.org/atscan.net/plcbundle/server" 8 + "tangled.org/atscan.net/plcbundle-go/server" 9 9 ) 10 10 11 11 func TestServerResponseTypes(t *testing.T) {
+2 -2
server/websocket.go
··· 11 11 12 12 "github.com/goccy/go-json" 13 13 "github.com/gorilla/websocket" 14 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 15 - "tangled.org/atscan.net/plcbundle/internal/types" 14 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 15 + "tangled.org/atscan.net/plcbundle-go/internal/types" 16 16 ) 17 17 18 18 var upgrader = websocket.Upgrader{
+1 -1
types.go
··· 3 3 import ( 4 4 "time" 5 5 6 - "tangled.org/atscan.net/plcbundle/internal/plcclient" 6 + "tangled.org/atscan.net/plcbundle-go/internal/plcclient" 7 7 ) 8 8 9 9 // Bundle represents a PLC bundle (public version)