Search…
API

About

This project forms the basis of a unified API for products belonging to island.is.
It's built as a thin GraphQL layer on top of data and services provided by government organisations and island.is microservices, where each unit is wrapped in a domain.

URLs

  • Dev: N/A
  • Staging
  • Production: N/A

Project structure

The code in this app package should be kept as small as possible. Most business logic should be in domain libraries. Shared utilities and middlewares should be in libraries as well.

Domains

Domain libraries represent and wrap an underlying data model or service. As a rule of thumb, each microservice and government organisation should have their own domain library.
They can contain the following exports:
  • typeDefs: GraphQL schema describing the types, inputs, queries and mutations of the domain.
  • resolvers: Object containing GraphQL resolvers for any fields, queries and mutations as needed by the domain.
  • services: The domain can export arbitrary services for other domains. These should be strongly typed and not expose any internals of the domain.
The typeDefs and resolvers for all domains are merged into a single GraphQL server.
Generally, the resolvers should be really small. They should only manage the resolver arguments, including input and payload wrappers.
The actual resolver logic should be in service functions. These may call another domain's service, call external services and publish messages on exchanges.

Services

Services are classes that contain most of the logic for a domain. They should be easy to test and use dependency injection (DI) to get access to other services and connectors.
Currently, there is no DI container. Everything is hooked up manually in tests and /apps/api/src/graphql/context.

Type Generation

We use graphql-codegen to generate TypeScript types for all GraphQL schemas. We also generate type definitions for all resolvers, which provides strong typing for parent, input and context arguments as well as the return payload.
To gain these benefits, resolvers should be defined like this:
1
import { Resolvers } from '@island.is/api/schema'
2
3
export const resolvers: Resolvers = {
4
Person: {
5
application(person, input, context) {},
6
},
7
Query: {
8
allApplications(_, input, context) {},
9
},
10
}
Copied!
For more information, read the following article. It also explains how to specify a typed context as well as custom model types:
In addition, client apps can use graphql-codegen to join together the API schema with client operations. This validates that operations match the schema, and generates type definitions for operation inputs and payloads.

Shared libraries

For code that can be reused, consider adding it to a shared library. If it's specific to the API, it should be under /libs/api, otherwise consider making it available wider. Either way, we can start flat and refactor into subfoldres as the number of libraries grows.
Examples:
1
# Flat
2
/libs/api/middlewares
3
4
# Grouped
5
/libs/api/clients/cms
6
/libs/api/clients/x-road
7
/libs/api/utilities/graphql
Copied!

Fetch development secrets

Run AWS_PROFILE=<profile> yarn nx get-secrets <project>
Example:
1
AWS_PROFILE=islandis yarn nx get-secrets api
Copied!

Test requirements

This API has minimal logic and mostly wraps external services. Until we figure out an integration/contract testing strategy, the main focus is on unit tests using mocks for external dependencies.
There should be good test coverage on shared code and services. The resolvers are tricky to test so they should be kept simple, with the main logic in unit tested services.

Getting started

To start the API, run:
1
yarn start api
Copied!

Codegen

If you change a GraphQL schema, you need to update the generated TypeScript types which are used by resolvers and client applications:
1
yarn nx run api:schemas/codegen
Copied!

Tests

To run tests, you can either run all tests affected by your changes, or run tests in a specific project:
1
yarn affected:test
2
yarn test api
Copied!
Many jest arguments can be passed to test commands. For more details, add --help.
1
yarn test api --help
2
yarn test api --watch
3
yarn test api --updateSnapshots
4
yarn test api --runInBand
Copied!

New domain

You can create a new domain or shared library using an NX schematic:
1
yarn generate @nrwl/node:library api/domains/your-domain
2
yarn generate @nrwl/node:library api/your-library
Copied!
If your domain needs to expose fields in the GraphQL schema, make sure to export typeDefs and resolvers in your domain's index.ts, then add your domain to the list in /apps/spi/src/graphql/domains.ts.

Code owners and maintainers

  • Kosmos & Kaos: libs/cms, libs/api/domains/content-search
  • Aranja: libs/cms, libs/api/domains/application, libs/api/domains/content-search
  • Sendiráðið: libs/api/domains/documents, libs/api/domains/national-registry
  • Stefna: libs/api/domains/content-search
  • Advania libs/api/domains/api-catalogue
Last modified 3mo ago