Browse Source

feat: Ready for deployment via nix

develop v0.1.0-gql
Dale 3 weeks ago
parent
commit
f343cf9c77
Signed by: Deiru GPG Key ID: AA250C0277B927E1
28 changed files with 2709 additions and 5185 deletions
  1. +2
    -0
      .gitignore
  2. +0
    -6
      bin/build.sh
  3. +22
    -16
      default.nix
  4. +44
    -1
      graphql.schema.json
  5. +51
    -0
      module.nix
  6. +0
    -43
      nix/package.json
  7. +0
    -4954
      nix/yarn.lock
  8. +9
    -3
      package.json
  9. +1
    -1
      result
  10. +31
    -0
      src/config/index.ts
  11. +1
    -0
      src/config/local.json
  12. +21
    -6
      src/db/acl/roles.ts
  13. +42
    -25
      src/db/generate-roles.ts
  14. +3
    -3
      src/db/index.ts
  15. +6
    -1
      src/db/models/Users.ts
  16. +47
    -55
      src/db/setup-db.ts
  17. +1
    -1
      src/graphql/errors/auth.ts
  18. +4
    -0
      src/graphql/index.ts
  19. +8
    -2
      src/graphql/mutations/activities/index.ts
  20. +7
    -3
      src/graphql/mutations/channels/index.ts
  21. +5
    -1
      src/graphql/resolvers/channels/index.ts
  22. +5
    -1
      src/graphql/schema/Roles.graphql
  23. +1
    -0
      src/graphql/schema/Root.graphql
  24. +30
    -8
      src/server.ts
  25. +18
    -3
      src/types/graphql.ts
  26. +2
    -2
      tsconfig.json
  27. +760
    -38
      yarn.lock
  28. +1588
    -12
      yarn.nix

+ 2
- 0
.gitignore View File

@ -4,6 +4,8 @@ yarn-error.log
src/**/*.js
dev.sqlite3
result/
.log/
.vscode/
miracle-tv.*.zip
result/


+ 0
- 6
bin/build.sh View File

@ -1,6 +0,0 @@
#! /usr/bin/env sh
rm -rf ./dist
tsc
ls ./src/graphql
cp -r src/graphql/schema dist/graphql/schema

+ 22
- 16
default.nix View File

