# DongneLibrary API Reference

A JavaScript/TypeScript library for checking book availability across 190+ Korean public library branches.

## Installation

```bash
npm install dongnelibrary
```

## Quick Start

```javascript
import dongnelibrary from "dongnelibrary";

dongnelibrary.search(
  { title: "해리포터", libraryName: "판교도서관" },
  (err, result) => {
    if (err) return console.error(err.msg);
    console.log(`Found ${result.totalBookCount} books`);
    result.booklist.forEach((book) => {
      console.log(`${book.title} - ${book.exist ? "대출가능" : "대출중"}`);
    });
  },
);
```

## API

### search(options, onResult?, onComplete?)

Search for books across one or more libraries.

#### Parameters

| Parameter    | Type                     | Required | Description                       |
| ------------ | ------------------------ | -------- | --------------------------------- |
| `options`    | `SearchOptionsMain`      | Yes      | Search configuration              |
| `onResult`   | `SearchCallback`         | No       | Called for each library's results |
| `onComplete` | `SearchCompleteCallback` | No       | Called when all searches complete |

#### SearchOptionsMain

| Property      | Type                 | Required | Description                                         |
| ------------- | -------------------- | -------- | --------------------------------------------------- |
| `title`       | `string`             | Yes      | Book title to search (Korean or English)            |
| `libraryName` | `string \| string[]` | Yes      | Library name(s). Use `''` or `[]` for all libraries |
| `signal`      | `AbortSignal`        | No       | For cancelling in-progress searches                 |

#### Example: Single Library

```javascript
dongnelibrary.search(
  { title: "코스모스", libraryName: "판교도서관" },
  (err, result) => {
    if (result) {
      console.log(result.booklist);
    }
  },
);
```

#### Example: Multiple Libraries

```javascript
dongnelibrary.search(
  { title: "코스모스", libraryName: ["판교", "분당"] },
  (err, result) => {
    // Called once per library
    if (result) {
      console.log(`${result.libraryName}: ${result.totalBookCount} books`);
    }
  },
  (err, results) => {
    // Called once when all searches complete
    console.log(`Total libraries searched: ${results.length}`);
  },
);
```

#### Example: All Libraries

```javascript
dongnelibrary.search({ title: "해리포터", libraryName: "" }, (err, result) => {
  if (result) {
    console.log(`${result.libraryName}: ${result.booklist.length} results`);
  }
});
```

#### Example: With AbortSignal

```javascript
const controller = new AbortController();

dongnelibrary.search(
  { title: "해리포터", libraryName: "", signal: controller.signal },
  (err, result) => {
    /* ... */
  },
  (err, results) => {
    /* ... */
  },
);

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
```

---

### searchAsync(options, onResult?)

Promise-based search for books across one or more libraries.

#### Parameters

| Parameter  | Type                | Required | Description                       |
| ---------- | ------------------- | -------- | --------------------------------- |
| `options`  | `SearchOptionsMain` | Yes      | Search configuration              |
| `onResult` | `SearchCallback`    | No       | Called for each library's results |

#### Returns

`Promise<SearchResult[]>` - Array of search results from all libraries

#### Example: Basic Usage

```javascript
const results = await dongnelibrary.searchAsync({
  title: "해리포터",
  libraryName: "판교도서관",
});

results.forEach((result) => {
  console.log(`${result.libraryName}: ${result.totalBookCount} books`);
});
```

#### Example: Search All Libraries

```javascript
const results = await dongnelibrary.searchAsync({
  title: "코스모스",
  libraryName: "",
});

console.log(`Found results in ${results.length} libraries`);
```

#### Example: With Streaming Callback

```javascript
const results = await dongnelibrary.searchAsync(
  { title: "해리포터", libraryName: "" },
  (err, result) => {
    // Called as each library completes
    if (result) {
      console.log(`${result.libraryName}: ${result.booklist.length} books`);
    }
  },
);

// Final results available after all searches complete
console.log(`Total: ${results.length} libraries searched`);
```

#### Example: With AbortSignal

```javascript
const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  const results = await dongnelibrary.searchAsync({
    title: "해리포터",
    libraryName: "",
    signal: controller.signal,
  });
} catch (err) {
  console.log("Search was cancelled");
}
```

---

### getAllLibraryNames()

Returns an array of all supported library branch names.

#### Returns

`string[]` - Array of library names (190+ branches)

#### Example

```javascript
const libraries = dongnelibrary.getAllLibraryNames();
console.log(libraries);
// ['경기중앙교육도서관', '경기평택교육도서관', '경기광주교육도서관', ...]
```

---

### getModuleHomeUrls()

Returns a mapping of library system module names to their home URLs.

#### Returns

`Record<string, string>` - Object mapping module names to URLs

#### Example

```javascript
const urls = dongnelibrary.getModuleHomeUrls();
console.log(urls);
// {
//   '경기교육통합도서관': 'https://lib.goe.go.kr',
//   '군포시도서관': 'https://www.gunpolib.go.kr',
//   ...
// }
```

---

### getAllModuleNames()

Returns an array of all library system module names.

#### Returns

`string[]` - Array of module names

