如何让 UserApi 中的 User 实体连接到数据库?

发布于 2025-01-16 19:24:18 字数 3795 浏览 2 评论 0原文

我有一个带有 redis 缓存的 apollo-express-server。 这是index.ts:

const main = async () => {
  const app = express();
 
  app.use(
    cors({
      credentials: true,
      origin: process.env.CLIENT_URL,
    })
  );
  const router = express.Router();

  const store = await createConnection();
 

  const redis = new Redis({
    port: Number(process.env.REDIS_PORT),
    host: process.env.REDIS_HOST,
    //password: process.env.REDIS_PASSWORD,
  });


  const RedisStore = connectRedis(session);
  const redisStore = new RedisStore({
    client: redis,
  });
  app.use(bodyParser.json());
  app.use(
    session({
      store: redisStore,
      name: process.env.COOKIE_NAME,
      sameSite: "Strict",
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      cookie: {
        httpOnly: true,
        secure: false,
        maxAge: 1000 * 60 * 60 * 24,
      },
    } as any)
  );

  app.use(router);

  const dataSources = () => ({
    // @ts-ignore
    userAPI: new UserAPI({ store }),
  });

  const apolloServer = new ApolloServer({
    typeDefs,
    resolvers,
    dataSources,
    context: ({ req, res }: any) => ({ req, res }),
  });
  await apolloServer.start();

  apolloServer.applyMiddleware({ app, cors: false });

  app.listen({ port: process.env.SERVER_PORT }, () => {
    console.log(
      `Server ready at http://localhost:${process.env.SERVER_PORT}${apolloServer.graphqlPath}`
    );
  });
};

main().catch((err) => {
  console.error(err);
});

我的 UserApi 类包含登录方法的实现(为了简单起见),位于此处:

export class UserAPI extends DataSource {
  private readonly store: DataSource;
  private context: any;

  constructor(store: { store: DataSource }) {
    super();
    // @ts-ignore
    this.store = store;
  }

  initialize(config: { context: any }) {
    // @ts-ignore
    this.context = config.context;
    console.log("Context from initialize: ", config.context);
  }

  async login(email: string, password: string): Promise<UserResult> {
  
//this User throws an error DataSource is not set for this entity.
    const user = await User.findOne({ where: { email } });
   
   ...
  }
}

在以前版本的 apollo 服务器中,我可以在没有数据源的情况下使用。 像这样:

解析器中的index.ts

...
 const schema = makeExecutableSchema({ typeDefs, resolvers });
  const apolloServer = new ApolloServer({
    schema,
    context: ({ req, res }: any) => ({ req, res }),
  });
...

我定义了登录函数,它使用我的自定义UserRepo中的另一个函数。

...
 login: async (
      obj: any,
      args: { email: string; password: string },
      ctx: GqlContext,
      info: any
    ): Promise<string> => {
      let user: UserResult;

     // login is from UserRepo.ts
        user = await login(args.email, args.password);     
    },
...

UserRepo.ts

...
export const login = async (
    email: string,
    password: string
): Promise<UserResult> => {
    const user = await User.findOne({ where: { email } });
   // some code ...
};
...

一切正常。但对于新版本的 apollo 服务器,我不知道该怎么做。 我正在使用

"apollo-server-express": "^3.6.4", 

"express": "^4.17.3",
    "express-session": "^1.17.2",
 "graphql": "^15.8.0",
    "graphql-middleware": "^6.1.18",
    "graphql-subscriptions": "^2.0.0",
    "graphql-tools": "^8.2.1",
    "ioredis": "^4.28.5",
    "pg": "^8.7.3",
    "typeorm": "^0.3.1",
    "typescript": "^4.6.2",

我可以通过这种方式从数据库获取我的用户

 const userRepository = getRepository(User);
    let b = await userRepository.findOne({ where: { email } });

但是如果我想更改用户的话又会这样。假设我想为保存登录功能提供新的登录日期,

user.lastModifiedOn = new Date("new date");
    await user.save();

但我得到了相同的错误。

