An Nx library and NPM package for defining and interacting with Apolitical API endpoints, designed to streamline development with consistent contracts and robust type safety.
ℹ️Note that @apolitical/contracts
has been recently refactored to follow the RFC for consolidating contracts. Please refer to the RFC for more info on the new structure.
@apolitical/contracts
provides:
- Unified API contracts: Standardized TypeScript definitions for API endpoints
- Developer-friendly structure: A simplified and intuitive folder layout
- Type safety: Ensures reliable and predictable API interactions
For more on the underlying technology, check out ts-rest.
The new structure would look like this:
/src
/apis
/mgmt-api
/accounts
accounts.contract.ts
connections.contract.ts
index.ts
mgmt-api.contract.ts
mgmt-api.types.ts
index.ts
// more APIs here
/ts
/i18n
i18n.constants.ts
i18n.enums.ts
i18n.types.ts
// more files here
/zod
/extensions
index.ts
index.ts
Briefly:
-
/src/apis
contains the contracts for each API -
/src/ts
contains the shared types, enums and constants -
/src/zod
contains the shared zod extensions
Let’s imagine you have to create a new endpoint POST /images
within the assets-api
, so then the steps to create the contract for that new endpoint are as follows:
- Locate the
assets-api
at/backend/v2/libs/contracts/src/apis/assets-api
- Given that the
Image
is a new resource withinassets-api
, we create aimages.contract.ts
file (as described here) - Implement
images
subcontract with it’s newcreate
method (as described here) - Add the
images
subcontract to theassets
top-contract atassets-api.contract.ts
file - Expose any shared types at
assets-api.types.ts
- If there is a shared enum, define it at
assets-api.enums.ts
- If there is a shared constant, define it at
assets-api.constants.ts
- If there is a shared enum, define it at
Let’s imagine you have to create a new endpoint POST /learners/:id/images
within the assets-api
, so then the steps to create the contract for that new endpoint are as follows:
- Locate the
assets-api
at/backend/v2/libs/contracts/src/apis/assets-api
- If the
learners
folder doesn’t exist create one (note that thelearners
folder is created to encapsulate thelearners.contract.ts
and theimages.contract.ts
as theimages
contract is a subcontract oflearners
). - Follow the steps describe above, but exposing the subcontracts in right order of hierarchy, in this case
assets
→learners
→images
We follow the Nest.js integration guide to integrate with Nest.js endpoints. In particular, we use the @TsRestHandler
decorator to define the handler for the endpoint as we are progressing towards a fully ts-rest-fied Nest.js setup.
We follow the ts-rest client guide to consume the client on the frontend. In particular, we use the Fetch Client to interact with the APIs from the frontend. This means that 4/5xx status codes will not throw an error, so you must check for these codes explicitly.
Run nx build contracts
to build the library.
Run nx test contracts
to execute the unit tests via Jest.
From the root of contracts run
node add-locale.js --locale <localeCode> --englishName <EnglishName> --nativeName <nativeName> --flag <flag>
for example
node add-locale.js --locale sv --englishName "Swedish" --nativeName "Svenska" --flag "🇸🇪"