Skip to content
Merged
Show file tree
Hide file tree
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
55 changes: 55 additions & 0 deletions content/fpm/how-to/publish/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Publish a package

Use this guide when you already have a package directory and need to publish it to an FPM registry.

## Before you publish

The target directory must contain `package.json`. FPM requires a scoped package name and a valid version. The package name and version identify the release, so increment the version before publishing a new release of the same package.

Review the package boundary before uploading. The `files` field limits the archive to matching entries; when it is absent, FPM considers files not excluded by `.gitignore`. FPM always includes `package.json`, and it excludes `.git`, `node_modules`, and other ignored metadata. Only regular files can be published.

## Preview the archive

Run a dry run from the package directory:

```bash
fpm publish --dry-run
```

To preview another directory, pass its path:

```bash
fpm publish ./packages/widget --dry-run
```

A dry run performs local packing and validation but does not acquire an upload session, upload bytes, or commit a release.

## Publish to a selected registry

The configured registry is used by default. Override it for one invocation with `--registry`:

```bash
fpm publish ./packages/widget --registry https://registry.example.com/v1
```

The token is resolved from `FPM_TOKEN` first and then from the local configuration created by `fpm login`. A command-line registry override changes the endpoint for that invocation; it does not rewrite the saved registry configuration.

## Use JSON output in automation

Use `--json` when a pipeline needs to consume the result:

```bash
FPM_TOKEN="$FPM_PUBLISH_TOKEN" fpm publish ./packages/widget --json
```

The JSON result contains `name`, `version`, `tarball`, and `sha256`. Keep the token in the CI secret store and expose it only to the publishing step. Do not commit FPM configuration files or tokens to source control.

## Understand the upload sequence

FPM first sends the package name, version, and SHA-256 checksum to the registry to acquire an upload session. It then uploads the gzip archive to the returned upload URL and commits the session with the normalized manifest. Registry API requests use JSON and include the token as a Bearer authorization header when a token is configured.

If a network or registry error is retryable, the upload step may be retried once. A successful publish prints the package identifier, tarball URL, and checksum. Save the checksum with the release metadata when you need to verify the uploaded archive later.

## Troubleshoot common failures

If FPM reports that no token is configured, run `fpm login` or set `FPM_TOKEN`. If the manifest name is rejected, change it to a scoped name such as `@example/widget`. If the version is invalid, use a valid Semantic Version. If a file is missing from the archive, check both the `files` field and `.gitignore` rules.
55 changes: 55 additions & 0 deletions content/fpm/how-to/publish/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 发布包

当你已经有一个包目录,并需要将它发布到 FPM 注册表时,可以使用本指南。

## 发布前检查

目标目录必须包含 `package.json`。FPM 要求包名带作用域,并且版本号有效。包名和版本共同标识一个发布版本,因此同一个包发布新版本前需要先递增版本号。

发布前请检查包的边界。`files` 字段会将归档限制为匹配的条目;未设置该字段时,FPM 会考虑未被 `.gitignore` 排除的文件。FPM 始终包含 `package.json`,并排除 `.git`、`node_modules` 以及其他被忽略的元数据。只有普通文件可以被发布。

## 预览归档

在包目录中执行 dry-run:

```bash
fpm publish --dry-run
```

如果要预览其他目录,可以传入目录路径:

```bash
fpm publish ./packages/widget --dry-run
```

dry-run 会执行本地打包和验证,但不会获取上传会话、上传字节或提交发布版本。

## 发布到指定注册表

默认使用已配置的注册表。可以使用 `--registry` 为单次执行覆盖注册表:

```bash
fpm publish ./packages/widget --registry https://registry.example.com/v1
```

令牌会优先从 `FPM_TOKEN` 读取;如果没有设置,则使用 `fpm login` 写入的本地配置。命令行传入的注册表只影响当前执行,不会改写已保存的注册表配置。

## 在自动化环境中使用 JSON 输出

流水线需要读取结果时,请使用 `--json`:

```bash
FPM_TOKEN="$FPM_PUBLISH_TOKEN" fpm publish ./packages/widget --json
```

JSON 结果包含 `name`、`version`、`tarball` 和 `sha256`。请将令牌保存到 CI 的密钥存储中,并仅在发布步骤中注入。不要把 FPM 配置文件或令牌提交到源代码仓库。

## 了解上传流程

FPM 首先向注册表发送包名、版本和 SHA-256 校验和,以获取上传会话。随后,它将 gzip 归档上传到返回的 URL,并使用规范化后的包清单提交会话。注册表 API 请求使用 JSON;配置了令牌时,请求会将令牌放在 Bearer authorization header 中。

如果网络或注册表错误可重试,上传步骤最多会重试一次。发布成功后会输出包标识符、归档 URL 和校验和。如果之后需要验证上传的归档,可以将校验和保存到发布元数据中。

## 排查常见错误

如果 FPM 报告没有配置令牌,请执行 `fpm login` 或设置 `FPM_TOKEN`。如果包名校验失败,请改为 `@example/widget` 这样的带作用域名称。如果版本无效,请使用符合 Semantic Version 的版本号。如果归档缺少文件,请同时检查 `files` 字段和 `.gitignore` 规则。
24 changes: 24 additions & 0 deletions content/fpm/overview/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# FPM package publishing

FPM is a package registry and command-line publishing tool for source packages. It helps package authors validate a package, create a deterministic archive, upload it to an FPM registry, and commit the published manifest.

## Choose a path