@ -5,35 +5,41 @@ let
src = ./.;
nodePkg = pkgs.nodejs-14_x;
yarnPkg = pkgs.yarn.override { nodejs = nodePkg; };
packages = (import ./packages.nix);
in pkgs.stdenv.mkDerivation rec {
in mkYarnPackage rec {
name = "miracle-tv";
inherit version src nodePkg yarnPkg;
doDist = false;
packageJSON = "${src}/package.json";
yarnLock = "${src}/yarn.lock";
yarnNix = "${src}/yarn.nix";
configurePhase = ''
rm -rf ./node_modules || true
mkdir -p ./node_modules/.bin
cp -r ${packages}/modules/* ./node_modules
cp -r ${packages}/modules/.bin/* ./node_modules/.bin
true
'';
buildPhase = ''
./node_modules/.bin/tsc
$node_modules/.bin/tsc -p .
'';
installPhase = ''
mkdir $out
cp -r ./dist/* $out
mkdir -p $out/node_modules
cp -r ./* $out
cp tsconfig.json $out/tsconfig.json
makeWrapper ${nodePkg}/bin/node $out/bin/${name} \
--set TS_NODE_PROJECT $out/tsconfig.json \
--add-flags '-r ts-node/register/transpile-only' \
--add-flags '-r tsconfig-paths/register' \
--add-flags $out/server.js \
--set NODE_PATH $NODE_PATH:$out:${packages}/modules
cp -r $node_modules/* $out/node_modules
makeWrapper ${yarnPkg}/bin/yarn $out/bin/${name} \
--add-flags "--cwd $out" \
--add-flags server
makeWrapper ${yarnPkg}/bin/yarn $out/bin/${name}-start \
--add-flags "--cwd $out" \
--add-flags daemon:start
makeWrapper ${yarnPkg}/bin/yarn $out/bin/${name}-stop \
--add-flags "--cwd $out" \
--add-flags daemon:stop
makeWrapper ${yarnPkg}/bin/yarn $out/bin/${name}-restart \
--add-flags "--cwd $out" \
--add-flags daemon:restart
'';
distPhase = ''
@ -43,6 +49,6 @@ in pkgs.stdenv.mkDerivation rec {
nativeBuildInputs = with pkgs; [
nodePkg yarnPkg makeWrapper
automake autoconf m4 git bash
libpng libGL gcc yarn2nix packages
libpng libGL gcc yarn2nix
];
}

+ 44
- 1
graphql.schema.json View File

@ -10,7 +10,7 @@
"types": [
{
"kind": "OBJECT",
"name": "AccessTargets",
"name": "AccessRights",
"description": null,
"fields": [
{
@ -48,6 +48,33 @@
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AccessTargets",
"description": null,
"fields": [
{
"name": "rights",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AccessRights",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "actions",
@ -875,6 +902,22 @@
"name": "InfoResponse",
"description": null,
"fields": [
{
"name": "name",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "version",
"description": null,


+ 51
- 0
module.nix View File

@ -0,0 +1,51 @@
{ lib, pkgs, config, ... }:
with lib;
let
cfg = config.services.miracle-tv;
miracleSrc = ./.;
miracle-tv = (import "${miracleSrc}/default.nix");
in {
options.services.miracle-tv = {
enable = mkEnableOption "Miracle TV server";
settings = {
name = mkOption {
type = types.str;
default = "MiracleTV";
};
server = {
hostname = mkOption {
type = types.str;
default = "0.0.0.0";
};
port = mkOption {
type = types.int;
default = 4000;
};
};
database = {
host = mkOption {
type = types.str;
default = "localhost";
};
port = mkOption {
type = types.int;
default = 28015;
};
db = mkOption {
type = types.str;
default = "miracle-tv";
};
};
};
};
config = let
configFile = pkgs.writeText "config.json" (builtins.toJSON cfg.settings);
in lib.mkIf cfg.enable {
systemd.services.miracle-tv = {
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${miracle-tv}/bin/miracle-tv ${configFile}";
};
};
}

+ 0
- 43
nix/package.json View File

@ -1,43 +0,0 @@
{
"name": "miracle-tv",
"version": "0.1.0",
"main": "server.js",
"repository": "https://code.gensokyo.social/Gensokyo.social/miracle-tv",
"license": "MIT",
"scripts": {
"server": "ts-node -r $node_modules/tsconfig-paths/register src/server.ts",
"codegen": "graphql-codegen --config codegen.yml",
"dev": "nodemon -e ts,tsx,graphql --exec \"yarn run server\""
},
"dependencies": {
"apollo-server": "^2.24.0",
"apollo-server-express": "^2.24.0",
"async": "^3.2.0",
"express": "^4.17.1",
"express-graphql": "^0.12.0",
"glob": "^7.1.7",
"graphql": "^15.5.0",
"luxon": "^1.27.0",
"md5": "^2.3.0",
"ramda": "^0.27.1",
"rethinkdb": "^2.4.2"
},
"devDependencies": {
"@graphql-codegen/cli": "1.21.4",
"@graphql-codegen/introspection": "1.18.2",
"@graphql-codegen/typescript": "1.22.0",
"@graphql-codegen/typescript-resolvers": "1.19.1",
"@types/async": "^3.2.6",
"@types/express": "^4.17.11",
"@types/express-graphql": "^0.9.0",
"@types/glob": "^7.1.3",
"@types/luxon": "^1.26.5",
"@types/md5": "^2.3.0",
"@types/ramda": "^0.27.40",
"@types/rethinkdb": "^2.3.16",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.4"
}
}

+ 0
- 4954
nix/yarn.lock
File diff suppressed because it is too large
View File


+ 9
- 3
package.json View File

@ -5,7 +5,10 @@
"repository": "https://code.gensokyo.social/Gensokyo.social/miracle-tv",
"license": "MIT",
"scripts": {
"server": "ts-node -r $node_modules/tsconfig-paths/register src/server.ts",
"daemon:start": "NODE_ENV=production name=miracle-tv pm2 start yarn --name miracle-tv -- server",
"daemon:stop": "pm2 delete miracle-tv",
"daemon:restart": "name=miracle-tv pm2 restart miracle-tv --update-env",
"server": "NODE_ENV=production ts-node -r tsconfig-paths/register src/server.ts",
"codegen": "graphql-codegen --config codegen.yml",
"dev": "nodemon -e ts,tsx,graphql --exec \"yarn run server\""
},
@ -19,8 +22,11 @@
"graphql": "^15.5.0",
"luxon": "^1.27.0",
"md5": "^2.3.0",
"module-alias": "^2.2.2",
"pm2": "^4.5.6",
"ramda": "^0.27.1",
"rethinkdb": "^2.4.2"
"rethinkdb": "^2.4.2",
"tsconfig-paths": "^3.9.0"
},
"devDependencies": {
"@graphql-codegen/cli": "1.21.4",
@ -33,6 +39,7 @@
"@types/glob": "^7.1.3",
"@types/luxon": "^1.26.5",
"@types/md5": "^2.3.0",
"@types/module-alias": "^2.0.0",
"@types/ramda": "^0.27.40",
"@types/rethinkdb": "^2.3.16",
"file-loader": "^6.2.0",
@ -41,7 +48,6 @@
"prettier": "^2.3.0",
"ts-loader": "^9.2.1",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.4",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0"


+ 1
- 1
result View File

@ -1 +1 @@
/nix/store/swivdq0jx7zmiq10bybxxhrmnvkhbs3r-miracle-tv
/nix/store/d4gc5hnnk1c1d7r503nfpxa3m5i2fhrh-miracle-tv

+ 31
- 0
src/config/index.ts View File

@ -0,0 +1,31 @@
import { readFileSync } from "fs";
import defaultConfig from "./local.json";
export type DBConfig = {
host?: string;
port?: number;
db?: string;
};
export type ServerConfig = {
hostname?: string;
port?: number;
};
export type Config = {
name?: string;
domain?: string;
server?: ServerConfig;
database?: DBConfig;
};
export const getConfig = (): Config => {
const args = process.argv.slice(2);
const configPath = args[0];
if (configPath) {
return JSON.parse(readFileSync(configPath).toString()) as Config;
}
return defaultConfig as Config;
};
export default getConfig();

+ 1
- 0
src/config/local.json View File

@ -1,4 +1,5 @@
{
"name": "Miracle TV Test",
"database": {
"host": "localhost",
"port": 28015,


+ 21
- 6
src/db/acl/roles.ts View File

@ -1,14 +1,15 @@
import { AccessUnit, Role } from "miracle-tv/types/graphql";
import { pathOr, pick } from "ramda";
import { curry, pathOr, pick } from "ramda";
import { any, lensPath, view } from "ramda";
type RowMap = Record<string, Role>;
const fetchAccess = (
roles: RowMap,
targetRole: keyof RowMap,
target: keyof Role["access"]
target: keyof Role["access"]["rights"]
): AccessUnit => {
const currentAccessPath = [targetRole, "access", target];
const currentAccessPath = [targetRole, "access", "rights", target];
const currentParentPath = [targetRole, "parentId"];
const access: AccessUnit = pathOr(
AccessUnit.Inherit,
@ -51,9 +52,11 @@ export const getCompleteRights = (roles: Role[], target: Role["id"]): Role => {
id: target,
name: rolesById[target].name,
access: {
channels: fetchAccess(rolesById, target, "channels"),
users: fetchAccess(rolesById, target, "users"),
activities: fetchAccess(rolesById, target, "activities"),
rights: {
channels: fetchAccess(rolesById, target, "channels"),
users: fetchAccess(rolesById, target, "users"),
activities: fetchAccess(rolesById, target, "activities"),
},
actions: {
user: {
ban: fetchActions(rolesById, target, ["user", "ban"]),
@ -66,3 +69,15 @@ export const getCompleteRights = (roles: Role[], target: Role["id"]): Role => {
return endRole;
};
export const checkRight = (
roles: Role[],
unit: AccessUnit,
subject: string
) => {
const channelEditRightsLens = lensPath(["access", "rights", subject]);
return any(
(right: AccessUnit) => right === unit,
roles.map(view(channelEditRightsLens))
);
};

+ 42
- 25
src/db/generate-roles.ts View File

@ -1,16 +1,18 @@
import * as rdb from "rethinkdb";
import config from "miracle-tv/config/local.json";
import config from "miracle-tv/config";
import { AccessUnit, CreateRoleInput, Role } from "miracle-tv/types/graphql";
import { AccessUnit, Role } from "miracle-tv/types/graphql";
const defaultAdminRole: Role = {
id: "admin",
name: "Admin",
parentId: "user",
parentId: "moderator",
access: {
channels: AccessUnit.Write,
users: AccessUnit.Write,
rights: {
channels: AccessUnit.Write,
users: AccessUnit.Write,
},
actions: {
user: {
silence: true,
@ -26,7 +28,9 @@ const defaultModeratorRole: Role = {
name: "Moderator",
parentId: "user",
access: {
activities: AccessUnit.Write,
rights: {
activities: AccessUnit.Write,
},
actions: {
user: {
silence: true,
@ -42,6 +46,7 @@ const defaultVolounteerRole: Role = {
name: "Volounteer",
parentId: "user",
access: {
rights: {},
actions: {
user: {
warn: true,
@ -54,9 +59,11 @@ const defaultUserRole: Role = {
id: "user",
name: "user",
access: {
channels: AccessUnit.Self,
users: AccessUnit.Read,
activities: AccessUnit.Read,
rights: {
channels: AccessUnit.Self,
users: AccessUnit.Read,
activities: AccessUnit.Read,
},
actions: {
user: {
silence: false,
@ -67,19 +74,29 @@ const defaultUserRole: Role = {
},
};
export const connection = rdb
.connect({ host: "localhost", port: 28015 })
.then(async (conn) => {
const table = rdb.db(config.database.db).table("roles");
const roles = await table.getAll().coerceTo("array").run(conn);
if (roles.length === 0) {
const result = await table
.insert([
defaultUserRole,
defaultVolounteerRole,
defaultModeratorRole,
defaultAdminRole,
])
.run(conn);
}
});
const defaultRoles = [
defaultUserRole,
defaultVolounteerRole,
defaultModeratorRole,
defaultAdminRole,
];
export const generateRoles = async () => {
const conn = await rdb.connect({ host: "localhost", port: 28015 });
const table = rdb.db(config.database?.db || "miracle-tv").table("roles");
const roles = await table.filter({}).coerceTo("array").run(conn);
const roleIds = roles.map((role) => role.id);
return await Promise.all(
defaultRoles.map(async (dr) => {
if (!roleIds.includes(dr.id)) {
const res = await table.insert(dr).run(conn);
if (res.errors > 0) {
console.info(`Error with ${dr.id}`, res.first_error);
} else {
console.info(`${dr.id} Ok!`);
}
return res;
}
})
);
};

+ 3
- 3
src/db/index.ts View File

@ -1,6 +1,6 @@
import rethinkdb from 'rethinkdb'
import config from 'miracle-tv/config/local.json';
import rethinkdb from "rethinkdb";
import config from "miracle-tv/config";
const db = rethinkdb.db(config.database.db);
const db = rethinkdb.db(config.database?.db || "miracle-tv");
export default db;

+ 6
- 1
src/db/models/Users.ts View File

@ -7,6 +7,7 @@ import {
EmailExistsError,
UserExistsError,
} from "miracle-tv/graphql/errors/users";
import { NotFoundError } from "miracle-tv/graphql/errors/general";
type UsersFilter = Partial<Record<keyof DbUser, any>>;
@ -41,7 +42,11 @@ export class UsersModel extends Model {
}
async getUserByIdSafe(id: string): Promise<User> {
return await this.getUserById(id).then(this.sanitizeUser);
const user = await this.getUserById(id);
if (!user) {
throw new NotFoundError("User not found");
}
return this.sanitizeUser(user);
}
async getUsers(filter: UsersFilter = {}): Promise<DbUser[]> {


+ 47
- 55
src/db/setup-db.ts View File

@ -1,5 +1,6 @@
import * as rdb from "rethinkdb";
import config from "miracle-tv/config/local.json";
import config from "miracle-tv/config";
import { generateRoles } from "./generate-roles";
const tables: string[] = [
"users",
@ -9,60 +10,51 @@ const tables: string[] = [
"roles",
];
export const connection = rdb
.connect({ host: "localhost", port: 28015 })
.then((con) => {
console.log("\x1b[33m", "[Checking Database Setup]", "\x1b[0m");
console.log(
export const connection = rdb.connect({
host: config.database?.host || "localhost",
port: config.database?.port || 28015,
});
export const setupDB = async () => {
const con = await connection;
console.info("\x1b[33m", "[Checking Database Setup]", "\x1b[0m");
console.info(
"\x1b[33m",
`- Checking database \`${config.database?.db || "miracle-tv"}\`...`,
"\x1b[0m"
);
const dbList = await rdb.dbList().run(con);
if (!dbList.includes(config.database?.db || "miracle-tv")) {
console.info(
"\x1b[33m",
`- Checking database \`${config.database.db}\`...`,
`-- Creating database \`${config.database?.db || "miracle-tv"}\`...`,
"\x1b[0m"
);
return rdb
.dbList()
.run(con)
.then((dbList) => {
if (!dbList.includes(config.database.db)) {
console.log(
"\x1b[33m",
`-- Creating database \`${config.database.db}\`...`,
"\x1b[0m"
);
return rdb.dbCreate(config.database.db).run(con);
} else {
console.log(
"\x1b[32m",
`-- ✔ Database \`${config.database.db}\` ok!`,
"\x1b[0m"
);
}
})
.then(() => {
rdb
.db(config.database.db)
.tableList()
.run(con)
.then((tableList) => {
tables.forEach((table) => {
console.log(
"\x1b[33m",
`- Checking \`${table}\` Table`,
"\x1b[0m"
);
if (!tableList.includes(table)) {
console.log(
"\x1b[33m",
`-- Creating \`${table}\` table...`,
"\x1b[0m"
);
rdb.db(config.database.db).tableCreate(table).run(con);
} else {
console.log("\x1b[32m", `-- Table \`${table}\` ok!`, "\x1b[0m");
}
});
console.log("\x1b[32m", "- ✔ Table Check Complete!", "\x1b[0m");
console.log("\x1b[32m", "✔ Database Check Complete!", "\x1b[0m");
});
return con;
});
});
await rdb.dbCreate(config.database?.db || "miracle-tv").run(con);
}
console.info(
"\x1b[32m",
`-- ✔ Database \`${config.database?.db || "miracle-tv"}\` ok!`,
"\x1b[0m"
);
const tableList = await rdb.db(config.database.db).tableList().run(con);
await Promise.all(
tables.map((table) => {
console.info("\x1b[33m", `- Checking \`${table}\` Table`, "\x1b[0m");
if (!tableList.includes(table)) {
console.info(
"\x1b[33m",
`-- Creating \`${table}\` table...`,
"\x1b[0m"
);
return rdb.db(config.database.db).tableCreate(table).run(con);
} else {
console.info("\x1b[32m", `-- Table \`${table}\` ok!`, "\x1b[0m");
}
})
);
console.info("\x1b[32m", "- ✔ Table Check Complete!", "\x1b[0m");
console.info("\x1b[32m", "✔ Database Check Complete!", "\x1b[0m");
const res = await generateRoles();
return res;
};

+ 1
- 1
src/graphql/errors/auth.ts View File

@ -2,7 +2,7 @@ import { ApolloError } from "apollo-server-errors";
export class InputErrorLogin extends ApolloError {
constructor() {
super("User was not found or wrong password provided");
super("User was not found or wrong password provided", "E_LOGIN");
Object.defineProperty(this, "code", { value: "E_LOGIN" });
}


+ 4
- 0
src/graphql/index.ts View File

@ -42,6 +42,7 @@ import {
import { RolesModel } from "miracle-tv/db/models/Roles";
import { getCompleteRights } from "miracle-tv/db/acl/roles";
import { roleResolvers } from "./resolvers/roles";
import config from "miracle-tv/config";
const schemaString = glob
.sync(path.resolve(__dirname, "./**/*.graphql"))
@ -58,6 +59,7 @@ export const schema = gql`
const resolvers: Resolvers<ResolverContext> = {
Query: {
info: () => ({
name: config.name || "MiracleTV",
version: process.env.npm_package_version || "none",
packageName: process.env.npm_package_name || "none",
}),
@ -91,6 +93,8 @@ const resolvers: Resolvers<ResolverContext> = {
export const graphqlEndpoint = new ApolloServer({
typeDefs: schema,
resolvers,
introspection: true,
playground: true,
context: async ({ req }) => {
const con = await connection;
const db = {


+ 8
- 2
src/graphql/mutations/activities/index.ts View File

@ -12,7 +12,10 @@ export const createActivityMutaiton: MutationResolvers<ResolverContext>["createA
throw new AuthenticationError();
}
if (
!any((role) => role.access.activities === AccessUnit.Write, userRoles)
!any(
(role) => role.access.rights.activities === AccessUnit.Write,
userRoles
)
) {
throw new AuthorizationError();
}
@ -25,7 +28,10 @@ export const updateActivityMutation: MutationResolvers<ResolverContext>["updateA
throw new AuthenticationError();
}
if (
!any((role) => role.access.activities === AccessUnit.Write, userRoles)
!any(
(role) => role.access.rights.activities === AccessUnit.Write,
userRoles
)
) {
throw new AuthorizationError();
}


+ 7
- 3
src/graphql/mutations/channels/index.ts View File

@ -1,9 +1,10 @@
import { checkRight } from "miracle-tv/db/acl/roles";
import {
AuthenticationError,
AuthorizationError,
} from "miracle-tv/graphql/errors/auth";
import { NotFoundError } from "miracle-tv/graphql/errors/general";
import { MutationResolvers } from "miracle-tv/types/graphql";
import { AccessUnit, MutationResolvers } from "miracle-tv/types/graphql";
import { ResolverContext } from "miracle-tv/types/resolver";
export const createChannelMutation: MutationResolvers<ResolverContext>["createChannel"] =
@ -15,15 +16,18 @@ export const createChannelMutation: MutationResolvers<ResolverContext>["createCh
};
export const updateChannelMutation: MutationResolvers<ResolverContext>["updateChannel"] =
async (_, { input }, { user, db: { channels } }) => {
async (_, { input }, { user, userRoles, db: { channels } }) => {
const channel = await channels.getChannelById(input.id);
const channelRights =
user?.id === ((channel as any).userId as string) ||
checkRight(userRoles, AccessUnit.Write, "channels");
if (!user) {
throw new AuthenticationError();
}
if (!channel) {
throw new NotFoundError("Channel not found");
}
if (user?.id !== (channel.user as unknown as string)) {
if (!channelRights) {
throw new AuthorizationError();
}
return await channels.updateChannel(input);


+ 5
- 1
src/graphql/resolvers/channels/index.ts View File

@ -17,7 +17,11 @@ export const channelQueryResolver: QueryResolvers<ResolverContext>["channel"] =
export const channelResolver: ChannelResolvers<ResolverContext> = {
activity: async (channel, _, { db: { activities } }) => {
return await activities.getActivityById((channel as any).activityId);
const activityId: string | null = (channel as any).activityId;
if (activityId) {
return await activities.getActivityById(activityId);
}
return null;
},
user: async (channel, _, { db: { users } }) => {
return await users.getUserByIdSafe((channel as any).userId);


+ 5
- 1
src/graphql/schema/Roles.graphql View File

@ -16,10 +16,14 @@ type Actions {
user: UserActions
}
type AccessTargets {
type AccessRights {
channels: AccessUnit
users: AccessUnit
activities: AccessUnit
}
type AccessTargets {
rights: AccessRights!
actions: Actions!
}


+ 1
- 0
src/graphql/schema/Root.graphql View File

@ -1,4 +1,5 @@
type InfoResponse {
name: String!
version: String!
packageName: String!
}


+ 30
- 8
src/server.ts View File

@ -1,13 +1,35 @@
import Express from 'express';
import { graphqlEndpoint } from 'miracle-tv/graphql';
import 'miracle-tv/db/setup-db';
import Express from "express";
import { graphqlEndpoint } from "miracle-tv/graphql";
import { setupDB } from "miracle-tv/db/setup-db";
import config from "./config";
const app = Express();
app.get('/', (_, res) => res.send('FUCK!'));
app.get("/", (_, res) => res.send("FUCK!"));
graphqlEndpoint.applyMiddleware({ app })
graphqlEndpoint.applyMiddleware({ app });
app.listen(4000, () => {
console.info('Server started on localhost:4000');
})
const main = async () => {
await setupDB();
app.listen(
config.server?.port || 4000,
config.server?.hostname || "0.0.0.0",
() => {
console.info(
"\x1b[32m",
`Server started on ${config.server?.hostname || "0.0.0.0"}:${
config.server?.port || 4000
}`,
"\x1b[0m"
);
console.info(
"",
`Playground: http://${config.domain || "localhost"}:${
config.server?.port || 4000
}/graphql`
);
}
);
};
main();

+ 18
- 3
src/types/graphql.ts View File

@ -17,11 +17,16 @@ export type Scalars = {
};
export type AccessTargets = {
__typename?: 'AccessTargets';
export type AccessRights = {
__typename?: 'AccessRights';
channels?: Maybe<AccessUnit>;
users?: Maybe<AccessUnit>;
activities?: Maybe<AccessUnit>;
};
export type AccessTargets = {
__typename?: 'AccessTargets';
rights: AccessRights;
actions: Actions;
};
@ -121,6 +126,7 @@ export type CreateUserInput = {
export type InfoResponse = {
__typename?: 'InfoResponse';
name: Scalars['String'];
version: Scalars['String'];
packageName: Scalars['String'];
};
@ -398,6 +404,7 @@ export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs
/** Mapping between all available schema types and the resolvers types */
export type ResolversTypes = {
AccessRights: ResolverTypeWrapper<AccessRights>;
AccessTargets: ResolverTypeWrapper<AccessTargets>;
AccessTargetsInput: AccessTargetsInput;
AccessUnit: AccessUnit;
@ -437,6 +444,7 @@ export type ResolversTypes = {
/** Mapping between all available schema types and the resolvers parents */
export type ResolversParentTypes = {
AccessRights: AccessRights;
AccessTargets: AccessTargets;
AccessTargetsInput: AccessTargetsInput;
Actions: Actions;
@ -477,10 +485,15 @@ export type CacheControlDirectiveArgs = { maxAge?: Maybe<Scalars['Int']>;
export type CacheControlDirectiveResolver<Result, Parent, ContextType = any, Args = CacheControlDirectiveArgs> = DirectiveResolverFn<Result, Parent, ContextType, Args>;
export type AccessTargetsResolvers<ContextType = any, ParentType extends ResolversParentTypes['AccessTargets'] = ResolversParentTypes['AccessTargets']> = {
export type AccessRightsResolvers<ContextType = any, ParentType extends ResolversParentTypes['AccessRights'] = ResolversParentTypes['AccessRights']> = {
channels?: Resolver<Maybe<ResolversTypes['AccessUnit']>, ParentType, ContextType>;
users?: Resolver<Maybe<ResolversTypes['AccessUnit']>, ParentType, ContextType>;
activities?: Resolver<Maybe<ResolversTypes['AccessUnit']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type AccessTargetsResolvers<ContextType = any, ParentType extends ResolversParentTypes['AccessTargets'] = ResolversParentTypes['AccessTargets']> = {
rights?: Resolver<ResolversTypes['AccessRights'], ParentType, ContextType>;
actions?: Resolver<ResolversTypes['Actions'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
@ -514,6 +527,7 @@ export interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<ResolversT
}
export type InfoResponseResolvers<ContextType = any, ParentType extends ResolversParentTypes['InfoResponse'] = ResolversParentTypes['InfoResponse']> = {
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
version?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
packageName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -602,6 +616,7 @@ export type UserSettingsResolvers<ContextType = any, ParentType extends Resolver
};
export type Resolvers<ContextType = any> = {
AccessRights?: AccessRightsResolvers<ContextType>;
AccessTargets?: AccessTargetsResolvers<ContextType>;
Actions?: ActionsResolvers<ContextType>;
Activity?: ActivityResolvers<ContextType>;


+ 2
- 2
tsconfig.json View File

@ -1,9 +1,9 @@
{
"compilerOptions": {
"target": "es2020",
"target": "es2019",
"module": "commonjs",
"skipLibCheck": true,
"lib": ["es2020"],
"lib": ["es5", "es6", "es2020"],
"esModuleInterop": true,
"noImplicitAny": true,
"moduleResolution": "node",


+ 760
- 38
yarn.lock
File diff suppressed because it is too large
View File


yarn.nix
File diff suppressed because it is too large
View File


Loading…
Cancel
Save