# @canonical/summon-core 中文文档

规范地址：https://npmcn.com/package/%40canonical/summon-core/

版本：0\.44\.0
npm 元数据更新时间：2026-10-23T01:40:42.325Z
中文译文更新时间：2026-11-09T12:55:24.294Z
软件包许可：GPL-3\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40canonical/summon-core
原文对照：https://npmcn.com/package/%40canonical/summon-core/?lang=original
项目主页：https://github.com/canonical/pragma-core#readme
源码仓库：https://github.com/canonical/pragma-core

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：552 kB，340 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.18 \<23 \|\| \>=23\.6
- 运行依赖：9 个
- 首次发布：2026-03-26T12:24:32.287Z
- 最新版本发布：2026-10-23T01:40:41.901Z
- 近 30 天下载量：2691（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：27（近 12 个月 27 个）

## 中文简介

代码生成框架:生成器定义,模板,邮票,发现. 建于 @ canonical/ task 上 .

## 安装

```sh
npm install @canonical/summon-core
```

也可以使用：`pnpm add @canonical/summon-core`、`yarn add @canonical/summon-core`、`bun add @canonical/summon-core`

## README

# 调用

一个代码生成器框架,其中生成器是返回数据的纯函数,而不是副作用.

写发电机一次。 运行它的真实。 预览方式 `--dry-run`. 测试没有嘲笑。 同样的代码,不同的翻译.

```typescript
generate: (answers) => writeFile(`src/${answers.name}.ts`, code)
// Returns a Task describing "write this file"
// Not a file write. Data.
```

## 安装

```bash
npm install -g @canonical/summon   # or: bun add -g @canonical/summon
```

CLI运行在平地节点下-不需要Bun. 它只用一个 示例生成器和 `summon init` (脚手架自己的发电机). 真实的 发电机在自己的软件包中生活; 将您需要的软件包安装在同一软件包中 位置和Summon自动发现它们:

```bash
npm install -g @canonical/summon-application   # summon application / domain / page / wrapper
npm install -g @canonical/summon-component      # summon component
```

## 使用发电机

提醒自动从已安装的软件包中发现生成器 . 见 [安装发电机包](https://npmcn.com/package/%40canonical/summon-core/#readme-installing-generator-packages) 安装现有发电机包, 或者说 [创建生成器](https://npmcn.com/package/%40canonical/summon-core/#readme-creating-generators) 来创造一个新的.

```bash
# See what's available
summon

# Run a generator interactively
summon component react

# Pass answers as positional argument (when supported)
summon component react src/components/Button

# Or as a flag
summon component react --component-path=src/components/Button

# Preview first (nothing written to disk)
summon component react src/components/Button --dry-run

# Show debug output
summon component react src/components/Button --verbose
```

每个提示都变成CLI旗. 布尔提示 `default: true` 使用该 `--no-` 要禁用前缀。 发电机也可定义a **位置参数** 允许更清洁的命令引用.

### CLI 选项

| 旗帜 | 说明 |
| --- | --- |
| `-d, --dry-run` | 不写入文件预览 |
| `-y, --yes` | 跳过确认提示并预览 |
| `-v, --verbose` | 显示调试输出 |
| `--show-files` | 在干线中显示文件内容 |
| `-l, --llm` | LLM 模式: 有下调输出的干运行, 无提示, 无邮票 |
| `--format <type>` | 输出格式 : `json` (简单的干燥,没有提示,没有邮票) |
| `--no-preview` | 略过文件预览 |
| `--no-generated-stamp` | 禁用生成的文件章注释 |

**LLM 用法 :** Summon将LLMs视为一等CLI用户. 使用 `--llm` 用于结构化的平分输出或 `--format json` 为机器解剖JSON。 两者都意味着 `--dry-run --yes --show-files --no-generated-stamp`数字 :

```bash
# Structured markdown (answers table, plan table, fenced code blocks)
summon component react src/components/Button --llm

# Machine-parseable JSON
summon component react src/components/Button --format json

# Session-level LLM mode via environment variable
export SUMMON_LLM=1
summon component react src/components/Button

# Structured help for LLMs
summon component react --help --llm
```

### Shell 自动补全

Summon支持为Bash,Zsh和Fish壳完成TAB. 完成情况 **动态** - 它们自动检测新安装的发电机包,而不需要重新运行设置.

```bash
# Automatic setup (recommended)
summon --setup-completion

# Or manual installation for each shell:

# Zsh
echo '. <(summon --completion)' >> ~/.zshrc

# Bash (may need: brew install bash-completion on macOS)
summon --completion >> ~/.summon-completion.sh
echo 'source ~/.summon-completion.sh' >> ~/.bash_profile

# Fish
echo 'summon --completion-fish | source' >> ~/.config/fish/config.fish
```

设置后, 重新启动您的 shell 或源代码配置文件 。 然后说:

```bash
summon <TAB>                    # Shows: component, application, init, ...
summon component <TAB>          # Shows: react, svelte, lit
summon component react <TAB>    # Shows: --component-path, --no-with-styles, ...
summon component react --comp<TAB>  # Completes to: --component-path
```

完成特性 :

-   **生成器名称** - 用 TAB 导航命令树
-   **发电机旗** - 所有提示成为可完成的旗帜
-   **确认提示** - 显示 `--no-X` 用于提示 `default: true`
-   **选择/ 多选择** - 完成现有选择
-   **路径提示** - 包含“路径”、“目录”、“文件”等提示的文件系统路径补全.

删除自动补全 :

```bash
summon --cleanup-completion
```

### 位置参数

生成器可以定义一个提示为 **位置参数**,允许用户提供主输入而不用旗:

```bash
# With positional argument support
summon component react src/components/Button

# Equivalent to
summon component react --component-path=src/components/Button
```

位置参数在使用 TAB 时也会获得文件系统路径补全 :

```bash
summon component react src/comp<TAB>  # Completes to: src/components/
```

### 安装发电机包

CLI 捆绑 `application`, (中文(简体) ), `domain`, (中文(简体) ), `page`,以及 `wrapper` 发电机. 其他发电机——包括公务发电机 `@canonical/summon-component` 船舶作为 后面的单独包 `summon-*` 或者说 `@scope/summon-*` 命名大会. 将一个安装到 **同一地点** 作为CLI(既包括全球项目,也包括两个项目) )和召唤自动发现:

