Compare commits

...

No commits in common. "dev" and "mpabi" have entirely different histories.
dev ... mpabi

10 changed files with 179 additions and 3944 deletions

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
node_modules/
database.sqlite
dist/

BIN
doc/main.pdf Normal file

Binary file not shown.

179
doc/main.tex Normal file
View File

@ -0,0 +1,179 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{listings}
\usepackage{xcolor}
% Configure colors for code
\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
% Code listing style
\lstdefinestyle{mystyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen},
keywordstyle=\color{magenta},
stringstyle=\color{codepurple},
basicstyle=\ttfamily\footnotesize,
breakatwhitespace=false,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showspaces=false,
showstringspaces=false,
showtabs=false,
tabsize=2
}
\lstset{style=mystyle}
\title{Instructions for Integrating Fastify, GraphQL, and TypeORM}
\author{}
\date{}
\begin{document}
\maketitle
\section*{Step 1: Install Dependencies}
Install the required packages using npm:
\begin{lstlisting}[language=bash]
npm install fastify mercurius typeorm reflect-metadata sqlite3 graphql
\end{lstlisting}
\section*{Step 2: Configure TypeORM}
Create a file named \texttt{ormconfig.json} with the following content:
\begin{lstlisting}[language=json]
{
"type": "sqlite",
"database": "./db.sqlite",
"synchronize": true,
"logging": false,
"entities": ["src/entity/**/*.ts"],
"migrations": ["src/migration/**/*.ts"],
"subscribers": ["src/subscriber/**/*.ts"]
}
\end{lstlisting}
Next, create entities in the \texttt{src/entity} folder. Example of \texttt{User.ts}:
\begin{lstlisting}[language=typescript]
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { Post } from './Post';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(() => Post, (post) => post.author)
posts: Post[];
}
\end{lstlisting}
Example of \texttt{Post.ts}:
\begin{lstlisting}[language=typescript]
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './User';
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(() => User, (user) => user.posts)
author: User;
}
\end{lstlisting}
\section*{Step 3: Configure Fastify with GraphQL}
Create a file named \texttt{index.ts} with the following content:
\begin{lstlisting}[language=typescript]
import 'reflect-metadata';
import { createConnection } from 'typeorm';
import fastify from 'fastify';
import mercurius from 'mercurius';
import { User } from './entity/User';
import { Post } from './entity/Post';
const app = fastify();
const schema = `
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: async (_, { id }) => {
return await User.findOne({ where: { id }, relations: ['posts'] });
},
},
};
const startServer = async () => {
await createConnection();
app.register(mercurius, {
schema,
resolvers,
graphiql: true,
});
app.listen({ port: 3000 }, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`🚀 Server ready at ${address}`);
});
};
startServer();
\end{lstlisting}
\section*{Step 4: Testing}
1. Start the server:
\begin{lstlisting}[language=bash]
npx ts-node index.ts
\end{lstlisting}
2. Open your browser at:
\begin{lstlisting}[language=text]
http://localhost:3000/graphiql
\end{lstlisting}
3. Send a sample GraphQL query:
\begin{lstlisting}[language=graphql]
query {
user(id: 1) {
name
posts {
title
}
}
}
\end{lstlisting}
\end{document}

3784
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
{
"dependencies": {
"-": "^0.0.1",
"fastify": "^5.2.2",
"graphql": "^16.10.0",
"mercurius": "^16.1.0",
"metadata": "^0.1.0",
"reflect": "^0.1.3",
"reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7",
"typeorm": "^0.3.21",
"typeorm-fastify-plugin": "^3.0.0"
},
"devDependencies": {
"@types/node": "^22.13.14"
}
}

View File

@ -1,16 +0,0 @@
import 'reflect-metadata';
import dbConnection from 'typeorm-fastify-plugin';
import { User } from './entity/User';
import { Post } from './entity/Post';
import { FastifyInstance } from 'fastify';
export async function registerDb(fastify: FastifyInstance) {
fastify.register(dbConnection, {
type: 'sqlite',
database: 'database.sqlite',
entities: [User, Post],
synchronize: true,
logging: true,
})
}

View File

@ -1,14 +0,0 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './User';
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(() => User, (user) => user.posts)
author: User;
}

View File

@ -1,14 +0,0 @@
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { Post } from './Post';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(() => Post, (post) => post.author)
posts: Post[];
}

View File

@ -1,82 +0,0 @@
import 'reflect-metadata';
import Fastify from 'fastify';
import mercurius from 'mercurius';
import { registerDb } from './db';
import { User } from './entity/User';
import { Post } from './entity/Post';
const fastify = Fastify( {
logger: true
});
const schema = `
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
type Query {
user(id: ID!): User
}
type Mutation {
createUser(name: String!): User
createPost(title: String!, userId: ID!): Post
}
`
const resolvers = {
Query: {
user: async (_: unknown, { id }: {id: number} ) => {
const userRepository = fastify.orm.getRepository(User)
return await userRepository.findOne({where: { id}, relations: ['posts']})
}
},
Mutation: {
createUser: async (_: unknown, { name }: {name: string}) => {
const user = new User();
user.name = name;
const userRepository = fastify.orm.getRepository(User)
await userRepository.save(user);
return user;
},
createPost: async (_: unknown, { title, userId }: {title: string, userId: number}) => {
const userRepository = fastify.orm.getRepository(User)
const user = await userRepository.findOne({ where: { id: userId } });
if (!user) {
throw new Error("User not found");
}
const postRepository = fastify.orm.getRepository(Post)
const post = new Post();
post.title = title;
post.author = user;
await postRepository.save(post);
return post;
}
}
}
registerDb(fastify);
fastify.register(mercurius, {
schema,
resolvers,
graphiql: true
})
fastify.listen({ port: 3000}, function (err, address) {
if (err) {
fastify.log.error(err);
process.exit(1);
}
console.log(`Server listening on ${address}`);
})

View File

@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "ES6",
"module": "CommonJS",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strictPropertyInitialization": false
},
"include": ["src"]
}