How to use custom directives graphql-modules with apollo - graphql

I need help with custom directives when using graphql-modules library. Have no idea where to place my custom directives so it is combined with overall schema

I would like to post answer from Discord community, from user Maapteh.
here it the quote from him
in our app with old version we had everything in common module. We
kept that approach partly when using the latest version of modules.
See some parts of our codebase:
import { ApolloServer, SchemaDirectiveVisitor } from
'apollo-server-express';
const schema = AppModule.createSchemaForApollo();
SchemaDirectiveVisitor.visitSchemaDirectives(schema, {
isMember: IsMemberDirective,
deprecated: isDeprecated,
...SNIP... });
as you can see we create the schema we pass eventually to the apollo
server (example using apollo). We add our generic directives like so.
The schema for them is in our common module. Read further...
For common scalars we added a common module. With their schema (so in
schema directory we also have the directives schemas) and their
resolver.
const typeDefsArray = loadFilesSync(${__dirname}/schema/*.graphql, {
useRequire: true, }); const typeDefs = mergeTypeDefs(typeDefsArray, { useSchemaDefinition: false });
const resolverFunctions = {
ImageUrl: ImageUrlType,
PageSize: PageSizeType,
Date: DateResolver,
...SNIP... };
export const CommonModule = createModule({
id: 'common',
typeDefs: typeDefs,
resolvers: resolverFunctions, });
hope it helps you
https://discord.com/channels/625400653321076807/631489837416841253/832595211166548049

Related

How to get GraphQL document validation error before launching a server?

I have some schema with simple misuse cases like on the picture bellow.
I was able to get them only via this stupid idea running apollo-server, as this was the first time when I saw them, so it would perform validation on create.
const { ApolloServer } = require("apollo-server-express");
const { readFileSync } = require("fs");
const typeDefs = readFileSync(process.argv[2]).toString("utf-8");
try {
new ApolloServer({
typeDefs: typeDefs,
debug: true,
mockEntireSchema: true,
});
} catch (error) {
console.error(error.message);
process.exit(-1);
}
I wasn't really able to get any validation cli tool which can accept only SDL definition and do this simple syntax checks. Are there any? I'm just trying to build build pipeline and injecting as many as I can into compile time, rather than runtime. I mean, hack is working, but this is so weird that there is no ready solutions for that.
I also using graphql-codegen for typescript, but it just doesn't care and no errors are thrown. The tool is okay with interfaces being used in unions.
graphql-cli with it's validate requires document and schema, but it's doing a bit different kind of validation.

Vercel app with graphql-codegen endpoint error Unable to find any GraphQL type definitions for the following pointers

I load my GraphQL schema like:
const schema = loadSchemaSync('./src/graphql/server/schema/*.gql', {
loaders: [new GraphQLFileLoader()],
})
This works fine locally, however, when deploying to vercel I get the error:
Unable to find any GraphQL type definitions for the following pointers:
- ./src/graphql/server/schema/*.gql
I think this is because vercel is dropping the relevant files after build?
The problem is that you cannot use dynamic loaders in Vercel Serverless Functions.
A workaround for this problem is to use a inline GraphQL schema.
// src/graphql/schema.ts
import { gql } from "apollo-server-core";
export default gql`
type Query {
greet: String!
}
`;
// src/pages/api/graphql.ts
import { ApolloServerPluginLandingPageGraphQLPlayground } from "apollo-server-core";
import Schema from "../../graphql/schema";
const apolloServer = new ApolloServer({
typeDefs: Schema,
resolvers,
plugins: [ApolloServerPluginLandingPageGraphQLPlayground],
introspection: true,
});
If you are using tools like codegen:
// codegen.ts
import { CodegenConfig } from "#graphql-codegen/cli";
const config: CodegenConfig = {
schema: "src/graphql/schema.ts",
documents: ["./src/**/*.{ts,tsx}"],
ignoreNoDocuments: true,
generates: {
"src/graphql/types/server.ts": {
plugins: [
"#graphql-codegen/typescript",
"#graphql-codegen/typescript-resolvers",
],
},
"src/graphql/types/client/": {
preset: "client",
plugins: [],
},
},
};
export default config;

Spartacus Storefront Multisite I18n with Backend