```bash
# Component generators (react/svelte/lit)
npm install -g @canonical/summon-component   # or: bun add -g ...

# Now available (completions work immediately!)
summon component react
summon component svelte
```

## 创建生成器

生成器是一个纯函数,它接收答案并返回 a `Task`\- 描述该怎么做的数据结构.

```typescript
// src/module/types.ts
interface ModuleAnswers {
  name: string;
  withTests: boolean;
}

// src/module/generator.ts
import type { GeneratorDefinition } from "@canonical/summon";
import { debug, info, writeFile, mkdir, sequence_, when } from "@canonical/summon";
import type { ModuleAnswers } from "./types.js";

export const generator = {
  meta: {
    name: "module",
    description: "Creates a new module",
    version: "0.1.0",
  },

  prompts: [
    // positional: true allows `summon module src/utils` instead of `--name=src/utils`
    { name: "name", type: "text", message: "Module name:", positional: true },
    { name: "withTests", type: "confirm", message: "Include tests?", default: true },
  ],

  generate: (answers) => sequence_([
    info(`Creating module: ${answers.name}`),

    debug("Creating module directory"),
    mkdir(`src/${answers.name}`),

    debug("Creating index file"),
    writeFile(`src/${answers.name}/index.ts`, `export const ${answers.name} = {};\n`),

    when(answers.withTests, debug("Creating test file")),
    when(answers.withTests,
      writeFile(`src/${answers.name}/index.test.ts`, `test("works", () => {});\n`)
    ),

    info(`Created module at src/${answers.name}`),
  ]),
} as const satisfies GeneratorDefinition<ModuleAnswers>;

// src/module/index.ts (barrel)
export { generator } from "./generator.js";
export type { ModuleAnswers } from "./types.js";

// src/index.ts (package barrel)
import type { AnyGenerator } from "@canonical/summon";
import { generator as moduleGenerator } from "./module/index.js";

export const generators = {
  "module": moduleGenerator,
} as const satisfies Record<string, AnyGenerator>;
```

### 软件包结构

每个发电机应被分为三个文件,以便维持:

```
my-summon-package/
├── package.json
├── src/
│   ├── index.ts              # Package barrel - exports generators record
│   ├── module/
│   │   ├── index.ts          # Generator barrel
│   │   ├── types.ts          # Answer types
│   │   └── generator.ts      # Generator definition
│   └── templates/            # EJS templates (optional)
└── README.md
```

