Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).

orm: extract orm package from appview

includes query and migration helpers

Signed-off-by: oppiliappan <me@oppi.li>

authored by oppi.li and committed by

Tangled a53d124e 0a341bcc

+519 -464
+3 -2
appview/db/artifact.go
··· 8 8 "github.com/go-git/go-git/v5/plumbing" 9 9 "github.com/ipfs/go-cid" 10 10 "tangled.org/core/appview/models" 11 + "tangled.org/core/orm" 11 12 ) 12 13 13 14 func AddArtifact(e Execer, artifact models.Artifact) error { ··· 38 37 return err 39 38 } 40 39 41 - func GetArtifact(e Execer, filters ...filter) ([]models.Artifact, error) { 40 + func GetArtifact(e Execer, filters ...orm.Filter) ([]models.Artifact, error) { 42 41 var artifacts []models.Artifact 43 42 44 43 var conditions []string ··· 110 109 return artifacts, nil 111 110 } 112 111 113 - func DeleteArtifact(e Execer, filters ...filter) error { 112 + func DeleteArtifact(e Execer, filters ...orm.Filter) error { 114 113 var conditions []string 115 114 var args []any 116 115 for _, filter := range filters {
+4 -3
appview/db/collaborators.go
··· 6 6 "time" 7 7 8 8 "tangled.org/core/appview/models" 9 + "tangled.org/core/orm" 9 10 ) 10 11 11 12 func AddCollaborator(e Execer, c models.Collaborator) error { ··· 17 16 return err 18 17 } 19 18 20 - func DeleteCollaborator(e Execer, filters ...filter) error { 19 + func DeleteCollaborator(e Execer, filters ...orm.Filter) error { 21 20 var conditions []string 22 21 var args []any 23 22 for _, filter := range filters { ··· 59 58 return nil, nil 60 59 } 61 60 62 - return GetRepos(e, 0, FilterIn("at_uri", repoAts)) 61 + return GetRepos(e, 0, orm.FilterIn("at_uri", repoAts)) 63 62 } 64 63 65 - func GetCollaborators(e Execer, filters ...filter) ([]models.Collaborator, error) { 64 + func GetCollaborators(e Execer, filters ...orm.Filter) ([]models.Collaborator, error) { 66 65 var collaborators []models.Collaborator 67 66 var conditions []string 68 67 var args []any
+24 -137
appview/db/db.go
··· 3 3 import ( 4 4 "context" 5 5 "database/sql" 6 - "fmt" 7 6 "log/slog" 8 - "reflect" 9 7 "strings" 10 8 11 9 _ "github.com/mattn/go-sqlite3" 12 10 "tangled.org/core/log" 11 + "tangled.org/core/orm" 13 12 ) 14 13 15 14 type DB struct { ··· 583 584 } 584 585 585 586 // run migrations 586 - runMigration(conn, logger, "add-description-to-repos", func(tx *sql.Tx) error { 587 + orm.RunMigration(conn, logger, "add-description-to-repos", func(tx *sql.Tx) error { 587 588 tx.Exec(` 588 589 alter table repos add column description text check (length(description) <= 200); 589 590 `) 590 591 return nil 591 592 }) 592 593 593 - runMigration(conn, logger, "add-rkey-to-pubkeys", func(tx *sql.Tx) error { 594 + orm.RunMigration(conn, logger, "add-rkey-to-pubkeys", func(tx *sql.Tx) error { 594 595 // add unconstrained column 595 596 _, err := tx.Exec(` 596 597 alter table public_keys ··· 613 614 return nil 614 615 }) 615 616 616 - runMigration(conn, logger, "add-rkey-to-comments", func(tx *sql.Tx) error { 617 + orm.RunMigration(conn, logger, "add-rkey-to-comments", func(tx *sql.Tx) error { 617 618 _, err := tx.Exec(` 618 619 alter table comments drop column comment_at; 619 620 alter table comments add column rkey text; ··· 621 622 return err 622 623 }) 623 624 624 - runMigration(conn, logger, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error { 625 + orm.RunMigration(conn, logger, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error { 625 626 _, err := tx.Exec(` 626 627 alter table comments add column deleted text; -- timestamp 627 628 alter table comments add column edited text; -- timestamp ··· 629 630 return err 630 631 }) 631 632 632 - runMigration(conn, logger, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error { 633 + orm.RunMigration(conn, logger, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error { 633 634 _, err := tx.Exec(` 634 635 alter table pulls add column source_branch text; 635 636 alter table pulls add column source_repo_at text; ··· 638 639 return err 639 640 }) 640 641 641 - runMigration(conn, logger, "add-source-to-repos", func(tx *sql.Tx) error { 642 + orm.RunMigration(conn, logger, "add-source-to-repos", func(tx *sql.Tx) error { 642 643 _, err := tx.Exec(` 643 644 alter table repos add column source text; 644 645 `) ··· 650 651 // 651 652 // [0]: https://sqlite.org/pragma.html#pragma_foreign_keys 652 653 conn.ExecContext(ctx, "pragma foreign_keys = off;") 653 - runMigration(conn, logger, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error { 654 + orm.RunMigration(conn, logger, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error { 654 655 _, err := tx.Exec(` 655 656 create table pulls_new ( 656 657 -- identifiers ··· 707 708 }) 708 709 conn.ExecContext(ctx, "pragma foreign_keys = on;") 709 710 710 - runMigration(conn, logger, "add-spindle-to-repos", func(tx *sql.Tx) error { 711 + orm.RunMigration(conn, logger, "add-spindle-to-repos", func(tx *sql.Tx) error { 711 712 tx.Exec(` 712 713 alter table repos add column spindle text; 713 714 `) ··· 717 718 // drop all knot secrets, add unique constraint to knots 718 719 // 719 720 // knots will henceforth use service auth for signed requests 720 - runMigration(conn, logger, "no-more-secrets", func(tx *sql.Tx) error { 721 + orm.RunMigration(conn, logger, "no-more-secrets", func(tx *sql.Tx) error { 721 722 _, err := tx.Exec(` 722 723 create table registrations_new ( 723 724 id integer primary key autoincrement, ··· 740 741 }) 741 742 742 743 // recreate and add rkey + created columns with default constraint 743 - runMigration(conn, logger, "rework-collaborators-table", func(tx *sql.Tx) error { 744 + orm.RunMigration(conn, logger, "rework-collaborators-table", func(tx *sql.Tx) error { 744 745 // create new table 745 746 // - repo_at instead of repo integer 746 747 // - rkey field ··· 794 795 return err 795 796 }) 796 797 797 - runMigration(conn, logger, "add-rkey-to-issues", func(tx *sql.Tx) error { 798 + orm.RunMigration(conn, logger, "add-rkey-to-issues", func(tx *sql.Tx) error { 798 799 _, err := tx.Exec(` 799 800 alter table issues add column rkey text not null default ''; 800 801 ··· 806 807 }) 807 808 808 809 // repurpose the read-only column to "needs-upgrade" 809 - runMigration(conn, logger, "rename-registrations-read-only-to-needs-upgrade", func(tx *sql.Tx) error { 810 + orm.RunMigration(conn, logger, "rename-registrations-read-only-to-needs-upgrade", func(tx *sql.Tx) error { 810 811 _, err := tx.Exec(` 811 812 alter table registrations rename column read_only to needs_upgrade; 812 813 `) ··· 814 815 }) 815 816 816 817 // require all knots to upgrade after the release of total xrpc 817 - runMigration(conn, logger, "migrate-knots-to-total-xrpc", func(tx *sql.Tx) error { 818 + orm.RunMigration(conn, logger, "migrate-knots-to-total-xrpc", func(tx *sql.Tx) error { 818 819 _, err := tx.Exec(` 819 820 update registrations set needs_upgrade = 1; 820 821 `) ··· 822 823 }) 823 824 824 825 // require all knots to upgrade after the release of total xrpc 825 - runMigration(conn, logger, "migrate-spindles-to-xrpc-owner", func(tx *sql.Tx) error { 826 + orm.RunMigration(conn, logger, "migrate-spindles-to-xrpc-owner", func(tx *sql.Tx) error { 826 827 _, err := tx.Exec(` 827 828 alter table spindles add column needs_upgrade integer not null default 0; 828 829 `) ··· 840 841 // 841 842 // disable foreign-keys for the next migration 842 843 conn.ExecContext(ctx, "pragma foreign_keys = off;") 843 - runMigration(conn, logger, "remove-issue-at-from-issues", func(tx *sql.Tx) error { 844 + orm.RunMigration(conn, logger, "remove-issue-at-from-issues", func(tx *sql.Tx) error { 844 845 _, err := tx.Exec(` 845 846 create table if not exists issues_new ( 846 847 -- identifiers ··· 910 911 // - new columns 911 912 // * column "reply_to" which can be any other comment 912 913 // * column "at-uri" which is a generated column 913 - runMigration(conn, logger, "rework-issue-comments", func(tx *sql.Tx) error { 914 + orm.RunMigration(conn, logger, "rework-issue-comments", func(tx *sql.Tx) error { 914 915 _, err := tx.Exec(` 915 916 create table if not exists issue_comments ( 916 917 -- identifiers ··· 970 971 // 971 972 // disable foreign-keys for the next migration 972 973 conn.ExecContext(ctx, "pragma foreign_keys = off;") 973 - runMigration(conn, logger, "add-at-uri-to-pulls", func(tx *sql.Tx) error { 974 + orm.RunMigration(conn, logger, "add-at-uri-to-pulls", func(tx *sql.Tx) error { 974 975 _, err := tx.Exec(` 975 976 create table if not exists pulls_new ( 976 977 -- identifiers ··· 1051 1052 // 1052 1053 // disable foreign-keys for the next migration 1053 1054 conn.ExecContext(ctx, "pragma foreign_keys = off;") 1054 - runMigration(conn, logger, "remove-repo-at-pull-id-from-pull-submissions", func(tx *sql.Tx) error { 1055 + orm.RunMigration(conn, logger, "remove-repo-at-pull-id-from-pull-submissions", func(tx *sql.Tx) error { 1055 1056 _, err := tx.Exec(` 1056 1057 create table if not exists pull_submissions_new ( 1057 1058 -- identifiers ··· 1105 1106 1106 1107 // knots may report the combined patch for a comparison, we can store that on the appview side 1107 1108 // (but not on the pds record), because calculating the combined patch requires a git index 1108 - runMigration(conn, logger, "add-combined-column-submissions", func(tx *sql.Tx) error { 1109 + orm.RunMigration(conn, logger, "add-combined-column-submissions", func(tx *sql.Tx) error { 1109 1110 _, err := tx.Exec(` 1110 1111 alter table pull_submissions add column combined text; 1111 1112 `) 1112 1113 return err 1113 1114 }) 1114 1115 1115 - runMigration(conn, logger, "add-pronouns-profile", func(tx *sql.Tx) error { 1116 + orm.RunMigration(conn, logger, "add-pronouns-profile", func(tx *sql.Tx) error { 1116 1117 _, err := tx.Exec(` 1117 1118 alter table profile add column pronouns text; 1118 1119 `) 1119 1120 return err 1120 1121 }) 1121 1122 1122 - runMigration(conn, logger, "add-meta-column-repos", func(tx *sql.Tx) error { 1123 + orm.RunMigration(conn, logger, "add-meta-column-repos", func(tx *sql.Tx) error { 1123 1124 _, err := tx.Exec(` 1124 1125 alter table repos add column website text; 1125 1126 alter table repos add column topics text; ··· 1127 1128 return err 1128 1129 }) 1129 1130 1130 - runMigration(conn, logger, "add-usermentioned-preference", func(tx *sql.Tx) error { 1131 + orm.RunMigration(conn, logger, "add-usermentioned-preference", func(tx *sql.Tx) error { 1131 1132 _, err := tx.Exec(` 1132 1133 alter table notification_preferences add column user_mentioned integer not null default 1; 1133 1134 `) ··· 1135 1136 }) 1136 1137 1137 1138 // remove the foreign key constraints from stars. 1138 - runMigration(conn, logger, "generalize-stars-subject", func(tx *sql.Tx) error { 1139 + orm.RunMigration(conn, logger, "generalize-stars-subject", func(tx *sql.Tx) error { 1139 1140 _, err := tx.Exec(` 1140 1141 create table stars_new ( 1141 1142 id integer primary key autoincrement, ··· 1179 1180 }, nil 1180 1181 } 1181 1182 1182 - type migrationFn = func(*sql.Tx) error 1183 - 1184 - func runMigration(c *sql.Conn, logger *slog.Logger, name string, migrationFn migrationFn) error { 1185 - logger = logger.With("migration", name) 1186 - 1187 - tx, err := c.BeginTx(context.Background(), nil) 1188 - if err != nil { 1189 - return err 1190 - } 1191 - defer tx.Rollback() 1192 - 1193 - var exists bool 1194 - err = tx.QueryRow("select exists (select 1 from migrations where name = ?)", name).Scan(&exists) 1195 - if err != nil { 1196 - return err 1197 - } 1198 - 1199 - if !exists { 1200 - // run migration 1201 - err = migrationFn(tx) 1202 - if err != nil { 1203 - logger.Error("failed to run migration", "err", err) 1204 - return err 1205 - } 1206 - 1207 - // mark migration as complete 1208 - _, err = tx.Exec("insert into migrations (name) values (?)", name) 1209 - if err != nil { 1210 - logger.Error("failed to mark migration as complete", "err", err) 1211 - return err 1212 - } 1213 - 1214 - // commit the transaction 1215 - if err := tx.Commit(); err != nil { 1216 - return err 1217 - } 1218 - 1219 - logger.Info("migration applied successfully") 1220 - } else { 1221 - logger.Warn("skipped migration, already applied") 1222 - } 1223 - 1224 - return nil 1225 - } 1226 - 1227 1183 func (d *DB) Close() error { 1228 1184 return d.DB.Close() 1229 - } 1230 - 1231 - type filter struct { 1232 - key string 1233 - arg any 1234 - cmp string 1235 - } 1236 - 1237 - func newFilter(key, cmp string, arg any) filter { 1238 - return filter{ 1239 - key: key, 1240 - arg: arg, 1241 - cmp: cmp, 1242 - } 1243 - } 1244 - 1245 - func FilterEq(key string, arg any) filter { return newFilter(key, "=", arg) } 1246 - func FilterNotEq(key string, arg any) filter { return newFilter(key, "<>", arg) } 1247 - func FilterGte(key string, arg any) filter { return newFilter(key, ">=", arg) } 1248 - func FilterLte(key string, arg any) filter { return newFilter(key, "<=", arg) } 1249 - func FilterIs(key string, arg any) filter { return newFilter(key, "is", arg) } 1250 - func FilterIsNot(key string, arg any) filter { return newFilter(key, "is not", arg) } 1251 - func FilterIn(key string, arg any) filter { return newFilter(key, "in", arg) } 1252 - func FilterLike(key string, arg any) filter { return newFilter(key, "like", arg) } 1253 - func FilterNotLike(key string, arg any) filter { return newFilter(key, "not like", arg) } 1254 - func FilterContains(key string, arg any) filter { 1255 - return newFilter(key, "like", fmt.Sprintf("%%%v%%", arg)) 1256 - } 1257 - 1258 - func (f filter) Condition() string { 1259 - rv := reflect.ValueOf(f.arg) 1260 - kind := rv.Kind() 1261 - 1262 - // if we have `FilterIn(k, [1, 2, 3])`, compile it down to `k in (?, ?, ?)` 1263 - if (kind == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8) || kind == reflect.Array { 1264 - if rv.Len() == 0 { 1265 - // always false 1266 - return "1 = 0" 1267 - } 1268 - 1269 - placeholders := make([]string, rv.Len()) 1270 - for i := range placeholders { 1271 - placeholders[i] = "?" 1272 - } 1273 - 1274 - return fmt.Sprintf("%s %s (%s)", f.key, f.cmp, strings.Join(placeholders, ", ")) 1275 - } 1276 - 1277 - return fmt.Sprintf("%s %s ?", f.key, f.cmp) 1278 - } 1279 - 1280 - func (f filter) Arg() []any { 1281 - rv := reflect.ValueOf(f.arg) 1282 - kind := rv.Kind() 1283 - if (kind == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8) || kind == reflect.Array { 1284 - if rv.Len() == 0 { 1285 - return nil 1286 - } 1287 - 1288 - out := make([]any, rv.Len()) 1289 - for i := range rv.Len() { 1290 - out[i] = rv.Index(i).Interface() 1291 - } 1292 - return out 1293 - } 1294 - 1295 - return []any{f.arg} 1296 1185 }
+4 -3
appview/db/follow.go
··· 7 7 "time" 8 8 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 13 func AddFollow(e Execer, follow *models.Follow) error { ··· 135 134 return result, nil 136 135 } 137 136 138 - func GetFollows(e Execer, limit int, filters ...filter) ([]models.Follow, error) { 137 + func GetFollows(e Execer, limit int, filters ...orm.Filter) ([]models.Follow, error) { 139 138 var follows []models.Follow 140 139 141 140 var conditions []string ··· 192 191 } 193 192 194 193 func GetFollowers(e Execer, did string) ([]models.Follow, error) { 195 - return GetFollows(e, 0, FilterEq("subject_did", did)) 194 + return GetFollows(e, 0, orm.FilterEq("subject_did", did)) 196 195 } 197 196 198 197 func GetFollowing(e Execer, did string) ([]models.Follow, error) { 199 - return GetFollows(e, 0, FilterEq("user_did", did)) 198 + return GetFollows(e, 0, orm.FilterEq("user_did", did)) 200 199 } 201 200 202 201 func getFollowStatuses(e Execer, userDid string, subjectDids []string) (map[string]models.FollowStatus, error) {
+21 -20
appview/db/issues.go
··· 13 13 "tangled.org/core/api/tangled" 14 14 "tangled.org/core/appview/models" 15 15 "tangled.org/core/appview/pagination" 16 + "tangled.org/core/orm" 16 17 ) 17 18 18 19 func PutIssue(tx *sql.Tx, issue *models.Issue) error { ··· 28 27 29 28 issues, err := GetIssues( 30 29 tx, 31 - FilterEq("did", issue.Did), 32 - FilterEq("rkey", issue.Rkey), 30 + orm.FilterEq("did", issue.Did), 31 + orm.FilterEq("rkey", issue.Rkey), 33 32 ) 34 33 switch { 35 34 case err != nil: ··· 99 98 return nil 100 99 } 101 100 102 - func GetIssuesPaginated(e Execer, page pagination.Page, filters ...filter) ([]models.Issue, error) { 101 + func GetIssuesPaginated(e Execer, page pagination.Page, filters ...orm.Filter) ([]models.Issue, error) { 103 102 issueMap := make(map[string]*models.Issue) // at-uri -> issue 104 103 105 104 var conditions []string ··· 115 114 whereClause = " where " + strings.Join(conditions, " and ") 116 115 } 117 116 118 - pLower := FilterGte("row_num", page.Offset+1) 119 - pUpper := FilterLte("row_num", page.Offset+page.Limit) 117 + pLower := orm.FilterGte("row_num", page.Offset+1) 118 + pUpper := orm.FilterLte("row_num", page.Offset+page.Limit) 120 119 121 120 pageClause := "" 122 121 if page.Limit > 0 { ··· 206 205 repoAts = append(repoAts, string(issue.RepoAt)) 207 206 } 208 207 209 - repos, err := GetRepos(e, 0, FilterIn("at_uri", repoAts)) 208 + repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", repoAts)) 210 209 if err != nil { 211 210 return nil, fmt.Errorf("failed to build repo mappings: %w", err) 212 211 } ··· 229 228 // collect comments 230 229 issueAts := slices.Collect(maps.Keys(issueMap)) 231 230 232 - comments, err := GetIssueComments(e, FilterIn("issue_at", issueAts)) 231 + comments, err := GetIssueComments(e, orm.FilterIn("issue_at", issueAts)) 233 232 if err != nil { 234 233 return nil, fmt.Errorf("failed to query comments: %w", err) 235 234 } ··· 241 240 } 242 241 243 242 // collect allLabels for each issue 244 - allLabels, err := GetLabels(e, FilterIn("subject", issueAts)) 243 + allLabels, err := GetLabels(e, orm.FilterIn("subject", issueAts)) 245 244 if err != nil { 246 245 return nil, fmt.Errorf("failed to query labels: %w", err) 247 246 } ··· 252 251 } 253 252 254 253 // collect references for each issue 255 - allReferencs, err := GetReferencesAll(e, FilterIn("from_at", issueAts)) 254 + allReferencs, err := GetReferencesAll(e, orm.FilterIn("from_at", issueAts)) 256 255 if err != nil { 257 256 return nil, fmt.Errorf("failed to query reference_links: %w", err) 258 257 } ··· 278 277 issues, err := GetIssuesPaginated( 279 278 e, 280 279 pagination.Page{}, 281 - FilterEq("repo_at", repoAt), 282 - FilterEq("issue_id", issueId), 280 + orm.FilterEq("repo_at", repoAt), 281 + orm.FilterEq("issue_id", issueId), 283 282 ) 284 283 if err != nil { 285 284 return nil, err ··· 291 290 return &issues[0], nil 292 291 } 293 292 294 - func GetIssues(e Execer, filters ...filter) ([]models.Issue, error) { 293 + func GetIssues(e Execer, filters ...orm.Filter) ([]models.Issue, error) { 295 294 return GetIssuesPaginated(e, pagination.Page{}, filters...) 296 295 } 297 296 ··· 299 298 func GetIssueIDs(e Execer, opts models.IssueSearchOptions) ([]int64, error) { 300 299 var ids []int64 301 300 302 - var filters []filter 301 + var filters []orm.Filter 303 302 openValue := 0 304 303 if opts.IsOpen { 305 304 openValue = 1 306 305 } 307 - filters = append(filters, FilterEq("open", openValue)) 306 + filters = append(filters, orm.FilterEq("open", openValue)) 308 307 if opts.RepoAt != "" { 309 - filters = append(filters, FilterEq("repo_at", opts.RepoAt)) 308 + filters = append(filters, orm.FilterEq("repo_at", opts.RepoAt)) 310 309 } 311 310 312 311 var conditions []string ··· 398 397 return id, nil 399 398 } 400 399 401 - func DeleteIssueComments(e Execer, filters ...filter) error { 400 + func DeleteIssueComments(e Execer, filters ...orm.Filter) error { 402 401 var conditions []string 403 402 var args []any 404 403 for _, filter := range filters { ··· 417 416 return err 418 417 } 419 418 420 - func GetIssueComments(e Execer, filters ...filter) ([]models.IssueComment, error) { 419 + func GetIssueComments(e Execer, filters ...orm.Filter) ([]models.IssueComment, error) { 421 420 commentMap := make(map[string]*models.IssueComment) 422 421 423 422 var conditions []string ··· 507 506 508 507 // collect references for each comments 509 508 commentAts := slices.Collect(maps.Keys(commentMap)) 510 - allReferencs, err := GetReferencesAll(e, FilterIn("from_at", commentAts)) 509 + allReferencs, err := GetReferencesAll(e, orm.FilterIn("from_at", commentAts)) 511 510 if err != nil { 512 511 return nil, fmt.Errorf("failed to query reference_links: %w", err) 513 512 } ··· 549 548 return nil 550 549 } 551 550 552 - func CloseIssues(e Execer, filters ...filter) error { 551 + func CloseIssues(e Execer, filters ...orm.Filter) error { 553 552 var conditions []string 554 553 var args []any 555 554 for _, filter := range filters { ··· 567 566 return err 568 567 } 569 568 570 - func ReopenIssues(e Execer, filters ...filter) error { 569 + func ReopenIssues(e Execer, filters ...orm.Filter) error { 571 570 var conditions []string 572 571 var args []any 573 572 for _, filter := range filters {
+8 -7
appview/db/label.go
··· 10 10 11 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 12 "tangled.org/core/appview/models" 13 + "tangled.org/core/orm" 13 14 ) 14 15 15 16 // no updating type for now ··· 60 59 return id, nil 61 60 } 62 61 63 - func DeleteLabelDefinition(e Execer, filters ...filter) error { 62 + func DeleteLabelDefinition(e Execer, filters ...orm.Filter) error { 64 63 var conditions []string 65 64 var args []any 66 65 for _, filter := range filters { ··· 76 75 return err 77 76 } 78 77 79 - func GetLabelDefinitions(e Execer, filters ...filter) ([]models.LabelDefinition, error) { 78 + func GetLabelDefinitions(e Execer, filters ...orm.Filter) ([]models.LabelDefinition, error) { 80 79 var labelDefinitions []models.LabelDefinition 81 80 var conditions []string 82 81 var args []any ··· 168 167 } 169 168 170 169 // helper to get exactly one label def 171 - func GetLabelDefinition(e Execer, filters ...filter) (*models.LabelDefinition, error) { 170 + func GetLabelDefinition(e Execer, filters ...orm.Filter) (*models.LabelDefinition, error) { 172 171 labels, err := GetLabelDefinitions(e, filters...) 173 172 if err != nil { 174 173 return nil, err ··· 228 227 return id, nil 229 228 } 230 229 231 - func GetLabelOps(e Execer, filters ...filter) ([]models.LabelOp, error) { 230 + func GetLabelOps(e Execer, filters ...orm.Filter) ([]models.LabelOp, error) { 232 231 var labelOps []models.LabelOp 233 232 var conditions []string 234 233 var args []any ··· 303 302 } 304 303 305 304 // get labels for a given list of subject URIs 306 - func GetLabels(e Execer, filters ...filter) (map[syntax.ATURI]models.LabelState, error) { 305 + func GetLabels(e Execer, filters ...orm.Filter) (map[syntax.ATURI]models.LabelState, error) { 307 306 ops, err := GetLabelOps(e, filters...) 308 307 if err != nil { 309 308 return nil, err ··· 323 322 } 324 323 labelAts := slices.Collect(maps.Keys(labelAtSet)) 325 324 326 - actx, err := NewLabelApplicationCtx(e, FilterIn("at_uri", labelAts)) 325 + actx, err := NewLabelApplicationCtx(e, orm.FilterIn("at_uri", labelAts)) 327 326 if err != nil { 328 327 return nil, err 329 328 } ··· 339 338 return results, nil 340 339 } 341 340 342 - func NewLabelApplicationCtx(e Execer, filters ...filter) (*models.LabelApplicationCtx, error) { 341 + func NewLabelApplicationCtx(e Execer, filters ...orm.Filter) (*models.LabelApplicationCtx, error) { 343 342 labels, err := GetLabelDefinitions(e, filters...) 344 343 if err != nil { 345 344 return nil, err
+5 -4
appview/db/language.go
··· 7 7 8 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 - func GetRepoLanguages(e Execer, filters ...filter) ([]models.RepoLanguage, error) { 13 + func GetRepoLanguages(e Execer, filters ...orm.Filter) ([]models.RepoLanguage, error) { 13 14 var conditions []string 14 15 var args []any 15 16 for _, filter := range filters { ··· 86 85 return nil 87 86 } 88 87 89 - func DeleteRepoLanguages(e Execer, filters ...filter) error { 88 + func DeleteRepoLanguages(e Execer, filters ...orm.Filter) error { 90 89 var conditions []string 91 90 var args []any 92 91 for _, filter := range filters { ··· 108 107 func UpdateRepoLanguages(tx *sql.Tx, repoAt syntax.ATURI, ref string, langs []models.RepoLanguage) error { 109 108 err := DeleteRepoLanguages( 110 109 tx, 111 - FilterEq("repo_at", repoAt), 112 - FilterEq("ref", ref), 110 + orm.FilterEq("repo_at", repoAt), 111 + orm.FilterEq("ref", ref), 113 112 ) 114 113 if err != nil { 115 114 return fmt.Errorf("failed to delete existing languages: %w", err)
+14 -13
appview/db/notifications.go
··· 11 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 12 "tangled.org/core/appview/models" 13 13 "tangled.org/core/appview/pagination" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 17 func CreateNotification(e Execer, notification *models.Notification) error { ··· 45 44 } 46 45 47 46 // GetNotificationsPaginated retrieves notifications with filters and pagination 48 - func GetNotificationsPaginated(e Execer, page pagination.Page, filters ...filter) ([]*models.Notification, error) { 47 + func GetNotificationsPaginated(e Execer, page pagination.Page, filters ...orm.Filter) ([]*models.Notification, error) { 49 48 var conditions []string 50 49 var args []any 51 50 ··· 114 113 } 115 114 116 115 // GetNotificationsWithEntities retrieves notifications with their related entities 117 - func GetNotificationsWithEntities(e Execer, page pagination.Page, filters ...filter) ([]*models.NotificationWithEntity, error) { 116 + func GetNotificationsWithEntities(e Execer, page pagination.Page, filters ...orm.Filter) ([]*models.NotificationWithEntity, error) { 118 117 var conditions []string 119 118 var args []any 120 119 ··· 257 256 } 258 257 259 258 // GetNotifications retrieves notifications with filters 260 - func GetNotifications(e Execer, filters ...filter) ([]*models.Notification, error) { 259 + func GetNotifications(e Execer, filters ...orm.Filter) ([]*models.Notification, error) { 261 260 return GetNotificationsPaginated(e, pagination.FirstPage(), filters...) 262 261 } 263 262 264 - func CountNotifications(e Execer, filters ...filter) (int64, error) { 263 + func CountNotifications(e Execer, filters ...orm.Filter) (int64, error) { 265 264 var conditions []string 266 265 var args []any 267 266 for _, filter := range filters { ··· 286 285 } 287 286 288 287 func MarkNotificationRead(e Execer, notificationID int64, userDID string) error { 289 - idFilter := FilterEq("id", notificationID) 290 - recipientFilter := FilterEq("recipient_did", userDID) 288 + idFilter := orm.FilterEq("id", notificationID) 289 + recipientFilter := orm.FilterEq("recipient_did", userDID) 291 290 292 291 query := fmt.Sprintf(` 293 292 UPDATE notifications ··· 315 314 } 316 315 317 316 func MarkAllNotificationsRead(e Execer, userDID string) error { 318 - recipientFilter := FilterEq("recipient_did", userDID) 319 - readFilter := FilterEq("read", 0) 317 + recipientFilter := orm.FilterEq("recipient_did", userDID) 318 + readFilter := orm.FilterEq("read", 0) 320 319 321 320 query := fmt.Sprintf(` 322 321 UPDATE notifications ··· 335 334 } 336 335 337 336 func DeleteNotification(e Execer, notificationID int64, userDID string) error { 338 - idFilter := FilterEq("id", notificationID) 339 - recipientFilter := FilterEq("recipient_did", userDID) 337 + idFilter := orm.FilterEq("id", notificationID) 338 + recipientFilter := orm.FilterEq("recipient_did", userDID) 340 339 341 340 query := fmt.Sprintf(` 342 341 DELETE FROM notifications ··· 363 362 } 364 363 365 364 func GetNotificationPreference(e Execer, userDid string) (*models.NotificationPreferences, error) { 366 - prefs, err := GetNotificationPreferences(e, FilterEq("user_did", userDid)) 365 + prefs, err := GetNotificationPreferences(e, orm.FilterEq("user_did", userDid)) 367 366 if err != nil { 368 367 return nil, err 369 368 } ··· 376 375 return p, nil 377 376 } 378 377 379 - func GetNotificationPreferences(e Execer, filters ...filter) (map[syntax.DID]*models.NotificationPreferences, error) { 378 + func GetNotificationPreferences(e Execer, filters ...orm.Filter) (map[syntax.DID]*models.NotificationPreferences, error) { 380 379 prefsMap := make(map[syntax.DID]*models.NotificationPreferences) 381 380 382 381 var conditions []string ··· 484 483 485 484 func (d *DB) ClearOldNotifications(ctx context.Context, olderThan time.Duration) error { 486 485 cutoff := time.Now().Add(-olderThan) 487 - createdFilter := FilterLte("created", cutoff) 486 + createdFilter := orm.FilterLte("created", cutoff) 488 487 489 488 query := fmt.Sprintf(` 490 489 DELETE FROM notifications
+6 -5
appview/db/pipeline.go
··· 7 7 "time" 8 8 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 - func GetPipelines(e Execer, filters ...filter) ([]models.Pipeline, error) { 13 + func GetPipelines(e Execer, filters ...orm.Filter) ([]models.Pipeline, error) { 13 14 var pipelines []models.Pipeline 14 15 15 16 var conditions []string ··· 169 168 170 169 // this is a mega query, but the most useful one: 171 170 // get N pipelines, for each one get the latest status of its N workflows 172 - func GetPipelineStatuses(e Execer, limit int, filters ...filter) ([]models.Pipeline, error) { 171 + func GetPipelineStatuses(e Execer, limit int, filters ...orm.Filter) ([]models.Pipeline, error) { 173 172 var conditions []string 174 173 var args []any 175 174 for _, filter := range filters { 176 - filter.key = "p." + filter.key // the table is aliased in the query to `p` 175 + filter.Key = "p." + filter.Key // the table is aliased in the query to `p` 177 176 conditions = append(conditions, filter.Condition()) 178 177 args = append(args, filter.Arg()...) 179 178 } ··· 265 264 conditions = nil 266 265 args = nil 267 266 for _, p := range pipelines { 268 - knotFilter := FilterEq("pipeline_knot", p.Knot) 269 - rkeyFilter := FilterEq("pipeline_rkey", p.Rkey) 267 + knotFilter := orm.FilterEq("pipeline_knot", p.Knot) 268 + rkeyFilter := orm.FilterEq("pipeline_rkey", p.Rkey) 270 269 conditions = append(conditions, fmt.Sprintf("(%s and %s)", knotFilter.Condition(), rkeyFilter.Condition())) 271 270 args = append(args, p.Knot) 272 271 args = append(args, p.Rkey)
+6 -5
appview/db/profile.go
··· 11 11 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 13 "tangled.org/core/appview/models" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 17 const TimeframeMonths = 7 ··· 45 44 46 45 issues, err := GetIssues( 47 46 e, 48 - FilterEq("did", forDid), 49 - FilterGte("created", time.Now().AddDate(0, -TimeframeMonths, 0)), 47 + orm.FilterEq("did", forDid), 48 + orm.FilterGte("created", time.Now().AddDate(0, -TimeframeMonths, 0)), 50 49 ) 51 50 if err != nil { 52 51 return nil, fmt.Errorf("error getting issues by owner did: %w", err) ··· 66 65 *items = append(*items, &issue) 67 66 } 68 67 69 - repos, err := GetRepos(e, 0, FilterEq("did", forDid)) 68 + repos, err := GetRepos(e, 0, orm.FilterEq("did", forDid)) 70 69 if err != nil { 71 70 return nil, fmt.Errorf("error getting all repos by did: %w", err) 72 71 } ··· 200 199 return tx.Commit() 201 200 } 202 201 203 - func GetProfiles(e Execer, filters ...filter) (map[string]*models.Profile, error) { 202 + func GetProfiles(e Execer, filters ...orm.Filter) (map[string]*models.Profile, error) { 204 203 var conditions []string 205 204 var args []any 206 205 for _, filter := range filters { ··· 442 441 } 443 442 444 443 // ensure all pinned repos are either own repos or collaborating repos 445 - repos, err := GetRepos(e, 0, FilterEq("did", profile.Did)) 444 + repos, err := GetRepos(e, 0, orm.FilterEq("did", profile.Did)) 446 445 if err != nil { 447 446 log.Printf("getting repos for %s: %s", profile.Did, err) 448 447 }
+21 -20
appview/db/pulls.go
··· 13 13 14 14 "github.com/bluesky-social/indigo/atproto/syntax" 15 15 "tangled.org/core/appview/models" 16 + "tangled.org/core/orm" 16 17 ) 17 18 18 19 func NewPull(tx *sql.Tx, pull *models.Pull) error { ··· 119 118 return pullId - 1, err 120 119 } 121 120 122 - func GetPullsWithLimit(e Execer, limit int, filters ...filter) ([]*models.Pull, error) { 121 + func GetPullsWithLimit(e Execer, limit int, filters ...orm.Filter) ([]*models.Pull, error) { 123 122 pulls := make(map[syntax.ATURI]*models.Pull) 124 123 125 124 var conditions []string ··· 230 229 for _, p := range pulls { 231 230 pullAts = append(pullAts, p.AtUri()) 232 231 } 233 - submissionsMap, err := GetPullSubmissions(e, FilterIn("pull_at", pullAts)) 232 + submissionsMap, err := GetPullSubmissions(e, orm.FilterIn("pull_at", pullAts)) 234 233 if err != nil { 235 234 return nil, fmt.Errorf("failed to get submissions: %w", err) 236 235 } ··· 242 241 } 243 242 244 243 // collect allLabels for each issue 245 - allLabels, err := GetLabels(e, FilterIn("subject", pullAts)) 244 + allLabels, err := GetLabels(e, orm.FilterIn("subject", pullAts)) 246 245 if err != nil { 247 246 return nil, fmt.Errorf("failed to query labels: %w", err) 248 247 } ··· 259 258 sourceAts = append(sourceAts, *p.PullSource.RepoAt) 260 259 } 261 260 } 262 - sourceRepos, err := GetRepos(e, 0, FilterIn("at_uri", sourceAts)) 261 + sourceRepos, err := GetRepos(e, 0, orm.FilterIn("at_uri", sourceAts)) 263 262 if err != nil && !errors.Is(err, sql.ErrNoRows) { 264 263 return nil, fmt.Errorf("failed to get source repos: %w", err) 265 264 } ··· 275 274 } 276 275 } 277 276 278 - allReferences, err := GetReferencesAll(e, FilterIn("from_at", pullAts)) 277 + allReferences, err := GetReferencesAll(e, orm.FilterIn("from_at", pullAts)) 279 278 if err != nil { 280 279 return nil, fmt.Errorf("failed to query reference_links: %w", err) 281 280 } ··· 296 295 return orderedByPullId, nil 297 296 } 298 297 299 - func GetPulls(e Execer, filters ...filter) ([]*models.Pull, error) { 298 + func GetPulls(e Execer, filters ...orm.Filter) ([]*models.Pull, error) { 300 299 return GetPullsWithLimit(e, 0, filters...) 301 300 } 302 301 303 302 func GetPullIDs(e Execer, opts models.PullSearchOptions) ([]int64, error) { 304 303 var ids []int64 305 304 306 - var filters []filter 307 - filters = append(filters, FilterEq("state", opts.State)) 305 + var filters []orm.Filter 306 + filters = append(filters, orm.FilterEq("state", opts.State)) 308 307 if opts.RepoAt != "" { 309 - filters = append(filters, FilterEq("repo_at", opts.RepoAt)) 308 + filters = append(filters, orm.FilterEq("repo_at", opts.RepoAt)) 310 309 } 311 310 312 311 var conditions []string ··· 362 361 } 363 362 364 363 func GetPull(e Execer, repoAt syntax.ATURI, pullId int) (*models.Pull, error) { 365 - pulls, err := GetPullsWithLimit(e, 1, FilterEq("repo_at", repoAt), FilterEq("pull_id", pullId)) 364 + pulls, err := GetPullsWithLimit(e, 1, orm.FilterEq("repo_at", repoAt), orm.FilterEq("pull_id", pullId)) 366 365 if err != nil { 367 366 return nil, err 368 367 } ··· 374 373 } 375 374 376 375 // mapping from pull -> pull submissions 377 - func GetPullSubmissions(e Execer, filters ...filter) (map[syntax.ATURI][]*models.PullSubmission, error) { 376 + func GetPullSubmissions(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]*models.PullSubmission, error) { 378 377 var conditions []string 379 378 var args []any 380 379 for _, filter := range filters { ··· 449 448 450 449 // Get comments for all submissions using GetPullComments 451 450 submissionIds := slices.Collect(maps.Keys(submissionMap)) 452 - comments, err := GetPullComments(e, FilterIn("submission_id", submissionIds)) 451 + comments, err := GetPullComments(e, orm.FilterIn("submission_id", submissionIds)) 453 452 if err != nil { 454 453 return nil, fmt.Errorf("failed to get pull comments: %w", err) 455 454 } ··· 475 474 return m, nil 476 475 } 477 476 478 - func GetPullComments(e Execer, filters ...filter) ([]models.PullComment, error) { 477 + func GetPullComments(e Execer, filters ...orm.Filter) ([]models.PullComment, error) { 479 478 var conditions []string 480 479 var args []any 481 480 for _, filter := range filters { ··· 543 542 544 543 // collect references for each comments 545 544 commentAts := slices.Collect(maps.Keys(commentMap)) 546 - allReferencs, err := GetReferencesAll(e, FilterIn("from_at", commentAts)) 545 + allReferencs, err := GetReferencesAll(e, orm.FilterIn("from_at", commentAts)) 547 546 if err != nil { 548 547 return nil, fmt.Errorf("failed to query reference_links: %w", err) 549 548 } ··· 709 708 return err 710 709 } 711 710 712 - func SetPullParentChangeId(e Execer, parentChangeId string, filters ...filter) error { 711 + func SetPullParentChangeId(e Execer, parentChangeId string, filters ...orm.Filter) error { 713 712 var conditions []string 714 713 var args []any 715 714 ··· 733 732 734 733 // Only used when stacking to update contents in the event of a rebase (the interdiff should be empty). 735 734 // otherwise submissions are immutable 736 - func UpdatePull(e Execer, newPatch, sourceRev string, filters ...filter) error { 735 + func UpdatePull(e Execer, newPatch, sourceRev string, filters ...orm.Filter) error { 737 736 var conditions []string 738 737 var args []any 739 738 ··· 791 790 func GetStack(e Execer, stackId string) (models.Stack, error) { 792 791 unorderedPulls, err := GetPulls( 793 792 e, 794 - FilterEq("stack_id", stackId), 795 - FilterNotEq("state", models.PullDeleted), 793 + orm.FilterEq("stack_id", stackId), 794 + orm.FilterNotEq("state", models.PullDeleted), 796 795 ) 797 796 if err != nil { 798 797 return nil, err ··· 836 835 func GetAbandonedPulls(e Execer, stackId string) ([]*models.Pull, error) { 837 836 pulls, err := GetPulls( 838 837 e, 839 - FilterEq("stack_id", stackId), 840 - FilterEq("state", models.PullDeleted), 838 + orm.FilterEq("stack_id", stackId), 839 + orm.FilterEq("state", models.PullDeleted), 841 840 ) 842 841 if err != nil { 843 842 return nil, err
+2 -1
appview/db/punchcard.go
··· 7 7 "time" 8 8 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 13 // this adds to the existing count ··· 21 20 return err 22 21 } 23 22 24 - func MakePunchcard(e Execer, filters ...filter) (*models.Punchcard, error) { 23 + func MakePunchcard(e Execer, filters ...orm.Filter) (*models.Punchcard, error) { 25 24 punchcard := &models.Punchcard{} 26 25 now := time.Now() 27 26 startOfYear := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
+4 -3
appview/db/reference.go
··· 8 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 9 "tangled.org/core/api/tangled" 10 10 "tangled.org/core/appview/models" 11 + "tangled.org/core/orm" 11 12 ) 12 13 13 14 // ValidateReferenceLinks resolves refLinks to Issue/PR/IssueComment/PullComment ATURIs. ··· 206 205 return err 207 206 } 208 207 209 - func GetReferencesAll(e Execer, filters ...filter) (map[syntax.ATURI][]syntax.ATURI, error) { 208 + func GetReferencesAll(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]syntax.ATURI, error) { 210 209 var ( 211 210 conditions []string 212 211 args []any ··· 348 347 if len(aturis) == 0 { 349 348 return nil, nil 350 349 } 351 - filter := FilterIn("c.at_uri", aturis) 350 + filter := orm.FilterIn("c.at_uri", aturis) 352 351 rows, err := e.Query( 353 352 fmt.Sprintf( 354 353 `select r.did, r.name, i.issue_id, c.id, i.title, i.open ··· 428 427 if len(aturis) == 0 { 429 428 return nil, nil 430 429 } 431 - filter := FilterIn("c.comment_at", aturis) 430 + filter := orm.FilterIn("c.comment_at", aturis) 432 431 rows, err := e.Query( 433 432 fmt.Sprintf( 434 433 `select r.did, r.name, p.pull_id, c.id, p.title, p.state
+4 -3
appview/db/registration.go
··· 7 7 "time" 8 8 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 - func GetRegistrations(e Execer, filters ...filter) ([]models.Registration, error) { 13 + func GetRegistrations(e Execer, filters ...orm.Filter) ([]models.Registration, error) { 13 14 var registrations []models.Registration 14 15 15 16 var conditions []string ··· 70 69 return registrations, nil 71 70 } 72 71 73 - func MarkRegistered(e Execer, filters ...filter) error { 72 + func MarkRegistered(e Execer, filters ...orm.Filter) error { 74 73 var conditions []string 75 74 var args []any 76 75 for _, filter := range filters { ··· 95 94 return err 96 95 } 97 96 98 - func DeleteKnot(e Execer, filters ...filter) error { 97 + func DeleteKnot(e Execer, filters ...orm.Filter) error { 99 98 var conditions []string 100 99 var args []any 101 100 for _, filter := range filters {
+6 -5
appview/db/repos.go
··· 11 11 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 13 "tangled.org/core/appview/models" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 - func GetRepos(e Execer, limit int, filters ...filter) ([]models.Repo, error) { 17 + func GetRepos(e Execer, limit int, filters ...orm.Filter) ([]models.Repo, error) { 17 18 repoMap := make(map[syntax.ATURI]*models.Repo) 18 19 19 20 var conditions []string ··· 295 294 } 296 295 297 296 // helper to get exactly one repo 298 - func GetRepo(e Execer, filters ...filter) (*models.Repo, error) { 297 + func GetRepo(e Execer, filters ...orm.Filter) (*models.Repo, error) { 299 298 repos, err := GetRepos(e, 0, filters...) 300 299 if err != nil { 301 300 return nil, err ··· 312 311 return &repos[0], nil 313 312 } 314 313 315 - func CountRepos(e Execer, filters ...filter) (int64, error) { 314 + func CountRepos(e Execer, filters ...orm.Filter) (int64, error) { 316 315 var conditions []string 317 316 var args []any 318 317 for _, filter := range filters { ··· 543 542 return err 544 543 } 545 544 546 - func UnsubscribeLabel(e Execer, filters ...filter) error { 545 + func UnsubscribeLabel(e Execer, filters ...orm.Filter) error { 547 546 var conditions []string 548 547 var args []any 549 548 for _, filter := range filters { ··· 561 560 return err 562 561 } 563 562 564 - func GetRepoLabels(e Execer, filters ...filter) ([]models.RepoLabel, error) { 563 + func GetRepoLabels(e Execer, filters ...orm.Filter) ([]models.RepoLabel, error) { 565 564 var conditions []string 566 565 var args []any 567 566 for _, filter := range filters {
+6 -5
appview/db/spindle.go
··· 7 7 "time" 8 8 9 9 "tangled.org/core/appview/models" 10 + "tangled.org/core/orm" 10 11 ) 11 12 12 - func GetSpindles(e Execer, filters ...filter) ([]models.Spindle, error) { 13 + func GetSpindles(e Execer, filters ...orm.Filter) ([]models.Spindle, error) { 13 14 var spindles []models.Spindle 14 15 15 16 var conditions []string ··· 92 91 return err 93 92 } 94 93 95 - func VerifySpindle(e Execer, filters ...filter) (int64, error) { 94 + func VerifySpindle(e Execer, filters ...orm.Filter) (int64, error) { 96 95 var conditions []string 97 96 var args []any 98 97 for _, filter := range filters { ··· 115 114 return res.RowsAffected() 116 115 } 117 116 118 - func DeleteSpindle(e Execer, filters ...filter) error { 117 + func DeleteSpindle(e Execer, filters ...orm.Filter) error { 119 118 var conditions []string 120 119 var args []any 121 120 for _, filter := range filters { ··· 145 144 return err 146 145 } 147 146 148 - func RemoveSpindleMember(e Execer, filters ...filter) error { 147 + func RemoveSpindleMember(e Execer, filters ...orm.Filter) error { 149 148 var conditions []string 150 149 var args []any 151 150 for _, filter := range filters { ··· 164 163 return err 165 164 } 166 165 167 - func GetSpindleMembers(e Execer, filters ...filter) ([]models.SpindleMember, error) { 166 + func GetSpindleMembers(e Execer, filters ...orm.Filter) ([]models.SpindleMember, error) { 168 167 var members []models.SpindleMember 169 168 170 169 var conditions []string
+5 -4
appview/db/star.go
··· 11 11 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 13 "tangled.org/core/appview/models" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 17 func AddStar(e Execer, star *models.Star) error { ··· 134 133 135 134 // GetRepoStars return a list of stars each holding target repository. 136 135 // If there isn't known repo with starred at-uri, those stars will be ignored. 137 - func GetRepoStars(e Execer, limit int, filters ...filter) ([]models.RepoStar, error) { 136 + func GetRepoStars(e Execer, limit int, filters ...orm.Filter) ([]models.RepoStar, error) { 138 137 var conditions []string 139 138 var args []any 140 139 for _, filter := range filters { ··· 196 195 return nil, nil 197 196 } 198 197 199 - repos, err := GetRepos(e, 0, FilterIn("at_uri", args)) 198 + repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", args)) 200 199 if err != nil { 201 200 return nil, err 202 201 } ··· 226 225 return repoStars, nil 227 226 } 228 227 229 - func CountStars(e Execer, filters ...filter) (int64, error) { 228 + func CountStars(e Execer, filters ...orm.Filter) (int64, error) { 230 229 var conditions []string 231 230 var args []any 232 231 for _, filter := range filters { ··· 299 298 } 300 299 301 300 // get full repo data 302 - repos, err := GetRepos(e, 0, FilterIn("at_uri", repoUris)) 301 + repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", repoUris)) 303 302 if err != nil { 304 303 return nil, err 305 304 }
+4 -3
appview/db/strings.go
··· 8 8 "time" 9 9 10 10 "tangled.org/core/appview/models" 11 + "tangled.org/core/orm" 11 12 ) 12 13 13 14 func AddString(e Execer, s models.String) error { ··· 45 44 return err 46 45 } 47 46 48 - func GetStrings(e Execer, limit int, filters ...filter) ([]models.String, error) { 47 + func GetStrings(e Execer, limit int, filters ...orm.Filter) ([]models.String, error) { 49 48 var all []models.String 50 49 51 50 var conditions []string ··· 128 127 return all, nil 129 128 } 130 129 131 - func CountStrings(e Execer, filters ...filter) (int64, error) { 130 + func CountStrings(e Execer, filters ...orm.Filter) (int64, error) { 132 131 var conditions []string 133 132 var args []any 134 133 for _, filter := range filters { ··· 152 151 return count, nil 153 152 } 154 153 155 - func DeleteString(e Execer, filters ...filter) error { 154 + func DeleteString(e Execer, filters ...orm.Filter) error { 156 155 var conditions []string 157 156 var args []any 158 157 for _, filter := range filters {
+9 -8
appview/db/timeline.go
··· 5 5 6 6 "github.com/bluesky-social/indigo/atproto/syntax" 7 7 "tangled.org/core/appview/models" 8 + "tangled.org/core/orm" 8 9 ) 9 10 10 11 // TODO: this gathers heterogenous events from different sources and aggregates ··· 85 84 } 86 85 87 86 func getTimelineRepos(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { 88 - filters := make([]filter, 0) 87 + filters := make([]orm.Filter, 0) 89 88 if userIsFollowing != nil { 90 - filters = append(filters, FilterIn("did", userIsFollowing)) 89 + filters = append(filters, orm.FilterIn("did", userIsFollowing)) 91 90 } 92 91 93 92 repos, err := GetRepos(e, limit, filters...) ··· 105 104 106 105 var origRepos []models.Repo 107 106 if args != nil { 108 - origRepos, err = GetRepos(e, 0, FilterIn("at_uri", args)) 107 + origRepos, err = GetRepos(e, 0, orm.FilterIn("at_uri", args)) 109 108 } 110 109 if err != nil { 111 110 return nil, err ··· 145 144 } 146 145 147 146 func getTimelineStars(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { 148 - filters := make([]filter, 0) 147 + filters := make([]orm.Filter, 0) 149 148 if userIsFollowing != nil { 150 - filters = append(filters, FilterIn("did", userIsFollowing)) 149 + filters = append(filters, orm.FilterIn("did", userIsFollowing)) 151 150 } 152 151 153 152 stars, err := GetRepoStars(e, limit, filters...) ··· 181 180 } 182 181 183 182 func getTimelineFollows(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { 184 - filters := make([]filter, 0) 183 + filters := make([]orm.Filter, 0) 185 184 if userIsFollowing != nil { 186 - filters = append(filters, FilterIn("user_did", userIsFollowing)) 185 + filters = append(filters, orm.FilterIn("user_did", userIsFollowing)) 187 186 } 188 187 189 188 follows, err := GetFollows(e, limit, filters...) ··· 200 199 return nil, nil 201 200 } 202 201 203 - profiles, err := GetProfiles(e, FilterIn("did", subjects)) 202 + profiles, err := GetProfiles(e, orm.FilterIn("did", subjects)) 204 203 if err != nil { 205 204 return nil, err 206 205 }
+25 -24
appview/ingester.go
··· 21 21 "tangled.org/core/appview/serververify" 22 22 "tangled.org/core/appview/validator" 23 23 "tangled.org/core/idresolver" 24 + "tangled.org/core/orm" 24 25 "tangled.org/core/rbac" 25 26 ) 26 27 ··· 254 253 255 254 err = db.AddArtifact(i.Db, artifact) 256 255 case jmodels.CommitOperationDelete: 257 - err = db.DeleteArtifact(i.Db, db.FilterEq("did", did), db.FilterEq("rkey", e.Commit.RKey)) 256 + err = db.DeleteArtifact(i.Db, orm.FilterEq("did", did), orm.FilterEq("rkey", e.Commit.RKey)) 258 257 } 259 258 260 259 if err != nil { ··· 351 350 352 351 err = db.UpsertProfile(tx, &profile) 353 352 case jmodels.CommitOperationDelete: 354 - err = db.DeleteArtifact(i.Db, db.FilterEq("did", did), db.FilterEq("rkey", e.Commit.RKey)) 353 + err = db.DeleteArtifact(i.Db, orm.FilterEq("did", did), orm.FilterEq("rkey", e.Commit.RKey)) 355 354 } 356 355 357 356 if err != nil { ··· 425 424 // get record from db first 426 425 members, err := db.GetSpindleMembers( 427 426 ddb, 428 - db.FilterEq("did", did), 429 - db.FilterEq("rkey", rkey), 427 + orm.FilterEq("did", did), 428 + orm.FilterEq("rkey", rkey), 430 429 ) 431 430 if err != nil || len(members) != 1 { 432 431 return fmt.Errorf("failed to get member: %w, len(members) = %d", err, len(members)) ··· 441 440 // remove record by rkey && update enforcer 442 441 if err = db.RemoveSpindleMember( 443 442 tx, 444 - db.FilterEq("did", did), 445 - db.FilterEq("rkey", rkey), 443 + orm.FilterEq("did", did), 444 + orm.FilterEq("rkey", rkey), 446 445 ); err != nil { 447 446 return fmt.Errorf("failed to remove from db: %w", err) 448 447 } ··· 524 523 // get record from db first 525 524 spindles, err := db.GetSpindles( 526 525 ddb, 527 - db.FilterEq("owner", did), 528 - db.FilterEq("instance", instance), 526 + orm.FilterEq("owner", did), 527 + orm.FilterEq("instance", instance), 529 528 ) 530 529 if err != nil || len(spindles) != 1 { 531 530 return fmt.Errorf("failed to get spindles: %w, len(spindles) = %d", err, len(spindles)) ··· 544 543 // remove spindle members first 545 544 err = db.RemoveSpindleMember( 546 545 tx, 547 - db.FilterEq("owner", did), 548 - db.FilterEq("instance", instance), 546 + orm.FilterEq("owner", did), 547 + orm.FilterEq("instance", instance), 549 548 ) 550 549 if err != nil { 551 550 return err ··· 553 552 554 553 err = db.DeleteSpindle( 555 554 tx, 556 - db.FilterEq("owner", did), 557 - db.FilterEq("instance", instance), 555 + orm.FilterEq("owner", did), 556 + orm.FilterEq("instance", instance), 558 557 ) 559 558 if err != nil { 560 559 return err ··· 622 621 case jmodels.CommitOperationDelete: 623 622 if err := db.DeleteString( 624 623 ddb, 625 - db.FilterEq("did", did), 626 - db.FilterEq("rkey", rkey), 624 + orm.FilterEq("did", did), 625 + orm.FilterEq("rkey", rkey), 627 626 ); err != nil { 628 627 l.Error("failed to delete", "err", err) 629 628 return fmt.Errorf("failed to delete string record: %w", err) ··· 741 740 // get record from db first 742 741 registrations, err := db.GetRegistrations( 743 742 ddb, 744 - db.FilterEq("domain", domain), 745 - db.FilterEq("did", did), 743 + orm.FilterEq("domain", domain), 744 + orm.FilterEq("did", did), 746 745 ) 747 746 if err != nil { 748 747 return fmt.Errorf("failed to get registration: %w", err) ··· 763 762 764 763 err = db.DeleteKnot( 765 764 tx, 766 - db.FilterEq("did", did), 767 - db.FilterEq("domain", domain), 765 + orm.FilterEq("did", did), 766 + orm.FilterEq("domain", domain), 768 767 ) 769 768 if err != nil { 770 769 return err ··· 916 915 case jmodels.CommitOperationDelete: 917 916 if err := db.DeleteIssueComments( 918 917 ddb, 919 - db.FilterEq("did", did), 920 - db.FilterEq("rkey", rkey), 918 + orm.FilterEq("did", did), 919 + orm.FilterEq("rkey", rkey), 921 920 ); err != nil { 922 921 return fmt.Errorf("failed to delete issue comment record: %w", err) 923 922 } ··· 970 969 case jmodels.CommitOperationDelete: 971 970 if err := db.DeleteLabelDefinition( 972 971 ddb, 973 - db.FilterEq("did", did), 974 - db.FilterEq("rkey", rkey), 972 + orm.FilterEq("did", did), 973 + orm.FilterEq("rkey", rkey), 975 974 ); err != nil { 976 975 return fmt.Errorf("failed to delete labeldef record: %w", err) 977 976 } ··· 1011 1010 var repo *models.Repo 1012 1011 switch collection { 1013 1012 case tangled.RepoIssueNSID: 1014 - i, err := db.GetIssues(ddb, db.FilterEq("at_uri", subject)) 1013 + i, err := db.GetIssues(ddb, orm.FilterEq("at_uri", subject)) 1015 1014 if err != nil || len(i) != 1 { 1016 1015 return fmt.Errorf("failed to find subject: %w || subject count %d", err, len(i)) 1017 1016 } ··· 1020 1019 return fmt.Errorf("unsupport label subject: %s", collection) 1021 1020 } 1022 1021 1023 - actx, err := db.NewLabelApplicationCtx(ddb, db.FilterIn("at_uri", repo.Labels)) 1022 + actx, err := db.NewLabelApplicationCtx(ddb, orm.FilterIn("at_uri", repo.Labels)) 1024 1023 if err != nil { 1025 1024 return fmt.Errorf("failed to build label application ctx: %w", err) 1026 1025 }
+16 -15
appview/issues/issues.go
··· 29 29 "tangled.org/core/appview/reporesolver" 30 30 "tangled.org/core/appview/validator" 31 31 "tangled.org/core/idresolver" 32 + "tangled.org/core/orm" 32 33 "tangled.org/core/rbac" 33 34 "tangled.org/core/tid" 34 35 ) ··· 114 113 115 114 labelDefs, err := db.GetLabelDefinitions( 116 115 rp.db, 117 - db.FilterIn("at_uri", f.Labels), 118 - db.FilterContains("scope", tangled.RepoIssueNSID), 116 + orm.FilterIn("at_uri", f.Labels), 117 + orm.FilterContains("scope", tangled.RepoIssueNSID), 119 118 ) 120 119 if err != nil { 121 120 l.Error("failed to fetch labels", "err", err) ··· 315 314 if isIssueOwner || isRepoOwner || isCollaborator { 316 315 err = db.CloseIssues( 317 316 rp.db, 318 - db.FilterEq("id", issue.Id), 317 + orm.FilterEq("id", issue.Id), 319 318 ) 320 319 if err != nil { 321 320 l.Error("failed to close issue", "err", err) ··· 362 361 if isCollaborator || isRepoOwner || isIssueOwner { 363 362 err := db.ReopenIssues( 364 363 rp.db, 365 - db.FilterEq("id", issue.Id), 364 + orm.FilterEq("id", issue.Id), 366 365 ) 367 366 if err != nil { 368 367 l.Error("failed to reopen issue", "err", err) ··· 507 506 commentId := chi.URLParam(r, "commentId") 508 507 comments, err := db.GetIssueComments( 509 508 rp.db, 510 - db.FilterEq("id", commentId), 509 + orm.FilterEq("id", commentId), 511 510 ) 512 511 if err != nil { 513 512 l.Error("failed to fetch comment", "id", commentId) ··· 543 542 commentId := chi.URLParam(r, "commentId") 544 543 comments, err := db.GetIssueComments( 545 544 rp.db, 546 - db.FilterEq("id", commentId), 545 + orm.FilterEq("id", commentId), 547 546 ) 548 547 if err != nil { 549 548 l.Error("failed to fetch comment", "id", commentId) ··· 653 652 commentId := chi.URLParam(r, "commentId") 654 653 comments, err := db.GetIssueComments( 655 654 rp.db, 656 - db.FilterEq("id", commentId), 655 + orm.FilterEq("id", commentId), 657 656 ) 658 657 if err != nil { 659 658 l.Error("failed to fetch comment", "id", commentId) ··· 689 688 commentId := chi.URLParam(r, "commentId") 690 689 comments, err := db.GetIssueComments( 691 690 rp.db, 692 - db.FilterEq("id", commentId), 691 + orm.FilterEq("id", commentId), 693 692 ) 694 693 if err != nil { 695 694 l.Error("failed to fetch comment", "id", commentId) ··· 725 724 commentId := chi.URLParam(r, "commentId") 726 725 comments, err := db.GetIssueComments( 727 726 rp.db, 728 - db.FilterEq("id", commentId), 727 + orm.FilterEq("id", commentId), 729 728 ) 730 729 if err != nil { 731 730 l.Error("failed to fetch comment", "id", commentId) ··· 752 751 753 752 // optimistic deletion 754 753 deleted := time.Now() 755 - err = db.DeleteIssueComments(rp.db, db.FilterEq("id", comment.Id)) 754 + err = db.DeleteIssueComments(rp.db, orm.FilterEq("id", comment.Id)) 756 755 if err != nil { 757 756 l.Error("failed to delete comment", "err", err) 758 757 rp.pages.Notice(w, fmt.Sprintf("comment-%s-status", commentId), "failed to delete comment") ··· 841 840 842 841 issues, err = db.GetIssues( 843 842 rp.db, 844 - db.FilterIn("id", res.Hits), 843 + orm.FilterIn("id", res.Hits), 845 844 ) 846 845 if err != nil { 847 846 l.Error("failed to get issues", "err", err) ··· 857 856 issues, err = db.GetIssuesPaginated( 858 857 rp.db, 859 858 page, 860 - db.FilterEq("repo_at", f.RepoAt()), 861 - db.FilterEq("open", openInt), 859 + orm.FilterEq("repo_at", f.RepoAt()), 860 + orm.FilterEq("open", openInt), 862 861 ) 863 862 if err != nil { 864 863 l.Error("failed to get issues", "err", err) ··· 869 868 870 869 labelDefs, err := db.GetLabelDefinitions( 871 870 rp.db, 872 - db.FilterIn("at_uri", f.Labels), 873 - db.FilterContains("scope", tangled.RepoIssueNSID), 871 + orm.FilterIn("at_uri", f.Labels), 872 + orm.FilterContains("scope", tangled.RepoIssueNSID), 874 873 ) 875 874 if err != nil { 876 875 l.Error("failed to fetch labels", "err", err)
+19 -18
appview/knots/knots.go
··· 21 21 "tangled.org/core/appview/xrpcclient" 22 22 "tangled.org/core/eventconsumer" 23 23 "tangled.org/core/idresolver" 24 + "tangled.org/core/orm" 24 25 "tangled.org/core/rbac" 25 26 "tangled.org/core/tid" 26 27 ··· 73 72 user := k.OAuth.GetUser(r) 74 73 registrations, err := db.GetRegistrations( 75 74 k.Db, 76 - db.FilterEq("did", user.Did), 75 + orm.FilterEq("did", user.Did), 77 76 ) 78 77 if err != nil { 79 78 k.Logger.Error("failed to fetch knot registrations", "err", err) ··· 103 102 104 103 registrations, err := db.GetRegistrations( 105 104 k.Db, 106 - db.FilterEq("did", user.Did), 107 - db.FilterEq("domain", domain), 105 + orm.FilterEq("did", user.Did), 106 + orm.FilterEq("domain", domain), 108 107 ) 109 108 if err != nil { 110 109 l.Error("failed to get registrations", "err", err) ··· 128 127 repos, err := db.GetRepos( 129 128 k.Db, 130 129 0, 131 - db.FilterEq("knot", domain), 130 + orm.FilterEq("knot", domain), 132 131 ) 133 132 if err != nil { 134 133 l.Error("failed to get knot repos", "err", err) ··· 294 293 // get record from db first 295 294 registrations, err := db.GetRegistrations( 296 295 k.Db, 297 - db.FilterEq("did", user.Did), 298 - db.FilterEq("domain", domain), 296 + orm.FilterEq("did", user.Did), 297 + orm.FilterEq("domain", domain), 299 298 ) 300 299 if err != nil { 301 300 l.Error("failed to get registration", "err", err) ··· 322 321 323 322 err = db.DeleteKnot( 324 323 tx, 325 - db.FilterEq("did", user.Did), 326 - db.FilterEq("domain", domain), 324 + orm.FilterEq("did", user.Did), 325 + orm.FilterEq("domain", domain), 327 326 ) 328 327 if err != nil { 329 328 l.Error("failed to delete registration", "err", err) ··· 403 402 // get record from db first 404 403 registrations, err := db.GetRegistrations( 405 404 k.Db, 406 - db.FilterEq("did", user.Did), 407 - db.FilterEq("domain", domain), 405 + orm.FilterEq("did", user.Did), 406 + orm.FilterEq("domain", domain), 408 407 ) 409 408 if err != nil { 410 409 l.Error("failed to get registration", "err", err) ··· 494 493 // Get updated registration to show 495 494 registrations, err = db.GetRegistrations( 496 495 k.Db, 497 - db.FilterEq("did", user.Did), 498 - db.FilterEq("domain", domain), 496 + orm.FilterEq("did", user.Did), 497 + orm.FilterEq("domain", domain), 499 498 ) 500 499 if err != nil { 501 500 l.Error("failed to get registration", "err", err) ··· 530 529 531 530 registrations, err := db.GetRegistrations( 532 531 k.Db, 533 - db.FilterEq("did", user.Did), 534 - db.FilterEq("domain", domain), 535 - db.FilterIsNot("registered", "null"), 532 + orm.FilterEq("did", user.Did), 533 + orm.FilterEq("domain", domain), 534 + orm.FilterIsNot("registered", "null"), 536 535 ) 537 536 if err != nil { 538 537 l.Error("failed to get registration", "err", err) ··· 638 637 639 638 registrations, err := db.GetRegistrations( 640 639 k.Db, 641 - db.FilterEq("did", user.Did), 642 - db.FilterEq("domain", domain), 643 - db.FilterIsNot("registered", "null"), 640 + orm.FilterEq("did", user.Did), 641 + orm.FilterEq("domain", domain), 642 + orm.FilterIsNot("registered", "null"), 644 643 ) 645 644 if err != nil { 646 645 l.Error("failed to get registration", "err", err)
+5 -4
appview/labels/labels.go
··· 16 16 "tangled.org/core/appview/oauth" 17 17 "tangled.org/core/appview/pages" 18 18 "tangled.org/core/appview/validator" 19 + "tangled.org/core/orm" 19 20 "tangled.org/core/rbac" 20 21 "tangled.org/core/tid" 21 22 ··· 89 88 repoAt := r.Form.Get("repo") 90 89 subjectUri := r.Form.Get("subject") 91 90 92 - repo, err := db.GetRepo(l.db, db.FilterEq("at_uri", repoAt)) 91 + repo, err := db.GetRepo(l.db, orm.FilterEq("at_uri", repoAt)) 93 92 if err != nil { 94 93 fail("Failed to get repository.", err) 95 94 return 96 95 } 97 96 98 97 // find all the labels that this repo subscribes to 99 - repoLabels, err := db.GetRepoLabels(l.db, db.FilterEq("repo_at", repoAt)) 98 + repoLabels, err := db.GetRepoLabels(l.db, orm.FilterEq("repo_at", repoAt)) 100 99 if err != nil { 101 100 fail("Failed to get labels for this repository.", err) 102 101 return ··· 107 106 labelAts = append(labelAts, rl.LabelAt.String()) 108 107 } 109 108 110 - actx, err := db.NewLabelApplicationCtx(l.db, db.FilterIn("at_uri", labelAts)) 109 + actx, err := db.NewLabelApplicationCtx(l.db, orm.FilterIn("at_uri", labelAts)) 111 110 if err != nil { 112 111 fail("Invalid form data.", err) 113 112 return 114 113 } 115 114 116 115 // calculate the start state by applying already known labels 117 - existingOps, err := db.GetLabelOps(l.db, db.FilterEq("subject", subjectUri)) 116 + existingOps, err := db.GetLabelOps(l.db, orm.FilterEq("subject", subjectUri)) 118 117 if err != nil { 119 118 fail("Invalid form data.", err) 120 119 return
+3 -2
appview/middleware/middleware.go
··· 18 18 "tangled.org/core/appview/pagination" 19 19 "tangled.org/core/appview/reporesolver" 20 20 "tangled.org/core/idresolver" 21 + "tangled.org/core/orm" 21 22 "tangled.org/core/rbac" 22 23 ) 23 24 ··· 218 217 219 218 repo, err := db.GetRepo( 220 219 mw.db, 221 - db.FilterEq("did", id.DID.String()), 222 - db.FilterEq("name", repoName), 220 + orm.FilterEq("did", id.DID.String()), 221 + orm.FilterEq("name", repoName), 223 222 ) 224 223 if err != nil { 225 224 log.Println("failed to resolve repo", "err", err)
+5 -4
appview/notifications/notifications.go
··· 11 11 "tangled.org/core/appview/oauth" 12 12 "tangled.org/core/appview/pages" 13 13 "tangled.org/core/appview/pagination" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 17 type Notifications struct { ··· 54 53 55 54 total, err := db.CountNotifications( 56 55 n.db, 57 - db.FilterEq("recipient_did", user.Did), 56 + orm.FilterEq("recipient_did", user.Did), 58 57 ) 59 58 if err != nil { 60 59 l.Error("failed to get total notifications", "err", err) ··· 65 64 notifications, err := db.GetNotificationsWithEntities( 66 65 n.db, 67 66 page, 68 - db.FilterEq("recipient_did", user.Did), 67 + orm.FilterEq("recipient_did", user.Did), 69 68 ) 70 69 if err != nil { 71 70 l.Error("failed to get notifications", "err", err) ··· 97 96 98 97 count, err := db.CountNotifications( 99 98 n.db, 100 - db.FilterEq("recipient_did", user.Did), 101 - db.FilterEq("read", 0), 99 + orm.FilterEq("recipient_did", user.Did), 100 + orm.FilterEq("read", 0), 102 101 ) 103 102 if err != nil { 104 103 http.Error(w, "Failed to get unread count", http.StatusInternalServerError)
+11 -10
appview/notify/db/db.go
··· 12 12 "tangled.org/core/appview/models" 13 13 "tangled.org/core/appview/notify" 14 14 "tangled.org/core/idresolver" 15 + "tangled.org/core/orm" 15 16 ) 16 17 17 18 const ( ··· 43 42 return 44 43 } 45 44 var err error 46 - repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(star.RepoAt))) 45 + repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(star.RepoAt))) 47 46 if err != nil { 48 47 log.Printf("NewStar: failed to get repos: %v", err) 49 48 return ··· 81 80 // - collaborators in the repo 82 81 var recipients []syntax.DID 83 82 recipients = append(recipients, syntax.DID(issue.Repo.Did)) 84 - collaborators, err := db.GetCollaborators(n.db, db.FilterEq("repo_at", issue.Repo.RepoAt())) 83 + collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt())) 85 84 if err != nil { 86 85 log.Printf("failed to fetch collaborators: %v", err) 87 86 return ··· 120 119 } 121 120 122 121 func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment, mentions []syntax.DID) { 123 - issues, err := db.GetIssues(n.db, db.FilterEq("at_uri", comment.IssueAt)) 122 + issues, err := db.GetIssues(n.db, orm.FilterEq("at_uri", comment.IssueAt)) 124 123 if err != nil { 125 124 log.Printf("NewIssueComment: failed to get issues: %v", err) 126 125 return ··· 208 207 } 209 208 210 209 func (n *databaseNotifier) NewPull(ctx context.Context, pull *models.Pull) { 211 - repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(pull.RepoAt))) 210 + repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(pull.RepoAt))) 212 211 if err != nil { 213 212 log.Printf("NewPull: failed to get repos: %v", err) 214 213 return ··· 219 218 // - collaborators in the repo 220 219 var recipients []syntax.DID 221 220 recipients = append(recipients, syntax.DID(repo.Did)) 222 - collaborators, err := db.GetCollaborators(n.db, db.FilterEq("repo_at", repo.RepoAt())) 221 + collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt())) 223 222 if err != nil { 224 223 log.Printf("failed to fetch collaborators: %v", err) 225 224 return ··· 259 258 return 260 259 } 261 260 262 - repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", comment.RepoAt)) 261 + repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", comment.RepoAt)) 263 262 if err != nil { 264 263 log.Printf("NewPullComment: failed to get repos: %v", err) 265 264 return ··· 328 327 // - all issue participants 329 328 var recipients []syntax.DID 330 329 recipients = append(recipients, syntax.DID(issue.Repo.Did)) 331 - collaborators, err := db.GetCollaborators(n.db, db.FilterEq("repo_at", issue.Repo.RepoAt())) 330 + collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt())) 332 331 if err != nil { 333 332 log.Printf("failed to fetch collaborators: %v", err) 334 333 return ··· 367 366 368 367 func (n *databaseNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) { 369 368 // Get repo details 370 - repo, err := db.GetRepo(n.db, db.FilterEq("at_uri", string(pull.RepoAt))) 369 + repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(pull.RepoAt))) 371 370 if err != nil { 372 371 log.Printf("NewPullState: failed to get repos: %v", err) 373 372 return ··· 378 377 // - all pull participants 379 378 var recipients []syntax.DID 380 379 recipients = append(recipients, syntax.DID(repo.Did)) 381 - collaborators, err := db.GetCollaborators(n.db, db.FilterEq("repo_at", repo.RepoAt())) 380 + collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt())) 382 381 if err != nil { 383 382 log.Printf("failed to fetch collaborators: %v", err) 384 383 return ··· 444 443 445 444 prefMap, err := db.GetNotificationPreferences( 446 445 n.db, 447 - db.FilterIn("user_did", slices.Collect(maps.Keys(recipientSet))), 446 + orm.FilterIn("user_did", slices.Collect(maps.Keys(recipientSet))), 448 447 ) 449 448 if err != nil { 450 449 // failed to get prefs for users
+3 -2
appview/oauth/handler.go
··· 16 16 "tangled.org/core/api/tangled" 17 17 "tangled.org/core/appview/db" 18 18 "tangled.org/core/consts" 19 + "tangled.org/core/orm" 19 20 "tangled.org/core/tid" 20 21 ) 21 22 ··· 98 97 // and create an sh.tangled.spindle.member record with that 99 98 spindleMembers, err := db.GetSpindleMembers( 100 99 o.Db, 101 - db.FilterEq("instance", "spindle.tangled.sh"), 102 - db.FilterEq("subject", did), 100 + orm.FilterEq("instance", "spindle.tangled.sh"), 101 + orm.FilterEq("subject", did), 103 102 ) 104 103 if err != nil { 105 104 l.Error("failed to get spindle members", "err", err)
+12 -11
appview/pipelines/pipelines.go
··· 16 16 "tangled.org/core/appview/reporesolver" 17 17 "tangled.org/core/eventconsumer" 18 18 "tangled.org/core/idresolver" 19 + "tangled.org/core/orm" 19 20 "tangled.org/core/rbac" 20 21 spindlemodel "tangled.org/core/spindle/models" 21 22 ··· 82 81 ps, err := db.GetPipelineStatuses( 83 82 p.db, 84 83 30, 85 - db.FilterEq("repo_owner", f.Did), 86 - db.FilterEq("repo_name", f.Name), 87 - db.FilterEq("knot", f.Knot), 84 + orm.FilterEq("repo_owner", f.Did), 85 + orm.FilterEq("repo_name", f.Name), 86 + orm.FilterEq("knot", f.Knot), 88 87 ) 89 88 if err != nil { 90 89 l.Error("failed to query db", "err", err) ··· 123 122 ps, err := db.GetPipelineStatuses( 124 123 p.db, 125 124 1, 126 - db.FilterEq("repo_owner", f.Did), 127 - db.FilterEq("repo_name", f.Name), 128 - db.FilterEq("knot", f.Knot), 129 - db.FilterEq("id", pipelineId), 125 + orm.FilterEq("repo_owner", f.Did), 126 + orm.FilterEq("repo_name", f.Name), 127 + orm.FilterEq("knot", f.Knot), 128 + orm.FilterEq("id", pipelineId), 130 129 ) 131 130 if err != nil { 132 131 l.Error("failed to query db", "err", err) ··· 190 189 ps, err := db.GetPipelineStatuses( 191 190 p.db, 192 191 1, 193 - db.FilterEq("repo_owner", f.Did), 194 - db.FilterEq("repo_name", f.Name), 195 - db.FilterEq("knot", f.Knot), 196 - db.FilterEq("id", pipelineId), 192 + orm.FilterEq("repo_owner", f.Did), 193 + orm.FilterEq("repo_name", f.Name), 194 + orm.FilterEq("knot", f.Knot), 195 + orm.FilterEq("id", pipelineId), 197 196 ) 198 197 if err != nil || len(ps) != 1 { 199 198 l.Error("pipeline query failed", "err", err, "count", len(ps))
+2 -1
appview/pulls/opengraph.go
··· 13 13 "tangled.org/core/appview/db" 14 14 "tangled.org/core/appview/models" 15 15 "tangled.org/core/appview/ogcard" 16 + "tangled.org/core/orm" 16 17 "tangled.org/core/patchutil" 17 18 "tangled.org/core/types" 18 19 ) ··· 277 276 } 278 277 279 278 // Get comment count from database 280 - comments, err := db.GetPullComments(s.db, db.FilterEq("pull_id", pull.ID)) 279 + comments, err := db.GetPullComments(s.db, orm.FilterEq("pull_id", pull.ID)) 281 280 if err != nil { 282 281 log.Printf("failed to get pull comments: %v", err) 283 282 }
+19 -18
appview/pulls/pulls.go
··· 30 30 "tangled.org/core/appview/validator" 31 31 "tangled.org/core/appview/xrpcclient" 32 32 "tangled.org/core/idresolver" 33 + "tangled.org/core/orm" 33 34 "tangled.org/core/patchutil" 34 35 "tangled.org/core/rbac" 35 36 "tangled.org/core/tid" ··· 191 190 ps, err := db.GetPipelineStatuses( 192 191 s.db, 193 192 len(shas), 194 - db.FilterEq("repo_owner", f.Did), 195 - db.FilterEq("repo_name", f.Name), 196 - db.FilterEq("knot", f.Knot), 197 - db.FilterIn("sha", shas), 193 + orm.FilterEq("repo_owner", f.Did), 194 + orm.FilterEq("repo_name", f.Name), 195 + orm.FilterEq("knot", f.Knot), 196 + orm.FilterIn("sha", shas), 198 197 ) 199 198 if err != nil { 200 199 log.Printf("failed to fetch pipeline statuses: %s", err) ··· 218 217 219 218 labelDefs, err := db.GetLabelDefinitions( 220 219 s.db, 221 - db.FilterIn("at_uri", f.Labels), 222 - db.FilterContains("scope", tangled.RepoPullNSID), 220 + orm.FilterIn("at_uri", f.Labels), 221 + orm.FilterContains("scope", tangled.RepoPullNSID), 223 222 ) 224 223 if err != nil { 225 224 log.Println("failed to fetch labels", err) ··· 598 597 599 598 pulls, err := db.GetPulls( 600 599 s.db, 601 - db.FilterIn("id", ids), 600 + orm.FilterIn("id", ids), 602 601 ) 603 602 if err != nil { 604 603 log.Println("failed to get pulls", err) ··· 649 648 ps, err := db.GetPipelineStatuses( 650 649 s.db, 651 650 len(shas), 652 - db.FilterEq("repo_owner", f.Did), 653 - db.FilterEq("repo_name", f.Name), 654 - db.FilterEq("knot", f.Knot), 655 - db.FilterIn("sha", shas), 651 + orm.FilterEq("repo_owner", f.Did), 652 + orm.FilterEq("repo_name", f.Name), 653 + orm.FilterEq("knot", f.Knot), 654 + orm.FilterIn("sha", shas), 656 655 ) 657 656 if err != nil { 658 657 log.Printf("failed to fetch pipeline statuses: %s", err) ··· 665 664 666 665 labelDefs, err := db.GetLabelDefinitions( 667 666 s.db, 668 - db.FilterIn("at_uri", f.Labels), 669 - db.FilterContains("scope", tangled.RepoPullNSID), 667 + orm.FilterIn("at_uri", f.Labels), 668 + orm.FilterContains("scope", tangled.RepoPullNSID), 670 669 ) 671 670 if err != nil { 672 671 log.Println("failed to fetch labels", err) ··· 1499 1498 // fork repo 1500 1499 repo, err := db.GetRepo( 1501 1500 s.db, 1502 - db.FilterEq("did", forkOwnerDid), 1503 - db.FilterEq("name", forkName), 1501 + orm.FilterEq("did", forkOwnerDid), 1502 + orm.FilterEq("name", forkName), 1504 1503 ) 1505 1504 if err != nil { 1506 1505 log.Println("failed to get repo", "did", forkOwnerDid, "name", forkName, "err", err) ··· 2067 2066 tx, 2068 2067 p.ParentChangeId, 2069 2068 // these should be enough filters to be unique per-stack 2070 - db.FilterEq("repo_at", p.RepoAt.String()), 2071 - db.FilterEq("owner_did", p.OwnerDid), 2072 - db.FilterEq("change_id", p.ChangeId), 2069 + orm.FilterEq("repo_at", p.RepoAt.String()), 2070 + orm.FilterEq("owner_did", p.OwnerDid), 2071 + orm.FilterEq("change_id", p.ChangeId), 2073 2072 ) 2074 2073 2075 2074 if err != nil {
+10 -9
appview/repo/artifact.go
··· 15 15 "tangled.org/core/appview/models" 16 16 "tangled.org/core/appview/pages" 17 17 "tangled.org/core/appview/xrpcclient" 18 + "tangled.org/core/orm" 18 19 "tangled.org/core/tid" 19 20 "tangled.org/core/types" 20 21 ··· 156 155 157 156 artifacts, err := db.GetArtifact( 158 157 rp.db, 159 - db.FilterEq("repo_at", f.RepoAt()), 160 - db.FilterEq("tag", tag.Tag.Hash[:]), 161 - db.FilterEq("name", filename), 158 + orm.FilterEq("repo_at", f.RepoAt()), 159 + orm.FilterEq("tag", tag.Tag.Hash[:]), 160 + orm.FilterEq("name", filename), 162 161 ) 163 162 if err != nil { 164 163 log.Println("failed to get artifacts", err) ··· 235 234 236 235 artifacts, err := db.GetArtifact( 237 236 rp.db, 238 - db.FilterEq("repo_at", f.RepoAt()), 239 - db.FilterEq("tag", tag[:]), 240 - db.FilterEq("name", filename), 237 + orm.FilterEq("repo_at", f.RepoAt()), 238 + orm.FilterEq("tag", tag[:]), 239 + orm.FilterEq("name", filename), 241 240 ) 242 241 if err != nil { 243 242 log.Println("failed to get artifacts", err) ··· 277 276 defer tx.Rollback() 278 277 279 278 err = db.DeleteArtifact(tx, 280 - db.FilterEq("repo_at", f.RepoAt()), 281 - db.FilterEq("tag", artifact.Tag[:]), 282 - db.FilterEq("name", filename), 279 + orm.FilterEq("repo_at", f.RepoAt()), 280 + orm.FilterEq("tag", artifact.Tag[:]), 281 + orm.FilterEq("name", filename), 283 282 ) 284 283 if err != nil { 285 284 log.Println("failed to remove artifact record from db", err)
+3 -2
appview/repo/feed.go
··· 11 11 "tangled.org/core/appview/db" 12 12 "tangled.org/core/appview/models" 13 13 "tangled.org/core/appview/pagination" 14 + "tangled.org/core/orm" 14 15 15 16 "github.com/bluesky-social/indigo/atproto/identity" 16 17 "github.com/bluesky-social/indigo/atproto/syntax" ··· 21 20 func (rp *Repo) getRepoFeed(ctx context.Context, repo *models.Repo, ownerSlashRepo string) (*feeds.Feed, error) { 22 21 const feedLimitPerType = 100 23 22 24 - pulls, err := db.GetPullsWithLimit(rp.db, feedLimitPerType, db.FilterEq("repo_at", repo.RepoAt())) 23 + pulls, err := db.GetPullsWithLimit(rp.db, feedLimitPerType, orm.FilterEq("repo_at", repo.RepoAt())) 25 24 if err != nil { 26 25 return nil, err 27 26 } ··· 29 28 issues, err := db.GetIssuesPaginated( 30 29 rp.db, 31 30 pagination.Page{Limit: feedLimitPerType}, 32 - db.FilterEq("repo_at", repo.RepoAt()), 31 + orm.FilterEq("repo_at", repo.RepoAt()), 33 32 ) 34 33 if err != nil { 35 34 return nil, err
+3 -2
appview/repo/index.go
··· 23 23 "tangled.org/core/appview/models" 24 24 "tangled.org/core/appview/pages" 25 25 "tangled.org/core/appview/xrpcclient" 26 + "tangled.org/core/orm" 26 27 "tangled.org/core/types" 27 28 28 29 "github.com/go-chi/chi/v5" ··· 172 171 // first attempt to fetch from db 173 172 langs, err := db.GetRepoLanguages( 174 173 rp.db, 175 - db.FilterEq("repo_at", repo.RepoAt()), 176 - db.FilterEq("ref", currentRef), 174 + orm.FilterEq("repo_at", repo.RepoAt()), 175 + orm.FilterEq("ref", currentRef), 177 176 ) 178 177 179 178 if err != nil || langs == nil {
+3 -2
appview/repo/opengraph.go
··· 16 16 "tangled.org/core/appview/db" 17 17 "tangled.org/core/appview/models" 18 18 "tangled.org/core/appview/ogcard" 19 + "tangled.org/core/orm" 19 20 "tangled.org/core/types" 20 21 ) 21 22 ··· 339 338 var languageStats []types.RepoLanguageDetails 340 339 langs, err := db.GetRepoLanguages( 341 340 rp.db, 342 - db.FilterEq("repo_at", f.RepoAt()), 343 - db.FilterEq("is_default_ref", 1), 341 + orm.FilterEq("repo_at", f.RepoAt()), 342 + orm.FilterEq("is_default_ref", 1), 344 343 ) 345 344 if err != nil { 346 345 log.Printf("failed to get language stats from db: %v", err)
+17 -16
appview/repo/repo.go
··· 24 24 xrpcclient "tangled.org/core/appview/xrpcclient" 25 25 "tangled.org/core/eventconsumer" 26 26 "tangled.org/core/idresolver" 27 + "tangled.org/core/orm" 27 28 "tangled.org/core/rbac" 28 29 "tangled.org/core/tid" 29 30 "tangled.org/core/xrpc/serviceauth" ··· 346 345 // get form values 347 346 labelId := r.FormValue("label-id") 348 347 349 - label, err := db.GetLabelDefinition(rp.db, db.FilterEq("id", labelId)) 348 + label, err := db.GetLabelDefinition(rp.db, orm.FilterEq("id", labelId)) 350 349 if err != nil { 351 350 fail("Failed to find label definition.", err) 352 351 return ··· 410 409 411 410 err = db.UnsubscribeLabel( 412 411 tx, 413 - db.FilterEq("repo_at", f.RepoAt()), 414 - db.FilterEq("label_at", removedAt), 412 + orm.FilterEq("repo_at", f.RepoAt()), 413 + orm.FilterEq("label_at", removedAt), 415 414 ) 416 415 if err != nil { 417 416 fail("Failed to unsubscribe label.", err) 418 417 return 419 418 } 420 419 421 - err = db.DeleteLabelDefinition(tx, db.FilterEq("id", label.Id)) 420 + err = db.DeleteLabelDefinition(tx, orm.FilterEq("id", label.Id)) 422 421 if err != nil { 423 422 fail("Failed to delete label definition.", err) 424 423 return ··· 457 456 } 458 457 459 458 labelAts := r.Form["label"] 460 - _, err = db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", labelAts)) 459 + _, err = db.GetLabelDefinitions(rp.db, orm.FilterIn("at_uri", labelAts)) 461 460 if err != nil { 462 461 fail("Failed to subscribe to label.", err) 463 462 return ··· 543 542 } 544 543 545 544 labelAts := r.Form["label"] 546 - _, err = db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", labelAts)) 545 + _, err = db.GetLabelDefinitions(rp.db, orm.FilterIn("at_uri", labelAts)) 547 546 if err != nil { 548 547 fail("Failed to unsubscribe to label.", err) 549 548 return ··· 583 582 584 583 err = db.UnsubscribeLabel( 585 584 rp.db, 586 - db.FilterEq("repo_at", f.RepoAt()), 587 - db.FilterIn("label_at", labelAts), 585 + orm.FilterEq("repo_at", f.RepoAt()), 586 + orm.FilterIn("label_at", labelAts), 588 587 ) 589 588 if err != nil { 590 589 fail("Failed to unsubscribe label.", err) ··· 613 612 614 613 labelDefs, err := db.GetLabelDefinitions( 615 614 rp.db, 616 - db.FilterIn("at_uri", f.Labels), 617 - db.FilterContains("scope", subject.Collection().String()), 615 + orm.FilterIn("at_uri", f.Labels), 616 + orm.FilterContains("scope", subject.Collection().String()), 618 617 ) 619 618 if err != nil { 620 619 l.Error("failed to fetch label defs", "err", err) ··· 626 625 defs[l.AtUri().String()] = &l 627 626 } 628 627 629 - states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject)) 628 + states, err := db.GetLabels(rp.db, orm.FilterEq("subject", subject)) 630 629 if err != nil { 631 630 l.Error("failed to build label state", "err", err) 632 631 return ··· 661 660 662 661 labelDefs, err := db.GetLabelDefinitions( 663 662 rp.db, 664 - db.FilterIn("at_uri", f.Labels), 665 - db.FilterContains("scope", subject.Collection().String()), 663 + orm.FilterIn("at_uri", f.Labels), 664 + orm.FilterContains("scope", subject.Collection().String()), 666 665 ) 667 666 if err != nil { 668 667 l.Error("failed to fetch labels", "err", err) ··· 674 673 defs[l.AtUri().String()] = &l 675 674 } 676 675 677 - states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject)) 676 + states, err := db.GetLabels(rp.db, orm.FilterEq("subject", subject)) 678 677 if err != nil { 679 678 l.Error("failed to build label state", "err", err) 680 679 return ··· 1037 1036 // in the user's account. 1038 1037 existingRepo, err := db.GetRepo( 1039 1038 rp.db, 1040 - db.FilterEq("did", user.Did), 1041 - db.FilterEq("name", forkName), 1039 + orm.FilterEq("did", user.Did), 1040 + orm.FilterEq("name", forkName), 1042 1041 ) 1043 1042 if err != nil { 1044 1043 if !errors.Is(err, sql.ErrNoRows) {
+5 -4
appview/repo/repo_util.go
··· 8 8 9 9 "tangled.org/core/appview/db" 10 10 "tangled.org/core/appview/models" 11 + "tangled.org/core/orm" 11 12 "tangled.org/core/types" 12 13 ) 13 14 ··· 103 102 ps, err := db.GetPipelineStatuses( 104 103 d, 105 104 len(shas), 106 - db.FilterEq("repo_owner", repo.Did), 107 - db.FilterEq("repo_name", repo.Name), 108 - db.FilterEq("knot", repo.Knot), 109 - db.FilterIn("sha", shas), 105 + orm.FilterEq("repo_owner", repo.Did), 106 + orm.FilterEq("repo_name", repo.Name), 107 + orm.FilterEq("knot", repo.Knot), 108 + orm.FilterIn("sha", shas), 110 109 ) 111 110 if err != nil { 112 111 return nil, err
+3 -2
appview/repo/settings.go
··· 14 14 "tangled.org/core/appview/oauth" 15 15 "tangled.org/core/appview/pages" 16 16 xrpcclient "tangled.org/core/appview/xrpcclient" 17 + "tangled.org/core/orm" 17 18 "tangled.org/core/types" 18 19 19 20 comatproto "github.com/bluesky-social/indigo/api/atproto" ··· 211 210 return 212 211 } 213 212 214 - defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", rp.config.Label.DefaultLabelDefs)) 213 + defaultLabels, err := db.GetLabelDefinitions(rp.db, orm.FilterIn("at_uri", rp.config.Label.DefaultLabelDefs)) 215 214 if err != nil { 216 215 l.Error("failed to fetch labels", "err", err) 217 216 rp.pages.Error503(w) 218 217 return 219 218 } 220 219 221 - labels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", f.Labels)) 220 + labels, err := db.GetLabelDefinitions(rp.db, orm.FilterIn("at_uri", f.Labels)) 222 221 if err != nil { 223 222 l.Error("failed to fetch labels", "err", err) 224 223 rp.pages.Error503(w)
+2 -1
appview/repo/tags.go
··· 10 10 "tangled.org/core/appview/models" 11 11 "tangled.org/core/appview/pages" 12 12 xrpcclient "tangled.org/core/appview/xrpcclient" 13 + "tangled.org/core/orm" 13 14 "tangled.org/core/types" 14 15 15 16 indigoxrpc "github.com/bluesky-social/indigo/xrpc" ··· 45 44 rp.pages.Error503(w) 46 45 return 47 46 } 48 - artifacts, err := db.GetArtifact(rp.db, db.FilterEq("repo_at", f.RepoAt())) 47 + artifacts, err := db.GetArtifact(rp.db, orm.FilterEq("repo_at", f.RepoAt())) 49 48 if err != nil { 50 49 l.Error("failed grab artifacts", "err", err) 51 50 return
+5 -4
appview/serververify/verify.go
··· 9 9 "tangled.org/core/api/tangled" 10 10 "tangled.org/core/appview/db" 11 11 "tangled.org/core/appview/xrpcclient" 12 + "tangled.org/core/orm" 12 13 "tangled.org/core/rbac" 13 14 ) 14 15 ··· 77 76 // mark this spindle as verified in the db 78 77 rowId, err := db.VerifySpindle( 79 78 tx, 80 - db.FilterEq("owner", owner), 81 - db.FilterEq("instance", instance), 79 + orm.FilterEq("owner", owner), 80 + orm.FilterEq("instance", instance), 82 81 ) 83 82 if err != nil { 84 83 return 0, fmt.Errorf("failed to write to DB: %w", err) ··· 116 115 // mark as registered 117 116 err = db.MarkRegistered( 118 117 tx, 119 - db.FilterEq("did", owner), 120 - db.FilterEq("domain", domain), 118 + orm.FilterEq("did", owner), 119 + orm.FilterEq("domain", domain), 121 120 ) 122 121 if err != nil { 123 122 return fmt.Errorf("failed to register domain: %w", err)
+25 -24
appview/spindles/spindles.go
··· 20 20 "tangled.org/core/appview/serververify" 21 21 "tangled.org/core/appview/xrpcclient" 22 22 "tangled.org/core/idresolver" 23 + "tangled.org/core/orm" 23 24 "tangled.org/core/rbac" 24 25 "tangled.org/core/tid" 25 26 ··· 72 71 user := s.OAuth.GetUser(r) 73 72 all, err := db.GetSpindles( 74 73 s.Db, 75 - db.FilterEq("owner", user.Did), 74 + orm.FilterEq("owner", user.Did), 76 75 ) 77 76 if err != nil { 78 77 s.Logger.Error("failed to fetch spindles", "err", err) ··· 102 101 103 102 spindles, err := db.GetSpindles( 104 103 s.Db, 105 - db.FilterEq("instance", instance), 106 - db.FilterEq("owner", user.Did), 107 - db.FilterIsNot("verified", "null"), 104 + orm.FilterEq("instance", instance), 105 + orm.FilterEq("owner", user.Did), 106 + orm.FilterIsNot("verified", "null"), 108 107 ) 109 108 if err != nil || len(spindles) != 1 { 110 109 l.Error("failed to get spindle", "err", err, "len(spindles)", len(spindles)) ··· 124 123 repos, err := db.GetRepos( 125 124 s.Db, 126 125 0, 127 - db.FilterEq("spindle", instance), 126 + orm.FilterEq("spindle", instance), 128 127 ) 129 128 if err != nil { 130 129 l.Error("failed to get spindle repos", "err", err) ··· 291 290 292 291 spindles, err := db.GetSpindles( 293 292 s.Db, 294 - db.FilterEq("owner", user.Did), 295 - db.FilterEq("instance", instance), 293 + orm.FilterEq("owner", user.Did), 294 + orm.FilterEq("instance", instance), 296 295 ) 297 296 if err != nil || len(spindles) != 1 { 298 297 l.Error("failed to retrieve instance", "err", err, "len(spindles)", len(spindles)) ··· 320 319 // remove spindle members first 321 320 err = db.RemoveSpindleMember( 322 321 tx, 323 - db.FilterEq("did", user.Did), 324 - db.FilterEq("instance", instance), 322 + orm.FilterEq("did", user.Did), 323 + orm.FilterEq("instance", instance), 325 324 ) 326 325 if err != nil { 327 326 l.Error("failed to remove spindle members", "err", err) ··· 331 330 332 331 err = db.DeleteSpindle( 333 332 tx, 334 - db.FilterEq("owner", user.Did), 335 - db.FilterEq("instance", instance), 333 + orm.FilterEq("owner", user.Did), 334 + orm.FilterEq("instance", instance), 336 335 ) 337 336 if err != nil { 338 337 l.Error("failed to delete spindle", "err", err) ··· 411 410 412 411 spindles, err := db.GetSpindles( 413 412 s.Db, 414 - db.FilterEq("owner", user.Did), 415 - db.FilterEq("instance", instance), 413 + orm.FilterEq("owner", user.Did), 414 + orm.FilterEq("instance", instance), 416 415 ) 417 416 if err != nil || len(spindles) != 1 { 418 417 l.Error("failed to retrieve instance", "err", err, "len(spindles)", len(spindles)) ··· 454 453 455 454 verifiedSpindle, err := db.GetSpindles( 456 455 s.Db, 457 - db.FilterEq("id", rowId), 456 + orm.FilterEq("id", rowId), 458 457 ) 459 458 if err != nil || len(verifiedSpindle) != 1 { 460 459 l.Error("failed get new spindle", "err", err) ··· 487 486 488 487 spindles, err := db.GetSpindles( 489 488 s.Db, 490 - db.FilterEq("owner", user.Did), 491 - db.FilterEq("instance", instance), 489 + orm.FilterEq("owner", user.Did), 490 + orm.FilterEq("instance", instance), 492 491 ) 493 492 if err != nil || len(spindles) != 1 { 494 493 l.Error("failed to retrieve instance", "err", err, "len(spindles)", len(spindles)) ··· 623 622 624 623 spindles, err := db.GetSpindles( 625 624 s.Db, 626 - db.FilterEq("owner", user.Did), 627 - db.FilterEq("instance", instance), 625 + orm.FilterEq("owner", user.Did), 626 + orm.FilterEq("instance", instance), 628 627 ) 629 628 if err != nil || len(spindles) != 1 { 630 629 l.Error("failed to retrieve instance", "err", err, "len(spindles)", len(spindles)) ··· 673 672 // get the record from the DB first: 674 673 members, err := db.GetSpindleMembers( 675 674 s.Db, 676 - db.FilterEq("did", user.Did), 677 - db.FilterEq("instance", instance), 678 - db.FilterEq("subject", memberId.DID), 675 + orm.FilterEq("did", user.Did), 676 + orm.FilterEq("instance", instance), 677 + orm.FilterEq("subject", memberId.DID), 679 678 ) 680 679 if err != nil || len(members) != 1 { 681 680 l.Error("failed to get member", "err", err) ··· 686 685 // remove from db 687 686 if err = db.RemoveSpindleMember( 688 687 tx, 689 - db.FilterEq("did", user.Did), 690 - db.FilterEq("instance", instance), 691 - db.FilterEq("subject", memberId.DID), 688 + orm.FilterEq("did", user.Did), 689 + orm.FilterEq("instance", instance), 690 + orm.FilterEq("subject", memberId.DID), 692 691 ); err != nil { 693 692 l.Error("failed to remove spindle member", "err", err) 694 693 fail()
+6 -5
appview/state/gfi.go
··· 11 11 "tangled.org/core/appview/pages" 12 12 "tangled.org/core/appview/pagination" 13 13 "tangled.org/core/consts" 14 + "tangled.org/core/orm" 14 15 ) 15 16 16 17 func (s *State) GoodFirstIssues(w http.ResponseWriter, r *http.Request) { ··· 21 20 22 21 goodFirstIssueLabel := s.config.Label.GoodFirstIssue 23 22 24 - gfiLabelDef, err := db.GetLabelDefinition(s.db, db.FilterEq("at_uri", goodFirstIssueLabel)) 23 + gfiLabelDef, err := db.GetLabelDefinition(s.db, orm.FilterEq("at_uri", goodFirstIssueLabel)) 25 24 if err != nil { 26 25 log.Println("failed to get gfi label def", err) 27 26 s.pages.Error500(w) 28 27 return 29 28 } 30 29 31 - repoLabels, err := db.GetRepoLabels(s.db, db.FilterEq("label_at", goodFirstIssueLabel)) 30 + repoLabels, err := db.GetRepoLabels(s.db, orm.FilterEq("label_at", goodFirstIssueLabel)) 32 31 if err != nil { 33 32 log.Println("failed to get repo labels", err) 34 33 s.pages.Error503(w) ··· 56 55 pagination.Page{ 57 56 Limit: 500, 58 57 }, 59 - db.FilterIn("repo_at", repoUris), 60 - db.FilterEq("open", 1), 58 + orm.FilterIn("repo_at", repoUris), 59 + orm.FilterEq("open", 1), 61 60 ) 62 61 if err != nil { 63 62 log.Println("failed to get issues", err) ··· 133 132 } 134 133 135 134 if len(uriList) > 0 { 136 - allLabelDefs, err = db.GetLabelDefinitions(s.db, db.FilterIn("at_uri", uriList)) 135 + allLabelDefs, err = db.GetLabelDefinitions(s.db, orm.FilterIn("at_uri", uriList)) 137 136 if err != nil { 138 137 log.Println("failed to fetch labels", err) 139 138 }
+6 -5
appview/state/knotstream.go
··· 16 16 ec "tangled.org/core/eventconsumer" 17 17 "tangled.org/core/eventconsumer/cursor" 18 18 "tangled.org/core/log" 19 + "tangled.org/core/orm" 19 20 "tangled.org/core/rbac" 20 21 "tangled.org/core/workflow" 21 22 ··· 31 30 32 31 knots, err := db.GetRegistrations( 33 32 d, 34 - db.FilterIsNot("registered", "null"), 33 + orm.FilterIsNot("registered", "null"), 35 34 ) 36 35 if err != nil { 37 36 return nil, err ··· 144 143 repos, err := db.GetRepos( 145 144 d, 146 145 0, 147 - db.FilterEq("did", record.RepoDid), 148 - db.FilterEq("name", record.RepoName), 146 + orm.FilterEq("did", record.RepoDid), 147 + orm.FilterEq("name", record.RepoName), 149 148 ) 150 149 if err != nil { 151 150 return fmt.Errorf("failed to look for repo in DB (%s/%s): %w", record.RepoDid, record.RepoName, err) ··· 210 209 repos, err := db.GetRepos( 211 210 d, 212 211 0, 213 - db.FilterEq("did", record.TriggerMetadata.Repo.Did), 214 - db.FilterEq("name", record.TriggerMetadata.Repo.Repo), 212 + orm.FilterEq("did", record.TriggerMetadata.Repo.Did), 213 + orm.FilterEq("name", record.TriggerMetadata.Repo.Repo), 215 214 ) 216 215 if err != nil { 217 216 return fmt.Errorf("failed to look for repo in DB: nsid %s, rkey %s, %w", msg.Nsid, msg.Rkey, err)
+13 -12
appview/state/profile.go
··· 19 19 "tangled.org/core/appview/db" 20 20 "tangled.org/core/appview/models" 21 21 "tangled.org/core/appview/pages" 22 + "tangled.org/core/orm" 22 23 ) 23 24 24 25 func (s *State) Profile(w http.ResponseWriter, r *http.Request) { ··· 57 56 return nil, fmt.Errorf("failed to get profile: %w", err) 58 57 } 59 58 60 - repoCount, err := db.CountRepos(s.db, db.FilterEq("did", did)) 59 + repoCount, err := db.CountRepos(s.db, orm.FilterEq("did", did)) 61 60 if err != nil { 62 61 return nil, fmt.Errorf("failed to get repo count: %w", err) 63 62 } 64 63 65 - stringCount, err := db.CountStrings(s.db, db.FilterEq("did", did)) 64 + stringCount, err := db.CountStrings(s.db, orm.FilterEq("did", did)) 66 65 if err != nil { 67 66 return nil, fmt.Errorf("failed to get string count: %w", err) 68 67 } 69 68 70 - starredCount, err := db.CountStars(s.db, db.FilterEq("did", did)) 69 + starredCount, err := db.CountStars(s.db, orm.FilterEq("did", did)) 71 70 if err != nil { 72 71 return nil, fmt.Errorf("failed to get starred repo count: %w", err) 73 72 } ··· 87 86 startOfYear := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC) 88 87 punchcard, err := db.MakePunchcard( 89 88 s.db, 90 - db.FilterEq("did", did), 91 - db.FilterGte("date", startOfYear.Format(time.DateOnly)), 92 - db.FilterLte("date", now.Format(time.DateOnly)), 89 + orm.FilterEq("did", did), 90 + orm.FilterGte("date", startOfYear.Format(time.DateOnly)), 91 + orm.FilterLte("date", now.Format(time.DateOnly)), 93 92 ) 94 93 if err != nil { 95 94 return nil, fmt.Errorf("failed to get punchcard for %s: %w", did, err) ··· 124 123 repos, err := db.GetRepos( 125 124 s.db, 126 125 0, 127 - db.FilterEq("did", profile.UserDid), 126 + orm.FilterEq("did", profile.UserDid), 128 127 ) 129 128 if err != nil { 130 129 l.Error("failed to fetch repos", "err", err) ··· 194 193 repos, err := db.GetRepos( 195 194 s.db, 196 195 0, 197 - db.FilterEq("did", profile.UserDid), 196 + orm.FilterEq("did", profile.UserDid), 198 197 ) 199 198 if err != nil { 200 199 l.Error("failed to get repos", "err", err) ··· 220 219 } 221 220 l = l.With("profileDid", profile.UserDid) 222 221 223 - stars, err := db.GetRepoStars(s.db, 0, db.FilterEq("did", profile.UserDid)) 222 + stars, err := db.GetRepoStars(s.db, 0, orm.FilterEq("did", profile.UserDid)) 224 223 if err != nil { 225 224 l.Error("failed to get stars", "err", err) 226 225 s.pages.Error500(w) ··· 249 248 } 250 249 l = l.With("profileDid", profile.UserDid) 251 250 252 - strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 251 + strings, err := db.GetStrings(s.db, 0, orm.FilterEq("did", profile.UserDid)) 253 252 if err != nil { 254 253 l.Error("failed to get strings", "err", err) 255 254 s.pages.Error500(w) ··· 301 300 followDids = append(followDids, extractDid(follow)) 302 301 } 303 302 304 - profiles, err := db.GetProfiles(s.db, db.FilterIn("did", followDids)) 303 + profiles, err := db.GetProfiles(s.db, orm.FilterIn("did", followDids)) 305 304 if err != nil { 306 305 l.Error("failed to get profiles", "followDids", followDids, "err", err) 307 306 return &params, err ··· 704 703 log.Printf("getting profile data for %s: %s", user.Did, err) 705 704 } 706 705 707 - repos, err := db.GetRepos(s.db, 0, db.FilterEq("did", user.Did)) 706 + repos, err := db.GetRepos(s.db, 0, orm.FilterEq("did", user.Did)) 708 707 if err != nil { 709 708 log.Printf("getting repos for %s: %s", user.Did, err) 710 709 }
+2 -1
appview/state/spindlestream.go
··· 17 17 ec "tangled.org/core/eventconsumer" 18 18 "tangled.org/core/eventconsumer/cursor" 19 19 "tangled.org/core/log" 20 + "tangled.org/core/orm" 20 21 "tangled.org/core/rbac" 21 22 spindle "tangled.org/core/spindle/models" 22 23 ) ··· 28 27 29 28 spindles, err := db.GetSpindles( 30 29 d, 31 - db.FilterIsNot("verified", "null"), 30 + orm.FilterIsNot("verified", "null"), 32 31 ) 33 32 if err != nil { 34 33 return nil, err
+9 -8
appview/state/state.go
··· 30 30 "tangled.org/core/jetstream" 31 31 "tangled.org/core/log" 32 32 tlog "tangled.org/core/log" 33 + "tangled.org/core/orm" 33 34 "tangled.org/core/rbac" 34 35 "tangled.org/core/tid" 35 36 ··· 300 299 return 301 300 } 302 301 303 - gfiLabel, err := db.GetLabelDefinition(s.db, db.FilterEq("at_uri", s.config.Label.GoodFirstIssue)) 302 + gfiLabel, err := db.GetLabelDefinition(s.db, orm.FilterEq("at_uri", s.config.Label.GoodFirstIssue)) 304 303 if err != nil { 305 304 // non-fatal 306 305 } ··· 324 323 325 324 regs, err := db.GetRegistrations( 326 325 s.db, 327 - db.FilterEq("did", user.Did), 328 - db.FilterEq("needs_upgrade", 1), 326 + orm.FilterEq("did", user.Did), 327 + orm.FilterEq("needs_upgrade", 1), 329 328 ) 330 329 if err != nil { 331 330 l.Error("non-fatal: failed to get registrations", "err", err) ··· 333 332 334 333 spindles, err := db.GetSpindles( 335 334 s.db, 336 - db.FilterEq("owner", user.Did), 337 - db.FilterEq("needs_upgrade", 1), 335 + orm.FilterEq("owner", user.Did), 336 + orm.FilterEq("needs_upgrade", 1), 338 337 ) 339 338 if err != nil { 340 339 l.Error("non-fatal: failed to get spindles", "err", err) ··· 505 504 // Check for existing repos 506 505 existingRepo, err := db.GetRepo( 507 506 s.db, 508 - db.FilterEq("did", user.Did), 509 - db.FilterEq("name", repoName), 507 + orm.FilterEq("did", user.Did), 508 + orm.FilterEq("name", repoName), 510 509 ) 511 510 if err == nil && existingRepo != nil { 512 511 l.Info("repo exists") ··· 666 665 } 667 666 668 667 func BackfillDefaultDefs(e db.Execer, r *idresolver.Resolver, defaults []string) error { 669 - defaultLabels, err := db.GetLabelDefinitions(e, db.FilterIn("at_uri", defaults)) 668 + defaultLabels, err := db.GetLabelDefinitions(e, orm.FilterIn("at_uri", defaults)) 670 669 if err != nil { 671 670 return err 672 671 }
+7 -6
appview/strings/strings.go
··· 17 17 "tangled.org/core/appview/pages" 18 18 "tangled.org/core/appview/pages/markup" 19 19 "tangled.org/core/idresolver" 20 + "tangled.org/core/orm" 20 21 "tangled.org/core/tid" 21 22 22 23 "github.com/bluesky-social/indigo/api/atproto" ··· 109 108 strings, err := db.GetStrings( 110 109 s.Db, 111 110 0, 112 - db.FilterEq("did", id.DID), 113 - db.FilterEq("rkey", rkey), 111 + orm.FilterEq("did", id.DID), 112 + orm.FilterEq("rkey", rkey), 114 113 ) 115 114 if err != nil { 116 115 l.Error("failed to fetch string", "err", err) ··· 200 199 all, err := db.GetStrings( 201 200 s.Db, 202 201 0, 203 - db.FilterEq("did", id.DID), 204 - db.FilterEq("rkey", rkey), 202 + orm.FilterEq("did", id.DID), 203 + orm.FilterEq("rkey", rkey), 205 204 ) 206 205 if err != nil { 207 206 l.Error("failed to fetch string", "err", err) ··· 409 408 410 409 if err := db.DeleteString( 411 410 s.Db, 412 - db.FilterEq("did", user.Did), 413 - db.FilterEq("rkey", rkey), 411 + orm.FilterEq("did", user.Did), 412 + orm.FilterEq("rkey", rkey), 414 413 ); err != nil { 415 414 fail("Failed to delete string.", err) 416 415 return
+2 -1
appview/validator/issue.go
··· 6 6 7 7 "tangled.org/core/appview/db" 8 8 "tangled.org/core/appview/models" 9 + "tangled.org/core/orm" 9 10 ) 10 11 11 12 func (v *Validator) ValidateIssueComment(comment *models.IssueComment) error { 12 13 // if comments have parents, only ingest ones that are 1 level deep 13 14 if comment.ReplyTo != nil { 14 - parents, err := db.GetIssueComments(v.db, db.FilterEq("at_uri", *comment.ReplyTo)) 15 + parents, err := db.GetIssueComments(v.db, orm.FilterEq("at_uri", *comment.ReplyTo)) 15 16 if err != nil { 16 17 return fmt.Errorf("failed to fetch parent comment: %w", err) 17 18 }
+122
orm/orm.go
··· 1 + package orm 2 + 3 + import ( 4 + "context" 5 + "database/sql" 6 + "fmt" 7 + "log/slog" 8 + "reflect" 9 + "strings" 10 + ) 11 + 12 + type migrationFn = func(*sql.Tx) error 13 + 14 + func RunMigration(c *sql.Conn, logger *slog.Logger, name string, migrationFn migrationFn) error { 15 + logger = logger.With("migration", name) 16 + 17 + tx, err := c.BeginTx(context.Background(), nil) 18 + if err != nil { 19 + return err 20 + } 21 + defer tx.Rollback() 22 + 23 + var exists bool 24 + err = tx.QueryRow("select exists (select 1 from migrations where name = ?)", name).Scan(&exists) 25 + if err != nil { 26 + return err 27 + } 28 + 29 + if !exists { 30 + // run migration 31 + err = migrationFn(tx) 32 + if err != nil { 33 + logger.Error("failed to run migration", "err", err) 34 + return err 35 + } 36 + 37 + // mark migration as complete 38 + _, err = tx.Exec("insert into migrations (name) values (?)", name) 39 + if err != nil { 40 + logger.Error("failed to mark migration as complete", "err", err) 41 + return err 42 + } 43 + 44 + // commit the transaction 45 + if err := tx.Commit(); err != nil { 46 + return err 47 + } 48 + 49 + logger.Info("migration applied successfully") 50 + } else { 51 + logger.Warn("skipped migration, already applied") 52 + } 53 + 54 + return nil 55 + } 56 + 57 + type Filter struct { 58 + Key string 59 + arg any 60 + Cmp string 61 + } 62 + 63 + func newFilter(key, cmp string, arg any) Filter { 64 + return Filter{ 65 + Key: key, 66 + arg: arg, 67 + Cmp: cmp, 68 + } 69 + } 70 + 71 + func FilterEq(key string, arg any) Filter { return newFilter(key, "=", arg) } 72 + func FilterNotEq(key string, arg any) Filter { return newFilter(key, "<>", arg) } 73 + func FilterGte(key string, arg any) Filter { return newFilter(key, ">=", arg) } 74 + func FilterLte(key string, arg any) Filter { return newFilter(key, "<=", arg) } 75 + func FilterIs(key string, arg any) Filter { return newFilter(key, "is", arg) } 76 + func FilterIsNot(key string, arg any) Filter { return newFilter(key, "is not", arg) } 77 + func FilterIn(key string, arg any) Filter { return newFilter(key, "in", arg) } 78 + func FilterLike(key string, arg any) Filter { return newFilter(key, "like", arg) } 79 + func FilterNotLike(key string, arg any) Filter { return newFilter(key, "not like", arg) } 80 + func FilterContains(key string, arg any) Filter { 81 + return newFilter(key, "like", fmt.Sprintf("%%%v%%", arg)) 82 + } 83 + 84 + func (f Filter) Condition() string { 85 + rv := reflect.ValueOf(f.arg) 86 + kind := rv.Kind() 87 + 88 + // if we have `FilterIn(k, [1, 2, 3])`, compile it down to `k in (?, ?, ?)` 89 + if (kind == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8) || kind == reflect.Array { 90 + if rv.Len() == 0 { 91 + // always false 92 + return "1 = 0" 93 + } 94 + 95 + placeholders := make([]string, rv.Len()) 96 + for i := range placeholders { 97 + placeholders[i] = "?" 98 + } 99 + 100 + return fmt.Sprintf("%s %s (%s)", f.Key, f.Cmp, strings.Join(placeholders, ", ")) 101 + } 102 + 103 + return fmt.Sprintf("%s %s ?", f.Key, f.Cmp) 104 + } 105 + 106 + func (f Filter) Arg() []any { 107 + rv := reflect.ValueOf(f.arg) 108 + kind := rv.Kind() 109 + if (kind == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8) || kind == reflect.Array { 110 + if rv.Len() == 0 { 111 + return nil 112 + } 113 + 114 + out := make([]any, rv.Len()) 115 + for i := range rv.Len() { 116 + out[i] = rv.Index(i).Interface() 117 + } 118 + return out 119 + } 120 + 121 + return []any{f.arg} 122 + }