# Packages API

## Endpoints

### List Packages

```
GET /api/v1/packages/{owner}
```

**Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `type` | string | Filter by package type |
| `q` | string | Search keyword |
| `page` | integer | Page number (1-based) |
| `limit` | integer | Page size |

```bash
# List all packages for an owner
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Filter by type
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}?type=npm" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Search packages
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}?q=utils&type=generic" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Paginated
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}?page=1&limit=20" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

---

### Get Package Version

```
GET /api/v1/packages/{owner}/{type}/{name}/{version}
```

```bash
# Get a specific npm package version
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}/npm/{name}/{version}" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Get a generic package version
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}/generic/{name}/{version}" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Get a container image version
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}/container/{name}/latest" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Get a PyPI package version
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}/pypi/{name}/{version}" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

---

### Delete Package Version

```
DELETE /api/v1/packages/{owner}/{type}/{name}/{version}
```

```bash
# Delete a specific version
curl -s -X DELETE "${FORGEJO_URL}/api/v1/packages/{owner}/generic/{name}/{version}" \
  -H "Authorization: token ${FORGEJO_PAT}"

# Delete an npm package version
curl -s -X DELETE "${FORGEJO_URL}/api/v1/packages/{owner}/npm/{name}/{version}" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

---

### List Package Version Files

```
GET /api/v1/packages/{owner}/{type}/{name}/{version}/files
```

```bash
curl -s "${FORGEJO_URL}/api/v1/packages/{owner}/generic/{name}/{version}/files" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

**Response:**

```json
[
  {
    "id": 1,
    "size": 10485760,
    "name": "{filename}",
    "hash_md5": "d41d8cd98f00b204e9800998ecf8427e",
    "hash_sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "hash_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "hash_sha512": "cf83e1357..."
  }
]
```

---

### Link Package to Repository

```
POST /api/v1/packages/{owner}/{type}/{name}/-/link/{repo_name}
```

```bash
curl -s -X POST "${FORGEJO_URL}/api/v1/packages/{owner}/npm/{name}/-/link/{repo}" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

---

### Unlink Package from Repository

```
POST /api/v1/packages/{owner}/{type}/{name}/-/unlink
```

```bash
curl -s -X POST "${FORGEJO_URL}/api/v1/packages/{owner}/npm/{name}/-/unlink" \
  -H "Authorization: token ${FORGEJO_PAT}"
```

---

## Supported Package Types

| Type | Description | Registry Protocol |
|------|-------------|-------------------|
| `cargo` | Rust packages | Cargo registry |
| `chef` | Chef cookbooks | Chef Supermarket |
| `composer` | PHP packages | Composer/Packagist |
| `conan` | C/C++ packages | Conan |
| `conda` | Conda packages | Conda |
| `container` | OCI container images | Docker/OCI |
| `cran` | R packages | CRAN |
| `debian` | Debian packages | APT |
| `generic` | Generic file storage | HTTP upload |
| `go` | Go modules | Go module proxy |
| `helm` | Kubernetes charts | Helm |
| `maven` | Java packages | Maven |
| `npm` | JavaScript packages | npm |
| `nuget` | .NET packages | NuGet |
| `pub` | Dart/Flutter packages | pub.dev |
| `pypi` | Python packages | PyPI |
| `rpm` | RPM packages | RPM/DNF |
| `rubygems` | Ruby gems | RubyGems |
| `swift` | Swift packages | Swift Package Registry |
| `vagrant` | Vagrant boxes | Vagrant Cloud |

---

## Package Upload Examples

Packages are uploaded through their native registry protocols, not the REST API. Configure your package manager to use Forgejo as the registry.

### Generic Package Upload

```bash
# Upload a generic package file
curl -s -X PUT \
  "${FORGEJO_URL}/api/packages/{owner}/generic/{name}/{version}/{filename}" \
  -H "Authorization: token ${FORGEJO_PAT}" \
  --upload-file ./{filename}
```

### npm Package

```bash
# Configure npm to use Forgejo registry
npm config set @{owner}:registry "${FORGEJO_URL}/api/packages/{owner}/npm/"
npm config set -- "//${FORGEJO_URL#https://}/api/packages/{owner}/npm/:_authToken" "${FORGEJO_PAT}"

# Publish
npm publish
```

### PyPI Package

```bash
# Upload with twine
TWINE_USERNAME=__token__ TWINE_PASSWORD="${FORGEJO_PAT}" \
  twine upload --repository-url "${FORGEJO_URL}/api/packages/{owner}/pypi" dist/*
```

### Container Image

```bash
# Login to container registry
echo "${FORGEJO_PAT}" | docker login "${FORGEJO_URL#https://}" -u {username} --password-stdin

# Tag and push
docker tag {name}:latest "${FORGEJO_URL#https://}/{owner}/{image}:v1.0.0"
docker push "${FORGEJO_URL#https://}/{owner}/{image}:v1.0.0"
```

### Maven Package

Configure `~/.m2/settings.xml`:

```xml
<servers>
  <server>
    <id>forgejo</id>
    <configuration>
      <httpHeaders>
        <property>
          <name>Authorization</name>
          <value>token ${FORGEJO_PAT}</value>
        </property>
      </httpHeaders>
    </configuration>
  </server>
</servers>
```

### Helm Chart

```bash
# Package and push a Helm chart
helm package ./my-chart
curl -s -X PUT \
  "${FORGEJO_URL}/api/packages/{owner}/helm/api/charts" \
  -H "Authorization: token ${FORGEJO_PAT}" \
  --upload-file my-chart-0.1.0.tgz
```

---

## Package Object

```json
{
  "id": 1,
  "owner": {
    "id": 1,
    "login": "{owner}"
  },
  "repository": null,
  "creator": {
    "id": 2,
    "login": "admin"
  },
  "type": "generic",
  "name": "{name}",
  "version": "v1.0.0",
  "created_at": "2024-03-15T10:00:00Z",
  "html_url": "https://{FORGEJO_HOST}/{owner}/-/packages/generic/{name}/{version}"
}
```