```json
{
  "name": "@myorg/summon-module",
  "main": "src/index.ts",
  "peerDependencies": {
    "@canonical/summon": "workspace:*"
  }
}
```

### 地方发展

为在当地开发发电机,将发电机连接到全球:

```bash
# From your generator package directory
cd /path/to/my-summon-package
bun link        # for bun
npm link        # for npm

# Now available everywhere
summon module src/utils
```

项目-当地软件包 `./node_modules`)优于全球链接的版本,因此可以使用特定项目版本来覆盖.

### 测试发电机

由于发电机返回数据,测试是直接的,不需要模拟:

```typescript
import { dryRun, getAffectedFiles } from "@canonical/summon";
import { generators } from "./index";

const generator = generators["module"];

test("creates expected files", () => {
  const task = generator.generate({ name: "utils", withTests: true });
  const { effects } = dryRun(task);

  expect(getAffectedFiles(effects)).toEqual([
    "src/utils/index.ts",
    "src/utils/index.test.ts",
  ]);
});

test("skips test file when disabled", () => {
  const task = generator.generate({ name: "utils", withTests: false });
  const { effects } = dryRun(task);

  expect(getAffectedFiles(effects)).not.toContain("src/utils/index.test.ts");
});
```

干流解译器维持虚拟文件系统,所以基于 `exists()` 即使没有碰到磁盘,工作也是正确的.

## 修道院模式

调用 a **摩纳德** 来写任务。 如果你用过"承诺",你已经理解了核心思想.

### 什么是摩纳德?

Monad是一些有上下文(如"可能失败"或"有效果")的连锁操作的设计模式. 把它当作一个管道,每个步骤都可以:

1.  **转换值** (单位:千美元)`map`——对结果应用函数
2.  **连锁业务** (单位:千美元)`flatMap`)——利用结果创造出下一步
3.  **故障后短路** —— 错误自动传播

```typescript
// Promise (async context)
fetchUser(id)
  .then(user => fetchOrders(user.id))    // chain
  .then(orders => orders.length)          // transform
  .catch(handleError);                    // recover

// Task (effect context)
task(readFile("config.json"))
  .map(content => JSON.parse(content))    // transform
  .flatMap(config => writeFile(           // chain
    config.outputPath,
    generateCode(config)
  ))
  .recover(err => pure(defaultConfig));   // recover
```

### 任务类型

`Task<A>` 代表计算:

-   描述效果( 文件 I/ O、 shell 命令等)
-   最终产生类型值 `A`
-   可能因错误而失败

```typescript
// A Task is one of three things:
type Task<A> =
  | { _tag: "Pure"; value: A }                           // Done, here's the value
  | { _tag: "Fail"; error: TaskError }                   // Failed with error
  | { _tag: "Effect"; effect: Effect; cont: ... }        // Do this effect, then continue
```

### 编译任务

这个 `TaskBuilder` 为组成提供流利的API:

```typescript
import { task, pure } from "@canonical/summon";

// Build a pipeline
const pipeline = task(readFile("input.txt"))
  .map(content => content.toUpperCase())           // Transform the value
  .flatMap(upper => writeFile("output.txt", upper)) // Chain another effect
  .andThen(info("Done!"))                          // Sequence (ignore previous value)
  .recover(err => pure(void 0));                   // Handle errors

// pipeline is still just data — nothing has executed yet
```

### 关键操作

| 运行 | 说明 | 示例 |
| --- | --- | --- |
| `pure(value)` | 在任务中环绕一个值 | `pure(42)` |
| `map(fn)` | 转换结果 | `.map(x => x * 2)` |
| `flatMap(fn)` | 与另一个任务连锁 | `.flatMap(x => writeFile(...))` |
| `andThen(task)` | 顺序, 前一个丢弃 | `.andThen(info("next"))` |
| `recover(fn)` | 处理错误 | `.recover(e => pure(default))` |
| `tap(fn)` | 边效果, 保留值 | `.tap(x => debug(x))` |

### 为什么Monads为发电机?

1.  **可编曲** ——小任务结合成复杂的工作流程
2.  **可预见** ——错误在不明确处理的情况下在每一步骤上传播
3.  **可测试** ——输油管为数据;检查时无运行效果
4.  **声明** - 说明 _什麽_ 做,没有 _怎么样_ 要做到这一点

