@savvy-web/bundler 2.0.13 → 2.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/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` declaration output. Override any of it in your own `tsconfig.json`.
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, layered onto the base config. The base build stays as configured; only the listed `entries` (by export subpath) get the override:
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 the base `externals`list what that partition needs. 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.
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 valueevery 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, CopyAmbientDtsOptions, CssOptions, ExeConfig, GenerateMetaOptions, Json, JsxConfig, LooseFiles, MetaOptions, MetaResult, NextVersions, PublishTargets, RenderedOutput, RunExeBuildOptions, TargetGroupRef, TargetResolution, TsconfigJsx, defaultManifestTransform, extractAmbientDts } from "@savvy-web/tsdown-plugins";
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.0.13",
3
+ "version": "2.1.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",
@@ -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.2.2",
35
+ "@savvy-web/tsdown-plugins": "2.3.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, ConfigValidatorLive, ReportPipelineLive, assertNoEntryCollisions, buildEmittedManifest, buildTargetGroups, computeExeFileName, copyAmbientDts, createEntryName, deriveExportPaths, extractAmbientDts, normalizeExeOptions, normalizeLooseFiles, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveTargets, runExeBuild, runMetaPass, writeIssuesArtifact, writeResolvedTsconfig, writeTargetsBinding } from "@savvy-web/tsdown-plugins";
2
+ import { BuildCollector, ConfigValidationError, ConfigValidator, ConfigValidatorLive, ReportPipelineLive, 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";
@@ -280,14 +280,6 @@ async function runBuild(config, options) {
280
280
  });
281
281
  }
282
282
  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
283
  if (config.exe !== void 0 && exeSpec !== void 0 && exeRewrite !== void 0 && exeFileName !== void 0) {
292
284
  const runExe = options.runExeBuild ?? runExeBuild;
293
285
  const groupOutDir = (g) => target === "dev" ? join(cwd, "dist", "dev", "pkg") : join(cwd, "dist", "prod", g.id, "pkg");
@@ -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": true,
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}/types/*.ts",
46
+ "${configDir}/src/*.d.ts",
47
+ "${configDir}/types/*.d.ts",
46
48
  "${configDir}/package.json",
47
49
  "${configDir}/*.ts",
48
50
  "${configDir}/*.cts",