@savvy-web/bundler 2.0.13 → 2.1.1
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 +15 -3
- package/env.d.ts +12 -0
- package/index.d.ts +1 -3
- package/package.json +5 -2
- package/run.js +7 -13
- package/tsconfig/ecma.json +4 -2
package/README.md
CHANGED
|
@@ -58,7 +58,11 @@ The bundler ships its shared TypeScript base as a subpath export. Extend it from
|
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
`ecma.json` sets ESNext libs, NodeNext resolution, strict mode and `composite`
|
|
61
|
+
`ecma.json` sets ESNext libs, NodeNext resolution, strict mode and declaration emit (`declaration: true`, `composite: false`). Override any of it in your own `tsconfig.json`.
|
|
62
|
+
|
|
63
|
+
Pick the one preset that matches your package type and extend it once: `@savvy-web/bundler/tsconfig/ecma.json` for a plain Node library, `@savvy-web/rspress-builder/tsconfig/plugin.json` for an RSPress plugin, `@savvy-web/github-action-builder/tsconfig/action.json` for a GitHub Action. Each preset is a complete, self-contained config for its package type — none of them uses `extends` internally, so you never need to compose or chain them together.
|
|
64
|
+
|
|
65
|
+
That design choice exists because TypeScript's own `extends` replaces array-valued compiler options rather than merging them. If you override `types` or `lib` in your own `tsconfig.json`, the override replaces the base preset's list outright instead of adding to it, so you have to re-list every entry you still need, `node` included, or lose it silently — the symptom is `console`, `process` and `Buffer` no longer resolving. `packages/rspress-builder/public/tsconfig/plugin.json` illustrates both points at once: it is a fully self-contained preset for RSPress plugins, and it declares `types: ["node", "react", "react-dom"]` rather than assuming `node` inherits.
|
|
62
66
|
|
|
63
67
|
## Multi-target publishing
|
|
64
68
|
|
|
@@ -206,7 +210,7 @@ const config = defineBuild({
|
|
|
206
210
|
|
|
207
211
|
## Per-entry overrides
|
|
208
212
|
|
|
209
|
-
The format and bundling fields above apply to every export entry. Use `overrides` to pin a subset of entries to their own format and bundling
|
|
213
|
+
The format and bundling fields above apply to every export entry. Use `overrides` to pin a subset of entries to their own format and bundling. Each override is built from its own values alone — it does not inherit from the base config, so every field it needs must be listed again (see below). The base build stays as configured; only the listed `entries` (by export subpath) get the override:
|
|
210
214
|
|
|
211
215
|
```ts
|
|
212
216
|
const config = defineBuild({
|
|
@@ -223,7 +227,7 @@ const config = defineBuild({
|
|
|
223
227
|
});
|
|
224
228
|
```
|
|
225
229
|
|
|
226
|
-
Each override carries the same `format`, `bundle`, `externals`, `bundleNodeModules`, `bundledPackages` and `dtsExternals` fields as the base config, plus three partition-only fields: `platform` (the JS-pass target, `"node"` by default or `"browser"` for a client runtime), `css` (forwarded to tsdown's `css` option to enable `@tsdown/css`) and `outSubdir` (builds the partition into an isolated `<group>/pkg/<subdir>/` sub-package, for which exactly one export path may be pinned). An override does not inherit
|
|
230
|
+
Each override carries the same `format`, `bundle`, `externals`, `bundleNodeModules`, `bundledPackages` and `dtsExternals` fields as the base config, plus three partition-only fields: `platform` (the JS-pass target, `"node"` by default or `"browser"` for a client runtime), `css` (forwarded to tsdown's `css` option to enable `@tsdown/css`) and `outSubdir` (builds the partition into an isolated `<group>/pkg/<subdir>/` sub-package, for which exactly one export path may be pinned). An override does not inherit any base-config value — every field it needs, including `externals`, must be listed again. The build errors if an override names an export path the package does not declare. These partition fields are what [`@savvy-web/rspress-builder`](https://www.npmjs.com/package/@savvy-web/rspress-builder) composes to build an RSPress plugin's browser runtime bundle.
|
|
227
231
|
|
|
228
232
|
## Loose files
|
|
229
233
|
|
|
@@ -308,6 +312,14 @@ const config = defineBuild({
|
|
|
308
312
|
|
|
309
313
|
`define` merges with the auto-injected version constant; a key of `process.env.__PACKAGE_VERSION__` in your own `define` wins.
|
|
310
314
|
|
|
315
|
+
`@savvy-web/bundler` ships an ambient declaration for that injected key as its own `./env` types-only export, so a consumer's `process.env.__PACKAGE_VERSION__` resolves instead of falling through `@types/node`'s untyped index signature. Add a triple-slash reference to a `.d.ts` in your project to pull it in:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
/// <reference types="@savvy-web/bundler/env" />
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
That gives you `readonly __PACKAGE_VERSION__?: string` on `NodeJS.ProcessEnv` — optional, matching the `?? "0.0.0"` fallback every consumer already uses for unbuilt source.
|
|
322
|
+
|
|
311
323
|
## Features
|
|
312
324
|
|
|
313
325
|
- **One self-executing config** — `savvy.build.ts` is a top-level `await build({...})` call that derives `cwd` and `argv` from process globals. No main guard, no `export default`, no factory-notation config file.
|
package/env.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Ambient process.env declaration for packages built with @savvy-web/bundler.
|
|
2
|
+
|
|
3
|
+
declare namespace NodeJS {
|
|
4
|
+
interface ProcessEnv {
|
|
5
|
+
/**
|
|
6
|
+
* The built package's version, injected at build time by `@savvy-web/bundler`
|
|
7
|
+
* (`buildTargetGroups`'s `define`, `process.env.__PACKAGE_VERSION__`). Absent when running
|
|
8
|
+
* unbuilt source — a consumer reading it should fall back, e.g. `?? "0.0.0"`.
|
|
9
|
+
*/
|
|
10
|
+
readonly __PACKAGE_VERSION__?: string;
|
|
11
|
+
}
|
|
12
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AmbientDtsEntry, BuildFormat, BuildPlatform, BuildReport, BuildTargetGroupsOptions,
|
|
1
|
+
import { AmbientDtsEntry, BuildFormat, BuildPlatform, BuildReport, BuildTargetGroupsOptions, CssOptions, ExeConfig, GenerateMetaOptions, Json, JsxConfig, LooseFiles, MetaOptions, MetaResult, NextVersions, PublishTargets, RenderedOutput, RunExeBuildOptions, TargetGroupRef, TargetResolution, TsconfigJsx, defaultManifestTransform, extractAmbientDts } from "@savvy-web/tsdown-plugins";
|
|
2
2
|
import { Plugin, Plugin as Plugin$1 } from "rolldown";
|
|
3
3
|
//#region src/config.d.ts
|
|
4
4
|
/** @public */
|
|
@@ -269,8 +269,6 @@ interface RunOptions {
|
|
|
269
269
|
message: string;
|
|
270
270
|
} | undefined;
|
|
271
271
|
}) => string | undefined;
|
|
272
|
-
/** Injectable ambient-.d.ts copier (defaults to copyAmbientDts). */
|
|
273
|
-
readonly copyAmbientDts?: ((o: CopyAmbientDtsOptions) => void) | undefined;
|
|
274
272
|
}
|
|
275
273
|
/** Run a build from a normalized config. Pure orchestration; all IO injectable. @public */
|
|
276
274
|
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": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
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",
|
|
@@ -25,11 +25,14 @@
|
|
|
25
25
|
"import": "./index.js",
|
|
26
26
|
"default": "./index.js"
|
|
27
27
|
},
|
|
28
|
+
"./env": {
|
|
29
|
+
"types": "./env.d.ts"
|
|
30
|
+
},
|
|
28
31
|
"./tsconfig/ecma.json": "./tsconfig/ecma.json",
|
|
29
32
|
"./package.json": "./package.json"
|
|
30
33
|
},
|
|
31
34
|
"dependencies": {
|
|
32
|
-
"@savvy-web/tsdown-plugins": "2.
|
|
35
|
+
"@savvy-web/tsdown-plugins": "2.4.0",
|
|
33
36
|
"@tsdown/exe": "^0.22.14",
|
|
34
37
|
"effect": "4.0.0-beta.101",
|
|
35
38
|
"rolldown": "^1.2.0",
|
package/run.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineBuild, parseArgs } from "./config.js";
|
|
2
|
-
import { BuildCollector, ConfigValidationError, ConfigValidator,
|
|
2
|
+
import { BuildCollector, ConfigValidationError, ConfigValidator, ReportPipeline, assertNoEntryCollisions, buildEmittedManifest, buildTargetGroups, computeExeFileName, createEntryName, deriveExportPaths, extractAmbientDts, normalizeExeOptions, normalizeLooseFiles, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveTargets, runExeBuild, runMetaPass, writeIssuesArtifact, writeResolvedTsconfig, writeTargetsBinding } from "@savvy-web/tsdown-plugins";
|
|
3
3
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { Effect } from "effect";
|
|
@@ -32,8 +32,9 @@ function readPackageJson(cwd) {
|
|
|
32
32
|
}
|
|
33
33
|
/** Resolve the prod build groups and the target binding from publishConfig.targets (or the single-npm default). */
|
|
34
34
|
function deriveProdGroups(targets, baseName) {
|
|
35
|
+
const effective = targets !== void 0 && Object.keys(targets).length > 0 ? targets : { npm: true };
|
|
35
36
|
const resolution = resolveTargets({
|
|
36
|
-
targets:
|
|
37
|
+
targets: effective,
|
|
37
38
|
baseName
|
|
38
39
|
});
|
|
39
40
|
return {
|
|
@@ -87,7 +88,8 @@ async function runBuild(config, options) {
|
|
|
87
88
|
};
|
|
88
89
|
let renderAndWrite;
|
|
89
90
|
try {
|
|
90
|
-
const
|
|
91
|
+
const readJsx = options.readTsconfigJsx ?? (() => readTsconfigJsx(cwd));
|
|
92
|
+
const jsx = resolveJsxConfig(readJsx(), config.jsx);
|
|
91
93
|
const tsconfigPath = (options.writeTsconfig ?? ((c) => writeResolvedTsconfig({
|
|
92
94
|
cwd: c,
|
|
93
95
|
...jsx?.runtime === "automatic" ? {
|
|
@@ -114,7 +116,7 @@ async function runBuild(config, options) {
|
|
|
114
116
|
osCpu: osCpuForValidate,
|
|
115
117
|
...config.meta !== void 0 && config.meta !== false ? { meta: config.meta } : {},
|
|
116
118
|
...config.looseFiles !== void 0 ? { looseFiles: config.looseFiles } : {}
|
|
117
|
-
})).pipe(Effect.provide(
|
|
119
|
+
})).pipe(Effect.provide(ConfigValidator.layer)));
|
|
118
120
|
const exeSpecs = config.exe !== void 0 ? normalizeExeOptions(config.exe, osCpuForValidate) : [];
|
|
119
121
|
if (config.exe !== void 0 && (exeSpecs.length !== 1 || (exeSpecs[0]?.targets.length ?? 0) !== 1)) throw new Error(`exe build requires exactly one binary with one target (got ${exeSpecs.length} spec(s), ${exeSpecs[0]?.targets.length ?? 0} target(s) on the first). A package's exports["."] resolves to a single SEA — cross-platform binaries must each ship as their own per-platform package.`);
|
|
120
122
|
const exeSpec = exeSpecs[0];
|
|
@@ -231,7 +233,7 @@ async function runBuild(config, options) {
|
|
|
231
233
|
...explicitFormat !== void 0 ? { explicitFormat } : {},
|
|
232
234
|
verbose,
|
|
233
235
|
noColor: process.env.NO_COLOR !== void 0 || !process.stdout.isTTY
|
|
234
|
-
}).pipe(Effect.provide(
|
|
236
|
+
}).pipe(Effect.provide(ReportPipeline)));
|
|
235
237
|
for (const output of rendered) writeOutput(output);
|
|
236
238
|
};
|
|
237
239
|
if (hasJsEntries || config.exe === void 0) await build({
|
|
@@ -280,14 +282,6 @@ async function runBuild(config, options) {
|
|
|
280
282
|
});
|
|
281
283
|
}
|
|
282
284
|
if (target === "prod") for (const g of groups) removeDeclarationMaps(join(cwd, "dist", "prod", g.id, "pkg"));
|
|
283
|
-
if (ambient.length > 0 && (target === "dev" || target === "prod")) {
|
|
284
|
-
const copyAmbient = options.copyAmbientDts ?? copyAmbientDts;
|
|
285
|
-
for (const g of groups) copyAmbient({
|
|
286
|
-
ambient,
|
|
287
|
-
srcCwd: cwd,
|
|
288
|
-
outDir: target === "dev" ? join(cwd, "dist", "dev", "pkg") : join(cwd, "dist", "prod", g.id, "pkg")
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
285
|
if (config.exe !== void 0 && exeSpec !== void 0 && exeRewrite !== void 0 && exeFileName !== void 0) {
|
|
292
286
|
const runExe = options.runExeBuild ?? runExeBuild;
|
|
293
287
|
const groupOutDir = (g) => target === "dev" ? join(cwd, "dist", "dev", "pkg") : join(cwd, "dist", "prod", g.id, "pkg");
|
package/tsconfig/ecma.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
+
"//": "types and lib REPLACE the base list rather than merging with it. If you override either, re-list every entry you still need, including node.",
|
|
2
3
|
"$schema": "https://json.schemastore.org/tsconfig.json",
|
|
3
4
|
"compilerOptions": {
|
|
4
5
|
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"composite":
|
|
6
|
+
"composite": false,
|
|
6
7
|
"declaration": true,
|
|
7
8
|
"declarationDir": "${configDir}/dist",
|
|
8
9
|
"declarationMap": false,
|
|
@@ -42,7 +43,8 @@
|
|
|
42
43
|
"${configDir}/__fixtures__/**/*"
|
|
43
44
|
],
|
|
44
45
|
"include": [
|
|
45
|
-
"${configDir}/
|
|
46
|
+
"${configDir}/src/*.d.ts",
|
|
47
|
+
"${configDir}/types/*.d.ts",
|
|
46
48
|
"${configDir}/package.json",
|
|
47
49
|
"${configDir}/*.ts",
|
|
48
50
|
"${configDir}/*.cts",
|