This commit is contained in:
23
models/graphql/resolvers.ts
Normal file
23
models/graphql/resolvers.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const resolvers = {
|
||||||
|
Query: {
|
||||||
|
_empty: (): null => null,
|
||||||
|
},
|
||||||
|
|
||||||
|
Mutation: {
|
||||||
|
addTorrent: async (_: any, { input }: any, context: any) => {
|
||||||
|
const { broker } = context;
|
||||||
|
if (!broker) throw new Error("Broker not available in context");
|
||||||
|
|
||||||
|
return broker.call("qbittorrent.addTorrent", {
|
||||||
|
torrentToDownload: input.torrentToDownload,
|
||||||
|
comicObjectId: input.comicObjectId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
JSON: {
|
||||||
|
__parseValue: (value: any) => value,
|
||||||
|
__serialize: (value: any) => value,
|
||||||
|
__parseLiteral: (ast: any) => ast.value,
|
||||||
|
},
|
||||||
|
};
|
||||||
25
models/graphql/typedef.ts
Normal file
25
models/graphql/typedef.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { gql } from "graphql-tag";
|
||||||
|
|
||||||
|
export const typeDefs = gql`
|
||||||
|
scalar JSON
|
||||||
|
|
||||||
|
input AddTorrentInput {
|
||||||
|
torrentToDownload: String!
|
||||||
|
comicObjectId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddTorrentResult {
|
||||||
|
result: JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
_empty: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
"""
|
||||||
|
Add a torrent to qBittorrent
|
||||||
|
"""
|
||||||
|
addTorrent(input: AddTorrentInput!): AddTorrentResult
|
||||||
|
}
|
||||||
|
`;
|
||||||
890
package-lock.json
generated
890
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -46,10 +46,13 @@
|
|||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@graphql-tools/schema": "^10.0.31",
|
||||||
"@robertklep/qbittorrent": "^1.0.1",
|
"@robertklep/qbittorrent": "^1.0.1",
|
||||||
|
"axios": "^1.7.9",
|
||||||
|
"graphql": "^16.13.1",
|
||||||
|
"graphql-tag": "^2.12.6",
|
||||||
"ioredis": "^5.0.0",
|
"ioredis": "^5.0.0",
|
||||||
"kafkajs": "^2.2.4",
|
"kafkajs": "^2.2.4",
|
||||||
"axios": "^1.7.9",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moleculer": "^0.14.34",
|
"moleculer": "^0.14.34",
|
||||||
"moleculer-web": "^0.10.7",
|
"moleculer-web": "^0.10.7",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import fs from "fs";
|
|
||||||
import { Service, ServiceBroker } from "moleculer";
|
import { Service, ServiceBroker } from "moleculer";
|
||||||
import ApiGateway from "moleculer-web";
|
import ApiGateway from "moleculer-web";
|
||||||
|
|
||||||
@@ -45,6 +44,57 @@ export default class ApiService extends Service {
|
|||||||
logging: true,
|
logging: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/acquisition-graphql",
|
||||||
|
whitelist: ["acquisition-graphql.query"],
|
||||||
|
cors: {
|
||||||
|
origin: "*",
|
||||||
|
methods: ["GET", "POST", "OPTIONS"],
|
||||||
|
allowedHeaders: ["*"],
|
||||||
|
credentials: false,
|
||||||
|
maxAge: 3600,
|
||||||
|
},
|
||||||
|
aliases: {
|
||||||
|
"POST /": async (req: any, res: any) => {
|
||||||
|
try {
|
||||||
|
const { query, variables, operationName } = req.body;
|
||||||
|
const result = await req.$ctx.broker.call("acquisition-graphql.query", {
|
||||||
|
query,
|
||||||
|
variables,
|
||||||
|
operationName,
|
||||||
|
});
|
||||||
|
res.setHeader("Content-Type", "application/json");
|
||||||
|
res.end(JSON.stringify(result));
|
||||||
|
} catch (error: any) {
|
||||||
|
res.statusCode = 500;
|
||||||
|
res.setHeader("Content-Type", "application/json");
|
||||||
|
res.end(JSON.stringify({ errors: [{ message: error.message }] }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GET /": async (req: any, res: any) => {
|
||||||
|
try {
|
||||||
|
const query = req.$params.query;
|
||||||
|
const variables = req.$params.variables ? JSON.parse(req.$params.variables) : undefined;
|
||||||
|
const operationName = req.$params.operationName;
|
||||||
|
const result = await req.$ctx.broker.call("acquisition-graphql.query", {
|
||||||
|
query,
|
||||||
|
variables,
|
||||||
|
operationName,
|
||||||
|
});
|
||||||
|
res.setHeader("Content-Type", "application/json");
|
||||||
|
res.end(JSON.stringify(result));
|
||||||
|
} catch (error: any) {
|
||||||
|
res.statusCode = 500;
|
||||||
|
res.setHeader("Content-Type", "application/json");
|
||||||
|
res.end(JSON.stringify({ errors: [{ message: error.message }] }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bodyParsers: { json: { strict: false, limit: "1MB" } },
|
||||||
|
mappingPolicy: "restrict",
|
||||||
|
logging: true,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/logs",
|
path: "/logs",
|
||||||
use: [ApiGateway.serveStatic("logs")],
|
use: [ApiGateway.serveStatic("logs")],
|
||||||
|
|||||||
41
services/graphql.service.ts
Normal file
41
services/graphql.service.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Service, ServiceBroker } from "moleculer";
|
||||||
|
import { graphql, GraphQLSchema } from "graphql";
|
||||||
|
import { makeExecutableSchema } from "@graphql-tools/schema";
|
||||||
|
import { typeDefs } from "../models/graphql/typedef";
|
||||||
|
import { resolvers } from "../models/graphql/resolvers";
|
||||||
|
|
||||||
|
export default class GraphQLService extends Service {
|
||||||
|
private graphqlSchema!: GraphQLSchema;
|
||||||
|
|
||||||
|
public constructor(broker: ServiceBroker) {
|
||||||
|
super(broker);
|
||||||
|
this.parseServiceSchema({
|
||||||
|
name: "acquisition-graphql",
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
query: {
|
||||||
|
params: {
|
||||||
|
query: "string",
|
||||||
|
variables: { type: "object", optional: true },
|
||||||
|
operationName: { type: "string", optional: true },
|
||||||
|
},
|
||||||
|
async handler(ctx: any) {
|
||||||
|
const { query, variables, operationName } = ctx.params;
|
||||||
|
return graphql({
|
||||||
|
schema: this.graphqlSchema,
|
||||||
|
source: query,
|
||||||
|
variableValues: variables,
|
||||||
|
operationName,
|
||||||
|
contextValue: { broker: this.broker, ctx },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
started() {
|
||||||
|
this.graphqlSchema = makeExecutableSchema({ typeDefs, resolvers });
|
||||||
|
this.logger.info("Acquisition GraphQL service started");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user