Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TsEd with apollo server 4 support #2493

Open
SavvasAmruthShivaprakash opened this issue Oct 27, 2023 · 29 comments
Open

TsEd with apollo server 4 support #2493

SavvasAmruthShivaprakash opened this issue Oct 27, 2023 · 29 comments
Assignees

Comments

@SavvasAmruthShivaprakash

Is your feature request related to a problem? Please describe.

Migrating from apollo3 to apollo4 , the current dependencies are all compliant with apollo3.

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Additional context

No response

Acceptance criteria

No response

@Romakita
Copy link
Collaborator

Romakita commented Nov 2, 2023

Hello @SavvasAmruthShivaprakash

you can create a PR if you have time to update dependencies :)

See you
Romain

@alecl
Copy link

alecl commented May 14, 2024

While the Apollo 4 EoL was extended for a bit, it is coming up again.

@Romakita
Copy link
Collaborator

Hi everybody,

PR is welcome to update dependencies.

See you

@Romakita
Copy link
Collaborator

@Romakita
Copy link
Collaborator

PR is ready:
#2713

@alecl @SavvasAmruthShivaprakash Can you review the PR.
Also the migration to Apollo 4 change a lot of things so I haven't choice to broke the module configuration.

I don't want to create major release for that :/

@Romakita Romakita moved this from To do to Review in progress in Global Board Jun 19, 2024
@SavvasManteshPatil
Copy link

Hi @Romakita Getting below error while building the monorepo

Lerna (powered by Nx) Running target build for 58 projects failed

Tasks not run because their dependencies failed or --nx-bail=true:

  • @tsed/typegraphql:build
  • @tsed/adapters-redis:build
  • @tsed/mikro-orm:build
  • @tsed/platform-express:build
  • @tsed/platform-koa:build
  • @tsed/platform-serverless:build
  • @tsed/platform-serverless-http:build
  • @tsed/platform-test-sdk:build
  • @tsed/oidc-provider:build
  • @tsed/oidc-provider-plugin-wildcard-redirect-uri:build
  • @tsed/event-emitter:build
  • @tsed/formio:build
  • @tsed/pulse:build
  • @tsed/socketio:build
  • @tsed/sse:build
  • @tsed/temporal:build
  • @tsed/terminus:build
  • @tsed/vite-ssr-plugin:build

Failed tasks:

  • @tsed/adapters:build
  • @tsed/passport:build