#### Example

```javascript
const modules = dongnelibrary.getAllModuleNames();
console.log(modules);
// ['경기교육통합도서관', '군포시도서관', '성남시도서관', ...]
```

---

### getLibraryNamesInModule(moduleName)

Returns an array of library branch names belonging to a specific module.

#### Parameters

| Parameter    | Type     | Required | Description              |
| ------------ | -------- | -------- | ------------------------ |
| `moduleName` | `string` | Yes      | Module name to look up   |

#### Returns

`string[]` - Array of library branch names in the module

#### Example

```javascript
const libs = dongnelibrary.getLibraryNamesInModule("성남시도서관");
console.log(libs);
// ['논골도서관', '중원어린이도서관', '성남중앙도서관', '분당도서관', ...]
```

---

### resolveLibraryCount(libraryName)

Returns the number of libraries that will be searched for the given name(s).

#### Parameters

| Parameter     | Type                 | Required | Description                                         |
| ------------- | -------------------- | -------- | --------------------------------------------------- |
| `libraryName` | `string \| string[]` | Yes      | Library name(s). Use `''` for all libraries         |

#### Returns

`number` - Number of libraries that will be searched

#### Example

```javascript
dongnelibrary.resolveLibraryCount("");            // 193 (all libraries)
dongnelibrary.resolveLibraryCount("성남시도서관"); // 18 (all branches in module)
dongnelibrary.resolveLibraryCount("판교도서관");   // 1
```

---

### isModuleName(name)

Checks if a given name is a library system module name.

#### Parameters

| Parameter | Type     | Required | Description   |
| --------- | -------- | -------- | ------------- |
| `name`    | `string` | Yes      | Name to check |

#### Returns

`boolean` - `true` if the name is a module name

#### Example

```javascript
dongnelibrary.isModuleName("성남시도서관"); // true
dongnelibrary.isModuleName("판교도서관"); // false (branch name, not module name)
```

---

## Types

### SearchResult

Returned for each library search.

```typescript
interface SearchResult {
  title?: string; // Search query
  libraryName?: string; // Library branch name
  homeUrl?: string; // Library website URL
  totalBookCount: number | string; // Total matching books
  startPage?: number; // Pagination start
  booklist: Book[]; // Array of found books
}
```

### Book

Individual book information.

```typescript
interface Book {
  libraryName: string; // Library where book is located
  title: string; // Book title
  exist: boolean; // true = available, false = checked out
  bookUrl?: string; // Direct link to book detail page
}
```

### SearchError

Error object returned on failure.

```typescript
interface SearchError {
  msg: string; // Error message
}
```

### Callback Types

```typescript
// Called for each library result
type SearchCallback = (err: SearchError | null, result?: SearchResult) => void;

// Called when all searches complete
type SearchCompleteCallback = (
  err: SearchError | null,
  results?: SearchResult[],
) => void;
```

---

## Supported Library Systems

| Module   | Library System                 | Region            |
| -------- | ------------------------------ | ----------------- |
| `gg`     | 경기교육통합도서관             | Gyeonggi Province |
| `gunpo`  | 군포시도서관                   | Gunpo City        |
| `hscity` | 화성시립도서관                 | Hwaseong City     |
| `ice`    | 인천광역시교육청통합공공도서관 | Incheon City      |
| `osan`   | 오산시도서관                   | Osan City         |
| `snlib`  | 성남시도서관                   | Seongnam City     |
| `suwon`  | 수원시도서관                   | Suwon City        |
| `yjlib`  | 여주시립도서관                 | Yeoju City        |
| `yongin` | 용인시도서관                   | Yongin City       |
| `jeju`   | 제주시도서관                   | Jeju City         |

Use `getAllLibraryNames()` to see all 190+ individual branch names.

---

## CLI Usage

```bash
# Interactive mode (default - no arguments needed)
npx dongnelibrary

# Interactive mode (explicit)
npx dongnelibrary -i

# List all libraries grouped by module
npx dongnelibrary -a

# Search specific library
npx dongnelibrary -t "해리포터" -l "판교도서관"

# Quick search with combined query
npx dongnelibrary -q "판교 해리포터"

# Search multiple libraries
npx dongnelibrary -q "판교,정자 해리포터"
```

The interactive mode prompts for book title first, then lets you choose a search scope:
- Search all libraries
- Search by library system (10 modules)
- Search by library name (autocomplete)

See `dongnelibrary --help` for all options.

---

## TypeScript Support

The package includes TypeScript declarations. Import types directly:

```typescript
import dongnelibrary, {
  SearchResult,
  SearchError,
  SearchOptionsMain,
  SearchCallback,
  SearchCompleteCallback,
  Book,
} from "dongnelibrary";
```

---

## Error Handling

```javascript
dongnelibrary.search(
  { title: "책제목", libraryName: "알수없는도서관" },
  (err, result) => {
    if (err) {
      console.error("Search failed:", err.msg);
      // Common errors:
      // - "Unknown library name"
      // - "invalid Data response"
      // - Network/timeout errors
      return;
    }
    // Process result...
  },
);
```

---

## License

MIT
