Skip to content

Commit 8c2c579

Browse files
committed
feat(data): implement table creation in DatabaseSeedingService
Adds the `createTables` method to the `DatabaseSeedingService`. This method defines and executes the SQL `CREATE TABLE IF NOT EXISTS` statements for all application models within a single transaction. The schema includes primary keys, foreign keys with cascading deletes, and appropriate data types like `JSONB` and `TIMESTAMPTZ`.
1 parent 8013166 commit 8c2c579

File tree

1 file changed

+117
-1
lines changed

1 file changed

+117
-1
lines changed

lib/src/services/database_seeding_service.dart

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:logging/logging.dart';
22
import 'package:postgres/postgres.dart';
3+
import 'package:ht_shared/ht_shared.dart';
34

45
/// {@template database_seeding_service}
56
/// A service responsible for initializing the database schema and seeding it
@@ -20,5 +21,120 @@ class DatabaseSeedingService {
2021
final Connection _connection;
2122
final Logger _log;
2223

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+
}
24140
}

0 commit comments

Comments
 (0)