at makeError (file:///C:/SAVVAS/STUDENT/apollo-server/tsed/node_modules/execa/lib/error.js:60:11)
at handlePromise (file:///C:/SAVVAS/STUDENT/apollo-server/tsed/node_modules/execa/index.js:124:26)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async LernaCli.runMany (file:///C:/SAVVAS/STUDENT/apollo-server/tsed/node_modules/@tsed/monorepo-utils/src/utils/cli/Lerna.js:24:12)
at async Task.run (file:///C:/SAVVAS/STUDENT/apollo-server/tsed/node_modules/@tsed/monorepo-utils/node_modules/listr2/dist/index.js:2051:11)

@SavvasManteshPatil
Copy link

SavvasManteshPatil commented Aug 28, 2024

@Romakita, Finding an issue while implementing PR 2713. I am not able load playground after server start. my server configuration is as below and package and code changes are here

@Configuration({
    mount: {
        '/': [ HealthCheckController ],
    },
    apollo: {
        server1: {
            path: '/url',
            includeStacktraceInErrorResponses: true,
            debug: isStackTraceEnabled,
            playground: true,
            resolvers: [
               /* resolvers list */
            ],
            buildSchemaOptions: {
                authChecker: customAuthChecker,
                emitSchemaFile: true
            },
            plugins: [setHttpPlugin],
            formatError: (formattedError: GraphQLFormattedError, error: unknown) => {  }
        }
    },
    httpPort: config.get('port'),
    httpsPort: false,
    logger: {
        logRequest: false
    },
    env: config.get<boolean>('production') ? Env.PROD : Env.DEV
})

@Romakita
Copy link
Collaborator

Hi @SavvasAmruthShivaprakash
How have you installed package? because the new package isn't available on npm right know ^^

@Romakita
Copy link
Collaborator

Finding an issue while implementing PR #2713. I am not able load playground after server start. my server configuration is as below and package and code changes are here

Your doc isn't public

@SavvasManteshPatil
Copy link

Finding an issue while implementing PR #2713. I am not able load playground after server start. my server configuration is as below and package and code changes are here

Your doc isn't public

updated the link please check now

@SavvasManteshPatil
Copy link

SavvasManteshPatil commented Aug 28, 2024

Hi @SavvasAmruthShivaprakash How have you installed package? because the new package isn't available on npm right know ^^

Have pulled the feature branch and built locally. referring @tsed/apollo,@tsed/typegraphql and @tsed/di packages from local directory by updating path in package.json

@Romakita
Copy link
Collaborator

Ok @SavvasAmruthShivaprakash I see. Your test wasn't executed in a normal condition, links modules can cause many errors due to the DI implement and javascript (node module resolutions). In your case, You haven't guarantees to have only one DI injector service imported in the code. And the branche has some ts issue (related to the last rebase).

So I prefer to fix ts issue on the branche and give RC version of the module to test correctly the new packages.

Se you. ;)

@Romakita
Copy link
Collaborator

@SavvasAmruthShivaprakash new packages are now available under v7.81.0-rc.1 ;) enjoy it!

@SavvasManteshPatil
Copy link

Hi @Romakita I have tried installing all packages from shared RC version, finding an issue while installing @tsed/apollo. attached error log below.

npm i --save @tsed/apollo@7.81.0-rc.1
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/@apollo%2fdatasource-http - Not found
npm error 404
npm error 404 '@apollo/datasource-http' is not in this registry.
npm error 404
npm error 404 Note that you can also install from a
npm error 404 tarball, folder, http url, or git url.
npm error A complete log of this run can be found in: C:\Users\mantesh.patil\AppData\Local\npm-cache_logs\2024-09-05T10_37_02_380Z-debug-0.log

@Romakita
Copy link
Collaborator

Romakita commented Sep 6, 2024

Ok I'll publish a new release to fix that :)

@Romakita Romakita mentioned this issue Sep 8, 2024
8 tasks
@Romakita
Copy link
Collaborator

Romakita commented Sep 8, 2024

@SavvasAmruthShivaprakash fixed and released :)

@SavvasManteshPatil
Copy link

Hi @Romakita I have tried implementing new package, can install packages and run the application. I am trying to alter context using $alterApolloContext hook like bellow.
$alterApolloContext(context: ApolloContext, $ctx: PlatformContext) {
return ({
...context,
authorization: $ctx.getRequest().headers.authorization,
userId: $ctx.getRequest().headers['user-id'],
orgId: $ctx.getRequest().headers['org-id'],
isAuthenticated: $ctx.getRequest().authenticated,
userScope: $ctx.getRequest().userScope,
error: $ctx.getRequest().error,
logger: $ctx.getRequest().logger
});
}

where server throwing an authentication error
"errors": [
{
"message": "Not authenticated.",
"path": [
//Query name
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"status": 500
}
}
],
"data": null
}

@Romakita
Copy link
Collaborator

@SavvasAmruthShivaprakash your stack error isn’t enougth to investigate. Can please create reproducible repo example?

@SavvasManteshPatil
Copy link

SavvasManteshPatil commented Sep 11, 2024

@Romakita Can you please have look at server.ts appended below and let me know any modification required. Basically it is failed to create the context.

import '@tsed/ajv';
import { Configuration, Constant, Inject, PlatformApplication, PlatformContext } from '@tsed/common';
import { Env } from '@tsed/core';
import { Logger } from '@tsed/logger';
import '@tsed/platform-express'; // /!\ keep this import
import '@tsed/typegraphql';
import bodyParser from 'body-parser';
import compress from 'compression';
import config from 'config';
import cookieParser from 'cookie-parser';
import cors from 'cors';
import { NextFunction } from 'express';
import methodOverride from 'method-override';

