crud

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

README

CRUD — niezależne nazwane rekordy

Ten katalog jest kopiowalnym modułem list/get/save/delete dowolnych nazwanych danych serializowalnych do YAML. Nie importuje srcpack, nie zna konfiguracji, app/schema, dawnych views ani selektorów. Nie jest bazą danych i nie prowadzi historii rewizji. Wartości są danymi, nigdy kodem do wykonania.

Skopiuj cały katalog, włącznie z crud.nflow, do własnego modułu. Zależności: Go 1.26.9, Flow i kernel v0.35.0, gopkg.in/yaml.v3 v3.0.1. Nie trzeba zmieniać wewnętrznych importów CRUD; konsument importuje moduł pod swoją ścieżką.

Użycie

_, err := crud.Execute(ctx, map[string]any{
    "operation": "save", "path": "data.yml", "name": "review",
    "value": map[string]any{"enabled": true},
})

operation: list, get, save lub delete; path jest wymaganym stringiem (lokalizacją interpretowaną przez magazyn), section domyślnie records. name musi być niepuste poza list, a replace jest domyślnie false. value może być strukturą, tablicą, skalarem lub null.

list zwraca {names: [...], records: {...}} z posortowanymi nazwami; get zwraca {value: ...}, a save/delete — {name: ...}. Wrapper Flow zwraca nazwy jako []any. errors.Is rozpoznaje ErrConflict i ErrNotFound. save istniejącej nazwy wymaga replace: true; zastępowany jest cały rekord, bez scalania i bez zachowania poprzedniej wersji. Brak nazwy przy get/delete nie zmienia magazynu.

other_setting: keep
records:
  review:
    enabled: true

Polityka i kompozycja

crud.nflow deklaruje schematy CrudOperationInput i CrudNamedOperationInput: typy, domyślne pola, dozwolone operacje i wymagane pola są opisane raz w @schema. @crud_operation() zachowuje warunkowy wymóg nazwy oraz odrzuca wartości złożone wyłącznie z białych znaków, odczytuje magazyn raz i wywołuje @crud_route(). Adapter może użyć @crud_route() po własnej walidacji i odczycie; nie następuje wtedy drugi odczyt. Bezpośrednie wywołanie route/akcji to interfejs niskopoziomowy — host musi wcześniej zweryfikować kopertę i rekordy.

Do kompozycji zamontuj crud.Bundle(nil) z native.Bundles(), ustaw compiler.WithSourceLoader(ctx, crud.Loader()), dołącz crud.nflow i wywołaj pipeline.crud lub makro w swoim pipeline. Publiczne ID to crud, FS zawiera źródło. Bundle montuje wyłącznie akcje crud.read, crud.patch, crud.reject. Go nie wybiera operacji ani reguł zastępowania; wykonuje magazyn i tłumaczy błędy.

Wymienny magazyn

type Store interface {
    Read(context.Context, string, string) (Snapshot, error)
    Patch(context.Context, string, string, Snapshot, Patch) error
}
type Snapshot struct {
    Entries map[string]any
    Token   any
}
type Patch struct {
    Key    string
    Remove bool
    Value  any
}

Parametry string w obu metodach to path i section. Read zwraca wpisy i token migawki odczytu. Patch mechanicznie zmienia jeden klucz; nie ustala polityki konfliktu nazwy. Token jest przekazywany bez interpretacji. Może służyć własnemu magazynowi do kontroli współbieżności, ale domyślny magazyn jej nie zapewnia. Własny magazyn powinien zwracać stabilny widok wpisów i respektować anulowanie.

crud.WithStore(ctx, store) wybiera implementację zarówno dla Execute, jak i zewnętrznego runnera Flow, również przez adapter config_views. Domyślnie działa YAMLStore{}. Testowy magazyn pamięciowy nie korzysta w ogóle z filesystemu.

Akcja read zachowuje wejście, dodając entries i source (token). Akcja patch przyjmuje path, section, source oraz patch: {key, remove, value} i przekazuje token do Store.Patch; entries jest opcjonalne. Nie należy wiązać własnego magazynu z tym, że token magazynu YAML ma postać stringa.

Bezpieczny YAML, nie transakcje

YAMLStore przechowuje w tokenie źródłowy tekst YAML. Zachowuje niezwiązane węzły, sprawdza serializację i zapisuje atomowo przez xfs.WriteFileAtomic z trybem 0600. Formatowanie może się zmienić. Brak pliku oznacza pusty zbiór; odczyty go nie tworzą, a zapis może utworzyć katalogi. Pusty dokument i sekcja null są puste.

Niepoprawny YAML, wiele dokumentów, duplikaty kluczy, sekcja inna niż bezpośrednia mapa lub klucze sekcji inne niż stringi są odrzucane. Aliasy zamiast samej mapy sekcji nie są obsługiwane. Błędy odczytu, serializacji, anulowania i zapisu są propagowane; niedopuszczalne wartości Go nie powodują paniki procesu.

Zapis atomowy chroni integralność pliku, nie izoluje równoległych operacji read-modify-write. Host musi serializować autorów lub dostarczyć magazyn z własną kontrolą współbieżności. Nie ma ukrytych rewizji, automatycznego stosowania danych ani gwarancji transakcyjnych.

Testy niezależności

go test ./bundles/crud -count=1 uruchamia testy Go _test.go z xtest/ktest: magazyn pamięciowy, wszystkie operacje, konflikt/replace, null i struktury, walidację, propagację błędów, zachowanie YAML i awarię zapisu atomowego. TestCopiedBundleConsumer kopiuje produkcję i zestaw testów do osobnego modułu, uruchamia testy także zewnętrznego konsumenta i sprawdza brak srcpack w zależnościach. Nie używa asercji shellowych.

Documentation

Overview

Package crud provides a copyable, policy-free CRUD Flow bundle.

Index

Constants

View Source
const ID = "crud"

Variables

View Source
var (
	ErrConflict = errors.New("crud: conflict")
	ErrNotFound = errors.New("crud: not found")
)

Functions

func Bundle

func Bundle(_ map[string]string) compiler.Bundle

func Execute

func Execute(ctx context.Context, input map[string]any) (map[string]any, error)

func Loader

func Loader() compiler.SourceLoader

func WithStore

func WithStore(ctx context.Context, store Store) context.Context

WithStore scopes a Store override to Execute or an external Flow runner context.

Types

type Patch

type Patch struct {
	Key    string
	Remove bool
	Value  any
}

Patch describes a single-key mapping mutation.

type Snapshot

type Snapshot struct {
	Entries map[string]any
	Token   any
}

Snapshot is a read view and opaque token supplied back to the Store on patch.

type Store

type Store interface {
	Read(ctx context.Context, path, section string) (Snapshot, error)
	Patch(ctx context.Context, path, section string, snapshot Snapshot, patch Patch) error
}

Store is the persistence boundary; policy remains in NFlow.

type YAMLStore

type YAMLStore struct{}

YAMLStore preserves unrelated YAML nodes and writes patches atomically.

func (YAMLStore) Patch

func (YAMLStore) Patch(ctx context.Context, path, section string, snap Snapshot, patch Patch) error

func (YAMLStore) Read

func (YAMLStore) Read(ctx context.Context, path, section string) (Snapshot, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL