66 "encoding/json"
77 "io"
88 "os"
9+ "strings"
910
1011 _ "github.com/mattn/go-sqlite3"
1112 "github.com/pkg/errors"
@@ -47,12 +48,12 @@ func (s *Sqlite) GetDevProject(ctx context.Context, key string) (*model.Project,
4748 var flagStateData string
4849
4950 row := s .database .QueryRowContext (ctx , `
50- SELECT key, source_environment_key, context, last_sync_time, flag_state
51+ SELECT key, source_environment_key, client_side_id, context, last_sync_time, flag_state
5152 FROM projects
5253 WHERE key = ?
5354 ` , key )
5455
55- if err := row .Scan (& project .Key , & project .SourceEnvironmentKey , & contextData , & project .LastSyncTime , & flagStateData ); err != nil {
56+ if err := row .Scan (& project .Key , & project .SourceEnvironmentKey , & project . ClientSideId , & contextData , & project .LastSyncTime , & flagStateData ); err != nil {
5657 if errors .Is (err , sql .ErrNoRows ) {
5758 return nil , model .NewErrNotFound ("project" , key )
5859 }
@@ -72,6 +73,37 @@ func (s *Sqlite) GetDevProject(ctx context.Context, key string) (*model.Project,
7273 return & project , nil
7374}
7475
76+ func (s * Sqlite ) GetDevProjectByClientSideId (ctx context.Context , clientSideId string ) (* model.Project , error ) {
77+ var project model.Project
78+ var contextData string
79+ var flagStateData string
80+
81+ row := s .database .QueryRowContext (ctx , `
82+ SELECT key, source_environment_key, client_side_id, context, last_sync_time, flag_state
83+ FROM projects
84+ WHERE client_side_id = ? AND client_side_id IS NOT NULL
85+ ` , clientSideId )
86+
87+ if err := row .Scan (& project .Key , & project .SourceEnvironmentKey , & project .ClientSideId , & contextData , & project .LastSyncTime , & flagStateData ); err != nil {
88+ if errors .Is (err , sql .ErrNoRows ) {
89+ return nil , model .NewErrNotFound ("project" , clientSideId )
90+ }
91+ return nil , err
92+ }
93+
94+ // Parse the context JSON string
95+ if err := json .Unmarshal ([]byte (contextData ), & project .Context ); err != nil {
96+ return nil , errors .Wrap (err , "unable to unmarshal context data" )
97+ }
98+
99+ // Parse the flag state JSON string
100+ if err := json .Unmarshal ([]byte (flagStateData ), & project .AllFlagsState ); err != nil {
101+ return nil , errors .Wrap (err , "unable to unmarshal flag state data" )
102+ }
103+
104+ return & project , nil
105+ }
106+
75107func (s * Sqlite ) UpdateProject (ctx context.Context , project model.Project ) (bool , error ) {
76108 flagsStateJson , err := json .Marshal (project .AllFlagsState )
77109 if err != nil {
@@ -89,9 +121,9 @@ func (s *Sqlite) UpdateProject(ctx context.Context, project model.Project) (bool
89121 }()
90122 result , err := tx .ExecContext (ctx , `
91123 UPDATE projects
92- SET flag_state = ?, last_sync_time = ?, context=?, source_environment_key=?
124+ SET flag_state = ?, last_sync_time = ?, context=?, source_environment_key=?, client_side_id=?
93125 WHERE key = ?;
94- ` , flagsStateJson , project .LastSyncTime , project .Context .JSONString (), project .SourceEnvironmentKey , project .Key )
126+ ` , flagsStateJson , project .LastSyncTime , project .Context .JSONString (), project .SourceEnvironmentKey , project .ClientSideId , project . Key )
95127 if err != nil {
96128 return false , errors .Wrap (err , "unable to execute update project" )
97129 }
@@ -200,11 +232,12 @@ SELECT 1 FROM projects WHERE key = ?
200232 return
201233 }
202234 _ , err = tx .Exec (`
203- INSERT INTO projects (key, source_environment_key, context, last_sync_time, flag_state)
204- VALUES (?, ?, ?, ?, ?)
235+ INSERT INTO projects (key, source_environment_key, client_side_id, context, last_sync_time, flag_state)
236+ VALUES (?, ?, ?, ?, ?, ? )
205237` ,
206238 project .Key ,
207239 project .SourceEnvironmentKey ,
240+ project .ClientSideId ,
208241 project .Context .JSONString (),
209242 project .LastSyncTime ,
210243 string (flagsStateJson ),
@@ -429,6 +462,11 @@ var validationQueries = []string{
429462 "SELECT COUNT(1) from available_variations" ,
430463}
431464
465+ func isColumnExistsError (err error ) bool {
466+ return err != nil && (strings .Contains (err .Error (), "duplicate column name: client_side_id" ) ||
467+ strings .Contains (err .Error (), "table projects has no column named client_side_id" ))
468+ }
469+
432470func (s * Sqlite ) runMigrations (ctx context.Context ) error {
433471 tx , err := s .database .BeginTx (ctx , nil )
434472 if err != nil {
@@ -443,6 +481,7 @@ func (s *Sqlite) runMigrations(ctx context.Context) error {
443481 CREATE TABLE IF NOT EXISTS projects (
444482 key text PRIMARY KEY,
445483 source_environment_key text NOT NULL,
484+ client_side_id text,
446485 context text NOT NULL,
447486 last_sync_time timestamp NOT NULL,
448487 flag_state TEXT NOT NULL
@@ -479,5 +518,14 @@ func (s *Sqlite) runMigrations(ctx context.Context) error {
479518 return err
480519 }
481520
521+ // Add client_side_id column to existing projects table if it doesn't exist
522+ _ , err = tx .Exec (`ALTER TABLE projects ADD COLUMN client_side_id text` )
523+ if err != nil {
524+ // Ignore error if column already exists
525+ if ! isColumnExistsError (err ) {
526+ return err
527+ }
528+ }
529+
482530 return tx .Commit ()
483531}
0 commit comments