> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fetchski-attract.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The SDK in AdonisJS

> The TypeScript SDK the AdonisJS way: one configure command, the client injected where you need it, faked in Japa in one line.

[AdonisJS](https://adonisjs.com) is to TypeScript what Laravel is to PHP: a complete, typed framework
with a container, providers, an ORM (Lucid), encryption, a command line (Ace) and a test runner (Japa)
built in. The `@fetchski/attract-cms-adonis` package fits the SDK into it: one `node ace configure`
and the client is in the container.

> [card] [@fetchski/attract-cms-adonis for AdonisJS 7](https://docs.fetchski-attract.com/adonisjs/installation.md)
>
> The same SDK as the TypeScript tab · Node 26.12.1+ · Lucid, Ace and Japa

```ts Call it theme={"dark"}
import { inject } from '@adonisjs/core'
import type { HttpContext } from '@adonisjs/core/http'
import { SiteClient } from '@fetchski/attract-cms-sdk'

@inject()
export default class BlogPostsController {
  constructor(protected site: SiteClient) {}

  async show({ params }: HttpContext) {
    return this.site.blogPosts().getBlog({ id: params.id })
  }
}
```

```ts Test it theme={"dark"}
import { test } from '@japa/runner'
import { fakeAttract } from '@fetchski/attract-cms-adonis/testing'

test('shows a post', async ({ client }) => {
  const site = fakeAttract()

  await client.get('/blog/example-id')

  site.assertCalled('blogPosts.getBlog')
})
```

## Why AdonisJS

> [card] One command to set up
>
> `node ace configure` asks for the URL and key, then writes the config, `.env` and provider.

> [card] One client, injected
>
> The package puts `SiteClient` in the container; `@inject()` hands it to controllers, services
> and jobs.

> [card] Keys kept secret
>
> `Env.schema.secret()` prints as `[redacted]`; with `--database`, the key is sealed under your
> `APP_KEY`.

> [card] Ace commands
>
> `attract:check`, `attract:sweep`, `attract:store-key`, and a REPL with the client loaded.

> [card] Background work
>
> Queue jobs, schedules and a cache that keeps serving when the site is down.

> [card] Japa fakes
>
> `fakeAttract()` fakes every call the app makes, restored after each test.

## The guides

**1. Installation**

The package from your own site, then `node ace configure`. [Install →](https://docs.fetchski-attract.com/adonisjs/installation.md)

**2. Configuration**

`config/attract.ts`, the default site, and more sites. [Configure →](https://docs.fetchski-attract.com/adonisjs/configuration.md)

**3. Key in the database**

The key sealed in a table, stored with one Ace command. [Store it →](https://docs.fetchski-attract.com/adonisjs/key-in-database.md)

**4. Calling the API**

Controllers, routes, validation, uploads and errors. [Make calls →](https://docs.fetchski-attract.com/adonisjs/calling-the-api.md)

**5. Testing, Ace and background work**

[Testing](https://docs.fetchski-attract.com/adonisjs/testing.md) · [Ace commands](https://docs.fetchski-attract.com/adonisjs/ace-commands.md) · [Jobs, cache and health](https://docs.fetchski-attract.com/adonisjs/background-work.md)

> [!NOTE]
>
> Everything the SDK itself does (models, paging, retries, error classes, keeping keys secret) is the same
> as in plain TypeScript, and the [TypeScript tab](https://docs.fetchski-attract.com/typescript/overview.md) explains it in full. The package
> adds the AdonisJS parts: the config file, the container, the Ace commands and the fakes. Not using AdonisJS? The TypeScript tab works in any
> Node or Bun app.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.