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

# Pagination

> Manual pagination and auto-pagination with AsyncGenerator in the Law4Devs TypeScript SDK.

## The `Page<T>` type

Every `list()` method returns a `Promise<Page<T>>`. The `Page<T>` object has three properties:

```typescript theme={null}
interface Page<T> {
  data: T[];           // items on the current page
  meta: PageMeta;      // totals and current position
  links: PageLinks;    // pre-built URLs for adjacent pages
}

interface PageMeta {
  total: number;       // total items across all pages
  page: number;        // current page number (1-based)
  perPage: number;     // items per page
  pages: number;       // total number of pages
  apiVersion: string;  // API version string
}

interface PageLinks {
  next: string | null; // URL of the next page, or null on the last page
  prev: string | null; // URL of the previous page, or null on the first page
}
```

***

## Manual pagination

Use `links.next` to detect when there are more pages and increment `page` manually.

```typescript theme={null}
let page = 1;
let total = 0;

while (true) {
  const result = await client.frameworks.list({ page, perPage: 10 });
  total += result.data.length;

  console.log(`Page ${result.meta.page}/${result.meta.pages}: ${result.data.length} items`);

  if (!result.links.next) break; // no more pages
  page++;
}

console.log(`Fetched ${total} frameworks in total`);
```

***

## Auto-pagination with `for await`

Every resource exposes an `iter()` method (or `iterDeadlines()` for compliance) that returns an `AsyncGenerator<T>`. Pages are fetched lazily — only when the current batch is exhausted.

```typescript theme={null}
// Frameworks
for await (const fw of client.frameworks.iter()) {
  console.log(fw.slug);
}

// Articles scoped to a framework
for await (const article of client.articles.iter('gdpr')) {
  console.log(`Art. ${article.articleNumber}: ${article.title}`);
}

// Compliance deadlines
for await (const deadline of client.compliance.iterDeadlines({ frameworkSlug: 'nis2' })) {
  console.log(deadline.description);
}
```

TypeScript infers the correct item type from the generator signature:

```typescript theme={null}
// article is typed as ArticleSummary — no cast needed
for await (const article of client.articles.iter('cra')) {
  const tags: Tag[] = article.tags; // fully typed
}
```

***

## Early exit

Because `iter()` is a lazy `AsyncGenerator`, breaking out of the loop stops further fetches immediately.

```typescript theme={null}
// Find the first article tagged 'security' — stop as soon as found
let found: ArticleSummary | undefined;

for await (const article of client.articles.iter('nis2')) {
  if (article.tags.some(t => t.slug === 'security')) {
    found = article;
    break; // no further pages are fetched
  }
}

if (found) {
  console.log(`First security article: Art. ${found.articleNumber}`);
}
```

***

## Controlling page size

Pass `perPage` to `iter()` or `list()` to tune the number of items fetched per HTTP request. Valid range is 1–100; default is 20.

```typescript theme={null}
// Fewer, larger pages — fewer HTTP requests
for await (const req of client.requirements.iter({
  frameworkSlug: 'gdpr',
  perPage: 100,
})) {
  // process requirement
}
```

<Tip>
  For large datasets, a higher `perPage` value reduces the number of HTTP round-trips. For interactive UIs where you want to display results quickly, a smaller `perPage` value returns the first items faster.
</Tip>

***

## Collecting all results into an array

```typescript theme={null}
async function collectAll<T>(gen: AsyncGenerator<T>): Promise<T[]> {
  const items: T[] = [];
  for await (const item of gen) {
    items.push(item);
  }
  return items;
}

const allFrameworks = await collectAll(client.frameworks.iter());
console.log(`${allFrameworks.length} total frameworks`);
```

<Warning>
  Collecting all results into memory with a helper like `collectAll` is convenient but be mindful of response size. For large resources such as requirements or articles across all frameworks, stream and process items one-by-one inside the `for await` loop instead.
</Warning>