I have an apollo-express-server with redis cache.
This is the index.ts:

const main = async () => {
  const app = express();
 
  app.use(
    cors({
      credentials: true,
      origin: process.env.CLIENT_URL,
    })
  );
  const router = express.Router();

  const store = await createConnection();
 

  const redis = new Redis({
    port: Number(process.env.REDIS_PORT),
    host: process.env.REDIS_HOST,
    //password: process.env.REDIS_PASSWORD,
  });


  const RedisStore = connectRedis(session);
  const redisStore = new RedisStore({
    client: redis,
  });
  app.use(bodyParser.json());
  app.use(
    session({
      store: redisStore,
      name: process.env.COOKIE_NAME,
      sameSite: "Strict",
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      cookie: {
        httpOnly: true,
        secure: false,
        maxAge: 1000 * 60 * 60 * 24,
      },
    } as any)
  );

  app.use(router);

  const dataSources = () => ({
    // @ts-ignore
    userAPI: new UserAPI({ store }),
  });

  const apolloServer = new ApolloServer({
    typeDefs,
    resolvers,
    dataSources,
    context: ({ req, res }: any) => ({ req, res }),
  });
  await apolloServer.start();

  apolloServer.applyMiddleware({ app, cors: false });

  app.listen({ port: process.env.SERVER_PORT }, () => {
    console.log(
      `Server ready at http://localhost:${process.env.SERVER_PORT}${apolloServer.graphqlPath}`
    );
  });
};

main().catch((err) => {
  console.error(err);
});

my UserApi class that contains implementations of a login method(for simplicity) is here:

export class UserAPI extends DataSource {
  private readonly store: DataSource;
  private context: any;

  constructor(store: { store: DataSource }) {
    super();
    // @ts-ignore
    this.store = store;
  }

  initialize(config: { context: any }) {
    // @ts-ignore
    this.context = config.context;
    console.log("Context from initialize: ", config.context);
  }

  async login(email: string, password: string): Promise<UserResult> {
  
//this User throws an error DataSource is not set for this entity.
    const user = await User.findOne({ where: { email } });
   
   ...
  }
}

In previous versions of the apollo server I could use without the dataSource.
Like this:

index.ts

...
 const schema = makeExecutableSchema({ typeDefs, resolvers });
  const apolloServer = new ApolloServer({
    schema,
    context: ({ req, res }: any) => ({ req, res }),
  });
...

in resolvers I have defined the login function which uses another function from My custom UserRepo.

...
 login: async (
      obj: any,
      args: { email: string; password: string },
      ctx: GqlContext,
      info: any
    ): Promise<string> => {
      let user: UserResult;

     // login is from UserRepo.ts
        user = await login(args.email, args.password);     
    },
...

UserRepo.ts

...
export const login = async (
    email: string,
    password: string
): Promise<UserResult> => {
    const user = await User.findOne({ where: { email } });
   // some code ...
};
...

And everything is working. But with the new version of the apollo server I can't figure out how to do it.
I am using

"apollo-server-express": "^3.6.4", 

"express": "^4.17.3",
    "express-session": "^1.17.2",
 "graphql": "^15.8.0",
    "graphql-middleware": "^6.1.18",
    "graphql-subscriptions": "^2.0.0",
    "graphql-tools": "^8.2.1",
    "ioredis": "^4.28.5",
    "pg": "^8.7.3",
    "typeorm": "^0.3.1",
    "typescript": "^4.6.2",

I can get my user from db in this way

 const userRepository = getRepository(User);
    let b = await userRepository.findOne({ where: { email } });

But then again if I want to change the user. Let's say I want to give e new date for loging in the save login function

user.lastModifiedOn = new Date("new date");
    await user.save();

I get the same error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稀香 2025-01-23 19:24:18

将 tsconfig.json 中的 "target" 更改为 "es6"

{
  "compilerOptions": {
    ...
    "target": "es6",
    ...

  },
  ...
}

Change "target" in you tsconfig.json to "es6":

{
  "compilerOptions": {
    ...
    "target": "es6",
    ...

  },
  ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文