diff --git a/src/docs/Modules/Module-Types.md b/src/docs/Modules/Module-Types.md new file mode 100644 index 0000000..be97843 --- /dev/null +++ b/src/docs/Modules/Module-Types.md @@ -0,0 +1,106 @@ +# Module types + +Most PSModule modules fall into one of a few archetypes. The general rules in +[PowerShell module standard](Standards.md) and [PowerShell Standards](../PowerShell/Standard/index.md) always apply; this +page adds the conventions that are specific to a module's type so that modules of the same kind feel +the same to use. + +Two archetypes have enough shared shape to standardize: + +- **Integration (API) modules** wrap an external service's REST or GraphQL API. +- **Data modules** convert or manage a data format or in-memory structure. + +A module can be both (for example, an integration module that also exposes conversion helpers). +Apply each relevant section. + +## Integration (API) modules + +Integration modules are the PowerShell face of an external service. `GitHub`, and the +service-client modules such as `Anthropic`, `OpenAI`, `Bluesky`, and `Domeneshop`, are integration +modules. + +### Command naming maps to the resource, not the HTTP method + +Name commands after the resource and the intent, using approved verbs. Never name a command after +the HTTP method or the endpoint path. Map REST methods to verbs: + +| REST method | PowerShell verb | Example | +| ----------- | --------------- | ------- | +| `GET` | `Get-` | `Get-GitHubRepository` | +| `POST` (create) | `New-` / `Add-` | `New-GitHubRepository` | +| `PUT` / `PATCH` (update) | `Set-` / `Update-` | `Set-GitHubRepository` | +| `DELETE` | `Remove-` | `Remove-GitHubRepository` | +| Non-CRUD action | Approved verb for the intent | `Invoke-`, `Start-`, `Stop-`, `Enable-`, ... | + +Prefix the noun with the service's term of art (`GitHubRepository`, not `Repository`). + +### Transport abstraction + +Lower-level helpers own the concrete `Invoke-RestMethod` / GraphQL / HTTP calls. How you expose +or hide this abstraction is a design choice: + +- **Private transport** (common): Keep REST, GraphQL, and HTTP helpers private. Public functions + accept resolved inputs and typed objects. This follows the Dependency Inversion rule from + [Standards](Standards.md#solid-applied) applied to the network boundary. +- **Public transport**: Expose REST or GraphQL functions publicly for power users or module + composition. +- **Public Context**: Expose the `Context` module as public so users can configure and manage + module state, secrets, and settings directly. + +Choose the strategy that best serves your module's audience. + +### Use Context for user and module settings + +Integration modules persist state with the [`Context`](https://github.com/PSModule/Context) module +rather than inventing bespoke storage. Context provides on-disk storage for user data and secrets, +organized by context and environment. Two kinds of state are both standard: + +- **User settings and secrets**: accounts, tokens, sessions, and per-user configuration. Store these + in a per-user context. `Context` encrypts secrets at rest (via `Sodium`), so a user can resume work + without reconfiguring or logging in again when the service supports session refresh. +- **Module settings**: module-wide defaults, endpoints, and feature flags that are not tied to a + single user. Store these in a module-scoped context. + +Your module must expose functions and object types so users can target specific contexts and +environments. Users need to be able to read from, write to, and manage contexts programmatically, +selecting which environment or context their functions operate against. Persisting both through +`Context` gives every integration module the same, discoverable settings model and keeps secrets +out of source, logs, and plain files. + +## Data modules + +Data modules convert between representations or manage an in-memory structure. `Hashtable` is the +reference shape; `Base64`, `Json`, `Lua`, `Hcl`, `Sodium`, and `Uri` follow the same pattern. + +### The neutral object is the pivot + +Every conversion goes through the neutral PowerShell object model +(`[PSCustomObject]` / `[hashtable]` / `[PSObject]`). `ConvertFrom-` parses a +format-specific representation into an object; `ConvertTo-` renders an object into the +format. Converting through the object as a common pivot means any format interoperates with any +other, instead of writing a direct converter for every pair. + +Always ship both directions so data can round-trip between the format and the object model. + +### Verb vocabulary + +| Verb pattern | Purpose | +| ------------ | ------- | +| `ConvertFrom-` | Format-specific text/representation → `[PSCustomObject]` / `[hashtable]` | +| `ConvertTo-` | `[PSCustomObject]` / `[hashtable]` → format-specific text/representation | +| `Import-` | Read from a file or store into objects | +| `Export-` | Write objects to a file or store | +| `Format-` | Produce a normalized or pretty rendering | +| `Merge-` | Combine two structures | +| `Compare-` | Diff two structures | +| `Test-` | Validate a value or structure | +| `Remove-Entry` | Remove elements by criteria | + +The `Hashtable` module demonstrates the full set: `ConvertFrom-Hashtable`, `ConvertTo-Hashtable`, +`Import-Hashtable`, `Export-Hashtable`, `Format-Hashtable`, `Merge-Hashtable`, and +`Remove-HashtableEntry`. + +## Where this connects + +- [PowerShell module standard](Standards.md): layout, private functions, and the mandatory context parameter. +- [Repository Defaults](Repository-Defaults.md): repository files, README shape, and agent onboarding. diff --git a/src/docs/Modules/Repository-Defaults.md b/src/docs/Modules/Repository-Defaults.md index 3575b76..066f06b 100644 --- a/src/docs/Modules/Repository-Defaults.md +++ b/src/docs/Modules/Repository-Defaults.md @@ -2,7 +2,7 @@ This page defines the default repository contract for PowerShell module repositories in the PSModule organization. It describes what a newly created or maintained module repository should look like before module-specific code, tests, documentation, and managed repository files are considered. -The implementation standard still lives in [PowerShell module standard](Standards.md). This page covers repository defaults: files, metadata, README shape, release integration, placeholder handling, shared community files, and managed-file distribution. +The implementation standard still lives in [PowerShell module standard](Standards.md). Type-specific conventions for integration (API) and data modules live in [Module types](Module-Types.md). This page covers repository defaults: files, metadata, README shape, release integration, placeholder handling, shared community files, and managed-file distribution. ## Scope diff --git a/src/docs/Modules/index.md b/src/docs/Modules/index.md index 8c458df..2989ec8 100644 --- a/src/docs/Modules/index.md +++ b/src/docs/Modules/index.md @@ -13,6 +13,7 @@ This section is the local source of truth for: - [Repository Defaults](Repository-Defaults.md) - [Standards](Standards.md) +- [Module types](Module-Types.md) - [Test Specification](Test-Specification.md) - [Versioning](Versioning.md) - [Catalog](Catalog/index.md) diff --git a/src/zensical.toml b/src/zensical.toml index 24f5553..7894e6f 100644 --- a/src/zensical.toml +++ b/src/zensical.toml @@ -21,6 +21,7 @@ nav = [ "Modules/index.md", {"Repository Defaults" = "Modules/Repository-Defaults.md"}, {"Standards" = "Modules/Standards.md"}, + {"Module types" = "Modules/Module-Types.md"}, {"Test Specification" = "Modules/Test-Specification.md"}, {"Versioning" = "Modules/Versioning.md"}, {"Catalog" = [