Browse Source

feat: Working nix build

develop
Dale 1 month ago
parent
commit
6be6f073c9
Signed by: Deiru GPG Key ID: AA250C0277B927E1
27 changed files with 11425 additions and 161 deletions
  1. +6
    -0
      bin/build.sh
  2. +16
    -13
      default.nix
  3. +43
    -0
      nix/package.json
  4. +4954
    -0
      nix/yarn.lock
  5. +5485
    -0
      nix/yarn.nix
  6. +7
    -1
      package.json
  7. +34
    -0
      packages.nix
  8. +1
    -0
      result
  9. +1
    -1
      src/db/models/Sessions.ts
  10. +26
    -19
      src/db/models/Users.ts
  11. +57
    -27
      src/db/setup-db.ts
  12. +0
    -0
      src/graphql/errors/auth.ts
  13. +0
    -0
      src/graphql/errors/general.ts
  14. +0
    -0
      src/graphql/errors/users.ts
  15. +81
    -0
      src/graphql/index.ts
  16. +14
    -0
      src/graphql/mutations/users/auth.ts
  17. +0
    -0
      src/graphql/mutations/users/index.ts
  18. +1
    -1
      src/graphql/resolvers/users/index.ts
  19. +0
    -0
      src/graphql/schema/Root.graphql
  20. +0
    -0
      src/graphql/schema/Scalars.graphql
  21. +0
    -0
      src/graphql/schema/User.graphql
  22. +0
    -53
      src/grpahql/index.ts
  23. +0
    -13
      src/grpahql/mutations/users/auth.ts
  24. +0
    -15
      src/grpahql/schema/index.ts
  25. +1
    -1
      src/server.ts
  26. +5
    -4
      tsconfig.json
  27. +693
    -13
      yarn.lock

+ 6
- 0
bin/build.sh View File

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

+ 16
- 13
default.nix View File