```typescript
// Complex workflow, reads like a recipe
const scaffoldFeature = (name: string) =>
  task(mkdir(`src/features/${name}`))
    .andThen(template({
      source: "templates/feature.ts.ejs",
      dest: `src/features/${name}/index.ts`,
      vars: { name },
    }))
    .andThen(when(config.withTests,
      template({
        source: "templates/test.ts.ejs",
        dest: `src/features/${name}/index.test.ts`,
        vars: { name },
      })
    ))
    .andThen(info(`Created feature: ${name}`))
    .unwrap();
```

关于更深入地潜入“作为数据的效果”哲学,见: [解释](https://npmcn.com/package/%40canonical/summon-core/docs/explanation.md)。 。 。 .

## 调温引擎

Summon默认使用EJS进行模板渲染,但支持自定义调温引擎通过 `TemplatingEngine` 接口.

### 默认 (EJS)

```typescript
import { template, templateDir } from "@canonical/summon";

// Uses EJS by default
template({
  source: "templates/component.tsx.ejs",
  dest: "src/components/<%= name %>.tsx",
  vars: { name: "Button" },
});
```

### 自定义引擎

执行 `TemplatingEngine` 用于使用 Handlebars、Mustache、Nunjucks 或任何其他引擎:

```typescript
import type { TemplatingEngine } from "@canonical/summon";
import Handlebars from "handlebars";
import * as fs from "node:fs/promises";

const handlebarsEngine: TemplatingEngine = {
  render(template, vars) {
    return Handlebars.compile(template)(vars);
  },

  async renderAsync(template, vars) {
    return Handlebars.compile(template)(vars);
  },

  async renderFile(templatePath, vars) {
    const content = await fs.readFile(templatePath, "utf-8");
    return Handlebars.compile(content)(vars);
  },
};

// Use in templates
template({
  source: "templates/component.hbs",
  dest: "src/components/{{name}}.tsx",
  vars: { name: "Button" },
  engine: handlebarsEngine,
});
```

### 接口

```typescript
interface TemplatingEngine {
  /** Render a template string synchronously */
  render(template: string, vars: Record<string, unknown>): string;

  /** Render a template string asynchronously */
  renderAsync(template: string, vars: Record<string, unknown>): Promise<string>;

  /** Render a template file asynchronously */
  renderFile(templatePath: string, vars: Record<string, unknown>): Promise<string>;
}
```

这个 `engine` 选项在 `template()`, (中文(简体) ), `templateDir()`, (中文(简体) ), `renderString()`, (中文(简体) ), `renderStringAsync()`,以及 `renderFile()`。 。 。 .

## 文档

-   **[教学](https://npmcn.com/package/%40canonical/summon-core/docs/tutorial.md)** - 从头开始建造第一个发电机
-   **[如何向导](https://npmcn.com/package/%40canonical/summon-core/docs/how-to.md)** 解决具体问题
-   **[参考文献](https://npmcn.com/package/%40canonical/summon-core/docs/reference.md)** - 完整的API文件
-   **[解释](https://npmcn.com/package/%40canonical/summon-core/docs/explanation.md)** - 为什么把效果当作数据? 苏蒙背后的想法

## 许可证

GPL-3.0 (英语)

## 常见问题

### @canonical/summon-core 是什么？

代码生成框架:生成器定义,模板,邮票,发现\. 建于 @ canonical/ task 上 \.

### 如何安装 @canonical/summon-core？

在项目目录运行 npm install @canonical/summon-core，或使用 pnpm add / yarn add / bun add。

### @canonical/summon-core 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @canonical/summon-core 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @canonical/summon-core 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.18 \<23 \|\| \>=23\.6。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @canonical/summon-core 可以商用吗？

@canonical/summon-core 使用 GPL-3\.0 许可。强 Copyleft：分发包含该代码的软件时，整个作品需以 GPL-3\.0 兼容许可开源，并附带专利与反锁定条款。仅内部使用不触发此义务。以上为概括，不构成法律意见，请以许可原文为准。

### @canonical/summon-core 的下载量有多少？

根据 npm 官方下载统计，@canonical/summon-core 在 2026/10/09 – 2026/11/07 这 30 天内被下载 2,691 次，日均约 90 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @canonical/summon-core 还在维护吗？

最新版本 0\.44\.0 发布于 2026/10/23（17 天前）；至今共发布 27 个版本，其中过去 12 个月发布了 27 个；首次发布于 2026/03/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