import { ApolloContext } from '@tsed/apollo';
import { GraphQLFormattedError } from 'graphql';
import { StatusCodes } from 'http-status-codes';
import { customAuthChecker } from './auth-checker/custom-auth.checker';
import { HealthCheckController } from './controllers/health-check.controller';
import { HelloController } from './controllers/helloController';
import { configureHttp, logAgentDetails } from './http/configure-http';
import { DEBUG_LOGGING, KEEP_ALIVE_OPTIONS } from './model/common/const';
import { CONFIG } from './services/config/config.provider';
import { LOGGER } from './utils/logger';

const rootDir = process.cwd();
const isStackTraceEnabled = process.env.STACK_TRACE_ENABLED === 'true';
const setHttpPlugin = {
    async requestDidStart() {
        return {
            async willSendResponse(Response: any): Promise<void> {
                const { response } = Response;
                const ErrorResponse = response?.errors?.[0]?.extensions;
                if (ErrorResponse) {
                    response.http.status = ErrorResponse?.response?.status || ErrorResponse?.status;
                }
            }
        };
    }
};

@Configuration({
    mount: {
        '/': [HealthCheckController, HelloController],
    },
    apollo: {
        server1: {
            path: '/graphql',
            includeStacktraceInErrorResponses: true,
            debug: isStackTraceEnabled,
            playground: true,
            resolvers: [
                //Resolvers List
            ],
            buildSchemaOptions: {
                authChecker: customAuthChecker,
                emitSchemaFile: true
            },
            plugins: [setHttpPlugin],
            formatError: (formattedError: GraphQLFormattedError, error: unknown) => {
                let extensions: any = {};
                if (formattedError.extensions && formattedError.extensions.code) {
                    let statusCode;
                    switch (formattedError.extensions.code) {
                        case 'INTERNAL_SERVER_ERROR':
                            statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
                            break;
                        case 'GRAPHQL_VALIDATION_FAILED':
                            statusCode = StatusCodes.BAD_REQUEST;
                            break;
                        case 'FORBIDDEN':
                            statusCode = StatusCodes.FORBIDDEN;
                            break;
                        default:
                            if (Number(formattedError.extensions.code) || formattedError.extensions.status) {
                                statusCode = formattedError.extensions?.status || formattedError.extensions?.code;
                            } else {
                                // Default to a sensible status code
                                statusCode = StatusCodes.BAD_REQUEST;
                                // Add a flag to indicate a malformed error
                                extensions.malformedError = true;
                            }
                    }
                    extensions = { ...extensions, code: formattedError.extensions.code, status: statusCode };
                }
                if (formattedError.extensions && formattedError.extensions.status) {
                    extensions = { ...extensions, status: formattedError.extensions.status };
                }
                if (formattedError.extensions && formattedError.extensions.response) {
                    extensions = { ...extensions, response: formattedError.extensions.response };
                }
                if (formattedError.extensions && formattedError.extensions.exception) {
                    let processedException = {};
                    if (formattedError.extensions.stacktrace) {
                        processedException = { stacktrace: formattedError.extensions.stacktrace };
                    }
                    extensions = { ...extensions, exception: processedException };
                }
                /**
                 * TODO: We might want to go in the path of doing error masking for some error messages,  
                 * to prevent leaking some internal information.
                 * https://learning.postman.com/open-technologies/blog/graphql-error-handling/
                 */
                return { message: formattedError.message, path: formattedError.path, extensions };
            }
        }
    },
    httpPort: config.get('port'),
    httpsPort: false,
    logger: {
        logRequest: false
    },
    env: config.get<boolean>('production') ? Env.PROD : Env.DEV
})

export class Server {

    @Inject()
    private readonly app: PlatformApplication;

    @Inject(LOGGER)
    private readonly logger: Logger;

