mirror of
https://github.com/captbaritone/webamp.git
synced 2026-08-02 15:03:53 +00:00
Expand GraphQL schema
This commit is contained in:
parent
2dca4bfb85
commit
77ad5ce70a
4 changed files with 134 additions and 59 deletions
61
packages/skin-database/api/graphql/SkinsConnection.ts
Normal file
61
packages/skin-database/api/graphql/SkinsConnection.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import SkinModel from "../../data/SkinModel";
|
||||
import * as Skins from "../../data/skins";
|
||||
import { knex } from "../../db";
|
||||
import SkinResolver from "./resolvers/SkinResolver";
|
||||
|
||||
export default class SkinsConnection {
|
||||
_first: number;
|
||||
_offset: number;
|
||||
_sort: string;
|
||||
_filter: string;
|
||||
constructor(first: number, offset: number, sort: string, filter: string) {
|
||||
this._first = first;
|
||||
this._offset = offset;
|
||||
this._filter = filter;
|
||||
this._sort = sort;
|
||||
}
|
||||
_getQuery() {
|
||||
let query = knex("skins").where({ skin_type: 1 });
|
||||
|
||||
if (this._filter === "APPROVED") {
|
||||
query = query
|
||||
.leftJoin("skin_reviews", "skin_reviews.skin_md5", "=", "skins.md5")
|
||||
.where("review", "APPROVED");
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
async count() {
|
||||
const count = await this._getQuery().count("*", { as: "count" });
|
||||
return count[0].count;
|
||||
}
|
||||
|
||||
async nodes(args, ctx) {
|
||||
if (this._sort === "MUSEUM") {
|
||||
if (this._filter) {
|
||||
throw new Error(
|
||||
"We don't support combining sorting and filtering at the same time."
|
||||
);
|
||||
}
|
||||
const items = await Skins.getMuseumPage({
|
||||
first: this._first,
|
||||
offset: this._offset,
|
||||
});
|
||||
return Promise.all(
|
||||
items.map(async (item) => {
|
||||
const model = await SkinModel.fromMd5Assert(ctx, item.md5);
|
||||
return new SkinResolver(model);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const skins = await this._getQuery()
|
||||
.select()
|
||||
.limit(this._first)
|
||||
.offset(this._offset);
|
||||
return skins.map((skin) => {
|
||||
return new SkinResolver(new SkinModel(ctx, skin));
|
||||
});
|
||||
}
|
||||
}
|
||||
40
packages/skin-database/api/graphql/TweetsConnection.ts
Normal file
40
packages/skin-database/api/graphql/TweetsConnection.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import TweetModel from "../../data/TweetModel";
|
||||
import { knex } from "../../db";
|
||||
import TweetResolver from "./resolvers/TweetResolver";
|
||||
|
||||
export default class TweetsConnection {
|
||||
_first: number;
|
||||
_offset: number;
|
||||
_sort: string;
|
||||
constructor(first: number, offset: number, sort: string) {
|
||||
this._first = first;
|
||||
this._offset = offset;
|
||||
this._sort = sort;
|
||||
}
|
||||
_getQuery() {
|
||||
let query = knex("tweets");
|
||||
|
||||
if (this._sort === "LIKES") {
|
||||
query = query.orderBy("likes", "desc");
|
||||
} else if (this._sort === "RETWEETS") {
|
||||
query = query.orderBy("retweets", "desc");
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
async count() {
|
||||
const count = await this._getQuery().count("*", { as: "count" });
|
||||
return count[0].count;
|
||||
}
|
||||
|
||||
async nodes(args, ctx) {
|
||||
const tweets = await this._getQuery()
|
||||
.select()
|
||||
.limit(this._first)
|
||||
.offset(this._offset);
|
||||
return tweets.map((tweet) => {
|
||||
return new TweetResolver(new TweetModel(ctx, tweet));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@ import { graphqlHTTP } from "express-graphql";
|
|||
|
||||
import { buildSchema } from "graphql";
|
||||
import SkinModel from "../../data/SkinModel";
|
||||
import { knex } from "../../db";
|
||||
import SkinResolver from "./resolvers/SkinResolver";
|
||||
import * as Skins from "../../data/skins";
|
||||
import UserResolver from "./resolvers/UserResolver";
|
||||
import SkinsConnection from "./SkinsConnection";
|
||||
import TweetsConnection from "./TweetsConnection";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
|
@ -123,9 +123,23 @@ type InternetArchiveItem {
|
|||
skin: Skin
|
||||
}
|
||||
|
||||
"""A collection of tweets made by the @winampskins bot"""
|
||||
type TweetsConnection {
|
||||
"""The total number of tweets"""
|
||||
count: Int
|
||||
|
||||
"""The list of tweets"""
|
||||
nodes: [Tweet]
|
||||
}
|
||||
|
||||
enum TweetsSortOption {
|
||||
LIKES
|
||||
RETWEETS
|
||||
}
|
||||
|
||||
"""A collection of classic Winamp skins"""
|
||||
type SkinsConnection {
|
||||
"""The total number of skins"""
|
||||
"""The total number of skins matching the filter"""
|
||||
count: Int
|
||||
|
||||
"""The list of skins"""
|
||||
|
|
@ -175,63 +189,17 @@ type Query {
|
|||
sort: SkinsSortOption,
|
||||
filter: SkinsFilterOption
|
||||
): SkinsConnection
|
||||
|
||||
"""
|
||||
Tweets tweeted by @winampskins
|
||||
"""
|
||||
tweets(
|
||||
first: Int,
|
||||
offset: Int,
|
||||
sort: TweetsSortOption
|
||||
): TweetsConnection
|
||||
}`);
|
||||
|
||||
class SkinsConnection {
|
||||
_first: number;
|
||||
_offset: number;
|
||||
_sort: string;
|
||||
_filter: string;
|
||||
constructor(first: number, offset: number, sort: string, filter: string) {
|
||||
this._first = first;
|
||||
this._offset = offset;
|
||||
this._filter = filter;
|
||||
this._sort = sort;
|
||||
}
|
||||
async count() {
|
||||
const count = await knex("skins")
|
||||
.where({ skin_type: 1 })
|
||||
.count("*", { as: "count" });
|
||||
return count[0].count;
|
||||
}
|
||||
async nodes(args, ctx) {
|
||||
if (this._sort === "MUSEUM") {
|
||||
if (this._filter) {
|
||||
throw new Error(
|
||||
"We don't support combining sorting and filtering at the same time."
|
||||
);
|
||||
}
|
||||
const items = await Skins.getMuseumPage({
|
||||
first: this._first,
|
||||
offset: this._offset,
|
||||
});
|
||||
return Promise.all(
|
||||
items.map(async (item) => {
|
||||
const model = await SkinModel.fromMd5Assert(ctx, item.md5);
|
||||
return new SkinResolver(model);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let query = knex("skins");
|
||||
|
||||
if (this._filter === "APPROVED") {
|
||||
query = query
|
||||
.leftJoin("skin_reviews", "skin_reviews.skin_md5", "=", "skins.md5")
|
||||
.where("review", "APPROVED");
|
||||
}
|
||||
|
||||
const skins = await query
|
||||
.where({ skin_type: 1 })
|
||||
.select()
|
||||
.limit(this._first)
|
||||
.offset(this._offset);
|
||||
return skins.map((skin) => {
|
||||
return new SkinResolver(new SkinModel(ctx, skin));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const root = {
|
||||
async fetch_skin_by_md5({ md5 }, { ctx }) {
|
||||
const skin = await SkinModel.fromMd5(ctx, md5);
|
||||
|
|
@ -246,6 +214,12 @@ const root = {
|
|||
}
|
||||
return new SkinsConnection(first, offset, sort, filter);
|
||||
},
|
||||
async tweets({ first, offset, sort }) {
|
||||
if (first > 1000) {
|
||||
throw new Error("Maximum limit is 1000");
|
||||
}
|
||||
return new TweetsConnection(first, offset, sort);
|
||||
},
|
||||
me() {
|
||||
return new UserResolver();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export default class UserResolver {
|
||||
username(_args, ctx) {
|
||||
// For now every user is the current user.
|
||||
return ctx.user.username;
|
||||
return ctx.user?.username;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue