1
1
import 'package:logging/logging.dart' ;
2
2
import 'package:postgres/postgres.dart' ;
3
+ import 'package:ht_shared/ht_shared.dart' ;
3
4
4
5
/// {@template database_seeding_service}
5
6
/// A service responsible for initializing the database schema and seeding it
@@ -20,5 +21,120 @@ class DatabaseSeedingService {
20
21
final Connection _connection;
21
22
final Logger _log;
22
23
23
- // Methods for table creation and data seeding will be added here.
24
+ /// Creates all necessary tables in the database if they do not already exist.
25
+ ///
26
+ /// This method executes a series of `CREATE TABLE IF NOT EXISTS` statements
27
+ /// within a single transaction to ensure atomicity.
28
+ Future <void > createTables () async {
29
+ _log.info ('Starting database schema creation...' );
30
+ try {
31
+ await _connection.transaction ((ctx) async {
32
+ _log.fine ('Creating "users" table...' );
33
+ await ctx.execute ('''
34
+ CREATE TABLE IF NOT EXISTS users (
35
+ id TEXT PRIMARY KEY,
36
+ email TEXT UNIQUE,
37
+ roles JSONB NOT NULL,
38
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
39
+ last_engagement_shown_at TIMESTAMPTZ
40
+ );
41
+ ''' );
42
+
43
+ _log.fine ('Creating "app_config" table...' );
44
+ await ctx.execute ('''
45
+ CREATE TABLE IF NOT EXISTS app_config (
46
+ id TEXT PRIMARY KEY,
47
+ user_preference_limits JSONB NOT NULL,
48
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
49
+ updated_at TIMESTAMPTZ
50
+ );
51
+ ''' );
52
+
53
+ _log.fine ('Creating "categories" table...' );
54
+ await ctx.execute ('''
55
+ CREATE TABLE IF NOT EXISTS categories (
56
+ id TEXT PRIMARY KEY,
57
+ name TEXT NOT NULL UNIQUE,
58
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
59
+ updated_at TIMESTAMPTZ
60
+ );
61
+ ''' );
62
+
63
+ _log.fine ('Creating "sources" table...' );
64
+ await ctx.execute ('''
65
+ CREATE TABLE IF NOT EXISTS sources (
66
+ id TEXT PRIMARY KEY,
67
+ name TEXT NOT NULL UNIQUE,
68
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
69
+ updated_at TIMESTAMPTZ
70
+ );
71
+ ''' );
72
+
73
+ _log.fine ('Creating "countries" table...' );
74
+ await ctx.execute ('''
75
+ CREATE TABLE IF NOT EXISTS countries (
76
+ id TEXT PRIMARY KEY,
77
+ name TEXT NOT NULL UNIQUE,
78
+ code TEXT NOT NULL UNIQUE,
79
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
80
+ updated_at TIMESTAMPTZ
81
+ );
82
+ ''' );
83
+
84
+ _log.fine ('Creating "headlines" table...' );
85
+ await ctx.execute ('''
86
+ CREATE TABLE IF NOT EXISTS headlines (
87
+ id TEXT PRIMARY KEY,
88
+ title TEXT NOT NULL,
89
+ source_id TEXT NOT NULL,
90
+ category_id TEXT NOT NULL,
91
+ image_url TEXT NOT NULL,
92
+ url TEXT NOT NULL,
93
+ published_at TIMESTAMPTZ NOT NULL,
94
+ description TEXT,
95
+ content TEXT,
96
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
97
+ updated_at TIMESTAMPTZ
98
+ );
99
+ ''' );
100
+
101
+ _log.fine ('Creating "user_app_settings" table...' );
102
+ await ctx.execute ('''
103
+ CREATE TABLE IF NOT EXISTS user_app_settings (
104
+ id TEXT PRIMARY KEY,
105
+ user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
106
+ display_settings JSONB NOT NULL,
107
+ language JSONB NOT NULL,
108
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
109
+ updated_at TIMESTAMPTZ
110
+ );
111
+ ''' );
112
+
113
+ _log.fine ('Creating "user_content_preferences" table...' );
114
+ await ctx.execute ('''
115
+ CREATE TABLE IF NOT EXISTS user_content_preferences (
116
+ id TEXT PRIMARY KEY,
117
+ user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
118
+ followed_categories JSONB NOT NULL,
119
+ followed_sources JSONB NOT NULL,
120
+ followed_countries JSONB NOT NULL,
121
+ saved_headlines JSONB NOT NULL,
122
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
123
+ updated_at TIMESTAMPTZ
124
+ );
125
+ ''' );
126
+ });
127
+ _log.info ('Database schema creation completed successfully.' );
128
+ } on Object catch (e, st) {
129
+ _log.severe (
130
+ 'An error occurred during database schema creation.' ,
131
+ e,
132
+ st,
133
+ );
134
+ // Propagate as a standard exception for the server to handle.
135
+ throw OperationFailedException (
136
+ 'Failed to initialize database schema: $e ' ,
137
+ );
138
+ }
139
+ }
24
140
}
0 commit comments