@savvy-web/bundler 0.6.0 → 0.7.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/README.md +19 -12
- package/index.d.ts +8 -5
- package/package.json +3 -3
- package/run.js +12 -32
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ npm run build:prod
|
|
|
49
49
|
# writes dist/prod/npm/pkg — the tarball root, with a resolved manifest and built code
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
`--target dev` writes `dist/dev/pkg`, the local-link target with `catalog:`/`workspace:` specifiers preserved. `--target prod` writes `dist/prod/npm/pkg` with those specifiers resolved to concrete ranges, ready to publish
|
|
52
|
+
`--target dev` writes `dist/dev/pkg`, the local-link target with `catalog:`/`workspace:` specifiers preserved. `--target prod` writes `dist/prod/npm/pkg` with those specifiers resolved to concrete ranges, ready to publish — and emits the API Extractor api-model alongside it. A third target, `--target exe`, compiles SEA binaries and is covered below.
|
|
53
53
|
|
|
54
54
|
Every build emits per-module JavaScript alongside a single rolled-up, self-contained `.d.ts` per public entry. Each entry's declaration file pulls in every re-exported type, so a consumer that infers a type from your public API never has to reach into a deep sibling module that no export subpath addresses.
|
|
55
55
|
|
|
@@ -87,22 +87,19 @@ With no `targets` map the build falls back to the single-`npm` group above.
|
|
|
87
87
|
|
|
88
88
|
## API Extractor meta
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
`savvy build --target prod` generates an [API Extractor](https://api-extractor.com/) api-model from each prod group's resolved `.d.ts`. For every group it writes the bundle (`<unscoped>.api.json`, `tsdoc-metadata.json` and a resolved `tsconfig.json`) into `dist/prod/<group>/meta` as a release asset alongside `pkg/`, and copies the canonical group's bundle into any `localPaths` directories. Because it reads the prod build, the meta `package.json` carries concrete dependency versions rather than `catalog:`/`workspace:` specifiers.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
- `savvy build --target prod` additionally emits the same bundle into `dist/prod/npm/meta` as a release asset alongside `pkg/`.
|
|
92
|
+
The `meta` field on `defineBuild` is tri-state:
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
- **An object** — override the defaults: `localPaths` (directories the api-model is copied into on `--target meta`) and `tsdoc` (warning suppression and custom tags).
|
|
99
|
-
- **`false`** — opt out entirely; both `--target meta` and the prod meta asset become no-ops.
|
|
94
|
+
- **Omitted** (or `undefined`) — generation runs with default options. This is the default; you do not need a `meta` field for `--target prod` to emit the api-model.
|
|
95
|
+
- **An object** — override the defaults: `localPaths` (directories the canonical api-model is copied into), `tsdoc` (warning suppression and custom tags) and `optimistic` (see below).
|
|
96
|
+
- **`false`** — opt out entirely; the prod meta asset becomes a no-op.
|
|
100
97
|
|
|
101
98
|
```ts
|
|
102
99
|
const config = defineBuild({
|
|
103
100
|
format: ["esm"],
|
|
104
101
|
meta: {
|
|
105
|
-
// directories the generated api-model is copied into
|
|
102
|
+
// directories the generated api-model is copied into
|
|
106
103
|
localPaths: ["../mcp/models/@savvy-web/bundler"],
|
|
107
104
|
tsdoc: {
|
|
108
105
|
suppressWarnings: [{ messageId: "ae-undocumented" }],
|
|
@@ -115,6 +112,16 @@ const config = defineBuild({
|
|
|
115
112
|
// const config = defineBuild({ meta: false });
|
|
116
113
|
```
|
|
117
114
|
|
|
115
|
+
`optimistic` (`"auto"`, the default, or a boolean) forward-looks the meta bundle's own `version` and its workspace-sibling dependency versions to their next release version from pending changesets. `"auto"` is off under CI (`CI` or `GITHUB_ACTIONS` set) and on locally, so a locally generated bundle matches what the CI release build would emit. Set it to `true` or `false` to pin the behavior:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const config = defineBuild({
|
|
119
|
+
meta: { optimistic: false }, // always use the current package.json versions
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`--target meta` is deprecated: it warns and no-ops. Generate the api-model with `--target prod` instead.
|
|
124
|
+
|
|
118
125
|
## Executable binaries
|
|
119
126
|
|
|
120
127
|
Set the optional `exe` field to compile a single-executable application (SEA) from a bin entry, via [`@tsdown/exe`](https://www.npmjs.com/package/@tsdown/exe):
|
|
@@ -268,7 +275,7 @@ const config = defineBuild({
|
|
|
268
275
|
## Features
|
|
269
276
|
|
|
270
277
|
- **One self-executing config** — `savvy.build.ts` exports a `defineBuild` object for tooling to introspect and runs the build when invoked directly. No factory-notation config file.
|
|
271
|
-
- **
|
|
278
|
+
- **Build targets** — `dev` for local linking, `prod` for a resolved publishable manifest (which also emits an API Extractor api-model) and `exe` for SEA binaries, on disjoint `dist/dev` and `dist/prod` output paths for clean caching.
|
|
272
279
|
- **Bundled declarations** — per-module JavaScript with a single rolled-up `.d.ts` per public entry, so re-exported types stay reachable through your published export subpaths.
|
|
273
280
|
- **Shared tsconfig base** — extend `@savvy-web/bundler/ecma.json` for the ESNext/NodeNext/strict settings the build expects.
|
|
274
281
|
- **Manifest resolution** — `catalog:` and `workspace:` specifiers are resolved against the workspace for the published target, and preserved for the linked dev target.
|
|
@@ -295,7 +302,7 @@ const config = defineBuild({
|
|
|
295
302
|
|
|
296
303
|
## Turbo tasks
|
|
297
304
|
|
|
298
|
-
`pnpm turbo run build:
|
|
305
|
+
`pnpm turbo run build:prod` produces the publishable output and the api-model bundle in one pass, writing the canonical group's api-model into the `localPaths` configured in each package's `savvy.build.ts`. The standalone `build:meta` task is deprecated — its `--target meta` now warns and no-ops.
|
|
299
306
|
|
|
300
307
|
## License
|
|
301
308
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BuildFormat, BuildPlatform, BuildTargetGroupsOptions, CssOptions, ExeConfig, GenerateMetaOptions, Json, JsxConfig, LooseFiles, MetaOptions, MetaResult, PublishTargets, RenderedOutput, RunExeBuildOptions, TargetGroupRef, TargetResolution, TsconfigJsx, defaultManifestTransform } from "@savvy-web/tsdown-plugins";
|
|
1
|
+
import { BuildFormat, BuildPlatform, BuildTargetGroupsOptions, CssOptions, ExeConfig, GenerateMetaOptions, Json, JsxConfig, LooseFiles, MetaOptions, MetaResult, NextVersions, PublishTargets, RenderedOutput, RunExeBuildOptions, TargetGroupRef, TargetResolution, TsconfigJsx, defaultManifestTransform } from "@savvy-web/tsdown-plugins";
|
|
2
2
|
|
|
3
3
|
//#region src/config.d.ts
|
|
4
4
|
interface BuildEntryOverride {
|
|
@@ -86,10 +86,11 @@ interface BuildConfigInput {
|
|
|
86
86
|
}) => Json;
|
|
87
87
|
readonly output?: OutputConfig;
|
|
88
88
|
/**
|
|
89
|
-
* API-model (meta) generation. Tri-state: omit it (or `undefined`) to generate with
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* `false` to opt OUT
|
|
89
|
+
* API-model (meta) generation. Tri-state: omit it (or `undefined`) to generate with DEFAULT
|
|
90
|
+
* options; `--target prod` emits the meta release asset for every prod group and copies the
|
|
91
|
+
* canonical group's bundle into `localPaths`. Pass an object to override defaults (`localPaths`,
|
|
92
|
+
* `tsdoc`, `optimistic`). Pass `false` to opt OUT (the prod meta asset becomes a no-op).
|
|
93
|
+
* NOTE: `--target meta` is deprecated and now a no-op; meta is a function of `--target prod`.
|
|
93
94
|
*/
|
|
94
95
|
readonly meta?: MetaOptions | false;
|
|
95
96
|
readonly jsx?: JsxConfig | undefined;
|
|
@@ -209,6 +210,8 @@ interface RunOptions {
|
|
|
209
210
|
os: ReadonlyArray<string>;
|
|
210
211
|
cpu: ReadonlyArray<string>;
|
|
211
212
|
}) | undefined;
|
|
213
|
+
/** Injectable for tests: resolves next release versions for the optimistic meta rewrite. */
|
|
214
|
+
readonly resolveNextVersions?: ((cwd: string) => Promise<NextVersions>) | undefined;
|
|
212
215
|
}
|
|
213
216
|
/** Run a build from a normalized config. Pure orchestration; all IO injectable. */
|
|
214
217
|
declare function runBuild(config: BuildConfig, options: RunOptions): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/bundler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Zero-config tsdown-based bundler for Silk Suite TypeScript packages",
|
|
6
6
|
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/bundler",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"./package.json": "./package.json"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@savvy-web/tsdown-plugins": "0.
|
|
32
|
+
"@savvy-web/tsdown-plugins": "0.7.0",
|
|
33
33
|
"@tsdown/exe": "^0.22.1",
|
|
34
|
-
"tsdown": "^0.22.
|
|
34
|
+
"tsdown": "^0.22.3"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"effect": ">=3.21.0"
|
package/run.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseArgs } from "./config.js";
|
|
2
|
-
import { ConfigValidator, ConfigValidatorLive, ReportPipelineLive, buildEmittedManifest, buildTargetGroups, computeExeFileName, createEntryName, generateMeta, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveTargets, runExeBuild, writeResolvedTsconfig, writeTargetsBinding } from "@savvy-web/tsdown-plugins";
|
|
2
|
+
import { ConfigValidator, ConfigValidatorLive, ReportPipelineLive, buildEmittedManifest, buildTargetGroups, computeExeFileName, createEntryName, generateMeta, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveNextVersions, resolveTargets, rewriteMetaVersions, runExeBuild, writeResolvedTsconfig, writeTargetsBinding } from "@savvy-web/tsdown-plugins";
|
|
3
3
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { Effect } from "effect";
|
|
@@ -128,34 +128,10 @@ async function runBuild(config, options) {
|
|
|
128
128
|
const hasJsEntries = Object.keys(entries).length > 0;
|
|
129
129
|
validateSubdirOverrides(config.overrides, entries, packageName);
|
|
130
130
|
if (target === "meta") {
|
|
131
|
-
if (config.meta === false) {
|
|
132
|
-
(options.writeOutput ?? ((o) => process.stdout.write(`${o.content}\n`)))({
|
|
133
|
-
target: "stdout",
|
|
134
|
-
contentType: "text/plain",
|
|
135
|
-
content: `meta: generation disabled (meta: false) for ${packageName}`
|
|
136
|
-
});
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const norm = normalizeMetaOptions(config.meta ?? {});
|
|
140
|
-
const dtsBasenames = {};
|
|
141
|
-
for (const name of Object.keys(entries)) dtsBasenames[name] = name;
|
|
142
|
-
const exportPaths = deriveExportPaths(entries, exportsMap);
|
|
143
|
-
applySubdirMetaEntries(config.overrides, dtsBasenames, exportPaths);
|
|
144
|
-
await runGenerateMeta({
|
|
145
|
-
cwd,
|
|
146
|
-
packageName,
|
|
147
|
-
tsconfigPath,
|
|
148
|
-
dtsDir: join(cwd, "dist", "dev", "pkg"),
|
|
149
|
-
entries: dtsBasenames,
|
|
150
|
-
exportPaths,
|
|
151
|
-
outMetaDir: join(cwd, "dist", "dev", "meta"),
|
|
152
|
-
localPaths: norm.localPaths,
|
|
153
|
-
tsdoc: norm.tsdoc
|
|
154
|
-
});
|
|
155
131
|
(options.writeOutput ?? ((o) => process.stdout.write(`${o.content}\n`)))({
|
|
156
132
|
target: "stdout",
|
|
157
133
|
contentType: "text/plain",
|
|
158
|
-
content: `meta:
|
|
134
|
+
content: `meta: --target meta is deprecated and now a no-op; meta is emitted by --target prod (${packageName}).`
|
|
159
135
|
});
|
|
160
136
|
return;
|
|
161
137
|
}
|
|
@@ -254,22 +230,26 @@ async function runBuild(config, options) {
|
|
|
254
230
|
});
|
|
255
231
|
if (target === "prod" && resolution !== void 0) writeBinding(cwd, resolution);
|
|
256
232
|
if (target === "prod" && config.meta !== false && (config.exe === void 0 || hasJsEntries)) {
|
|
257
|
-
const metaGroupId = (groups.find((g) => g.name === packageName) ?? groups[0])?.id ?? "npm";
|
|
258
233
|
const norm = normalizeMetaOptions(config.meta ?? {});
|
|
234
|
+
const canonicalId = (groups.find((g) => g.name === packageName) ?? groups[0])?.id ?? "npm";
|
|
259
235
|
const dtsBasenames = {};
|
|
260
236
|
for (const name of Object.keys(entries)) dtsBasenames[name] = name;
|
|
261
237
|
const exportPaths = deriveExportPaths(entries, exportsMap);
|
|
262
238
|
applySubdirMetaEntries(config.overrides, dtsBasenames, exportPaths);
|
|
263
|
-
|
|
239
|
+
const resolveNext = options.resolveNextVersions ?? resolveNextVersions;
|
|
240
|
+
const nextVersions = norm.optimistic ? await resolveNext(cwd) : void 0;
|
|
241
|
+
const manifestTransform = nextVersions ? (m) => rewriteMetaVersions(m, nextVersions.versions, packageName) : void 0;
|
|
242
|
+
for (const g of groups) await runGenerateMeta({
|
|
264
243
|
cwd,
|
|
265
244
|
packageName,
|
|
266
245
|
tsconfigPath,
|
|
267
|
-
dtsDir: join(cwd, "dist", "prod",
|
|
246
|
+
dtsDir: join(cwd, "dist", "prod", g.id, "pkg"),
|
|
268
247
|
entries: dtsBasenames,
|
|
269
248
|
exportPaths,
|
|
270
|
-
outMetaDir: join(cwd, "dist", "prod",
|
|
271
|
-
localPaths: [],
|
|
272
|
-
tsdoc: norm.tsdoc
|
|
249
|
+
outMetaDir: join(cwd, "dist", "prod", g.id, "meta"),
|
|
250
|
+
localPaths: g.id === canonicalId ? norm.localPaths : [],
|
|
251
|
+
tsdoc: norm.tsdoc,
|
|
252
|
+
...manifestTransform !== void 0 ? { manifestTransform } : {}
|
|
273
253
|
});
|
|
274
254
|
}
|
|
275
255
|
if (target === "prod") for (const g of groups) removeDeclarationMaps(join(cwd, "dist", "prod", g.id, "pkg"));
|