We've run into some problems for our MultiSite Spartacus setup when doing I18n.
We'd like to have different translations for each site, so we put these on an API that can give back the messages dependent on the baseSite, eg: backend.org/baseSiteX/messages?group=common
But the Spartacus setup doesn't let us pass the baseSite? We can
pass {{lng}} and {{ns}}, but no baseSite.
See https://sap.github.io/spartacus-docs/i18n/#lazy-loading
We'd could do it by overriding i18nextInit, but I'm unsure how to achieve this.
In the documentation, it says you can use crossOrigin: true in the config, but that does not seem to work. The type-checking say it's unsupported, and it still shows uw CORS-issues
Does someone have ideas for these problems?
Currently only language {{lng}} and chunk name {{ns}} are supported as dynamic params in the i18n.backend.loadPath config.
To achieve your goal, you can implement a custom Spartacus CONFIG_INITIALIZER to will populate your i18n.backend.loadPath config based on the value from the BaseSiteService.getActive():
#Injectable({ providedIn: 'root' })
export class I18nBackendPathConfigInitializer implements ConfigInitializer {
readonly scopes = ['i18n.backend.loadPath']; // declare config key that you will resolve
readonly configFactory = () => this.resolveConfig().toPromise();
constructor(protected baseSiteService: BaseSiteService) {}
protected resolveConfig(): Observable<I18nConfig> {
return this.baseSiteService.getActive().pipe(
take(1),
map((baseSite) => ({
i18n: {
backend: {
// initialize your i18n backend path using the basesite value:
loadPath: `https://backend.org/${baseSite}/messages?lang={{lng}}&group={{ns}}`,
},
},
}))
);
}
}
and provide it in your module (i.e. in app.module):
#NgModule({
providers: [
{
provide: CONFIG_INITIALIZER,
useExisting: I18nBackendPathConfigInitializer,
multi: true,
},
],
/* ... */
})
Note: the above solution assumes the active basesite is set only once, on app start (which is the case in Spartacus by default).

prisma.yml could not be found

I am trying to generate schema for my prisma data model while at the same time using secrets to restrict prisma access. After running prisma delete and prisma deploy, I run the command graphql get-schema -p prisma and get the following error message:
✖ prisma/prisma.yml could not be found.
Is there something wrong I am doing in my .graphqlconfig or how I am listing my prisma.yml? Thanks.
.graphqlconfig:
{
"projects": {
"prisma": {
"schemaPath": "generated/prisma.graphql",
"extensions": {
"prisma": "prisma/prisma.yml",
"endpoints": {
"default": "http://localhost:4466"
}
}
}
}
}
prisma/prisma.yml:
endpoint: http://localhost:4466
datamodel: datamodel.prisma
secret: 'secretFoo'
index.js:
import http from 'http';
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import resolvers from './resolvers';
import schema from './generated/prisma.graphql';
import { Prisma } from 'prisma-binding';
const prisma = new Prisma({
endpoint: 'http://localhost:4466',
secret: 'secretFoo',
typeDefs: 'server/generated/prisma.graphql',
});
const server = new ApolloServer({
context: {
prisma,
},
resolvers,
typeDefs: schema,
});
const app = express();
server.applyMiddleware({ app });
const PORT = 5000;
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
httpServer.listen(PORT, () => {
console.log(`Server ready at http://localhost:${PORT}${server.graphqlPath}`);
console.log(`Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
});
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => server.stop());
}
You can generate a schema directly from your prisma.yml file, by adding the following to the file:
generate:
- generator: graphql-schema
output: ./generated/prisma.graphql
Then you can refer your .graphqlconfig to the generated file:
projects:
prisma:
schemaPath: generated/prisma.graphql
extensions:
endpoints:
dev: http://localhost:4466
You would generally restrict access to the management functionality of your endpoint through the Prisma docker-compose file (managementApiSecret in PRISMA_CONFIG). Then when you run commands like prisma deploy you would need to pass the appropriate environment variables through either the --env-file flag, or by having a dotenv file in the root of your application's directory (you also need the dotenv package installed in package.json.
Another way to secure your endpoint is to disable the GraphQL Playground altogether. I believe Apollo Server does this automatically when NODE_ENV is set to production, although you can do it explicitly with:
const server = new ApolloServer({
context: {
prisma,
},
resolvers,
typeDefs: schema,
playground: false, // <- Here
});
I'm sorry, I don't think this directly answered your question, but it may assist either way.

how to seperate schema and resolvers and merage them apollo-server-express

I have User and Post typeDefs/resolvers I want to separate them so I can get
User.schema.js
User.resolver.js
Post.schema.js
Post.resolver.js
link.Schema.js
link.resolvers.js
how to do this and merge them to get just one typeDefs/resolvers to pass it to
const server = new ApolloServer({
typeDefs,
resolvers
});
I have been using the merge-graphql-schemas package for the type definition and lodash deep object merge function for the resolvers like so:
import merge from "lodash/merge"
import { mergeTypes } from "merge-graphql-schemas"
import UserSchema from "./User.schema"
import UserResolvers from "./User.resolvers"
import PostSchema from "./Post.schema"
import PostResolvers from "./Post.resolvers"
import LinkSchema from "./Link.schema"
import LinkResolvers from "./Link.resolvers"
const typeDefs = mergeTypes([UserSchema, PostSchema, LinkSchema])
const resolvers = merge(UserResolvers, PostResolvers, LinkResolvers)
const server = new ApolloServer({
typeDefs,
resolvers
});
EDIT: please note that graphql-tools's mergeSchemas is now the recommended way of schema stitching with apollo server now.
There is no need for some more dependency for merging the types, as graphql-tools are fine for them.
Have a look https://github.com/techyaura/graphqlNodeMongodb-server/tree/master/src/gql, if it helps.
I have two files todo.types.js & user.type.js in the repo https://github.com/techyaura/graphqlNodeMongodb-server/tree/master/src/gql/types & I am simply concatenating them & that's working fine.
NOTE: I am not using APOLLO GRAPHQL, instead using express-graphql simply

Resources