”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Node.js 入门项目包括 GraphQL、Redis、JWT 和 Sequelize

Node.js 入门项目包括 GraphQL、Redis、JWT 和 Sequelize

发布于2024-12-22
浏览:683

Node.js Starter Project dengan GraphQL, Redis, JWT, dan Sequelize

此模板提供了一个 Node.js 入门项目,已配置 GraphQL 用于 API,Redis 用于缓存和临时数据存储,JWT 用于身份验证和授权,Sequelize 用于 ORM连接到关系数据库,例如 PostgreSQL 或 MySQL。该项目具有模块化结构,可让您立即开发具有集成和可扩展功能的现代 Web 应用程序。

?项目概况

该项目旨在让使用 GraphQL API 更轻松地开发后端应用程序,该 API 使用 Redis 进行数据缓存,并使用 JWT 来保护 API。 Sequelize 用作 ORM 来促进与关系数据库的交互。此外,还有中间件可以更轻松地处理身份验证、验证和日志记录。

主要特点

  • GraphQL API实现更灵活、高效的查询和数据突变
  • JWT 身份验证 用于基于令牌的安全身份验证
  • Redis用于数据缓存和提高应用程序性能
  • Sequelize ORM用于关系数据库管理
  • 中间件用于集中授权和请求处理
  • 模块化且结构良好可扩展且更易于维护

?️ 使用的技术

  • Node.js:使用 JavaScript 构建服务器端应用程序的平台。了解更多
  • GraphQL:API 的查询语言,可实现高效、灵活的数据检索。了解更多
  • Redis:临时数据存储(内存中),通常用于缓存和消息代理。了解更多
  • JWT:安全且简单的基于令牌的身份验证技术。了解更多
  • Sequelize:Node.js 的 ORM,支持 PostgreSQL、MySQL 和其他关系数据库。了解更多

?设置和运行项目的步骤

1. 克隆存储库

首先,将此模板存储库克隆到本地计算机:

git clone https://gitlab.com/dioarafi1/graphify-api.git
cd graphify-api

如果您从头开始,请使用以下命令初始化一个新项目:

mkdir blog-api
cd blog-api
npm init -y

2. 安装依赖项

克隆存储库或创建新项目后,运行命令安装所需的依赖项:

yarn install

这将安装 package.json 文件中列出的所有依赖项。


3. 环境配置

在项目根目录下创建.env文件,为RedisJWTDatabase添加如下配置:

DATABASE_URL="postgresql://user:password@localhost:5432/mydatabase"
JWT_SECRET="your_jwt_secret_key"
REDIS_HOST="localhost"
REDIS_PORT="6379"

根据您的数据库配置更改用户、密码和 mydatabase。


4. 使用 Sequelize 准备数据库

如果没有配置数据库,请运行命令初始化Sequelize并创建模型:

yarn sequelize init

这将在您的项目中创建配置、模型和迁移目录结构。接下来,为应用程序创建必要的模型,例如 UserPost,并执行迁移以在数据库中创建表。

yarn sequelize db:migrate

确保数据库正在运行(例如使用 PostgreSQL 或 MySQL)。


5. 设置 GraphQL Server

安装 Apollo Server 和 GraphQL 的依赖项:

yarn add apollo-server graphql

之后,创建 GraphQL 服务器配置文件、架构和解析器。您可以通过以下方式配置 GraphQL 服务器:

src/服务器.ts

import { ApolloServer } from 'apollo-server-express';
import express from 'express';
import { typeDefs, resolvers } from './graphql';
import { authenticateJWT } from './middlewares/auth';
import { sequelize } from './config/database';

const app = express();

// Gunakan middleware JWT
app.use(authenticateJWT);

// Inisialisasi Apollo Server
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => ({ user: req.user }),
});

server.applyMiddleware({ app });

const PORT = process.env.PORT || 4000;

app.listen(PORT, async () => {
  console.log(`Server running at http://localhost:${PORT}${server.graphqlPath}`);
  await sequelize.authenticate();
  console.log('Database connected');
});

src/graphql/schema.ts

定义查询和突变的 GraphQL 架构:

import { gql } from 'apollo-server-express';

export const typeDefs = gql`
  type User {
    id: ID!
    username: String!
  }

  type Post {
    id: ID!
    title: String!
    content: String!
    user: User!
  }

  type Query {
    posts: [Post]
    post(id: ID!): Post
    users: [User]
  }

  type Mutation {
    createPost(title: String!, content: String!): Post
    register(username: String!, password: String!): User
    login(username: String!, password: String!): String # JWT token
  }
`;

src/graphql/resolvers.ts

为查询和突变实现解析器:

import { Post, User } from '../models';
import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';