@ -1,34 +1,37 @@
with import <nixpkgs> {};
let
executableName = "miracle-tv";
version = "0.1.0";
version = "0.1.1";
src = ./.;
nodePkg = pkgs.nodejs-14_x;
yarnPkg = pkgs.yarn.override { nodejs = nodePkg; };
in mkYarnPackage rec {
name = "miarcle-tv";
packages = (import ./packages.nix);
in pkgs.stdenv.mkDerivation 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
ln -s $node_modules ./node_modules
mkdir -p ./node_modules/.bin
cp -r ${packages}/modules/* ./node_modules
cp -r ${packages}/modules/.bin/* ./node_modules/.bin
'';
buildPhase = ''
sh ./bin/build.sh
./node_modules/.bin/tsc
'';
installPhase = ''
mkdir $out
cp -R ./dist/* $out
cp -R ./migrations $out/migrations
cp -r ./dist/* $out
makeWrapper ${nodePkg}/bin/node $out/bin/${name} \
--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
'';
distPhase = ''
@ -38,6 +41,6 @@ in mkYarnPackage rec {
nativeBuildInputs = with pkgs; [
nodePkg yarnPkg makeWrapper
automake autoconf m4 git bash
libpng libGL gcc
libpng libGL gcc yarn2nix packages
];
}

+ 43
- 0
nix/package.json View File

@ -0,0 +1,43 @@
{
"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"
}
}

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


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


+ 7
- 1
package.json View File

@ -35,9 +35,15 @@
"@types/md5": "^2.3.0",
"@types/ramda": "^0.27.40",
"@types/rethinkdb": "^2.3.16",
"file-loader": "^6.2.0",
"json-loader": "^0.5.7",
"nodemon": "^2.0.7",
"prettier": "^2.3.0",
"ts-loader": "^9.2.1",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.4"
"typescript": "^4.2.4",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0"
}
}

+ 34
- 0
packages.nix View File

@ -0,0 +1,34 @@
with import <nixpkgs> {};
let
version = "0.1.0";
src = ./nix;
nodePkg = pkgs.nodejs-14_x;
yarnPkg = pkgs.yarn.override { nodejs = nodePkg; };
in mkYarnPackage rec {
name = "miracle-tv-packages";
inherit version src nodePkg yarnPkg;
packageJSON = "${src}/package.json";
yarnLock = "${src}/yarn.lock";
yarnNix = "${src}/yarn.nix";
doConfigure = false;
configurePhase = ''
true
'';
doBuild = false;
buildPhase = ''
true
'';
doDist = false;
distPhase = ''
true
'';
installPhase = ''
mkdir -p $out/modules/.bin
cp -R $node_modules/* $out/modules
cp -R $node_modules/.bin/* $out/modules/.bin
'';
}

+ 1
- 0
result View File

@ -0,0 +1 @@
/nix/store/swivdq0jx7zmiq10bybxxhrmnvkhbs3r-miracle-tv

+ 1
- 1
src/db/models/Sessions.ts View File

@ -4,7 +4,7 @@ import { Model } from 'miracle-tv/db/models';
import { Session, SessionResponse } from 'miracle-tv/types/graphql';
import { DateTime } from 'luxon';
import { head } from 'ramda'
import { ServerError } from 'miracle-tv/grpahql/errors/general';
import { ServerError } from 'miracle-tv/graphql/errors/general';
export class SessionsModel extends Model {
table = db.table('sessions')


+ 26
- 19
src/db/models/Users.ts View File

@ -1,17 +1,20 @@
import db from 'miracle-tv/db';
import { DbUser } from 'miracle-tv/db/types';
import { Model } from 'miracle-tv/db/models';
import { CreateUserInput, User } from 'miracle-tv/types/graphql';
import { head, map, omit } from 'ramda';
import { EmailExistsError, UserExistsError } from 'miracle-tv/grpahql/errors/users';
import db from "miracle-tv/db";
import { DbUser } from "miracle-tv/db/types";
import { Model } from "miracle-tv/db/models";
import { CreateUserInput, User } from "miracle-tv/types/graphql";
import { head, map, omit } from "ramda";
import {
EmailExistsError,
UserExistsError,
} from "miracle-tv/graphql/errors/users";
type UsersFilter = Partial<Record <keyof DbUser, any>>
type UsersFilter = Partial<Record<keyof DbUser, any>>;
export class UsersModel extends Model {
table = db.table('users');
table = db.table("users");
sanitizeUser(dbUser: DbUser): User {
return omit(['password'], dbUser);
return omit(["password"], dbUser);
}
async createUserSafe({ password, ...input }: CreateUserInput): Promise<User> {
@ -24,27 +27,31 @@ export class UsersModel extends Model {
if (dbEmails.length > 0) {
throw new EmailExistsError();
}
return await this.table
.insert({ password: saltedPassword, ...input, singleUserMode: false }).run(this.conn)
return (await this.table
.insert({ password: saltedPassword, ...input, singleUserMode: false })
.run(this.conn)
.then((result) => {
const key = head(result.generated_keys);
return this.table.get(key).run(this.conn).then(this.sanitizeUser)
}) as User;
return this.table.get(key).run(this.conn).then(this.sanitizeUser);
})) as User;
}
async getUserById(id: string): Promise<DbUser | null> {
return await this.table.get(id).run(this.conn) as DbUser | null;
return (await this.table.get(id).run(this.conn)) as DbUser | null;
}
async getUserByIdSafe(id: string): Promise<User> {
return await this.getUserById(id).then(this.sanitizeUser);
}
async getUsers(filter?: UsersFilter): Promise<DbUser[]> {
return await this.table.filter(filter).coerceTo('array').run(this.conn) as DbUser[];
async getUsers(filter: UsersFilter = {}): Promise<DbUser[]> {
return (await this.table
.filter(filter)
.coerceTo("array")
.run(this.conn)) as DbUser[];
}
async getUsersSafe(filter?: UsersFilter): Promise<User[]> {
return await this.getUsers(filter).then(map(this.sanitizeUser)) as User[];
async getUsersSafe(filter: UsersFilter = {}): Promise<User[]> {
return (await this.getUsers(filter).then(map(this.sanitizeUser))) as User[];
}
}

+ 57
- 27
src/db/setup-db.ts View File

@ -1,32 +1,62 @@
import * as rdb from 'rethinkdb';
import config from 'src/config/local.json';
import * as rdb from "rethinkdb";
import config from "miracle-tv/config/local.json";
const tables: string[] = ['users', 'sessions'];
const tables: string[] = ["users", "sessions"];
export const connection = rdb.connect({ host: 'localhost', port: 28015 }).then((con) => {
console.log('\x1b[33m', '[Checking Database Setup]', '\x1b[0m')
console.log('\x1b[33m', `- Checking database \`${config.database.db}\`...`, '\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);
export const connection = rdb
.connect({ host: "localhost", port: 28015 })
.then((con) => {
console.log("\x1b[33m", "[Checking Database Setup]", "\x1b[0m");
console.log(
"\x1b[33m",
`- Checking database \`${config.database.db}\`...`,
"\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', `-- Table \`${table}\` ok!`, '\x1b[0m')
console.log(
"\x1b[32m",
`-- ✔ Database \`${config.database.db}\` ok!`,
"\x1b[0m"
);
}
})
console.log('\x1b[32m', '- ✔ Table Check Complete!', '\x1b[0m')
console.log('\x1b[32m', '✔ Database Check Complete!', '\x1b[0m')
})
return con
})
})
.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;
});
});

src/grpahql/errors/auth.ts → src/graphql/errors/auth.ts View File


src/grpahql/errors/general.ts → src/graphql/errors/general.ts View File


src/grpahql/errors/users.ts → src/graphql/errors/users.ts View File


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

@ -0,0 +1,81 @@
import { Resolvers } from "miracle-tv/types/graphql";
import { connection } from "miracle-tv/db/setup-db";
import { ResolverContext } from "miracle-tv/types/resolver";
import {
userQueryResolver,
userResolver,
userListQueryResolver,
userSelfQueryResolver,
userTestQueryResolver,
} from "./resolvers/users";
import { signUpMutation } from "./mutations/users";
import { ApolloServer } from "apollo-server-express";
import { gql } from "apollo-server";
import { signInMutation } from "./mutations/users/auth";
import { DbSession, DbUser } from "miracle-tv/db/types";
import { DateTime } from "luxon";
import { SessionsModel } from "miracle-tv/db/models/Sessions";
import { UsersModel } from "miracle-tv/db/models/Users";
import glob from "glob";
import path from "path";
import { readFileSync } from "fs";
const schemaString = glob
.sync(path.resolve(__dirname, "./**/*.graphql"))
.map((filename) => {
const contents = readFileSync(filename).toString();
return contents;
})
.join("\n");
export const schema = gql`
${schemaString}
`;
const resolvers: Resolvers<ResolverContext> = {
Query: {
info: () => ({
version: process.env.npm_package_version || "none",
packageName: process.env.npm_package_name || "none",
}),
users: userListQueryResolver,
user: userQueryResolver,
self: userSelfQueryResolver,
test: userTestQueryResolver,
},
Mutation: {
ping: (...args) => {
args;
return "pong";
},
signUp: signUpMutation,
signIn: signInMutation,
},
User: userResolver,
};
export const graphqlEndpoint = new ApolloServer({
typeDefs: schema,
resolvers,
context: async ({ req }) => {
const con = await connection;
const db = {
sessions: new SessionsModel(con),
users: new UsersModel(con),
};
const session = (await db.sessions.getSessionById(
req.headers.authorization || ""
)) as DbSession | null;
const sessionIsValid =
DateTime.fromISO(session?.expiresAt).diffNow("seconds").seconds > 0 ||
false;
const user = sessionIsValid
? ((await db.users.getUserById(session?.user)) as DbUser | null)
: null;
return {
db,
session,
user,
};
},
});

+ 14
- 0
src/graphql/mutations/users/auth.ts View File

@ -0,0 +1,14 @@
import { MutationResolvers } from "miracle-tv/types/graphql";
import { ResolverContext } from "miracle-tv/types/resolver";
import { head } from "ramda";
import { InputErrorLogin } from "miracle-tv/graphql/errors/auth";
export const signInMutation: MutationResolvers<ResolverContext>["signIn"] =
async (_, { input: { username, password } }, { db: { users, sessions } }) => {
const userList = await users.getUsers({ username });
const user = head(userList);
if (user?.password === `salted+${password}`) {
return await sessions.createSession(user?.id!);
}
throw new InputErrorLogin();
};

src/grpahql/mutations/users/index.ts → src/graphql/mutations/users/index.ts View File


src/grpahql/resolvers/users/index.ts → src/graphql/resolvers/users/index.ts View File


src/grpahql/schema/Root.graphql → src/graphql/schema/Root.graphql View File


src/grpahql/schema/Scalars.graphql → src/graphql/schema/Scalars.graphql View File


src/grpahql/schema/User.graphql → src/graphql/schema/User.graphql View File


+ 0
- 53
src/grpahql/index.ts View File

@ -1,53 +0,0 @@
import schema from 'miracle-tv/grpahql/schema';
import { Resolvers } from 'miracle-tv/types/graphql';
import { connection } from 'miracle-tv/db/setup-db';
import { ResolverContext } from 'miracle-tv/types/resolver';
import { userQueryResolver, userResolver, userListQueryResolver, userSelfQueryResolver, userTestQueryResolver } from './resolvers/users';
import { signUpMutation } from './mutations/users';
import { ApolloServer } from 'apollo-server-express';
import { signInMutation } from './mutations/users/auth';
import { DbSession, DbUser } from 'miracle-tv/db/types';
import { DateTime } from 'luxon';
import { SessionsModel } from 'miracle-tv/db/models/Sessions';
import { UsersModel } from 'miracle-tv/db/models/Users';
const resolvers: Resolvers<ResolverContext> = {
Query: {
info: () => ({
version: process.env.npm_package_version || 'none',
packageName: process.env.npm_package_name || 'none',
}),
users: userListQueryResolver,
user: userQueryResolver,
self: userSelfQueryResolver,
test: userTestQueryResolver,
},
Mutation: {
ping: (...args) => {
args
return 'pong';
},
signUp: signUpMutation,
signIn: signInMutation,
},
User: userResolver,
}
export const graphqlEndpoint = new ApolloServer({ typeDefs: schema, resolvers, context: async ({ req }) => {
const con = await connection
const db = {
sessions: new SessionsModel(con),
users: new UsersModel(con)
};
const session = await db.sessions.getSessionById(req.headers.authorization || '') as DbSession | null
const sessionIsValid = DateTime.fromISO(session?.expiresAt).diffNow('seconds').seconds > 0 || false
const user = sessionIsValid
? await db.users.getUserById(session?.user) as DbUser | null
: null
return {
db,
session,
user,
}
} })

+ 0
- 13
src/grpahql/mutations/users/auth.ts View File

@ -1,13 +0,0 @@
import { MutationResolvers } from 'miracle-tv/types/graphql';
import { ResolverContext } from 'miracle-tv/types/resolver';
import { head } from 'ramda';
import { InputErrorLogin } from 'miracle-tv/grpahql/errors/auth';
export const signInMutation: MutationResolvers<ResolverContext>['signIn'] = async (_, { input: { username, password } }, { db: { users, sessions } }) => {
const userList = await users.getUsers({ username });
const user = head(userList)
if (user?.password === `salted+${password}`) {
return await sessions.createSession(user?.id!)
}
throw new InputErrorLogin()
}

+ 0
- 15
src/grpahql/schema/index.ts View File

@ -1,15 +0,0 @@
import glob from 'glob';
import path from 'path';
import {gql} from 'apollo-server';
import { readFileSync } from 'fs';
import { buildSchema } from 'graphql';
const schemaString = glob.sync(path.resolve(__dirname, './**/*.graphql')).map(filename => {
const contents = readFileSync(filename).toString();
return contents;
}).join('\n');
const schema = gql`${schemaString}`
export default schema;

+ 1
- 1
src/server.ts View File

@ -1,5 +1,5 @@
import Express from 'express';
import { graphqlEndpoint } from 'miracle-tv/grpahql';
import { graphqlEndpoint } from 'miracle-tv/graphql';
import 'miracle-tv/db/setup-db';
const app = Express();


+ 5
- 4
tsconfig.json View File

@ -1,15 +1,16 @@
{
"compilerOptions": {
"target": "es6",
"target": "es5",
"module": "commonjs",
"lib": ["es2015", "es2016", "dom", "es2017", "es6", "es5"],
"skipLibCheck": true,
"lib": ["es2020"],
"esModuleInterop": true,
"noImplicitAny": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"sourceMap": false,
"outDir": "./dist/server",
"baseUrl": "./",
"outDir": "./dist",
"baseUrl": ".",
"types": [],
"typeRoots" : ["./node_modules", "./node_modules/@types"],
"paths": {


+ 693
- 13
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save