| If you want to... | Start here |
| :--- | :--- |
| Install FPM and publish your first package | [Get started](../tutorials/getting-started) |
| Publish an existing package from a specific directory | [Publish a package](../how-to/publish) |
| Check every command and option | [CLI reference](../reference/cli) |
| Understand the package and upload workflow | [CLI reference](../reference/cli#publish) |

FPM is designed to be installed globally. After installation, use the `fpm` command directly instead of invoking the generated JavaScript file with Node.js.

## What FPM publishes

FPM reads the `package.json` in the target directory. The package must have a scoped name, such as `@example/widget`, and a valid Semantic Version. The archive includes the package manifest and the files selected by the manifest and `.gitignore` rules. Workspace dependency ranges are normalized before the manifest is committed.

The publish operation uses a short-lived upload session: FPM acquires an upload URL, uploads the compressed archive with its SHA-256 checksum, and commits the manifest. The registry token is sent as a Bearer token and is stored locally with restrictive file permissions when you use `fpm login`.

## Documentation model

This module separates learning, task completion, and lookup. The tutorial gives a complete first-run path, the how-to guide focuses on publishing an existing package, and the reference describes command syntax and behavior. This separation follows the user-needs model described by [Diátaxis](https://diataxis.fr/) and the task-oriented navigation principles used by [Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/information-architecture-principles).
24 changes: 24 additions & 0 deletions content/fpm/overview/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# FPM 包发布工具

FPM 是一个包注册表和命令行发布工具,面向源代码包作者。它可以验证包、生成确定性的压缩归档、将归档上传到 FPM 注册表,并提交已发布的包清单。

## 选择文档路径

| 你想要…… | 从这里开始 |
| :--- | :--- |
| 安装 FPM 并发布第一个包 | [快速上手](../tutorials/getting-started) |
| 从指定目录发布已有包 | [发布包](../how-to/publish) |
| 查看全部命令和选项 | [CLI 参考](../reference/cli) |
| 了解包和上传流程 | [CLI 参考:publish](../reference/cli#publish) |

FPM 设计为全局安装。安装完成后,直接使用 `fpm` 命令即可,不需要再通过 Node.js 显式执行生成的 JavaScript 文件。

## FPM 发布什么内容

FPM 会读取目标目录中的 `package.json`。包名必须是带作用域的名称,例如 `@example/widget`,版本号必须符合 Semantic Version 规范。归档包含包清单,以及由清单和 `.gitignore` 规则选中的文件。提交清单前,workspace 依赖范围会被规范化。

发布过程使用短期上传会话:FPM 先获取上传 URL,再使用 SHA-256 校验和上传压缩归档,最后提交包清单。注册表令牌会作为 Bearer token 发送;使用 `fpm login` 时,令牌会以严格的本地文件权限保存。

## 文档组织方式

本模块将学习、完成任务和查找信息分开:教程提供完整的首次使用路径,操作指南聚焦发布已有包,参考页描述命令语法与行为。这种划分参考了 [Diátaxis](https://diataxis.fr/) 的用户需求模型,以及 [Microsoft Learn 信息架构原则](https://learn.microsoft.com/en-us/sharepoint/information-architecture-principles) 中以用户任务和可查找性为中心的导航方式。
74 changes: 74 additions & 0 deletions content/fpm/reference/cli/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# FPM CLI reference

The global executable is `fpm`. Run `fpm help` to print the current command summary.

## Commands

| Command | Purpose |
| :--- | :--- |
| `fpm login [--registry <url>]` | Save a registry and personal access token locally. |
| `fpm logout` | Remove the saved token while retaining the registry setting. |
| `fpm whoami` | Query the registry for the authenticated user. |
| `fpm config` | Print the configured registry and whether a token is present. The token itself is never printed. |
| `fpm publish [directory] [options]` | Pack and publish a package. The directory defaults to `.`. |

## `publish`

```text
fpm publish [directory] [--dry-run] [--json] [--registry <url>]
```

The command reads `package.json`, validates the scoped name and Semantic Version, packs the selected files, and publishes the archive. `directory` is optional and defaults to the current working directory.

| Option | Behavior |
| :--- | :--- |
| `--dry-run` | Pack and validate locally without contacting the registry. |
| `--json` | Print the result as one JSON object instead of human-readable lines. |
| `--registry <url>` | Use a registry URL for this invocation. |
| `--help`, `-h` | Print help. |
| `--version`, `-v` | Print the CLI version after a command has been selected. |

A successful human-readable result contains the package identifier, tarball URL, and SHA-256 checksum:

```text
Published @example/widget@1.0.0
Tarball: https://registry.example.com/v1/packages/@example/widget/1.0.0.tgz
SHA-256: <hexadecimal checksum>
```

The JSON form contains these keys:

```json
{
"name": "@example/widget",
"version": "1.0.0",
"tarball": "https://registry.example.com/v1/packages/@example/widget/1.0.0.tgz",
"sha256": "<hexadecimal checksum>"
}
```

## Configuration

The registry and token are resolved using the following precedence:

| Value | Precedence |
| :--- | :--- |
| Registry | `--registry` for `publish`, then `FPM_REGISTRY`, then the saved configuration. |
| Token | `FPM_TOKEN`, then the saved configuration. |

`fpm login` writes the configuration to `fpm/config.json` below the platform configuration directory. On systems that set `XDG_CONFIG_HOME`, FPM uses `$XDG_CONFIG_HOME/fpm/config.json`; otherwise it uses the user's platform configuration directory. The file is written with mode `0600`.

## Package requirements

A publishable package must have a `package.json` with a scoped `name` and a valid `version`. The packer includes `package.json`, respects the `files` field, applies `.gitignore` exclusions, excludes `.git` and `node_modules`, and rejects non-regular files. Workspace dependency ranges are rewritten to publishable version ranges when a workspace root can be found.

## Runtime and installation

Install the CLI globally with npm or pnpm:

```bash
npm install --global @fuyeor/fpm-cli
pnpm add --global @fuyeor/fpm-cli
```

The package exposes `dist/cli.js` as the `fpm` binary through `package.json#bin`. The published package is built during packing, so consumers do not need the repository or TypeScript toolchain installed.
74 changes: 74 additions & 0 deletions content/fpm/reference/cli/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# FPM CLI 参考

全局可执行命令为 `fpm`。运行 `fpm help` 可以输出当前命令摘要。

## 命令

| 命令 | 作用 |
| :--- | :--- |
| `fpm login [--registry <url>]` | 在本地保存注册表和个人访问令牌。 |
| `fpm logout` | 删除已保存的令牌,但保留注册表设置。 |
| `fpm whoami` | 向注册表查询当前已认证用户。 |
| `fpm config` | 输出已配置的注册表以及是否存在令牌;不会输出令牌本身。 |
| `fpm publish [directory] [options]` | 打包并发布包;目录默认为 `.`。 |

## `publish`

```text
fpm publish [directory] [--dry-run] [--json] [--registry <url>]
```

该命令读取 `package.json`,验证带作用域的包名和 Semantic Version,打包选中的文件,并发布归档。`directory` 是可选参数,默认为当前工作目录。

| 选项 | 行为 |
| :--- | :--- |
| `--dry-run` | 只在本地打包和验证,不访问注册表。 |
| `--json` | 将结果输出为单个 JSON 对象,而不是人类可读的多行文本。 |
| `--registry <url>` | 为本次执行使用指定的注册表 URL。 |
| `--help`、`-h` | 输出帮助。 |
| `--version`、`-v` | 在选定命令后输出 CLI 版本。 |

成功执行后的人类可读输出包含包标识符、归档 URL 和 SHA-256 校验和:

```text
Published @example/widget@1.0.0
Tarball: https://registry.example.com/v1/packages/@example/widget/1.0.0.tgz
SHA-256: <hexadecimal checksum>
```

JSON 输出包含以下字段:

```json
{
"name": "@example/widget",
"version": "1.0.0",
"tarball": "https://registry.example.com/v1/packages/@example/widget/1.0.0.tgz",
"sha256": "<hexadecimal checksum>"
}
```

## 配置

注册表和令牌按以下优先级解析:

| 值 | 优先级 |
| :--- | :--- |
| 注册表 | `publish` 的 `--registry`,然后是 `FPM_REGISTRY`,最后是已保存的配置。 |
| 令牌 | `FPM_TOKEN`,然后是已保存的配置。 |

`fpm login` 会将配置写入平台配置目录下的 `fpm/config.json`。设置了 `XDG_CONFIG_HOME` 的系统使用 `$XDG_CONFIG_HOME/fpm/config.json`;否则使用当前用户的平台配置目录。文件以 `0600` 模式写入。

## 包要求

可发布的包必须有一个包含带作用域 `name` 和有效 `version` 的 `package.json`。打包器会包含 `package.json`,遵循 `files` 字段,应用 `.gitignore` 排除规则,排除 `.git` 和 `node_modules`,并拒绝非普通文件。当能够找到 workspace 根目录时,workspace 依赖范围会被改写为可发布的版本范围。

## 运行时与安装

使用 npm 或 pnpm 全局安装 CLI:

```bash
npm install --global @fuyeor/fpm-cli
pnpm add --global @fuyeor/fpm-cli
```

该包通过 `package.json#bin` 将 `dist/cli.js` 暴露为 `fpm` 命令。发布包会在打包阶段构建,因此使用者不需要克隆仓库,也不需要安装 TypeScript 工具链。
37 changes: 37 additions & 0 deletions content/fpm/structure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"title": {
"zh-hans": "FPM 包发布工具",
"en": "FPM Package Publishing"
},
"description": {
"zh-hans": "FPM 包注册表与命令行发布工具的入门、操作指南和 CLI 参考。",
"en": "Getting started, how-to guides, and CLI reference for the FPM package registry and publishing tool."
},
"navigation": [
{ "slug": "overview" },
{
"slug": "tutorials",
"title": {
"zh-hans": "教程",
"en": "Tutorials"
},
"navigation": [{ "slug": "getting-started" }]
},
{
"slug": "how-to",
"title": {
"zh-hans": "操作指南",
"en": "How-to guides"
},
"navigation": [{ "slug": "publish" }]
},
{
"slug": "reference",
"title": {
"zh-hans": "参考",
"en": "Reference"
},
"navigation": [{ "slug": "cli" }]
}
]
}
Loading