export const resolvers = {
  Query: {
    posts: () => Post.findAll(),
    post: (_, { id }) => Post.findByPk(id),
    users: () => User.findAll(),
  },
  Mutation: {
    createPost: async (_, { title, content }, { user }) => {
      if (!user) throw new Error('Authentication required');
      const post = await Post.create({ title, content, userId: user.id });
      return post;
    },
    register: async (_, { username, password }) => {
      const hashedPassword = await bcrypt.hash(password, 10);
      const user = await User.create({ username, password: hashedPassword });
      return user;
    },
    login: async (_, { username, password }) => {
      const user = await User.findOne({ where: { username } });
      if (!user) throw new Error('User not found');

      const match = await bcrypt.compare(password, user.password);
      if (!match) throw new Error('Invalid password');

      const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET!, { expiresIn: '1h' });
      return token;
    },
  },
};

6. 运行开发服务器

要使用hot-reload在开发环境中运行服务器,请使用以下命令:

yarn dev

服务器将在http://localhost:4000运行,您可以访问GraphQL Playground来测试API查询和突变。


?项目目录结构

此项目目录结构旨在分隔应用程序的不同部分,使其更加模块化且易于维护:

/myapp
├── src
│   ├── middlewares      # Berisi middleware untuk otentikasi (JWT), caching (Redis), dan validasi
│   ├── routes           # Definisi endpoint API dan resolver GraphQL
│   ├── services         # Logika bisnis utama dan pengolahan data
│   ├── app.ts           # File utama untuk inisialisasi aplikasi dan middleware
│   ├── graphql          # Menyimpan konfigurasi GraphQL, schema, dan resolvers
│   ├── models           # Model Sequelize untuk mengelola database relasional
│   ├── config           # File konfigurasi global untuk Redis, JWT, database, dll
│   ├── index.ts         # Entry point aplikasi, menginisialisasi server dan middleware
│   ├── resolvers        # Berisi resolver GraphQL untuk query dan mutasi
│   ├── server.ts        # File untuk setup Apollo Server dan konfigurasi GraphQL
│   ├── schema           # Definisi schema GraphQL
│   ├── types            # TypeScript types dan interfaces untuk GraphQL dan lainnya
│   └── utils            # Berisi helper dan fungsi utility
├──

 .env                 # File konfigurasi environment (Redis, JWT Secret, Database URL)
├── package.json         # Metadata proyek dan dependensi
└── tsconfig.json        # Konfigurasi TypeScript

?部署

要准备生产项目,请使用以下命令将 TypeScript 构建为 JavaScript:

yarn build

输出将位于 dist/ 文件夹中并准备好部署到生产服务器。

为云平台做准备

此项目可以部署到 HerokuAWSDigitalOcean 等平台,步骤如下:

  1. 将代码推送到 Git 存储库(GitHub、GitLab 或其他)。
  2. 在所选云平台(Redis、JWT Secret、URL 数据库)上设置环境变量
  3. 使用云平台的命令或集成部署项目

?资源

  • GraphQL 文档
  • Redis 文档
  • 智威汤逊文档
  • 续集文档

按照上述步骤,您现在可以使用 RedisJWTSequelize 运行和开发 GraphQL API 应用程序。

版本声明 本文转载于:https://dev.to/dioarafi/nodejs-starter-project-dengan-graphql-redis-jwt-dan-sequelize-2l3i?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-03-11
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-03-11
  • 大批
    大批
    [2 数组是对象,因此它们在JS中也具有方法。 切片(开始):在新数组中提取部分数组,而无需突变原始数组。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    编程 发布于2025-03-11
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-03-11
  • 如何在Java字符串中有效替换多个子字符串?
    如何在Java字符串中有效替换多个子字符串?
    在java 中有效地替换多个substring,需要在需要替换一个字符串中的多个substring的情况下,很容易求助于重复应用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    编程 发布于2025-03-11
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-03-11
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中3个Party Package将另一个PAXPANCE带有导入式套件之间的另一个软件包,并在导入式套件之间导入另一个软件包。如回声消息所证明的那样: go.etcd.io/bbolt [&&&&&&&&&&&&&&&&...
    编程 发布于2025-03-11
  • 对象拟合:IE和Edge中的封面失败,如何修复?
    对象拟合:IE和Edge中的封面失败,如何修复?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    编程 发布于2025-03-11
  • 为什么尽管有效代码,为什么在PHP中捕获输入?
    为什么尽管有效代码,为什么在PHP中捕获输入?
    在php ;?>" method="post">The intention is to capture the input from the text box and display it when the submit button is clicked.但是,输出...
    编程 发布于2025-03-11
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-03-11
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-03-11
  • 如何使用PHP将斑点(图像)正确插入MySQL?
    如何使用PHP将斑点(图像)正确插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call ...
    编程 发布于2025-03-11
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-03-11
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-03-11
  • 为什么不使用CSS`content'属性显示图像?
    为什么不使用CSS`content'属性显示图像?
    在Firefox extemers属性为某些图像很大,&& && && &&华倍华倍[华氏华倍华氏度]很少见,却是某些浏览属性很少,尤其是特定于Firefox的某些浏览器未能在使用内容属性引用时未能显示图像的情况。这可以在提供的CSS类中看到:。googlepic { 内容:url(&#...
    编程 发布于2025-03-11

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3