repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / apps / pgs / db
Eric Bower  ·  2026-03-05

memory.go

  1package pgsdb
  2
  3import (
  4	"fmt"
  5	"log/slog"
  6	"time"
  7
  8	"github.com/google/uuid"
  9	"github.com/picosh/pico/pkg/db"
 10	"github.com/picosh/pico/pkg/shared"
 11)
 12
 13type MemoryDB struct {
 14	Logger      *slog.Logger
 15	Users       []*db.User
 16	Projects    []*db.Project
 17	Pubkeys     []*db.PublicKey
 18	Feature     *db.FeatureFlag
 19	FormEntries []*db.FormEntry
 20}
 21
 22var _ PgsDB = (*MemoryDB)(nil)
 23
 24func NewDBMemory(logger *slog.Logger) *MemoryDB {
 25	d := &MemoryDB{
 26		Logger: logger,
 27	}
 28	d.Logger.Info("connecting to our in-memory database. All data created during runtime will be lost on exit.")
 29	return d
 30}
 31
 32func (me *MemoryDB) SetupTestData() {
 33	user := &db.User{
 34		ID:   uuid.NewString(),
 35		Name: "testusr",
 36	}
 37	me.Users = append(me.Users, user)
 38	feature := db.NewFeatureFlag(
 39		user.ID,
 40		"plus",
 41		uint64(25*shared.MB),
 42		int64(10*shared.MB),
 43		int64(5*shared.KB),
 44	)
 45	expiresAt := time.Now().Add(time.Hour * 24)
 46	feature.ExpiresAt = &expiresAt
 47	me.Feature = feature
 48}
 49
 50var errNotImpl = fmt.Errorf("not implemented")
 51
 52func (me *MemoryDB) FindUsers() ([]*db.User, error) {
 53	users := []*db.User{}
 54	return users, errNotImpl
 55}
 56
 57func (me *MemoryDB) FindUserByPubkey(key string) (*db.User, error) {
 58	for _, pk := range me.Pubkeys {
 59		if pk.Key == key {
 60			return me.FindUser(pk.UserID)
 61		}
 62	}
 63	return nil, fmt.Errorf("user not found")
 64}
 65
 66func (me *MemoryDB) FindUser(userID string) (*db.User, error) {
 67	for _, user := range me.Users {
 68		if user.ID == userID {
 69			return user, nil
 70		}
 71	}
 72	return nil, fmt.Errorf("user not found")
 73}
 74
 75func (me *MemoryDB) FindUserByName(name string) (*db.User, error) {
 76	for _, user := range me.Users {
 77		if user.Name == name {
 78			return user, nil
 79		}
 80	}
 81	return nil, fmt.Errorf("user not found")
 82}
 83
 84func (me *MemoryDB) FindFeature(userID, name string) (*db.FeatureFlag, error) {
 85	return me.Feature, nil
 86}
 87
 88func (me *MemoryDB) Close() error {
 89	return nil
 90}
 91
 92func (me *MemoryDB) FindTotalSizeForUser(userID string) (int, error) {
 93	return 0, errNotImpl
 94}
 95
 96func (me *MemoryDB) InsertProject(userID, name, projectDir string) (string, error) {
 97	id := uuid.NewString()
 98	now := time.Now()
 99	me.Projects = append(me.Projects, &db.Project{
100		ID:         id,
101		UserID:     userID,
102		Name:       name,
103		ProjectDir: projectDir,
104		CreatedAt:  &now,
105		UpdatedAt:  &now,
106	})
107	return id, nil
108}
109
110func (me *MemoryDB) UpdateProject(userID, name string) error {
111	project, err := me.FindProjectByName(userID, name)
112	if err != nil {
113		return err
114	}
115
116	now := time.Now()
117	project.UpdatedAt = &now
118
119	return nil
120}
121
122func (me *MemoryDB) UpsertProject(userID, projectName, projectDir string) (*db.Project, error) {
123	project, err := me.FindProjectByName(userID, projectName)
124	if err == nil {
125		// this just updates the `createdAt` timestamp, useful for book-keeping
126		err = me.UpdateProject(userID, projectName)
127		if err != nil {
128			me.Logger.Error("could not update project", "err", err)
129			return nil, err
130		}
131		return project, nil
132	}
133
134	_, err = me.InsertProject(userID, projectName, projectName)
135	if err != nil {
136		me.Logger.Error("could not create project", "err", err)
137		return nil, err
138	}
139	return me.FindProjectByName(userID, projectName)
140}
141
142func (me *MemoryDB) LinkToProject(userID, projectID, projectDir string, commit bool) error {
143	return errNotImpl
144}
145
146func (me *MemoryDB) RemoveProject(projectID string) error {
147	return errNotImpl
148}
149
150func (me *MemoryDB) FindProjectByName(userID, name string) (*db.Project, error) {
151	for _, project := range me.Projects {
152		if project.UserID != userID {
153			continue
154		}
155
156		if project.Name != name {
157			continue
158		}
159
160		return project, nil
161	}
162	return nil, fmt.Errorf("project not found by name %s", name)
163}
164
165func (me *MemoryDB) FindProjectLinks(userID, name string) ([]*db.Project, error) {
166	return []*db.Project{}, errNotImpl
167}
168
169func (me *MemoryDB) FindProjectsByPrefix(userID, prefix string) ([]*db.Project, error) {
170	return []*db.Project{}, errNotImpl
171}
172
173func (me *MemoryDB) FindProjectsByUser(userID string) ([]*db.Project, error) {
174	pjs := []*db.Project{}
175	for _, project := range me.Projects {
176		if project.UserID != userID {
177			continue
178		}
179		pjs = append(pjs, project)
180	}
181	return pjs, nil
182}
183
184func (me *MemoryDB) FindProjects(userID string) ([]*db.Project, error) {
185	return []*db.Project{}, errNotImpl
186}
187
188func (me *MemoryDB) UpdateProjectAcl(userID, name string, acl db.ProjectAcl) error {
189	return errNotImpl
190}
191
192func (me *MemoryDB) RegisterAdmin(username, pubkey, pubkeyName string) error {
193	return errNotImpl
194}
195
196func (me *MemoryDB) InsertAccessLog(*db.AccessLog) error {
197	return errNotImpl
198}
199
200func (me *MemoryDB) InsertFormEntry(userID, name string, data map[string]interface{}) error {
201	id := uuid.NewString()
202	now := time.Now()
203	entry := &db.FormEntry{
204		ID:        id,
205		UserID:    userID,
206		Name:      name,
207		Data:      data,
208		CreatedAt: &now,
209	}
210	me.FormEntries = append(me.FormEntries, entry)
211	return nil
212}
213
214func (me *MemoryDB) FindFormEntriesByUserAndName(userID, name string) ([]*db.FormEntry, error) {
215	entries := []*db.FormEntry{}
216	for _, entry := range me.FormEntries {
217		if entry.UserID == userID && entry.Name == name {
218			entries = append(entries, entry)
219		}
220	}
221	return entries, nil
222}
223
224func (me *MemoryDB) FindFormNamesByUser(userID string) ([]string, error) {
225	names := make(map[string]bool)
226	for _, entry := range me.FormEntries {
227		if entry.UserID == userID {
228			names[entry.Name] = true
229		}
230	}
231	result := []string{}
232	for name := range names {
233		result = append(result, name)
234	}
235	return result, nil
236}
237
238func (me *MemoryDB) RemoveFormEntriesByUserAndName(userID, name string) error {
239	filtered := []*db.FormEntry{}
240	for _, entry := range me.FormEntries {
241		if entry.UserID != userID || entry.Name != name {
242			filtered = append(filtered, entry)
243		}
244	}
245	me.FormEntries = filtered
246	return nil
247}