159 lines
4.5 KiB
Go
159 lines
4.5 KiB
Go
package sqlite
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
|
|
"inbox/internal/domain/skill"
|
|
)
|
|
|
|
func (s *Store) UpsertSkill(ctx context.Context, value skill.Definition, changedBy string) (skill.Definition, error) {
|
|
if err := value.Validate(); err != nil {
|
|
return skill.Definition{}, err
|
|
}
|
|
return upsertVersionedConfig(ctx, s, value, changedBy, versionedConfigUpsertSpec[skill.Definition]{
|
|
entityName: "skill",
|
|
idKind: "skill",
|
|
loadTx: func(ctx context.Context, tx *sql.Tx) (skill.Definition, error) {
|
|
return getSkillByKeyTx(ctx, tx, value.SkillKey)
|
|
},
|
|
current: func(item skill.Definition) versionedConfigCurrent {
|
|
return versionedConfigCurrent{
|
|
ID: item.ID,
|
|
Version: item.Version,
|
|
CreatedAt: item.CreatedAt,
|
|
}
|
|
},
|
|
applyMetadata: func(item *skill.Definition, meta versionedConfigMetadata) {
|
|
item.ID = meta.ID
|
|
item.Version = meta.Version
|
|
item.CreatedAt = meta.CreatedAt
|
|
item.UpdatedAt = meta.UpdatedAt
|
|
},
|
|
writeTx: func(ctx context.Context, tx *sql.Tx, item skill.Definition) error {
|
|
_, err := tx.ExecContext(ctx, `
|
|
INSERT INTO skills(id, skill_key, name, description, source_type, content_markdown, status, version, created_at, updated_at)
|
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(id) DO UPDATE SET
|
|
name = excluded.name,
|
|
description = excluded.description,
|
|
source_type = excluded.source_type,
|
|
content_markdown = excluded.content_markdown,
|
|
status = excluded.status,
|
|
version = excluded.version,
|
|
updated_at = excluded.updated_at
|
|
`,
|
|
item.ID,
|
|
item.SkillKey,
|
|
item.Name,
|
|
item.Description,
|
|
item.SourceType,
|
|
item.ContentMarkdown,
|
|
item.Status,
|
|
item.Version,
|
|
item.CreatedAt,
|
|
item.UpdatedAt,
|
|
)
|
|
return err
|
|
},
|
|
})
|
|
}
|
|
|
|
func (s *Store) ListSkillsByIDs(ctx context.Context, ids []string) (map[string]skill.Definition, error) {
|
|
ids = slices.Clone(ids)
|
|
if len(ids) == 0 {
|
|
return map[string]skill.Definition{}, nil
|
|
}
|
|
placeholders := make([]string, len(ids))
|
|
args := make([]any, len(ids))
|
|
for i, id := range ids {
|
|
placeholders[i] = "?"
|
|
args[i] = id
|
|
}
|
|
query := fmt.Sprintf(`
|
|
SELECT id, skill_key, name, description, source_type, content_markdown, status, version, created_at, updated_at
|
|
FROM skills
|
|
WHERE id IN (%s)
|
|
`, strings.Join(placeholders, ", "))
|
|
rows, err := s.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list skills by ids: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
out := make(map[string]skill.Definition, len(ids))
|
|
for rows.Next() {
|
|
item, err := scanSkill(rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out[item.ID] = item
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("iterate skills: %w", err)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (s *Store) GetSkillByKey(ctx context.Context, skillKey string) (skill.Definition, error) {
|
|
row := s.db.QueryRowContext(ctx, `
|
|
SELECT id, skill_key, name, description, source_type, content_markdown, status, version, created_at, updated_at
|
|
FROM skills
|
|
WHERE skill_key = ?
|
|
`, skillKey)
|
|
return scanSkill(row)
|
|
}
|
|
|
|
func (s *Store) ListSkills(ctx context.Context) ([]skill.Definition, error) {
|
|
rows, err := s.db.QueryContext(ctx, `
|
|
SELECT id, skill_key, name, description, source_type, content_markdown, status, version, created_at, updated_at
|
|
FROM skills
|
|
ORDER BY name, skill_key
|
|
`)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list skills: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var out []skill.Definition
|
|
for rows.Next() {
|
|
item, err := scanSkill(rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, item)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("iterate skills: %w", err)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (s *Store) DeleteSkillByKey(ctx context.Context, skillKey string) error {
|
|
result, err := s.db.ExecContext(ctx, `DELETE FROM skills WHERE skill_key = ?`, skillKey)
|
|
if err != nil {
|
|
return fmt.Errorf("delete skill: %w", err)
|
|
}
|
|
return ensureAffected(result, sql.ErrNoRows)
|
|
}
|
|
|
|
func getSkillByKeyTx(ctx context.Context, tx *sql.Tx, skillKey string) (skill.Definition, error) {
|
|
row := tx.QueryRowContext(ctx, `
|
|
SELECT id, skill_key, name, description, source_type, content_markdown, status, version, created_at, updated_at
|
|
FROM skills
|
|
WHERE skill_key = ?
|
|
`, skillKey)
|
|
return scanSkill(row)
|
|
}
|
|
|
|
func scanSkill(s scanner) (skill.Definition, error) {
|
|
var item skill.Definition
|
|
if err := s.Scan(&item.ID, &item.SkillKey, &item.Name, &item.Description, &item.SourceType, &item.ContentMarkdown, &item.Status, &item.Version, &item.CreatedAt, &item.UpdatedAt); err != nil {
|
|
return skill.Definition{}, err
|
|
}
|
|
return item, nil
|
|
}
|