Create a service

To create a service, you have to:

  1. Add the new service in packages/services/list.ts with the corresponding new unique port and name.

  2. Create a new package in the directory packages/services/.

  3. The new service's package.json should at least have this defined:

    {
    "name": "service-NEW_SERVICE_NAME",
    "version": "0.0.1",
    "private": true,
    "scripts": {
    "dev": "bob-tsm --node-env=dev --watch=src src/index.ts",
    "start": "bob-tsm src/index.ts"
    },
    "dependencies": {
    "api-base": "workspace:^0.0.1",
    "db": "workspace:^0.0.1"
    }
    }

    This will give the new service access to the db package, which has the database connection and related code, and the api-base package, which has useful shared code between services.

  4. The new service needs a tsconfig.json alongside the just created package.json. It should be defined like this:

This configuration extends the main typescript configuration but isolates the service types

{
"extends": "../../../tsconfig.json",
"include": ["**/*"],
"exclude": ["**/node_modules"]
}
  1. The new service's "src/index.ts" file should look something like this:

    import { baseServicesList, logger, pubSub, smartListen } from "api-base";
    import Fastify from "fastify";
    import { buildApp } from "./ez";
    // This creates the new web server
    const app = Fastify({
    logger,
    pluginTimeout: 30000,
    });
    // This builds the GraphQL EZ API
    const ezApp = buildApp({
    async prepare() {
    // This will add the new expected gql api modules
    await import("./modules/index");
    },
    });
    app.register(ezApp.fastifyPlugin);
    app.ready(async (err) => {
    if (err) {
    console.error(err);
    process.exit(1);
    }
    // This will listen on the expected port, considering development mode and environment variables.
    await smartListen(app, baseServicesList.NEW_SERVICE_NAME);
    // This will notify the gateway to re-introspect all the services, and detect possible changes
    pubSub.publish("updateGateway", "NEW_SERVICE_NAME");
    });
  2. The new service's "src/ez.ts" file should look something like this:

    import { CreateApp } from "@graphql-ez/fastify";
    import { ezServicePreset } from "api-base";
    // This created the new GraphQL EZ instance, re-using a service preset with tools like GraphQL Codegen, GraphQL Altair and GraphQL Voyager
    export const { buildApp, gql, registerModule } = CreateApp({
    ez: {
    preset: ezServicePreset,
    },
    });
    export * from "api-base";
  3. A new service module, let's call it "src/modules/foo.ts", should start looking like this:

    import { gql, registerModule } from "../ez";
    export const fooModule = registerModule(
    // This defines the types
    gql`
    extend type Query {
    foo: String!
    }
    `,
    {
    id: "Foo",
    dirname: import.meta.url,
    // This defines the resolvers associated with the defined types
    resolvers: {
    Query: {
    foo() {
    return "Foo!";
    },
    },
    },
    }
    );
  4. And a new file "src/modules/index.ts" should start looking like this:

    export * from "./foo";
  5. Update the root docker-compose.yaml to include the new service; you can follow the format of the existing services.