# XLibrary Plugin SDK

Typed contracts and deterministic test tools for `.xlplugin` packages.

Full documentation is available in [`docs/README.md`](./docs/README.md). Start
with `templates/game-source-plugin` for a game provider, or use
`templates/plugin-reference` as a reference for every public capability.

## Create a runnable starter

Requirements: Node.js 20+ and pnpm 10+ (npm/npx works as well).

```sh
mkdir my-xlibrary-plugin
cd my-xlibrary-plugin
pnpm dlx @xlibrary/plugin-sdk create .
pnpm install
pnpm test
pnpm demo
pnpm package
```

The generator creates `manifest.json`, `src/index.ts`, a contract test,
`tsconfig.json`, and the build/demo/package scripts. `pnpm demo` runs the
compiled plugin through the SDK test host and prints a sample search and resolve
result without opening XLibrary or making a real network request. `pnpm package`
creates `dist/<plugin-id>-<version>.xlplugin`, ready to install from XLibrary →
Plugins.

The same generator can be run with `npx @xlibrary/plugin-sdk create .` or
`pnpx @xlibrary/plugin-sdk create .`.

## Install

```sh
pnpm add -D @xlibrary/plugin-sdk
```

The SDK is a development dependency. A packaged plugin must contain its own
compiled JavaScript entry; imports marked with `import type` are erased during
the build and do not add a runtime dependency on the SDK.

## Start with the game-source template

Copy `templates/game-source-plugin` into a new directory, replace the package
metadata and source hosts, then run:

```sh
pnpm install
pnpm test
pnpm build
zip -r my-plugin.xlplugin manifest.json runtime
```

To copy the complete reference template:

```sh
cp -R node_modules/@xlibrary/plugin-sdk/templates/plugin-reference my-plugin
```

Install the resulting `.xlplugin` through **Plugins → Install plugin** in
XLibrary. The application validates the manifest, requires explicit permission
approval, and runs the entry module in an isolated runtime.

## Test without XLibrary

```ts
import {createPluginTestHost, runGameSourceSearch} from '@xlibrary/plugin-sdk/testing';
import plugin from '../src/index.js';

const host = createPluginTestHost();
const result = await runGameSourceSearch(
  plugin,
  {sourceId: 'catalog', query: 'example', limit: 20},
  host,
);
```

The test host records calls, controls time and validates the result shape, so
plugin authors can test provider behavior without starting Electron.

When a plugin returns an invalid provider result, the test helpers throw
`PluginContractValidationError`. Its `issues` array contains the exact field
path, stable error code, message, and (when useful) a correction hint.

The [`docs/`](./docs/) directory covers the manifest, runtime API, contributions,
testing, security, and the release checklist.
