+2
-1
.dockerignore
+2
-1
.dockerignore
+3
-1
.env.example
+3
-1
.env.example
+2
-1
.gitignore
+2
-1
.gitignore
+15
Cargo.lock
+15
Cargo.lock
···
4968
4968
]
4969
4969
4970
4970
[[package]]
4971
+
name = "rocksky-pgpull"
4972
+
version = "0.1.0"
4973
+
dependencies = [
4974
+
"anyhow",
4975
+
"chrono",
4976
+
"owo-colors",
4977
+
"serde",
4978
+
"serde_json",
4979
+
"sqlx",
4980
+
"tokio",
4981
+
"tracing",
4982
+
]
4983
+
4984
+
[[package]]
4971
4985
name = "rocksky-playlists"
4972
4986
version = "0.1.0"
4973
4987
dependencies = [
···
5126
5140
"rocksky-dropbox",
5127
5141
"rocksky-googledrive",
5128
5142
"rocksky-jetstream",
5143
+
"rocksky-pgpull",
5129
5144
"rocksky-playlists",
5130
5145
"rocksky-scrobbler",
5131
5146
"rocksky-spotify",
+1
-1
apps/api/drizzle.config.ts
+1
-1
apps/api/drizzle.config.ts
+19
-20
apps/api/drizzle/0000_quiet_mister_sinister.sql
apps/api/drizzle/0000_left_swordsman.sql
+19
-20
apps/api/drizzle/0000_quiet_mister_sinister.sql
apps/api/drizzle/0000_left_swordsman.sql
···
4
4
"track_id" text NOT NULL,
5
5
"xata_createdat" timestamp DEFAULT now() NOT NULL,
6
6
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
7
-
"xata_version" integer NOT NULL
7
+
"xata_version" integer
8
8
);
9
9
--> statement-breakpoint
10
10
CREATE TABLE "albums" (
···
50
50
"album_id" text NOT NULL,
51
51
"xata_createdat" timestamp DEFAULT now() NOT NULL,
52
52
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
53
-
"xata_version" integer NOT NULL
53
+
"xata_version" integer
54
54
);
55
55
--> statement-breakpoint
56
56
CREATE TABLE "artist_tracks" (
···
59
59
"track_id" text NOT NULL,
60
60
"xata_createdat" timestamp DEFAULT now() NOT NULL,
61
61
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
62
-
"xata_version" integer NOT NULL
62
+
"xata_version" integer
63
63
);
64
64
--> statement-breakpoint
65
65
CREATE TABLE "artists" (
···
76
76
"spotify_link" text,
77
77
"tidal_link" text,
78
78
"youtube_link" text,
79
+
"genres" text[],
79
80
"xata_createdat" timestamp DEFAULT now() NOT NULL,
80
81
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
81
82
"xata_version" integer,
···
88
89
"email" text NOT NULL,
89
90
"is_beta_user" boolean DEFAULT false NOT NULL,
90
91
"user_id" text NOT NULL,
91
-
"xata_version" text NOT NULL,
92
+
"xata_version" text,
92
93
"xata_createdat" timestamp DEFAULT now() NOT NULL,
93
94
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
94
95
CONSTRAINT "dropbox_accounts_email_unique" UNIQUE("email")
···
101
102
"parent_id" text,
102
103
"dropbox_id" text NOT NULL,
103
104
"file_id" text NOT NULL,
104
-
"xata_version" text NOT NULL,
105
+
"xata_version" text,
105
106
"xata_createdat" timestamp DEFAULT now() NOT NULL,
106
107
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
107
108
CONSTRAINT "dropbox_directories_file_id_unique" UNIQUE("file_id")
···
115
116
"track_id" text NOT NULL,
116
117
"directory_id" text,
117
118
"file_id" text NOT NULL,
118
-
"xata_version" text NOT NULL,
119
+
"xata_version" text,
119
120
"xata_createdat" timestamp DEFAULT now() NOT NULL,
120
121
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
121
122
CONSTRAINT "dropbox_paths_file_id_unique" UNIQUE("file_id")
···
132
133
"xata_id" text PRIMARY KEY DEFAULT xata_id(),
133
134
"user_id" text NOT NULL,
134
135
"dropbox_token_id" text NOT NULL,
135
-
"xata_version" text NOT NULL,
136
+
"xata_version" text,
136
137
"xata_createdat" timestamp DEFAULT now() NOT NULL,
137
138
"xata_updatedat" timestamp DEFAULT now() NOT NULL
138
139
);
···
142
143
"email" text NOT NULL,
143
144
"is_beta_user" boolean DEFAULT false NOT NULL,
144
145
"user_id" text NOT NULL,
145
-
"xata_version" text NOT NULL,
146
+
"xata_version" text,
146
147
"xata_createdat" timestamp DEFAULT now() NOT NULL,
147
148
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
148
149
CONSTRAINT "google_drive_accounts_email_unique" UNIQUE("email")
···
155
156
"parent_id" text,
156
157
"google_drive_id" text NOT NULL,
157
158
"file_id" text NOT NULL,
158
-
"xata_version" text NOT NULL,
159
+
"xata_version" text,
159
160
"xata_createdat" timestamp DEFAULT now() NOT NULL,
160
161
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
161
162
CONSTRAINT "google_drive_directories_file_id_unique" UNIQUE("file_id")
···
168
169
"name" text NOT NULL,
169
170
"directory_id" text,
170
171
"file_id" text NOT NULL,
171
-
"xata_version" text NOT NULL,
172
+
"xata_version" text,
172
173
"xata_createdat" timestamp DEFAULT now() NOT NULL,
173
174
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
174
175
CONSTRAINT "google_drive_paths_file_id_unique" UNIQUE("file_id")
···
185
186
"xata_id" text PRIMARY KEY DEFAULT xata_id(),
186
187
"google_drive_token_id" text NOT NULL,
187
188
"user_id" text NOT NULL,
188
-
"xata_version" text NOT NULL,
189
+
"xata_version" text,
189
190
"xata_createdat" timestamp DEFAULT now() NOT NULL,
190
191
"xata_updatedat" timestamp DEFAULT now() NOT NULL
191
192
);
···
286
287
--> statement-breakpoint
287
288
CREATE TABLE "spotify_accounts" (
288
289
"xata_id" text PRIMARY KEY DEFAULT xata_id(),
289
-
"xata_version" integer NOT NULL,
290
+
"xata_version" integer,
290
291
"email" text NOT NULL,
291
292
"user_id" text NOT NULL,
292
293
"is_beta_user" boolean DEFAULT false NOT NULL,
···
296
297
--> statement-breakpoint
297
298
CREATE TABLE "spotify_tokens" (
298
299
"xata_id" text PRIMARY KEY DEFAULT xata_id(),
299
-
"xata_version" integer NOT NULL,
300
+
"xata_version" integer,
300
301
"access_token" text NOT NULL,
301
302
"refresh_token" text NOT NULL,
302
303
"user_id" text NOT NULL,
···
337
338
CONSTRAINT "tracks_apple_music_link_unique" UNIQUE("apple_music_link"),
338
339
CONSTRAINT "tracks_tidal_link_unique" UNIQUE("tidal_link"),
339
340
CONSTRAINT "tracks_sha256_unique" UNIQUE("sha256"),
340
-
CONSTRAINT "tracks_uri_unique" UNIQUE("uri"),
341
-
CONSTRAINT "tracks_album_uri_unique" UNIQUE("album_uri"),
342
-
CONSTRAINT "tracks_artist_uri_unique" UNIQUE("artist_uri")
341
+
CONSTRAINT "tracks_uri_unique" UNIQUE("uri")
343
342
);
344
343
--> statement-breakpoint
345
344
CREATE TABLE "user_albums" (
···
348
347
"album_id" text NOT NULL,
349
348
"xata_createdat" timestamp DEFAULT now() NOT NULL,
350
349
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
351
-
"xata_version" integer NOT NULL,
350
+
"xata_version" integer,
352
351
"scrobbles" integer,
353
352
"uri" text NOT NULL,
354
353
CONSTRAINT "user_albums_uri_unique" UNIQUE("uri")
···
360
359
"artist_id" text NOT NULL,
361
360
"xata_createdat" timestamp DEFAULT now() NOT NULL,
362
361
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
363
-
"xata_version" integer NOT NULL,
362
+
"xata_version" integer,
364
363
"scrobbles" integer,
365
364
"uri" text NOT NULL,
366
365
CONSTRAINT "user_artists_uri_unique" UNIQUE("uri")
···
381
380
"track_id" text NOT NULL,
382
381
"xata_createdat" timestamp DEFAULT now() NOT NULL,
383
382
"xata_updatedat" timestamp DEFAULT now() NOT NULL,
384
-
"xata_version" integer NOT NULL,
383
+
"xata_version" integer,
385
384
"uri" text NOT NULL,
386
385
"scrobbles" integer,
387
386
CONSTRAINT "user_tracks_uri_unique" UNIQUE("uri")
···
390
389
CREATE TABLE "users" (
391
390
"xata_id" text PRIMARY KEY DEFAULT xata_id(),
392
391
"did" text NOT NULL,
393
-
"display_name" text NOT NULL,
392
+
"display_name" text,
394
393
"handle" text NOT NULL,
395
394
"avatar" text NOT NULL,
396
395
"xata_createdat" timestamp DEFAULT now() NOT NULL,
+1
apps/api/drizzle/0001_fluffy_epoch.sql
+1
apps/api/drizzle/0001_fluffy_epoch.sql
···
1
+
ALTER TABLE "user_playlists" ALTER COLUMN "uri" DROP NOT NULL;
+3
apps/api/drizzle/0002_sweet_randall_flagg.sql
+3
apps/api/drizzle/0002_sweet_randall_flagg.sql
···
1
+
ALTER TABLE "user_playlists" DROP CONSTRAINT "user_playlists_playlist_id_tracks_xata_id_fk";
2
+
--> statement-breakpoint
3
+
ALTER TABLE "user_playlists" ADD CONSTRAINT "user_playlists_playlist_id_playlists_xata_id_fk" FOREIGN KEY ("playlist_id") REFERENCES "public"."playlists"("xata_id") ON DELETE no action ON UPDATE no action;
+24
-32
apps/api/drizzle/meta/0000_snapshot.json
+24
-32
apps/api/drizzle/meta/0000_snapshot.json
···
1
1
{
2
-
"id": "49adc24b-83c8-4065-8e13-80045e7f0f27",
2
+
"id": "6b33dcd0-52df-4403-bdc0-31517769923d",
3
3
"prevId": "00000000-0000-0000-0000-000000000000",
4
4
"version": "7",
5
5
"dialect": "postgresql",
···
44
44
"name": "xata_version",
45
45
"type": "integer",
46
46
"primaryKey": false,
47
-
"notNull": true
47
+
"notNull": false
48
48
}
49
49
},
50
50
"indexes": {},
···
360
360
"name": "xata_version",
361
361
"type": "integer",
362
362
"primaryKey": false,
363
-
"notNull": true
363
+
"notNull": false
364
364
}
365
365
},
366
366
"indexes": {},
···
438
438
"name": "xata_version",
439
439
"type": "integer",
440
440
"primaryKey": false,
441
-
"notNull": true
441
+
"notNull": false
442
442
}
443
443
},
444
444
"indexes": {},
···
555
555
"youtube_link": {
556
556
"name": "youtube_link",
557
557
"type": "text",
558
+
"primaryKey": false,
559
+
"notNull": false
560
+
},
561
+
"genres": {
562
+
"name": "genres",
563
+
"type": "text[]",
558
564
"primaryKey": false,
559
565
"notNull": false
560
566
},
···
635
641
"name": "xata_version",
636
642
"type": "text",
637
643
"primaryKey": false,
638
-
"notNull": true
644
+
"notNull": false
639
645
},
640
646
"xata_createdat": {
641
647
"name": "xata_createdat",
···
726
732
"name": "xata_version",
727
733
"type": "text",
728
734
"primaryKey": false,
729
-
"notNull": true
735
+
"notNull": false
730
736
},
731
737
"xata_createdat": {
732
738
"name": "xata_createdat",
···
823
829
"name": "xata_version",
824
830
"type": "text",
825
831
"primaryKey": false,
826
-
"notNull": true
832
+
"notNull": false
827
833
},
828
834
"xata_createdat": {
829
835
"name": "xata_createdat",
···
935
941
"name": "xata_version",
936
942
"type": "text",
937
943
"primaryKey": false,
938
-
"notNull": true
944
+
"notNull": false
939
945
},
940
946
"xata_createdat": {
941
947
"name": "xata_createdat",
···
1020
1026
"name": "xata_version",
1021
1027
"type": "text",
1022
1028
"primaryKey": false,
1023
-
"notNull": true
1029
+
"notNull": false
1024
1030
},
1025
1031
"xata_createdat": {
1026
1032
"name": "xata_createdat",
···
1111
1117
"name": "xata_version",
1112
1118
"type": "text",
1113
1119
"primaryKey": false,
1114
-
"notNull": true
1120
+
"notNull": false
1115
1121
},
1116
1122
"xata_createdat": {
1117
1123
"name": "xata_createdat",
···
1202
1208
"name": "xata_version",
1203
1209
"type": "text",
1204
1210
"primaryKey": false,
1205
-
"notNull": true
1211
+
"notNull": false
1206
1212
},
1207
1213
"xata_createdat": {
1208
1214
"name": "xata_createdat",
···
1314
1320
"name": "xata_version",
1315
1321
"type": "text",
1316
1322
"primaryKey": false,
1317
-
"notNull": true
1323
+
"notNull": false
1318
1324
},
1319
1325
"xata_createdat": {
1320
1326
"name": "xata_createdat",
···
2232
2238
"name": "xata_version",
2233
2239
"type": "integer",
2234
2240
"primaryKey": false,
2235
-
"notNull": true
2241
+
"notNull": false
2236
2242
},
2237
2243
"email": {
2238
2244
"name": "email",
···
2304
2310
"name": "xata_version",
2305
2311
"type": "integer",
2306
2312
"primaryKey": false,
2307
-
"notNull": true
2313
+
"notNull": false
2308
2314
},
2309
2315
"access_token": {
2310
2316
"name": "access_token",
···
2576
2582
"columns": [
2577
2583
"uri"
2578
2584
]
2579
-
},
2580
-
"tracks_album_uri_unique": {
2581
-
"name": "tracks_album_uri_unique",
2582
-
"nullsNotDistinct": false,
2583
-
"columns": [
2584
-
"album_uri"
2585
-
]
2586
-
},
2587
-
"tracks_artist_uri_unique": {
2588
-
"name": "tracks_artist_uri_unique",
2589
-
"nullsNotDistinct": false,
2590
-
"columns": [
2591
-
"artist_uri"
2592
-
]
2593
2585
}
2594
2586
},
2595
2587
"policies": {},
···
2636
2628
"name": "xata_version",
2637
2629
"type": "integer",
2638
2630
"primaryKey": false,
2639
-
"notNull": true
2631
+
"notNull": false
2640
2632
},
2641
2633
"scrobbles": {
2642
2634
"name": "scrobbles",
···
2734
2726
"name": "xata_version",
2735
2727
"type": "integer",
2736
2728
"primaryKey": false,
2737
-
"notNull": true
2729
+
"notNull": false
2738
2730
},
2739
2731
"scrobbles": {
2740
2732
"name": "scrobbles",
···
2911
2903
"name": "xata_version",
2912
2904
"type": "integer",
2913
2905
"primaryKey": false,
2914
-
"notNull": true
2906
+
"notNull": false
2915
2907
},
2916
2908
"uri": {
2917
2909
"name": "uri",
···
2989
2981
"name": "display_name",
2990
2982
"type": "text",
2991
2983
"primaryKey": false,
2992
-
"notNull": true
2984
+
"notNull": false
2993
2985
},
2994
2986
"handle": {
2995
2987
"name": "handle",
+3132
apps/api/drizzle/meta/0001_snapshot.json
+3132
apps/api/drizzle/meta/0001_snapshot.json
···
1
+
{
2
+
"id": "6ebb9775-b900-418c-bbd8-b704571a20d5",
3
+
"prevId": "6b33dcd0-52df-4403-bdc0-31517769923d",
4
+
"version": "7",
5
+
"dialect": "postgresql",
6
+
"tables": {
7
+
"public.album_tracks": {
8
+
"name": "album_tracks",
9
+
"schema": "",
10
+
"columns": {
11
+
"xata_id": {
12
+
"name": "xata_id",
13
+
"type": "text",
14
+
"primaryKey": true,
15
+
"notNull": true
16
+
},
17
+
"album_id": {
18
+
"name": "album_id",
19
+
"type": "text",
20
+
"primaryKey": false,
21
+
"notNull": true
22
+
},
23
+
"track_id": {
24
+
"name": "track_id",
25
+
"type": "text",
26
+
"primaryKey": false,
27
+
"notNull": true
28
+
},
29
+
"xata_createdat": {
30
+
"name": "xata_createdat",
31
+
"type": "timestamp",
32
+
"primaryKey": false,
33
+
"notNull": true,
34
+
"default": "now()"
35
+
},
36
+
"xata_updatedat": {
37
+
"name": "xata_updatedat",
38
+
"type": "timestamp",
39
+
"primaryKey": false,
40
+
"notNull": true,
41
+
"default": "now()"
42
+
},
43
+
"xata_version": {
44
+
"name": "xata_version",
45
+
"type": "integer",
46
+
"primaryKey": false,
47
+
"notNull": false
48
+
}
49
+
},
50
+
"indexes": {},
51
+
"foreignKeys": {
52
+
"album_tracks_album_id_albums_xata_id_fk": {
53
+
"name": "album_tracks_album_id_albums_xata_id_fk",
54
+
"tableFrom": "album_tracks",
55
+
"tableTo": "albums",
56
+
"columnsFrom": [
57
+
"album_id"
58
+
],
59
+
"columnsTo": [
60
+
"xata_id"
61
+
],
62
+
"onDelete": "no action",
63
+
"onUpdate": "no action"
64
+
},
65
+
"album_tracks_track_id_tracks_xata_id_fk": {
66
+
"name": "album_tracks_track_id_tracks_xata_id_fk",
67
+
"tableFrom": "album_tracks",
68
+
"tableTo": "tracks",
69
+
"columnsFrom": [
70
+
"track_id"
71
+
],
72
+
"columnsTo": [
73
+
"xata_id"
74
+
],
75
+
"onDelete": "no action",
76
+
"onUpdate": "no action"
77
+
}
78
+
},
79
+
"compositePrimaryKeys": {},
80
+
"uniqueConstraints": {},
81
+
"policies": {},
82
+
"checkConstraints": {},
83
+
"isRLSEnabled": false
84
+
},
85
+
"public.albums": {
86
+
"name": "albums",
87
+
"schema": "",
88
+
"columns": {
89
+
"xata_id": {
90
+
"name": "xata_id",
91
+
"type": "text",
92
+
"primaryKey": true,
93
+
"notNull": true
94
+
},
95
+
"title": {
96
+
"name": "title",
97
+
"type": "text",
98
+
"primaryKey": false,
99
+
"notNull": true
100
+
},
101
+
"artist": {
102
+
"name": "artist",
103
+
"type": "text",
104
+
"primaryKey": false,
105
+
"notNull": true
106
+
},
107
+
"release_date": {
108
+
"name": "release_date",
109
+
"type": "text",
110
+
"primaryKey": false,
111
+
"notNull": false
112
+
},
113
+
"year": {
114
+
"name": "year",
115
+
"type": "integer",
116
+
"primaryKey": false,
117
+
"notNull": false
118
+
},
119
+
"album_art": {
120
+
"name": "album_art",
121
+
"type": "text",
122
+
"primaryKey": false,
123
+
"notNull": false
124
+
},
125
+
"uri": {
126
+
"name": "uri",
127
+
"type": "text",
128
+
"primaryKey": false,
129
+
"notNull": false
130
+
},
131
+
"artist_uri": {
132
+
"name": "artist_uri",
133
+
"type": "text",
134
+
"primaryKey": false,
135
+
"notNull": false
136
+
},
137
+
"apple_music_link": {
138
+
"name": "apple_music_link",
139
+
"type": "text",
140
+
"primaryKey": false,
141
+
"notNull": false
142
+
},
143
+
"spotify_link": {
144
+
"name": "spotify_link",
145
+
"type": "text",
146
+
"primaryKey": false,
147
+
"notNull": false
148
+
},
149
+
"tidal_link": {
150
+
"name": "tidal_link",
151
+
"type": "text",
152
+
"primaryKey": false,
153
+
"notNull": false
154
+
},
155
+
"youtube_link": {
156
+
"name": "youtube_link",
157
+
"type": "text",
158
+
"primaryKey": false,
159
+
"notNull": false
160
+
},
161
+
"sha256": {
162
+
"name": "sha256",
163
+
"type": "text",
164
+
"primaryKey": false,
165
+
"notNull": true
166
+
},
167
+
"xata_createdat": {
168
+
"name": "xata_createdat",
169
+
"type": "timestamp",
170
+
"primaryKey": false,
171
+
"notNull": true,
172
+
"default": "now()"
173
+
},
174
+
"xata_updatedat": {
175
+
"name": "xata_updatedat",
176
+
"type": "timestamp",
177
+
"primaryKey": false,
178
+
"notNull": true,
179
+
"default": "now()"
180
+
},
181
+
"xata_version": {
182
+
"name": "xata_version",
183
+
"type": "integer",
184
+
"primaryKey": false,
185
+
"notNull": false
186
+
}
187
+
},
188
+
"indexes": {},
189
+
"foreignKeys": {},
190
+
"compositePrimaryKeys": {},
191
+
"uniqueConstraints": {
192
+
"albums_uri_unique": {
193
+
"name": "albums_uri_unique",
194
+
"nullsNotDistinct": false,
195
+
"columns": [
196
+
"uri"
197
+
]
198
+
},
199
+
"albums_apple_music_link_unique": {
200
+
"name": "albums_apple_music_link_unique",
201
+
"nullsNotDistinct": false,
202
+
"columns": [
203
+
"apple_music_link"
204
+
]
205
+
},
206
+
"albums_spotify_link_unique": {
207
+
"name": "albums_spotify_link_unique",
208
+
"nullsNotDistinct": false,
209
+
"columns": [
210
+
"spotify_link"
211
+
]
212
+
},
213
+
"albums_tidal_link_unique": {
214
+
"name": "albums_tidal_link_unique",
215
+
"nullsNotDistinct": false,
216
+
"columns": [
217
+
"tidal_link"
218
+
]
219
+
},
220
+
"albums_youtube_link_unique": {
221
+
"name": "albums_youtube_link_unique",
222
+
"nullsNotDistinct": false,
223
+
"columns": [
224
+
"youtube_link"
225
+
]
226
+
},
227
+
"albums_sha256_unique": {
228
+
"name": "albums_sha256_unique",
229
+
"nullsNotDistinct": false,
230
+
"columns": [
231
+
"sha256"
232
+
]
233
+
}
234
+
},
235
+
"policies": {},
236
+
"checkConstraints": {},
237
+
"isRLSEnabled": false
238
+
},
239
+
"public.api_keys": {
240
+
"name": "api_keys",
241
+
"schema": "",
242
+
"columns": {
243
+
"xata_id": {
244
+
"name": "xata_id",
245
+
"type": "text",
246
+
"primaryKey": true,
247
+
"notNull": true
248
+
},
249
+
"name": {
250
+
"name": "name",
251
+
"type": "text",
252
+
"primaryKey": false,
253
+
"notNull": true
254
+
},
255
+
"api_key": {
256
+
"name": "api_key",
257
+
"type": "text",
258
+
"primaryKey": false,
259
+
"notNull": true
260
+
},
261
+
"shared_secret": {
262
+
"name": "shared_secret",
263
+
"type": "text",
264
+
"primaryKey": false,
265
+
"notNull": true
266
+
},
267
+
"description": {
268
+
"name": "description",
269
+
"type": "text",
270
+
"primaryKey": false,
271
+
"notNull": false
272
+
},
273
+
"enabled": {
274
+
"name": "enabled",
275
+
"type": "boolean",
276
+
"primaryKey": false,
277
+
"notNull": true,
278
+
"default": true
279
+
},
280
+
"user_id": {
281
+
"name": "user_id",
282
+
"type": "text",
283
+
"primaryKey": false,
284
+
"notNull": true
285
+
},
286
+
"xata_createdat": {
287
+
"name": "xata_createdat",
288
+
"type": "timestamp",
289
+
"primaryKey": false,
290
+
"notNull": true,
291
+
"default": "now()"
292
+
},
293
+
"xata_updatedat": {
294
+
"name": "xata_updatedat",
295
+
"type": "timestamp",
296
+
"primaryKey": false,
297
+
"notNull": true,
298
+
"default": "now()"
299
+
}
300
+
},
301
+
"indexes": {},
302
+
"foreignKeys": {
303
+
"api_keys_user_id_users_xata_id_fk": {
304
+
"name": "api_keys_user_id_users_xata_id_fk",
305
+
"tableFrom": "api_keys",
306
+
"tableTo": "users",
307
+
"columnsFrom": [
308
+
"user_id"
309
+
],
310
+
"columnsTo": [
311
+
"xata_id"
312
+
],
313
+
"onDelete": "no action",
314
+
"onUpdate": "no action"
315
+
}
316
+
},
317
+
"compositePrimaryKeys": {},
318
+
"uniqueConstraints": {},
319
+
"policies": {},
320
+
"checkConstraints": {},
321
+
"isRLSEnabled": false
322
+
},
323
+
"public.artist_albums": {
324
+
"name": "artist_albums",
325
+
"schema": "",
326
+
"columns": {
327
+
"xata_id": {
328
+
"name": "xata_id",
329
+
"type": "text",
330
+
"primaryKey": true,
331
+
"notNull": true
332
+
},
333
+
"artist_id": {
334
+
"name": "artist_id",
335
+
"type": "text",
336
+
"primaryKey": false,
337
+
"notNull": true
338
+
},
339
+
"album_id": {
340
+
"name": "album_id",
341
+
"type": "text",
342
+
"primaryKey": false,
343
+
"notNull": true
344
+
},
345
+
"xata_createdat": {
346
+
"name": "xata_createdat",
347
+
"type": "timestamp",
348
+
"primaryKey": false,
349
+
"notNull": true,
350
+
"default": "now()"
351
+
},
352
+
"xata_updatedat": {
353
+
"name": "xata_updatedat",
354
+
"type": "timestamp",
355
+
"primaryKey": false,
356
+
"notNull": true,
357
+
"default": "now()"
358
+
},
359
+
"xata_version": {
360
+
"name": "xata_version",
361
+
"type": "integer",
362
+
"primaryKey": false,
363
+
"notNull": false
364
+
}
365
+
},
366
+
"indexes": {},
367
+
"foreignKeys": {
368
+
"artist_albums_artist_id_artists_xata_id_fk": {
369
+
"name": "artist_albums_artist_id_artists_xata_id_fk",
370
+
"tableFrom": "artist_albums",
371
+
"tableTo": "artists",
372
+
"columnsFrom": [
373
+
"artist_id"
374
+
],
375
+
"columnsTo": [
376
+
"xata_id"
377
+
],
378
+
"onDelete": "no action",
379
+
"onUpdate": "no action"
380
+
},
381
+
"artist_albums_album_id_albums_xata_id_fk": {
382
+
"name": "artist_albums_album_id_albums_xata_id_fk",
383
+
"tableFrom": "artist_albums",
384
+
"tableTo": "albums",
385
+
"columnsFrom": [
386
+
"album_id"
387
+
],
388
+
"columnsTo": [
389
+
"xata_id"
390
+
],
391
+
"onDelete": "no action",
392
+
"onUpdate": "no action"
393
+
}
394
+
},
395
+
"compositePrimaryKeys": {},
396
+
"uniqueConstraints": {},
397
+
"policies": {},
398
+
"checkConstraints": {},
399
+
"isRLSEnabled": false
400
+
},
401
+
"public.artist_tracks": {
402
+
"name": "artist_tracks",
403
+
"schema": "",
404
+
"columns": {
405
+
"xata_id": {
406
+
"name": "xata_id",
407
+
"type": "text",
408
+
"primaryKey": true,
409
+
"notNull": true
410
+
},
411
+
"artist_id": {
412
+
"name": "artist_id",
413
+
"type": "text",
414
+
"primaryKey": false,
415
+
"notNull": true
416
+
},
417
+
"track_id": {
418
+
"name": "track_id",
419
+
"type": "text",
420
+
"primaryKey": false,
421
+
"notNull": true
422
+
},
423
+
"xata_createdat": {
424
+
"name": "xata_createdat",
425
+
"type": "timestamp",
426
+
"primaryKey": false,
427
+
"notNull": true,
428
+
"default": "now()"
429
+
},
430
+
"xata_updatedat": {
431
+
"name": "xata_updatedat",
432
+
"type": "timestamp",
433
+
"primaryKey": false,
434
+
"notNull": true,
435
+
"default": "now()"
436
+
},
437
+
"xata_version": {
438
+
"name": "xata_version",
439
+
"type": "integer",
440
+
"primaryKey": false,
441
+
"notNull": false
442
+
}
443
+
},
444
+
"indexes": {},
445
+
"foreignKeys": {
446
+
"artist_tracks_artist_id_artists_xata_id_fk": {
447
+
"name": "artist_tracks_artist_id_artists_xata_id_fk",
448
+
"tableFrom": "artist_tracks",
449
+
"tableTo": "artists",
450
+
"columnsFrom": [
451
+
"artist_id"
452
+
],
453
+
"columnsTo": [
454
+
"xata_id"
455
+
],
456
+
"onDelete": "no action",
457
+
"onUpdate": "no action"
458
+
},
459
+
"artist_tracks_track_id_tracks_xata_id_fk": {
460
+
"name": "artist_tracks_track_id_tracks_xata_id_fk",
461
+
"tableFrom": "artist_tracks",
462
+
"tableTo": "tracks",
463
+
"columnsFrom": [
464
+
"track_id"
465
+
],
466
+
"columnsTo": [
467
+
"xata_id"
468
+
],
469
+
"onDelete": "no action",
470
+
"onUpdate": "no action"
471
+
}
472
+
},
473
+
"compositePrimaryKeys": {},
474
+
"uniqueConstraints": {},
475
+
"policies": {},
476
+
"checkConstraints": {},
477
+
"isRLSEnabled": false
478
+
},
479
+
"public.artists": {
480
+
"name": "artists",
481
+
"schema": "",
482
+
"columns": {
483
+
"xata_id": {
484
+
"name": "xata_id",
485
+
"type": "text",
486
+
"primaryKey": true,
487
+
"notNull": true
488
+
},
489
+
"name": {
490
+
"name": "name",
491
+
"type": "text",
492
+
"primaryKey": false,
493
+
"notNull": true
494
+
},
495
+
"biography": {
496
+
"name": "biography",
497
+
"type": "text",
498
+
"primaryKey": false,
499
+
"notNull": false
500
+
},
501
+
"born": {
502
+
"name": "born",
503
+
"type": "timestamp",
504
+
"primaryKey": false,
505
+
"notNull": false
506
+
},
507
+
"born_in": {
508
+
"name": "born_in",
509
+
"type": "text",
510
+
"primaryKey": false,
511
+
"notNull": false
512
+
},
513
+
"died": {
514
+
"name": "died",
515
+
"type": "timestamp",
516
+
"primaryKey": false,
517
+
"notNull": false
518
+
},
519
+
"picture": {
520
+
"name": "picture",
521
+
"type": "text",
522
+
"primaryKey": false,
523
+
"notNull": false
524
+
},
525
+
"sha256": {
526
+
"name": "sha256",
527
+
"type": "text",
528
+
"primaryKey": false,
529
+
"notNull": true
530
+
},
531
+
"uri": {
532
+
"name": "uri",
533
+
"type": "text",
534
+
"primaryKey": false,
535
+
"notNull": false
536
+
},
537
+
"apple_music_link": {
538
+
"name": "apple_music_link",
539
+
"type": "text",
540
+
"primaryKey": false,
541
+
"notNull": false
542
+
},
543
+
"spotify_link": {
544
+
"name": "spotify_link",
545
+
"type": "text",
546
+
"primaryKey": false,
547
+
"notNull": false
548
+
},
549
+
"tidal_link": {
550
+
"name": "tidal_link",
551
+
"type": "text",
552
+
"primaryKey": false,
553
+
"notNull": false
554
+
},
555
+
"youtube_link": {
556
+
"name": "youtube_link",
557
+
"type": "text",
558
+
"primaryKey": false,
559
+
"notNull": false
560
+
},
561
+
"genres": {
562
+
"name": "genres",
563
+
"type": "text[]",
564
+
"primaryKey": false,
565
+
"notNull": false
566
+
},
567
+
"xata_createdat": {
568
+
"name": "xata_createdat",
569
+
"type": "timestamp",
570
+
"primaryKey": false,
571
+
"notNull": true,
572
+
"default": "now()"
573
+
},
574
+
"xata_updatedat": {
575
+
"name": "xata_updatedat",
576
+
"type": "timestamp",
577
+
"primaryKey": false,
578
+
"notNull": true,
579
+
"default": "now()"
580
+
},
581
+
"xata_version": {
582
+
"name": "xata_version",
583
+
"type": "integer",
584
+
"primaryKey": false,
585
+
"notNull": false
586
+
}
587
+
},
588
+
"indexes": {},
589
+
"foreignKeys": {},
590
+
"compositePrimaryKeys": {},
591
+
"uniqueConstraints": {
592
+
"artists_sha256_unique": {
593
+
"name": "artists_sha256_unique",
594
+
"nullsNotDistinct": false,
595
+
"columns": [
596
+
"sha256"
597
+
]
598
+
},
599
+
"artists_uri_unique": {
600
+
"name": "artists_uri_unique",
601
+
"nullsNotDistinct": false,
602
+
"columns": [
603
+
"uri"
604
+
]
605
+
}
606
+
},
607
+
"policies": {},
608
+
"checkConstraints": {},
609
+
"isRLSEnabled": false
610
+
},
611
+
"public.dropbox_accounts": {
612
+
"name": "dropbox_accounts",
613
+
"schema": "",
614
+
"columns": {
615
+
"xata_id": {
616
+
"name": "xata_id",
617
+
"type": "text",
618
+
"primaryKey": true,
619
+
"notNull": true
620
+
},
621
+
"email": {
622
+
"name": "email",
623
+
"type": "text",
624
+
"primaryKey": false,
625
+
"notNull": true
626
+
},
627
+
"is_beta_user": {
628
+
"name": "is_beta_user",
629
+
"type": "boolean",
630
+
"primaryKey": false,
631
+
"notNull": true,
632
+
"default": false
633
+
},
634
+
"user_id": {
635
+
"name": "user_id",
636
+
"type": "text",
637
+
"primaryKey": false,
638
+
"notNull": true
639
+
},
640
+
"xata_version": {
641
+
"name": "xata_version",
642
+
"type": "text",
643
+
"primaryKey": false,
644
+
"notNull": false
645
+
},
646
+
"xata_createdat": {
647
+
"name": "xata_createdat",
648
+
"type": "timestamp",
649
+
"primaryKey": false,
650
+
"notNull": true,
651
+
"default": "now()"
652
+
},
653
+
"xata_updatedat": {
654
+
"name": "xata_updatedat",
655
+
"type": "timestamp",
656
+
"primaryKey": false,
657
+
"notNull": true,
658
+
"default": "now()"
659
+
}
660
+
},
661
+
"indexes": {},
662
+
"foreignKeys": {
663
+
"dropbox_accounts_user_id_users_xata_id_fk": {
664
+
"name": "dropbox_accounts_user_id_users_xata_id_fk",
665
+
"tableFrom": "dropbox_accounts",
666
+
"tableTo": "users",
667
+
"columnsFrom": [
668
+
"user_id"
669
+
],
670
+
"columnsTo": [
671
+
"xata_id"
672
+
],
673
+
"onDelete": "no action",
674
+
"onUpdate": "no action"
675
+
}
676
+
},
677
+
"compositePrimaryKeys": {},
678
+
"uniqueConstraints": {
679
+
"dropbox_accounts_email_unique": {
680
+
"name": "dropbox_accounts_email_unique",
681
+
"nullsNotDistinct": false,
682
+
"columns": [
683
+
"email"
684
+
]
685
+
}
686
+
},
687
+
"policies": {},
688
+
"checkConstraints": {},
689
+
"isRLSEnabled": false
690
+
},
691
+
"public.dropbox_directories": {
692
+
"name": "dropbox_directories",
693
+
"schema": "",
694
+
"columns": {
695
+
"xata_id": {
696
+
"name": "xata_id",
697
+
"type": "text",
698
+
"primaryKey": true,
699
+
"notNull": true
700
+
},
701
+
"name": {
702
+
"name": "name",
703
+
"type": "text",
704
+
"primaryKey": false,
705
+
"notNull": true
706
+
},
707
+
"path": {
708
+
"name": "path",
709
+
"type": "text",
710
+
"primaryKey": false,
711
+
"notNull": true
712
+
},
713
+
"parent_id": {
714
+
"name": "parent_id",
715
+
"type": "text",
716
+
"primaryKey": false,
717
+
"notNull": false
718
+
},
719
+
"dropbox_id": {
720
+
"name": "dropbox_id",
721
+
"type": "text",
722
+
"primaryKey": false,
723
+
"notNull": true
724
+
},
725
+
"file_id": {
726
+
"name": "file_id",
727
+
"type": "text",
728
+
"primaryKey": false,
729
+
"notNull": true
730
+
},
731
+
"xata_version": {
732
+
"name": "xata_version",
733
+
"type": "text",
734
+
"primaryKey": false,
735
+
"notNull": false
736
+
},
737
+
"xata_createdat": {
738
+
"name": "xata_createdat",
739
+
"type": "timestamp",
740
+
"primaryKey": false,
741
+
"notNull": true,
742
+
"default": "now()"
743
+
},
744
+
"xata_updatedat": {
745
+
"name": "xata_updatedat",
746
+
"type": "timestamp",
747
+
"primaryKey": false,
748
+
"notNull": true,
749
+
"default": "now()"
750
+
}
751
+
},
752
+
"indexes": {},
753
+
"foreignKeys": {
754
+
"dropbox_directories_parent_id_dropbox_directories_xata_id_fk": {
755
+
"name": "dropbox_directories_parent_id_dropbox_directories_xata_id_fk",
756
+
"tableFrom": "dropbox_directories",
757
+
"tableTo": "dropbox_directories",
758
+
"columnsFrom": [
759
+
"parent_id"
760
+
],
761
+
"columnsTo": [
762
+
"xata_id"
763
+
],
764
+
"onDelete": "no action",
765
+
"onUpdate": "no action"
766
+
}
767
+
},
768
+
"compositePrimaryKeys": {},
769
+
"uniqueConstraints": {
770
+
"dropbox_directories_file_id_unique": {
771
+
"name": "dropbox_directories_file_id_unique",
772
+
"nullsNotDistinct": false,
773
+
"columns": [
774
+
"file_id"
775
+
]
776
+
}
777
+
},
778
+
"policies": {},
779
+
"checkConstraints": {},
780
+
"isRLSEnabled": false
781
+
},
782
+
"public.dropbox_paths": {
783
+
"name": "dropbox_paths",
784
+
"schema": "",
785
+
"columns": {
786
+
"xata_id": {
787
+
"name": "xata_id",
788
+
"type": "text",
789
+
"primaryKey": true,
790
+
"notNull": true
791
+
},
792
+
"path": {
793
+
"name": "path",
794
+
"type": "text",
795
+
"primaryKey": false,
796
+
"notNull": true
797
+
},
798
+
"name": {
799
+
"name": "name",
800
+
"type": "text",
801
+
"primaryKey": false,
802
+
"notNull": true
803
+
},
804
+
"dropbox_id": {
805
+
"name": "dropbox_id",
806
+
"type": "text",
807
+
"primaryKey": false,
808
+
"notNull": true
809
+
},
810
+
"track_id": {
811
+
"name": "track_id",
812
+
"type": "text",
813
+
"primaryKey": false,
814
+
"notNull": true
815
+
},
816
+
"directory_id": {
817
+
"name": "directory_id",
818
+
"type": "text",
819
+
"primaryKey": false,
820
+
"notNull": false
821
+
},
822
+
"file_id": {
823
+
"name": "file_id",
824
+
"type": "text",
825
+
"primaryKey": false,
826
+
"notNull": true
827
+
},
828
+
"xata_version": {
829
+
"name": "xata_version",
830
+
"type": "text",
831
+
"primaryKey": false,
832
+
"notNull": false
833
+
},
834
+
"xata_createdat": {
835
+
"name": "xata_createdat",
836
+
"type": "timestamp",
837
+
"primaryKey": false,
838
+
"notNull": true,
839
+
"default": "now()"
840
+
},
841
+
"xata_updatedat": {
842
+
"name": "xata_updatedat",
843
+
"type": "timestamp",
844
+
"primaryKey": false,
845
+
"notNull": true,
846
+
"default": "now()"
847
+
}
848
+
},
849
+
"indexes": {},
850
+
"foreignKeys": {
851
+
"dropbox_paths_directory_id_dropbox_directories_xata_id_fk": {
852
+
"name": "dropbox_paths_directory_id_dropbox_directories_xata_id_fk",
853
+
"tableFrom": "dropbox_paths",
854
+
"tableTo": "dropbox_directories",
855
+
"columnsFrom": [
856
+
"directory_id"
857
+
],
858
+
"columnsTo": [
859
+
"xata_id"
860
+
],
861
+
"onDelete": "no action",
862
+
"onUpdate": "no action"
863
+
}
864
+
},
865
+
"compositePrimaryKeys": {},
866
+
"uniqueConstraints": {
867
+
"dropbox_paths_file_id_unique": {
868
+
"name": "dropbox_paths_file_id_unique",
869
+
"nullsNotDistinct": false,
870
+
"columns": [
871
+
"file_id"
872
+
]
873
+
}
874
+
},
875
+
"policies": {},
876
+
"checkConstraints": {},
877
+
"isRLSEnabled": false
878
+
},
879
+
"public.dropbox_tokens": {
880
+
"name": "dropbox_tokens",
881
+
"schema": "",
882
+
"columns": {
883
+
"xata_id": {
884
+
"name": "xata_id",
885
+
"type": "text",
886
+
"primaryKey": true,
887
+
"notNull": true
888
+
},
889
+
"refresh_token": {
890
+
"name": "refresh_token",
891
+
"type": "text",
892
+
"primaryKey": false,
893
+
"notNull": true
894
+
},
895
+
"xata_createdat": {
896
+
"name": "xata_createdat",
897
+
"type": "timestamp",
898
+
"primaryKey": false,
899
+
"notNull": true,
900
+
"default": "now()"
901
+
},
902
+
"xata_updatedat": {
903
+
"name": "xata_updatedat",
904
+
"type": "timestamp",
905
+
"primaryKey": false,
906
+
"notNull": true,
907
+
"default": "now()"
908
+
}
909
+
},
910
+
"indexes": {},
911
+
"foreignKeys": {},
912
+
"compositePrimaryKeys": {},
913
+
"uniqueConstraints": {},
914
+
"policies": {},
915
+
"checkConstraints": {},
916
+
"isRLSEnabled": false
917
+
},
918
+
"public.dropbox": {
919
+
"name": "dropbox",
920
+
"schema": "",
921
+
"columns": {
922
+
"xata_id": {
923
+
"name": "xata_id",
924
+
"type": "text",
925
+
"primaryKey": true,
926
+
"notNull": true
927
+
},
928
+
"user_id": {
929
+
"name": "user_id",
930
+
"type": "text",
931
+
"primaryKey": false,
932
+
"notNull": true
933
+
},
934
+
"dropbox_token_id": {
935
+
"name": "dropbox_token_id",
936
+
"type": "text",
937
+
"primaryKey": false,
938
+
"notNull": true
939
+
},
940
+
"xata_version": {
941
+
"name": "xata_version",
942
+
"type": "text",
943
+
"primaryKey": false,
944
+
"notNull": false
945
+
},
946
+
"xata_createdat": {
947
+
"name": "xata_createdat",
948
+
"type": "timestamp",
949
+
"primaryKey": false,
950
+
"notNull": true,
951
+
"default": "now()"
952
+
},
953
+
"xata_updatedat": {
954
+
"name": "xata_updatedat",
955
+
"type": "timestamp",
956
+
"primaryKey": false,
957
+
"notNull": true,
958
+
"default": "now()"
959
+
}
960
+
},
961
+
"indexes": {},
962
+
"foreignKeys": {
963
+
"dropbox_user_id_users_xata_id_fk": {
964
+
"name": "dropbox_user_id_users_xata_id_fk",
965
+
"tableFrom": "dropbox",
966
+
"tableTo": "users",
967
+
"columnsFrom": [
968
+
"user_id"
969
+
],
970
+
"columnsTo": [
971
+
"xata_id"
972
+
],
973
+
"onDelete": "no action",
974
+
"onUpdate": "no action"
975
+
},
976
+
"dropbox_dropbox_token_id_dropbox_tokens_xata_id_fk": {
977
+
"name": "dropbox_dropbox_token_id_dropbox_tokens_xata_id_fk",
978
+
"tableFrom": "dropbox",
979
+
"tableTo": "dropbox_tokens",
980
+
"columnsFrom": [
981
+
"dropbox_token_id"
982
+
],
983
+
"columnsTo": [
984
+
"xata_id"
985
+
],
986
+
"onDelete": "no action",
987
+
"onUpdate": "no action"
988
+
}
989
+
},
990
+
"compositePrimaryKeys": {},
991
+
"uniqueConstraints": {},
992
+
"policies": {},
993
+
"checkConstraints": {},
994
+
"isRLSEnabled": false
995
+
},
996
+
"public.google_drive_accounts": {
997
+
"name": "google_drive_accounts",
998
+
"schema": "",
999
+
"columns": {
1000
+
"xata_id": {
1001
+
"name": "xata_id",
1002
+
"type": "text",
1003
+
"primaryKey": true,
1004
+
"notNull": true
1005
+
},
1006
+
"email": {
1007
+
"name": "email",
1008
+
"type": "text",
1009
+
"primaryKey": false,
1010
+
"notNull": true
1011
+
},
1012
+
"is_beta_user": {
1013
+
"name": "is_beta_user",
1014
+
"type": "boolean",
1015
+
"primaryKey": false,
1016
+
"notNull": true,
1017
+
"default": false
1018
+
},
1019
+
"user_id": {
1020
+
"name": "user_id",
1021
+
"type": "text",
1022
+
"primaryKey": false,
1023
+
"notNull": true
1024
+
},
1025
+
"xata_version": {
1026
+
"name": "xata_version",
1027
+
"type": "text",
1028
+
"primaryKey": false,
1029
+
"notNull": false
1030
+
},
1031
+
"xata_createdat": {
1032
+
"name": "xata_createdat",
1033
+
"type": "timestamp",
1034
+
"primaryKey": false,
1035
+
"notNull": true,
1036
+
"default": "now()"
1037
+
},
1038
+
"xata_updatedat": {
1039
+
"name": "xata_updatedat",
1040
+
"type": "timestamp",
1041
+
"primaryKey": false,
1042
+
"notNull": true,
1043
+
"default": "now()"
1044
+
}
1045
+
},
1046
+
"indexes": {},
1047
+
"foreignKeys": {
1048
+
"google_drive_accounts_user_id_users_xata_id_fk": {
1049
+
"name": "google_drive_accounts_user_id_users_xata_id_fk",
1050
+
"tableFrom": "google_drive_accounts",
1051
+
"tableTo": "users",
1052
+
"columnsFrom": [
1053
+
"user_id"
1054
+
],
1055
+
"columnsTo": [
1056
+
"xata_id"
1057
+
],
1058
+
"onDelete": "no action",
1059
+
"onUpdate": "no action"
1060
+
}
1061
+
},
1062
+
"compositePrimaryKeys": {},
1063
+
"uniqueConstraints": {
1064
+
"google_drive_accounts_email_unique": {
1065
+
"name": "google_drive_accounts_email_unique",
1066
+
"nullsNotDistinct": false,
1067
+
"columns": [
1068
+
"email"
1069
+
]
1070
+
}
1071
+
},
1072
+
"policies": {},
1073
+
"checkConstraints": {},
1074
+
"isRLSEnabled": false
1075
+
},
1076
+
"public.google_drive_directories": {
1077
+
"name": "google_drive_directories",
1078
+
"schema": "",
1079
+
"columns": {
1080
+
"xata_id": {
1081
+
"name": "xata_id",
1082
+
"type": "text",
1083
+
"primaryKey": true,
1084
+
"notNull": true
1085
+
},
1086
+
"name": {
1087
+
"name": "name",
1088
+
"type": "text",
1089
+
"primaryKey": false,
1090
+
"notNull": true
1091
+
},
1092
+
"path": {
1093
+
"name": "path",
1094
+
"type": "text",
1095
+
"primaryKey": false,
1096
+
"notNull": true
1097
+
},
1098
+
"parent_id": {
1099
+
"name": "parent_id",
1100
+
"type": "text",
1101
+
"primaryKey": false,
1102
+
"notNull": false
1103
+
},
1104
+
"google_drive_id": {
1105
+
"name": "google_drive_id",
1106
+
"type": "text",
1107
+
"primaryKey": false,
1108
+
"notNull": true
1109
+
},
1110
+
"file_id": {
1111
+
"name": "file_id",
1112
+
"type": "text",
1113
+
"primaryKey": false,
1114
+
"notNull": true
1115
+
},
1116
+
"xata_version": {
1117
+
"name": "xata_version",
1118
+
"type": "text",
1119
+
"primaryKey": false,
1120
+
"notNull": false
1121
+
},
1122
+
"xata_createdat": {
1123
+
"name": "xata_createdat",
1124
+
"type": "timestamp",
1125
+
"primaryKey": false,
1126
+
"notNull": true,
1127
+
"default": "now()"
1128
+
},
1129
+
"xata_updatedat": {
1130
+
"name": "xata_updatedat",
1131
+
"type": "timestamp",
1132
+
"primaryKey": false,
1133
+
"notNull": true,
1134
+
"default": "now()"
1135
+
}
1136
+
},
1137
+
"indexes": {},
1138
+
"foreignKeys": {
1139
+
"google_drive_directories_parent_id_google_drive_directories_xata_id_fk": {
1140
+
"name": "google_drive_directories_parent_id_google_drive_directories_xata_id_fk",
1141
+
"tableFrom": "google_drive_directories",
1142
+
"tableTo": "google_drive_directories",
1143
+
"columnsFrom": [
1144
+
"parent_id"
1145
+
],
1146
+
"columnsTo": [
1147
+
"xata_id"
1148
+
],
1149
+
"onDelete": "no action",
1150
+
"onUpdate": "no action"
1151
+
}
1152
+
},
1153
+
"compositePrimaryKeys": {},
1154
+
"uniqueConstraints": {
1155
+
"google_drive_directories_file_id_unique": {
1156
+
"name": "google_drive_directories_file_id_unique",
1157
+
"nullsNotDistinct": false,
1158
+
"columns": [
1159
+
"file_id"
1160
+
]
1161
+
}
1162
+
},
1163
+
"policies": {},
1164
+
"checkConstraints": {},
1165
+
"isRLSEnabled": false
1166
+
},
1167
+
"public.google_drive_paths": {
1168
+
"name": "google_drive_paths",
1169
+
"schema": "",
1170
+
"columns": {
1171
+
"xata_id": {
1172
+
"name": "xata_id",
1173
+
"type": "text",
1174
+
"primaryKey": true,
1175
+
"notNull": true
1176
+
},
1177
+
"google_drive_id": {
1178
+
"name": "google_drive_id",
1179
+
"type": "text",
1180
+
"primaryKey": false,
1181
+
"notNull": true
1182
+
},
1183
+
"track_id": {
1184
+
"name": "track_id",
1185
+
"type": "text",
1186
+
"primaryKey": false,
1187
+
"notNull": true
1188
+
},
1189
+
"name": {
1190
+
"name": "name",
1191
+
"type": "text",
1192
+
"primaryKey": false,
1193
+
"notNull": true
1194
+
},
1195
+
"directory_id": {
1196
+
"name": "directory_id",
1197
+
"type": "text",
1198
+
"primaryKey": false,
1199
+
"notNull": false
1200
+
},
1201
+
"file_id": {
1202
+
"name": "file_id",
1203
+
"type": "text",
1204
+
"primaryKey": false,
1205
+
"notNull": true
1206
+
},
1207
+
"xata_version": {
1208
+
"name": "xata_version",
1209
+
"type": "text",
1210
+
"primaryKey": false,
1211
+
"notNull": false
1212
+
},
1213
+
"xata_createdat": {
1214
+
"name": "xata_createdat",
1215
+
"type": "timestamp",
1216
+
"primaryKey": false,
1217
+
"notNull": true,
1218
+
"default": "now()"
1219
+
},
1220
+
"xata_updatedat": {
1221
+
"name": "xata_updatedat",
1222
+
"type": "timestamp",
1223
+
"primaryKey": false,
1224
+
"notNull": true,
1225
+
"default": "now()"
1226
+
}
1227
+
},
1228
+
"indexes": {},
1229
+
"foreignKeys": {
1230
+
"google_drive_paths_directory_id_google_drive_directories_xata_id_fk": {
1231
+
"name": "google_drive_paths_directory_id_google_drive_directories_xata_id_fk",
1232
+
"tableFrom": "google_drive_paths",
1233
+
"tableTo": "google_drive_directories",
1234
+
"columnsFrom": [
1235
+
"directory_id"
1236
+
],
1237
+
"columnsTo": [
1238
+
"xata_id"
1239
+
],
1240
+
"onDelete": "no action",
1241
+
"onUpdate": "no action"
1242
+
}
1243
+
},
1244
+
"compositePrimaryKeys": {},
1245
+
"uniqueConstraints": {
1246
+
"google_drive_paths_file_id_unique": {
1247
+
"name": "google_drive_paths_file_id_unique",
1248
+
"nullsNotDistinct": false,
1249
+
"columns": [
1250
+
"file_id"
1251
+
]
1252
+
}
1253
+
},
1254
+
"policies": {},
1255
+
"checkConstraints": {},
1256
+
"isRLSEnabled": false
1257
+
},
1258
+
"public.google_drive_tokens": {
1259
+
"name": "google_drive_tokens",
1260
+
"schema": "",
1261
+
"columns": {
1262
+
"xata_id": {
1263
+
"name": "xata_id",
1264
+
"type": "text",
1265
+
"primaryKey": true,
1266
+
"notNull": true
1267
+
},
1268
+
"refresh_token": {
1269
+
"name": "refresh_token",
1270
+
"type": "text",
1271
+
"primaryKey": false,
1272
+
"notNull": true
1273
+
},
1274
+
"xata_createdat": {
1275
+
"name": "xata_createdat",
1276
+
"type": "timestamp",
1277
+
"primaryKey": false,
1278
+
"notNull": true,
1279
+
"default": "now()"
1280
+
},
1281
+
"xata_updatedat": {
1282
+
"name": "xata_updatedat",
1283
+
"type": "timestamp",
1284
+
"primaryKey": false,
1285
+
"notNull": true,
1286
+
"default": "now()"
1287
+
}
1288
+
},
1289
+
"indexes": {},
1290
+
"foreignKeys": {},
1291
+
"compositePrimaryKeys": {},
1292
+
"uniqueConstraints": {},
1293
+
"policies": {},
1294
+
"checkConstraints": {},
1295
+
"isRLSEnabled": false
1296
+
},
1297
+
"public.google_drive": {
1298
+
"name": "google_drive",
1299
+
"schema": "",
1300
+
"columns": {
1301
+
"xata_id": {
1302
+
"name": "xata_id",
1303
+
"type": "text",
1304
+
"primaryKey": true,
1305
+
"notNull": true
1306
+
},
1307
+
"google_drive_token_id": {
1308
+
"name": "google_drive_token_id",
1309
+
"type": "text",
1310
+
"primaryKey": false,
1311
+
"notNull": true
1312
+
},
1313
+
"user_id": {
1314
+
"name": "user_id",
1315
+
"type": "text",
1316
+
"primaryKey": false,
1317
+
"notNull": true
1318
+
},
1319
+
"xata_version": {
1320
+
"name": "xata_version",
1321
+
"type": "text",
1322
+
"primaryKey": false,
1323
+
"notNull": false
1324
+
},
1325
+
"xata_createdat": {
1326
+
"name": "xata_createdat",
1327
+
"type": "timestamp",
1328
+
"primaryKey": false,
1329
+
"notNull": true,
1330
+
"default": "now()"
1331
+
},
1332
+
"xata_updatedat": {
1333
+
"name": "xata_updatedat",
1334
+
"type": "timestamp",
1335
+
"primaryKey": false,
1336
+
"notNull": true,
1337
+
"default": "now()"
1338
+
}
1339
+
},
1340
+
"indexes": {},
1341
+
"foreignKeys": {
1342
+
"google_drive_google_drive_token_id_google_drive_tokens_xata_id_fk": {
1343
+
"name": "google_drive_google_drive_token_id_google_drive_tokens_xata_id_fk",
1344
+
"tableFrom": "google_drive",
1345
+
"tableTo": "google_drive_tokens",
1346
+
"columnsFrom": [
1347
+
"google_drive_token_id"
1348
+
],
1349
+
"columnsTo": [
1350
+
"xata_id"
1351
+
],
1352
+
"onDelete": "no action",
1353
+
"onUpdate": "no action"
1354
+
},
1355
+
"google_drive_user_id_users_xata_id_fk": {
1356
+
"name": "google_drive_user_id_users_xata_id_fk",
1357
+
"tableFrom": "google_drive",
1358
+
"tableTo": "users",
1359
+
"columnsFrom": [
1360
+
"user_id"
1361
+
],
1362
+
"columnsTo": [
1363
+
"xata_id"
1364
+
],
1365
+
"onDelete": "no action",
1366
+
"onUpdate": "no action"
1367
+
}
1368
+
},
1369
+
"compositePrimaryKeys": {},
1370
+
"uniqueConstraints": {},
1371
+
"policies": {},
1372
+
"checkConstraints": {},
1373
+
"isRLSEnabled": false
1374
+
},
1375
+
"public.loved_tracks": {
1376
+
"name": "loved_tracks",
1377
+
"schema": "",
1378
+
"columns": {
1379
+
"xata_id": {
1380
+
"name": "xata_id",
1381
+
"type": "text",
1382
+
"primaryKey": true,
1383
+
"notNull": true
1384
+
},
1385
+
"user_id": {
1386
+
"name": "user_id",
1387
+
"type": "text",
1388
+
"primaryKey": false,
1389
+
"notNull": true
1390
+
},
1391
+
"track_id": {
1392
+
"name": "track_id",
1393
+
"type": "text",
1394
+
"primaryKey": false,
1395
+
"notNull": true
1396
+
},
1397
+
"uri": {
1398
+
"name": "uri",
1399
+
"type": "text",
1400
+
"primaryKey": false,
1401
+
"notNull": false
1402
+
},
1403
+
"xata_createdat": {
1404
+
"name": "xata_createdat",
1405
+
"type": "timestamp",
1406
+
"primaryKey": false,
1407
+
"notNull": true,
1408
+
"default": "now()"
1409
+
}
1410
+
},
1411
+
"indexes": {},
1412
+
"foreignKeys": {
1413
+
"loved_tracks_user_id_users_xata_id_fk": {
1414
+
"name": "loved_tracks_user_id_users_xata_id_fk",
1415
+
"tableFrom": "loved_tracks",
1416
+
"tableTo": "users",
1417
+
"columnsFrom": [
1418
+
"user_id"
1419
+
],
1420
+
"columnsTo": [
1421
+
"xata_id"
1422
+
],
1423
+
"onDelete": "no action",
1424
+
"onUpdate": "no action"
1425
+
},
1426
+
"loved_tracks_track_id_tracks_xata_id_fk": {
1427
+
"name": "loved_tracks_track_id_tracks_xata_id_fk",
1428
+
"tableFrom": "loved_tracks",
1429
+
"tableTo": "tracks",
1430
+
"columnsFrom": [
1431
+
"track_id"
1432
+
],
1433
+
"columnsTo": [
1434
+
"xata_id"
1435
+
],
1436
+
"onDelete": "no action",
1437
+
"onUpdate": "no action"
1438
+
}
1439
+
},
1440
+
"compositePrimaryKeys": {},
1441
+
"uniqueConstraints": {
1442
+
"loved_tracks_uri_unique": {
1443
+
"name": "loved_tracks_uri_unique",
1444
+
"nullsNotDistinct": false,
1445
+
"columns": [
1446
+
"uri"
1447
+
]
1448
+
}
1449
+
},
1450
+
"policies": {},
1451
+
"checkConstraints": {},
1452
+
"isRLSEnabled": false
1453
+
},
1454
+
"public.playlist_tracks": {
1455
+
"name": "playlist_tracks",
1456
+
"schema": "",
1457
+
"columns": {
1458
+
"xata_id": {
1459
+
"name": "xata_id",
1460
+
"type": "text",
1461
+
"primaryKey": true,
1462
+
"notNull": true
1463
+
},
1464
+
"playlist_id": {
1465
+
"name": "playlist_id",
1466
+
"type": "text",
1467
+
"primaryKey": false,
1468
+
"notNull": true
1469
+
},
1470
+
"track_id": {
1471
+
"name": "track_id",
1472
+
"type": "text",
1473
+
"primaryKey": false,
1474
+
"notNull": true
1475
+
},
1476
+
"xata_createdat": {
1477
+
"name": "xata_createdat",
1478
+
"type": "timestamp",
1479
+
"primaryKey": false,
1480
+
"notNull": true,
1481
+
"default": "now()"
1482
+
}
1483
+
},
1484
+
"indexes": {},
1485
+
"foreignKeys": {
1486
+
"playlist_tracks_playlist_id_playlists_xata_id_fk": {
1487
+
"name": "playlist_tracks_playlist_id_playlists_xata_id_fk",
1488
+
"tableFrom": "playlist_tracks",
1489
+
"tableTo": "playlists",
1490
+
"columnsFrom": [
1491
+
"playlist_id"
1492
+
],
1493
+
"columnsTo": [
1494
+
"xata_id"
1495
+
],
1496
+
"onDelete": "no action",
1497
+
"onUpdate": "no action"
1498
+
},
1499
+
"playlist_tracks_track_id_tracks_xata_id_fk": {
1500
+
"name": "playlist_tracks_track_id_tracks_xata_id_fk",
1501
+
"tableFrom": "playlist_tracks",
1502
+
"tableTo": "tracks",
1503
+
"columnsFrom": [
1504
+
"track_id"
1505
+
],
1506
+
"columnsTo": [
1507
+
"xata_id"
1508
+
],
1509
+
"onDelete": "no action",
1510
+
"onUpdate": "no action"
1511
+
}
1512
+
},
1513
+
"compositePrimaryKeys": {},
1514
+
"uniqueConstraints": {},
1515
+
"policies": {},
1516
+
"checkConstraints": {},
1517
+
"isRLSEnabled": false
1518
+
},
1519
+
"public.playlists": {
1520
+
"name": "playlists",
1521
+
"schema": "",
1522
+
"columns": {
1523
+
"xata_id": {
1524
+
"name": "xata_id",
1525
+
"type": "text",
1526
+
"primaryKey": true,
1527
+
"notNull": true
1528
+
},
1529
+
"name": {
1530
+
"name": "name",
1531
+
"type": "text",
1532
+
"primaryKey": false,
1533
+
"notNull": true
1534
+
},
1535
+
"picture": {
1536
+
"name": "picture",
1537
+
"type": "text",
1538
+
"primaryKey": false,
1539
+
"notNull": false
1540
+
},
1541
+
"description": {
1542
+
"name": "description",
1543
+
"type": "text",
1544
+
"primaryKey": false,
1545
+
"notNull": false
1546
+
},
1547
+
"uri": {
1548
+
"name": "uri",
1549
+
"type": "text",
1550
+
"primaryKey": false,
1551
+
"notNull": false
1552
+
},
1553
+
"spotify_link": {
1554
+
"name": "spotify_link",
1555
+
"type": "text",
1556
+
"primaryKey": false,
1557
+
"notNull": false
1558
+
},
1559
+
"tidal_link": {
1560
+
"name": "tidal_link",
1561
+
"type": "text",
1562
+
"primaryKey": false,
1563
+
"notNull": false
1564
+
},
1565
+
"apple_music_link": {
1566
+
"name": "apple_music_link",
1567
+
"type": "text",
1568
+
"primaryKey": false,
1569
+
"notNull": false
1570
+
},
1571
+
"created_by": {
1572
+
"name": "created_by",
1573
+
"type": "text",
1574
+
"primaryKey": false,
1575
+
"notNull": true
1576
+
},
1577
+
"xata_createdat": {
1578
+
"name": "xata_createdat",
1579
+
"type": "timestamp",
1580
+
"primaryKey": false,
1581
+
"notNull": true,
1582
+
"default": "now()"
1583
+
},
1584
+
"xata_updatedat": {
1585
+
"name": "xata_updatedat",
1586
+
"type": "timestamp",
1587
+
"primaryKey": false,
1588
+
"notNull": true,
1589
+
"default": "now()"
1590
+
}
1591
+
},
1592
+
"indexes": {},
1593
+
"foreignKeys": {
1594
+
"playlists_created_by_users_xata_id_fk": {
1595
+
"name": "playlists_created_by_users_xata_id_fk",
1596
+
"tableFrom": "playlists",
1597
+
"tableTo": "users",
1598
+
"columnsFrom": [
1599
+
"created_by"
1600
+
],
1601
+
"columnsTo": [
1602
+
"xata_id"
1603
+
],
1604
+
"onDelete": "no action",
1605
+
"onUpdate": "no action"
1606
+
}
1607
+
},
1608
+
"compositePrimaryKeys": {},
1609
+
"uniqueConstraints": {
1610
+
"playlists_uri_unique": {
1611
+
"name": "playlists_uri_unique",
1612
+
"nullsNotDistinct": false,
1613
+
"columns": [
1614
+
"uri"
1615
+
]
1616
+
}
1617
+
},
1618
+
"policies": {},
1619
+
"checkConstraints": {},
1620
+
"isRLSEnabled": false
1621
+
},
1622
+
"public.profile_shouts": {
1623
+
"name": "profile_shouts",
1624
+
"schema": "",
1625
+
"columns": {
1626
+
"xata_id": {
1627
+
"name": "xata_id",
1628
+
"type": "text",
1629
+
"primaryKey": true,
1630
+
"notNull": true
1631
+
},
1632
+
"user_id": {
1633
+
"name": "user_id",
1634
+
"type": "text",
1635
+
"primaryKey": false,
1636
+
"notNull": true
1637
+
},
1638
+
"shout_id": {
1639
+
"name": "shout_id",
1640
+
"type": "text",
1641
+
"primaryKey": false,
1642
+
"notNull": true
1643
+
},
1644
+
"xata_createdat": {
1645
+
"name": "xata_createdat",
1646
+
"type": "timestamp",
1647
+
"primaryKey": false,
1648
+
"notNull": true,
1649
+
"default": "now()"
1650
+
}
1651
+
},
1652
+
"indexes": {},
1653
+
"foreignKeys": {
1654
+
"profile_shouts_user_id_users_xata_id_fk": {
1655
+
"name": "profile_shouts_user_id_users_xata_id_fk",
1656
+
"tableFrom": "profile_shouts",
1657
+
"tableTo": "users",
1658
+
"columnsFrom": [
1659
+
"user_id"
1660
+
],
1661
+
"columnsTo": [
1662
+
"xata_id"
1663
+
],
1664
+
"onDelete": "no action",
1665
+
"onUpdate": "no action"
1666
+
},
1667
+
"profile_shouts_shout_id_shouts_xata_id_fk": {
1668
+
"name": "profile_shouts_shout_id_shouts_xata_id_fk",
1669
+
"tableFrom": "profile_shouts",
1670
+
"tableTo": "shouts",
1671
+
"columnsFrom": [
1672
+
"shout_id"
1673
+
],
1674
+
"columnsTo": [
1675
+
"xata_id"
1676
+
],
1677
+
"onDelete": "no action",
1678
+
"onUpdate": "no action"
1679
+
}
1680
+
},
1681
+
"compositePrimaryKeys": {},
1682
+
"uniqueConstraints": {},
1683
+
"policies": {},
1684
+
"checkConstraints": {},
1685
+
"isRLSEnabled": false
1686
+
},
1687
+
"public.queue_tracks": {
1688
+
"name": "queue_tracks",
1689
+
"schema": "",
1690
+
"columns": {
1691
+
"xata_id": {
1692
+
"name": "xata_id",
1693
+
"type": "text",
1694
+
"primaryKey": true,
1695
+
"notNull": true
1696
+
},
1697
+
"user_id": {
1698
+
"name": "user_id",
1699
+
"type": "text",
1700
+
"primaryKey": false,
1701
+
"notNull": true
1702
+
},
1703
+
"track_id": {
1704
+
"name": "track_id",
1705
+
"type": "text",
1706
+
"primaryKey": false,
1707
+
"notNull": true
1708
+
},
1709
+
"position": {
1710
+
"name": "position",
1711
+
"type": "integer",
1712
+
"primaryKey": false,
1713
+
"notNull": true
1714
+
},
1715
+
"file_uri": {
1716
+
"name": "file_uri",
1717
+
"type": "text",
1718
+
"primaryKey": false,
1719
+
"notNull": true
1720
+
},
1721
+
"xata_version": {
1722
+
"name": "xata_version",
1723
+
"type": "integer",
1724
+
"primaryKey": false,
1725
+
"notNull": true,
1726
+
"default": 0
1727
+
},
1728
+
"xata_createdat": {
1729
+
"name": "xata_createdat",
1730
+
"type": "timestamp",
1731
+
"primaryKey": false,
1732
+
"notNull": true,
1733
+
"default": "now()"
1734
+
},
1735
+
"xata_updatedat": {
1736
+
"name": "xata_updatedat",
1737
+
"type": "timestamp",
1738
+
"primaryKey": false,
1739
+
"notNull": true,
1740
+
"default": "now()"
1741
+
}
1742
+
},
1743
+
"indexes": {},
1744
+
"foreignKeys": {
1745
+
"queue_tracks_user_id_users_xata_id_fk": {
1746
+
"name": "queue_tracks_user_id_users_xata_id_fk",
1747
+
"tableFrom": "queue_tracks",
1748
+
"tableTo": "users",
1749
+
"columnsFrom": [
1750
+
"user_id"
1751
+
],
1752
+
"columnsTo": [
1753
+
"xata_id"
1754
+
],
1755
+
"onDelete": "no action",
1756
+
"onUpdate": "no action"
1757
+
},
1758
+
"queue_tracks_track_id_tracks_xata_id_fk": {
1759
+
"name": "queue_tracks_track_id_tracks_xata_id_fk",
1760
+
"tableFrom": "queue_tracks",
1761
+
"tableTo": "tracks",
1762
+
"columnsFrom": [
1763
+
"track_id"
1764
+
],
1765
+
"columnsTo": [
1766
+
"xata_id"
1767
+
],
1768
+
"onDelete": "no action",
1769
+
"onUpdate": "no action"
1770
+
}
1771
+
},
1772
+
"compositePrimaryKeys": {},
1773
+
"uniqueConstraints": {},
1774
+
"policies": {},
1775
+
"checkConstraints": {},
1776
+
"isRLSEnabled": false
1777
+
},
1778
+
"public.scrobbles": {
1779
+
"name": "scrobbles",
1780
+
"schema": "",
1781
+
"columns": {
1782
+
"xata_id": {
1783
+
"name": "xata_id",
1784
+
"type": "text",
1785
+
"primaryKey": true,
1786
+
"notNull": true
1787
+
},
1788
+
"user_id": {
1789
+
"name": "user_id",
1790
+
"type": "text",
1791
+
"primaryKey": false,
1792
+
"notNull": false
1793
+
},
1794
+
"track_id": {
1795
+
"name": "track_id",
1796
+
"type": "text",
1797
+
"primaryKey": false,
1798
+
"notNull": false
1799
+
},
1800
+
"album_id": {
1801
+
"name": "album_id",
1802
+
"type": "text",
1803
+
"primaryKey": false,
1804
+
"notNull": false
1805
+
},
1806
+
"artist_id": {
1807
+
"name": "artist_id",
1808
+
"type": "text",
1809
+
"primaryKey": false,
1810
+
"notNull": false
1811
+
},
1812
+
"uri": {
1813
+
"name": "uri",
1814
+
"type": "text",
1815
+
"primaryKey": false,
1816
+
"notNull": false
1817
+
},
1818
+
"xata_createdat": {
1819
+
"name": "xata_createdat",
1820
+
"type": "timestamp",
1821
+
"primaryKey": false,
1822
+
"notNull": true,
1823
+
"default": "now()"
1824
+
},
1825
+
"xata_updatedat": {
1826
+
"name": "xata_updatedat",
1827
+
"type": "timestamp",
1828
+
"primaryKey": false,
1829
+
"notNull": true,
1830
+
"default": "now()"
1831
+
},
1832
+
"xata_version": {
1833
+
"name": "xata_version",
1834
+
"type": "integer",
1835
+
"primaryKey": false,
1836
+
"notNull": false
1837
+
},
1838
+
"timestamp": {
1839
+
"name": "timestamp",
1840
+
"type": "timestamp",
1841
+
"primaryKey": false,
1842
+
"notNull": true,
1843
+
"default": "now()"
1844
+
}
1845
+
},
1846
+
"indexes": {},
1847
+
"foreignKeys": {
1848
+
"scrobbles_user_id_users_xata_id_fk": {
1849
+
"name": "scrobbles_user_id_users_xata_id_fk",
1850
+
"tableFrom": "scrobbles",
1851
+
"tableTo": "users",
1852
+
"columnsFrom": [
1853
+
"user_id"
1854
+
],
1855
+
"columnsTo": [
1856
+
"xata_id"
1857
+
],
1858
+
"onDelete": "no action",
1859
+
"onUpdate": "no action"
1860
+
},
1861
+
"scrobbles_track_id_tracks_xata_id_fk": {
1862
+
"name": "scrobbles_track_id_tracks_xata_id_fk",
1863
+
"tableFrom": "scrobbles",
1864
+
"tableTo": "tracks",
1865
+
"columnsFrom": [
1866
+
"track_id"
1867
+
],
1868
+
"columnsTo": [
1869
+
"xata_id"
1870
+
],
1871
+
"onDelete": "no action",
1872
+
"onUpdate": "no action"
1873
+
},
1874
+
"scrobbles_album_id_albums_xata_id_fk": {
1875
+
"name": "scrobbles_album_id_albums_xata_id_fk",
1876
+
"tableFrom": "scrobbles",
1877
+
"tableTo": "albums",
1878
+
"columnsFrom": [
1879
+
"album_id"
1880
+
],
1881
+
"columnsTo": [
1882
+
"xata_id"
1883
+
],
1884
+
"onDelete": "no action",
1885
+
"onUpdate": "no action"
1886
+
},
1887
+
"scrobbles_artist_id_artists_xata_id_fk": {
1888
+
"name": "scrobbles_artist_id_artists_xata_id_fk",
1889
+
"tableFrom": "scrobbles",
1890
+
"tableTo": "artists",
1891
+
"columnsFrom": [
1892
+
"artist_id"
1893
+
],
1894
+
"columnsTo": [
1895
+
"xata_id"
1896
+
],
1897
+
"onDelete": "no action",
1898
+
"onUpdate": "no action"
1899
+
}
1900
+
},
1901
+
"compositePrimaryKeys": {},
1902
+
"uniqueConstraints": {
1903
+
"scrobbles_uri_unique": {
1904
+
"name": "scrobbles_uri_unique",
1905
+
"nullsNotDistinct": false,
1906
+
"columns": [
1907
+
"uri"
1908
+
]
1909
+
}
1910
+
},
1911
+
"policies": {},
1912
+
"checkConstraints": {},
1913
+
"isRLSEnabled": false
1914
+
},
1915
+
"public.shout_likes": {
1916
+
"name": "shout_likes",
1917
+
"schema": "",
1918
+
"columns": {
1919
+
"xata_id": {
1920
+
"name": "xata_id",
1921
+
"type": "text",
1922
+
"primaryKey": true,
1923
+
"notNull": true
1924
+
},
1925
+
"user_id": {
1926
+
"name": "user_id",
1927
+
"type": "text",
1928
+
"primaryKey": false,
1929
+
"notNull": true
1930
+
},
1931
+
"shout_id": {
1932
+
"name": "shout_id",
1933
+
"type": "text",
1934
+
"primaryKey": false,
1935
+
"notNull": true
1936
+
},
1937
+
"xata_createdat": {
1938
+
"name": "xata_createdat",
1939
+
"type": "timestamp",
1940
+
"primaryKey": false,
1941
+
"notNull": true,
1942
+
"default": "now()"
1943
+
},
1944
+
"uri": {
1945
+
"name": "uri",
1946
+
"type": "text",
1947
+
"primaryKey": false,
1948
+
"notNull": true
1949
+
}
1950
+
},
1951
+
"indexes": {},
1952
+
"foreignKeys": {
1953
+
"shout_likes_user_id_users_xata_id_fk": {
1954
+
"name": "shout_likes_user_id_users_xata_id_fk",
1955
+
"tableFrom": "shout_likes",
1956
+
"tableTo": "users",
1957
+
"columnsFrom": [
1958
+
"user_id"
1959
+
],
1960
+
"columnsTo": [
1961
+
"xata_id"
1962
+
],
1963
+
"onDelete": "no action",
1964
+
"onUpdate": "no action"
1965
+
},
1966
+
"shout_likes_shout_id_shouts_xata_id_fk": {
1967
+
"name": "shout_likes_shout_id_shouts_xata_id_fk",
1968
+
"tableFrom": "shout_likes",
1969
+
"tableTo": "shouts",
1970
+
"columnsFrom": [
1971
+
"shout_id"
1972
+
],
1973
+
"columnsTo": [
1974
+
"xata_id"
1975
+
],
1976
+
"onDelete": "no action",
1977
+
"onUpdate": "no action"
1978
+
}
1979
+
},
1980
+
"compositePrimaryKeys": {},
1981
+
"uniqueConstraints": {
1982
+
"shout_likes_uri_unique": {
1983
+
"name": "shout_likes_uri_unique",
1984
+
"nullsNotDistinct": false,
1985
+
"columns": [
1986
+
"uri"
1987
+
]
1988
+
}
1989
+
},
1990
+
"policies": {},
1991
+
"checkConstraints": {},
1992
+
"isRLSEnabled": false
1993
+
},
1994
+
"public.shout_reports": {
1995
+
"name": "shout_reports",
1996
+
"schema": "",
1997
+
"columns": {
1998
+
"xata_id": {
1999
+
"name": "xata_id",
2000
+
"type": "text",
2001
+
"primaryKey": true,
2002
+
"notNull": true
2003
+
},
2004
+
"user_id": {
2005
+
"name": "user_id",
2006
+
"type": "text",
2007
+
"primaryKey": false,
2008
+
"notNull": true
2009
+
},
2010
+
"shout_id": {
2011
+
"name": "shout_id",
2012
+
"type": "text",
2013
+
"primaryKey": false,
2014
+
"notNull": true
2015
+
},
2016
+
"xata_createdat": {
2017
+
"name": "xata_createdat",
2018
+
"type": "timestamp",
2019
+
"primaryKey": false,
2020
+
"notNull": true,
2021
+
"default": "now()"
2022
+
}
2023
+
},
2024
+
"indexes": {},
2025
+
"foreignKeys": {
2026
+
"shout_reports_user_id_users_xata_id_fk": {
2027
+
"name": "shout_reports_user_id_users_xata_id_fk",
2028
+
"tableFrom": "shout_reports",
2029
+
"tableTo": "users",
2030
+
"columnsFrom": [
2031
+
"user_id"
2032
+
],
2033
+
"columnsTo": [
2034
+
"xata_id"
2035
+
],
2036
+
"onDelete": "no action",
2037
+
"onUpdate": "no action"
2038
+
},
2039
+
"shout_reports_shout_id_shouts_xata_id_fk": {
2040
+
"name": "shout_reports_shout_id_shouts_xata_id_fk",
2041
+
"tableFrom": "shout_reports",
2042
+
"tableTo": "shouts",
2043
+
"columnsFrom": [
2044
+
"shout_id"
2045
+
],
2046
+
"columnsTo": [
2047
+
"xata_id"
2048
+
],
2049
+
"onDelete": "no action",
2050
+
"onUpdate": "no action"
2051
+
}
2052
+
},
2053
+
"compositePrimaryKeys": {},
2054
+
"uniqueConstraints": {},
2055
+
"policies": {},
2056
+
"checkConstraints": {},
2057
+
"isRLSEnabled": false
2058
+
},
2059
+
"public.shouts": {
2060
+
"name": "shouts",
2061
+
"schema": "",
2062
+
"columns": {
2063
+
"xata_id": {
2064
+
"name": "xata_id",
2065
+
"type": "text",
2066
+
"primaryKey": true,
2067
+
"notNull": true
2068
+
},
2069
+
"content": {
2070
+
"name": "content",
2071
+
"type": "text",
2072
+
"primaryKey": false,
2073
+
"notNull": true
2074
+
},
2075
+
"track_id": {
2076
+
"name": "track_id",
2077
+
"type": "text",
2078
+
"primaryKey": false,
2079
+
"notNull": false
2080
+
},
2081
+
"artist_id": {
2082
+
"name": "artist_id",
2083
+
"type": "text",
2084
+
"primaryKey": false,
2085
+
"notNull": false
2086
+
},
2087
+
"album_id": {
2088
+
"name": "album_id",
2089
+
"type": "text",
2090
+
"primaryKey": false,
2091
+
"notNull": false
2092
+
},
2093
+
"scrobble_id": {
2094
+
"name": "scrobble_id",
2095
+
"type": "text",
2096
+
"primaryKey": false,
2097
+
"notNull": false
2098
+
},
2099
+
"uri": {
2100
+
"name": "uri",
2101
+
"type": "text",
2102
+
"primaryKey": false,
2103
+
"notNull": true
2104
+
},
2105
+
"author_id": {
2106
+
"name": "author_id",
2107
+
"type": "text",
2108
+
"primaryKey": false,
2109
+
"notNull": true
2110
+
},
2111
+
"parent_id": {
2112
+
"name": "parent_id",
2113
+
"type": "text",
2114
+
"primaryKey": false,
2115
+
"notNull": false
2116
+
},
2117
+
"xata_createdat": {
2118
+
"name": "xata_createdat",
2119
+
"type": "timestamp",
2120
+
"primaryKey": false,
2121
+
"notNull": true,
2122
+
"default": "now()"
2123
+
},
2124
+
"xata_updatedat": {
2125
+
"name": "xata_updatedat",
2126
+
"type": "timestamp",
2127
+
"primaryKey": false,
2128
+
"notNull": true,
2129
+
"default": "now()"
2130
+
}
2131
+
},
2132
+
"indexes": {},
2133
+
"foreignKeys": {
2134
+
"shouts_track_id_tracks_xata_id_fk": {
2135
+
"name": "shouts_track_id_tracks_xata_id_fk",
2136
+
"tableFrom": "shouts",
2137
+
"tableTo": "tracks",
2138
+
"columnsFrom": [
2139
+
"track_id"
2140
+
],
2141
+
"columnsTo": [
2142
+
"xata_id"
2143
+
],
2144
+
"onDelete": "no action",
2145
+
"onUpdate": "no action"
2146
+
},
2147
+
"shouts_artist_id_users_xata_id_fk": {
2148
+
"name": "shouts_artist_id_users_xata_id_fk",
2149
+
"tableFrom": "shouts",
2150
+
"tableTo": "users",
2151
+
"columnsFrom": [
2152
+
"artist_id"
2153
+
],
2154
+
"columnsTo": [
2155
+
"xata_id"
2156
+
],
2157
+
"onDelete": "no action",
2158
+
"onUpdate": "no action"
2159
+
},
2160
+
"shouts_album_id_albums_xata_id_fk": {
2161
+
"name": "shouts_album_id_albums_xata_id_fk",
2162
+
"tableFrom": "shouts",
2163
+
"tableTo": "albums",
2164
+
"columnsFrom": [
2165
+
"album_id"
2166
+
],
2167
+
"columnsTo": [
2168
+
"xata_id"
2169
+
],
2170
+
"onDelete": "no action",
2171
+
"onUpdate": "no action"
2172
+
},
2173
+
"shouts_scrobble_id_scrobbles_xata_id_fk": {
2174
+
"name": "shouts_scrobble_id_scrobbles_xata_id_fk",
2175
+
"tableFrom": "shouts",
2176
+
"tableTo": "scrobbles",
2177
+
"columnsFrom": [
2178
+
"scrobble_id"
2179
+
],
2180
+
"columnsTo": [
2181
+
"xata_id"
2182
+
],
2183
+
"onDelete": "no action",
2184
+
"onUpdate": "no action"
2185
+
},
2186
+
"shouts_author_id_users_xata_id_fk": {
2187
+
"name": "shouts_author_id_users_xata_id_fk",
2188
+
"tableFrom": "shouts",
2189
+
"tableTo": "users",
2190
+
"columnsFrom": [
2191
+
"author_id"
2192
+
],
2193
+
"columnsTo": [
2194
+
"xata_id"
2195
+
],
2196
+
"onDelete": "no action",
2197
+
"onUpdate": "no action"
2198
+
},
2199
+
"shouts_parent_id_shouts_xata_id_fk": {
2200
+
"name": "shouts_parent_id_shouts_xata_id_fk",
2201
+
"tableFrom": "shouts",
2202
+
"tableTo": "shouts",
2203
+
"columnsFrom": [
2204
+
"parent_id"
2205
+
],
2206
+
"columnsTo": [
2207
+
"xata_id"
2208
+
],
2209
+
"onDelete": "no action",
2210
+
"onUpdate": "no action"
2211
+
}
2212
+
},
2213
+
"compositePrimaryKeys": {},
2214
+
"uniqueConstraints": {
2215
+
"shouts_uri_unique": {
2216
+
"name": "shouts_uri_unique",
2217
+
"nullsNotDistinct": false,
2218
+
"columns": [
2219
+
"uri"
2220
+
]
2221
+
}
2222
+
},
2223
+
"policies": {},
2224
+
"checkConstraints": {},
2225
+
"isRLSEnabled": false
2226
+
},
2227
+
"public.spotify_accounts": {
2228
+
"name": "spotify_accounts",
2229
+
"schema": "",
2230
+
"columns": {
2231
+
"xata_id": {
2232
+
"name": "xata_id",
2233
+
"type": "text",
2234
+
"primaryKey": true,
2235
+
"notNull": true
2236
+
},
2237
+
"xata_version": {
2238
+
"name": "xata_version",
2239
+
"type": "integer",
2240
+
"primaryKey": false,
2241
+
"notNull": false
2242
+
},
2243
+
"email": {
2244
+
"name": "email",
2245
+
"type": "text",
2246
+
"primaryKey": false,
2247
+
"notNull": true
2248
+
},
2249
+
"user_id": {
2250
+
"name": "user_id",
2251
+
"type": "text",
2252
+
"primaryKey": false,
2253
+
"notNull": true
2254
+
},
2255
+
"is_beta_user": {
2256
+
"name": "is_beta_user",
2257
+
"type": "boolean",
2258
+
"primaryKey": false,
2259
+
"notNull": true,
2260
+
"default": false
2261
+
},
2262
+
"xata_createdat": {
2263
+
"name": "xata_createdat",
2264
+
"type": "timestamp",
2265
+
"primaryKey": false,
2266
+
"notNull": true,
2267
+
"default": "now()"
2268
+
},
2269
+
"xata_updatedat": {
2270
+
"name": "xata_updatedat",
2271
+
"type": "timestamp",
2272
+
"primaryKey": false,
2273
+
"notNull": true,
2274
+
"default": "now()"
2275
+
}
2276
+
},
2277
+
"indexes": {},
2278
+
"foreignKeys": {
2279
+
"spotify_accounts_user_id_users_xata_id_fk": {
2280
+
"name": "spotify_accounts_user_id_users_xata_id_fk",
2281
+
"tableFrom": "spotify_accounts",
2282
+
"tableTo": "users",
2283
+
"columnsFrom": [
2284
+
"user_id"
2285
+
],
2286
+
"columnsTo": [
2287
+
"xata_id"
2288
+
],
2289
+
"onDelete": "no action",
2290
+
"onUpdate": "no action"
2291
+
}
2292
+
},
2293
+
"compositePrimaryKeys": {},
2294
+
"uniqueConstraints": {},
2295
+
"policies": {},
2296
+
"checkConstraints": {},
2297
+
"isRLSEnabled": false
2298
+
},
2299
+
"public.spotify_tokens": {
2300
+
"name": "spotify_tokens",
2301
+
"schema": "",
2302
+
"columns": {
2303
+
"xata_id": {
2304
+
"name": "xata_id",
2305
+
"type": "text",
2306
+
"primaryKey": true,
2307
+
"notNull": true
2308
+
},
2309
+
"xata_version": {
2310
+
"name": "xata_version",
2311
+
"type": "integer",
2312
+
"primaryKey": false,
2313
+
"notNull": false
2314
+
},
2315
+
"access_token": {
2316
+
"name": "access_token",
2317
+
"type": "text",
2318
+
"primaryKey": false,
2319
+
"notNull": true
2320
+
},
2321
+
"refresh_token": {
2322
+
"name": "refresh_token",
2323
+
"type": "text",
2324
+
"primaryKey": false,
2325
+
"notNull": true
2326
+
},
2327
+
"user_id": {
2328
+
"name": "user_id",
2329
+
"type": "text",
2330
+
"primaryKey": false,
2331
+
"notNull": true
2332
+
},
2333
+
"xata_createdat": {
2334
+
"name": "xata_createdat",
2335
+
"type": "timestamp",
2336
+
"primaryKey": false,
2337
+
"notNull": true,
2338
+
"default": "now()"
2339
+
},
2340
+
"xata_updatedat": {
2341
+
"name": "xata_updatedat",
2342
+
"type": "timestamp",
2343
+
"primaryKey": false,
2344
+
"notNull": true,
2345
+
"default": "now()"
2346
+
}
2347
+
},
2348
+
"indexes": {},
2349
+
"foreignKeys": {
2350
+
"spotify_tokens_user_id_users_xata_id_fk": {
2351
+
"name": "spotify_tokens_user_id_users_xata_id_fk",
2352
+
"tableFrom": "spotify_tokens",
2353
+
"tableTo": "users",
2354
+
"columnsFrom": [
2355
+
"user_id"
2356
+
],
2357
+
"columnsTo": [
2358
+
"xata_id"
2359
+
],
2360
+
"onDelete": "no action",
2361
+
"onUpdate": "no action"
2362
+
}
2363
+
},
2364
+
"compositePrimaryKeys": {},
2365
+
"uniqueConstraints": {},
2366
+
"policies": {},
2367
+
"checkConstraints": {},
2368
+
"isRLSEnabled": false
2369
+
},
2370
+
"public.tracks": {
2371
+
"name": "tracks",
2372
+
"schema": "",
2373
+
"columns": {
2374
+
"xata_id": {
2375
+
"name": "xata_id",
2376
+
"type": "text",
2377
+
"primaryKey": true,
2378
+
"notNull": true
2379
+
},
2380
+
"title": {
2381
+
"name": "title",
2382
+
"type": "text",
2383
+
"primaryKey": false,
2384
+
"notNull": true
2385
+
},
2386
+
"artist": {
2387
+
"name": "artist",
2388
+
"type": "text",
2389
+
"primaryKey": false,
2390
+
"notNull": true
2391
+
},
2392
+
"album_artist": {
2393
+
"name": "album_artist",
2394
+
"type": "text",
2395
+
"primaryKey": false,
2396
+
"notNull": true
2397
+
},
2398
+
"album_art": {
2399
+
"name": "album_art",
2400
+
"type": "text",
2401
+
"primaryKey": false,
2402
+
"notNull": false
2403
+
},
2404
+
"album": {
2405
+
"name": "album",
2406
+
"type": "text",
2407
+
"primaryKey": false,
2408
+
"notNull": true
2409
+
},
2410
+
"track_number": {
2411
+
"name": "track_number",
2412
+
"type": "integer",
2413
+
"primaryKey": false,
2414
+
"notNull": false
2415
+
},
2416
+
"duration": {
2417
+
"name": "duration",
2418
+
"type": "integer",
2419
+
"primaryKey": false,
2420
+
"notNull": true
2421
+
},
2422
+
"mb_id": {
2423
+
"name": "mb_id",
2424
+
"type": "text",
2425
+
"primaryKey": false,
2426
+
"notNull": false
2427
+
},
2428
+
"youtube_link": {
2429
+
"name": "youtube_link",
2430
+
"type": "text",
2431
+
"primaryKey": false,
2432
+
"notNull": false
2433
+
},
2434
+
"spotify_link": {
2435
+
"name": "spotify_link",
2436
+
"type": "text",
2437
+
"primaryKey": false,
2438
+
"notNull": false
2439
+
},
2440
+
"apple_music_link": {
2441
+
"name": "apple_music_link",
2442
+
"type": "text",
2443
+
"primaryKey": false,
2444
+
"notNull": false
2445
+
},
2446
+
"tidal_link": {
2447
+
"name": "tidal_link",
2448
+
"type": "text",
2449
+
"primaryKey": false,
2450
+
"notNull": false
2451
+
},
2452
+
"sha256": {
2453
+
"name": "sha256",
2454
+
"type": "text",
2455
+
"primaryKey": false,
2456
+
"notNull": true
2457
+
},
2458
+
"disc_number": {
2459
+
"name": "disc_number",
2460
+
"type": "integer",
2461
+
"primaryKey": false,
2462
+
"notNull": false
2463
+
},
2464
+
"lyrics": {
2465
+
"name": "lyrics",
2466
+
"type": "text",
2467
+
"primaryKey": false,
2468
+
"notNull": false
2469
+
},
2470
+
"composer": {
2471
+
"name": "composer",
2472
+
"type": "text",
2473
+
"primaryKey": false,
2474
+
"notNull": false
2475
+
},
2476
+
"genre": {
2477
+
"name": "genre",
2478
+
"type": "text",
2479
+
"primaryKey": false,
2480
+
"notNull": false
2481
+
},
2482
+
"label": {
2483
+
"name": "label",
2484
+
"type": "text",
2485
+
"primaryKey": false,
2486
+
"notNull": false
2487
+
},
2488
+
"copyright_message": {
2489
+
"name": "copyright_message",
2490
+
"type": "text",
2491
+
"primaryKey": false,
2492
+
"notNull": false
2493
+
},
2494
+
"uri": {
2495
+
"name": "uri",
2496
+
"type": "text",
2497
+
"primaryKey": false,
2498
+
"notNull": false
2499
+
},
2500
+
"album_uri": {
2501
+
"name": "album_uri",
2502
+
"type": "text",
2503
+
"primaryKey": false,
2504
+
"notNull": false
2505
+
},
2506
+
"artist_uri": {
2507
+
"name": "artist_uri",
2508
+
"type": "text",
2509
+
"primaryKey": false,
2510
+
"notNull": false
2511
+
},
2512
+
"xata_createdat": {
2513
+
"name": "xata_createdat",
2514
+
"type": "timestamp",
2515
+
"primaryKey": false,
2516
+
"notNull": true,
2517
+
"default": "now()"
2518
+
},
2519
+
"xata_updatedat": {
2520
+
"name": "xata_updatedat",
2521
+
"type": "timestamp",
2522
+
"primaryKey": false,
2523
+
"notNull": true,
2524
+
"default": "now()"
2525
+
},
2526
+
"xata_version": {
2527
+
"name": "xata_version",
2528
+
"type": "integer",
2529
+
"primaryKey": false,
2530
+
"notNull": false
2531
+
}
2532
+
},
2533
+
"indexes": {},
2534
+
"foreignKeys": {},
2535
+
"compositePrimaryKeys": {},
2536
+
"uniqueConstraints": {
2537
+
"tracks_mb_id_unique": {
2538
+
"name": "tracks_mb_id_unique",
2539
+
"nullsNotDistinct": false,
2540
+
"columns": [
2541
+
"mb_id"
2542
+
]
2543
+
},
2544
+
"tracks_youtube_link_unique": {
2545
+
"name": "tracks_youtube_link_unique",
2546
+
"nullsNotDistinct": false,
2547
+
"columns": [
2548
+
"youtube_link"
2549
+
]
2550
+
},
2551
+
"tracks_spotify_link_unique": {
2552
+
"name": "tracks_spotify_link_unique",
2553
+
"nullsNotDistinct": false,
2554
+
"columns": [
2555
+
"spotify_link"
2556
+
]
2557
+
},
2558
+
"tracks_apple_music_link_unique": {
2559
+
"name": "tracks_apple_music_link_unique",
2560
+
"nullsNotDistinct": false,
2561
+
"columns": [
2562
+
"apple_music_link"
2563
+
]
2564
+
},
2565
+
"tracks_tidal_link_unique": {
2566
+
"name": "tracks_tidal_link_unique",
2567
+
"nullsNotDistinct": false,
2568
+
"columns": [
2569
+
"tidal_link"
2570
+
]
2571
+
},
2572
+
"tracks_sha256_unique": {
2573
+
"name": "tracks_sha256_unique",
2574
+
"nullsNotDistinct": false,
2575
+
"columns": [
2576
+
"sha256"
2577
+
]
2578
+
},
2579
+
"tracks_uri_unique": {
2580
+
"name": "tracks_uri_unique",
2581
+
"nullsNotDistinct": false,
2582
+
"columns": [
2583
+
"uri"
2584
+
]
2585
+
}
2586
+
},
2587
+
"policies": {},
2588
+
"checkConstraints": {},
2589
+
"isRLSEnabled": false
2590
+
},
2591
+
"public.user_albums": {
2592
+
"name": "user_albums",
2593
+
"schema": "",
2594
+
"columns": {
2595
+
"xata_id": {
2596
+
"name": "xata_id",
2597
+
"type": "text",
2598
+
"primaryKey": true,
2599
+
"notNull": true
2600
+
},
2601
+
"user_id": {
2602
+
"name": "user_id",
2603
+
"type": "text",
2604
+
"primaryKey": false,
2605
+
"notNull": true
2606
+
},
2607
+
"album_id": {
2608
+
"name": "album_id",
2609
+
"type": "text",
2610
+
"primaryKey": false,
2611
+
"notNull": true
2612
+
},
2613
+
"xata_createdat": {
2614
+
"name": "xata_createdat",
2615
+
"type": "timestamp",
2616
+
"primaryKey": false,
2617
+
"notNull": true,
2618
+
"default": "now()"
2619
+
},
2620
+
"xata_updatedat": {
2621
+
"name": "xata_updatedat",
2622
+
"type": "timestamp",
2623
+
"primaryKey": false,
2624
+
"notNull": true,
2625
+
"default": "now()"
2626
+
},
2627
+
"xata_version": {
2628
+
"name": "xata_version",
2629
+
"type": "integer",
2630
+
"primaryKey": false,
2631
+
"notNull": false
2632
+
},
2633
+
"scrobbles": {
2634
+
"name": "scrobbles",
2635
+
"type": "integer",
2636
+
"primaryKey": false,
2637
+
"notNull": false
2638
+
},
2639
+
"uri": {
2640
+
"name": "uri",
2641
+
"type": "text",
2642
+
"primaryKey": false,
2643
+
"notNull": true
2644
+
}
2645
+
},
2646
+
"indexes": {},
2647
+
"foreignKeys": {
2648
+
"user_albums_user_id_users_xata_id_fk": {
2649
+
"name": "user_albums_user_id_users_xata_id_fk",
2650
+
"tableFrom": "user_albums",
2651
+
"tableTo": "users",
2652
+
"columnsFrom": [
2653
+
"user_id"
2654
+
],
2655
+
"columnsTo": [
2656
+
"xata_id"
2657
+
],
2658
+
"onDelete": "no action",
2659
+
"onUpdate": "no action"
2660
+
},
2661
+
"user_albums_album_id_albums_xata_id_fk": {
2662
+
"name": "user_albums_album_id_albums_xata_id_fk",
2663
+
"tableFrom": "user_albums",
2664
+
"tableTo": "albums",
2665
+
"columnsFrom": [
2666
+
"album_id"
2667
+
],
2668
+
"columnsTo": [
2669
+
"xata_id"
2670
+
],
2671
+
"onDelete": "no action",
2672
+
"onUpdate": "no action"
2673
+
}
2674
+
},
2675
+
"compositePrimaryKeys": {},
2676
+
"uniqueConstraints": {
2677
+
"user_albums_uri_unique": {
2678
+
"name": "user_albums_uri_unique",
2679
+
"nullsNotDistinct": false,
2680
+
"columns": [
2681
+
"uri"
2682
+
]
2683
+
}
2684
+
},
2685
+
"policies": {},
2686
+
"checkConstraints": {},
2687
+
"isRLSEnabled": false
2688
+
},
2689
+
"public.user_artists": {
2690
+
"name": "user_artists",
2691
+
"schema": "",
2692
+
"columns": {
2693
+
"xata_id": {
2694
+
"name": "xata_id",
2695
+
"type": "text",
2696
+
"primaryKey": true,
2697
+
"notNull": true
2698
+
},
2699
+
"user_id": {
2700
+
"name": "user_id",
2701
+
"type": "text",
2702
+
"primaryKey": false,
2703
+
"notNull": true
2704
+
},
2705
+
"artist_id": {
2706
+
"name": "artist_id",
2707
+
"type": "text",
2708
+
"primaryKey": false,
2709
+
"notNull": true
2710
+
},
2711
+
"xata_createdat": {
2712
+
"name": "xata_createdat",
2713
+
"type": "timestamp",
2714
+
"primaryKey": false,
2715
+
"notNull": true,
2716
+
"default": "now()"
2717
+
},
2718
+
"xata_updatedat": {
2719
+
"name": "xata_updatedat",
2720
+
"type": "timestamp",
2721
+
"primaryKey": false,
2722
+
"notNull": true,
2723
+
"default": "now()"
2724
+
},
2725
+
"xata_version": {
2726
+
"name": "xata_version",
2727
+
"type": "integer",
2728
+
"primaryKey": false,
2729
+
"notNull": false
2730
+
},
2731
+
"scrobbles": {
2732
+
"name": "scrobbles",
2733
+
"type": "integer",
2734
+
"primaryKey": false,
2735
+
"notNull": false
2736
+
},
2737
+
"uri": {
2738
+
"name": "uri",
2739
+
"type": "text",
2740
+
"primaryKey": false,
2741
+
"notNull": true
2742
+
}
2743
+
},
2744
+
"indexes": {},
2745
+
"foreignKeys": {
2746
+
"user_artists_user_id_users_xata_id_fk": {
2747
+
"name": "user_artists_user_id_users_xata_id_fk",
2748
+
"tableFrom": "user_artists",
2749
+
"tableTo": "users",
2750
+
"columnsFrom": [
2751
+
"user_id"
2752
+
],
2753
+
"columnsTo": [
2754
+
"xata_id"
2755
+
],
2756
+
"onDelete": "no action",
2757
+
"onUpdate": "no action"
2758
+
},
2759
+
"user_artists_artist_id_artists_xata_id_fk": {
2760
+
"name": "user_artists_artist_id_artists_xata_id_fk",
2761
+
"tableFrom": "user_artists",
2762
+
"tableTo": "artists",
2763
+
"columnsFrom": [
2764
+
"artist_id"
2765
+
],
2766
+
"columnsTo": [
2767
+
"xata_id"
2768
+
],
2769
+
"onDelete": "no action",
2770
+
"onUpdate": "no action"
2771
+
}
2772
+
},
2773
+
"compositePrimaryKeys": {},
2774
+
"uniqueConstraints": {
2775
+
"user_artists_uri_unique": {
2776
+
"name": "user_artists_uri_unique",
2777
+
"nullsNotDistinct": false,
2778
+
"columns": [
2779
+
"uri"
2780
+
]
2781
+
}
2782
+
},
2783
+
"policies": {},
2784
+
"checkConstraints": {},
2785
+
"isRLSEnabled": false
2786
+
},
2787
+
"public.user_playlists": {
2788
+
"name": "user_playlists",
2789
+
"schema": "",
2790
+
"columns": {
2791
+
"xata_id": {
2792
+
"name": "xata_id",
2793
+
"type": "text",
2794
+
"primaryKey": true,
2795
+
"notNull": true
2796
+
},
2797
+
"user_id": {
2798
+
"name": "user_id",
2799
+
"type": "text",
2800
+
"primaryKey": false,
2801
+
"notNull": true
2802
+
},
2803
+
"playlist_id": {
2804
+
"name": "playlist_id",
2805
+
"type": "text",
2806
+
"primaryKey": false,
2807
+
"notNull": true
2808
+
},
2809
+
"xata_createdat": {
2810
+
"name": "xata_createdat",
2811
+
"type": "timestamp",
2812
+
"primaryKey": false,
2813
+
"notNull": true,
2814
+
"default": "now()"
2815
+
},
2816
+
"uri": {
2817
+
"name": "uri",
2818
+
"type": "text",
2819
+
"primaryKey": false,
2820
+
"notNull": false
2821
+
}
2822
+
},
2823
+
"indexes": {},
2824
+
"foreignKeys": {
2825
+
"user_playlists_user_id_users_xata_id_fk": {
2826
+
"name": "user_playlists_user_id_users_xata_id_fk",
2827
+
"tableFrom": "user_playlists",
2828
+
"tableTo": "users",
2829
+
"columnsFrom": [
2830
+
"user_id"
2831
+
],
2832
+
"columnsTo": [
2833
+
"xata_id"
2834
+
],
2835
+
"onDelete": "no action",
2836
+
"onUpdate": "no action"
2837
+
},
2838
+
"user_playlists_playlist_id_tracks_xata_id_fk": {
2839
+
"name": "user_playlists_playlist_id_tracks_xata_id_fk",
2840
+
"tableFrom": "user_playlists",
2841
+
"tableTo": "tracks",
2842
+
"columnsFrom": [
2843
+
"playlist_id"
2844
+
],
2845
+
"columnsTo": [
2846
+
"xata_id"
2847
+
],
2848
+
"onDelete": "no action",
2849
+
"onUpdate": "no action"
2850
+
}
2851
+
},
2852
+
"compositePrimaryKeys": {},
2853
+
"uniqueConstraints": {
2854
+
"user_playlists_uri_unique": {
2855
+
"name": "user_playlists_uri_unique",
2856
+
"nullsNotDistinct": false,
2857
+
"columns": [
2858
+
"uri"
2859
+
]
2860
+
}
2861
+
},
2862
+
"policies": {},
2863
+
"checkConstraints": {},
2864
+
"isRLSEnabled": false
2865
+
},
2866
+
"public.user_tracks": {
2867
+
"name": "user_tracks",
2868
+
"schema": "",
2869
+
"columns": {
2870
+
"xata_id": {
2871
+
"name": "xata_id",
2872
+
"type": "text",
2873
+
"primaryKey": true,
2874
+
"notNull": true
2875
+
},
2876
+
"user_id": {
2877
+
"name": "user_id",
2878
+
"type": "text",
2879
+
"primaryKey": false,
2880
+
"notNull": true
2881
+
},
2882
+
"track_id": {
2883
+
"name": "track_id",
2884
+
"type": "text",
2885
+
"primaryKey": false,
2886
+
"notNull": true
2887
+
},
2888
+
"xata_createdat": {
2889
+
"name": "xata_createdat",
2890
+
"type": "timestamp",
2891
+
"primaryKey": false,
2892
+
"notNull": true,
2893
+
"default": "now()"
2894
+
},
2895
+
"xata_updatedat": {
2896
+
"name": "xata_updatedat",
2897
+
"type": "timestamp",
2898
+
"primaryKey": false,
2899
+
"notNull": true,
2900
+
"default": "now()"
2901
+
},
2902
+
"xata_version": {
2903
+
"name": "xata_version",
2904
+
"type": "integer",
2905
+
"primaryKey": false,
2906
+
"notNull": false
2907
+
},
2908
+
"uri": {
2909
+
"name": "uri",
2910
+
"type": "text",
2911
+
"primaryKey": false,
2912
+
"notNull": true
2913
+
},
2914
+
"scrobbles": {
2915
+
"name": "scrobbles",
2916
+
"type": "integer",
2917
+
"primaryKey": false,
2918
+
"notNull": false
2919
+
}
2920
+
},
2921
+
"indexes": {},
2922
+
"foreignKeys": {
2923
+
"user_tracks_user_id_users_xata_id_fk": {
2924
+
"name": "user_tracks_user_id_users_xata_id_fk",
2925
+
"tableFrom": "user_tracks",
2926
+
"tableTo": "users",
2927
+
"columnsFrom": [
2928
+
"user_id"
2929
+
],
2930
+
"columnsTo": [
2931
+
"xata_id"
2932
+
],
2933
+
"onDelete": "no action",
2934
+
"onUpdate": "no action"
2935
+
},
2936
+
"user_tracks_track_id_tracks_xata_id_fk": {
2937
+
"name": "user_tracks_track_id_tracks_xata_id_fk",
2938
+
"tableFrom": "user_tracks",
2939
+
"tableTo": "tracks",
2940
+
"columnsFrom": [
2941
+
"track_id"
2942
+
],
2943
+
"columnsTo": [
2944
+
"xata_id"
2945
+
],
2946
+
"onDelete": "no action",
2947
+
"onUpdate": "no action"
2948
+
}
2949
+
},
2950
+
"compositePrimaryKeys": {},
2951
+
"uniqueConstraints": {
2952
+
"user_tracks_uri_unique": {
2953
+
"name": "user_tracks_uri_unique",
2954
+
"nullsNotDistinct": false,
2955
+
"columns": [
2956
+
"uri"
2957
+
]
2958
+
}
2959
+
},
2960
+
"policies": {},
2961
+
"checkConstraints": {},
2962
+
"isRLSEnabled": false
2963
+
},
2964
+
"public.users": {
2965
+
"name": "users",
2966
+
"schema": "",
2967
+
"columns": {
2968
+
"xata_id": {
2969
+
"name": "xata_id",
2970
+
"type": "text",
2971
+
"primaryKey": true,
2972
+
"notNull": true
2973
+
},
2974
+
"did": {
2975
+
"name": "did",
2976
+
"type": "text",
2977
+
"primaryKey": false,
2978
+
"notNull": true
2979
+
},
2980
+
"display_name": {
2981
+
"name": "display_name",
2982
+
"type": "text",
2983
+
"primaryKey": false,
2984
+
"notNull": false
2985
+
},
2986
+
"handle": {
2987
+
"name": "handle",
2988
+
"type": "text",
2989
+
"primaryKey": false,
2990
+
"notNull": true
2991
+
},
2992
+
"avatar": {
2993
+
"name": "avatar",
2994
+
"type": "text",
2995
+
"primaryKey": false,
2996
+
"notNull": true
2997
+
},
2998
+
"xata_createdat": {
2999
+
"name": "xata_createdat",
3000
+
"type": "timestamp",
3001
+
"primaryKey": false,
3002
+
"notNull": true,
3003
+
"default": "now()"
3004
+
},
3005
+
"xata_updatedat": {
3006
+
"name": "xata_updatedat",
3007
+
"type": "timestamp",
3008
+
"primaryKey": false,
3009
+
"notNull": true,
3010
+
"default": "now()"
3011
+
},
3012
+
"xata_version": {
3013
+
"name": "xata_version",
3014
+
"type": "integer",
3015
+
"primaryKey": false,
3016
+
"notNull": false
3017
+
}
3018
+
},
3019
+
"indexes": {},
3020
+
"foreignKeys": {},
3021
+
"compositePrimaryKeys": {},
3022
+
"uniqueConstraints": {
3023
+
"users_did_unique": {
3024
+
"name": "users_did_unique",
3025
+
"nullsNotDistinct": false,
3026
+
"columns": [
3027
+
"did"
3028
+
]
3029
+
},
3030
+
"users_handle_unique": {
3031
+
"name": "users_handle_unique",
3032
+
"nullsNotDistinct": false,
3033
+
"columns": [
3034
+
"handle"
3035
+
]
3036
+
}
3037
+
},
3038
+
"policies": {},
3039
+
"checkConstraints": {},
3040
+
"isRLSEnabled": false
3041
+
},
3042
+
"public.webscrobblers": {
3043
+
"name": "webscrobblers",
3044
+
"schema": "",
3045
+
"columns": {
3046
+
"xata_id": {
3047
+
"name": "xata_id",
3048
+
"type": "text",
3049
+
"primaryKey": true,
3050
+
"notNull": true
3051
+
},
3052
+
"name": {
3053
+
"name": "name",
3054
+
"type": "text",
3055
+
"primaryKey": false,
3056
+
"notNull": true
3057
+
},
3058
+
"uuid": {
3059
+
"name": "uuid",
3060
+
"type": "text",
3061
+
"primaryKey": false,
3062
+
"notNull": true
3063
+
},
3064
+
"description": {
3065
+
"name": "description",
3066
+
"type": "text",
3067
+
"primaryKey": false,
3068
+
"notNull": false
3069
+
},
3070
+
"enabled": {
3071
+
"name": "enabled",
3072
+
"type": "boolean",
3073
+
"primaryKey": false,
3074
+
"notNull": true,
3075
+
"default": true
3076
+
},
3077
+
"user_id": {
3078
+
"name": "user_id",
3079
+
"type": "text",
3080
+
"primaryKey": false,
3081
+
"notNull": true
3082
+
},
3083
+
"xata_createdat": {
3084
+
"name": "xata_createdat",
3085
+
"type": "timestamp",
3086
+
"primaryKey": false,
3087
+
"notNull": true,
3088
+
"default": "now()"
3089
+
},
3090
+
"xata_updatedat": {
3091
+
"name": "xata_updatedat",
3092
+
"type": "timestamp",
3093
+
"primaryKey": false,
3094
+
"notNull": true,
3095
+
"default": "now()"
3096
+
}
3097
+
},
3098
+
"indexes": {},
3099
+
"foreignKeys": {
3100
+
"webscrobblers_user_id_users_xata_id_fk": {
3101
+
"name": "webscrobblers_user_id_users_xata_id_fk",
3102
+
"tableFrom": "webscrobblers",
3103
+
"tableTo": "users",
3104
+
"columnsFrom": [
3105
+
"user_id"
3106
+
],
3107
+
"columnsTo": [
3108
+
"xata_id"
3109
+
],
3110
+
"onDelete": "no action",
3111
+
"onUpdate": "no action"
3112
+
}
3113
+
},
3114
+
"compositePrimaryKeys": {},
3115
+
"uniqueConstraints": {},
3116
+
"policies": {},
3117
+
"checkConstraints": {},
3118
+
"isRLSEnabled": false
3119
+
}
3120
+
},
3121
+
"enums": {},
3122
+
"schemas": {},
3123
+
"sequences": {},
3124
+
"roles": {},
3125
+
"policies": {},
3126
+
"views": {},
3127
+
"_meta": {
3128
+
"columns": {},
3129
+
"schemas": {},
3130
+
"tables": {}
3131
+
}
3132
+
}
+3132
apps/api/drizzle/meta/0002_snapshot.json
+3132
apps/api/drizzle/meta/0002_snapshot.json
···
1
+
{
2
+
"id": "3ef49661-fdf0-4245-8943-ff69567a09b9",
3
+
"prevId": "6ebb9775-b900-418c-bbd8-b704571a20d5",
4
+
"version": "7",
5
+
"dialect": "postgresql",
6
+
"tables": {
7
+
"public.album_tracks": {
8
+
"name": "album_tracks",
9
+
"schema": "",
10
+
"columns": {
11
+
"xata_id": {
12
+
"name": "xata_id",
13
+
"type": "text",
14
+
"primaryKey": true,
15
+
"notNull": true
16
+
},
17
+
"album_id": {
18
+
"name": "album_id",
19
+
"type": "text",
20
+
"primaryKey": false,
21
+
"notNull": true
22
+
},
23
+
"track_id": {
24
+
"name": "track_id",
25
+
"type": "text",
26
+
"primaryKey": false,
27
+
"notNull": true
28
+
},
29
+
"xata_createdat": {
30
+
"name": "xata_createdat",
31
+
"type": "timestamp",
32
+
"primaryKey": false,
33
+
"notNull": true,
34
+
"default": "now()"
35
+
},
36
+
"xata_updatedat": {
37
+
"name": "xata_updatedat",
38
+
"type": "timestamp",
39
+
"primaryKey": false,
40
+
"notNull": true,
41
+
"default": "now()"
42
+
},
43
+
"xata_version": {
44
+
"name": "xata_version",
45
+
"type": "integer",
46
+
"primaryKey": false,
47
+
"notNull": false
48
+
}
49
+
},
50
+
"indexes": {},
51
+
"foreignKeys": {
52
+
"album_tracks_album_id_albums_xata_id_fk": {
53
+
"name": "album_tracks_album_id_albums_xata_id_fk",
54
+
"tableFrom": "album_tracks",
55
+
"tableTo": "albums",
56
+
"columnsFrom": [
57
+
"album_id"
58
+
],
59
+
"columnsTo": [
60
+
"xata_id"
61
+
],
62
+
"onDelete": "no action",
63
+
"onUpdate": "no action"
64
+
},
65
+
"album_tracks_track_id_tracks_xata_id_fk": {
66
+
"name": "album_tracks_track_id_tracks_xata_id_fk",
67
+
"tableFrom": "album_tracks",
68
+
"tableTo": "tracks",
69
+
"columnsFrom": [
70
+
"track_id"
71
+
],
72
+
"columnsTo": [
73
+
"xata_id"
74
+
],
75
+
"onDelete": "no action",
76
+
"onUpdate": "no action"
77
+
}
78
+
},
79
+
"compositePrimaryKeys": {},
80
+
"uniqueConstraints": {},
81
+
"policies": {},
82
+
"checkConstraints": {},
83
+
"isRLSEnabled": false
84
+
},
85
+
"public.albums": {
86
+
"name": "albums",
87
+
"schema": "",
88
+
"columns": {
89
+
"xata_id": {
90
+
"name": "xata_id",
91
+
"type": "text",
92
+
"primaryKey": true,
93
+
"notNull": true
94
+
},
95
+
"title": {
96
+
"name": "title",
97
+
"type": "text",
98
+
"primaryKey": false,
99
+
"notNull": true
100
+
},
101
+
"artist": {
102
+
"name": "artist",
103
+
"type": "text",
104
+
"primaryKey": false,
105
+
"notNull": true
106
+
},
107
+
"release_date": {
108
+
"name": "release_date",
109
+
"type": "text",
110
+
"primaryKey": false,
111
+
"notNull": false
112
+
},
113
+
"year": {
114
+
"name": "year",
115
+
"type": "integer",
116
+
"primaryKey": false,
117
+
"notNull": false
118
+
},
119
+
"album_art": {
120
+
"name": "album_art",
121
+
"type": "text",
122
+
"primaryKey": false,
123
+
"notNull": false
124
+
},
125
+
"uri": {
126
+
"name": "uri",
127
+
"type": "text",
128
+
"primaryKey": false,
129
+
"notNull": false
130
+
},
131
+
"artist_uri": {
132
+
"name": "artist_uri",
133
+
"type": "text",
134
+
"primaryKey": false,
135
+
"notNull": false
136
+
},
137
+
"apple_music_link": {
138
+
"name": "apple_music_link",
139
+
"type": "text",
140
+
"primaryKey": false,
141
+
"notNull": false
142
+
},
143
+
"spotify_link": {
144
+
"name": "spotify_link",
145
+
"type": "text",
146
+
"primaryKey": false,
147
+
"notNull": false
148
+
},
149
+
"tidal_link": {
150
+
"name": "tidal_link",
151
+
"type": "text",
152
+
"primaryKey": false,
153
+
"notNull": false
154
+
},
155
+
"youtube_link": {
156
+
"name": "youtube_link",
157
+
"type": "text",
158
+
"primaryKey": false,
159
+
"notNull": false
160
+
},
161
+
"sha256": {
162
+
"name": "sha256",
163
+
"type": "text",
164
+
"primaryKey": false,
165
+
"notNull": true
166
+
},
167
+
"xata_createdat": {
168
+
"name": "xata_createdat",
169
+
"type": "timestamp",
170
+
"primaryKey": false,
171
+
"notNull": true,
172
+
"default": "now()"
173
+
},
174
+
"xata_updatedat": {
175
+
"name": "xata_updatedat",
176
+
"type": "timestamp",
177
+
"primaryKey": false,
178
+
"notNull": true,
179
+
"default": "now()"
180
+
},
181
+
"xata_version": {
182
+
"name": "xata_version",
183
+
"type": "integer",
184
+
"primaryKey": false,
185
+
"notNull": false
186
+
}
187
+
},
188
+
"indexes": {},
189
+
"foreignKeys": {},
190
+
"compositePrimaryKeys": {},
191
+
"uniqueConstraints": {
192
+
"albums_uri_unique": {
193
+
"name": "albums_uri_unique",
194
+
"nullsNotDistinct": false,
195
+
"columns": [
196
+
"uri"
197
+
]
198
+
},
199
+
"albums_apple_music_link_unique": {
200
+
"name": "albums_apple_music_link_unique",
201
+
"nullsNotDistinct": false,
202
+
"columns": [
203
+
"apple_music_link"
204
+
]
205
+
},
206
+
"albums_spotify_link_unique": {
207
+
"name": "albums_spotify_link_unique",
208
+
"nullsNotDistinct": false,
209
+
"columns": [
210
+
"spotify_link"
211
+
]
212
+
},
213
+
"albums_tidal_link_unique": {
214
+
"name": "albums_tidal_link_unique",
215
+
"nullsNotDistinct": false,
216
+
"columns": [
217
+
"tidal_link"
218
+
]
219
+
},
220
+
"albums_youtube_link_unique": {
221
+
"name": "albums_youtube_link_unique",
222
+
"nullsNotDistinct": false,
223
+
"columns": [
224
+
"youtube_link"
225
+
]
226
+
},
227
+
"albums_sha256_unique": {
228
+
"name": "albums_sha256_unique",
229
+
"nullsNotDistinct": false,
230
+
"columns": [
231
+
"sha256"
232
+
]
233
+
}
234
+
},
235
+
"policies": {},
236
+
"checkConstraints": {},
237
+
"isRLSEnabled": false
238
+
},
239
+
"public.api_keys": {
240
+
"name": "api_keys",
241
+
"schema": "",
242
+
"columns": {
243
+
"xata_id": {
244
+
"name": "xata_id",
245
+
"type": "text",
246
+
"primaryKey": true,
247
+
"notNull": true
248
+
},
249
+
"name": {
250
+
"name": "name",
251
+
"type": "text",
252
+
"primaryKey": false,
253
+
"notNull": true
254
+
},
255
+
"api_key": {
256
+
"name": "api_key",
257
+
"type": "text",
258
+
"primaryKey": false,
259
+
"notNull": true
260
+
},
261
+
"shared_secret": {
262
+
"name": "shared_secret",
263
+
"type": "text",
264
+
"primaryKey": false,
265
+
"notNull": true
266
+
},
267
+
"description": {
268
+
"name": "description",
269
+
"type": "text",
270
+
"primaryKey": false,
271
+
"notNull": false
272
+
},
273
+
"enabled": {
274
+
"name": "enabled",
275
+
"type": "boolean",
276
+
"primaryKey": false,
277
+
"notNull": true,
278
+
"default": true
279
+
},
280
+
"user_id": {
281
+
"name": "user_id",
282
+
"type": "text",
283
+
"primaryKey": false,
284
+
"notNull": true
285
+
},
286
+
"xata_createdat": {
287
+
"name": "xata_createdat",
288
+
"type": "timestamp",
289
+
"primaryKey": false,
290
+
"notNull": true,
291
+
"default": "now()"
292
+
},
293
+
"xata_updatedat": {
294
+
"name": "xata_updatedat",
295
+
"type": "timestamp",
296
+
"primaryKey": false,
297
+
"notNull": true,
298
+
"default": "now()"
299
+
}
300
+
},
301
+
"indexes": {},
302
+
"foreignKeys": {
303
+
"api_keys_user_id_users_xata_id_fk": {
304
+
"name": "api_keys_user_id_users_xata_id_fk",
305
+
"tableFrom": "api_keys",
306
+
"tableTo": "users",
307
+
"columnsFrom": [
308
+
"user_id"
309
+
],
310
+
"columnsTo": [
311
+
"xata_id"
312
+
],
313
+
"onDelete": "no action",
314
+
"onUpdate": "no action"
315
+
}
316
+
},
317
+
"compositePrimaryKeys": {},
318
+
"uniqueConstraints": {},
319
+
"policies": {},
320
+
"checkConstraints": {},
321
+
"isRLSEnabled": false
322
+
},
323
+
"public.artist_albums": {
324
+
"name": "artist_albums",
325
+
"schema": "",
326
+
"columns": {
327
+
"xata_id": {
328
+
"name": "xata_id",
329
+
"type": "text",
330
+
"primaryKey": true,
331
+
"notNull": true
332
+
},
333
+
"artist_id": {
334
+
"name": "artist_id",
335
+
"type": "text",
336
+
"primaryKey": false,
337
+
"notNull": true
338
+
},
339
+
"album_id": {
340
+
"name": "album_id",
341
+
"type": "text",
342
+
"primaryKey": false,
343
+
"notNull": true
344
+
},
345
+
"xata_createdat": {
346
+
"name": "xata_createdat",
347
+
"type": "timestamp",
348
+
"primaryKey": false,
349
+
"notNull": true,
350
+
"default": "now()"
351
+
},
352
+
"xata_updatedat": {
353
+
"name": "xata_updatedat",
354
+
"type": "timestamp",
355
+
"primaryKey": false,
356
+
"notNull": true,
357
+
"default": "now()"
358
+
},
359
+
"xata_version": {
360
+
"name": "xata_version",
361
+
"type": "integer",
362
+
"primaryKey": false,
363
+
"notNull": false
364
+
}
365
+
},
366
+
"indexes": {},
367
+
"foreignKeys": {
368
+
"artist_albums_artist_id_artists_xata_id_fk": {
369
+
"name": "artist_albums_artist_id_artists_xata_id_fk",
370
+
"tableFrom": "artist_albums",
371
+
"tableTo": "artists",
372
+
"columnsFrom": [
373
+
"artist_id"
374
+
],
375
+
"columnsTo": [
376
+
"xata_id"
377
+
],
378
+
"onDelete": "no action",
379
+
"onUpdate": "no action"
380
+
},
381
+
"artist_albums_album_id_albums_xata_id_fk": {
382
+
"name": "artist_albums_album_id_albums_xata_id_fk",
383
+
"tableFrom": "artist_albums",
384
+
"tableTo": "albums",
385
+
"columnsFrom": [
386
+
"album_id"
387
+
],
388
+
"columnsTo": [
389
+
"xata_id"
390
+
],
391
+
"onDelete": "no action",
392
+
"onUpdate": "no action"
393
+
}
394
+
},
395
+
"compositePrimaryKeys": {},
396
+
"uniqueConstraints": {},
397
+
"policies": {},
398
+
"checkConstraints": {},
399
+
"isRLSEnabled": false
400
+
},
401
+
"public.artist_tracks": {
402
+
"name": "artist_tracks",
403
+
"schema": "",
404
+
"columns": {
405
+
"xata_id": {
406
+
"name": "xata_id",
407
+
"type": "text",
408
+
"primaryKey": true,
409
+
"notNull": true
410
+
},
411
+
"artist_id": {
412
+
"name": "artist_id",
413
+
"type": "text",
414
+
"primaryKey": false,
415
+
"notNull": true
416
+
},
417
+
"track_id": {
418
+
"name": "track_id",
419
+
"type": "text",
420
+
"primaryKey": false,
421
+
"notNull": true
422
+
},
423
+
"xata_createdat": {
424
+
"name": "xata_createdat",
425
+
"type": "timestamp",
426
+
"primaryKey": false,
427
+
"notNull": true,
428
+
"default": "now()"
429
+
},
430
+
"xata_updatedat": {
431
+
"name": "xata_updatedat",
432
+
"type": "timestamp",
433
+
"primaryKey": false,
434
+
"notNull": true,
435
+
"default": "now()"
436
+
},
437
+
"xata_version": {
438
+
"name": "xata_version",
439
+
"type": "integer",
440
+
"primaryKey": false,
441
+
"notNull": false
442
+
}
443
+
},
444
+
"indexes": {},
445
+
"foreignKeys": {
446
+
"artist_tracks_artist_id_artists_xata_id_fk": {
447
+
"name": "artist_tracks_artist_id_artists_xata_id_fk",
448
+
"tableFrom": "artist_tracks",
449
+
"tableTo": "artists",
450
+
"columnsFrom": [
451
+
"artist_id"
452
+
],
453
+
"columnsTo": [
454
+
"xata_id"
455
+
],
456
+
"onDelete": "no action",
457
+
"onUpdate": "no action"
458
+
},
459
+
"artist_tracks_track_id_tracks_xata_id_fk": {
460
+
"name": "artist_tracks_track_id_tracks_xata_id_fk",
461
+
"tableFrom": "artist_tracks",
462
+
"tableTo": "tracks",
463
+
"columnsFrom": [
464
+
"track_id"
465
+
],
466
+
"columnsTo": [
467
+
"xata_id"
468
+
],
469
+
"onDelete": "no action",
470
+
"onUpdate": "no action"
471
+
}
472
+
},
473
+
"compositePrimaryKeys": {},
474
+
"uniqueConstraints": {},
475
+
"policies": {},
476
+
"checkConstraints": {},
477
+
"isRLSEnabled": false
478
+
},
479
+
"public.artists": {
480
+
"name": "artists",
481
+
"schema": "",
482
+
"columns": {
483
+
"xata_id": {
484
+
"name": "xata_id",
485
+
"type": "text",
486
+
"primaryKey": true,
487
+
"notNull": true
488
+
},
489
+
"name": {
490
+
"name": "name",
491
+
"type": "text",
492
+
"primaryKey": false,
493
+
"notNull": true
494
+
},
495
+
"biography": {
496
+
"name": "biography",
497
+
"type": "text",
498
+
"primaryKey": false,
499
+
"notNull": false
500
+
},
501
+
"born": {
502
+
"name": "born",
503
+
"type": "timestamp",
504
+
"primaryKey": false,
505
+
"notNull": false
506
+
},
507
+
"born_in": {
508
+
"name": "born_in",
509
+
"type": "text",
510
+
"primaryKey": false,
511
+
"notNull": false
512
+
},
513
+
"died": {
514
+
"name": "died",
515
+
"type": "timestamp",
516
+
"primaryKey": false,
517
+
"notNull": false
518
+
},
519
+
"picture": {
520
+
"name": "picture",
521
+
"type": "text",
522
+
"primaryKey": false,
523
+
"notNull": false
524
+
},
525
+
"sha256": {
526
+
"name": "sha256",
527
+
"type": "text",
528
+
"primaryKey": false,
529
+
"notNull": true
530
+
},
531
+
"uri": {
532
+
"name": "uri",
533
+
"type": "text",
534
+
"primaryKey": false,
535
+
"notNull": false
536
+
},
537
+
"apple_music_link": {
538
+
"name": "apple_music_link",
539
+
"type": "text",
540
+
"primaryKey": false,
541
+
"notNull": false
542
+
},
543
+
"spotify_link": {
544
+
"name": "spotify_link",
545
+
"type": "text",
546
+
"primaryKey": false,
547
+
"notNull": false
548
+
},
549
+
"tidal_link": {
550
+
"name": "tidal_link",
551
+
"type": "text",
552
+
"primaryKey": false,
553
+
"notNull": false
554
+
},
555
+
"youtube_link": {
556
+
"name": "youtube_link",
557
+
"type": "text",
558
+
"primaryKey": false,
559
+
"notNull": false
560
+
},
561
+
"genres": {
562
+
"name": "genres",
563
+
"type": "text[]",
564
+
"primaryKey": false,
565
+
"notNull": false
566
+
},
567
+
"xata_createdat": {
568
+
"name": "xata_createdat",
569
+
"type": "timestamp",
570
+
"primaryKey": false,
571
+
"notNull": true,
572
+
"default": "now()"
573
+
},
574
+
"xata_updatedat": {
575
+
"name": "xata_updatedat",
576
+
"type": "timestamp",
577
+
"primaryKey": false,
578
+
"notNull": true,
579
+
"default": "now()"
580
+
},
581
+
"xata_version": {
582
+
"name": "xata_version",
583
+
"type": "integer",
584
+
"primaryKey": false,
585
+
"notNull": false
586
+
}
587
+
},
588
+
"indexes": {},
589
+
"foreignKeys": {},
590
+
"compositePrimaryKeys": {},
591
+
"uniqueConstraints": {
592
+
"artists_sha256_unique": {
593
+
"name": "artists_sha256_unique",
594
+
"nullsNotDistinct": false,
595
+
"columns": [
596
+
"sha256"
597
+
]
598
+
},
599
+
"artists_uri_unique": {
600
+
"name": "artists_uri_unique",
601
+
"nullsNotDistinct": false,
602
+
"columns": [
603
+
"uri"
604
+
]
605
+
}
606
+
},
607
+
"policies": {},
608
+
"checkConstraints": {},
609
+
"isRLSEnabled": false
610
+
},
611
+
"public.dropbox_accounts": {
612
+
"name": "dropbox_accounts",
613
+
"schema": "",
614
+
"columns": {
615
+
"xata_id": {
616
+
"name": "xata_id",
617
+
"type": "text",
618
+
"primaryKey": true,
619
+
"notNull": true
620
+
},
621
+
"email": {
622
+
"name": "email",
623
+
"type": "text",
624
+
"primaryKey": false,
625
+
"notNull": true
626
+
},
627
+
"is_beta_user": {
628
+
"name": "is_beta_user",
629
+
"type": "boolean",
630
+
"primaryKey": false,
631
+
"notNull": true,
632
+
"default": false
633
+
},
634
+
"user_id": {
635
+
"name": "user_id",
636
+
"type": "text",
637
+
"primaryKey": false,
638
+
"notNull": true
639
+
},
640
+
"xata_version": {
641
+
"name": "xata_version",
642
+
"type": "text",
643
+
"primaryKey": false,
644
+
"notNull": false
645
+
},
646
+
"xata_createdat": {
647
+
"name": "xata_createdat",
648
+
"type": "timestamp",
649
+
"primaryKey": false,
650
+
"notNull": true,
651
+
"default": "now()"
652
+
},
653
+
"xata_updatedat": {
654
+
"name": "xata_updatedat",
655
+
"type": "timestamp",
656
+
"primaryKey": false,
657
+
"notNull": true,
658
+
"default": "now()"
659
+
}
660
+
},
661
+
"indexes": {},
662
+
"foreignKeys": {
663
+
"dropbox_accounts_user_id_users_xata_id_fk": {
664
+
"name": "dropbox_accounts_user_id_users_xata_id_fk",
665
+
"tableFrom": "dropbox_accounts",
666
+
"tableTo": "users",
667
+
"columnsFrom": [
668
+
"user_id"
669
+
],
670
+
"columnsTo": [
671
+
"xata_id"
672
+
],
673
+
"onDelete": "no action",
674
+
"onUpdate": "no action"
675
+
}
676
+
},
677
+
"compositePrimaryKeys": {},
678
+
"uniqueConstraints": {
679
+
"dropbox_accounts_email_unique": {
680
+
"name": "dropbox_accounts_email_unique",
681
+
"nullsNotDistinct": false,
682
+
"columns": [
683
+
"email"
684
+
]
685
+
}
686
+
},
687
+
"policies": {},
688
+
"checkConstraints": {},
689
+
"isRLSEnabled": false
690
+
},
691
+
"public.dropbox_directories": {
692
+
"name": "dropbox_directories",
693
+
"schema": "",
694
+
"columns": {
695
+
"xata_id": {
696
+
"name": "xata_id",
697
+
"type": "text",
698
+
"primaryKey": true,
699
+
"notNull": true
700
+
},
701
+
"name": {
702
+
"name": "name",
703
+
"type": "text",
704
+
"primaryKey": false,
705
+
"notNull": true
706
+
},
707
+
"path": {
708
+
"name": "path",
709
+
"type": "text",
710
+
"primaryKey": false,
711
+
"notNull": true
712
+
},
713
+
"parent_id": {
714
+
"name": "parent_id",
715
+
"type": "text",
716
+
"primaryKey": false,
717
+
"notNull": false
718
+
},
719
+
"dropbox_id": {
720
+
"name": "dropbox_id",
721
+
"type": "text",
722
+
"primaryKey": false,
723
+
"notNull": true
724
+
},
725
+
"file_id": {
726
+
"name": "file_id",
727
+
"type": "text",
728
+
"primaryKey": false,
729
+
"notNull": true
730
+
},
731
+
"xata_version": {
732
+
"name": "xata_version",
733
+
"type": "text",
734
+
"primaryKey": false,
735
+
"notNull": false
736
+
},
737
+
"xata_createdat": {
738
+
"name": "xata_createdat",
739
+
"type": "timestamp",
740
+
"primaryKey": false,
741
+
"notNull": true,
742
+
"default": "now()"
743
+
},
744
+
"xata_updatedat": {
745
+
"name": "xata_updatedat",
746
+
"type": "timestamp",
747
+
"primaryKey": false,
748
+
"notNull": true,
749
+
"default": "now()"
750
+
}
751
+
},
752
+
"indexes": {},
753
+
"foreignKeys": {
754
+
"dropbox_directories_parent_id_dropbox_directories_xata_id_fk": {
755
+
"name": "dropbox_directories_parent_id_dropbox_directories_xata_id_fk",
756
+
"tableFrom": "dropbox_directories",
757
+
"tableTo": "dropbox_directories",
758
+
"columnsFrom": [
759
+
"parent_id"
760
+
],
761
+
"columnsTo": [
762
+
"xata_id"
763
+
],
764
+
"onDelete": "no action",
765
+
"onUpdate": "no action"
766
+
}
767
+
},
768
+
"compositePrimaryKeys": {},
769
+
"uniqueConstraints": {
770
+
"dropbox_directories_file_id_unique": {
771
+
"name": "dropbox_directories_file_id_unique",
772
+
"nullsNotDistinct": false,
773
+
"columns": [
774
+
"file_id"
775
+
]
776
+
}
777
+
},
778
+
"policies": {},
779
+
"checkConstraints": {},
780
+
"isRLSEnabled": false
781
+
},
782
+
"public.dropbox_paths": {
783
+
"name": "dropbox_paths",
784
+
"schema": "",
785
+
"columns": {
786
+
"xata_id": {
787
+
"name": "xata_id",
788
+
"type": "text",
789
+
"primaryKey": true,
790
+
"notNull": true
791
+
},
792
+
"path": {
793
+
"name": "path",
794
+
"type": "text",
795
+
"primaryKey": false,
796
+
"notNull": true
797
+
},
798
+
"name": {
799
+
"name": "name",
800
+
"type": "text",
801
+
"primaryKey": false,
802
+
"notNull": true
803
+
},
804
+
"dropbox_id": {
805
+
"name": "dropbox_id",
806
+
"type": "text",
807
+
"primaryKey": false,
808
+
"notNull": true
809
+
},
810
+
"track_id": {
811
+
"name": "track_id",
812
+
"type": "text",
813
+
"primaryKey": false,
814
+
"notNull": true
815
+
},
816
+
"directory_id": {
817
+
"name": "directory_id",
818
+
"type": "text",
819
+
"primaryKey": false,
820
+
"notNull": false
821
+
},
822
+
"file_id": {
823
+
"name": "file_id",
824
+
"type": "text",
825
+
"primaryKey": false,
826
+
"notNull": true
827
+
},
828
+
"xata_version": {
829
+
"name": "xata_version",
830
+
"type": "text",
831
+
"primaryKey": false,
832
+
"notNull": false
833
+
},
834
+
"xata_createdat": {
835
+
"name": "xata_createdat",
836
+
"type": "timestamp",
837
+
"primaryKey": false,
838
+
"notNull": true,
839
+
"default": "now()"
840
+
},
841
+
"xata_updatedat": {
842
+
"name": "xata_updatedat",
843
+
"type": "timestamp",
844
+
"primaryKey": false,
845
+
"notNull": true,
846
+
"default": "now()"
847
+
}
848
+
},
849
+
"indexes": {},
850
+
"foreignKeys": {
851
+
"dropbox_paths_directory_id_dropbox_directories_xata_id_fk": {
852
+
"name": "dropbox_paths_directory_id_dropbox_directories_xata_id_fk",
853
+
"tableFrom": "dropbox_paths",
854
+
"tableTo": "dropbox_directories",
855
+
"columnsFrom": [
856
+
"directory_id"
857
+
],
858
+
"columnsTo": [
859
+
"xata_id"
860
+
],
861
+
"onDelete": "no action",
862
+
"onUpdate": "no action"
863
+
}
864
+
},
865
+
"compositePrimaryKeys": {},
866
+
"uniqueConstraints": {
867
+
"dropbox_paths_file_id_unique": {
868
+
"name": "dropbox_paths_file_id_unique",
869
+
"nullsNotDistinct": false,
870
+
"columns": [
871
+
"file_id"
872
+
]
873
+
}
874
+
},
875
+
"policies": {},
876
+
"checkConstraints": {},
877
+
"isRLSEnabled": false
878
+
},
879
+
"public.dropbox_tokens": {
880
+
"name": "dropbox_tokens",
881
+
"schema": "",
882
+
"columns": {
883
+
"xata_id": {
884
+
"name": "xata_id",
885
+
"type": "text",
886
+
"primaryKey": true,
887
+
"notNull": true
888
+
},
889
+
"refresh_token": {
890
+
"name": "refresh_token",
891
+
"type": "text",
892
+
"primaryKey": false,
893
+
"notNull": true
894
+
},
895
+
"xata_createdat": {
896
+
"name": "xata_createdat",
897
+
"type": "timestamp",
898
+
"primaryKey": false,
899
+
"notNull": true,
900
+
"default": "now()"
901
+
},
902
+
"xata_updatedat": {
903
+
"name": "xata_updatedat",
904
+
"type": "timestamp",
905
+
"primaryKey": false,
906
+
"notNull": true,
907
+
"default": "now()"
908
+
}
909
+
},
910
+
"indexes": {},
911
+
"foreignKeys": {},
912
+
"compositePrimaryKeys": {},
913
+
"uniqueConstraints": {},
914
+
"policies": {},
915
+
"checkConstraints": {},
916
+
"isRLSEnabled": false
917
+
},
918
+
"public.dropbox": {
919
+
"name": "dropbox",
920
+
"schema": "",
921
+
"columns": {
922
+
"xata_id": {
923
+
"name": "xata_id",
924
+
"type": "text",
925
+
"primaryKey": true,
926
+
"notNull": true
927
+
},
928
+
"user_id": {
929
+
"name": "user_id",
930
+
"type": "text",
931
+
"primaryKey": false,
932
+
"notNull": true
933
+
},
934
+
"dropbox_token_id": {
935
+
"name": "dropbox_token_id",
936
+
"type": "text",
937
+
"primaryKey": false,
938
+
"notNull": true
939
+
},
940
+
"xata_version": {
941
+
"name": "xata_version",
942
+
"type": "text",
943
+
"primaryKey": false,
944
+
"notNull": false
945
+
},
946
+
"xata_createdat": {
947
+
"name": "xata_createdat",
948
+
"type": "timestamp",
949
+
"primaryKey": false,
950
+
"notNull": true,
951
+
"default": "now()"
952
+
},
953
+
"xata_updatedat": {
954
+
"name": "xata_updatedat",
955
+
"type": "timestamp",
956
+
"primaryKey": false,
957
+
"notNull": true,
958
+
"default": "now()"
959
+
}
960
+
},
961
+
"indexes": {},
962
+
"foreignKeys": {
963
+
"dropbox_user_id_users_xata_id_fk": {
964
+
"name": "dropbox_user_id_users_xata_id_fk",
965
+
"tableFrom": "dropbox",
966
+
"tableTo": "users",
967
+
"columnsFrom": [
968
+
"user_id"
969
+
],
970
+
"columnsTo": [
971
+
"xata_id"
972
+
],
973
+
"onDelete": "no action",
974
+
"onUpdate": "no action"
975
+
},
976
+
"dropbox_dropbox_token_id_dropbox_tokens_xata_id_fk": {
977
+
"name": "dropbox_dropbox_token_id_dropbox_tokens_xata_id_fk",
978
+
"tableFrom": "dropbox",
979
+
"tableTo": "dropbox_tokens",
980
+
"columnsFrom": [
981
+
"dropbox_token_id"
982
+
],
983
+
"columnsTo": [
984
+
"xata_id"
985
+
],
986
+
"onDelete": "no action",
987
+
"onUpdate": "no action"
988
+
}
989
+
},
990
+
"compositePrimaryKeys": {},
991
+
"uniqueConstraints": {},
992
+
"policies": {},
993
+
"checkConstraints": {},
994
+
"isRLSEnabled": false
995
+
},
996
+
"public.google_drive_accounts": {
997
+
"name": "google_drive_accounts",
998
+
"schema": "",
999
+
"columns": {
1000
+
"xata_id": {
1001
+
"name": "xata_id",
1002
+
"type": "text",
1003
+
"primaryKey": true,
1004
+
"notNull": true
1005
+
},
1006
+
"email": {
1007
+
"name": "email",
1008
+
"type": "text",
1009
+
"primaryKey": false,
1010
+
"notNull": true
1011
+
},
1012
+
"is_beta_user": {
1013
+
"name": "is_beta_user",
1014
+
"type": "boolean",
1015
+
"primaryKey": false,
1016
+
"notNull": true,
1017
+
"default": false
1018
+
},
1019
+
"user_id": {
1020
+
"name": "user_id",
1021
+
"type": "text",
1022
+
"primaryKey": false,
1023
+
"notNull": true
1024
+
},
1025
+
"xata_version": {
1026
+
"name": "xata_version",
1027
+
"type": "text",
1028
+
"primaryKey": false,
1029
+
"notNull": false
1030
+
},
1031
+
"xata_createdat": {
1032
+
"name": "xata_createdat",
1033
+
"type": "timestamp",
1034
+
"primaryKey": false,
1035
+
"notNull": true,
1036
+
"default": "now()"
1037
+
},
1038
+
"xata_updatedat": {
1039
+
"name": "xata_updatedat",
1040
+
"type": "timestamp",
1041
+
"primaryKey": false,
1042
+
"notNull": true,
1043
+
"default": "now()"
1044
+
}
1045
+
},
1046
+
"indexes": {},
1047
+
"foreignKeys": {
1048
+
"google_drive_accounts_user_id_users_xata_id_fk": {
1049
+
"name": "google_drive_accounts_user_id_users_xata_id_fk",
1050
+
"tableFrom": "google_drive_accounts",
1051
+
"tableTo": "users",
1052
+
"columnsFrom": [
1053
+
"user_id"
1054
+
],
1055
+
"columnsTo": [
1056
+
"xata_id"
1057
+
],
1058
+
"onDelete": "no action",
1059
+
"onUpdate": "no action"
1060
+
}
1061
+
},
1062
+
"compositePrimaryKeys": {},
1063
+
"uniqueConstraints": {
1064
+
"google_drive_accounts_email_unique": {
1065
+
"name": "google_drive_accounts_email_unique",
1066
+
"nullsNotDistinct": false,
1067
+
"columns": [
1068
+
"email"
1069
+
]
1070
+
}
1071
+
},
1072
+
"policies": {},
1073
+
"checkConstraints": {},
1074
+
"isRLSEnabled": false
1075
+
},
1076
+
"public.google_drive_directories": {
1077
+
"name": "google_drive_directories",
1078
+
"schema": "",
1079
+
"columns": {
1080
+
"xata_id": {
1081
+
"name": "xata_id",
1082
+
"type": "text",
1083
+
"primaryKey": true,
1084
+
"notNull": true
1085
+
},
1086
+
"name": {
1087
+
"name": "name",
1088
+
"type": "text",
1089
+
"primaryKey": false,
1090
+
"notNull": true
1091
+
},
1092
+
"path": {
1093
+
"name": "path",
1094
+
"type": "text",
1095
+
"primaryKey": false,
1096
+
"notNull": true
1097
+
},
1098
+
"parent_id": {
1099
+
"name": "parent_id",
1100
+
"type": "text",
1101
+
"primaryKey": false,
1102
+
"notNull": false
1103
+
},
1104
+
"google_drive_id": {
1105
+
"name": "google_drive_id",
1106
+
"type": "text",
1107
+
"primaryKey": false,
1108
+
"notNull": true
1109
+
},
1110
+
"file_id": {
1111
+
"name": "file_id",
1112
+
"type": "text",
1113
+
"primaryKey": false,
1114
+
"notNull": true
1115
+
},
1116
+
"xata_version": {
1117
+
"name": "xata_version",
1118
+
"type": "text",
1119
+
"primaryKey": false,
1120
+
"notNull": false
1121
+
},
1122
+
"xata_createdat": {
1123
+
"name": "xata_createdat",
1124
+
"type": "timestamp",
1125
+
"primaryKey": false,
1126
+
"notNull": true,
1127
+
"default": "now()"
1128
+
},
1129
+
"xata_updatedat": {
1130
+
"name": "xata_updatedat",
1131
+
"type": "timestamp",
1132
+
"primaryKey": false,
1133
+
"notNull": true,
1134
+
"default": "now()"
1135
+
}
1136
+
},
1137
+
"indexes": {},
1138
+
"foreignKeys": {
1139
+
"google_drive_directories_parent_id_google_drive_directories_xata_id_fk": {
1140
+
"name": "google_drive_directories_parent_id_google_drive_directories_xata_id_fk",
1141
+
"tableFrom": "google_drive_directories",
1142
+
"tableTo": "google_drive_directories",
1143
+
"columnsFrom": [
1144
+
"parent_id"
1145
+
],
1146
+
"columnsTo": [
1147
+
"xata_id"
1148
+
],
1149
+
"onDelete": "no action",
1150
+
"onUpdate": "no action"
1151
+
}
1152
+
},
1153
+
"compositePrimaryKeys": {},
1154
+
"uniqueConstraints": {
1155
+
"google_drive_directories_file_id_unique": {
1156
+
"name": "google_drive_directories_file_id_unique",
1157
+
"nullsNotDistinct": false,
1158
+
"columns": [
1159
+
"file_id"
1160
+
]
1161
+
}
1162
+
},
1163
+
"policies": {},
1164
+
"checkConstraints": {},
1165
+
"isRLSEnabled": false
1166
+
},
1167
+
"public.google_drive_paths": {
1168
+
"name": "google_drive_paths",
1169
+
"schema": "",
1170
+
"columns": {
1171
+
"xata_id": {
1172
+
"name": "xata_id",
1173
+
"type": "text",
1174
+
"primaryKey": true,
1175
+
"notNull": true
1176
+
},
1177
+
"google_drive_id": {
1178
+
"name": "google_drive_id",
1179
+
"type": "text",
1180
+
"primaryKey": false,
1181
+
"notNull": true
1182
+
},
1183
+
"track_id": {
1184
+
"name": "track_id",
1185
+
"type": "text",
1186
+
"primaryKey": false,
1187
+
"notNull": true
1188
+
},
1189
+
"name": {
1190
+
"name": "name",
1191
+
"type": "text",
1192
+
"primaryKey": false,
1193
+
"notNull": true
1194
+
},
1195
+
"directory_id": {
1196
+
"name": "directory_id",
1197
+
"type": "text",
1198
+
"primaryKey": false,
1199
+
"notNull": false
1200
+
},
1201
+
"file_id": {
1202
+
"name": "file_id",
1203
+
"type": "text",
1204
+
"primaryKey": false,
1205
+
"notNull": true
1206
+
},
1207
+
"xata_version": {
1208
+
"name": "xata_version",
1209
+
"type": "text",
1210
+
"primaryKey": false,
1211
+
"notNull": false
1212
+
},
1213
+
"xata_createdat": {
1214
+
"name": "xata_createdat",
1215
+
"type": "timestamp",
1216
+
"primaryKey": false,
1217
+
"notNull": true,
1218
+
"default": "now()"
1219
+
},
1220
+
"xata_updatedat": {
1221
+
"name": "xata_updatedat",
1222
+
"type": "timestamp",
1223
+
"primaryKey": false,
1224
+
"notNull": true,
1225
+
"default": "now()"
1226
+
}
1227
+
},
1228
+
"indexes": {},
1229
+
"foreignKeys": {
1230
+
"google_drive_paths_directory_id_google_drive_directories_xata_id_fk": {
1231
+
"name": "google_drive_paths_directory_id_google_drive_directories_xata_id_fk",
1232
+
"tableFrom": "google_drive_paths",
1233
+
"tableTo": "google_drive_directories",
1234
+
"columnsFrom": [
1235
+
"directory_id"
1236
+
],
1237
+
"columnsTo": [
1238
+
"xata_id"
1239
+
],
1240
+
"onDelete": "no action",
1241
+
"onUpdate": "no action"
1242
+
}
1243
+
},
1244
+
"compositePrimaryKeys": {},
1245
+
"uniqueConstraints": {
1246
+
"google_drive_paths_file_id_unique": {
1247
+
"name": "google_drive_paths_file_id_unique",
1248
+
"nullsNotDistinct": false,
1249
+
"columns": [
1250
+
"file_id"
1251
+
]
1252
+
}
1253
+
},
1254
+
"policies": {},
1255
+
"checkConstraints": {},
1256
+
"isRLSEnabled": false
1257
+
},
1258
+
"public.google_drive_tokens": {
1259
+
"name": "google_drive_tokens",
1260
+
"schema": "",
1261
+
"columns": {
1262
+
"xata_id": {
1263
+
"name": "xata_id",
1264
+
"type": "text",
1265
+
"primaryKey": true,
1266
+
"notNull": true
1267
+
},
1268
+
"refresh_token": {
1269
+
"name": "refresh_token",
1270
+
"type": "text",
1271
+
"primaryKey": false,
1272
+
"notNull": true
1273
+
},
1274
+
"xata_createdat": {
1275
+
"name": "xata_createdat",
1276
+
"type": "timestamp",
1277
+
"primaryKey": false,
1278
+
"notNull": true,
1279
+
"default": "now()"
1280
+
},
1281
+
"xata_updatedat": {
1282
+
"name": "xata_updatedat",
1283
+
"type": "timestamp",
1284
+
"primaryKey": false,
1285
+
"notNull": true,
1286
+
"default": "now()"
1287
+
}
1288
+
},
1289
+
"indexes": {},
1290
+
"foreignKeys": {},
1291
+
"compositePrimaryKeys": {},
1292
+
"uniqueConstraints": {},
1293
+
"policies": {},
1294
+
"checkConstraints": {},
1295
+
"isRLSEnabled": false
1296
+
},
1297
+
"public.google_drive": {
1298
+
"name": "google_drive",
1299
+
"schema": "",
1300
+
"columns": {
1301
+
"xata_id": {
1302
+
"name": "xata_id",
1303
+
"type": "text",
1304
+
"primaryKey": true,
1305
+
"notNull": true
1306
+
},
1307
+
"google_drive_token_id": {
1308
+
"name": "google_drive_token_id",
1309
+
"type": "text",
1310
+
"primaryKey": false,
1311
+
"notNull": true
1312
+
},
1313
+
"user_id": {
1314
+
"name": "user_id",
1315
+
"type": "text",
1316
+
"primaryKey": false,
1317
+
"notNull": true
1318
+
},
1319
+
"xata_version": {
1320
+
"name": "xata_version",
1321
+
"type": "text",
1322
+
"primaryKey": false,
1323
+
"notNull": false
1324
+
},
1325
+
"xata_createdat": {
1326
+
"name": "xata_createdat",
1327
+
"type": "timestamp",
1328
+
"primaryKey": false,
1329
+
"notNull": true,
1330
+
"default": "now()"
1331
+
},
1332
+
"xata_updatedat": {
1333
+
"name": "xata_updatedat",
1334
+
"type": "timestamp",
1335
+
"primaryKey": false,
1336
+
"notNull": true,
1337
+
"default": "now()"
1338
+
}
1339
+
},
1340
+
"indexes": {},
1341
+
"foreignKeys": {
1342
+
"google_drive_google_drive_token_id_google_drive_tokens_xata_id_fk": {
1343
+
"name": "google_drive_google_drive_token_id_google_drive_tokens_xata_id_fk",
1344
+
"tableFrom": "google_drive",
1345
+
"tableTo": "google_drive_tokens",
1346
+
"columnsFrom": [
1347
+
"google_drive_token_id"
1348
+
],
1349
+
"columnsTo": [
1350
+
"xata_id"
1351
+
],
1352
+
"onDelete": "no action",
1353
+
"onUpdate": "no action"
1354
+
},
1355
+
"google_drive_user_id_users_xata_id_fk": {
1356
+
"name": "google_drive_user_id_users_xata_id_fk",
1357
+
"tableFrom": "google_drive",
1358
+
"tableTo": "users",
1359
+
"columnsFrom": [
1360
+
"user_id"
1361
+
],
1362
+
"columnsTo": [
1363
+
"xata_id"
1364
+
],
1365
+
"onDelete": "no action",
1366
+
"onUpdate": "no action"
1367
+
}
1368
+
},
1369
+
"compositePrimaryKeys": {},
1370
+
"uniqueConstraints": {},
1371
+
"policies": {},
1372
+
"checkConstraints": {},
1373
+
"isRLSEnabled": false
1374
+
},
1375
+
"public.loved_tracks": {
1376
+
"name": "loved_tracks",
1377
+
"schema": "",
1378
+
"columns": {
1379
+
"xata_id": {
1380
+
"name": "xata_id",
1381
+
"type": "text",
1382
+
"primaryKey": true,
1383
+
"notNull": true
1384
+
},
1385
+
"user_id": {
1386
+
"name": "user_id",
1387
+
"type": "text",
1388
+
"primaryKey": false,
1389
+
"notNull": true
1390
+
},
1391
+
"track_id": {
1392
+
"name": "track_id",
1393
+
"type": "text",
1394
+
"primaryKey": false,
1395
+
"notNull": true
1396
+
},
1397
+
"uri": {
1398
+
"name": "uri",
1399
+
"type": "text",
1400
+
"primaryKey": false,
1401
+
"notNull": false
1402
+
},
1403
+
"xata_createdat": {
1404
+
"name": "xata_createdat",
1405
+
"type": "timestamp",
1406
+
"primaryKey": false,
1407
+
"notNull": true,
1408
+
"default": "now()"
1409
+
}
1410
+
},
1411
+
"indexes": {},
1412
+
"foreignKeys": {
1413
+
"loved_tracks_user_id_users_xata_id_fk": {
1414
+
"name": "loved_tracks_user_id_users_xata_id_fk",
1415
+
"tableFrom": "loved_tracks",
1416
+
"tableTo": "users",
1417
+
"columnsFrom": [
1418
+
"user_id"
1419
+
],
1420
+
"columnsTo": [
1421
+
"xata_id"
1422
+
],
1423
+
"onDelete": "no action",
1424
+
"onUpdate": "no action"
1425
+
},
1426
+
"loved_tracks_track_id_tracks_xata_id_fk": {
1427
+
"name": "loved_tracks_track_id_tracks_xata_id_fk",
1428
+
"tableFrom": "loved_tracks",
1429
+
"tableTo": "tracks",
1430
+
"columnsFrom": [
1431
+
"track_id"
1432
+
],
1433
+
"columnsTo": [
1434
+
"xata_id"
1435
+
],
1436
+
"onDelete": "no action",
1437
+
"onUpdate": "no action"
1438
+
}
1439
+
},
1440
+
"compositePrimaryKeys": {},
1441
+
"uniqueConstraints": {
1442
+
"loved_tracks_uri_unique": {
1443
+
"name": "loved_tracks_uri_unique",
1444
+
"nullsNotDistinct": false,
1445
+
"columns": [
1446
+
"uri"
1447
+
]
1448
+
}
1449
+
},
1450
+
"policies": {},
1451
+
"checkConstraints": {},
1452
+
"isRLSEnabled": false
1453
+
},
1454
+
"public.playlist_tracks": {
1455
+
"name": "playlist_tracks",
1456
+
"schema": "",
1457
+
"columns": {
1458
+
"xata_id": {
1459
+
"name": "xata_id",
1460
+
"type": "text",
1461
+
"primaryKey": true,
1462
+
"notNull": true
1463
+
},
1464
+
"playlist_id": {
1465
+
"name": "playlist_id",
1466
+
"type": "text",
1467
+
"primaryKey": false,
1468
+
"notNull": true
1469
+
},
1470
+
"track_id": {
1471
+
"name": "track_id",
1472
+
"type": "text",
1473
+
"primaryKey": false,
1474
+
"notNull": true
1475
+
},
1476
+
"xata_createdat": {
1477
+
"name": "xata_createdat",
1478
+
"type": "timestamp",
1479
+
"primaryKey": false,
1480
+
"notNull": true,
1481
+
"default": "now()"
1482
+
}
1483
+
},
1484
+
"indexes": {},
1485
+
"foreignKeys": {
1486
+
"playlist_tracks_playlist_id_playlists_xata_id_fk": {
1487
+
"name": "playlist_tracks_playlist_id_playlists_xata_id_fk",
1488
+
"tableFrom": "playlist_tracks",
1489
+
"tableTo": "playlists",
1490
+
"columnsFrom": [
1491
+
"playlist_id"
1492
+
],
1493
+
"columnsTo": [
1494
+
"xata_id"
1495
+
],
1496
+
"onDelete": "no action",
1497
+
"onUpdate": "no action"
1498
+
},
1499
+
"playlist_tracks_track_id_tracks_xata_id_fk": {
1500
+
"name": "playlist_tracks_track_id_tracks_xata_id_fk",
1501
+
"tableFrom": "playlist_tracks",
1502
+
"tableTo": "tracks",
1503
+
"columnsFrom": [
1504
+
"track_id"
1505
+
],
1506
+
"columnsTo": [
1507
+
"xata_id"
1508
+
],
1509
+
"onDelete": "no action",
1510
+
"onUpdate": "no action"
1511
+
}
1512
+
},
1513
+
"compositePrimaryKeys": {},
1514
+
"uniqueConstraints": {},
1515
+
"policies": {},
1516
+
"checkConstraints": {},
1517
+
"isRLSEnabled": false
1518
+
},
1519
+
"public.playlists": {
1520
+
"name": "playlists",
1521
+
"schema": "",
1522
+
"columns": {
1523
+
"xata_id": {
1524
+
"name": "xata_id",
1525
+
"type": "text",
1526
+
"primaryKey": true,
1527
+
"notNull": true
1528
+
},
1529
+
"name": {
1530
+
"name": "name",
1531
+
"type": "text",
1532
+
"primaryKey": false,
1533
+
"notNull": true
1534
+
},
1535
+
"picture": {
1536
+
"name": "picture",
1537
+
"type": "text",
1538
+
"primaryKey": false,
1539
+
"notNull": false
1540
+
},
1541
+
"description": {
1542
+
"name": "description",
1543
+
"type": "text",
1544
+
"primaryKey": false,
1545
+
"notNull": false
1546
+
},
1547
+
"uri": {
1548
+
"name": "uri",
1549
+
"type": "text",
1550
+
"primaryKey": false,
1551
+
"notNull": false
1552
+
},
1553
+
"spotify_link": {
1554
+
"name": "spotify_link",
1555
+
"type": "text",
1556
+
"primaryKey": false,
1557
+
"notNull": false
1558
+
},
1559
+
"tidal_link": {
1560
+
"name": "tidal_link",
1561
+
"type": "text",
1562
+
"primaryKey": false,
1563
+
"notNull": false
1564
+
},
1565
+
"apple_music_link": {
1566
+
"name": "apple_music_link",
1567
+
"type": "text",
1568
+
"primaryKey": false,
1569
+
"notNull": false
1570
+
},
1571
+
"created_by": {
1572
+
"name": "created_by",
1573
+
"type": "text",
1574
+
"primaryKey": false,
1575
+
"notNull": true
1576
+
},
1577
+
"xata_createdat": {
1578
+
"name": "xata_createdat",
1579
+
"type": "timestamp",
1580
+
"primaryKey": false,
1581
+
"notNull": true,
1582
+
"default": "now()"
1583
+
},
1584
+
"xata_updatedat": {
1585
+
"name": "xata_updatedat",
1586
+
"type": "timestamp",
1587
+
"primaryKey": false,
1588
+
"notNull": true,
1589
+
"default": "now()"
1590
+
}
1591
+
},
1592
+
"indexes": {},
1593
+
"foreignKeys": {
1594
+
"playlists_created_by_users_xata_id_fk": {
1595
+
"name": "playlists_created_by_users_xata_id_fk",
1596
+
"tableFrom": "playlists",
1597
+
"tableTo": "users",
1598
+
"columnsFrom": [
1599
+
"created_by"
1600
+
],
1601
+
"columnsTo": [
1602
+
"xata_id"
1603
+
],
1604
+
"onDelete": "no action",
1605
+
"onUpdate": "no action"
1606
+
}
1607
+
},
1608
+
"compositePrimaryKeys": {},
1609
+
"uniqueConstraints": {
1610
+
"playlists_uri_unique": {
1611
+
"name": "playlists_uri_unique",
1612
+
"nullsNotDistinct": false,
1613
+
"columns": [
1614
+
"uri"
1615
+
]
1616
+
}
1617
+
},
1618
+
"policies": {},
1619
+
"checkConstraints": {},
1620
+
"isRLSEnabled": false
1621
+
},
1622
+
"public.profile_shouts": {
1623
+
"name": "profile_shouts",
1624
+
"schema": "",
1625
+
"columns": {
1626
+
"xata_id": {
1627
+
"name": "xata_id",
1628
+
"type": "text",
1629
+
"primaryKey": true,
1630
+
"notNull": true
1631
+
},
1632
+
"user_id": {
1633
+
"name": "user_id",
1634
+
"type": "text",
1635
+
"primaryKey": false,
1636
+
"notNull": true
1637
+
},
1638
+
"shout_id": {
1639
+
"name": "shout_id",
1640
+
"type": "text",
1641
+
"primaryKey": false,
1642
+
"notNull": true
1643
+
},
1644
+
"xata_createdat": {
1645
+
"name": "xata_createdat",
1646
+
"type": "timestamp",
1647
+
"primaryKey": false,
1648
+
"notNull": true,
1649
+
"default": "now()"
1650
+
}
1651
+
},
1652
+
"indexes": {},
1653
+
"foreignKeys": {
1654
+
"profile_shouts_user_id_users_xata_id_fk": {
1655
+
"name": "profile_shouts_user_id_users_xata_id_fk",
1656
+
"tableFrom": "profile_shouts",
1657
+
"tableTo": "users",
1658
+
"columnsFrom": [
1659
+
"user_id"
1660
+
],
1661
+
"columnsTo": [
1662
+
"xata_id"
1663
+
],
1664
+
"onDelete": "no action",
1665
+
"onUpdate": "no action"
1666
+
},
1667
+
"profile_shouts_shout_id_shouts_xata_id_fk": {
1668
+
"name": "profile_shouts_shout_id_shouts_xata_id_fk",
1669
+
"tableFrom": "profile_shouts",
1670
+
"tableTo": "shouts",
1671
+
"columnsFrom": [
1672
+
"shout_id"
1673
+
],
1674
+
"columnsTo": [
1675
+
"xata_id"
1676
+
],
1677
+
"onDelete": "no action",
1678
+
"onUpdate": "no action"
1679
+
}
1680
+
},
1681
+
"compositePrimaryKeys": {},
1682
+
"uniqueConstraints": {},
1683
+
"policies": {},
1684
+
"checkConstraints": {},
1685
+
"isRLSEnabled": false
1686
+
},
1687
+
"public.queue_tracks": {
1688
+
"name": "queue_tracks",
1689
+
"schema": "",
1690
+
"columns": {
1691
+
"xata_id": {
1692
+
"name": "xata_id",
1693
+
"type": "text",
1694
+
"primaryKey": true,
1695
+
"notNull": true
1696
+
},
1697
+
"user_id": {
1698
+
"name": "user_id",
1699
+
"type": "text",
1700
+
"primaryKey": false,
1701
+
"notNull": true
1702
+
},
1703
+
"track_id": {
1704
+
"name": "track_id",
1705
+
"type": "text",
1706
+
"primaryKey": false,
1707
+
"notNull": true
1708
+
},
1709
+
"position": {
1710
+
"name": "position",
1711
+
"type": "integer",
1712
+
"primaryKey": false,
1713
+
"notNull": true
1714
+
},
1715
+
"file_uri": {
1716
+
"name": "file_uri",
1717
+
"type": "text",
1718
+
"primaryKey": false,
1719
+
"notNull": true
1720
+
},
1721
+
"xata_version": {
1722
+
"name": "xata_version",
1723
+
"type": "integer",
1724
+
"primaryKey": false,
1725
+
"notNull": true,
1726
+
"default": 0
1727
+
},
1728
+
"xata_createdat": {
1729
+
"name": "xata_createdat",
1730
+
"type": "timestamp",
1731
+
"primaryKey": false,
1732
+
"notNull": true,
1733
+
"default": "now()"
1734
+
},
1735
+
"xata_updatedat": {
1736
+
"name": "xata_updatedat",
1737
+
"type": "timestamp",
1738
+
"primaryKey": false,
1739
+
"notNull": true,
1740
+
"default": "now()"
1741
+
}
1742
+
},
1743
+
"indexes": {},
1744
+
"foreignKeys": {
1745
+
"queue_tracks_user_id_users_xata_id_fk": {
1746
+
"name": "queue_tracks_user_id_users_xata_id_fk",
1747
+
"tableFrom": "queue_tracks",
1748
+
"tableTo": "users",
1749
+
"columnsFrom": [
1750
+
"user_id"
1751
+
],
1752
+
"columnsTo": [
1753
+
"xata_id"
1754
+
],
1755
+
"onDelete": "no action",
1756
+
"onUpdate": "no action"
1757
+
},
1758
+
"queue_tracks_track_id_tracks_xata_id_fk": {
1759
+
"name": "queue_tracks_track_id_tracks_xata_id_fk",
1760
+
"tableFrom": "queue_tracks",
1761
+
"tableTo": "tracks",
1762
+
"columnsFrom": [
1763
+
"track_id"
1764
+
],
1765
+
"columnsTo": [
1766
+
"xata_id"
1767
+
],
1768
+
"onDelete": "no action",
1769
+
"onUpdate": "no action"
1770
+
}
1771
+
},
1772
+
"compositePrimaryKeys": {},
1773
+
"uniqueConstraints": {},
1774
+
"policies": {},
1775
+
"checkConstraints": {},
1776
+
"isRLSEnabled": false
1777
+
},
1778
+
"public.scrobbles": {
1779
+
"name": "scrobbles",
1780
+
"schema": "",
1781
+
"columns": {
1782
+
"xata_id": {
1783
+
"name": "xata_id",
1784
+
"type": "text",
1785
+
"primaryKey": true,
1786
+
"notNull": true
1787
+
},
1788
+
"user_id": {
1789
+
"name": "user_id",
1790
+
"type": "text",
1791
+
"primaryKey": false,
1792
+
"notNull": false
1793
+
},
1794
+
"track_id": {
1795
+
"name": "track_id",
1796
+
"type": "text",
1797
+
"primaryKey": false,
1798
+
"notNull": false
1799
+
},
1800
+
"album_id": {
1801
+
"name": "album_id",
1802
+
"type": "text",
1803
+
"primaryKey": false,
1804
+
"notNull": false
1805
+
},
1806
+
"artist_id": {
1807
+
"name": "artist_id",
1808
+
"type": "text",
1809
+
"primaryKey": false,
1810
+
"notNull": false
1811
+
},
1812
+
"uri": {
1813
+
"name": "uri",
1814
+
"type": "text",
1815
+
"primaryKey": false,
1816
+
"notNull": false
1817
+
},
1818
+
"xata_createdat": {
1819
+
"name": "xata_createdat",
1820
+
"type": "timestamp",
1821
+
"primaryKey": false,
1822
+
"notNull": true,
1823
+
"default": "now()"
1824
+
},
1825
+
"xata_updatedat": {
1826
+
"name": "xata_updatedat",
1827
+
"type": "timestamp",
1828
+
"primaryKey": false,
1829
+
"notNull": true,
1830
+
"default": "now()"
1831
+
},
1832
+
"xata_version": {
1833
+
"name": "xata_version",
1834
+
"type": "integer",
1835
+
"primaryKey": false,
1836
+
"notNull": false
1837
+
},
1838
+
"timestamp": {
1839
+
"name": "timestamp",
1840
+
"type": "timestamp",
1841
+
"primaryKey": false,
1842
+
"notNull": true,
1843
+
"default": "now()"
1844
+
}
1845
+
},
1846
+
"indexes": {},
1847
+
"foreignKeys": {
1848
+
"scrobbles_user_id_users_xata_id_fk": {
1849
+
"name": "scrobbles_user_id_users_xata_id_fk",
1850
+
"tableFrom": "scrobbles",
1851
+
"tableTo": "users",
1852
+
"columnsFrom": [
1853
+
"user_id"
1854
+
],
1855
+
"columnsTo": [
1856
+
"xata_id"
1857
+
],
1858
+
"onDelete": "no action",
1859
+
"onUpdate": "no action"
1860
+
},
1861
+
"scrobbles_track_id_tracks_xata_id_fk": {
1862
+
"name": "scrobbles_track_id_tracks_xata_id_fk",
1863
+
"tableFrom": "scrobbles",
1864
+
"tableTo": "tracks",
1865
+
"columnsFrom": [
1866
+
"track_id"
1867
+
],
1868
+
"columnsTo": [
1869
+
"xata_id"
1870
+
],
1871
+
"onDelete": "no action",
1872
+
"onUpdate": "no action"
1873
+
},
1874
+
"scrobbles_album_id_albums_xata_id_fk": {
1875
+
"name": "scrobbles_album_id_albums_xata_id_fk",
1876
+
"tableFrom": "scrobbles",
1877
+
"tableTo": "albums",
1878
+
"columnsFrom": [
1879
+
"album_id"
1880
+
],
1881
+
"columnsTo": [
1882
+
"xata_id"
1883
+
],
1884
+
"onDelete": "no action",
1885
+
"onUpdate": "no action"
1886
+
},
1887
+
"scrobbles_artist_id_artists_xata_id_fk": {
1888
+
"name": "scrobbles_artist_id_artists_xata_id_fk",
1889
+
"tableFrom": "scrobbles",
1890
+
"tableTo": "artists",
1891
+
"columnsFrom": [
1892
+
"artist_id"
1893
+
],
1894
+
"columnsTo": [
1895
+
"xata_id"
1896
+
],
1897
+
"onDelete": "no action",
1898
+
"onUpdate": "no action"
1899
+
}
1900
+
},
1901
+
"compositePrimaryKeys": {},
1902
+
"uniqueConstraints": {
1903
+
"scrobbles_uri_unique": {
1904
+
"name": "scrobbles_uri_unique",
1905
+
"nullsNotDistinct": false,
1906
+
"columns": [
1907
+
"uri"
1908
+
]
1909
+
}
1910
+
},
1911
+
"policies": {},
1912
+
"checkConstraints": {},
1913
+
"isRLSEnabled": false
1914
+
},
1915
+
"public.shout_likes": {
1916
+
"name": "shout_likes",
1917
+
"schema": "",
1918
+
"columns": {
1919
+
"xata_id": {
1920
+
"name": "xata_id",
1921
+
"type": "text",
1922
+
"primaryKey": true,
1923
+
"notNull": true
1924
+
},
1925
+
"user_id": {
1926
+
"name": "user_id",
1927
+
"type": "text",
1928
+
"primaryKey": false,
1929
+
"notNull": true
1930
+
},
1931
+
"shout_id": {
1932
+
"name": "shout_id",
1933
+
"type": "text",
1934
+
"primaryKey": false,
1935
+
"notNull": true
1936
+
},
1937
+
"xata_createdat": {
1938
+
"name": "xata_createdat",
1939
+
"type": "timestamp",
1940
+
"primaryKey": false,
1941
+
"notNull": true,
1942
+
"default": "now()"
1943
+
},
1944
+
"uri": {
1945
+
"name": "uri",
1946
+
"type": "text",
1947
+
"primaryKey": false,
1948
+
"notNull": true
1949
+
}
1950
+
},
1951
+
"indexes": {},
1952
+
"foreignKeys": {
1953
+
"shout_likes_user_id_users_xata_id_fk": {
1954
+
"name": "shout_likes_user_id_users_xata_id_fk",
1955
+
"tableFrom": "shout_likes",
1956
+
"tableTo": "users",
1957
+
"columnsFrom": [
1958
+
"user_id"
1959
+
],
1960
+
"columnsTo": [
1961
+
"xata_id"
1962
+
],
1963
+
"onDelete": "no action",
1964
+
"onUpdate": "no action"
1965
+
},
1966
+
"shout_likes_shout_id_shouts_xata_id_fk": {
1967
+
"name": "shout_likes_shout_id_shouts_xata_id_fk",
1968
+
"tableFrom": "shout_likes",
1969
+
"tableTo": "shouts",
1970
+
"columnsFrom": [
1971
+
"shout_id"
1972
+
],
1973
+
"columnsTo": [
1974
+
"xata_id"
1975
+
],
1976
+
"onDelete": "no action",
1977
+
"onUpdate": "no action"
1978
+
}
1979
+
},
1980
+
"compositePrimaryKeys": {},
1981
+
"uniqueConstraints": {
1982
+
"shout_likes_uri_unique": {
1983
+
"name": "shout_likes_uri_unique",
1984
+
"nullsNotDistinct": false,
1985
+
"columns": [
1986
+
"uri"
1987
+
]
1988
+
}
1989
+
},
1990
+
"policies": {},
1991
+
"checkConstraints": {},
1992
+
"isRLSEnabled": false
1993
+
},
1994
+
"public.shout_reports": {
1995
+
"name": "shout_reports",
1996
+
"schema": "",
1997
+
"columns": {
1998
+
"xata_id": {
1999
+
"name": "xata_id",
2000
+
"type": "text",
2001
+
"primaryKey": true,
2002
+
"notNull": true
2003
+
},
2004
+
"user_id": {
2005
+
"name": "user_id",
2006
+
"type": "text",
2007
+
"primaryKey": false,
2008
+
"notNull": true
2009
+
},
2010
+
"shout_id": {
2011
+
"name": "shout_id",
2012
+
"type": "text",
2013
+
"primaryKey": false,
2014
+
"notNull": true
2015
+
},
2016
+
"xata_createdat": {
2017
+
"name": "xata_createdat",
2018
+
"type": "timestamp",
2019
+
"primaryKey": false,
2020
+
"notNull": true,
2021
+
"default": "now()"
2022
+
}
2023
+
},
2024
+
"indexes": {},
2025
+
"foreignKeys": {
2026
+
"shout_reports_user_id_users_xata_id_fk": {
2027
+
"name": "shout_reports_user_id_users_xata_id_fk",
2028
+
"tableFrom": "shout_reports",
2029
+
"tableTo": "users",
2030
+
"columnsFrom": [
2031
+
"user_id"
2032
+
],
2033
+
"columnsTo": [
2034
+
"xata_id"
2035
+
],
2036
+
"onDelete": "no action",
2037
+
"onUpdate": "no action"
2038
+
},
2039
+
"shout_reports_shout_id_shouts_xata_id_fk": {
2040
+
"name": "shout_reports_shout_id_shouts_xata_id_fk",
2041
+
"tableFrom": "shout_reports",
2042
+
"tableTo": "shouts",
2043
+
"columnsFrom": [
2044
+
"shout_id"
2045
+
],
2046
+
"columnsTo": [
2047
+
"xata_id"
2048
+
],
2049
+
"onDelete": "no action",
2050
+
"onUpdate": "no action"
2051
+
}
2052
+
},
2053
+
"compositePrimaryKeys": {},
2054
+
"uniqueConstraints": {},
2055
+
"policies": {},
2056
+
"checkConstraints": {},
2057
+
"isRLSEnabled": false
2058
+
},
2059
+
"public.shouts": {
2060
+
"name": "shouts",
2061
+
"schema": "",
2062
+
"columns": {
2063
+
"xata_id": {
2064
+
"name": "xata_id",
2065
+
"type": "text",
2066
+
"primaryKey": true,
2067
+
"notNull": true
2068
+
},
2069
+
"content": {
2070
+
"name": "content",
2071
+
"type": "text",
2072
+
"primaryKey": false,
2073
+
"notNull": true
2074
+
},
2075
+
"track_id": {
2076
+
"name": "track_id",
2077
+
"type": "text",
2078
+
"primaryKey": false,
2079
+
"notNull": false
2080
+
},
2081
+
"artist_id": {
2082
+
"name": "artist_id",
2083
+
"type": "text",
2084
+
"primaryKey": false,
2085
+
"notNull": false
2086
+
},
2087
+
"album_id": {
2088
+
"name": "album_id",
2089
+
"type": "text",
2090
+
"primaryKey": false,
2091
+
"notNull": false
2092
+
},
2093
+
"scrobble_id": {
2094
+
"name": "scrobble_id",
2095
+
"type": "text",
2096
+
"primaryKey": false,
2097
+
"notNull": false
2098
+
},
2099
+
"uri": {
2100
+
"name": "uri",
2101
+
"type": "text",
2102
+
"primaryKey": false,
2103
+
"notNull": true
2104
+
},
2105
+
"author_id": {
2106
+
"name": "author_id",
2107
+
"type": "text",
2108
+
"primaryKey": false,
2109
+
"notNull": true
2110
+
},
2111
+
"parent_id": {
2112
+
"name": "parent_id",
2113
+
"type": "text",
2114
+
"primaryKey": false,
2115
+
"notNull": false
2116
+
},
2117
+
"xata_createdat": {
2118
+
"name": "xata_createdat",
2119
+
"type": "timestamp",
2120
+
"primaryKey": false,
2121
+
"notNull": true,
2122
+
"default": "now()"
2123
+
},
2124
+
"xata_updatedat": {
2125
+
"name": "xata_updatedat",
2126
+
"type": "timestamp",
2127
+
"primaryKey": false,
2128
+
"notNull": true,
2129
+
"default": "now()"
2130
+
}
2131
+
},
2132
+
"indexes": {},
2133
+
"foreignKeys": {
2134
+
"shouts_track_id_tracks_xata_id_fk": {
2135
+
"name": "shouts_track_id_tracks_xata_id_fk",
2136
+
"tableFrom": "shouts",
2137
+
"tableTo": "tracks",
2138
+
"columnsFrom": [
2139
+
"track_id"
2140
+
],
2141
+
"columnsTo": [
2142
+
"xata_id"
2143
+
],
2144
+
"onDelete": "no action",
2145
+
"onUpdate": "no action"
2146
+
},
2147
+
"shouts_artist_id_users_xata_id_fk": {
2148
+
"name": "shouts_artist_id_users_xata_id_fk",
2149
+
"tableFrom": "shouts",
2150
+
"tableTo": "users",
2151
+
"columnsFrom": [
2152
+
"artist_id"
2153
+
],
2154
+
"columnsTo": [
2155
+
"xata_id"
2156
+
],
2157
+
"onDelete": "no action",
2158
+
"onUpdate": "no action"
2159
+
},
2160
+
"shouts_album_id_albums_xata_id_fk": {
2161
+
"name": "shouts_album_id_albums_xata_id_fk",
2162
+
"tableFrom": "shouts",
2163
+
"tableTo": "albums",
2164
+
"columnsFrom": [
2165
+
"album_id"
2166
+
],
2167
+
"columnsTo": [
2168
+
"xata_id"
2169
+
],
2170
+
"onDelete": "no action",
2171
+
"onUpdate": "no action"
2172
+
},
2173
+
"shouts_scrobble_id_scrobbles_xata_id_fk": {
2174
+
"name": "shouts_scrobble_id_scrobbles_xata_id_fk",
2175
+
"tableFrom": "shouts",
2176
+
"tableTo": "scrobbles",
2177
+
"columnsFrom": [
2178
+
"scrobble_id"
2179
+
],
2180
+
"columnsTo": [
2181
+
"xata_id"
2182
+
],
2183
+
"onDelete": "no action",
2184
+
"onUpdate": "no action"
2185
+
},
2186
+
"shouts_author_id_users_xata_id_fk": {
2187
+
"name": "shouts_author_id_users_xata_id_fk",
2188
+
"tableFrom": "shouts",
2189
+
"tableTo": "users",
2190
+
"columnsFrom": [
2191
+
"author_id"
2192
+
],
2193
+
"columnsTo": [
2194
+
"xata_id"
2195
+
],
2196
+
"onDelete": "no action",
2197
+
"onUpdate": "no action"
2198
+
},
2199
+
"shouts_parent_id_shouts_xata_id_fk": {
2200
+
"name": "shouts_parent_id_shouts_xata_id_fk",
2201
+
"tableFrom": "shouts",
2202
+
"tableTo": "shouts",
2203
+
"columnsFrom": [
2204
+
"parent_id"
2205
+
],
2206
+
"columnsTo": [
2207
+
"xata_id"
2208
+
],
2209
+
"onDelete": "no action",
2210
+
"onUpdate": "no action"
2211
+
}
2212
+
},
2213
+
"compositePrimaryKeys": {},
2214
+
"uniqueConstraints": {
2215
+
"shouts_uri_unique": {
2216
+
"name": "shouts_uri_unique",
2217
+
"nullsNotDistinct": false,
2218
+
"columns": [
2219
+
"uri"
2220
+
]
2221
+
}
2222
+
},
2223
+
"policies": {},
2224
+
"checkConstraints": {},
2225
+
"isRLSEnabled": false
2226
+
},
2227
+
"public.spotify_accounts": {
2228
+
"name": "spotify_accounts",
2229
+
"schema": "",
2230
+
"columns": {
2231
+
"xata_id": {
2232
+
"name": "xata_id",
2233
+
"type": "text",
2234
+
"primaryKey": true,
2235
+
"notNull": true
2236
+
},
2237
+
"xata_version": {
2238
+
"name": "xata_version",
2239
+
"type": "integer",
2240
+
"primaryKey": false,
2241
+
"notNull": false
2242
+
},
2243
+
"email": {
2244
+
"name": "email",
2245
+
"type": "text",
2246
+
"primaryKey": false,
2247
+
"notNull": true
2248
+
},
2249
+
"user_id": {
2250
+
"name": "user_id",
2251
+
"type": "text",
2252
+
"primaryKey": false,
2253
+
"notNull": true
2254
+
},
2255
+
"is_beta_user": {
2256
+
"name": "is_beta_user",
2257
+
"type": "boolean",
2258
+
"primaryKey": false,
2259
+
"notNull": true,
2260
+
"default": false
2261
+
},
2262
+
"xata_createdat": {
2263
+
"name": "xata_createdat",
2264
+
"type": "timestamp",
2265
+
"primaryKey": false,
2266
+
"notNull": true,
2267
+
"default": "now()"
2268
+
},
2269
+
"xata_updatedat": {
2270
+
"name": "xata_updatedat",
2271
+
"type": "timestamp",
2272
+
"primaryKey": false,
2273
+
"notNull": true,
2274
+
"default": "now()"
2275
+
}
2276
+
},
2277
+
"indexes": {},
2278
+
"foreignKeys": {
2279
+
"spotify_accounts_user_id_users_xata_id_fk": {
2280
+
"name": "spotify_accounts_user_id_users_xata_id_fk",
2281
+
"tableFrom": "spotify_accounts",
2282
+
"tableTo": "users",
2283
+
"columnsFrom": [
2284
+
"user_id"
2285
+
],
2286
+
"columnsTo": [
2287
+
"xata_id"
2288
+
],
2289
+
"onDelete": "no action",
2290
+
"onUpdate": "no action"
2291
+
}
2292
+
},
2293
+
"compositePrimaryKeys": {},
2294
+
"uniqueConstraints": {},
2295
+
"policies": {},
2296
+
"checkConstraints": {},
2297
+
"isRLSEnabled": false
2298
+
},
2299
+
"public.spotify_tokens": {
2300
+
"name": "spotify_tokens",
2301
+
"schema": "",
2302
+
"columns": {
2303
+
"xata_id": {
2304
+
"name": "xata_id",
2305
+
"type": "text",
2306
+
"primaryKey": true,
2307
+
"notNull": true
2308
+
},
2309
+
"xata_version": {
2310
+
"name": "xata_version",
2311
+
"type": "integer",
2312
+
"primaryKey": false,
2313
+
"notNull": false
2314
+
},
2315
+
"access_token": {
2316
+
"name": "access_token",
2317
+
"type": "text",
2318
+
"primaryKey": false,
2319
+
"notNull": true
2320
+
},
2321
+
"refresh_token": {
2322
+
"name": "refresh_token",
2323
+
"type": "text",
2324
+
"primaryKey": false,
2325
+
"notNull": true
2326
+
},
2327
+
"user_id": {
2328
+
"name": "user_id",
2329
+
"type": "text",
2330
+
"primaryKey": false,
2331
+
"notNull": true
2332
+
},
2333
+
"xata_createdat": {
2334
+
"name": "xata_createdat",
2335
+
"type": "timestamp",
2336
+
"primaryKey": false,
2337
+
"notNull": true,
2338
+
"default": "now()"
2339
+
},
2340
+
"xata_updatedat": {
2341
+
"name": "xata_updatedat",
2342
+
"type": "timestamp",
2343
+
"primaryKey": false,
2344
+
"notNull": true,
2345
+
"default": "now()"
2346
+
}
2347
+
},
2348
+
"indexes": {},
2349
+
"foreignKeys": {
2350
+
"spotify_tokens_user_id_users_xata_id_fk": {
2351
+
"name": "spotify_tokens_user_id_users_xata_id_fk",
2352
+
"tableFrom": "spotify_tokens",
2353
+
"tableTo": "users",
2354
+
"columnsFrom": [
2355
+
"user_id"
2356
+
],
2357
+
"columnsTo": [
2358
+
"xata_id"
2359
+
],
2360
+
"onDelete": "no action",
2361
+
"onUpdate": "no action"
2362
+
}
2363
+
},
2364
+
"compositePrimaryKeys": {},
2365
+
"uniqueConstraints": {},
2366
+
"policies": {},
2367
+
"checkConstraints": {},
2368
+
"isRLSEnabled": false
2369
+
},
2370
+
"public.tracks": {
2371
+
"name": "tracks",
2372
+
"schema": "",
2373
+
"columns": {
2374
+
"xata_id": {
2375
+
"name": "xata_id",
2376
+
"type": "text",
2377
+
"primaryKey": true,
2378
+
"notNull": true
2379
+
},
2380
+
"title": {
2381
+
"name": "title",
2382
+
"type": "text",
2383
+
"primaryKey": false,
2384
+
"notNull": true
2385
+
},
2386
+
"artist": {
2387
+
"name": "artist",
2388
+
"type": "text",
2389
+
"primaryKey": false,
2390
+
"notNull": true
2391
+
},
2392
+
"album_artist": {
2393
+
"name": "album_artist",
2394
+
"type": "text",
2395
+
"primaryKey": false,
2396
+
"notNull": true
2397
+
},
2398
+
"album_art": {
2399
+
"name": "album_art",
2400
+
"type": "text",
2401
+
"primaryKey": false,
2402
+
"notNull": false
2403
+
},
2404
+
"album": {
2405
+
"name": "album",
2406
+
"type": "text",
2407
+
"primaryKey": false,
2408
+
"notNull": true
2409
+
},
2410
+
"track_number": {
2411
+
"name": "track_number",
2412
+
"type": "integer",
2413
+
"primaryKey": false,
2414
+
"notNull": false
2415
+
},
2416
+
"duration": {
2417
+
"name": "duration",
2418
+
"type": "integer",
2419
+
"primaryKey": false,
2420
+
"notNull": true
2421
+
},
2422
+
"mb_id": {
2423
+
"name": "mb_id",
2424
+
"type": "text",
2425
+
"primaryKey": false,
2426
+
"notNull": false
2427
+
},
2428
+
"youtube_link": {
2429
+
"name": "youtube_link",
2430
+
"type": "text",
2431
+
"primaryKey": false,
2432
+
"notNull": false
2433
+
},
2434
+
"spotify_link": {
2435
+
"name": "spotify_link",
2436
+
"type": "text",
2437
+
"primaryKey": false,
2438
+
"notNull": false
2439
+
},
2440
+
"apple_music_link": {
2441
+
"name": "apple_music_link",
2442
+
"type": "text",
2443
+
"primaryKey": false,
2444
+
"notNull": false
2445
+
},
2446
+
"tidal_link": {
2447
+
"name": "tidal_link",
2448
+
"type": "text",
2449
+
"primaryKey": false,
2450
+
"notNull": false
2451
+
},
2452
+
"sha256": {
2453
+
"name": "sha256",
2454
+
"type": "text",
2455
+
"primaryKey": false,
2456
+
"notNull": true
2457
+
},
2458
+
"disc_number": {
2459
+
"name": "disc_number",
2460
+
"type": "integer",
2461
+
"primaryKey": false,
2462
+
"notNull": false
2463
+
},
2464
+
"lyrics": {
2465
+
"name": "lyrics",
2466
+
"type": "text",
2467
+
"primaryKey": false,
2468
+
"notNull": false
2469
+
},
2470
+
"composer": {
2471
+
"name": "composer",
2472
+
"type": "text",
2473
+
"primaryKey": false,
2474
+
"notNull": false
2475
+
},
2476
+
"genre": {
2477
+
"name": "genre",
2478
+
"type": "text",
2479
+
"primaryKey": false,
2480
+
"notNull": false
2481
+
},
2482
+
"label": {
2483
+
"name": "label",
2484
+
"type": "text",
2485
+
"primaryKey": false,
2486
+
"notNull": false
2487
+
},
2488
+
"copyright_message": {
2489
+
"name": "copyright_message",
2490
+
"type": "text",
2491
+
"primaryKey": false,
2492
+
"notNull": false
2493
+
},
2494
+
"uri": {
2495
+
"name": "uri",
2496
+
"type": "text",
2497
+
"primaryKey": false,
2498
+
"notNull": false
2499
+
},
2500
+
"album_uri": {
2501
+
"name": "album_uri",
2502
+
"type": "text",
2503
+
"primaryKey": false,
2504
+
"notNull": false
2505
+
},
2506
+
"artist_uri": {
2507
+
"name": "artist_uri",
2508
+
"type": "text",
2509
+
"primaryKey": false,
2510
+
"notNull": false
2511
+
},
2512
+
"xata_createdat": {
2513
+
"name": "xata_createdat",
2514
+
"type": "timestamp",
2515
+
"primaryKey": false,
2516
+
"notNull": true,
2517
+
"default": "now()"
2518
+
},
2519
+
"xata_updatedat": {
2520
+
"name": "xata_updatedat",
2521
+
"type": "timestamp",
2522
+
"primaryKey": false,
2523
+
"notNull": true,
2524
+
"default": "now()"
2525
+
},
2526
+
"xata_version": {
2527
+
"name": "xata_version",
2528
+
"type": "integer",
2529
+
"primaryKey": false,
2530
+
"notNull": false
2531
+
}
2532
+
},
2533
+
"indexes": {},
2534
+
"foreignKeys": {},
2535
+
"compositePrimaryKeys": {},
2536
+
"uniqueConstraints": {
2537
+
"tracks_mb_id_unique": {
2538
+
"name": "tracks_mb_id_unique",
2539
+
"nullsNotDistinct": false,
2540
+
"columns": [
2541
+
"mb_id"
2542
+
]
2543
+
},
2544
+
"tracks_youtube_link_unique": {
2545
+
"name": "tracks_youtube_link_unique",
2546
+
"nullsNotDistinct": false,
2547
+
"columns": [
2548
+
"youtube_link"
2549
+
]
2550
+
},
2551
+
"tracks_spotify_link_unique": {
2552
+
"name": "tracks_spotify_link_unique",
2553
+
"nullsNotDistinct": false,
2554
+
"columns": [
2555
+
"spotify_link"
2556
+
]
2557
+
},
2558
+
"tracks_apple_music_link_unique": {
2559
+
"name": "tracks_apple_music_link_unique",
2560
+
"nullsNotDistinct": false,
2561
+
"columns": [
2562
+
"apple_music_link"
2563
+
]
2564
+
},
2565
+
"tracks_tidal_link_unique": {
2566
+
"name": "tracks_tidal_link_unique",
2567
+
"nullsNotDistinct": false,
2568
+
"columns": [
2569
+
"tidal_link"
2570
+
]
2571
+
},
2572
+
"tracks_sha256_unique": {
2573
+
"name": "tracks_sha256_unique",
2574
+
"nullsNotDistinct": false,
2575
+
"columns": [
2576
+
"sha256"
2577
+
]
2578
+
},
2579
+
"tracks_uri_unique": {
2580
+
"name": "tracks_uri_unique",
2581
+
"nullsNotDistinct": false,
2582
+
"columns": [
2583
+
"uri"
2584
+
]
2585
+
}
2586
+
},
2587
+
"policies": {},
2588
+
"checkConstraints": {},
2589
+
"isRLSEnabled": false
2590
+
},
2591
+
"public.user_albums": {
2592
+
"name": "user_albums",
2593
+
"schema": "",
2594
+
"columns": {
2595
+
"xata_id": {
2596
+
"name": "xata_id",
2597
+
"type": "text",
2598
+
"primaryKey": true,
2599
+
"notNull": true
2600
+
},
2601
+
"user_id": {
2602
+
"name": "user_id",
2603
+
"type": "text",
2604
+
"primaryKey": false,
2605
+
"notNull": true
2606
+
},
2607
+
"album_id": {
2608
+
"name": "album_id",
2609
+
"type": "text",
2610
+
"primaryKey": false,
2611
+
"notNull": true
2612
+
},
2613
+
"xata_createdat": {
2614
+
"name": "xata_createdat",
2615
+
"type": "timestamp",
2616
+
"primaryKey": false,
2617
+
"notNull": true,
2618
+
"default": "now()"
2619
+
},
2620
+
"xata_updatedat": {
2621
+
"name": "xata_updatedat",
2622
+
"type": "timestamp",
2623
+
"primaryKey": false,
2624
+
"notNull": true,
2625
+
"default": "now()"
2626
+
},
2627
+
"xata_version": {
2628
+
"name": "xata_version",
2629
+
"type": "integer",
2630
+
"primaryKey": false,
2631
+
"notNull": false
2632
+
},
2633
+
"scrobbles": {
2634
+
"name": "scrobbles",
2635
+
"type": "integer",
2636
+
"primaryKey": false,
2637
+
"notNull": false
2638
+
},
2639
+
"uri": {
2640
+
"name": "uri",
2641
+
"type": "text",
2642
+
"primaryKey": false,
2643
+
"notNull": true
2644
+
}
2645
+
},
2646
+
"indexes": {},
2647
+
"foreignKeys": {
2648
+
"user_albums_user_id_users_xata_id_fk": {
2649
+
"name": "user_albums_user_id_users_xata_id_fk",
2650
+
"tableFrom": "user_albums",
2651
+
"tableTo": "users",
2652
+
"columnsFrom": [
2653
+
"user_id"
2654
+
],
2655
+
"columnsTo": [
2656
+
"xata_id"
2657
+
],
2658
+
"onDelete": "no action",
2659
+
"onUpdate": "no action"
2660
+
},
2661
+
"user_albums_album_id_albums_xata_id_fk": {
2662
+
"name": "user_albums_album_id_albums_xata_id_fk",
2663
+
"tableFrom": "user_albums",
2664
+
"tableTo": "albums",
2665
+
"columnsFrom": [
2666
+
"album_id"
2667
+
],
2668
+
"columnsTo": [
2669
+
"xata_id"
2670
+
],
2671
+
"onDelete": "no action",
2672
+
"onUpdate": "no action"
2673
+
}
2674
+
},
2675
+
"compositePrimaryKeys": {},
2676
+
"uniqueConstraints": {
2677
+
"user_albums_uri_unique": {
2678
+
"name": "user_albums_uri_unique",
2679
+
"nullsNotDistinct": false,
2680
+
"columns": [
2681
+
"uri"
2682
+
]
2683
+
}
2684
+
},
2685
+
"policies": {},
2686
+
"checkConstraints": {},
2687
+
"isRLSEnabled": false
2688
+
},
2689
+
"public.user_artists": {
2690
+
"name": "user_artists",
2691
+
"schema": "",
2692
+
"columns": {
2693
+
"xata_id": {
2694
+
"name": "xata_id",
2695
+
"type": "text",
2696
+
"primaryKey": true,
2697
+
"notNull": true
2698
+
},
2699
+
"user_id": {
2700
+
"name": "user_id",
2701
+
"type": "text",
2702
+
"primaryKey": false,
2703
+
"notNull": true
2704
+
},
2705
+
"artist_id": {
2706
+
"name": "artist_id",
2707
+
"type": "text",
2708
+
"primaryKey": false,
2709
+
"notNull": true
2710
+
},
2711
+
"xata_createdat": {
2712
+
"name": "xata_createdat",
2713
+
"type": "timestamp",
2714
+
"primaryKey": false,
2715
+
"notNull": true,
2716
+
"default": "now()"
2717
+
},
2718
+
"xata_updatedat": {
2719
+
"name": "xata_updatedat",
2720
+
"type": "timestamp",
2721
+
"primaryKey": false,
2722
+
"notNull": true,
2723
+
"default": "now()"
2724
+
},
2725
+
"xata_version": {
2726
+
"name": "xata_version",
2727
+
"type": "integer",
2728
+
"primaryKey": false,
2729
+
"notNull": false
2730
+
},
2731
+
"scrobbles": {
2732
+
"name": "scrobbles",
2733
+
"type": "integer",
2734
+
"primaryKey": false,
2735
+
"notNull": false
2736
+
},
2737
+
"uri": {
2738
+
"name": "uri",
2739
+
"type": "text",
2740
+
"primaryKey": false,
2741
+
"notNull": true
2742
+
}
2743
+
},
2744
+
"indexes": {},
2745
+
"foreignKeys": {
2746
+
"user_artists_user_id_users_xata_id_fk": {
2747
+
"name": "user_artists_user_id_users_xata_id_fk",
2748
+
"tableFrom": "user_artists",
2749
+
"tableTo": "users",
2750
+
"columnsFrom": [
2751
+
"user_id"
2752
+
],
2753
+
"columnsTo": [
2754
+
"xata_id"
2755
+
],
2756
+
"onDelete": "no action",
2757
+
"onUpdate": "no action"
2758
+
},
2759
+
"user_artists_artist_id_artists_xata_id_fk": {
2760
+
"name": "user_artists_artist_id_artists_xata_id_fk",
2761
+
"tableFrom": "user_artists",
2762
+
"tableTo": "artists",
2763
+
"columnsFrom": [
2764
+
"artist_id"
2765
+
],
2766
+
"columnsTo": [
2767
+
"xata_id"
2768
+
],
2769
+
"onDelete": "no action",
2770
+
"onUpdate": "no action"
2771
+
}
2772
+
},
2773
+
"compositePrimaryKeys": {},
2774
+
"uniqueConstraints": {
2775
+
"user_artists_uri_unique": {
2776
+
"name": "user_artists_uri_unique",
2777
+
"nullsNotDistinct": false,
2778
+
"columns": [
2779
+
"uri"
2780
+
]
2781
+
}
2782
+
},
2783
+
"policies": {},
2784
+
"checkConstraints": {},
2785
+
"isRLSEnabled": false
2786
+
},
2787
+
"public.user_playlists": {
2788
+
"name": "user_playlists",
2789
+
"schema": "",
2790
+
"columns": {
2791
+
"xata_id": {
2792
+
"name": "xata_id",
2793
+
"type": "text",
2794
+
"primaryKey": true,
2795
+
"notNull": true
2796
+
},
2797
+
"user_id": {
2798
+
"name": "user_id",
2799
+
"type": "text",
2800
+
"primaryKey": false,
2801
+
"notNull": true
2802
+
},
2803
+
"playlist_id": {
2804
+
"name": "playlist_id",
2805
+
"type": "text",
2806
+
"primaryKey": false,
2807
+
"notNull": true
2808
+
},
2809
+
"xata_createdat": {
2810
+
"name": "xata_createdat",
2811
+
"type": "timestamp",
2812
+
"primaryKey": false,
2813
+
"notNull": true,
2814
+
"default": "now()"
2815
+
},
2816
+
"uri": {
2817
+
"name": "uri",
2818
+
"type": "text",
2819
+
"primaryKey": false,
2820
+
"notNull": false
2821
+
}
2822
+
},
2823
+
"indexes": {},
2824
+
"foreignKeys": {
2825
+
"user_playlists_user_id_users_xata_id_fk": {
2826
+
"name": "user_playlists_user_id_users_xata_id_fk",
2827
+
"tableFrom": "user_playlists",
2828
+
"tableTo": "users",
2829
+
"columnsFrom": [
2830
+
"user_id"
2831
+
],
2832
+
"columnsTo": [
2833
+
"xata_id"
2834
+
],
2835
+
"onDelete": "no action",
2836
+
"onUpdate": "no action"
2837
+
},
2838
+
"user_playlists_playlist_id_playlists_xata_id_fk": {
2839
+
"name": "user_playlists_playlist_id_playlists_xata_id_fk",
2840
+
"tableFrom": "user_playlists",
2841
+
"tableTo": "playlists",
2842
+
"columnsFrom": [
2843
+
"playlist_id"
2844
+
],
2845
+
"columnsTo": [
2846
+
"xata_id"
2847
+
],
2848
+
"onDelete": "no action",
2849
+
"onUpdate": "no action"
2850
+
}
2851
+
},
2852
+
"compositePrimaryKeys": {},
2853
+
"uniqueConstraints": {
2854
+
"user_playlists_uri_unique": {
2855
+
"name": "user_playlists_uri_unique",
2856
+
"nullsNotDistinct": false,
2857
+
"columns": [
2858
+
"uri"
2859
+
]
2860
+
}
2861
+
},
2862
+
"policies": {},
2863
+
"checkConstraints": {},
2864
+
"isRLSEnabled": false
2865
+
},
2866
+
"public.user_tracks": {
2867
+
"name": "user_tracks",
2868
+
"schema": "",
2869
+
"columns": {
2870
+
"xata_id": {
2871
+
"name": "xata_id",
2872
+
"type": "text",
2873
+
"primaryKey": true,
2874
+
"notNull": true
2875
+
},
2876
+
"user_id": {
2877
+
"name": "user_id",
2878
+
"type": "text",
2879
+
"primaryKey": false,
2880
+
"notNull": true
2881
+
},
2882
+
"track_id": {
2883
+
"name": "track_id",
2884
+
"type": "text",
2885
+
"primaryKey": false,
2886
+
"notNull": true
2887
+
},
2888
+
"xata_createdat": {
2889
+
"name": "xata_createdat",
2890
+
"type": "timestamp",
2891
+
"primaryKey": false,
2892
+
"notNull": true,
2893
+
"default": "now()"
2894
+
},
2895
+
"xata_updatedat": {
2896
+
"name": "xata_updatedat",
2897
+
"type": "timestamp",
2898
+
"primaryKey": false,
2899
+
"notNull": true,
2900
+
"default": "now()"
2901
+
},
2902
+
"xata_version": {
2903
+
"name": "xata_version",
2904
+
"type": "integer",
2905
+
"primaryKey": false,
2906
+
"notNull": false
2907
+
},
2908
+
"uri": {
2909
+
"name": "uri",
2910
+
"type": "text",
2911
+
"primaryKey": false,
2912
+
"notNull": true
2913
+
},
2914
+
"scrobbles": {
2915
+
"name": "scrobbles",
2916
+
"type": "integer",
2917
+
"primaryKey": false,
2918
+
"notNull": false
2919
+
}
2920
+
},
2921
+
"indexes": {},
2922
+
"foreignKeys": {
2923
+
"user_tracks_user_id_users_xata_id_fk": {
2924
+
"name": "user_tracks_user_id_users_xata_id_fk",
2925
+
"tableFrom": "user_tracks",
2926
+
"tableTo": "users",
2927
+
"columnsFrom": [
2928
+
"user_id"
2929
+
],
2930
+
"columnsTo": [
2931
+
"xata_id"
2932
+
],
2933
+
"onDelete": "no action",
2934
+
"onUpdate": "no action"
2935
+
},
2936
+
"user_tracks_track_id_tracks_xata_id_fk": {
2937
+
"name": "user_tracks_track_id_tracks_xata_id_fk",
2938
+
"tableFrom": "user_tracks",
2939
+
"tableTo": "tracks",
2940
+
"columnsFrom": [
2941
+
"track_id"
2942
+
],
2943
+
"columnsTo": [
2944
+
"xata_id"
2945
+
],
2946
+
"onDelete": "no action",
2947
+
"onUpdate": "no action"
2948
+
}
2949
+
},
2950
+
"compositePrimaryKeys": {},
2951
+
"uniqueConstraints": {
2952
+
"user_tracks_uri_unique": {
2953
+
"name": "user_tracks_uri_unique",
2954
+
"nullsNotDistinct": false,
2955
+
"columns": [
2956
+
"uri"
2957
+
]
2958
+
}
2959
+
},
2960
+
"policies": {},
2961
+
"checkConstraints": {},
2962
+
"isRLSEnabled": false
2963
+
},
2964
+
"public.users": {
2965
+
"name": "users",
2966
+
"schema": "",
2967
+
"columns": {
2968
+
"xata_id": {
2969
+
"name": "xata_id",
2970
+
"type": "text",
2971
+
"primaryKey": true,
2972
+
"notNull": true
2973
+
},
2974
+
"did": {
2975
+
"name": "did",
2976
+
"type": "text",
2977
+
"primaryKey": false,
2978
+
"notNull": true
2979
+
},
2980
+
"display_name": {
2981
+
"name": "display_name",
2982
+
"type": "text",
2983
+
"primaryKey": false,
2984
+
"notNull": false
2985
+
},
2986
+
"handle": {
2987
+
"name": "handle",
2988
+
"type": "text",
2989
+
"primaryKey": false,
2990
+
"notNull": true
2991
+
},
2992
+
"avatar": {
2993
+
"name": "avatar",
2994
+
"type": "text",
2995
+
"primaryKey": false,
2996
+
"notNull": true
2997
+
},
2998
+
"xata_createdat": {
2999
+
"name": "xata_createdat",
3000
+
"type": "timestamp",
3001
+
"primaryKey": false,
3002
+
"notNull": true,
3003
+
"default": "now()"
3004
+
},
3005
+
"xata_updatedat": {
3006
+
"name": "xata_updatedat",
3007
+
"type": "timestamp",
3008
+
"primaryKey": false,
3009
+
"notNull": true,
3010
+
"default": "now()"
3011
+
},
3012
+
"xata_version": {
3013
+
"name": "xata_version",
3014
+
"type": "integer",
3015
+
"primaryKey": false,
3016
+
"notNull": false
3017
+
}
3018
+
},
3019
+
"indexes": {},
3020
+
"foreignKeys": {},
3021
+
"compositePrimaryKeys": {},
3022
+
"uniqueConstraints": {
3023
+
"users_did_unique": {
3024
+
"name": "users_did_unique",
3025
+
"nullsNotDistinct": false,
3026
+
"columns": [
3027
+
"did"
3028
+
]
3029
+
},
3030
+
"users_handle_unique": {
3031
+
"name": "users_handle_unique",
3032
+
"nullsNotDistinct": false,
3033
+
"columns": [
3034
+
"handle"
3035
+
]
3036
+
}
3037
+
},
3038
+
"policies": {},
3039
+
"checkConstraints": {},
3040
+
"isRLSEnabled": false
3041
+
},
3042
+
"public.webscrobblers": {
3043
+
"name": "webscrobblers",
3044
+
"schema": "",
3045
+
"columns": {
3046
+
"xata_id": {
3047
+
"name": "xata_id",
3048
+
"type": "text",
3049
+
"primaryKey": true,
3050
+
"notNull": true
3051
+
},
3052
+
"name": {
3053
+
"name": "name",
3054
+
"type": "text",
3055
+
"primaryKey": false,
3056
+
"notNull": true
3057
+
},
3058
+
"uuid": {
3059
+
"name": "uuid",
3060
+
"type": "text",
3061
+
"primaryKey": false,
3062
+
"notNull": true
3063
+
},
3064
+
"description": {
3065
+
"name": "description",
3066
+
"type": "text",
3067
+
"primaryKey": false,
3068
+
"notNull": false
3069
+
},
3070
+
"enabled": {
3071
+
"name": "enabled",
3072
+
"type": "boolean",
3073
+
"primaryKey": false,
3074
+
"notNull": true,
3075
+
"default": true
3076
+
},
3077
+
"user_id": {
3078
+
"name": "user_id",
3079
+
"type": "text",
3080
+
"primaryKey": false,
3081
+
"notNull": true
3082
+
},
3083
+
"xata_createdat": {
3084
+
"name": "xata_createdat",
3085
+
"type": "timestamp",
3086
+
"primaryKey": false,
3087
+
"notNull": true,
3088
+
"default": "now()"
3089
+
},
3090
+
"xata_updatedat": {
3091
+
"name": "xata_updatedat",
3092
+
"type": "timestamp",
3093
+
"primaryKey": false,
3094
+
"notNull": true,
3095
+
"default": "now()"
3096
+
}
3097
+
},
3098
+
"indexes": {},
3099
+
"foreignKeys": {
3100
+
"webscrobblers_user_id_users_xata_id_fk": {
3101
+
"name": "webscrobblers_user_id_users_xata_id_fk",
3102
+
"tableFrom": "webscrobblers",
3103
+
"tableTo": "users",
3104
+
"columnsFrom": [
3105
+
"user_id"
3106
+
],
3107
+
"columnsTo": [
3108
+
"xata_id"
3109
+
],
3110
+
"onDelete": "no action",
3111
+
"onUpdate": "no action"
3112
+
}
3113
+
},
3114
+
"compositePrimaryKeys": {},
3115
+
"uniqueConstraints": {},
3116
+
"policies": {},
3117
+
"checkConstraints": {},
3118
+
"isRLSEnabled": false
3119
+
}
3120
+
},
3121
+
"enums": {},
3122
+
"schemas": {},
3123
+
"sequences": {},
3124
+
"roles": {},
3125
+
"policies": {},
3126
+
"views": {},
3127
+
"_meta": {
3128
+
"columns": {},
3129
+
"schemas": {},
3130
+
"tables": {}
3131
+
}
3132
+
}
+16
-2
apps/api/drizzle/meta/_journal.json
+16
-2
apps/api/drizzle/meta/_journal.json
···
5
5
{
6
6
"idx": 0,
7
7
"version": "7",
8
-
"when": 1753405608015,
9
-
"tag": "0000_quiet_mister_sinister",
8
+
"when": 1759744201158,
9
+
"tag": "0000_left_swordsman",
10
+
"breakpoints": true
11
+
},
12
+
{
13
+
"idx": 1,
14
+
"version": "7",
15
+
"when": 1759746264036,
16
+
"tag": "0001_fluffy_epoch",
17
+
"breakpoints": true
18
+
},
19
+
{
20
+
"idx": 2,
21
+
"version": "7",
22
+
"when": 1759747596050,
23
+
"tag": "0002_sweet_randall_flagg",
10
24
"breakpoints": true
11
25
}
12
26
]
+1
-1
apps/api/src/schema/album-tracks.ts
+1
-1
apps/api/src/schema/album-tracks.ts
···
13
13
.references(() => tracks.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
});
18
18
19
19
export type SelectAlbumTrack = InferSelectModel<typeof albumTracks>;
+1
-1
apps/api/src/schema/artist-albums.ts
+1
-1
apps/api/src/schema/artist-albums.ts
···
13
13
.references(() => albums.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
});
18
18
19
19
export type SelectArtistAlbum = InferSelectModel<typeof artistAlbums>;
+1
-1
apps/api/src/schema/artist-tracks.ts
+1
-1
apps/api/src/schema/artist-tracks.ts
···
13
13
.references(() => tracks.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
});
18
18
19
19
export type SelectArtistTrack = InferSelectModel<typeof artistTracks>;
+1
-1
apps/api/src/schema/dropbox-accounts.ts
+1
-1
apps/api/src/schema/dropbox-accounts.ts
···
9
9
userId: text("user_id")
10
10
.notNull()
11
11
.references(() => users.id),
12
-
xataVersion: text("xata_version").notNull(),
12
+
xataVersion: text("xata_version"),
13
13
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
14
14
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
15
15
});
+1
-1
apps/api/src/schema/dropbox-directories.ts
+1
-1
apps/api/src/schema/dropbox-directories.ts
···
8
8
parentId: text("parent_id").references(() => dropboxDirectories.id),
9
9
dropboxId: text("dropbox_id").notNull(),
10
10
fileId: text("file_id").notNull().unique(),
11
-
xataVersion: text("xata_version").notNull(),
11
+
xataVersion: text("xata_version"),
12
12
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
13
13
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
14
14
});
+1
-1
apps/api/src/schema/dropbox-paths.ts
+1
-1
apps/api/src/schema/dropbox-paths.ts
···
10
10
trackId: text("track_id").notNull(),
11
11
directoryId: text("directory_id").references(() => dropboxDirectories.id),
12
12
fileId: text("file_id").notNull().unique(),
13
-
xataVersion: text("xata_version").notNull(),
13
+
xataVersion: text("xata_version"),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
16
});
+1
-1
apps/api/src/schema/dropbox.ts
+1
-1
apps/api/src/schema/dropbox.ts
···
11
11
dropboxTokenId: text("dropbox_token_id")
12
12
.notNull()
13
13
.references(() => dropboxTokens.id),
14
-
xataVersion: text("xata_version").notNull(),
14
+
xataVersion: text("xata_version"),
15
15
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
16
16
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
17
17
});
+1
-1
apps/api/src/schema/google-drive-accounts.ts
+1
-1
apps/api/src/schema/google-drive-accounts.ts
···
9
9
userId: text("user_id")
10
10
.notNull()
11
11
.references(() => users.id),
12
-
xataVersion: text("xata_version").notNull(),
12
+
xataVersion: text("xata_version"),
13
13
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
14
14
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
15
15
});
+1
-1
apps/api/src/schema/google-drive-directories.ts
+1
-1
apps/api/src/schema/google-drive-directories.ts
···
8
8
parentId: text("parent_id").references(() => googleDriveDirectories.id),
9
9
googleDriveId: text("google_drive_id").notNull(),
10
10
fileId: text("file_id").notNull().unique(),
11
-
xataVersion: text("xata_version").notNull(),
11
+
xataVersion: text("xata_version"),
12
12
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
13
13
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
14
14
});
+1
-1
apps/api/src/schema/google-drive-paths.ts
+1
-1
apps/api/src/schema/google-drive-paths.ts
···
9
9
name: text("name").notNull(),
10
10
directoryId: text("directory_id").references(() => googleDriveDirectories.id),
11
11
fileId: text("file_id").notNull().unique(),
12
-
xataVersion: text("xata_version").notNull(),
12
+
xataVersion: text("xata_version"),
13
13
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
14
14
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
15
15
});
+1
-1
apps/api/src/schema/googledrive.ts
+1
-1
apps/api/src/schema/googledrive.ts
···
11
11
userId: text("user_id")
12
12
.notNull()
13
13
.references(() => users.id),
14
-
xataVersion: text("xata_version").notNull(),
14
+
xataVersion: text("xata_version"),
15
15
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
16
16
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
17
17
});
+1
-1
apps/api/src/schema/spotify-accounts.ts
+1
-1
apps/api/src/schema/spotify-accounts.ts
+1
-1
apps/api/src/schema/spotify-tokens.ts
+1
-1
apps/api/src/schema/spotify-tokens.ts
···
4
4
5
5
const spotifyTokens = pgTable("spotify_tokens", {
6
6
id: text("xata_id").primaryKey(),
7
-
xataVersion: integer("xata_version").notNull(),
7
+
xataVersion: integer("xata_version"),
8
8
accessToken: text("access_token").notNull(),
9
9
refreshToken: text("refresh_token").notNull(),
10
10
userId: text("user_id")
+2
-2
apps/api/src/schema/tracks.ts
+2
-2
apps/api/src/schema/tracks.ts
···
23
23
label: text("label"),
24
24
copyrightMessage: text("copyright_message"),
25
25
uri: text("uri").unique(),
26
-
albumUri: text("album_uri").unique(),
27
-
artistUri: text("artist_uri").unique(),
26
+
albumUri: text("album_uri"),
27
+
artistUri: text("artist_uri"),
28
28
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
29
29
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
30
30
xataVersion: integer("xata_version"),
+1
-1
apps/api/src/schema/user-albums.ts
+1
-1
apps/api/src/schema/user-albums.ts
···
13
13
.references(() => albums.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
scrobbles: integer("scrobbles"),
18
18
uri: text("uri").unique().notNull(),
19
19
});
+1
-1
apps/api/src/schema/user-artists.ts
+1
-1
apps/api/src/schema/user-artists.ts
···
13
13
.references(() => artists.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
scrobbles: integer("scrobbles"),
18
18
uri: text("uri").unique().notNull(),
19
19
});
+3
-3
apps/api/src/schema/user-playlists.ts
+3
-3
apps/api/src/schema/user-playlists.ts
···
1
1
import type { InferInsertModel, InferSelectModel } from "drizzle-orm";
2
2
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
3
-
import tracks from "./tracks";
3
+
import playlists from "./playlists";
4
4
import users from "./users";
5
5
6
6
const userPlaylists = pgTable("user_playlists", {
···
10
10
.references(() => users.id),
11
11
playlistId: text("playlist_id")
12
12
.notNull()
13
-
.references(() => tracks.id),
13
+
.references(() => playlists.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
-
uri: text("uri").unique().notNull(),
15
+
uri: text("uri").unique(),
16
16
});
17
17
18
18
export type SelectUserPlaylist = InferSelectModel<typeof userPlaylists>;
+1
-1
apps/api/src/schema/user-tracks.ts
+1
-1
apps/api/src/schema/user-tracks.ts
···
13
13
.references(() => tracks.id),
14
14
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
15
15
updatedAt: timestamp("xata_updatedat").defaultNow().notNull(),
16
-
xataVersion: integer("xata_version").notNull(),
16
+
xataVersion: integer("xata_version"),
17
17
uri: text("uri").unique().notNull(),
18
18
scrobbles: integer("scrobbles"),
19
19
});
+1
-1
apps/api/src/schema/users.ts
+1
-1
apps/api/src/schema/users.ts
···
4
4
const users = pgTable("users", {
5
5
id: text("xata_id").primaryKey(),
6
6
did: text("did").unique().notNull(),
7
-
displayName: text("display_name").notNull(),
7
+
displayName: text("display_name"),
8
8
handle: text("handle").unique().notNull(),
9
9
avatar: text("avatar").notNull(),
10
10
createdAt: timestamp("xata_createdat").defaultNow().notNull(),
+24
crates/pgpull/Cargo.toml
+24
crates/pgpull/Cargo.toml
···
1
+
[package]
2
+
name = "rocksky-pgpull"
3
+
version = "0.1.0"
4
+
authors.workspace = true
5
+
edition.workspace = true
6
+
license.workspace = true
7
+
repository.workspace = true
8
+
9
+
[dependencies]
10
+
serde = { version = "1.0.217", features = ["derive"] }
11
+
serde_json = "1.0.139"
12
+
sqlx = { version = "0.8.3", features = [
13
+
"runtime-tokio",
14
+
"tls-rustls",
15
+
"postgres",
16
+
"chrono",
17
+
"derive",
18
+
"macros",
19
+
] }
20
+
tokio = { version = "1.43.0", features = ["full"] }
21
+
chrono = { version = "= 0.4.39", features = ["serde"] }
22
+
owo-colors = "4.1.0"
23
+
anyhow = "1.0.96"
24
+
tracing = "0.1.41"
+698
crates/pgpull/src/lib.rs
+698
crates/pgpull/src/lib.rs
···
1
+
use std::env;
2
+
3
+
mod repo;
4
+
mod xata;
5
+
6
+
use anyhow::{Context, Error};
7
+
use owo_colors::OwoColorize;
8
+
use sqlx::{postgres::PgPoolOptions, PgPool};
9
+
10
+
const MAX_CONNECTIONS: u32 = 5;
11
+
const BATCH_SIZE: usize = 1000;
12
+
const BACKUP_URL: &str = "https://backup.rocksky.app/rocksky-backup.sql";
13
+
const BACKUP_PATH: &str = "/tmp/rocksky-backup.sql";
14
+
#[derive(Clone)]
15
+
pub struct DatabasePools {
16
+
pub source: PgPool,
17
+
pub destination: PgPool,
18
+
}
19
+
20
+
pub async fn pull_data() -> Result<(), Error> {
21
+
if env::var("SOURCE_POSTGRES_URL").is_err() {
22
+
tracing::info!(
23
+
backup = %BACKUP_URL.magenta(),
24
+
"SOURCE_POSTGRES_URL not set, downloading backup from Rocksky"
25
+
);
26
+
download_backup().await?;
27
+
return Ok(());
28
+
}
29
+
30
+
let pools = setup_database_pools().await?;
31
+
32
+
// Sync core entities first
33
+
let album_sync = tokio::spawn({
34
+
let pools = pools.clone();
35
+
async move { sync_albums(&pools).await }
36
+
});
37
+
38
+
let artist_sync = tokio::spawn({
39
+
let pools = pools.clone();
40
+
async move { sync_artists(&pools).await }
41
+
});
42
+
43
+
let track_sync = tokio::spawn({
44
+
let pools = pools.clone();
45
+
async move { sync_tracks(&pools).await }
46
+
});
47
+
48
+
let user_sync = tokio::spawn({
49
+
let pools = pools.clone();
50
+
async move { sync_users(&pools).await }
51
+
});
52
+
53
+
let (album_sync, artist_sync, track_sync, user_sync) =
54
+
tokio::join!(album_sync, artist_sync, track_sync, user_sync);
55
+
56
+
album_sync.context("Album sync task failed")??;
57
+
artist_sync.context("Artist sync task failed")??;
58
+
track_sync.context("Track sync task failed")??;
59
+
user_sync.context("User sync task failed")??;
60
+
61
+
// Sync relationship entities
62
+
let playlist_sync = tokio::spawn({
63
+
let pools = pools.clone();
64
+
async move { sync_playlists(&pools).await }
65
+
});
66
+
67
+
let loved_track_sync = tokio::spawn({
68
+
let pools = pools.clone();
69
+
async move { sync_loved_tracks(&pools).await }
70
+
});
71
+
72
+
let scrobble_sync = tokio::spawn({
73
+
let pools = pools.clone();
74
+
async move { sync_scrobbles(&pools).await }
75
+
});
76
+
77
+
let (loved_track_sync, playlist_sync, scrobble_sync) =
78
+
tokio::join!(loved_track_sync, playlist_sync, scrobble_sync);
79
+
loved_track_sync.context("Loved track sync task failed")??;
80
+
playlist_sync.context("Playlist sync task failed")??;
81
+
scrobble_sync.context("Scrobble sync task failed")??;
82
+
83
+
// Sync junction tables
84
+
let album_track_sync = tokio::spawn({
85
+
let pools = pools.clone();
86
+
async move { sync_album_tracks(&pools).await }
87
+
});
88
+
89
+
let artist_album_sync = tokio::spawn({
90
+
let pools = pools.clone();
91
+
async move { sync_artist_albums(&pools).await }
92
+
});
93
+
94
+
let artist_track_sync = tokio::spawn({
95
+
let pools = pools.clone();
96
+
async move { sync_artist_tracks(&pools).await }
97
+
});
98
+
99
+
let playlist_track_sync = tokio::spawn({
100
+
let pools = pools.clone();
101
+
async move { sync_playlist_tracks(&pools).await }
102
+
});
103
+
104
+
let user_album_sync = tokio::spawn({
105
+
let pools = pools.clone();
106
+
async move { sync_user_albums(&pools).await }
107
+
});
108
+
109
+
let user_artist_sync = tokio::spawn({
110
+
let pools = pools.clone();
111
+
async move { sync_user_artists(&pools).await }
112
+
});
113
+
114
+
let user_track_sync = tokio::spawn({
115
+
let pools = pools.clone();
116
+
async move { sync_user_tracks(&pools).await }
117
+
});
118
+
119
+
let user_playlist_sync = tokio::spawn({
120
+
let pools = pools.clone();
121
+
async move { sync_user_playlists(&pools).await }
122
+
});
123
+
124
+
let (
125
+
album_track_sync,
126
+
artist_album_sync,
127
+
artist_track_sync,
128
+
playlist_track_sync,
129
+
user_album_sync,
130
+
user_artist_sync,
131
+
user_track_sync,
132
+
user_playlist_sync,
133
+
) = tokio::join!(
134
+
album_track_sync,
135
+
artist_album_sync,
136
+
artist_track_sync,
137
+
playlist_track_sync,
138
+
user_album_sync,
139
+
user_artist_sync,
140
+
user_track_sync,
141
+
user_playlist_sync
142
+
);
143
+
144
+
album_track_sync.context("Album track sync task failed")??;
145
+
artist_album_sync.context("Artist album sync task failed")??;
146
+
artist_track_sync.context("Artist track sync task failed")??;
147
+
playlist_track_sync.context("Playlist track sync task failed")??;
148
+
user_album_sync.context("User album sync task failed")??;
149
+
user_artist_sync.context("User artist sync task failed")??;
150
+
user_track_sync.context("User track sync task failed")??;
151
+
user_playlist_sync.context("User playlist sync task failed")??;
152
+
153
+
Ok(())
154
+
}
155
+
156
+
async fn download_backup() -> Result<(), Error> {
157
+
let _ = tokio::fs::remove_file(BACKUP_PATH).await;
158
+
159
+
tokio::process::Command::new("curl")
160
+
.arg("-o")
161
+
.arg(BACKUP_PATH)
162
+
.arg(BACKUP_URL)
163
+
.stderr(std::process::Stdio::inherit())
164
+
.stdout(std::process::Stdio::inherit())
165
+
.spawn()?
166
+
.wait()
167
+
.await?;
168
+
169
+
tokio::process::Command::new("psql")
170
+
.arg(&env::var("XATA_POSTGRES_URL")?)
171
+
.arg("-f")
172
+
.arg(BACKUP_PATH)
173
+
.stderr(std::process::Stdio::inherit())
174
+
.stdout(std::process::Stdio::inherit())
175
+
.spawn()?
176
+
.wait()
177
+
.await?;
178
+
Ok(())
179
+
}
180
+
181
+
async fn setup_database_pools() -> Result<DatabasePools, Error> {
182
+
let source = PgPoolOptions::new()
183
+
.max_connections(MAX_CONNECTIONS)
184
+
.connect(&env::var("SOURCE_POSTGRES_URL")?)
185
+
.await?;
186
+
187
+
let destination = PgPoolOptions::new()
188
+
.max_connections(MAX_CONNECTIONS)
189
+
.connect(&env::var("XATA_POSTGRES_URL")?)
190
+
.await?;
191
+
192
+
Ok(DatabasePools {
193
+
source,
194
+
destination,
195
+
})
196
+
}
197
+
198
+
async fn sync_albums(pools: &DatabasePools) -> Result<(), Error> {
199
+
let total_albums: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM albums")
200
+
.fetch_one(&pools.source)
201
+
.await?;
202
+
let total_albums = total_albums.0;
203
+
tracing::info!(total = %total_albums.magenta(), "Total albums to sync");
204
+
205
+
let start = 0;
206
+
let mut i = 1;
207
+
208
+
for offset in (start..total_albums).step_by(BATCH_SIZE) {
209
+
let albums =
210
+
repo::album::get_albums(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
211
+
tracing::info!(
212
+
offset = %offset.magenta(),
213
+
end = %((offset + albums.len() as i64).min(total_albums)).magenta(),
214
+
total = %total_albums.magenta(),
215
+
"Fetched albums"
216
+
);
217
+
for album in &albums {
218
+
tracing::info!(title = %album.title.cyan(), i = %i.magenta(), total = %total_albums.magenta(), "Inserting album");
219
+
repo::album::insert_album(&pools.destination, album).await?;
220
+
i += 1;
221
+
}
222
+
}
223
+
Ok(())
224
+
}
225
+
226
+
async fn sync_artists(pools: &DatabasePools) -> Result<(), Error> {
227
+
let total_artists: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM artists")
228
+
.fetch_one(&pools.source)
229
+
.await?;
230
+
let total_artists = total_artists.0;
231
+
tracing::info!(total = %total_artists.magenta(), "Total artists to sync");
232
+
233
+
let start = 0;
234
+
let mut i = 1;
235
+
236
+
for offset in (start..total_artists).step_by(BATCH_SIZE) {
237
+
let artists =
238
+
repo::artist::get_artists(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
239
+
tracing::info!(
240
+
offset = %offset.magenta(),
241
+
end = %((offset + artists.len() as i64).min(total_artists)).magenta(),
242
+
total = %total_artists.magenta(),
243
+
"Fetched artists"
244
+
);
245
+
for artist in &artists {
246
+
tracing::info!(name = %artist.name.cyan(), i = %i.magenta(), total = %total_artists.magenta(), "Inserting artist");
247
+
repo::artist::insert_artist(&pools.destination, artist).await?;
248
+
i += 1;
249
+
}
250
+
}
251
+
Ok(())
252
+
}
253
+
254
+
async fn sync_tracks(pools: &DatabasePools) -> Result<(), Error> {
255
+
let total_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM tracks")
256
+
.fetch_one(&pools.source)
257
+
.await?;
258
+
let total_tracks = total_tracks.0;
259
+
tracing::info!(total = %total_tracks.magenta(), "Total tracks to sync");
260
+
261
+
let start = 0;
262
+
let mut i = 1;
263
+
264
+
for offset in (start..total_tracks).step_by(BATCH_SIZE) {
265
+
let tracks =
266
+
repo::track::get_tracks(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
267
+
tracing::info!(
268
+
offset = %offset.magenta(),
269
+
end = %((offset + tracks.len() as i64).min(total_tracks)).magenta(),
270
+
total = %total_tracks.magenta(),
271
+
"Fetched tracks"
272
+
);
273
+
274
+
for track in &tracks {
275
+
tracing::info!(title = %track.title.cyan(), i = %i.magenta(), total = %total_tracks.magenta(), "Inserting track");
276
+
match repo::track::insert_track(&pools.destination, track).await {
277
+
Ok(_) => {}
278
+
Err(e) => {
279
+
tracing::error!(error = %e, "Failed to insert track");
280
+
}
281
+
}
282
+
i += 1;
283
+
}
284
+
}
285
+
Ok(())
286
+
}
287
+
288
+
async fn sync_users(pools: &DatabasePools) -> Result<(), Error> {
289
+
let total_users: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM users")
290
+
.fetch_one(&pools.source)
291
+
.await?;
292
+
let total_users = total_users.0;
293
+
tracing::info!(total = %total_users.magenta(), "Total users to sync");
294
+
295
+
let start = 0;
296
+
let mut i = 1;
297
+
298
+
for offset in (start..total_users).step_by(BATCH_SIZE) {
299
+
let users = repo::user::get_users(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
300
+
tracing::info!(
301
+
offset = %offset.magenta(),
302
+
end = %((offset + users.len() as i64).min(total_users)).magenta(),
303
+
total = %total_users.magenta(),
304
+
"Fetched users"
305
+
);
306
+
307
+
for user in &users {
308
+
tracing::info!(handle = %user.handle.cyan(), i = %i.magenta(), total = %total_users.magenta(), "Inserting user");
309
+
match repo::user::insert_user(&pools.destination, user).await {
310
+
Ok(_) => {}
311
+
Err(e) => {
312
+
tracing::error!(error = %e, "Failed to insert user");
313
+
}
314
+
}
315
+
i += 1;
316
+
}
317
+
}
318
+
Ok(())
319
+
}
320
+
321
+
async fn sync_playlists(pools: &DatabasePools) -> Result<(), Error> {
322
+
let total_playlists: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM playlists")
323
+
.fetch_one(&pools.source)
324
+
.await?;
325
+
let total_playlists = total_playlists.0;
326
+
tracing::info!(total = %total_playlists.magenta(), "Total playlists to sync");
327
+
328
+
let start = 0;
329
+
let mut i = 1;
330
+
331
+
for offset in (start..total_playlists).step_by(BATCH_SIZE) {
332
+
let playlists =
333
+
repo::playlist::get_playlists(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
334
+
tracing::info!(
335
+
offset = %offset.magenta(),
336
+
end = %((offset + playlists.len() as i64).min(total_playlists)).magenta(),
337
+
total = %total_playlists.magenta(),
338
+
"Fetched playlists"
339
+
);
340
+
341
+
for playlist in &playlists {
342
+
tracing::info!(name = %playlist.name.cyan(), i = %i.magenta(), total = %total_playlists.magenta(), "Inserting playlist");
343
+
match repo::playlist::insert_playlist(&pools.destination, playlist).await {
344
+
Ok(_) => {}
345
+
Err(e) => {
346
+
tracing::error!(error = %e, "Failed to insert playlist");
347
+
}
348
+
}
349
+
i += 1;
350
+
}
351
+
}
352
+
Ok(())
353
+
}
354
+
355
+
async fn sync_loved_tracks(pools: &DatabasePools) -> Result<(), Error> {
356
+
let total_loved_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM loved_tracks")
357
+
.fetch_one(&pools.source)
358
+
.await?;
359
+
let total_loved_tracks = total_loved_tracks.0;
360
+
tracing::info!(total = %total_loved_tracks.magenta(), "Total loved tracks to sync");
361
+
362
+
let start = 0;
363
+
let mut i = 1;
364
+
365
+
for offset in (start..total_loved_tracks).step_by(BATCH_SIZE) {
366
+
let loved_tracks =
367
+
repo::loved_track::get_loved_tracks(&pools.source, offset as i64, BATCH_SIZE as i64)
368
+
.await?;
369
+
tracing::info!(
370
+
offset = %offset.magenta(),
371
+
end = %((offset + loved_tracks.len() as i64).min(total_loved_tracks)).magenta(),
372
+
total = %total_loved_tracks.magenta(),
373
+
"Fetched loved tracks"
374
+
);
375
+
376
+
for loved_track in &loved_tracks {
377
+
tracing::info!(user_id = %loved_track.user_id.cyan(), track_id = %loved_track.track_id.magenta(), i = %i.magenta(), total = %total_loved_tracks.magenta(), "Inserting loved track");
378
+
match repo::loved_track::insert_loved_track(&pools.destination, loved_track).await {
379
+
Ok(_) => {}
380
+
Err(e) => {
381
+
tracing::error!(error = %e, "Failed to insert loved track");
382
+
}
383
+
}
384
+
i += 1;
385
+
}
386
+
}
387
+
Ok(())
388
+
}
389
+
390
+
async fn sync_scrobbles(pools: &DatabasePools) -> Result<(), Error> {
391
+
let total_scrobbles: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM scrobbles")
392
+
.fetch_one(&pools.source)
393
+
.await?;
394
+
let total_scrobbles = total_scrobbles.0;
395
+
tracing::info!(total = %total_scrobbles.magenta(), "Total scrobbles to sync");
396
+
397
+
let start = 0;
398
+
let mut i = 1;
399
+
400
+
for offset in (start..total_scrobbles).step_by(BATCH_SIZE) {
401
+
let scrobbles =
402
+
repo::scrobble::get_scrobbles(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
403
+
tracing::info!(
404
+
offset = %offset.magenta(),
405
+
end = %((offset + scrobbles.len() as i64).min(total_scrobbles)).magenta(),
406
+
total = %total_scrobbles.magenta(),
407
+
"Fetched scrobbles"
408
+
);
409
+
410
+
for scrobble in &scrobbles {
411
+
tracing::info!(user_id = %scrobble.user_id.cyan(), track_id = %scrobble.track_id.magenta(), i = %i.magenta(), total = %total_scrobbles.magenta(), "Inserting scrobble");
412
+
match repo::scrobble::insert_scrobble(&pools.destination, scrobble).await {
413
+
Ok(_) => {}
414
+
Err(e) => {
415
+
tracing::error!(error = %e, "Failed to insert scrobble");
416
+
}
417
+
}
418
+
i += 1;
419
+
}
420
+
}
421
+
Ok(())
422
+
}
423
+
424
+
async fn sync_album_tracks(pools: &DatabasePools) -> Result<(), Error> {
425
+
let total_album_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM album_tracks")
426
+
.fetch_one(&pools.source)
427
+
.await?;
428
+
let total_album_tracks = total_album_tracks.0;
429
+
tracing::info!(total = %total_album_tracks.magenta(), "Total album tracks to sync");
430
+
431
+
let start = 0;
432
+
let mut i = 1;
433
+
434
+
for offset in (start..total_album_tracks).step_by(BATCH_SIZE) {
435
+
let album_tracks =
436
+
repo::album::get_album_tracks(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
437
+
tracing::info!(
438
+
offset = %offset.magenta(),
439
+
end = %((offset + album_tracks.len() as i64).min(total_album_tracks)).magenta(),
440
+
total = %total_album_tracks.magenta(),
441
+
"Fetched album tracks"
442
+
);
443
+
444
+
for album_track in &album_tracks {
445
+
tracing::info!(album_id = %album_track.album_id.cyan(), track_id = %album_track.track_id.magenta(), i = %i.magenta(), total = %total_album_tracks.magenta(), "Inserting album track");
446
+
match repo::album::insert_album_track(&pools.destination, album_track).await {
447
+
Ok(_) => {}
448
+
Err(e) => {
449
+
tracing::error!(error = %e, "Failed to insert album track");
450
+
}
451
+
}
452
+
i += 1;
453
+
}
454
+
}
455
+
Ok(())
456
+
}
457
+
458
+
async fn sync_artist_albums(pools: &DatabasePools) -> Result<(), Error> {
459
+
let total_artist_albums: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM artist_albums")
460
+
.fetch_one(&pools.source)
461
+
.await?;
462
+
let total_artist_albums = total_artist_albums.0;
463
+
tracing::info!(total = %total_artist_albums.magenta(), "Total artist albums to sync");
464
+
465
+
let start = 0;
466
+
let mut i = 1;
467
+
468
+
for offset in (start..total_artist_albums).step_by(BATCH_SIZE) {
469
+
let artist_albums =
470
+
repo::artist::get_artist_albums(&pools.source, offset as i64, BATCH_SIZE as i64)
471
+
.await?;
472
+
tracing::info!(
473
+
offset = %offset.magenta(),
474
+
end = %((offset + artist_albums.len() as i64).min(total_artist_albums)).magenta(),
475
+
total = %total_artist_albums.magenta(),
476
+
"Fetched artist albums"
477
+
);
478
+
479
+
for artist_album in &artist_albums {
480
+
tracing::info!(artist_id = %artist_album.artist_id.cyan(), album_id = %artist_album.album_id.magenta(), i = %i.magenta(), total = %total_artist_albums.magenta(), "Inserting artist album");
481
+
match repo::artist::insert_artist_album(&pools.destination, artist_album).await {
482
+
Ok(_) => {}
483
+
Err(e) => {
484
+
tracing::error!(error = %e, "Failed to insert artist album");
485
+
}
486
+
}
487
+
i += 1;
488
+
}
489
+
}
490
+
Ok(())
491
+
}
492
+
493
+
async fn sync_artist_tracks(pools: &DatabasePools) -> Result<(), Error> {
494
+
let total_artist_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM artist_tracks")
495
+
.fetch_one(&pools.source)
496
+
.await?;
497
+
let total_artist_tracks = total_artist_tracks.0;
498
+
tracing::info!(total = %total_artist_tracks.magenta(), "Total artist tracks to sync");
499
+
500
+
let start = 0;
501
+
let mut i = 1;
502
+
503
+
for offset in (start..total_artist_tracks).step_by(BATCH_SIZE) {
504
+
let artist_tracks =
505
+
repo::artist::get_artist_tracks(&pools.source, offset as i64, BATCH_SIZE as i64)
506
+
.await?;
507
+
tracing::info!(
508
+
offset = %offset.magenta(),
509
+
end = %((offset + artist_tracks.len() as i64).min(total_artist_tracks)).magenta(),
510
+
total = %total_artist_tracks.magenta(),
511
+
"Fetched artist tracks"
512
+
);
513
+
514
+
for artist_track in &artist_tracks {
515
+
tracing::info!(artist_id = %artist_track.artist_id.cyan(), track_id = %artist_track.track_id.magenta(), i = %i.magenta(), total = %total_artist_tracks.magenta(), "Inserting artist track");
516
+
match repo::artist::insert_artist_track(&pools.destination, artist_track).await {
517
+
Ok(_) => {}
518
+
Err(e) => {
519
+
tracing::error!(error = %e, "Failed to insert artist track");
520
+
}
521
+
}
522
+
i += 1;
523
+
}
524
+
}
525
+
Ok(())
526
+
}
527
+
528
+
async fn sync_playlist_tracks(pools: &DatabasePools) -> Result<(), Error> {
529
+
let total_playlist_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM playlist_tracks")
530
+
.fetch_one(&pools.source)
531
+
.await?;
532
+
let total_playlist_tracks = total_playlist_tracks.0;
533
+
tracing::info!(total = %total_playlist_tracks.magenta(), "Total playlist tracks to sync");
534
+
535
+
let start = 0;
536
+
let mut i = 1;
537
+
538
+
for offset in (start..total_playlist_tracks).step_by(BATCH_SIZE) {
539
+
let playlist_tracks =
540
+
repo::playlist::get_playlist_tracks(&pools.source, offset as i64, BATCH_SIZE as i64)
541
+
.await?;
542
+
tracing::info!(
543
+
offset = %offset.magenta(),
544
+
end = %((offset + playlist_tracks.len() as i64).min(total_playlist_tracks)).magenta(),
545
+
total = %total_playlist_tracks.magenta(),
546
+
"Fetched playlist tracks"
547
+
);
548
+
549
+
for playlist_track in &playlist_tracks {
550
+
tracing::info!(playlist_id = %playlist_track.playlist_id.cyan(), track_id = %playlist_track.track_id.magenta(), i = %i.magenta(), total = %total_playlist_tracks.magenta(), "Inserting playlist track");
551
+
match repo::playlist::insert_playlist_track(&pools.destination, playlist_track).await {
552
+
Ok(_) => {}
553
+
Err(e) => {
554
+
tracing::error!(error = %e, "Failed to insert playlist track");
555
+
}
556
+
}
557
+
i += 1;
558
+
}
559
+
}
560
+
Ok(())
561
+
}
562
+
563
+
async fn sync_user_albums(pools: &DatabasePools) -> Result<(), Error> {
564
+
let total_user_albums: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM user_albums")
565
+
.fetch_one(&pools.source)
566
+
.await?;
567
+
let total_user_albums = total_user_albums.0;
568
+
tracing::info!(total = %total_user_albums.magenta(), "Total user albums to sync");
569
+
570
+
let start = 0;
571
+
let mut i = 1;
572
+
573
+
for offset in (start..total_user_albums).step_by(BATCH_SIZE) {
574
+
let user_albums =
575
+
repo::album::get_user_albums(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
576
+
tracing::info!(
577
+
offset = %offset.magenta(),
578
+
end = %((offset + user_albums.len() as i64).min(total_user_albums)).magenta(),
579
+
total = %total_user_albums.magenta(),
580
+
"Fetched user albums"
581
+
);
582
+
583
+
for user_album in &user_albums {
584
+
tracing::info!(user_id = %user_album.user_id.cyan(), album_id = %user_album.album_id.magenta(), i = %i.magenta(), total = %total_user_albums.magenta(), "Inserting user album");
585
+
match repo::album::insert_user_album(&pools.destination, user_album).await {
586
+
Ok(_) => {}
587
+
Err(e) => {
588
+
tracing::error!(error = %e, "Failed to insert user album");
589
+
}
590
+
}
591
+
i += 1;
592
+
}
593
+
}
594
+
Ok(())
595
+
}
596
+
597
+
async fn sync_user_artists(pools: &DatabasePools) -> Result<(), Error> {
598
+
let total_user_artists: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM user_artists")
599
+
.fetch_one(&pools.source)
600
+
.await?;
601
+
let total_user_artists = total_user_artists.0;
602
+
tracing::info!(total = %total_user_artists.magenta(), "Total user artists to sync");
603
+
604
+
let start = 0;
605
+
let mut i = 1;
606
+
607
+
for offset in (start..total_user_artists).step_by(BATCH_SIZE) {
608
+
let user_artists =
609
+
repo::artist::get_user_artists(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
610
+
tracing::info!(
611
+
offset = %offset.magenta(),
612
+
end = %((offset + user_artists.len() as i64).min(total_user_artists)).magenta(),
613
+
total = %total_user_artists.magenta(),
614
+
"Fetched user artists"
615
+
);
616
+
617
+
for user_artist in &user_artists {
618
+
tracing::info!(user_id = %user_artist.user_id.cyan(), artist_id = %user_artist.artist_id.magenta(), i = %i.magenta(), total = %total_user_artists.magenta(), "Inserting user artist");
619
+
match repo::artist::insert_user_artist(&pools.destination, user_artist).await {
620
+
Ok(_) => {}
621
+
Err(e) => {
622
+
tracing::error!(error = %e, "Failed to insert user artist");
623
+
}
624
+
}
625
+
i += 1;
626
+
}
627
+
}
628
+
Ok(())
629
+
}
630
+
631
+
async fn sync_user_tracks(pools: &DatabasePools) -> Result<(), Error> {
632
+
let total_user_tracks: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM user_tracks")
633
+
.fetch_one(&pools.source)
634
+
.await?;
635
+
let total_user_tracks = total_user_tracks.0;
636
+
tracing::info!(total = %total_user_tracks.magenta(), "Total user tracks to sync");
637
+
638
+
let start = 0;
639
+
let mut i = 1;
640
+
641
+
for offset in (start..total_user_tracks).step_by(BATCH_SIZE) {
642
+
let user_tracks =
643
+
repo::track::get_user_tracks(&pools.source, offset as i64, BATCH_SIZE as i64).await?;
644
+
tracing::info!(
645
+
offset = %offset.magenta(),
646
+
end = %((offset + user_tracks.len() as i64).min(total_user_tracks)).magenta(),
647
+
total = %total_user_tracks.magenta(),
648
+
"Fetched user tracks"
649
+
);
650
+
651
+
for user_track in &user_tracks {
652
+
tracing::info!(user_id = %user_track.user_id.cyan(), track_id = %user_track.track_id.magenta(), i = %i.magenta(), total = %total_user_tracks.magenta(), "Inserting user track");
653
+
match repo::track::insert_user_track(&pools.destination, user_track).await {
654
+
Ok(_) => {}
655
+
Err(e) => {
656
+
tracing::error!(error = %e, "Failed to insert user track");
657
+
}
658
+
}
659
+
i += 1;
660
+
}
661
+
}
662
+
Ok(())
663
+
}
664
+
665
+
async fn sync_user_playlists(pools: &DatabasePools) -> Result<(), Error> {
666
+
let total_user_playlists: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM user_playlists")
667
+
.fetch_one(&pools.source)
668
+
.await?;
669
+
let total_user_playlists = total_user_playlists.0;
670
+
tracing::info!(total = %total_user_playlists.magenta(), "Total user playlists to sync");
671
+
672
+
let start = 0;
673
+
let mut i = 1;
674
+
675
+
for offset in (start..total_user_playlists).step_by(BATCH_SIZE) {
676
+
let user_playlists =
677
+
repo::playlist::get_user_playlists(&pools.source, offset as i64, BATCH_SIZE as i64)
678
+
.await?;
679
+
tracing::info!(
680
+
offset = %offset.magenta(),
681
+
end = %((offset + user_playlists.len() as i64).min(total_user_playlists)).magenta(),
682
+
total = %total_user_playlists.magenta(),
683
+
"Fetched user playlists"
684
+
);
685
+
686
+
for user_playlist in &user_playlists {
687
+
tracing::info!(user_id = %user_playlist.user_id.cyan(), playlist_id = %user_playlist.playlist_id.magenta(), i = %i.magenta(), total = %total_user_playlists.magenta(), "Inserting user playlist");
688
+
match repo::playlist::insert_user_playlist(&pools.destination, user_playlist).await {
689
+
Ok(_) => {}
690
+
Err(e) => {
691
+
tracing::error!(error = %e, "Failed to insert user playlist");
692
+
}
693
+
}
694
+
i += 1;
695
+
}
696
+
}
697
+
Ok(())
698
+
}
+126
crates/pgpull/src/repo/album.rs
+126
crates/pgpull/src/repo/album.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::{album::Album, album_track::AlbumTrack, user_album::UserAlbum};
5
+
6
+
pub async fn get_albums(
7
+
pool: &Pool<Postgres>,
8
+
offset: i64,
9
+
limit: i64,
10
+
) -> Result<Vec<Album>, Error> {
11
+
let albums: Vec<Album> = sqlx::query_as("SELECT * FROM albums OFFSET $1 LIMIT $2")
12
+
.bind(offset)
13
+
.bind(limit)
14
+
.fetch_all(pool)
15
+
.await?;
16
+
Ok(albums)
17
+
}
18
+
19
+
pub async fn get_album_tracks(
20
+
pool: &Pool<Postgres>,
21
+
offset: i64,
22
+
limit: i64,
23
+
) -> Result<Vec<AlbumTrack>, Error> {
24
+
let album_tracks: Vec<AlbumTrack> =
25
+
sqlx::query_as("SELECT * FROM album_tracks OFFSET $1 LIMIT $2")
26
+
.bind(offset)
27
+
.bind(limit)
28
+
.fetch_all(pool)
29
+
.await?;
30
+
Ok(album_tracks)
31
+
}
32
+
33
+
pub async fn get_user_albums(
34
+
pool: &Pool<Postgres>,
35
+
offset: i64,
36
+
limit: i64,
37
+
) -> Result<Vec<UserAlbum>, Error> {
38
+
let user_albums: Vec<UserAlbum> =
39
+
sqlx::query_as("SELECT * FROM user_albums OFFSET $1 LIMIT $2")
40
+
.bind(offset)
41
+
.bind(limit)
42
+
.fetch_all(pool)
43
+
.await?;
44
+
Ok(user_albums)
45
+
}
46
+
47
+
pub async fn insert_album(pool: &Pool<Postgres>, album: &Album) -> Result<(), Error> {
48
+
sqlx::query(
49
+
r#"INSERT INTO albums (
50
+
xata_id,
51
+
title,
52
+
artist,
53
+
release_date,
54
+
album_art,
55
+
year,
56
+
spotify_link,
57
+
tidal_link,
58
+
youtube_link,
59
+
apple_music_link,
60
+
sha256,
61
+
uri,
62
+
artist_uri,
63
+
xata_createdat
64
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
65
+
ON CONFLICT (xata_id) DO NOTHING"#,
66
+
)
67
+
.bind(&album.xata_id)
68
+
.bind(&album.title)
69
+
.bind(&album.artist)
70
+
.bind(&album.release_date)
71
+
.bind(&album.album_art)
72
+
.bind(album.year)
73
+
.bind(&album.spotify_link)
74
+
.bind(&album.tidal_link)
75
+
.bind(&album.youtube_link)
76
+
.bind(&album.apple_music_link)
77
+
.bind(&album.sha256)
78
+
.bind(&album.uri)
79
+
.bind(&album.artist_uri)
80
+
.bind(album.xata_createdat)
81
+
.execute(pool)
82
+
.await?;
83
+
84
+
Ok(())
85
+
}
86
+
87
+
pub async fn insert_album_track(
88
+
pool: &Pool<Postgres>,
89
+
album_track: &AlbumTrack,
90
+
) -> Result<(), Error> {
91
+
sqlx::query(
92
+
r#"INSERT INTO album_tracks (
93
+
xata_id,
94
+
album_id,
95
+
track_id
96
+
) VALUES ($1, $2, $3)
97
+
ON CONFLICT (xata_id) DO NOTHING"#,
98
+
)
99
+
.bind(&album_track.xata_id)
100
+
.bind(&album_track.album_id)
101
+
.bind(&album_track.track_id)
102
+
.execute(pool)
103
+
.await?;
104
+
Ok(())
105
+
}
106
+
107
+
pub async fn insert_user_album(pool: &Pool<Postgres>, user_album: &UserAlbum) -> Result<(), Error> {
108
+
sqlx::query(
109
+
r#"INSERT INTO user_albums (
110
+
xata_id,
111
+
user_id,
112
+
album_id,
113
+
uri,
114
+
xata_createdat
115
+
) VALUES ($1, $2, $3, $4, $5)
116
+
ON CONFLICT (xata_id) DO NOTHING"#,
117
+
)
118
+
.bind(&user_album.xata_id)
119
+
.bind(&user_album.user_id)
120
+
.bind(&user_album.album_id)
121
+
.bind(&user_album.uri)
122
+
.bind(user_album.xata_createdat)
123
+
.execute(pool)
124
+
.await?;
125
+
Ok(())
126
+
}
+170
crates/pgpull/src/repo/artist.rs
+170
crates/pgpull/src/repo/artist.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::{
5
+
artist::Artist, artist_album::ArtistAlbum, artist_track::ArtistTrack, user_artist::UserArtist,
6
+
};
7
+
8
+
pub async fn get_artists(
9
+
pool: &Pool<Postgres>,
10
+
offset: i64,
11
+
limit: i64,
12
+
) -> Result<Vec<Artist>, Error> {
13
+
let artists = sqlx::query_as::<_, Artist>("SELECT * FROM artists OFFSET $1 LIMIT $2")
14
+
.bind(offset)
15
+
.bind(limit)
16
+
.fetch_all(pool)
17
+
.await?;
18
+
Ok(artists)
19
+
}
20
+
21
+
pub async fn insert_artist(pool: &Pool<Postgres>, artist: &Artist) -> Result<(), Error> {
22
+
sqlx::query(
23
+
r#"INSERT INTO artists (
24
+
xata_id,
25
+
name,
26
+
biography,
27
+
born,
28
+
born_in,
29
+
died,
30
+
picture,
31
+
sha256,
32
+
spotify_link,
33
+
tidal_link,
34
+
youtube_link,
35
+
apple_music_link,
36
+
uri,
37
+
genres,
38
+
xata_createdat
39
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
40
+
ON CONFLICT (xata_id) DO NOTHING"#,
41
+
)
42
+
.bind(&artist.xata_id)
43
+
.bind(&artist.name)
44
+
.bind(&artist.biography)
45
+
.bind(&artist.born)
46
+
.bind(&artist.born_in)
47
+
.bind(&artist.died)
48
+
.bind(&artist.picture)
49
+
.bind(&artist.sha256)
50
+
.bind(&artist.spotify_link)
51
+
.bind(&artist.tidal_link)
52
+
.bind(&artist.youtube_link)
53
+
.bind(&artist.apple_music_link)
54
+
.bind(&artist.uri)
55
+
.bind(&artist.genres)
56
+
.bind(artist.xata_createdat)
57
+
.execute(pool)
58
+
.await?;
59
+
Ok(())
60
+
}
61
+
62
+
pub async fn get_artist_albums(
63
+
pool: &Pool<Postgres>,
64
+
offset: i64,
65
+
limit: i64,
66
+
) -> Result<Vec<ArtistAlbum>, Error> {
67
+
let artist_albums =
68
+
sqlx::query_as::<_, ArtistAlbum>("SELECT * FROM artist_albums OFFSET $1 LIMIT $2")
69
+
.bind(offset)
70
+
.bind(limit)
71
+
.fetch_all(pool)
72
+
.await?;
73
+
Ok(artist_albums)
74
+
}
75
+
76
+
pub async fn get_artist_tracks(
77
+
pool: &Pool<Postgres>,
78
+
offset: i64,
79
+
limit: i64,
80
+
) -> Result<Vec<ArtistTrack>, Error> {
81
+
let artist_tracks =
82
+
sqlx::query_as::<_, ArtistTrack>("SELECT * FROM artist_tracks OFFSET $1 LIMIT $2")
83
+
.bind(offset)
84
+
.bind(limit)
85
+
.fetch_all(pool)
86
+
.await?;
87
+
Ok(artist_tracks)
88
+
}
89
+
90
+
pub async fn get_user_artists(
91
+
pool: &Pool<Postgres>,
92
+
offset: i64,
93
+
limit: i64,
94
+
) -> Result<Vec<UserArtist>, Error> {
95
+
let user_artists =
96
+
sqlx::query_as::<_, UserArtist>("SELECT * FROM user_artists OFFSET $1 LIMIT $2")
97
+
.bind(offset)
98
+
.bind(limit)
99
+
.fetch_all(pool)
100
+
.await?;
101
+
Ok(user_artists)
102
+
}
103
+
104
+
pub async fn insert_artist_album(
105
+
pool: &Pool<Postgres>,
106
+
artist_album: &ArtistAlbum,
107
+
) -> Result<(), Error> {
108
+
sqlx::query(
109
+
r#"INSERT INTO artist_albums (
110
+
xata_id,
111
+
artist_id,
112
+
album_id,
113
+
xata_createdat
114
+
) VALUES ($1, $2, $3, $4)
115
+
ON CONFLICT (xata_id) DO NOTHING"#,
116
+
)
117
+
.bind(&artist_album.xata_id)
118
+
.bind(&artist_album.artist_id)
119
+
.bind(&artist_album.album_id)
120
+
.bind(artist_album.xata_createdat)
121
+
.execute(pool)
122
+
.await?;
123
+
Ok(())
124
+
}
125
+
126
+
pub async fn insert_artist_track(
127
+
pool: &Pool<Postgres>,
128
+
artist_track: &ArtistTrack,
129
+
) -> Result<(), Error> {
130
+
sqlx::query(
131
+
r#"INSERT INTO artist_tracks (
132
+
xata_id,
133
+
artist_id,
134
+
track_id,
135
+
xata_createdat
136
+
) VALUES ($1, $2, $3, $4)
137
+
ON CONFLICT (xata_id) DO NOTHING"#,
138
+
)
139
+
.bind(&artist_track.xata_id)
140
+
.bind(&artist_track.artist_id)
141
+
.bind(&artist_track.track_id) // Reusing album_id field for track_id
142
+
.bind(artist_track.xata_createdat)
143
+
.execute(pool)
144
+
.await?;
145
+
Ok(())
146
+
}
147
+
148
+
pub async fn insert_user_artist(
149
+
pool: &Pool<Postgres>,
150
+
user_artist: &UserArtist,
151
+
) -> Result<(), Error> {
152
+
sqlx::query(
153
+
r#"INSERT INTO user_artists (
154
+
xata_id,
155
+
user_id,
156
+
artist_id,
157
+
uri,
158
+
xata_createdat
159
+
) VALUES ($1, $2, $3, $4, $5)
160
+
ON CONFLICT (xata_id) DO NOTHING"#,
161
+
)
162
+
.bind(&user_artist.xata_id)
163
+
.bind(&user_artist.user_id)
164
+
.bind(&user_artist.artist_id)
165
+
.bind(&user_artist.uri)
166
+
.bind(user_artist.xata_createdat)
167
+
.execute(pool)
168
+
.await?;
169
+
Ok(())
170
+
}
+40
crates/pgpull/src/repo/loved_track.rs
+40
crates/pgpull/src/repo/loved_track.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::loved_track::LovedTrack;
5
+
6
+
pub async fn get_loved_tracks(
7
+
pool: &Pool<Postgres>,
8
+
offset: i64,
9
+
limit: i64,
10
+
) -> Result<Vec<LovedTrack>, Error> {
11
+
let loved_tracks =
12
+
sqlx::query_as::<_, LovedTrack>("SELECT * FROM loved_tracks OFFSET $1 LIMIT $2")
13
+
.bind(offset)
14
+
.bind(limit)
15
+
.fetch_all(pool)
16
+
.await?;
17
+
Ok(loved_tracks)
18
+
}
19
+
20
+
pub async fn insert_loved_track(
21
+
pool: &Pool<Postgres>,
22
+
loved_track: &LovedTrack,
23
+
) -> Result<(), Error> {
24
+
sqlx::query(
25
+
r#"INSERT INTO loved_tracks (
26
+
xata_id,
27
+
user_id,
28
+
track_id,
29
+
xata_createdat
30
+
) VALUES ($1, $2, $3, $4)
31
+
ON CONFLICT (xata_id) DO NOTHING"#,
32
+
)
33
+
.bind(&loved_track.xata_id)
34
+
.bind(&loved_track.user_id)
35
+
.bind(&loved_track.track_id)
36
+
.bind(loved_track.xata_createdat)
37
+
.execute(pool)
38
+
.await?;
39
+
Ok(())
40
+
}
+7
crates/pgpull/src/repo/mod.rs
+7
crates/pgpull/src/repo/mod.rs
+124
crates/pgpull/src/repo/playlist.rs
+124
crates/pgpull/src/repo/playlist.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::{playlist::Playlist, playlist_track::PlaylistTrack, user_playlist::UserPlaylist};
5
+
6
+
pub async fn get_playlists(
7
+
pool: &Pool<Postgres>,
8
+
offset: i64,
9
+
limit: i64,
10
+
) -> Result<Vec<Playlist>, Error> {
11
+
let playlists: Vec<Playlist> = sqlx::query_as("SELECT * FROM playlists OFFSET $1 LIMIT $2")
12
+
.bind(offset)
13
+
.bind(limit)
14
+
.fetch_all(pool)
15
+
.await?;
16
+
Ok(playlists)
17
+
}
18
+
19
+
pub async fn get_playlist_tracks(
20
+
pool: &Pool<Postgres>,
21
+
offset: i64,
22
+
limit: i64,
23
+
) -> Result<Vec<PlaylistTrack>, Error> {
24
+
let playlist_tracks: Vec<PlaylistTrack> =
25
+
sqlx::query_as("SELECT * FROM playlist_tracks OFFSET $1 LIMIT $2")
26
+
.bind(offset)
27
+
.bind(limit)
28
+
.fetch_all(pool)
29
+
.await?;
30
+
Ok(playlist_tracks)
31
+
}
32
+
33
+
pub async fn get_user_playlists(
34
+
pool: &Pool<Postgres>,
35
+
offset: i64,
36
+
limit: i64,
37
+
) -> Result<Vec<UserPlaylist>, Error> {
38
+
let user_playlists: Vec<UserPlaylist> =
39
+
sqlx::query_as("SELECT * FROM user_playlists OFFSET $1 LIMIT $2")
40
+
.bind(offset)
41
+
.bind(limit)
42
+
.fetch_all(pool)
43
+
.await?;
44
+
Ok(user_playlists)
45
+
}
46
+
47
+
pub async fn insert_playlist(pool: &Pool<Postgres>, playlist: &Playlist) -> Result<(), Error> {
48
+
sqlx::query(
49
+
r#"INSERT INTO playlists (
50
+
xata_id,
51
+
name,
52
+
description,
53
+
picture,
54
+
spotify_link,
55
+
tidal_link,
56
+
apple_music_link,
57
+
xata_createdat,
58
+
xata_updatedat,
59
+
uri,
60
+
created_by
61
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
62
+
ON CONFLICT (xata_id) DO NOTHING"#,
63
+
)
64
+
.bind(&playlist.xata_id)
65
+
.bind(&playlist.name)
66
+
.bind(&playlist.description)
67
+
.bind(&playlist.picture)
68
+
.bind(&playlist.spotify_link)
69
+
.bind(&playlist.tidal_link)
70
+
.bind(&playlist.apple_music_link)
71
+
.bind(playlist.xata_createdat)
72
+
.bind(playlist.xata_updatedat)
73
+
.bind(&playlist.uri)
74
+
.bind(&playlist.created_by)
75
+
.execute(pool)
76
+
.await?;
77
+
Ok(())
78
+
}
79
+
80
+
pub async fn insert_playlist_track(
81
+
pool: &Pool<Postgres>,
82
+
playlist_track: &PlaylistTrack,
83
+
) -> Result<(), Error> {
84
+
sqlx::query(
85
+
r#"INSERT INTO playlist_tracks (
86
+
xata_id,
87
+
playlist_id,
88
+
track_id,
89
+
xata_createdat
90
+
) VALUES ($1, $2, $3, $4)
91
+
ON CONFLICT (xata_id) DO NOTHING"#,
92
+
)
93
+
.bind(&playlist_track.xata_id)
94
+
.bind(&playlist_track.playlist_id)
95
+
.bind(&playlist_track.track_id)
96
+
.bind(playlist_track.xata_createdat)
97
+
.execute(pool)
98
+
.await?;
99
+
Ok(())
100
+
}
101
+
102
+
pub async fn insert_user_playlist(
103
+
pool: &Pool<Postgres>,
104
+
user_playlist: &UserPlaylist,
105
+
) -> Result<(), Error> {
106
+
sqlx::query(
107
+
r#"INSERT INTO user_playlists (
108
+
xata_id,
109
+
user_id,
110
+
playlist_id,
111
+
uri,
112
+
xata_createdat
113
+
) VALUES ($1, $2, $3, $4, $5)
114
+
ON CONFLICT (xata_id) DO NOTHING"#,
115
+
)
116
+
.bind(&user_playlist.xata_id)
117
+
.bind(&user_playlist.user_id)
118
+
.bind(&user_playlist.playlist_id)
119
+
.bind(&user_playlist.uri)
120
+
.bind(user_playlist.xata_createdat)
121
+
.execute(pool)
122
+
.await?;
123
+
Ok(())
124
+
}
+44
crates/pgpull/src/repo/scrobble.rs
+44
crates/pgpull/src/repo/scrobble.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::scrobble::Scrobble;
5
+
6
+
pub async fn get_scrobbles(
7
+
pool: &Pool<Postgres>,
8
+
offset: i64,
9
+
limit: i64,
10
+
) -> Result<Vec<Scrobble>, Error> {
11
+
let scrobbles = sqlx::query_as::<_, Scrobble>("SELECT * FROM scrobbles OFFSET $1 LIMIT $2")
12
+
.bind(offset)
13
+
.bind(limit)
14
+
.fetch_all(pool)
15
+
.await?;
16
+
Ok(scrobbles)
17
+
}
18
+
19
+
pub async fn insert_scrobble(pool: &Pool<Postgres>, scrobble: &Scrobble) -> Result<(), Error> {
20
+
sqlx::query(
21
+
r#"INSERT INTO scrobbles (
22
+
xata_id,
23
+
user_id,
24
+
track_id,
25
+
album_id,
26
+
artist_id,
27
+
uri,
28
+
xata_createdat,
29
+
timestamp
30
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
31
+
ON CONFLICT (xata_id) DO NOTHING"#,
32
+
)
33
+
.bind(&scrobble.xata_id)
34
+
.bind(&scrobble.user_id)
35
+
.bind(&scrobble.track_id)
36
+
.bind(&scrobble.album_id)
37
+
.bind(&scrobble.artist_id)
38
+
.bind(&scrobble.uri)
39
+
.bind(scrobble.xata_createdat)
40
+
.bind(scrobble.timestamp)
41
+
.execute(pool)
42
+
.await?;
43
+
Ok(())
44
+
}
+113
crates/pgpull/src/repo/track.rs
+113
crates/pgpull/src/repo/track.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::{track::Track, user_track::UserTrack};
5
+
6
+
pub async fn get_tracks(
7
+
pool: &Pool<Postgres>,
8
+
offset: i64,
9
+
limit: i64,
10
+
) -> Result<Vec<Track>, Error> {
11
+
let tracks: Vec<Track> = sqlx::query_as("SELECT * FROM tracks OFFSET $1 LIMIT $2")
12
+
.bind(offset)
13
+
.bind(limit)
14
+
.fetch_all(pool)
15
+
.await?;
16
+
Ok(tracks)
17
+
}
18
+
19
+
pub async fn get_user_tracks(
20
+
pool: &Pool<Postgres>,
21
+
offset: i64,
22
+
limit: i64,
23
+
) -> Result<Vec<UserTrack>, Error> {
24
+
let user_tracks: Vec<UserTrack> =
25
+
sqlx::query_as("SELECT * FROM user_tracks OFFSET $1 LIMIT $2")
26
+
.bind(offset)
27
+
.bind(limit)
28
+
.fetch_all(pool)
29
+
.await?;
30
+
Ok(user_tracks)
31
+
}
32
+
33
+
pub async fn insert_track(pool: &Pool<Postgres>, track: &Track) -> Result<(), Error> {
34
+
sqlx::query(
35
+
r#"INSERT INTO tracks (
36
+
xata_id,
37
+
title,
38
+
artist,
39
+
album_artist,
40
+
album_art,
41
+
album,
42
+
track_number,
43
+
duration,
44
+
mb_id,
45
+
youtube_link,
46
+
spotify_link,
47
+
tidal_link,
48
+
apple_music_link,
49
+
sha256,
50
+
lyrics,
51
+
composer,
52
+
genre,
53
+
disc_number,
54
+
copyright_message,
55
+
label,
56
+
uri,
57
+
artist_uri,
58
+
album_uri,
59
+
xata_createdat
60
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
61
+
ON CONFLICT (xata_id) DO NOTHING
62
+
"#,
63
+
)
64
+
.bind(&track.xata_id)
65
+
.bind(&track.title)
66
+
.bind(&track.artist)
67
+
.bind(&track.album_artist)
68
+
.bind(&track.album_art)
69
+
.bind(&track.album)
70
+
.bind(track.track_number)
71
+
.bind(track.duration)
72
+
.bind(&track.mb_id)
73
+
.bind(&track.youtube_link)
74
+
.bind(&track.spotify_link)
75
+
.bind(&track.tidal_link)
76
+
.bind(&track.apple_music_link)
77
+
.bind(&track.sha256)
78
+
.bind(&track.lyrics)
79
+
.bind(&track.composer)
80
+
.bind(&track.genre)
81
+
.bind(track.disc_number)
82
+
.bind(&track.copyright_message)
83
+
.bind(&track.label)
84
+
.bind(&track.uri)
85
+
.bind(&track.artist_uri)
86
+
.bind(&track.album_uri)
87
+
.bind(track.xata_createdat)
88
+
.execute(pool)
89
+
.await?;
90
+
Ok(())
91
+
}
92
+
93
+
pub async fn insert_user_track(pool: &Pool<Postgres>, user_track: &UserTrack) -> Result<(), Error> {
94
+
sqlx::query(
95
+
r#"INSERT INTO user_tracks (
96
+
xata_id,
97
+
user_id,
98
+
track_id,
99
+
uri,
100
+
xata_createdat
101
+
) VALUES ($1, $2, $3, $4, $5)
102
+
ON CONFLICT (xata_id) DO NOTHING
103
+
"#,
104
+
)
105
+
.bind(&user_track.xata_id)
106
+
.bind(&user_track.user_id)
107
+
.bind(&user_track.track_id)
108
+
.bind(&user_track.uri)
109
+
.bind(user_track.xata_createdat)
110
+
.execute(pool)
111
+
.await?;
112
+
Ok(())
113
+
}
+36
crates/pgpull/src/repo/user.rs
+36
crates/pgpull/src/repo/user.rs
···
1
+
use anyhow::Error;
2
+
use sqlx::{Pool, Postgres};
3
+
4
+
use crate::xata::user::User;
5
+
6
+
pub async fn get_users(pool: &Pool<Postgres>, offset: i64, limit: i64) -> Result<Vec<User>, Error> {
7
+
let users = sqlx::query_as::<_, User>("SELECT * FROM users OFFSET $1 LIMIT $2")
8
+
.bind(offset)
9
+
.bind(limit)
10
+
.fetch_all(pool)
11
+
.await?;
12
+
Ok(users)
13
+
}
14
+
15
+
pub async fn insert_user(pool: &Pool<Postgres>, user: &User) -> Result<(), Error> {
16
+
sqlx::query(
17
+
r#"INSERT INTO users (
18
+
xata_id,
19
+
display_name,
20
+
did,
21
+
handle,
22
+
avatar,
23
+
xata_createdat
24
+
) VALUES ($1, $2, $3, $4, $5, $6)
25
+
ON CONFLICT (xata_id) DO NOTHING"#,
26
+
)
27
+
.bind(&user.xata_id)
28
+
.bind(&user.display_name)
29
+
.bind(&user.did)
30
+
.bind(&user.handle)
31
+
.bind(&user.avatar)
32
+
.bind(user.xata_createdat)
33
+
.execute(pool)
34
+
.await?;
35
+
Ok(())
36
+
}
+21
crates/pgpull/src/xata/album.rs
+21
crates/pgpull/src/xata/album.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::Deserialize;
3
+
4
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
5
+
pub struct Album {
6
+
pub xata_id: String,
7
+
pub title: String,
8
+
pub artist: String,
9
+
pub release_date: Option<String>,
10
+
pub album_art: Option<String>,
11
+
pub year: Option<i32>,
12
+
pub spotify_link: Option<String>,
13
+
pub tidal_link: Option<String>,
14
+
pub youtube_link: Option<String>,
15
+
pub apple_music_link: Option<String>,
16
+
pub sha256: String,
17
+
pub uri: Option<String>,
18
+
pub artist_uri: Option<String>,
19
+
#[serde(with = "chrono::serde::ts_seconds")]
20
+
pub xata_createdat: DateTime<Utc>,
21
+
}
+8
crates/pgpull/src/xata/album_track.rs
+8
crates/pgpull/src/xata/album_track.rs
+24
crates/pgpull/src/xata/artist.rs
+24
crates/pgpull/src/xata/artist.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::Deserialize;
3
+
4
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
5
+
pub struct Artist {
6
+
pub xata_id: String,
7
+
pub name: String,
8
+
pub biography: Option<String>,
9
+
#[serde(with = "chrono::serde::ts_seconds_option")]
10
+
pub born: Option<DateTime<Utc>>,
11
+
pub born_in: Option<String>,
12
+
#[serde(with = "chrono::serde::ts_seconds_option")]
13
+
pub died: Option<DateTime<Utc>>,
14
+
pub picture: Option<String>,
15
+
pub sha256: String,
16
+
pub spotify_link: Option<String>,
17
+
pub tidal_link: Option<String>,
18
+
pub youtube_link: Option<String>,
19
+
pub apple_music_link: Option<String>,
20
+
pub uri: Option<String>,
21
+
pub genres: Option<Vec<String>>,
22
+
#[serde(with = "chrono::serde::ts_seconds")]
23
+
pub xata_createdat: DateTime<Utc>,
24
+
}
+10
crates/pgpull/src/xata/artist_album.rs
+10
crates/pgpull/src/xata/artist_album.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct ArtistAlbum {
5
+
pub xata_id: String,
6
+
pub artist_id: String,
7
+
pub album_id: String,
8
+
#[serde(with = "chrono::serde::ts_seconds")]
9
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
10
+
}
+10
crates/pgpull/src/xata/artist_track.rs
+10
crates/pgpull/src/xata/artist_track.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct ArtistTrack {
5
+
pub xata_id: String,
6
+
pub artist_id: String,
7
+
pub track_id: String,
8
+
#[serde(with = "chrono::serde::ts_seconds")]
9
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
10
+
}
+10
crates/pgpull/src/xata/loved_track.rs
+10
crates/pgpull/src/xata/loved_track.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct LovedTrack {
5
+
pub xata_id: String,
6
+
pub user_id: String,
7
+
pub track_id: String,
8
+
#[serde(with = "chrono::serde::ts_seconds")]
9
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
10
+
}
+15
crates/pgpull/src/xata/mod.rs
+15
crates/pgpull/src/xata/mod.rs
···
1
+
pub mod album;
2
+
pub mod album_track;
3
+
pub mod artist;
4
+
pub mod artist_album;
5
+
pub mod artist_track;
6
+
pub mod loved_track;
7
+
pub mod playlist;
8
+
pub mod playlist_track;
9
+
pub mod scrobble;
10
+
pub mod track;
11
+
pub mod user;
12
+
pub mod user_album;
13
+
pub mod user_artist;
14
+
pub mod user_playlist;
15
+
pub mod user_track;
+19
crates/pgpull/src/xata/playlist.rs
+19
crates/pgpull/src/xata/playlist.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::Deserialize;
3
+
4
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
5
+
pub struct Playlist {
6
+
pub xata_id: String,
7
+
pub name: String,
8
+
pub description: Option<String>,
9
+
pub picture: Option<String>,
10
+
pub spotify_link: Option<String>,
11
+
pub tidal_link: Option<String>,
12
+
pub apple_music_link: Option<String>,
13
+
#[serde(with = "chrono::serde::ts_seconds")]
14
+
pub xata_createdat: DateTime<Utc>,
15
+
#[serde(with = "chrono::serde::ts_seconds")]
16
+
pub xata_updatedat: DateTime<Utc>,
17
+
pub uri: Option<String>,
18
+
pub created_by: String,
19
+
}
+10
crates/pgpull/src/xata/playlist_track.rs
+10
crates/pgpull/src/xata/playlist_track.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct PlaylistTrack {
5
+
pub xata_id: String,
6
+
pub playlist_id: String,
7
+
pub track_id: String,
8
+
#[serde(with = "chrono::serde::ts_seconds")]
9
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
10
+
}
+16
crates/pgpull/src/xata/scrobble.rs
+16
crates/pgpull/src/xata/scrobble.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::Deserialize;
3
+
4
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
5
+
pub struct Scrobble {
6
+
pub xata_id: String,
7
+
pub user_id: String,
8
+
pub track_id: String,
9
+
pub album_id: Option<String>,
10
+
pub artist_id: Option<String>,
11
+
pub uri: Option<String>,
12
+
#[serde(with = "chrono::serde::ts_seconds")]
13
+
pub xata_createdat: DateTime<Utc>,
14
+
#[serde(with = "chrono::serde::ts_seconds")]
15
+
pub timestamp: DateTime<Utc>,
16
+
}
+31
crates/pgpull/src/xata/track.rs
+31
crates/pgpull/src/xata/track.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::{Deserialize, Serialize};
3
+
4
+
#[derive(Debug, sqlx::FromRow, Serialize, Deserialize, Clone)]
5
+
pub struct Track {
6
+
pub xata_id: String,
7
+
pub title: String,
8
+
pub artist: String,
9
+
pub album_artist: String,
10
+
pub album_art: Option<String>,
11
+
pub album: String,
12
+
pub track_number: i32,
13
+
pub duration: i32,
14
+
pub mb_id: Option<String>,
15
+
pub youtube_link: Option<String>,
16
+
pub spotify_link: Option<String>,
17
+
pub tidal_link: Option<String>,
18
+
pub apple_music_link: Option<String>,
19
+
pub sha256: String,
20
+
pub lyrics: Option<String>,
21
+
pub composer: Option<String>,
22
+
pub genre: Option<String>,
23
+
pub disc_number: i32,
24
+
pub copyright_message: Option<String>,
25
+
pub label: Option<String>,
26
+
pub uri: Option<String>,
27
+
pub artist_uri: Option<String>,
28
+
pub album_uri: Option<String>,
29
+
#[serde(with = "chrono::serde::ts_seconds")]
30
+
pub xata_createdat: DateTime<Utc>,
31
+
}
+13
crates/pgpull/src/xata/user.rs
+13
crates/pgpull/src/xata/user.rs
···
1
+
use chrono::{DateTime, Utc};
2
+
use serde::Deserialize;
3
+
4
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
5
+
pub struct User {
6
+
pub xata_id: String,
7
+
pub display_name: String,
8
+
pub did: String,
9
+
pub handle: String,
10
+
pub avatar: String,
11
+
#[serde(with = "chrono::serde::ts_seconds")]
12
+
pub xata_createdat: DateTime<Utc>,
13
+
}
+11
crates/pgpull/src/xata/user_album.rs
+11
crates/pgpull/src/xata/user_album.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct UserAlbum {
5
+
pub xata_id: String,
6
+
pub user_id: String,
7
+
pub album_id: String,
8
+
pub uri: Option<String>,
9
+
#[serde(with = "chrono::serde::ts_seconds")]
10
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
11
+
}
+11
crates/pgpull/src/xata/user_artist.rs
+11
crates/pgpull/src/xata/user_artist.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct UserArtist {
5
+
pub xata_id: String,
6
+
pub user_id: String,
7
+
pub artist_id: String,
8
+
pub uri: Option<String>,
9
+
#[serde(with = "chrono::serde::ts_seconds")]
10
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
11
+
}
+11
crates/pgpull/src/xata/user_playlist.rs
+11
crates/pgpull/src/xata/user_playlist.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct UserPlaylist {
5
+
pub xata_id: String,
6
+
pub user_id: String,
7
+
pub playlist_id: String,
8
+
pub uri: Option<String>,
9
+
#[serde(with = "chrono::serde::ts_seconds")]
10
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
11
+
}
+11
crates/pgpull/src/xata/user_track.rs
+11
crates/pgpull/src/xata/user_track.rs
···
1
+
use serde::Deserialize;
2
+
3
+
#[derive(Debug, sqlx::FromRow, Deserialize, Clone)]
4
+
pub struct UserTrack {
5
+
pub xata_id: String,
6
+
pub user_id: String,
7
+
pub track_id: String,
8
+
pub uri: Option<String>,
9
+
#[serde(with = "chrono::serde::ts_seconds")]
10
+
pub xata_createdat: chrono::DateTime<chrono::Utc>,
11
+
}
+1
crates/rockskyd/Cargo.toml
+1
crates/rockskyd/Cargo.toml
+1
crates/rockskyd/src/cmd/mod.rs
+1
crates/rockskyd/src/cmd/mod.rs
+5
crates/rockskyd/src/cmd/pull.rs
+5
crates/rockskyd/src/cmd/pull.rs
+8
crates/rockskyd/src/main.rs
+8
crates/rockskyd/src/main.rs
···
32
32
.subcommand(Command::new("spotify").about("Start Spotify Listener Service"))
33
33
.subcommand(Command::new("tracklist").about("Start User Current Track Queue Service"))
34
34
.subcommand(Command::new("webscrobbler").about("Start Webscrobbler API"))
35
+
.subcommand(
36
+
Command::new("pull")
37
+
.about("Pull data from a remote PostgreSQL database to your local PostgresSQL instance")
38
+
.long_about("Pull data from a remote PostgreSQL database to your local PostgresSQL instance. Ensure that the SOURCE_POSTGRES_URL environment variable is set to your remote PostgreSQL connection string."),
39
+
)
35
40
}
36
41
37
42
#[tokio::main]
···
84
89
}
85
90
Some(("webscrobbler", _)) => {
86
91
cmd::webscrobbler::start_webscrobbler_service().await?;
92
+
}
93
+
Some(("pull", _)) => {
94
+
cmd::pull::pull_data().await?;
87
95
}
88
96
_ => {
89
97
println!("No valid subcommand was used. Use --help to see available commands.");