    @Inject(CONFIG)
    private readonly config: any;

    @Constant("PLATFORM_NAME")
    platformName: string;

    $alterApolloContext(context: ApolloContext, $ctx: PlatformContext) {
        return ({
            ...context,
            authorization: $ctx.getRequest().headers.authorization,
            userId: $ctx.getRequest().headers['user-id'],
            orgId: $ctx.getRequest().headers['org-id'],
            isAuthenticated: $ctx.getRequest().authenticated,
            userScope: $ctx.getRequest().userScope,
            error: $ctx.getRequest().error,
            logger: $ctx.getRequest().logger
        });
    }

    public $beforeRoutesInit(): void {
        configureHttp(this.config.get(KEEP_ALIVE_OPTIONS));
        this.app
            .use(cors())
            .use(cookieParser())
            .use(compress({}))
            .use(methodOverride())
            .use(bodyParser.json())
            .use(
                bodyParser.urlencoded({
                    extended: true
                })
            )
            .use(async (req: any, res: Response, next: NextFunction) => {
                req.logger = this.logger;
                if (this.config.get(DEBUG_LOGGING)) {
                    logAgentDetails();
                }
                next();
            });
    }
}

@Romakita
Copy link
Collaborator

Romakita commented Sep 11, 2024

@SavvasAmruthShivaprakash Please create small repository to reproduce that ! and steps reproduction!

@SavvasManteshPatil
Copy link

@SavvasAmruthShivaprakash Please create small repository to reproduce that ! and steps reproduction!

I have created a repo @ https://github.com/ManteshP/tsed-sample.

@SavvasAmruthShivaprakash
Copy link
Author

@Romakita, Looks like issue is not resolved. It's just validating the query. I have reinstalled all the dependencies and checked it is failing to create the context since context value is undefined I am not able to access the data source supposed to be available the context.

"stacktrace": [
"TypeError: Cannot read properties of undefined (reading 'getStudentSessionUsage')",
" at StudentSessionUsageThisWeekResolver.getStudentSessionUsageThisWeek (C:\SA

@Romakita
Copy link
Collaborator

Romakita commented Sep 13, 2024

Yes but you haven’t given the step reproduction…

@Romakita
Copy link
Collaborator

Romakita commented Sep 13, 2024

Reproduced. Your issue occurs because, your datasource aren't imported in your code.

console.log('====> StudentSessionUsageService') // not displayed in terminal.

@DataSource()
export class StudentSessionUsageService extends BearerRestDataSource {}

Please take a time to fix that and push changes. You have a lot of imports issue in your reproducible repository. That's why I insist on having a repository with the minimum of code! You put too much and you have errors here and there (dependency problems, import problems and code problems), it makes debugging more complicated ;)
And for now, I have nothing to fix on my side :D

@SavvasManteshPatil
Copy link

SavvasManteshPatil commented Sep 13, 2024

@Romakita I revisited the code and observed that datasources are not imported, after some code correction it is working as expected. Thank you 👍

@SavvasManteshPatil
Copy link

SavvasManteshPatil commented Sep 26, 2024

@Romakita we have integrated v8.0.0-alpha.5 version and it's working as expected. As we see your roadmap you are moving from commonJs to esm syntax which is breaking change for us. Can you please release a tag version for v8.0.0-alpha.5.

@Romakita
Copy link
Collaborator

Hi @SavvasAmruthShivaprakash
What do you mean by "Can you please release a tag version for v8.0.0-alpha.5. ?"

@SavvasManteshPatil
Copy link

Hi @Romakita
I mean, could you provide a release for Apollo Server migration changes using CommonJS before transitioning to ESM syntax?

@Romakita
Copy link
Collaborator

Hi @SavvasAmruthShivaprakash

I can't publish v7 with Apollo 4, the package introduce breaking change. I won't plublish a v8 with cjs support.

So you have different solutions:

See you ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Review in progress
Development

No branches or pull requests

4 participants