mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-09 20:12:10 +10:00
fix: query type inference
This commit is contained in:
@ -26,8 +26,8 @@
|
||||
<div class="flex-auto">
|
||||
<h3 class="text-sm/6 font-semibold text-zinc-100">
|
||||
<button :class="actionsComplete[actionIdx]
|
||||
? 'line-through text-zinc-300'
|
||||
: ''
|
||||
? 'line-through text-zinc-300'
|
||||
: ''
|
||||
" @click="() => (currentAction = actionIdx)">
|
||||
<span class="absolute inset-0" aria-hidden="true" />
|
||||
{{ action.name }}
|
||||
|
||||
@ -6,30 +6,31 @@ const SearchGame = type({
|
||||
q: "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof SearchGame.infer;
|
||||
|
||||
/**
|
||||
* Search metadata providers for a query. Results can be used to import a game with metadata.
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof SearchGame.infer }>(
|
||||
async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["import:game:read"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["import:game:read"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
|
||||
const query = getQuery(h3);
|
||||
const search = SearchGame(query);
|
||||
if (search instanceof ArkErrors)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid search: " + search.summary,
|
||||
});
|
||||
const query = getQuery(h3);
|
||||
const search = SearchGame(query);
|
||||
if (search instanceof ArkErrors)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid search: " + search.summary,
|
||||
});
|
||||
|
||||
const results = await metadataHandler.search(search.q);
|
||||
const results = await metadataHandler.search(search.q);
|
||||
|
||||
if (results.length == 0)
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: "No metadata provider returned search results.",
|
||||
});
|
||||
if (results.length == 0)
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: "No metadata provider returned search results.",
|
||||
});
|
||||
|
||||
return results;
|
||||
},
|
||||
);
|
||||
return results;
|
||||
});
|
||||
|
||||
@ -7,10 +7,13 @@ const Query = type({
|
||||
id: "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* Fetch all versions available for import for a game (`id` in query params).
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof Query.infer }>(async (h3) => {
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["import:version:read"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
|
||||
|
||||
@ -7,10 +7,13 @@ const Query = type({
|
||||
version: "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* Fetch recommendations for version import.
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof Query.infer }>(async (h3) => {
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["import:version:read"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
|
||||
|
||||
@ -7,10 +7,13 @@ const Query = type({
|
||||
id: "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* Fetch invitation details for pre-filling
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof Query.infer }>(async (h3) => {
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const t = await useTranslation(h3);
|
||||
|
||||
if (!authManager.getAuthProviders().Simple)
|
||||
|
||||
@ -6,10 +6,13 @@ const Query = type({
|
||||
code: "string.upper",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* Fetch client ID by authorize code
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof Query.infer }>(async (h3) => {
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, []);
|
||||
if (!userId) throw createError({ statusCode: 403 });
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import type { FetchError } from "ofetch";
|
||||
import clientHandler from "~/server/internal/clients/handler";
|
||||
|
||||
/**
|
||||
* Client route to listen for code authorization.
|
||||
* Client route to listen for code authorization.
|
||||
* @request Pass the code in the `Authorization` header
|
||||
*/
|
||||
export default defineWebSocketHandler({
|
||||
|
||||
@ -9,7 +9,7 @@ const HandshakeBody = type({
|
||||
}).configure(throwingArktype);
|
||||
|
||||
/**
|
||||
* Client route to complete handshake, after the user has authorize it.
|
||||
* Client route to complete handshake, after the user has authorize it.
|
||||
*/
|
||||
export default defineEventHandler<{ body: typeof HandshakeBody.infer }>(
|
||||
async (h3) => {
|
||||
|
||||
@ -6,10 +6,13 @@ const Query = type({
|
||||
id: "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* Fetch details about an authorization request, and claim it for the current user
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof Query.infer }>(async (h3) => {
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, []);
|
||||
if (!userId) throw createError({ statusCode: 403 });
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ const ClientAuthInitiate = type({
|
||||
}).configure(throwingArktype);
|
||||
|
||||
/**
|
||||
* Client route to initiate authorization flow.
|
||||
* Client route to initiate authorization flow.
|
||||
* @response The requested callback or code.
|
||||
*/
|
||||
export default defineEventHandler<{ body: typeof ClientAuthInitiate.infer }>(
|
||||
|
||||
@ -18,86 +18,89 @@ const Query = type({
|
||||
chunk: "string.numeric.parse",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof Query.inferIn;
|
||||
|
||||
/**
|
||||
* v1 download API
|
||||
* @deprecated
|
||||
* @response Raw binary data (`application/octet-stream`)
|
||||
*/
|
||||
export default defineClientEventHandler<unknown, { query: typeof Query.infer }>(
|
||||
async (h3) => {
|
||||
const query = Query(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
const gameId = query.id;
|
||||
const versionName = query.version;
|
||||
const filename = query.name;
|
||||
const chunkIndex = query.chunk;
|
||||
export default defineClientEventHandler(async (h3) => {
|
||||
const query = Query(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
const gameId = query.id;
|
||||
const versionName = query.version;
|
||||
const filename = query.name;
|
||||
const chunkIndex = query.chunk;
|
||||
|
||||
if (!gameId || !versionName || !filename || Number.isNaN(chunkIndex))
|
||||
if (!gameId || !versionName || !filename || Number.isNaN(chunkIndex))
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid chunk arguments",
|
||||
});
|
||||
|
||||
let game = await gameLookupCache.getItem(gameId);
|
||||
if (!game) {
|
||||
game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: gameId,
|
||||
},
|
||||
select: {
|
||||
libraryId: true,
|
||||
libraryPath: true,
|
||||
},
|
||||
});
|
||||
if (!game || !game.libraryId)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid chunk arguments",
|
||||
statusMessage: "Invalid game ID",
|
||||
});
|
||||
|
||||
let game = await gameLookupCache.getItem(gameId);
|
||||
if (!game) {
|
||||
game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: gameId,
|
||||
},
|
||||
select: {
|
||||
libraryId: true,
|
||||
libraryPath: true,
|
||||
},
|
||||
});
|
||||
if (!game || !game.libraryId)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid game ID",
|
||||
});
|
||||
await gameLookupCache.setItem(gameId, game);
|
||||
}
|
||||
|
||||
await gameLookupCache.setItem(gameId, game);
|
||||
}
|
||||
if (!game.libraryId)
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: "Somehow, we got here.",
|
||||
});
|
||||
|
||||
if (!game.libraryId)
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: "Somehow, we got here.",
|
||||
});
|
||||
const peek = await libraryManager.peekFile(
|
||||
game.libraryId,
|
||||
game.libraryPath,
|
||||
versionName,
|
||||
filename,
|
||||
);
|
||||
if (!peek)
|
||||
throw createError({ status: 400, statusMessage: "Failed to peek file" });
|
||||
|
||||
const peek = await libraryManager.peekFile(
|
||||
game.libraryId,
|
||||
game.libraryPath,
|
||||
versionName,
|
||||
filename,
|
||||
);
|
||||
if (!peek)
|
||||
throw createError({ status: 400, statusMessage: "Failed to peek file" });
|
||||
const start = chunkIndex * chunkSize;
|
||||
const end = Math.min((chunkIndex + 1) * chunkSize, peek.size);
|
||||
const currentChunkSize = end - start;
|
||||
setHeader(h3, "Content-Length", currentChunkSize);
|
||||
|
||||
const start = chunkIndex * chunkSize;
|
||||
const end = Math.min((chunkIndex + 1) * chunkSize, peek.size);
|
||||
const currentChunkSize = end - start;
|
||||
setHeader(h3, "Content-Length", currentChunkSize);
|
||||
if (start >= end)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid chunk index",
|
||||
});
|
||||
|
||||
if (start >= end)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid chunk index",
|
||||
});
|
||||
const gameReadStream = await libraryManager.readFile(
|
||||
game.libraryId,
|
||||
game.libraryPath,
|
||||
versionName,
|
||||
filename,
|
||||
{ start, end },
|
||||
);
|
||||
if (!gameReadStream)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Failed to create stream",
|
||||
});
|
||||
|
||||
const gameReadStream = await libraryManager.readFile(
|
||||
game.libraryId,
|
||||
game.libraryPath,
|
||||
versionName,
|
||||
filename,
|
||||
{ start, end },
|
||||
);
|
||||
if (!gameReadStream)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Failed to create stream",
|
||||
});
|
||||
await sendStream(h3, gameReadStream);
|
||||
|
||||
return sendStream(h3, gameReadStream);
|
||||
},
|
||||
);
|
||||
return;
|
||||
});
|
||||
|
||||
@ -15,7 +15,7 @@ export default defineClientEventHandler(async (h3) => {
|
||||
const query = Query(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
|
||||
|
||||
const id = query.id;
|
||||
const version = query.version;
|
||||
|
||||
|
||||
@ -12,34 +12,35 @@ const NewsFetch = type({
|
||||
"search?": "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof NewsFetch.infer;
|
||||
|
||||
/**
|
||||
* Fetch instance news articles
|
||||
*/
|
||||
export default defineClientEventHandler<ReturnType<typeof newsManager.fetch>, { query: typeof NewsFetch.infer }>(
|
||||
async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["news:read"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Requires authentication",
|
||||
});
|
||||
export default defineClientEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["news:read"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Requires authentication",
|
||||
});
|
||||
|
||||
const query = NewsFetch(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
const query = NewsFetch(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
|
||||
const orderBy = query.order;
|
||||
const tags = query.tags;
|
||||
const orderBy = query.order;
|
||||
const tags = query.tags;
|
||||
|
||||
const options = {
|
||||
take: Math.min(query.limit ?? 10, 10),
|
||||
skip: query.skip ?? 0,
|
||||
orderBy: orderBy,
|
||||
...(tags && { tags: tags.map((e) => e.toString()) }),
|
||||
search: query.search,
|
||||
};
|
||||
const options = {
|
||||
take: Math.min(query.limit ?? 10, 10),
|
||||
skip: query.skip ?? 0,
|
||||
orderBy: orderBy,
|
||||
...(tags && { tags: tags.map((e) => e.toString()) }),
|
||||
search: query.search,
|
||||
};
|
||||
|
||||
const news = await newsManager.fetch(options);
|
||||
return news;
|
||||
},
|
||||
);
|
||||
const news = await newsManager.fetch(options);
|
||||
return news;
|
||||
});
|
||||
|
||||
@ -11,22 +11,24 @@ const AddEntry = type({
|
||||
* Add game to collection
|
||||
* @param id Collection ID
|
||||
*/
|
||||
export default defineEventHandler<{ body: typeof AddEntry.infer }>(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["collections:add"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
});
|
||||
export default defineEventHandler<{ body: typeof AddEntry.infer }>(
|
||||
async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["collections:add"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
});
|
||||
|
||||
const id = getRouterParam(h3, "id");
|
||||
if (!id)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "ID required in route params",
|
||||
});
|
||||
const id = getRouterParam(h3, "id");
|
||||
if (!id)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "ID required in route params",
|
||||
});
|
||||
|
||||
const body = await readDropValidatedBody(h3, AddEntry);
|
||||
const gameId = body.id;
|
||||
const body = await readDropValidatedBody(h3, AddEntry);
|
||||
const gameId = body.id;
|
||||
|
||||
return await userLibraryManager.collectionAdd(gameId, id, userId);
|
||||
});
|
||||
return await userLibraryManager.collectionAdd(gameId, id, userId);
|
||||
},
|
||||
);
|
||||
|
||||
@ -11,34 +11,35 @@ const NewsFetch = type({
|
||||
"search?": "string",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof NewsFetch.infer;
|
||||
|
||||
/**
|
||||
* Fetch instance news articles
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof NewsFetch.infer }, ReturnType<typeof newsManager.fetch>>(
|
||||
async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["news:read"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Requires authentication",
|
||||
});
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["news:read"]);
|
||||
if (!userId)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Requires authentication",
|
||||
});
|
||||
|
||||
const query = NewsFetch(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
const query = NewsFetch(getQuery(h3));
|
||||
if (query instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: query.summary });
|
||||
|
||||
const orderBy = query.order;
|
||||
const tags = query.tags;
|
||||
const orderBy = query.order;
|
||||
const tags = query.tags;
|
||||
|
||||
const options = {
|
||||
take: Math.min(query.limit ?? 10, 10),
|
||||
skip: query.skip ?? 0,
|
||||
orderBy: orderBy,
|
||||
...(tags && { tags: tags.map((e) => e.toString()) }),
|
||||
search: query.search,
|
||||
};
|
||||
const options = {
|
||||
take: Math.min(query.limit ?? 10, 10),
|
||||
skip: query.skip ?? 0,
|
||||
orderBy: orderBy,
|
||||
...(tags && { tags: tags.map((e) => e.toString()) }),
|
||||
search: query.search,
|
||||
};
|
||||
|
||||
const news = await newsManager.fetch(options);
|
||||
return news;
|
||||
},
|
||||
);
|
||||
const news = await newsManager.fetch(options);
|
||||
return news;
|
||||
});
|
||||
|
||||
@ -21,107 +21,108 @@ const StoreRead = type({
|
||||
sort: "'default' | 'newest' | 'recent' = 'default'",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type APIQuery = typeof StoreRead.inferIn;
|
||||
|
||||
/**
|
||||
* Store endpoint. Filter games with pagination. Used for all "store views".
|
||||
*/
|
||||
export default defineEventHandler<{ query: typeof StoreRead.infer }>(
|
||||
async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["store:read"]);
|
||||
if (!userId) throw createError({ statusCode: 403 });
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["store:read"]);
|
||||
if (!userId) throw createError({ statusCode: 403 });
|
||||
|
||||
const query = getQuery(h3);
|
||||
const options = StoreRead(query);
|
||||
if (options instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: options.summary });
|
||||
const query = getQuery(h3);
|
||||
const options = StoreRead(query);
|
||||
if (options instanceof ArkErrors)
|
||||
throw createError({ statusCode: 400, statusMessage: options.summary });
|
||||
|
||||
/**
|
||||
* Generic filters
|
||||
*/
|
||||
const tagFilter = options.tags
|
||||
? {
|
||||
tags: {
|
||||
some: {
|
||||
id: {
|
||||
in: options.tags.split(","),
|
||||
},
|
||||
/**
|
||||
* Generic filters
|
||||
*/
|
||||
const tagFilter = options.tags
|
||||
? {
|
||||
tags: {
|
||||
some: {
|
||||
id: {
|
||||
in: options.tags.split(","),
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const platformFilter = options.platform
|
||||
? {
|
||||
versions: {
|
||||
some: {
|
||||
platform: {
|
||||
in: options.platform
|
||||
.split(",")
|
||||
.map(parsePlatform)
|
||||
.filter((e) => e !== undefined),
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const platformFilter = options.platform
|
||||
? {
|
||||
versions: {
|
||||
some: {
|
||||
platform: {
|
||||
in: options.platform
|
||||
.split(",")
|
||||
.map(parsePlatform)
|
||||
.filter((e) => e !== undefined),
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
|
||||
/**
|
||||
* Company filtering
|
||||
*/
|
||||
const companyActions = options.companyActions.split(",");
|
||||
const developedFilter = companyActions.includes("developed")
|
||||
? {
|
||||
developers: {
|
||||
some: {
|
||||
id: options.company!,
|
||||
},
|
||||
/**
|
||||
* Company filtering
|
||||
*/
|
||||
const companyActions = options.companyActions.split(",");
|
||||
const developedFilter = companyActions.includes("developed")
|
||||
? {
|
||||
developers: {
|
||||
some: {
|
||||
id: options.company!,
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const publishedFilter = companyActions.includes("published")
|
||||
? {
|
||||
publishers: {
|
||||
some: {
|
||||
id: options.company!,
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const publishedFilter = companyActions.includes("published")
|
||||
? {
|
||||
publishers: {
|
||||
some: {
|
||||
id: options.company!,
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const companyFilter = options.company
|
||||
? ({
|
||||
OR: [developedFilter, publishedFilter].filter((e) => e !== undefined),
|
||||
} satisfies Prisma.GameWhereInput)
|
||||
: undefined;
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
const companyFilter = options.company
|
||||
? ({
|
||||
OR: [developedFilter, publishedFilter].filter((e) => e !== undefined),
|
||||
} satisfies Prisma.GameWhereInput)
|
||||
: undefined;
|
||||
|
||||
/**
|
||||
* Query
|
||||
*/
|
||||
/**
|
||||
* Query
|
||||
*/
|
||||
|
||||
const finalFilter: Prisma.GameWhereInput = {
|
||||
...tagFilter,
|
||||
...platformFilter,
|
||||
...companyFilter,
|
||||
};
|
||||
const finalFilter: Prisma.GameWhereInput = {
|
||||
...tagFilter,
|
||||
...platformFilter,
|
||||
...companyFilter,
|
||||
};
|
||||
|
||||
const sort: Prisma.GameOrderByWithRelationInput = {};
|
||||
switch (options.sort) {
|
||||
case "default":
|
||||
case "newest":
|
||||
sort.mReleased = "desc";
|
||||
break;
|
||||
case "recent":
|
||||
sort.created = "desc";
|
||||
break;
|
||||
}
|
||||
const sort: Prisma.GameOrderByWithRelationInput = {};
|
||||
switch (options.sort) {
|
||||
case "default":
|
||||
case "newest":
|
||||
sort.mReleased = "desc";
|
||||
break;
|
||||
case "recent":
|
||||
sort.created = "desc";
|
||||
break;
|
||||
}
|
||||
|
||||
const [results, count] = await prisma.$transaction([
|
||||
prisma.game.findMany({
|
||||
skip: options.skip,
|
||||
take: Math.min(options.take, 50),
|
||||
where: finalFilter,
|
||||
orderBy: sort,
|
||||
}),
|
||||
prisma.game.count({ where: finalFilter }),
|
||||
]);
|
||||
const [results, count] = await prisma.$transaction([
|
||||
prisma.game.findMany({
|
||||
skip: options.skip,
|
||||
take: Math.min(options.take, 50),
|
||||
where: finalFilter,
|
||||
orderBy: sort,
|
||||
}),
|
||||
prisma.game.count({ where: finalFilter }),
|
||||
]);
|
||||
|
||||
return { results, count };
|
||||
},
|
||||
);
|
||||
return { results, count };
|
||||
});
|
||||
|
||||
@ -13,7 +13,7 @@ const GetChunk = type({
|
||||
|
||||
/**
|
||||
* Part of v2 download API. Intended to be client-only.
|
||||
*
|
||||
*
|
||||
* Returns raw stream of all files requested, in order.
|
||||
* @response `application/octet-stream` stream of all files concatenated
|
||||
*/
|
||||
|
||||
@ -16,7 +16,7 @@ type ClientUtils<R> = {
|
||||
|
||||
const NONCE_LENIENCE = 30_000;
|
||||
|
||||
type ClientEventHandlerRequest<T, Q = {[key: string]: any }> = {
|
||||
type ClientEventHandlerRequest<T, Q = { [key: string]: any }> = {
|
||||
body?: T;
|
||||
query?: Q;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user