Documentation
¶
Overview ¶
specscore: feature/cli/resolve/auto-resolve/record-merge
Index ¶
- Constants
- func ApplyLocaleToRead(data map[string]any, cols map[string]*ColumnDef) map[string]any
- func ApplyLocaleToWrite(data map[string]any, cols map[string]*ColumnDef) map[string]any
- func EncodeListOfRecordsContent(rows []map[string]any, format RecordFormat, columnsOrder []string) ([]byte, error)
- func EncodeMapOfRecordsContent(data map[string]map[string]any, format RecordFormat, recordsetName string, ...) ([]byte, error)
- func EncodeRecordContentForCollection(value any, colDef *CollectionDef) ([]byte, error)
- func EvaluateFormula(formula string, fields map[string]any) (any, error)
- func ParseListOfRecordsContent(content []byte, format RecordFormat) ([]map[string]any, error)
- func ParseMapOfRecordsContent(content []byte, format RecordFormat) (map[string]map[string]any, error)
- func ParseRecordContent(content []byte, format RecordFormat) (map[string]any, error)
- func ParseRecordContentForCollection(content []byte, colDef *CollectionDef) (map[string]any, error)
- func ResolveListRecordKey(row map[string]any, colDef *CollectionDef) (string, bool)
- func Validate() func(*ReadOptions)
- func ValidateCollectionID(id string) error
- func ValidateColumnType(ct ColumnType) error
- type ChangeKind
- type ChangedFile
- type CollectionDef
- type CollectionReadmeDef
- type CollectionsReader
- type ColumnDef
- type ColumnDefWithID
- type ColumnType
- type ConflictResolutionConfig
- type Definition
- type DiscordDef
- type EffectiveRecordMerge
- type EmailDef
- type GitHubActionDef
- type GitLabCIDef
- type HandlerBase
- type IRecordEntry
- type MaterializeResult
- type NtfyDef
- type ProgressEvent
- type ProgressKind
- type RSSDef
- type ReadOption
- type ReadOptions
- type RecordEntry
- type RecordFileDef
- type RecordFormat
- type RecordMergeConfig
- type RecordType
- type RecordsReader
- type RuntimeOverrides
- type SMSDef
- type Scanner
- type SearchIndexDef
- type Settings
- type Severity
- type SlackDef
- type SubscriberDef
- type SubscriberFor
- type TelegramDef
- type TriggerDef
- type TriggerEventType
- type TriggerJobDef
- type TriggerStepDef
- type ValidationError
- type ValidationResult
- func (r *ValidationResult) Append(e ValidationError)
- func (r *ValidationResult) ErrorCount() int
- func (r *ValidationResult) Errors() []ValidationError
- func (r *ValidationResult) Filter(fn func(ValidationError) bool) []ValidationError
- func (r *ValidationResult) GetRecordCount(collectionID string) int
- func (r *ValidationResult) GetRecordCounts(collectionID string) (passed, total int)
- func (r *ValidationResult) HasErrors() bool
- func (r *ValidationResult) SetRecordCount(collectionID string, count int)
- func (r *ValidationResult) SetRecordCounts(collectionID string, passed, total int)
- type ViewDef
- type WebhookDef
- type WhatsAppDef
Constants ¶
const CollectionDefFileName = "definition.yaml"
CollectionDefFileName is the fixed file name for collection definitions inside the SchemaDir directory.
const CollectionsDir = ".collections"
CollectionsDir is the shared-directory layout folder name. When a directory contains a CollectionsDir sub-folder, each non-$-prefixed sub-directory inside it is treated as a separate collection (ID = sub-directory name).
const DefaultMarkdownContentField = "$content"
DefaultMarkdownContentField is the default name of the column that holds the Markdown body when a collection uses `format: markdown` and does not override `record_file.content_field`.
const DefaultViewID = "$default_view"
const IngitdbDir = "$ingitdb"
const SchemaDir = ".collection"
SharedViewsDir is the reserved sub-folder name for named views inside a CollectionsDir/{name}/ directory (new layout).
Variables ¶
This section is empty.
Functions ¶
func ApplyLocaleToRead ¶
ApplyLocaleToRead transforms record data from file representation to application representation. For each column that has a Locale value set (e.g. column "title" with locale "en"), the paired map column (e.g. "titles") is inspected: the locale entry is extracted and exposed as the shortcut column ("title"), and that locale key is removed from the pair map to avoid duplication. The caller receives e.g. {"title": "Work", "titles": {"ru": "Работа"}}.
func ApplyLocaleToWrite ¶
ApplyLocaleToWrite normalises record data before writing to file. For each column that has a Locale value set (e.g. column "title" with locale "en"):
- The shortcut column ("title") is stored as-is in the file.
- If the paired map column ("titles") contains an entry for the primary locale key ("en"), that entry is promoted to the shortcut column and removed from the map, so the value is never duplicated across both fields.
- If the paired map becomes empty after removing the primary locale entry, it is dropped from the result to avoid writing a redundant empty map.
func EncodeListOfRecordsContent ¶
func EncodeListOfRecordsContent(rows []map[string]any, format RecordFormat, columnsOrder []string) ([]byte, error)
EncodeListOfRecordsContent serializes list rows back to the declared format, preserving record (insertion) order. Within each record, keys are emitted in columnsOrder first, then remaining keys alphabetically. JSONL writes one compact JSON object per line; JSON writes a pretty array; YAML writes a top-level sequence. csv and ingr keep their dedicated encoders.
func EncodeMapOfRecordsContent ¶
func EncodeMapOfRecordsContent(data map[string]map[string]any, format RecordFormat, recordsetName string, columnsOrder []string) ([]byte, error)
EncodeMapOfRecordsContent serializes a map of ID-keyed records into the declared format. For yaml/json/toml, the data is written as a top-level mapping (record ID -> field map). For INGR, the data is flattened into a list of records (each gets `$ID` injected as the first column) and written via the ingr-io writer.
recordsetName is used as the INGR header title (typically the collection ID). It is ignored for non-INGR formats. columnsOrder controls the column order in the INGR header; when empty, columns are emitted in alphabetical order with `$ID` first.
func EncodeRecordContentForCollection ¶
func EncodeRecordContentForCollection(value any, colDef *CollectionDef) ([]byte, error)
EncodeRecordContentForCollection serializes record content using the collection's declared format. It is the write-side counterpart of ParseRecordContentForCollection and the only path callers should use when writing records that may be in a format that requires schema access (csv today; possibly others later).
For csv, value MUST be []map[string]any — see encodeCSVForCollection. For the other six formats, value is passed through to marshalForFormat unchanged; callers that want a single-record map[string]any can keep using the schema-agnostic marshalForFormat directly.
func EvaluateFormula ¶
EvaluateFormula evaluates a computed-column formula as a single Starlark expression in a deterministic, side-effect-free sandbox.
Each entry of fields is bound as a top-level variable available to the expression. Supported Go input types are string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64. The result is converted back to a Go-native value: string, bool, int64, or float64. A nil field value or a None result maps to/from Go nil.
The sandbox exposes no network, filesystem, clock, or randomness, and installs no load() loader, so evaluation has zero side effects and is deterministic: identical formula and fields always yield identical output. Evaluation is bounded by maxFormulaSteps. The compiled program is cached, so repeated reads of the same formula do not re-parse it.
func ParseListOfRecordsContent ¶
func ParseListOfRecordsContent(content []byte, format RecordFormat) ([]map[string]any, error)
ParseListOfRecordsContent parses a list-of-records file into ordered row maps. It handles a top-level YAML sequence, a top-level JSON array, and a JSONL stream (one JSON object per non-empty line). Empty content yields no rows. csv and ingr keep their dedicated parsers and are not handled here.
func ParseMapOfRecordsContent ¶
func ParseMapOfRecordsContent(content []byte, format RecordFormat) (map[string]map[string]any, error)
ParseMapOfRecordsContent parses content containing a map of ID-keyed records.
For yaml/json/toml, the file's top-level structure is a mapping from record ID to a per-record field map; we re-shape it into map[string]map[string]any.
For INGR, the file is a list of records where the reserved `$ID` column holds each record's key; we read the list and re-index by `$ID`. Records missing `$ID`, or with duplicate `$ID` values, are rejected as malformed.
func ParseRecordContent ¶
func ParseRecordContent(content []byte, format RecordFormat) (map[string]any, error)
ParseRecordContent parses record content in YAML or JSON format. For markdown-format collections use ParseRecordContentForCollection, which also has access to the column schema and content-field name.
func ParseRecordContentForCollection ¶
func ParseRecordContentForCollection(content []byte, colDef *CollectionDef) (map[string]any, error)
ParseRecordContentForCollection parses record content using the collection's declared format. For YAML and JSON this is equivalent to ParseRecordContent. For markdown records it parses YAML frontmatter, filters to columns declared in the schema, and exposes the body under the configured content_field column name.
func ResolveListRecordKey ¶
func ResolveListRecordKey(row map[string]any, colDef *CollectionDef) (string, bool)
ResolveListRecordKey resolves a list row's record key, in order: the collection's declared primary_key (composite values joined), else a "$id" field, else an "id" field. ok is false when none is available, meaning the list has no usable record key.
func Validate ¶
func Validate() func(*ReadOptions)
func ValidateCollectionID ¶
ValidateCollectionID validates a full collection ID. Allowed characters are alphanumeric, dot, and underscore; ID must start/end with alphanumeric.
func ValidateColumnType ¶
func ValidateColumnType(ct ColumnType) error
Types ¶
type ChangeKind ¶
type ChangeKind string
ChangeKind describes how a file changed between two git refs.
const ( ChangeKindAdded ChangeKind = "added" ChangeKindModified ChangeKind = "modified" ChangeKindDeleted ChangeKind = "deleted" ChangeKindRenamed ChangeKind = "renamed" )
type ChangedFile ¶
type ChangedFile struct {
Kind ChangeKind
Path string // repo-relative path
OldPath string // set only for ChangeKindRenamed
}
ChangedFile is one file that differed between two git refs.
type CollectionDef ¶
type CollectionDef struct {
ID string `json:"-"` // Taken from dir name
DirPath string `yaml:"-" json:"-"`
Titles map[string]string `yaml:"titles,omitempty"`
RecordFile *RecordFileDef `yaml:"record_file"`
DataDir string `yaml:"data_dir,omitempty"`
Columns map[string]*ColumnDef `yaml:"columns"`
ColumnsOrder []string `yaml:"columns_order,omitempty"`
// PrimaryKey lists the column names composing the source primary key,
// in declared order. Persisted by CreateCollection so that
// DescribeCollection can round-trip the real PK column names instead of
// the synthesized "$key" placeholder. Omitted from older
// definition.yaml files; callers should fall back to "$key" when empty.
PrimaryKey []string `yaml:"primary_key,omitempty"`
DefaultView *ViewDef `yaml:"default_view,omitempty"`
// SubCollections are not part of the collection definition file,
// they are stored in the "subcollections" subdirectory as directories,
// each containing their own .collection/definition.yaml.
SubCollections map[string]*CollectionDef `yaml:"-" json:"-"`
// Views are not part of the collection definition file,
// they are stored in the "views" subdirectory.
Views map[string]*ViewDef `yaml:"-" json:"-"`
Readme *CollectionReadmeDef `yaml:"readme,omitempty" json:"readme,omitempty"`
// ConflictResolution overrides the database-level conflict-resolution
// settings for this collection. Nil fields inherit the database default.
ConflictResolution *ConflictResolutionConfig `yaml:"conflict_resolution,omitempty" json:"conflict_resolution,omitempty"`
}
func (*CollectionDef) MarshalYAML ¶
func (c *CollectionDef) MarshalYAML() (interface{}, error)
MarshalYAML emits a CollectionDef as a YAML mapping with deterministic column ordering: columns named in ColumnsOrder appear in that order; any remaining columns follow in alphabetical order. The other fields keep their struct-declaration order.
This makes any yaml.Marshal of a CollectionDef diff-stable across runs and across machines.
func (*CollectionDef) Validate ¶
func (v *CollectionDef) Validate() error
type CollectionReadmeDef ¶
type CollectionReadmeDef struct {
HideColumns bool `yaml:"hide_columns,omitempty" json:"hide_columns,omitempty"`
HideSubcollections bool `yaml:"hide_subcollections,omitempty" json:"hide_subcollections,omitempty"`
HideViews bool `yaml:"hide_views,omitempty" json:"hide_views,omitempty"`
HideTriggers bool `yaml:"hide_triggers,omitempty" json:"hide_triggers,omitempty"`
DataPreview *ViewDef `yaml:"data_preview,omitempty" json:"data_preview,omitempty"`
}
func (*CollectionReadmeDef) Validate ¶
func (r *CollectionReadmeDef) Validate() error
type CollectionsReader ¶
type CollectionsReader interface {
ReadDefinition(dbPath string, opts ...ReadOption) (*Definition, error)
}
CollectionsReader loads the full database definition from disk. The default implementation wraps validator.ReadDefinition.
type ColumnDef ¶
type ColumnDef struct {
Type ColumnType `yaml:"type"`
Title string `yaml:"title,omitempty"`
Titles map[string]string `yaml:"titles,omitempty"`
ValueTitle string `yaml:"valueTitle,omitempty"`
Required bool `yaml:"required,omitempty"`
Length int `yaml:"length,omitempty"`
MinLength int `yaml:"min_length,omitempty"`
MaxLength int `yaml:"max_length,omitempty"`
ForeignKey string `yaml:"foreign_key,omitempty"`
// Locale pairs this column with a map[locale]string column named <this_column_name>+"s".
// For example, column "title" with locale "en" is paired with column "titles".
// When reading, the locale value is extracted from the pair column and exposed as this column.
// When writing, this column is stored as-is in the file; if the pair column contains an entry
// for the primary locale key, that entry is promoted here and removed from the pair column.
Locale string `yaml:"locale,omitempty"`
// Format is an optional, free-form hint about the column's logical content
// type. Well-known values include `markdown`, `html`, `json`, `jsonl`,
// `yaml`, `uri`, `email`, `pdf`. inGitDB does not validate the value;
// tooling may use it to choose a renderer or preview strategy.
Format string `yaml:"format,omitempty"`
// Formula declares this column as a computed (virtual) column. When set,
// it must be a single Starlark expression that references only stored
// (non-computed) sibling fields. Computed columns support only the
// string, int, float, bool, and any declared types.
//
// Note: Starlark's `/` operator is float division, so for an int column
// use integer division `//` (e.g. `total // count`) — `a / b` yields a
// float and fails coercion into an int column unless the result is whole.
Formula string `yaml:"formula,omitempty"`
}
type ColumnDefWithID ¶
type ColumnType ¶
type ColumnType string
const ( ColumnTypeL10N ColumnType = "map[locale]string" ColumnTypeString ColumnType = "string" ColumnTypeInt ColumnType = "int" ColumnTypeFloat ColumnType = "float" ColumnTypeBool ColumnType = "bool" ColumnTypeDate ColumnType = "date" ColumnTypeTime ColumnType = "time" ColumnTypeDateTime ColumnType = "datetime" ColumnTypeAny ColumnType = "any" )
type ConflictResolutionConfig ¶
type ConflictResolutionConfig struct {
RecordMerge *RecordMergeConfig `yaml:"record_merge,omitempty"`
}
ConflictResolutionConfig groups conflict-resolution settings. It is set at the database level (in .ingitdb settings) and may be overridden per collection (in the collection's definition).
type Definition ¶
type Definition struct {
Settings Settings `yaml:"settings,omitempty"`
RuntimeOverrides RuntimeOverrides `yaml:"-"`
Collections map[string]*CollectionDef `yaml:"collections,omitempty"`
Subscribers map[string]*SubscriberDef `yaml:"subscribers,omitempty"`
}
type DiscordDef ¶
type DiscordDef struct {
HandlerBase `yaml:",inline"`
WebhookURL string `yaml:"webhook_url"`
}
DiscordDef represents a Discord webhook subscriber handler
func (*DiscordDef) Validate ¶
func (d *DiscordDef) Validate() error
type EffectiveRecordMerge ¶
EffectiveRecordMerge is the resolved record-merge configuration after the database default and any per-collection override are applied.
func ResolveRecordMerge ¶
func ResolveRecordMerge(def *Definition, col *CollectionDef) EffectiveRecordMerge
ResolveRecordMerge computes the effective record-merge configuration for a collection: app defaults (enabled, not same-record) overlaid by the database-level config, then the per-collection override. Either argument may be nil.
type EmailDef ¶
type EmailDef struct {
HandlerBase `yaml:",inline"`
From string `yaml:"from,omitempty"`
To []string `yaml:"to"`
SMTP string `yaml:"smtp"`
Port int `yaml:"port,omitempty"`
User string `yaml:"user,omitempty"`
Pass string `yaml:"pass,omitempty"`
Subject string `yaml:"subject,omitempty"`
}
EmailDef represents an email subscriber handler via SMTP
type GitHubActionDef ¶
type GitHubActionDef struct {
HandlerBase `yaml:",inline"`
Owner string `yaml:"owner"`
Repo string `yaml:"repo"`
Workflow string `yaml:"workflow"`
Ref string `yaml:"ref"`
Token string `yaml:"token"`
}
GitHubActionDef represents a GitHub Actions workflow_dispatch subscriber handler
func (*GitHubActionDef) Validate ¶
func (d *GitHubActionDef) Validate() error
type GitLabCIDef ¶
type GitLabCIDef struct {
HandlerBase `yaml:",inline"`
ProjectID string `yaml:"project_id"`
Ref string `yaml:"ref"`
Token string `yaml:"token"`
Host string `yaml:"host,omitempty"`
}
GitLabCIDef represents a GitLab CI pipeline trigger subscriber handler
func (*GitLabCIDef) Validate ¶
func (d *GitLabCIDef) Validate() error
type HandlerBase ¶
type HandlerBase struct {
Name string `yaml:"name,omitempty"`
}
HandlerBase contains common fields for all subscriber handlers
type IRecordEntry ¶
func NewMapRecordEntry ¶
func NewMapRecordEntry[TKey comparable](id TKey, data map[string]any) IRecordEntry
type MaterializeResult ¶
type MaterializeResult struct {
FilesCreated int
FilesUpdated int
FilesUnchanged int
FilesDeleted int
Errors []error
}
MaterializeResult summarises the outcome of a materialisation run.
type NtfyDef ¶
type NtfyDef struct {
HandlerBase `yaml:",inline"`
Topic string `yaml:"topic"`
Server string `yaml:"server,omitempty"`
}
NtfyDef represents a ntfy.sh push notification subscriber handler
type ProgressEvent ¶
type ProgressEvent struct {
Kind ProgressKind
TaskName string // "validate" or "materialize"
Scope string // collection or view ID
ItemKey string // record key or output file name
Done int // items completed so far
Total int // total items; 0 = unknown
Err *ValidationError // non-nil only for ProgressKindError
}
ProgressEvent carries one progress update from a running task.
type ProgressKind ¶
type ProgressKind string
ProgressKind describes the type of progress update.
const ( ProgressKindStarted ProgressKind = "started" ProgressKindItemDone ProgressKind = "item_done" ProgressKindSkipped ProgressKind = "skipped" ProgressKindCompleted ProgressKind = "completed" ProgressKindAborted ProgressKind = "aborted" ProgressKindError ProgressKind = "error" )
type RSSDef ¶
type RSSDef struct {
HandlerBase `yaml:",inline"`
Output string `yaml:"output"`
Title string `yaml:"title"`
Link string `yaml:"link"`
Format string `yaml:"format,omitempty"`
}
RSSDef represents an RSS or Atom feed generator subscriber handler
type ReadOption ¶
type ReadOption func(*ReadOptions)
type ReadOptions ¶
type ReadOptions struct {
// contains filtered or unexported fields
}
func NewReadOptions ¶
func NewReadOptions(o ...ReadOption) (opts ReadOptions)
func (*ReadOptions) IsValidationRequired ¶
func (o *ReadOptions) IsValidationRequired() bool
type RecordEntry ¶
RecordEntry is one parsed record.
func (RecordEntry) GetData ¶
func (r RecordEntry) GetData() map[string]any
func (RecordEntry) GetID ¶
func (r RecordEntry) GetID() string
type RecordFileDef ¶
type RecordFileDef struct {
Name string `yaml:"name"`
Format RecordFormat `yaml:"format"`
// RecordType can have next values:
// "map[string]any" - each record in a separate file
// "[]map[string]any" - list of records
// "map[$record_id]map[$field_name]any" - all records in one file; top-level keys are record IDs, second level is field names
RecordType RecordType `yaml:"type"`
// ContentField is the name of the column that maps to the Markdown body
// in a `format: markdown` collection. When empty, the default
// (`DefaultMarkdownContentField`, `$content`) is used.
// It MUST only be set when Format is `markdown`.
ContentField string `yaml:"content_field,omitempty"`
// ExcludeRegex is an optional regular expression applied to the
// basename of each candidate record file. Files whose basename matches
// MUST be excluded from reads, validation, and record counts.
//
// Typical use: a record directory that legitimately contains a
// README.md or .gitkeep alongside `{key}.md` records can set
// `exclude_regex: '^README\.md$'` to keep those auxiliary files from
// being treated as records.
ExcludeRegex string `yaml:"exclude_regex,omitempty"`
}
func (RecordFileDef) GetRecordFileName ¶
func (rfd RecordFileDef) GetRecordFileName(record dal.Record) string
func (RecordFileDef) IsExcluded ¶
func (rfd RecordFileDef) IsExcluded(filename string) bool
IsExcluded reports whether a filename's basename matches the configured `exclude_regex`. Files for which IsExcluded returns true MUST be omitted from reads, validation, and record counts.
When ExcludeRegex is empty, IsExcluded always returns false. When the regex fails to compile (caller skipped Validate()), IsExcluded returns false rather than panicking — Validate() is the right place to surface compile errors.
func (RecordFileDef) RecordsBasePath ¶
func (rfd RecordFileDef) RecordsBasePath() string
RecordsBasePath returns "$records" when record_file.name contains {key}, causing inGitDB to store individual record files under a $records/ subdirectory. This keeps README.md visible at the top of the collection directory on GitHub.com.
func (RecordFileDef) ResolvedContentField ¶
func (rfd RecordFileDef) ResolvedContentField() string
ResolvedContentField returns the configured content_field name when set, otherwise the default (`$content`). Only meaningful when Format is `markdown`.
func (RecordFileDef) Validate ¶
func (rfd RecordFileDef) Validate() error
type RecordFormat ¶
type RecordFormat string
const ( RecordFormatYAML RecordFormat = "yaml" RecordFormatYML RecordFormat = "yml" RecordFormatJSON RecordFormat = "json" RecordFormatMarkdown RecordFormat = "markdown" RecordFormatTOML RecordFormat = "toml" RecordFormatINGR RecordFormat = "ingr" RecordFormatCSV RecordFormat = "csv" RecordFormatJSONL RecordFormat = "jsonl" )
Recognized record file formats. Tooling MUST treat unrecognized values as unsupported. The values are the strings that appear in `record_file.format` in `.collection/definition.yaml`.
type RecordMergeConfig ¶
type RecordMergeConfig struct {
// Enabled turns the default disjoint/non-divergent auto-merge on or off.
// Defaults to true when unset at every scope.
Enabled *bool `yaml:"enabled,omitempty"`
// SameRecord enables opt-in merging of non-contested changes to the same
// record. Defaults to false when unset at every scope.
SameRecord *bool `yaml:"same_record,omitempty"`
}
RecordMergeConfig configures the record-aware auto-merge of data-row conflicts. Both fields are pointers so an explicit `false` at a narrower scope (e.g. a collection) can override an inherited `true` — a nil value means "inherit".
type RecordType ¶
type RecordType string
const ( SingleRecord RecordType = "map[string]any" ListOfRecords RecordType = "[]map[string]any" MapOfRecords RecordType = "map[$record_id]map[$field_name]any" )
type RecordsReader ¶
type RecordsReader interface {
ReadRecords(
ctx context.Context,
dbPath string,
col *CollectionDef,
yield func(IRecordEntry) error,
) error
}
RecordsReader streams records from one collection. Uses a yield callback to avoid goroutine leaks and keep allocation low.
type RuntimeOverrides ¶
type RuntimeOverrides struct {
RecordsDelimiter *int `yaml:"-"`
}
RuntimeOverrides holds values set at runtime (e.g. CLI flags) that take highest priority over schema settings. Not persisted to YAML.
type SMSDef ¶
type SMSDef struct {
HandlerBase `yaml:",inline"`
Provider string `yaml:"provider"`
From string `yaml:"from"`
To string `yaml:"to"`
AccountSID string `yaml:"account_sid,omitempty"`
AuthToken string `yaml:"auth_token"`
APIKey string `yaml:"api_key,omitempty"`
}
SMSDef represents an SMS subscriber handler via Twilio or Vonage
type Scanner ¶
type Scanner interface {
// Scan walks dbPath, validates all records, and rebuilds all views.
Scan(ctx context.Context, dbPath string, def *Definition) error
}
Scanner orchestrates the full pipeline: walk filesystem, invoke Validator and ViewBuilder.
type SearchIndexDef ¶
type SearchIndexDef struct {
HandlerBase `yaml:",inline"`
Provider string `yaml:"provider"`
Index string `yaml:"index"`
AppID string `yaml:"app_id,omitempty"`
APIKey string `yaml:"api_key"`
Host string `yaml:"host,omitempty"`
}
SearchIndexDef represents a search index sync subscriber handler
func (*SearchIndexDef) Validate ¶
func (d *SearchIndexDef) Validate() error
type Settings ¶
type Settings struct {
// RecordsDelimiter controls whether a "#-" line is written after each record in INGR output.
// 0 = use project or app default (app default is 1 = enabled). 1 = enabled. -1 = disabled.
RecordsDelimiter int `yaml:"records_delimiter,omitempty"`
// ConflictResolution holds the database-level conflict-resolution
// defaults (e.g. record-merge), overridable per collection.
ConflictResolution *ConflictResolutionConfig `yaml:"conflict_resolution,omitempty"`
}
Settings holds database-level defaults that apply to all collections.
type SlackDef ¶
type SlackDef struct {
HandlerBase `yaml:",inline"`
WebhookURL string `yaml:"webhook_url"`
}
SlackDef represents a Slack incoming webhook subscriber handler
type SubscriberDef ¶
type SubscriberDef struct {
HandlerBase `yaml:",inline"`
For *SubscriberFor `yaml:"for"`
Webhooks []WebhookDef `yaml:"webhooks,omitempty"`
Emails []EmailDef `yaml:"emails,omitempty"`
Telegrams []TelegramDef `yaml:"telegrams,omitempty"`
WhatsApp []WhatsAppDef `yaml:"whatsapp,omitempty"`
Slacks []SlackDef `yaml:"slacks,omitempty"`
Discords []DiscordDef `yaml:"discords,omitempty"`
GitHubActions []GitHubActionDef `yaml:"github_actions,omitempty"`
GitLabCI []GitLabCIDef `yaml:"gitlab_ci,omitempty"`
Ntfy []NtfyDef `yaml:"ntfy,omitempty"`
SMS []SMSDef `yaml:"sms,omitempty"`
SearchIndexes []SearchIndexDef `yaml:"search_indexes,omitempty"`
RSS []RSSDef `yaml:"rss,omitempty"`
}
SubscriberDef represents a single subscriber configuration block
func (*SubscriberDef) Validate ¶
func (s *SubscriberDef) Validate() error
type SubscriberFor ¶
type SubscriberFor struct {
Paths []string `yaml:"paths,omitempty"`
Events []TriggerEventType `yaml:"events,omitempty"`
}
SubscriberFor represents the selector for when a subscriber group should be triggered
func (*SubscriberFor) Validate ¶
func (s *SubscriberFor) Validate() error
type TelegramDef ¶
type TelegramDef struct {
HandlerBase `yaml:",inline"`
Token string `yaml:"token"`
ChatID string `yaml:"chat_id"`
}
TelegramDef represents a Telegram subscriber handler
func (*TelegramDef) Validate ¶
func (d *TelegramDef) Validate() error
type TriggerDef ¶
type TriggerDef struct {
On []TriggerEventType `yaml:"on"`
Jobs map[string]*TriggerJobDef `yaml:"jobs"`
}
TriggerDef is the schema for a trigger workflow file (.collection/trigger_<name>.yaml). Modelled after GitHub Actions workflow syntax.
type TriggerEventType ¶
type TriggerEventType string
TriggerEventType is the lifecycle event that fires a trigger.
const ( TriggerEventCreated TriggerEventType = "created" TriggerEventUpdated TriggerEventType = "updated" TriggerEventDeleted TriggerEventType = "deleted" )
type TriggerJobDef ¶
type TriggerJobDef struct {
RunsOn string `yaml:"runs-on"`
Steps []TriggerStepDef `yaml:"steps"`
}
TriggerJobDef is one job inside a trigger workflow. RunsOn must be "." (run in the same environment as ingitdb itself).
type TriggerStepDef ¶
type TriggerStepDef struct {
Run string `yaml:"run"`
}
TriggerStepDef is a single shell step within a trigger job.
type ValidationError ¶
type ValidationError struct {
Severity Severity
CollectionID string // e.g. "todo.tasks"
FilePath string // absolute path to offending file
RecordKey string // empty for list/map files where key is unknown
FieldName string // set for field-level errors
Message string
Err error // wrapped cause
}
ValidationError is one finding from data validation. All location fields (CollectionID…FieldName) are optional. Implements error.
func (ValidationError) Error ¶
func (v ValidationError) Error() string
Error implements the error interface.
type ValidationResult ¶
type ValidationResult struct {
// contains filtered or unexported fields
}
ValidationResult aggregates findings; mutex-protected for goroutine safety.
func (*ValidationResult) Append ¶
func (r *ValidationResult) Append(e ValidationError)
Append adds a finding to the result.
func (*ValidationResult) ErrorCount ¶
func (r *ValidationResult) ErrorCount() int
ErrorCount returns the total number of recorded findings.
func (*ValidationResult) Errors ¶
func (r *ValidationResult) Errors() []ValidationError
Errors returns a snapshot copy of all findings.
func (*ValidationResult) Filter ¶
func (r *ValidationResult) Filter(fn func(ValidationError) bool) []ValidationError
Filter returns findings that match the given predicate.
func (*ValidationResult) GetRecordCount ¶
func (r *ValidationResult) GetRecordCount(collectionID string) int
GetRecordCount returns the number of records validated for a collection.
func (*ValidationResult) GetRecordCounts ¶
func (r *ValidationResult) GetRecordCounts(collectionID string) (passed, total int)
GetRecordCounts returns the passed and total record counts for a collection.
func (*ValidationResult) HasErrors ¶
func (r *ValidationResult) HasErrors() bool
HasErrors reports whether any findings have been recorded.
func (*ValidationResult) SetRecordCount ¶
func (r *ValidationResult) SetRecordCount(collectionID string, count int)
SetRecordCount sets the number of records validated for a collection.
func (*ValidationResult) SetRecordCounts ¶
func (r *ValidationResult) SetRecordCounts(collectionID string, passed, total int)
SetRecordCounts sets the passed and total record counts for a collection.
type ViewDef ¶
type ViewDef struct {
ID string `yaml:"-"`
Titles map[string]string `yaml:"titles,omitempty"`
OrderBy string `yaml:"order_by,omitempty"`
// Formats TODO: Needs definition
Formats []string `yaml:"formats,omitempty"`
Columns []string `yaml:"columns,omitempty"`
// How many records to include; 0 means all
Top int `yaml:"top,omitempty"`
// Where holds filtering condition
Where string `yaml:"where,omitempty"`
// Template path relative to the collection directory.
/*
Build in templates:
- md-table - renders a Markdown table
- md-list - renders a Markdown list
- JSON - renders JSON
- YAML - renders YAML
*/
Template string `yaml:"template,omitempty"`
// Output file name relative to the collection directory.
FileName string `yaml:"file_name,omitempty"`
// RecordsVarName provides a custom Template variable name for the records slice. The default is "records".
RecordsVarName string `yaml:"records_var_name,omitempty"`
Format string `yaml:"format,omitempty"`
MaxBatchSize int `yaml:"max_batch_size,omitempty"`
IsDefault bool `yaml:"-" json:"-"`
// IncludeHash controls whether a sha256 hash line is appended to INGR footer.
IncludeHash bool `yaml:"include_hash,omitempty"`
// RecordsDelimiter controls whether a "#-" line is written after each record in INGR output.
// 0 = use project or app default (app default is 1 = enabled). 1 = enabled. -1 = disabled.
RecordsDelimiter int `yaml:"records_delimiter,omitempty"`
}
type WebhookDef ¶
type WebhookDef struct {
HandlerBase `yaml:",inline"`
URL string `yaml:"url"`
Method string `yaml:"method,omitempty"`
Headers map[string]string `yaml:"headers,omitempty"`
}
WebhookDef represents a webhook subscriber handler
func (*WebhookDef) Validate ¶
func (d *WebhookDef) Validate() error
type WhatsAppDef ¶
type WhatsAppDef struct {
HandlerBase `yaml:",inline"`
From string `yaml:"from"`
To string `yaml:"to"`
AccountSID string `yaml:"account_sid"`
AuthToken string `yaml:"auth_token"`
}
WhatsAppDef represents a WhatsApp Business API subscriber handler
func (*WhatsAppDef) Validate ¶
func (d *WhatsAppDef) Validate() error
Source Files
¶
- changed_file.go
- collection_def.go
- collection_id.go
- collection_marshal.go
- collections_reader.go
- column_def.go
- column_formula.go
- column_formula_eval.go
- column_type.go
- conflict_resolution.go
- constants.go
- csv.go
- definition.go
- list_records.go
- locale.go
- materialize_result.go
- parse.go
- progress_event.go
- read_options.go
- record_entry.go
- record_file_def.go
- records_reader.go
- scanner.go
- seams_parse.go
- subscriber_def.go
- trigger_def.go
- validation_error.go
- view_def.go
Directories
¶
| Path | Synopsis |
|---|---|
|
ingitdb
module
|
|
|
internal
|
|
|
testutil
Package testutil provides shared test helpers for ingitdb-go tests.
|
Package testutil provides shared test helpers for ingitdb-go tests. |
|
Package markdown parses and serializes inGitDB Markdown record files — YAML frontmatter delimited by "---" lines followed by a body.
|
Package markdown parses and serializes inGitDB Markdown record files — YAML frontmatter delimited by "---" lines followed by a body. |
|
specscore: feature/cli/resolve/auto-resolve/record-merge
|
specscore: feature/cli/resolve/auto-resolve/record-merge |