From c41d13bb77be467f9445526475d1ff2fb0f2c42f Mon Sep 17 00:00:00 2001 From: Kirillkriv Date: Fri, 21 Aug 2026 15:48:02 +0500 Subject: [PATCH] feat: json importer --- internal/adapters/json/json.go | 33 +++++++++++++++++++++++++++++ internal/application/application.go | 5 +++++ internal/controllers/cli/add.go | 2 ++ 3 files changed, 40 insertions(+) diff --git a/internal/adapters/json/json.go b/internal/adapters/json/json.go index 1367903..adb1378 100644 --- a/internal/adapters/json/json.go +++ b/internal/adapters/json/json.go @@ -4,16 +4,20 @@ import ( "context" "encoding/json" "github.com/abelith/spellbook/internal/adapters/exporter" + "github.com/abelith/spellbook/internal/adapters/importer" "github.com/abelith/spellbook/internal/models" "io" ) func init() { exporter.Register("jsonl", &JsonlExporter{}) + importer.Register("jsonl", &JsonlImporter{}) } type JsonlExporter struct{} +type JsonlImporter struct{} + func (je *JsonlExporter) Export(ctx context.Context, ch <-chan models.Spell, w io.Writer) error { encoder := json.NewEncoder(w) @@ -32,3 +36,32 @@ func (je *JsonlExporter) Export(ctx context.Context, ch <-chan models.Spell, w i } } } + +func (ji JsonlImporter) Import(ctx context.Context, r io.Reader) (<-chan models.Spell, <-chan error, error) { + ch := make(chan models.Spell, 1) + errCh := make(chan error, 1) + + dec := json.NewDecoder(r) + + go func() { + defer close(ch) + defer close(errCh) + + for dec.More() { + var spell models.Spell + if err := dec.Decode(&spell); err != nil { + errCh <- err + return + } + + select { + case <-ctx.Done(): + errCh <- ctx.Err() + return + case ch <- spell: + } + } + }() + + return ch, errCh, nil +} diff --git a/internal/application/application.go b/internal/application/application.go index c5928d4..5f21a5b 100644 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -100,12 +100,17 @@ func (a *Application) ImportSpells( name string, r io.Reader, ) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + ch, errCh, err := importer.Import(ctx, name, r) if err != nil { + cancel() return err } if err := a.spellCmd.Import(ctx, ch); err != nil { + cancel() return err } diff --git a/internal/controllers/cli/add.go b/internal/controllers/cli/add.go index 8b9b56d..7b07e45 100644 --- a/internal/controllers/cli/add.go +++ b/internal/controllers/cli/add.go @@ -14,6 +14,8 @@ var reservedCommands = map[string]struct{}{ "help": {}, "completion": {}, "search": {}, + "export": {}, + "import": {}, } func NewAddCommand(app Application) *cobra.Command {