@savvy-web/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/547.js +417 -0
- package/bin/savvy-mcp.js +153 -0
- package/index.d.ts +127 -0
- package/index.js +3 -0
- package/package.json +80 -0
- package/resources/content/_templates/guides.md +12 -0
- package/resources/content/_templates/packages.md +21 -0
- package/resources/content/_templates/standards.md +17 -0
- package/resources/content/guides/api-docs-from-api-extractor.md +160 -0
- package/resources/content/guides/building-a-github-action.md +233 -0
- package/resources/content/guides/choosing-a-builder.md +140 -0
- package/resources/content/guides/llm-friendly-json-schemas.md +64 -0
- package/resources/content/manifest.json +490 -0
- package/resources/content/packages/cli/command-tree.md +70 -0
- package/resources/content/packages/cli/init-and-check.md +51 -0
- package/resources/content/packages/mcp/resource-taxonomy.md +63 -0
- package/resources/content/packages/rslib-builder/overview.md +68 -0
- package/resources/content/packages/silk/export-map.md +67 -0
- package/resources/content/packages/silk/install-and-setup.md +59 -0
- package/resources/content/packages/silk-effects/index.md +76 -0
- package/resources/content/packages/silk-effects/managed-section.md +84 -0
- package/resources/content/packages/silk-effects/platform-layers.md +94 -0
- package/resources/content/standards/api-model-pipeline.md +63 -0
- package/resources/content/standards/catalog-usage.md +48 -0
- package/resources/content/standards/changeset-discipline.md +52 -0
- package/resources/content/standards/changeset-format.md +131 -0
- package/resources/content/standards/commit-contract.md +58 -0
- package/resources/content/standards/dependency-conventions.md +82 -0
- package/resources/content/standards/linting-conventions.md +47 -0
- package/resources/content/standards/publishability.md +57 -0
- package/resources/content/standards/semver.md +51 -0
- package/resources/content/standards/test-classification.md +49 -0
- package/resources/content/tags.json +27 -0
- package/tsdoc-metadata.json +11 -0
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@savvy-web/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "The savvy MCP server — Silk Suite tooling and library knowledge for coding agents",
|
|
6
|
+
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/mcp",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/savvy-web/systems/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/savvy-web/systems.git",
|
|
13
|
+
"directory": "packages/mcp"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "C. Spencer Beggs",
|
|
18
|
+
"email": "spencer@savvyweb.systems",
|
|
19
|
+
"url": "https://savvyweb.systems"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./index.d.ts",
|
|
25
|
+
"import": "./index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"savvy-mcp": "bin/savvy-mcp.js"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@effect/platform": "^0.96.1",
|
|
33
|
+
"@effect/platform-node": "^0.106.0",
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
35
|
+
"@savvy-web/silk-effects": "0.6.0",
|
|
36
|
+
"effect": "^3.21.2",
|
|
37
|
+
"fuse.js": "^7.4.0",
|
|
38
|
+
"workspaces-effect": "^1.1.0",
|
|
39
|
+
"zod": "^4.4.3"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"!mcp.api.json",
|
|
43
|
+
"!tsconfig.json",
|
|
44
|
+
"!tsdoc.json",
|
|
45
|
+
"547.js",
|
|
46
|
+
"bin/savvy-mcp.js",
|
|
47
|
+
"index.d.ts",
|
|
48
|
+
"index.js",
|
|
49
|
+
"package.json",
|
|
50
|
+
"resources/content/_templates/guides.md",
|
|
51
|
+
"resources/content/_templates/packages.md",
|
|
52
|
+
"resources/content/_templates/standards.md",
|
|
53
|
+
"resources/content/guides/api-docs-from-api-extractor.md",
|
|
54
|
+
"resources/content/guides/building-a-github-action.md",
|
|
55
|
+
"resources/content/guides/choosing-a-builder.md",
|
|
56
|
+
"resources/content/guides/llm-friendly-json-schemas.md",
|
|
57
|
+
"resources/content/manifest.json",
|
|
58
|
+
"resources/content/packages/cli/command-tree.md",
|
|
59
|
+
"resources/content/packages/cli/init-and-check.md",
|
|
60
|
+
"resources/content/packages/mcp/resource-taxonomy.md",
|
|
61
|
+
"resources/content/packages/rslib-builder/overview.md",
|
|
62
|
+
"resources/content/packages/silk-effects/index.md",
|
|
63
|
+
"resources/content/packages/silk-effects/managed-section.md",
|
|
64
|
+
"resources/content/packages/silk-effects/platform-layers.md",
|
|
65
|
+
"resources/content/packages/silk/export-map.md",
|
|
66
|
+
"resources/content/packages/silk/install-and-setup.md",
|
|
67
|
+
"resources/content/standards/api-model-pipeline.md",
|
|
68
|
+
"resources/content/standards/catalog-usage.md",
|
|
69
|
+
"resources/content/standards/changeset-discipline.md",
|
|
70
|
+
"resources/content/standards/changeset-format.md",
|
|
71
|
+
"resources/content/standards/commit-contract.md",
|
|
72
|
+
"resources/content/standards/dependency-conventions.md",
|
|
73
|
+
"resources/content/standards/linting-conventions.md",
|
|
74
|
+
"resources/content/standards/publishability.md",
|
|
75
|
+
"resources/content/standards/semver.md",
|
|
76
|
+
"resources/content/standards/test-classification.md",
|
|
77
|
+
"resources/content/tags.json",
|
|
78
|
+
"tsdoc-metadata.json"
|
|
79
|
+
]
|
|
80
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Guide title
|
|
2
|
+
|
|
3
|
+
A short intro framing the problem and when to read this guide.
|
|
4
|
+
|
|
5
|
+
## A section
|
|
6
|
+
|
|
7
|
+
Free-form prose, lists, and code as the topic demands. Keep each guide a single
|
|
8
|
+
focused page; split when it outgrows the body budget.
|
|
9
|
+
|
|
10
|
+
## Another section
|
|
11
|
+
|
|
12
|
+
Close with concrete recommendations or a checklist where it helps.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Package topic title
|
|
2
|
+
|
|
3
|
+
## What
|
|
4
|
+
|
|
5
|
+
One paragraph: what this package or service is and the problem it solves.
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
The key shapes, signatures, and statics a consumer touches. Condensed, not a full port.
|
|
10
|
+
|
|
11
|
+
## Layer
|
|
12
|
+
|
|
13
|
+
The Effect layer(s) and their platform requirements, or the install/build wiring.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
A short, runnable example of the common path.
|
|
18
|
+
|
|
19
|
+
## Related
|
|
20
|
+
|
|
21
|
+
Cross-link sibling digests and the standards they implement.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Standard title
|
|
2
|
+
|
|
3
|
+
## Rule
|
|
4
|
+
|
|
5
|
+
State the durable rule in one or two sentences. This is the thing that must hold.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Explain the reasoning the rule encodes, so a reader can apply judgment at the edges.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
Show a conforming case and a non-conforming case.
|
|
14
|
+
|
|
15
|
+
## See also
|
|
16
|
+
|
|
17
|
+
Cross-link related standards and package digests by `silk://` URI.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: guides/api-docs-from-api-extractor
|
|
3
|
+
title: Generating API docs from API Extractor
|
|
4
|
+
summary: Configure apiModel, build the model, and render LLM-lean markdown with api-extractor-llms.
|
|
5
|
+
tier: guides
|
|
6
|
+
source: hand
|
|
7
|
+
tags: [api, build]
|
|
8
|
+
priority: 0.5
|
|
9
|
+
related: [standards/api-model-pipeline, packages/rslib-builder/overview]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
The Silk Suite generates API-reference docs from Microsoft API Extractor models
|
|
15
|
+
rather than hand-authoring them. The pipeline has three stages: emit a model,
|
|
16
|
+
render it to markdown, and compile rendered docs into the MCP resource corpus.
|
|
17
|
+
This guide walks through each stage as implemented in this repo.
|
|
18
|
+
|
|
19
|
+
For the policy contract (what is generated, what must not be edited, where docs
|
|
20
|
+
land), see `silk://standards/api-model-pipeline`.
|
|
21
|
+
|
|
22
|
+
## Step 1 — Enable the API model in `rslib.config.ts`
|
|
23
|
+
|
|
24
|
+
A library package opts in by passing an `apiModel` option to `NodeLibraryBuilder.create()`:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { NodeLibraryBuilder } from "@savvy-web/rslib-builder";
|
|
28
|
+
|
|
29
|
+
export default NodeLibraryBuilder.create({
|
|
30
|
+
apiModel: {
|
|
31
|
+
tsdoc: {
|
|
32
|
+
tagDefinitions: [{ tagName: "@since", syntaxKind: "block" }],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Passing any truthy value for `apiModel` enables model emission. Options under
|
|
39
|
+
`apiModel` are forwarded to the API Extractor TSDoc runner. A plain `apiModel: true`
|
|
40
|
+
works when no custom tag definitions are needed.
|
|
41
|
+
|
|
42
|
+
The entry point and package name are derived from the package's `exports` field.
|
|
43
|
+
Only public API surfaces are captured; members annotated `@internal` are excluded.
|
|
44
|
+
|
|
45
|
+
See `silk://packages/rslib-builder/overview` for full builder configuration.
|
|
46
|
+
|
|
47
|
+
## Step 2 — Build the model
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm --filter @savvy-web/your-package run build:prod
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The production build writes `dist/npm/<unscoped-name>.api.json`. For example,
|
|
54
|
+
`@savvy-web/silk-effects` emits `dist/npm/silk-effects.api.json`. The filename
|
|
55
|
+
is the unscoped package name with an `.api.json` suffix.
|
|
56
|
+
|
|
57
|
+
`dist/dev/` may also contain a model depending on the build configuration.
|
|
58
|
+
The generator script probes `dist/dev/` first, then `dist/npm/`.
|
|
59
|
+
|
|
60
|
+
## Step 3 — Render with `api-extractor-llms`
|
|
61
|
+
|
|
62
|
+
The rendering library takes a model path, two injectable callbacks, and returns
|
|
63
|
+
one `RenderedDoc` per top-level public member.
|
|
64
|
+
|
|
65
|
+
### Core API
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { loadApiModel, renderPackage } from "api-extractor-llms";
|
|
69
|
+
import type { FrontmatterRenderer, RouteFormatter } from "api-extractor-llms";
|
|
70
|
+
|
|
71
|
+
const pkg = await loadApiModel("/path/to/silk-effects.api.json");
|
|
72
|
+
|
|
73
|
+
const routeFor: RouteFormatter = (ref) =>
|
|
74
|
+
`silk://packages/silk-effects/api/${ref.kind}/${ref.slug}`;
|
|
75
|
+
|
|
76
|
+
const frontmatter: FrontmatterRenderer = (meta) =>
|
|
77
|
+
`---\nid: packages/silk-effects/api/${meta.kind}/${meta.slug}\ntitle: "${meta.name}"\n---\n\n`;
|
|
78
|
+
|
|
79
|
+
const docs = renderPackage(pkg, { packageName: "@savvy-web/silk-effects", routeFor, frontmatter });
|
|
80
|
+
|
|
81
|
+
for (const doc of docs) {
|
|
82
|
+
// doc.markdown = frontmatter block + rendered body
|
|
83
|
+
// doc.kind, doc.name, doc.slug identify the item
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### What `renderPackage` produces
|
|
88
|
+
|
|
89
|
+
For each top-level public member, the shared body renderer emits:
|
|
90
|
+
|
|
91
|
+
- An ATX `# Name` heading
|
|
92
|
+
- The TypeScript signature in a fenced `ts` code block (via `TypeSignatureFormatter`)
|
|
93
|
+
- TSDoc summary paragraph
|
|
94
|
+
- `## Parameters` list with types and descriptions (if any)
|
|
95
|
+
- `## Returns` section (if documented)
|
|
96
|
+
- `## Members` section listing class/interface/namespace members with signatures and summaries
|
|
97
|
+
- `## Examples` blocks with language-tagged fences (from `@example` TSDoc tags)
|
|
98
|
+
- Cross-links in prose resolved through the injected `routeFor` (via `CrossLinker`)
|
|
99
|
+
|
|
100
|
+
The two injectable callbacks — `routeFor` (URL scheme) and `frontmatter` (YAML
|
|
101
|
+
block) — are the only consumer-specific pieces. The body rendering is shared
|
|
102
|
+
across all consumers.
|
|
103
|
+
|
|
104
|
+
## Step 4 — The MCP generator script
|
|
105
|
+
|
|
106
|
+
`packages/mcp/scripts/generate-api-docs.ts` is the reference implementation of
|
|
107
|
+
steps 3 and 4 for the MCP resource corpus. It iterates `API_TARGETS` (defined in
|
|
108
|
+
`packages/mcp/scripts/api-targets.ts`), loads each model, injects silk-specific
|
|
109
|
+
frontmatter and `silk://` crosslink routes, and writes output under
|
|
110
|
+
`content/packages/<dir>/api/<kind>/<slug>.md` (gitignored).
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// The silk crosslink scheme
|
|
114
|
+
const routeFor = (target: ApiTarget) => (ref: ApiItemRef) =>
|
|
115
|
+
`silk://${target.idPrefix}/api/${ref.kind}/${ref.slug}`;
|
|
116
|
+
|
|
117
|
+
// The silk frontmatter renderer (derives id, title, summary, tags)
|
|
118
|
+
const frontmatter = (meta: DocMeta) => toYaml(frontMatterFor(target, meta));
|
|
119
|
+
|
|
120
|
+
const docs = renderPackage(pkg, {
|
|
121
|
+
packageName: target.packageName,
|
|
122
|
+
routeFor: routeFor(target),
|
|
123
|
+
frontmatter,
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Current targets (from `api-targets.ts`): `silk-effects`, `templates`,
|
|
128
|
+
`github-action-effects`, `github-action-builder`. The MCP package itself and `cli`/`silk`
|
|
129
|
+
are excluded (a generate→mcp build dependency would create a Turborepo cycle; cli
|
|
130
|
+
and silk are not library APIs).
|
|
131
|
+
|
|
132
|
+
## Step 5 — Compile into the corpus
|
|
133
|
+
|
|
134
|
+
After `generate-api-docs.ts` writes the markdown files, `build:catalog` picks them
|
|
135
|
+
up along with hand-authored docs and compiles the unified manifest. Generated docs
|
|
136
|
+
appear in `silk://catalog` marked `(generated)`.
|
|
137
|
+
|
|
138
|
+
In Turborepo the pipeline is:
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
build:prod (each library) → generate-api-docs → build:catalog
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Authoring notes
|
|
145
|
+
|
|
146
|
+
- TSDoc coverage determines output quality. Undocumented public members produce
|
|
147
|
+
sparse rendered docs with no summary or parameter descriptions.
|
|
148
|
+
- The slug is the lowercased display name. A class `MyService` maps to
|
|
149
|
+
`silk://packages/foo/api/class/myservice`.
|
|
150
|
+
- Cross-links in prose (`{@link OtherClass}`) resolve only if `OtherClass` is in
|
|
151
|
+
the same package's rendered set.
|
|
152
|
+
- Do not edit generated files under `content/packages/*/api/` — changes are
|
|
153
|
+
overwritten on the next `generate-api-docs` run.
|
|
154
|
+
|
|
155
|
+
## See also
|
|
156
|
+
|
|
157
|
+
- `silk://standards/api-model-pipeline` — policy: what is generated, provenance
|
|
158
|
+
markers, coverage scope
|
|
159
|
+
- `silk://packages/rslib-builder/overview` — configuring the builder that emits
|
|
160
|
+
the model
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: guides/building-a-github-action
|
|
3
|
+
title: Building a GitHub Action
|
|
4
|
+
summary: Scaffold a Node.js 24 GitHub Action with @savvy-web/github-action-builder and the github-action-effects services.
|
|
5
|
+
tier: guides
|
|
6
|
+
source: hand
|
|
7
|
+
tags: [github-actions, build]
|
|
8
|
+
priority: 0.5
|
|
9
|
+
related: [guides/choosing-a-builder, standards/api-model-pipeline]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Two packages work together to build and power Node.js 24 GitHub Actions in the
|
|
15
|
+
Silk Suite:
|
|
16
|
+
|
|
17
|
+
- **`@savvy-web/github-action-builder`** — zero-config rsbuild-based build tool
|
|
18
|
+
that bundles TypeScript source into self-contained ESM files and validates
|
|
19
|
+
`action.yml`
|
|
20
|
+
- **`@savvy-web/github-action-effects`** — Effect service library replacing all
|
|
21
|
+
`@actions/*` packages with native ESM implementations
|
|
22
|
+
|
|
23
|
+
Neither package depends on the other at build time. The builder bundles whatever
|
|
24
|
+
action code you write; the effects library provides the services that code uses.
|
|
25
|
+
|
|
26
|
+
For choosing the right builder, see `silk://guides/choosing-a-builder`. The
|
|
27
|
+
github-action-builder is separate from rslib-builder and bun-builder — it targets
|
|
28
|
+
a different output shape (single-file committed ESM bundles, not npm-published
|
|
29
|
+
libraries).
|
|
30
|
+
|
|
31
|
+
## Step 1 — Project structure
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
my-action/
|
|
35
|
+
├── src/
|
|
36
|
+
│ ├── main.ts # Required — main action logic
|
|
37
|
+
│ ├── pre.ts # Optional — pre-action hook
|
|
38
|
+
│ └── post.ts # Optional — post-action hook
|
|
39
|
+
├── action.yml # GitHub metadata; must have runs.using: "node24"
|
|
40
|
+
└── package.json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The builder auto-detects `src/pre.ts` and `src/post.ts` if they exist. Only
|
|
44
|
+
`src/main.ts` is required.
|
|
45
|
+
|
|
46
|
+
`action.yml` must declare `runs.using: "node24"`. The builder validates this and
|
|
47
|
+
fails if any other value is present.
|
|
48
|
+
|
|
49
|
+
## Step 2 — Install and configure the builder
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm add -D @savvy-web/github-action-builder
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Zero-config usage — no config file needed:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
github-action-builder build
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or create an optional `action.config.ts` for customization:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { defineConfig } from "@savvy-web/github-action-builder";
|
|
65
|
+
|
|
66
|
+
export default defineConfig({
|
|
67
|
+
build: {
|
|
68
|
+
minify: true, // default: true
|
|
69
|
+
sourceMap: false, // default: false
|
|
70
|
+
externals: [], // exclude from bundle (must be available at runtime)
|
|
71
|
+
ignore: [], // replace with a throwing stub
|
|
72
|
+
},
|
|
73
|
+
validation: {
|
|
74
|
+
requireActionYml: true,
|
|
75
|
+
strict: undefined, // auto-detects CI; warn locally, error in CI
|
|
76
|
+
},
|
|
77
|
+
persistLocal: {
|
|
78
|
+
enabled: true, // auto-copy to .github/actions/local/ after build
|
|
79
|
+
path: ".github/actions/local",
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Build output
|
|
85
|
+
|
|
86
|
+
Each detected entry emits one flat ESM file:
|
|
87
|
+
|
|
88
|
+
| Input | Output |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `src/main.ts` | `dist/main.js` |
|
|
91
|
+
| `src/pre.ts` | `dist/pre.js` |
|
|
92
|
+
| `src/post.ts` | `dist/post.js` |
|
|
93
|
+
| (generated) | `dist/package.json` |
|
|
94
|
+
|
|
95
|
+
All output files are self-contained ESM bundles. Dynamic `import()` calls are
|
|
96
|
+
folded back into the parent file (`asyncChunks: false`), so `action.yml` can
|
|
97
|
+
always reference a known single-file path.
|
|
98
|
+
|
|
99
|
+
The builder also copies output to `.github/actions/local/` for local testing with
|
|
100
|
+
[nektos/act](https://github.com/nektos/act) unless `persistLocal.enabled: false`.
|
|
101
|
+
|
|
102
|
+
## Step 3 — Write action logic with `github-action-effects`
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pnpm add @savvy-web/github-action-effects
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The library provides 37 Effect service interfaces across six domains:
|
|
109
|
+
|
|
110
|
+
| Domain | Services cover |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Core action I/O | Outputs, state, logging, environment, cache |
|
|
113
|
+
| Git operations | Branches, commits, tags via Git Data API |
|
|
114
|
+
| GitHub API | REST client, GraphQL, releases, issues, PR lifecycle, check runs, rate limiting |
|
|
115
|
+
| Build tooling | Command execution, npm registry, workspace detection, changeset analysis |
|
|
116
|
+
| Attestation | SLSA statement construction, Sigstore signing, CycloneDX SBOM generation |
|
|
117
|
+
| Runtime layer | GitHub Actions workflow command protocol, `ActionsConfigProvider`, `ActionsLogger`, `Step` |
|
|
118
|
+
|
|
119
|
+
### Runtime layer
|
|
120
|
+
|
|
121
|
+
The runtime layer replaces all `@actions/*` packages with native ESM implementations:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { Effect, Config } from "effect";
|
|
125
|
+
import { ActionsRuntime, Action, Step } from "@savvy-web/github-action-effects";
|
|
126
|
+
|
|
127
|
+
const program = Effect.gen(function* () {
|
|
128
|
+
// Inputs via Effect's Config API (reads INPUT_* env vars)
|
|
129
|
+
const name = yield* Config.string("name");
|
|
130
|
+
const count = yield* Config.integer("count");
|
|
131
|
+
|
|
132
|
+
// Logging maps to workflow commands
|
|
133
|
+
yield* Effect.log("Processing..."); // plain stdout
|
|
134
|
+
yield* Effect.logDebug("detail"); // ::debug::detail
|
|
135
|
+
yield* Effect.logWarning("heads up"); // ::warning::heads up
|
|
136
|
+
|
|
137
|
+
// Step buffering: one success line on pass, spills debug buffer on fail
|
|
138
|
+
yield* Step.withStep("fetch data", fetchData(name));
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Provide the runtime layer
|
|
142
|
+
Action.run(program);
|
|
143
|
+
// or: program.pipe(Effect.provide(ActionsRuntime.Default))
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Reading inputs
|
|
147
|
+
|
|
148
|
+
Action inputs are read via Effect's `Config` API backed by `ActionsConfigProvider`,
|
|
149
|
+
which translates config keys to `INPUT_*` environment variables:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const repoName = yield* Config.string("repo-name"); // reads INPUT_REPO-NAME
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Composing services
|
|
156
|
+
|
|
157
|
+
Services are provided via Effect Layers. The programmatic pattern:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { Effect } from "effect";
|
|
161
|
+
import {
|
|
162
|
+
ActionsRuntime,
|
|
163
|
+
GitHubClient,
|
|
164
|
+
GitHubClientLive,
|
|
165
|
+
} from "@savvy-web/github-action-effects";
|
|
166
|
+
|
|
167
|
+
const program = Effect.gen(function* () {
|
|
168
|
+
const client = yield* GitHubClient;
|
|
169
|
+
// use client ...
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
program.pipe(
|
|
173
|
+
Effect.provide(GitHubClientLive),
|
|
174
|
+
Effect.provide(ActionsRuntime.Default),
|
|
175
|
+
Effect.runPromise,
|
|
176
|
+
);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Testing
|
|
180
|
+
|
|
181
|
+
The library exports a `./testing` subpath that excludes `GitHubClientLive` and
|
|
182
|
+
`OctokitAuthAppLive` (which import `@octokit/rest`/`@octokit/auth-app`). Use this
|
|
183
|
+
in test files to avoid pulling in those dependencies:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { ... } from "@savvy-web/github-action-effects/testing";
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Step 4 — Validate and CI
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Validate action.yml and entry structure without building
|
|
193
|
+
github-action-builder validate
|
|
194
|
+
|
|
195
|
+
# Full build with validation
|
|
196
|
+
github-action-builder build
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
In CI (`CI=true` or `GITHUB_ACTIONS=true`), validation warnings become errors and
|
|
200
|
+
fail the build. Locally they are displayed as warnings and the build continues.
|
|
201
|
+
|
|
202
|
+
Add to `package.json`:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"scripts": {
|
|
207
|
+
"build": "github-action-builder build",
|
|
208
|
+
"validate": "github-action-builder validate"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Step 5 — Reference the built output in `action.yml`
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
name: My Action
|
|
217
|
+
description: Does something useful
|
|
218
|
+
runs:
|
|
219
|
+
using: node24
|
|
220
|
+
main: dist/main.js
|
|
221
|
+
post: dist/post.js # if you have a post step
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The `dist/` directory must be committed to the repository so GitHub runners can
|
|
225
|
+
execute it. The builder's `persistLocal` feature also syncs to
|
|
226
|
+
`.github/actions/local/` for local `act` runs.
|
|
227
|
+
|
|
228
|
+
## See also
|
|
229
|
+
|
|
230
|
+
- `silk://guides/choosing-a-builder` — when to use github-action-builder vs the
|
|
231
|
+
library builders
|
|
232
|
+
- `silk://standards/api-model-pipeline` — if your action repo also publishes a
|
|
233
|
+
library whose API is documented
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: guides/choosing-a-builder
|
|
3
|
+
title: Choosing a builder (rslib vs bun)
|
|
4
|
+
summary: When to reach for @savvy-web/rslib-builder vs @savvy-web/bun-builder for a Silk package.
|
|
5
|
+
tier: guides
|
|
6
|
+
source: hand
|
|
7
|
+
tags: [build]
|
|
8
|
+
priority: 0.5
|
|
9
|
+
related: [packages/rslib-builder/overview]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
The Silk Suite has two zero-config build tools for TypeScript libraries:
|
|
15
|
+
|
|
16
|
+
| Package | Bundler core | Primary target |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `@savvy-web/rslib-builder` | rsbuild / rspack | Node.js (pnpm monorepos) |
|
|
19
|
+
| `@savvy-web/bun-builder` | Bun.build() | Bun monorepos |
|
|
20
|
+
|
|
21
|
+
Both tools auto-detect entry points from `package.json` `exports`, emit `dist/dev/`
|
|
22
|
+
and `dist/npm/` build modes, generate rolled-up `.d.ts` declarations via API
|
|
23
|
+
Extractor, resolve `catalog:` and `workspace:` protocol references for publishing,
|
|
24
|
+
and transform the output `package.json` for publish readiness.
|
|
25
|
+
|
|
26
|
+
## `@savvy-web/rslib-builder`
|
|
27
|
+
|
|
28
|
+
The **ecosystem default** for packages inside the `savvy-web/systems` monorepo and
|
|
29
|
+
any pnpm-managed Silk Suite package.
|
|
30
|
+
|
|
31
|
+
### What it does
|
|
32
|
+
|
|
33
|
+
- Zero-config builds via `NodeLibraryBuilder.create({})` in `rslib.config.ts`
|
|
34
|
+
- Reads `exports` to discover entry points; builds `dist/dev/` and `dist/npm/`
|
|
35
|
+
- Generates type declarations and emits a Microsoft API Extractor model
|
|
36
|
+
(`<unscoped>.api.json`) on the npm build
|
|
37
|
+
- Transforms the output `package.json`: resolves `pnpm catalog:` references,
|
|
38
|
+
flips `private: true` to publish-ready based on `publishConfig.access`, rewrites
|
|
39
|
+
export paths from `.ts` to `.js`, adds type conditions
|
|
40
|
+
- Supports dual-format ESM+CJS builds when needed (e.g. `@savvy-web/silk` for CJS
|
|
41
|
+
consumers)
|
|
42
|
+
- Peer dependencies: `@rslib/core`, `@typescript/native-preview`
|
|
43
|
+
|
|
44
|
+
### Configuration
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { NodeLibraryBuilder } from "@savvy-web/rslib-builder";
|
|
48
|
+
|
|
49
|
+
export default NodeLibraryBuilder.create({
|
|
50
|
+
externals: ["effect", "@effect/platform"],
|
|
51
|
+
apiModel: {
|
|
52
|
+
tsdoc: {
|
|
53
|
+
tagDefinitions: [{ tagName: "@since", syntaxKind: "block" }],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Pass `apiModel: true` (or an options object) to enable API Extractor model
|
|
60
|
+
emission. See `silk://packages/rslib-builder/overview` for full details.
|
|
61
|
+
|
|
62
|
+
### When to use it
|
|
63
|
+
|
|
64
|
+
- You are building a package inside `savvy-web/systems` (or a pnpm-based Silk repo)
|
|
65
|
+
- You need dual-format ESM+CJS output
|
|
66
|
+
- You want API Extractor model emission for MCP doc generation
|
|
67
|
+
- The package uses `pnpm catalog:` or `workspace:` protocol in its dependencies
|
|
68
|
+
|
|
69
|
+
## `@savvy-web/bun-builder`
|
|
70
|
+
|
|
71
|
+
For **Bun-managed monorepos** where Bun.build() is the preferred bundler.
|
|
72
|
+
|
|
73
|
+
### What it does
|
|
74
|
+
|
|
75
|
+
- Zero-config builds via `BunLibraryBuilder.create({})` in `bun.config.ts`
|
|
76
|
+
- Auto-detects entry points from `package.json` `exports`
|
|
77
|
+
- Bundled or bundleless output (`bundle: false` preserves source structure)
|
|
78
|
+
- Rolled-up `.d.ts` in bundled mode; raw `.d.ts` in bundleless mode
|
|
79
|
+
- API Extractor model generation on npm builds (enabled by default)
|
|
80
|
+
- TSDoc warnings reported with source locations; severity configurable per
|
|
81
|
+
environment (`"fail"` in CI, `"log"` locally)
|
|
82
|
+
- Resolves Bun `catalog:` and `workspace:` protocol references for publishing
|
|
83
|
+
- Peer dependencies: `@microsoft/api-extractor`, `@typescript/native-preview`,
|
|
84
|
+
`typescript`, `@types/bun`
|
|
85
|
+
|
|
86
|
+
### Configuration
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { BunLibraryBuilder } from "@savvy-web/bun-builder";
|
|
90
|
+
|
|
91
|
+
export default BunLibraryBuilder.create({
|
|
92
|
+
bundle: true, // default; set false for bundleless
|
|
93
|
+
apiModel: true, // default; emits model on npm build
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Build via:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
bun run bun.config.ts # all modes
|
|
101
|
+
bun run bun.config.ts --env-mode dev
|
|
102
|
+
bun run bun.config.ts --env-mode npm
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### When to use it
|
|
106
|
+
|
|
107
|
+
- You are in a Bun-managed workspace (`bun.lock`, Bun catalog protocol)
|
|
108
|
+
- You want sub-second build iteration times
|
|
109
|
+
- You do not need rspack's CJS-to-ESM interop (which is important for certain
|
|
110
|
+
bundled GitHub Actions scenarios)
|
|
111
|
+
|
|
112
|
+
## Decision guide
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
Is this a package in savvy-web/systems (pnpm monorepo)?
|
|
116
|
+
Yes → rslib-builder
|
|
117
|
+
|
|
118
|
+
Does the package need dual-format ESM+CJS output?
|
|
119
|
+
Yes → rslib-builder
|
|
120
|
+
|
|
121
|
+
Is this a Bun-managed workspace?
|
|
122
|
+
Yes → bun-builder
|
|
123
|
+
|
|
124
|
+
Are you building a GitHub Action (bundled Node.js 24 binary)?
|
|
125
|
+
Use @savvy-web/github-action-builder instead — see silk://guides/building-a-github-action
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Common pitfalls
|
|
129
|
+
|
|
130
|
+
**rslib-builder:** Relative imports inside source must use `.js` extensions
|
|
131
|
+
(ESM requirement). The build will report "cannot find module" on missing extensions.
|
|
132
|
+
|
|
133
|
+
**bun-builder:** The Bun catalog protocol uses `workspaces.catalog` in the root
|
|
134
|
+
`package.json`, distinct from pnpm's catalog. Do not mix the two in the same
|
|
135
|
+
workspace.
|
|
136
|
+
|
|
137
|
+
## See also
|
|
138
|
+
|
|
139
|
+
- `silk://packages/rslib-builder/overview` — full rslib-builder reference
|
|
140
|
+
- `silk://guides/building-a-github-action` — GitHub Actions use a separate builder
|