Am updating my nest js apollo federation and am getting this error.
/Users/leonlishenga/Documents/code/omnivoltaic/nest/microservices/microservices-apigateway/node_modules/@apollo/gateway/src/supergraphManagers/IntrospectAndCompose/index.ts:118
throw Error(
^
Error: A valid schema couldn't be composed. The following composition errors were found:
[accounts-microservice] Type "Distributor" is an extension type, but there is no type definition for "Distributor" in any subgraph.
[accounts-microservice] Type "Item" is an extension type, but there is no type definition for "Item" in any subgraph.
[accounts-microservice] Type "AssetAccount" is an extension type, but there is no type definition for "AssetAccount" in any subgraph.
[accounts-microservice] Type "Person" is an extension type, but there is no type definition for "Person" in any subgraph.
[accounts-microservice] Type "CreditAccount" is an extension type, but there is no type definition for "CreditAccount" in any subgraph.
[auth-microservice] Type "AuthenticationInstance" is an extension type, but there is no type definition for "AuthenticationInstance" in any subgraph.
[auth-microservice] Type "Roles" is an extension type, but there is no type definition for "Roles" in any subgraph.
[auth-microservice] Type "Distributor" is an extension type, but there is no type definition for "Distributor" in any subgraph.
[auth-microservice] Type "Organization" is an extension type, but there is no type definition for "Organization" in any subgraph.
[auth-microservice] Type "Servicer" is an extension type, but there is no type definition for "Servicer" in any subgraph.
[auth-microservice] Type "Supplier" is an extension type, but there is no type definition for "Supplier" in any subgraph.
[auth-microservice] Type "AuthenticationSubInstance" is an extension type, but there is no type definition for "AuthenticationSubInstance" in any subgraph.
[auth-microservice] Type "SubRoles" is an extension type, but there is no type definition for "SubRoles" in any subgraph.
[auth-microservice] Type "SubRolePermissions" is an extension type, but there is no type definition for "SubRolePermissions" in any subgraph.
[client-microservice] Type "Supplier" is an extension type, but there is no type definition for "Supplier" in any subgraph.
[client-microservice] Type "Roles" is an extension type, but there is no type definition for "Roles" in any subgraph.
[client-microservice] Type "Servicer" is an extension type, but there is no type definition for "Servicer" in any subgraph.
[client-microservice] Type "AuthenticationInstance" is an extension type, but there is no type definition for "AuthenticationInstance" in any subgraph.
[client-microservice] Type "Organization" is an extension type, but there is no type definition for "Organization" in any subgraph.
[client-microservice] Type "Person" is an extension type, but there is no type definition for "Person" in any subgraph.
[client-microservice] Type "Distributor" is an extension type, but there is no type definition for "Distributor" in any subgraph.
[client-microservice] Type "SubRoles" is an extension type, but there is no type definition for "SubRoles" in any subgraph.
[client-microservice] Type "ItemFleet" is an extension type, but there is no type definition for "ItemFleet" in any subgraph.
[client-microservice] Type "ItemSKU" is an extension type, but there is no type definition for "ItemSKU" in any subgraph.
[thing-microservice] Type "ItemFleet" is an extension type, but there is no type definition for "ItemFleet" in any subgraph.
[thing-microservice] Type "Distributor" is an extension type, but there is no type definition for "Distributor" in any subgraph.
[thing-microservice] Type "Supplier" is an extension type, but there is no type definition for "Supplier" in any subgraph.
[thing-microservice] Type "ItemSKU" is an extension type, but there is no type definition for "ItemSKU" in any subgraph.
[thing-microservice] Type "Item" is an extension type, but there is no type definition for "Item" in any subgraph.
[thing-microservice] Type "Shipment" is an extension type, but there is no type definition for "Shipment" in any subgraph.
at IntrospectAndCompose.createSupergraphFromSubgraphList (/Users/leonlishenga/Documents/code/omnivoltaic/nest/microservices/microservices-apigateway/node_modules/@apollo/gateway/src/supergraphManagers/IntrospectAndCompose/index.ts:118:13)
This is how my schema looks for the Distributor entity class extension in the Account Microservice
import { Directive, ObjectType, Field, ID } from '@nestjs/graphql';
import { ObjectId } from 'bson';
import { AssetAccount } from 'src/account/entities/assetAccount.entity';
@ObjectType()
@Directive('@extends')
@Directive('@key(fields: "_id")')
export class Distributor {
@Field((type) => ID)
@Directive('@external')
_id: ObjectId;
@Field((type) => [AssetAccount], { name: 'assetAccount', nullable: true })
assetAccount?: AssetAccount;
}
In the service that owns the Distributor entity it looks like this
import { Entity, EntityRepositoryType, Enum, Property } from '@mikro-orm/core';
import { Directive, Field, ObjectType } from '@nestjs/graphql';
import { ItemFleet } from '../federation/entities/itemfleet.reference';
import { ItemSKU } from '../federation/entities/itemsku.reference';
import { DistributorRepository } from '../repositories/distributor.repository';
import { Org } from './org.entity';
import * as bcrypt from 'bcryptjs';
import { ObjectId } from 'bson';
import { PERMISSIONS } from '../enums/permissions.enum';
import { AuthenticationInstance } from '../federation/entities/authentication-instance.reference';
import { Roles } from '../federation/entities/roles.reference';
// Distributor is an instantiated object class
// This resource class can be edited and used
// by different applications and services
// A distributor is a specific type of Org
// Properties of a distributor include
// products, the SKUs that this distributor can sell, and
// fleets: each fleet is a list of unique item
@ObjectType()
@Directive('@key(fields: "_id")')
@Entity({
tableName: 'distributor',
customRepository: () => DistributorRepository,
})
export class Distributor extends Org {
[EntityRepositoryType]?: DistributorRepository;
// Standard information sets of a Distributor:
// default org type is OrgTypes.DISTRIBUTOR
// default org contact person should be CEO
// Distribution related information
// itemSKU type is to be federated from the thing-microservice
// @Field()
public products: [ItemSKU];
// itemFleet type is to be federated from the thing-microservice
// @Field()
public fleets: [ItemFleet];
@Field((type) => AuthenticationInstance, {
name: 'authenticationInstance',
nullable: true,
})
// @ManyToOne({ mapToPk: true })
@Property({ persist: true })
public activeAuthenticationInstanceId!: ObjectId;
@Field((type) => PERMISSIONS, { nullable: true })
@Enum()
public activeSubRolePermission: PERMISSIONS;
@Field((type) => Roles, { name: 'role', nullable: true })
// @ManyToOne({ mapToPk: true, nullable: true })
@Property({ persist: true })
public roleId?: ObjectId;
@Property({ persist: true })
public password: string;
@Field({ nullable: true })
@Property({ persist: true, nullable: true })
public mqtt_password: string;
@Property({ persist: true })
public salt: string;
public perms: any[];
async getUserRole(): Promise<string> {
if (this.roleId != null) {
// console.log(this.roleId)
// const role = await getModelForClass(Roles).findOne({ _id: this.roleId }).exec()
return 'Trial';
} else {
return null;
}
}
async validatePassword(password: string): Promise<boolean> {
const hash = await bcrypt.hash(password, this.salt);
return hash === this.password;
}
}
The Org that it extends to looks like this
import { Embedded, Entity, Enum, OneToOne, Property } from '@mikro-orm/core';
import { Field, InterfaceType } from '@nestjs/graphql';
import { OrgTypes } from '../enums/org-types.enum';
import { Address } from './address.entity';
import { BaseEntity } from './base.entity';
import { Person } from './person.entity';
// Actor class of objects can "act". e.g. create an event, or send a message
// All actors must extend from this class to be able to act!
@InterfaceType()
@Entity({ abstract: true })
export abstract class Org extends BaseEntity {
// This is used for certain event consequences, and for filtering
@Field((type) => OrgTypes)
@Enum({ items: () => OrgTypes, default: OrgTypes.DISTRIBUTOR })
public type: OrgTypes;
// Actor's name
// This is inherited by all sub-classes
@Field()
@Property({ default: 'OVES Distributor' })
public name: string;
// Actor's profile
// This is inherited by all sub-classes
@Field({ nullable: true })
@Property({ default: 'Standard PAYG Distribution Established in 2021' })
public description: string;
// Below is address of an Org embedded
@Field((type) => Address)
@Embedded(() => Address, { object: true })
public orgAddress: Address;
@Field((type) => Person, { nullable: true })
@OneToOne({ entity: () => Person })
public orgContactPerson: Person;
public contactRole: string; // e.g. CEO
}
With the BaseEntity looking like this
import { Directive, Field, ID, InterfaceType } from '@nestjs/graphql';
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
import { ObjectId } from '@mikro-orm/mongodb';
@InterfaceType()
@Directive('@key(fields: "_id")')
@Entity({
abstract: true,
})
export abstract class BaseEntity {
@Field(() => ID)
@PrimaryKey()
public _id!: ObjectId;
@Field((type) => Boolean, { nullable: true })
@Property({ default: false })
public deleteStatus: boolean;
@Field({ nullable: true })
@Property({ nullable: true })
public deleteAt: Date;
@Field({ nullable: true })
@Property({ onCreate: () => new Date() })
public createdAt: Date;
@Field({ nullable: true })
@Property({ onUpdate: () => new Date(), onCreate: () => new Date() })
public updatedAt: Date;
}
The gateway for the two subgraphs looks like this
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { LoggerModule, PinoLogger } from 'nestjs-pino';
import { GatewayModule } from './gateway/gateway.module';
import { GraphQLError, GraphQLFormattedError } from 'graphql';
import { IntrospectAndCompose } from '@apollo/gateway';
import { ApolloGatewayDriverConfig, ApolloGatewayDriver } from '@nestjs/apollo';
import { GraphQLModule } from '@nestjs/graphql';
@Module({
imports: [
ConfigModule.forRoot(),
LoggerModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
pinoHttp: {
safe: true,
// prettyPrint: configService.get<string>('NODE_ENV') !== 'production',
},
}),
inject: [ConfigService],
}),
GatewayModule,
GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
server: {
// ... Apollo server options
cors: true,
context: ({ req }) => ({
authorization: req.headers.authorization,
universe: req.headers.universe,
}),
},
gateway: {
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{
name: 'thing-microservice',
url: 'http://localhost:3101/graphql',
},
{
name: 'client-microservice',
url: 'http://localhost:3001/graphql',
},
{
name: 'event-microservice',
url: 'http://localhost:3002/graphql',
},
// {
// name: 'ecommerce-microservice',
// url: 'http://ecommerce-microservice-alb-1340537921.eu-central-1.elb.amazonaws.com/graphql',
// },
{
name: 'auth-microservice',
url: 'http://localhost:3010/graphql',
},
{
name: 'accounts-microservice',
url: 'http://localhost:3011/graphql',
},
],
}),
},
}),
],
})
export class AppModule {}
I have just taken a snapshot of two subgraphs i.e account-microservice and client-microservice. My question is this, what could be causing this error or issue? I can't seem to solve it.
My Package.json for the gateway looks like this
{
"name": "microservice-apigateway",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@apollo/gateway": "2.0.5",
"@nestjs/apollo": "10.0.17",
"@nestjs/axios": "^0.1.0",
"@nestjs/common": "9.0.1",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "9.0.1",
"@nestjs/graphql": "10.0.18",
"@nestjs/platform-express": "9.0.1",
"apollo-server-express": "3.9.0",
"graphql": "16.5.0",
"graphql-tools": "8.3.0",
"graphql-upload": "^12.0.0",
"nestjs-pino": "^3.1.1",
"reflect-metadata": "0.1.13",
"rimraf": "3.0.2",
"rxjs": "7.5.5",
"ts-morph": "15.1.0"
},
"devDependencies": {
"@nestjs/cli": "9.0.0",
"@nestjs/schematics": "9.0.1",
"@nestjs/testing": "9.0.1",
"@types/express": "4.17.13",
"@types/jest": "28.1.4",
"@types/node": "18.0.3",
"@types/supertest": "2.0.12",
"@typescript-eslint/eslint-plugin": "5.30.5",
"@typescript-eslint/parser": "5.30.5",
"eslint": "8.19.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-prettier": "4.2.1",
"jest": "28.1.2",
"prettier": "2.7.1",
"supertest": "6.2.4",
"ts-jest": "28.0.5",
"ts-loader": "9.3.1",
"ts-node": "10.8.2",
"tsconfig-paths": "4.0.0",
"typescript": "4.7.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
Anyone who can help me with this I will appreciate it greatly.