Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 270 additions & 0 deletions docs/specs/v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
# PowerShellGallery v1 Specification

## Overview

`PowerShellGallery` is a PowerShell module for interacting with the [PowerShell Gallery](https://www.powershellgallery.com). Version 1 focuses on two publisher-oriented workflows:

1. **Discovery** — read package and API metadata from the public OData v2 endpoint.
2. **Listing management** — list and unlist package versions you own, using gallery API credentials.

This spec defines the public API, expected behavior, error handling, and testing strategy for the v1 release.

## Supported PowerShell version

Latest PowerShell Long-Term Support (LTS) release, per the PSModule module standard. Windows PowerShell 5.1 is not a v1 target.

## Out of scope for v1

- Installing, updating, or saving packages (covered by `PowerShellGet`).
- Publishing packages to the gallery.
- User or organization management.
- Admin-level gallery operations.
- Cross-gallery support (e.g., private NuGet feeds).

## Naming convention

Public nouns are prefixed with the module term of art: `PowerShellGallery`.

Existing stub names `Hide-PowerShellGalleryItem` and `Show-PowerShellGalleryItem` are renamed to use the more precise noun `Package`, with backward-compatible aliases retained for the v1 major release.

## Public API

### `Get-PowerShellGalleryAPI`

Get metadata from the PowerShell Gallery v2 API root.

#### Synopsis

```text
Get-PowerShellGalleryAPI [[-Uri] <string>] [<CommonParameters>]
```

#### Parameters

| Name | Type | Mandatory | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| `Uri` | `string` | No | `https://www.powershellgallery.com/api/v2/` | Base URI of the gallery OData endpoint. |

#### Behavior

- Performs an HTTP `GET` against the provided URI with `application/json` content negotiation.
- Returns the raw service response (commonly an OData service document / JSON).
- Throws a terminating error if the endpoint is unreachable or returns a non-success status code.

#### Example

```powershell
Get-PowerShellGalleryAPI
```

---

### `Find-PowerShellGalleryPackage`

Search for packages on the PowerShell Gallery.

#### Synopsis

```text
Find-PowerShellGalleryPackage [[-Name] <string>] [-Tag <string[]>] [-IncludePrerelease] [-First <uint>]
[-Skip <uint>] [-OrderBy <string>] [<CommonParameters>]
```

#### Parameters

| Name | Type | Mandatory | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| `Name` | `string` | No | `*` | Package ID or search term. Supports wildcards. |
| `Tag` | `string[]` | No | none | Filter to packages that declare all specified tags. |
| `IncludePrerelease` | `switch` | No | false | Include prerelease versions in results. |
| `First` | `uint` | No | `50` | Maximum number of results to return. Capped at `1000`. |
| `Skip` | `uint` | No | `0` | Number of results to skip for pagination. |
| `OrderBy` | `string` | No | `DownloadCount desc` | OData `$orderby` expression. |

#### Behavior

- Queries `https://www.powershellgallery.com/api/v2/Packages()`.
- Supports pipeline input for `Name`.
- Returns one object per package version by default.
- Use `Get-PowerShellGalleryPackage` when you need a single package/version.

#### Example

```powershell
Find-PowerShellGalleryPackage -Name 'Pester' -First 5
'Az.*' | Find-PowerShellGalleryPackage -First 10
```

---

### `Get-PowerShellGalleryPackage`

Get detailed metadata for a specific package and optionally a specific version.

#### Synopsis

```text
Get-PowerShellGalleryPackage [-Name] <string> [[-Version] <string>] [-IncludePrerelease]
[<CommonParameters>]
```

#### Parameters

| Name | Type | Mandatory | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| `Name` | `string` | Yes | — | Exact package ID. |
| `Version` | `string` | No | latest stable | Specific version to retrieve. Accepts NuGet version strings including prerelease labels. |
| `IncludePrerelease` | `switch` | No | false | When `Version` is omitted, return the latest prerelease instead of the latest stable. |

#### Behavior

- If `Version` is provided, queries `Packages(Id='{Name}',Version='{Version}')`.
- If `Version` is omitted, queries the package feed filtered by ID, ordered by published date, and returns the newest item.
- Throws a terminating error if the package or version does not exist.

#### Example

```powershell
Get-PowerShellGalleryPackage -Name 'Pester'
Get-PowerShellGalleryPackage -Name 'Pester' -Version '5.5.0'
```

---

### `Hide-PowerShellGalleryPackage`

Unlist a package version on the PowerShell Gallery.

#### Synopsis

```text
Hide-PowerShellGalleryPackage [-Name] <string> [-Version] <string> [-APIKey] <string>
[-WhatIf] [-Confirm] [<CommonParameters>]
```

#### Aliases

- `Unlist-PowerShellGalleryPackage`

#### Parameters

| Name | Type | Mandatory | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| `Name` | `string` | Yes | — | Exact package ID. |
| `Version` | `string` | Yes | — | Exact version to unlist. |
| `APIKey` | `string` | Yes | — | PowerShell Gallery API key for the package owner. |

#### Behavior

- Requires ownership of the package.
- Uses the gallery listing endpoint to mark the version as unlisted.
- Supports `-WhatIf` and `-Confirm` via `SupportsShouldProcess`.
- Writes a non-terminating warning if the operation is not yet implemented or the gallery endpoint is unavailable.

#### Example

```powershell
Hide-PowerShellGalleryPackage -Name 'MyModule' -Version '1.0.0' -APIKey $env:PSGalleryAPIKey
```

---

### `Show-PowerShellGalleryPackage`

List a package version on the PowerShell Gallery.

#### Synopsis

```text
Show-PowerShellGalleryPackage [-Name] <string> [-Version] <string> [-APIKey] <string>
[-WhatIf] [-Confirm] [<CommonParameters>]
```

#### Aliases

- `List-PowerShellGalleryPackage`

#### Parameters

| Name | Type | Mandatory | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| `Name` | `string` | Yes | — | Exact package ID. |
| `Version` | `string` | Yes | — | Exact version to list. |
| `APIKey` | `string` | Yes | — | PowerShell Gallery API key for the package owner. |

#### Behavior

- Requires ownership of the package.
- Uses the gallery listing endpoint to mark the version as listed.
- Supports `-WhatIf` and `-Confirm` via `SupportsShouldProcess`.

#### Example

```powershell
Show-PowerShellGalleryPackage -Name 'MyModule' -Version '1.0.0' -APIKey $env:PSGalleryAPIKey
```

## Private helpers

Private functions are grouped under `src/functions/private/Gallery/`.

| Function | Responsibility |
| -------- | -------------- |
| `Invoke-PowerShellGalleryAPI` | Shared REST wrapper: handles URI building, headers, content negotiation, timeout, and error translation. |
| `Get-PowerShellGalleryResource` | Generic OData resource GET (to be merged into or replaced by `Invoke-PowerShellGalleryAPI`). |
| `Update-PowerShellGalleryResourceListing` | Shared POST to the gallery listing endpoint used by `Hide`/`Show`. |

## Return types

Commands return plain objects deserialized from OData JSON by default. A future release may introduce typed output classes; v1 does not.

## Error handling

- Use `ErrorAction` semantics consistently.
- Wrap `Invoke-RestMethod` failures in descriptive error records where the gallery response adds useful context.
- Authentication or authorization failures from listing endpoints produce clear, actionable messages.
- Discovery commands must not throw on empty result sets; they return nothing.

## Authentication

- Read commands require no authentication.
- Listing-management commands require a PowerShell Gallery API key with ownership of the target package.
- The API key is passed via the `APIKey` parameter. Do not persist keys in the module; callers supply them per command.

## Logging and progress

- Emit `Verbose` output for URIs, pagination, and auth-skipping details.
- Emit `Warning` when a listing command cannot complete because the gallery endpoint is unavailable.
- Do not emit progress bars for simple HTTP calls.

## Testing

Follow the [PSModule Test Specification](https://psmodule.github.io/docs/Modules/Test-Specification/):

- No mocks; use real inputs and the public gallery endpoint.
- Test each public command with `Describe`/`Context`/`It` hierarchy.
- Discovery tests use well-known packages (e.g., `Pester`, `PowerShellGet`) to ensure stable results.
- Listing-management tests validate parameter binding and `-WhatIf` behavior; they do not mutate real packages.
- Code coverage target remains 50% as configured in `.github/PSModule.yml` for v1.

## Documentation

- Each public function has full comment-based help with synopsis, description, examples, and parameter help.
- A `<Group>.md` overview file is added alongside public functions.
- README is updated to describe v1 capabilities.

## Migration from current stubs

| Current file | v1 disposition |
| ------------ | -------------- |
| `Get-PSGalleryAPI.ps1` | Rename to `Get-PowerShellGalleryAPI.ps1`; keep URI default. |
| `Hide-PowerShellGalleryItem.ps1` | Rename to `Hide-PowerShellGalleryPackage.ps1`; add `Unlist-PowerShellGalleryPackage` alias. |
| `Show-PowerShellGalleryItem.ps1` | Rename to `Show-PowerShellGalleryPackage.ps1`; add `List-PowerShellGalleryPackage` alias. |
| `Get-PSGalleryResource.ps1` | Refactor into `Invoke-PowerShellGalleryAPI` or retain as private helper. |
| `Update-PSGalleryResourceListing.ps1` | Retain as private helper; fix auth and parameter handling. |

## Open questions

1. Does the gallery expose a stable, API-key-only listing endpoint, or do we need a full web-login + anti-forgery token flow?
2. Should `Find-PowerShellGalleryPackage` collapse multiple versions of the same package ID by default?
3. Should v1 include `Save-PowerShellGalleryPackage` (download `.nupkg`) or leave that to `PowerShellGet`?