@savvy-web/tsdown-plugins 0.2.1 → 0.4.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
@@ -40,14 +40,15 @@ export default defineConfig({
40
40
  ## Features
41
41
 
42
42
  - **Entry detection** — `packageJsonEntries` and `extractEntries` derive build entries from a package's `exports` and `bin`, matching the rules used across the Silk Suite builders.
43
- - **Manifest transforms** — `transformManifest`, `transformExports`, `transformBin` and `normalizeBinPaths` rewrite a source `package.json` into a publishable one; `emitManifest` is the rolldown plugin that writes it. A dual-format build emits both `import` and `require` export conditions.
43
+ - **Manifest transforms** — `transformManifest`, `transformExports`, `transformBin` and `normalizeBinPaths` rewrite a source `package.json` into a publishable one; `emitManifest` is the rolldown plugin that writes it. A dual-format build emits both `import` and `require` export conditions, and a `"./package.json": "./package.json"` entry is added to the exports map so consumers can `import "<pkg>/package.json"`.
44
44
  - **Catalog resolution** — `resolveManifest` resolves `catalog:` and `workspace:` specifiers against the workspace, delegating to `workspaces-effect`'s `CatalogResolver`.
45
45
  - **Multi-target resolution** — `resolveTargets` turns a `publishConfig.targets` map into the distinct byte-variant groups to build and the registry bindings for each; `writeTargetsBinding` persists that resolution as `dist/prod/targets.json` for the release step.
46
46
  - **JSX resolution** — `resolveJsxConfig` and `readTsconfigJsx` derive the effective JSX transform from a package's tsconfig, with an explicit override winning.
47
47
  - **Executable binaries** — `normalizeExeOptions` fills the SEA defaults and infers targets from the package's `os`/`cpu`; `runExeBuild` drives `@tsdown/exe` to compile the binaries.
48
48
  - **Config validation** — the `ConfigValidator` Effect service (with `ConfigValidatorLive`) fast-fails on a bad `publishConfig.targets`, `exe` or `meta` config, raising the typed `ConfigValidationError`.
49
49
  - **dts tsconfig port** — `buildResolvedTsconfig` and `writeResolvedTsconfig` write a temp tsconfig with absolute paths so type declarations emit cleanly under pnpm symlinks.
50
- - **Per-target build loop** — `deriveTargetGroupOptions` and `buildTargetGroups` map a target to its `tsdown` options and run the build once per target, exposed as a helper so the escape hatch gets multi-target builds too. A `format` of `["esm", "cjs"]` (the `BuildFormat` type) derives a dual-format build — a require-able CJS output with default-export interop and `.d.cts` declarations alongside the ESM one. The `bundleNodeModules`, `bundledPackages` and `dtsExternals` options thread the dependency-bundling posture into both the JS and declaration passes.
50
+ - **Per-target build loop** — `deriveTargetGroupOptions` and `buildTargetGroups` map a target to its `tsdown` options and run the build once per target, exposed as a helper so the escape hatch gets multi-target builds too. A `format` of `["esm", "cjs"]` (the `BuildFormat` type) derives a dual-format build — a require-able CJS output with default-export interop and `.d.cts` declarations alongside the ESM one. The `bundleNodeModules`, `bundledPackages` and `dtsExternals` options thread the dependency-bundling posture into both the JS and declaration passes. The `define` option forwards compile-time global replacements to both passes, merged with an auto-injected `process.env.__PACKAGE_VERSION__` constant.
51
+ - **Loose files** — `normalizeLooseFiles` resolves a `LooseFiles` map of literal output filenames to `NormalizedLooseFile` descriptors, inferring the module format from each `.mjs`/`.cjs` key and raising `ConfigValidationError` on a path separator, an unsupported extension or an ambiguous `.js`. `buildTargetGroups` takes the normalized form as its `looseFiles` option and emits one extra single-entry, bundled, declaration-free and manifest-free pass per file per target group, inheriting the group's bundling posture so each file is self-contained.
51
52
  - **Bundled declarations** — each target runs two `tsdown` passes: a JavaScript pass that preserves per-module output, then a declaration-only pass that rolls every re-exported type into a single `.d.ts` per public entry (`deriveDtsPassOptions`). Per-module JavaScript stays intact while consumers keep reaching re-exported types through your published subpaths.
52
53
  - **API Extractor meta** — `generateMeta` runs [API Extractor](https://api-extractor.com/) over a package's emitted `.d.ts` to write an api-model bundle (`.api.json`, `tsdoc-metadata.json`, resolved `tsconfig.json`); `normalizeMetaOptions` fills the `MetaOptions` defaults that drive it.
53
54
  - **Output reporter** — `renderReport` plus the `BuildReport` schema and a set of formatters (terminal, JSON, markdown, CI annotations, silent) render a build report for humans, agents or CI.
@@ -2,7 +2,7 @@ import { emitManifest } from "../manifest/emit-manifest.js";
2
2
  import { cjsDefaultInterop } from "./cjs-default-interop.js";
3
3
  import { nodeBuiltinDefaultInterop } from "./node-builtin-default-interop.js";
4
4
  import { syncPublicDir } from "./sync-public.js";
5
- import { deriveDtsPassOptions, deriveTargetGroupOptions } from "./target-groups.js";
5
+ import { deriveDtsPassOptions, deriveTargetGroupOptions, outDirFor } from "./target-groups.js";
6
6
  import { join } from "node:path";
7
7
 
8
8
  //#region src/build/build-target-groups.ts
@@ -54,7 +54,8 @@ async function buildTargetGroups(options) {
54
54
  ...partBundledPackages !== void 0 ? { bundledPackages: partBundledPackages } : {},
55
55
  ...part.format !== void 0 ? { format: part.format } : {},
56
56
  ...options.minify !== void 0 ? { minify: options.minify } : {},
57
- ...options.jsx !== void 0 ? { jsx: options.jsx } : {}
57
+ ...options.jsx !== void 0 ? { jsx: options.jsx } : {},
58
+ ...options.define !== void 0 ? { define: options.define } : {}
58
59
  };
59
60
  const js = deriveTargetGroupOptions(deriveInput);
60
61
  const dts = deriveDtsPassOptions(deriveInput);
@@ -126,6 +127,37 @@ async function buildTargetGroups(options) {
126
127
  plugins: [...dts.format.includes("cjs") ? [nodeBuiltinDefaultInterop(), cjsDefaultInterop()] : [], ...options.extraPlugins ?? []]
127
128
  });
128
129
  }
130
+ const looseOutDir = outDirFor(options.cwd, group.id);
131
+ const isProdGroup = group.id !== "dev";
132
+ const looseDeps = {
133
+ ...options.externals?.length ? { neverBundle: options.externals } : {},
134
+ ...options.bundle?.length ? { alwaysBundle: options.bundle } : {},
135
+ ...options.bundleNodeModules ? { skipNodeModulesBundle: false } : {}
136
+ };
137
+ for (const lf of options.looseFiles ?? []) {
138
+ const hasCjs = lf.format === "cjs";
139
+ await build({
140
+ config: false,
141
+ cwd: options.cwd,
142
+ entry: { [lf.entryName]: lf.source },
143
+ outDir: looseOutDir,
144
+ format: [lf.format],
145
+ platform: "node",
146
+ sourcemap: !isProdGroup,
147
+ minify: isProdGroup && (options.minify ?? false),
148
+ unbundle: false,
149
+ clean: false,
150
+ fixedExtension: lf.fixedExtension,
151
+ dts: false,
152
+ define: {
153
+ "process.env.__PACKAGE_VERSION__": JSON.stringify(options.version),
154
+ ...options.define
155
+ },
156
+ ...Object.keys(looseDeps).length > 0 ? { deps: looseDeps } : {},
157
+ ...hasCjs ? { cjsDefault: true } : {},
158
+ plugins: [...hasCjs ? [nodeBuiltinDefaultInterop(), cjsDefaultInterop()] : [], ...options.extraPlugins ?? []]
159
+ });
160
+ }
129
161
  }
130
162
  }
131
163
 
@@ -0,0 +1,57 @@
1
+ import { ConfigValidationError } from "../errors.js";
2
+ import { basename, extname } from "node:path";
3
+
4
+ //#region src/build/loose-files.ts
5
+ /** Extension to its implied format; `.js` is ambiguous (undefined). */
6
+ const EXT_FORMAT = {
7
+ ".mjs": "esm",
8
+ ".cjs": "cjs",
9
+ ".js": void 0
10
+ };
11
+ /**
12
+ * Resolve a `looseFiles` map into normalized build descriptors. Pure (no filesystem):
13
+ * a missing `source` is surfaced later by tsdown's entry resolution. Throws
14
+ * {@link ConfigValidationError} on any structural problem so the bundler's ConfigValidator
15
+ * surfaces it as a typed, fast-fail config error.
16
+ */
17
+ function normalizeLooseFiles(files) {
18
+ const out = [];
19
+ for (const [outFile, raw] of Object.entries(files)) {
20
+ if (basename(outFile) !== outFile) throw new ConfigValidationError({
21
+ path: `looseFiles."${outFile}"`,
22
+ reason: "a loose file must be a root-level filename with no path separator"
23
+ });
24
+ const ext = extname(outFile);
25
+ if (!(ext in EXT_FORMAT)) throw new ConfigValidationError({
26
+ path: `looseFiles."${outFile}"`,
27
+ reason: `unsupported output extension "${ext}" — use .mjs, .cjs, or .js`
28
+ });
29
+ const source = typeof raw === "string" ? raw : raw.source;
30
+ const explicit = typeof raw === "string" ? void 0 : raw.format;
31
+ const inferred = EXT_FORMAT[ext];
32
+ if (inferred !== void 0 && explicit !== void 0 && explicit !== inferred) throw new ConfigValidationError({
33
+ path: `looseFiles."${outFile}".format`,
34
+ reason: `format "${explicit}" contradicts the "${ext}" extension (which implies "${inferred}")`
35
+ });
36
+ if (inferred === void 0 && explicit === void 0) throw new ConfigValidationError({
37
+ path: `looseFiles."${outFile}".format`,
38
+ reason: "a \".js\" output is format-ambiguous — set format: \"esm\""
39
+ });
40
+ const format = inferred ?? explicit;
41
+ if (ext === ".js" && format === "cjs") throw new ConfigValidationError({
42
+ path: `looseFiles."${outFile}"`,
43
+ reason: "a CJS file named \".js\" is not supported yet — name it \".cjs\""
44
+ });
45
+ out.push({
46
+ outFile,
47
+ entryName: basename(outFile, ext),
48
+ source,
49
+ format,
50
+ fixedExtension: ext !== ".js"
51
+ });
52
+ }
53
+ return out;
54
+ }
55
+
56
+ //#endregion
57
+ export { normalizeLooseFiles };
@@ -1,6 +1,7 @@
1
1
  import { join } from "node:path";
2
2
 
3
3
  //#region src/build/target-groups.ts
4
+ /** The output dir for a group: dev -> dist/dev/pkg, prod -> dist/prod/<group>/pkg. */
4
5
  const outDirFor = (cwd, group) => group === "dev" ? join(cwd, "dist/dev/pkg") : join(cwd, "dist/prod", group, "pkg");
5
6
  /** Derive the JS-pass tsdown options for one TargetGroup (per-module JS, no dts). */
6
7
  function deriveTargetGroupOptions(options) {
@@ -18,7 +19,10 @@ function deriveTargetGroupOptions(options) {
18
19
  fixedExtension: false,
19
20
  entry: options.entry,
20
21
  dts: false,
21
- define: { __PACKAGE_VERSION__: JSON.stringify(options.version) },
22
+ define: {
23
+ "process.env.__PACKAGE_VERSION__": JSON.stringify(options.version),
24
+ ...options.define
25
+ },
22
26
  isProd,
23
27
  ...hasCjs ? { cjsDefault: true } : {},
24
28
  ...options.jsx !== void 0 ? { jsx: options.jsx } : {}
@@ -41,7 +45,10 @@ function deriveDtsPassOptions(options) {
41
45
  tsconfig: options.tsconfigPath,
42
46
  emitDtsOnly: true
43
47
  },
44
- define: { __PACKAGE_VERSION__: JSON.stringify(options.version) },
48
+ define: {
49
+ "process.env.__PACKAGE_VERSION__": JSON.stringify(options.version),
50
+ ...options.define
51
+ },
45
52
  isProd,
46
53
  ...options.jsx !== void 0 ? { jsx: options.jsx } : {},
47
54
  ...options.bundledPackages !== void 0 ? { bundledPackages: options.bundledPackages } : {}
@@ -49,4 +56,4 @@ function deriveDtsPassOptions(options) {
49
56
  }
50
57
 
51
58
  //#endregion
52
- export { deriveDtsPassOptions, deriveTargetGroupOptions };
59
+ export { deriveDtsPassOptions, deriveTargetGroupOptions, outDirFor };
@@ -1,5 +1,6 @@
1
- import { ConfigValidator } from "./ConfigValidator.js";
2
1
  import { ConfigValidationError } from "../errors.js";
2
+ import { normalizeLooseFiles } from "../build/loose-files.js";
3
+ import { ConfigValidator } from "./ConfigValidator.js";
3
4
  import { normalizeExeOptions } from "../exe/config.js";
4
5
  import { resolveTargets } from "../targets/resolve-targets.js";
5
6
  import { Effect, Layer } from "effect";
@@ -47,6 +48,7 @@ function check(input) {
47
48
  reason: `"${p}" exists but is not a directory`
48
49
  });
49
50
  }
51
+ if (input.looseFiles !== void 0) normalizeLooseFiles(input.looseFiles);
50
52
  }
51
53
  /** Live ConfigValidator: wraps the synchronous rule set, surfacing ConfigValidationError as a typed Effect failure. */
52
54
  const ConfigValidatorLive = Layer.succeed(ConfigValidator, { validate: (input) => Effect.try({
package/index.d.ts CHANGED
@@ -148,6 +148,12 @@ interface DeriveOptions {
148
148
  readonly minify?: boolean | undefined;
149
149
  /** JSX transform settings to forward to rolldown's inputOptions. */
150
150
  readonly jsx?: JsxConfig | undefined;
151
+ /**
152
+ * Compile-time global replacements forwarded to the build `define`. Merged AFTER the
153
+ * auto-injected `process.env.__PACKAGE_VERSION__` so a user key of the same name wins.
154
+ * Values are inserted verbatim (string literals must already be quoted).
155
+ */
156
+ readonly define?: Record<string, string> | undefined;
151
157
  /**
152
158
  * External packages whose declarations should be INLINED into the bundled dts
153
159
  * (the rslib `dtsBundledPackages` equivalent). Maps to tsdown's `deps.onlyBundle`
@@ -227,6 +233,40 @@ interface DerivedTsdownOptions {
227
233
  /** Derive the JS-pass tsdown options for one TargetGroup (per-module JS, no dts). */
228
234
  declare function deriveTargetGroupOptions(options: DeriveOptions): DerivedTsdownOptions;
229
235
  //#endregion
236
+ //#region src/build/loose-files.d.ts
237
+ /** One standalone bundled output file, declared by its literal output filename. */
238
+ interface LooseFileSpec {
239
+ /** Source module to bundle into the file. */
240
+ readonly source: string;
241
+ /** Module format. Required only for an ambiguous `.js` key; inferred from `.mjs`/`.cjs`. */
242
+ readonly format?: BuildFormat | undefined;
243
+ }
244
+ /** Map of literal output filename to its source (bare string) or a `{ source, format }` spec. */
245
+ type LooseFiles = Record<string, string | LooseFileSpec>;
246
+ /** A loose file resolved to a concrete build descriptor. */
247
+ interface NormalizedLooseFile {
248
+ /** Literal output filename written into the package dir, e.g. `pnpmfile.mjs`. */
249
+ readonly outFile: string;
250
+ /** tsdown entry name (outFile without its extension), e.g. `pnpmfile`. */
251
+ readonly entryName: string;
252
+ /** Source module to bundle. */
253
+ readonly source: string;
254
+ /** Resolved module format. */
255
+ readonly format: BuildFormat;
256
+ /**
257
+ * Whether tsdown should use fixed extensions. `.mjs`/`.cjs` need `true` (tsdown derives
258
+ * `.mjs` for esm and `.cjs` for cjs); a `.js` + esm output needs `false` (tsdown derives `.js`).
259
+ */
260
+ readonly fixedExtension: boolean;
261
+ }
262
+ /**
263
+ * Resolve a `looseFiles` map into normalized build descriptors. Pure (no filesystem):
264
+ * a missing `source` is surfaced later by tsdown's entry resolution. Throws
265
+ * {@link ConfigValidationError} on any structural problem so the bundler's ConfigValidator
266
+ * surfaces it as a typed, fast-fail config error.
267
+ */
268
+ declare function normalizeLooseFiles(files: LooseFiles): ReadonlyArray<NormalizedLooseFile>;
269
+ //#endregion
230
270
  //#region src/build/build-target-groups.d.ts
231
271
  /** Signature compatible with tsdown's `build(inlineConfig)`. */
232
272
  type TsdownBuild = (config: Record<string, unknown>) => Promise<unknown>;
@@ -309,12 +349,26 @@ interface BuildTargetGroupsOptions {
309
349
  readonly extraPlugins?: ReadonlyArray<Plugin>;
310
350
  /** JSX transform settings forwarded to rolldown's inputOptions. */
311
351
  readonly jsx?: JsxConfig | undefined;
352
+ /**
353
+ * Compile-time global replacements forwarded to BOTH the JS and dts passes' `define`.
354
+ * Build-wide (shared by every entry partition); merged after the auto-injected
355
+ * `process.env.__PACKAGE_VERSION__` so a user key of the same name wins.
356
+ */
357
+ readonly define?: Record<string, string> | undefined;
312
358
  /**
313
359
  * Entry partitions with their own format/bundling, built into the same outDir after
314
360
  * the base entries. Used for per-entry format overrides (e.g. one CJS entry in an
315
361
  * otherwise ESM-only package). The base `entry` must already EXCLUDE these entries.
316
362
  */
317
363
  readonly overrides?: ReadonlyArray<EntryOverride> | undefined;
364
+ /**
365
+ * Standalone bundled output files emitted at literal paths into each group's pkg/ dir,
366
+ * outside the exports/dts/meta graph (e.g. pnpm config-dependency pnpmfiles). Each runs as
367
+ * one extra single-entry, bundled (unbundle:false), no-dts, no-manifest pass per group,
368
+ * inheriting the group's bundleNodeModules/bundle/externals posture so the file is
369
+ * self-contained. Caller passes the normalized form (see normalizeLooseFiles).
370
+ */
371
+ readonly looseFiles?: ReadonlyArray<NormalizedLooseFile> | undefined;
318
372
  /**
319
373
  * Which export keys get a CJS `require` condition in the emitted manifest. Pass a Set
320
374
  * when overrides give different entries different formats; omit for the uniform
@@ -618,6 +672,8 @@ interface ValidationInput {
618
672
  readonly cpu: ReadonlyArray<string>;
619
673
  } | undefined;
620
674
  readonly meta?: MetaOptions | undefined;
675
+ /** Standalone bundled output files; validated structurally (extension/format) before any build. */
676
+ readonly looseFiles?: LooseFiles | undefined;
621
677
  }
622
678
  declare const ConfigValidator_base: Context.TagClass<ConfigValidator, "@savvy-web/tsdown-plugins/ConfigValidator", {
623
679
  readonly validate: (input: ValidationInput) => Effect.Effect<void, ConfigValidationError>;
@@ -1453,5 +1509,5 @@ declare function resolveTargets(options: {
1453
1509
  baseName: string;
1454
1510
  }): TargetResolution;
1455
1511
  //#endregion
1456
- export { type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, type DeriveOptions, type DerivedTsdownOptions, type DualExports, type EmitManifestOptions, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, ExecutorResolver, ExecutorResolverLive, type ExtractOptions, type ExtractResult, FormatSelector, FormatSelectorLive, type Formatter, type FormatterContext, type GenerateMetaOptions, type Json, JsonFormatter, type JsxConfig, type ManifestLike, MarkdownFormatter, MetaGenerationError, type MetaOptions, type MetaResult, type NormalizedExe, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PkgOsCpu, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, SilentFormatter, type TargetGroupId, type TargetGroupRef, type TargetGroupReport, TargetGroupReport as TargetGroupReportSchema, type TargetResolution, TerminalFormatter, type Timer, type TransformManifestOptions, type TsconfigJsx, TsconfigResolver, type TsdocOptions, type TsdocTagDefinition, type TsdownBuild, type ValidationInput, type WarningSuppressionRule, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolvePortableTsconfig, resolveTargets, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
1512
+ export { type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, type DeriveOptions, type DerivedTsdownOptions, type DualExports, type EmitManifestOptions, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, ExecutorResolver, ExecutorResolverLive, type ExtractOptions, type ExtractResult, FormatSelector, FormatSelectorLive, type Formatter, type FormatterContext, type GenerateMetaOptions, type Json, JsonFormatter, type JsxConfig, type LooseFileSpec, type LooseFiles, type ManifestLike, MarkdownFormatter, MetaGenerationError, type MetaOptions, type MetaResult, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PkgOsCpu, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, SilentFormatter, type TargetGroupId, type TargetGroupRef, type TargetGroupReport, TargetGroupReport as TargetGroupReportSchema, type TargetResolution, TerminalFormatter, type Timer, type TransformManifestOptions, type TsconfigJsx, TsconfigResolver, type TsdocOptions, type TsdocTagDefinition, type TsdownBuild, type ValidationInput, type WarningSuppressionRule, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolvePortableTsconfig, resolveTargets, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
1457
1513
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -7,9 +7,10 @@ import { nodeBuiltinDefaultInterop } from "./build/node-builtin-default-interop.
7
7
  import { syncPublicDir } from "./build/sync-public.js";
8
8
  import { deriveTargetGroupOptions } from "./build/target-groups.js";
9
9
  import { buildTargetGroups } from "./build/build-target-groups.js";
10
+ import { ConfigValidationError, MetaGenerationError } from "./errors.js";
11
+ import { normalizeLooseFiles } from "./build/loose-files.js";
10
12
  import { removeDeclarationMaps } from "./build/strip-maps.js";
11
13
  import { ConfigValidator } from "./config-validation/ConfigValidator.js";
12
- import { ConfigValidationError, MetaGenerationError } from "./errors.js";
13
14
  import { DEFAULT_EXE_NODE_VERSION, normalizeExeOptions } from "./exe/config.js";
14
15
  import { isTargetObject } from "./targets/config.js";
15
16
  import { resolveTargets } from "./targets/resolve-targets.js";
@@ -41,4 +42,4 @@ import { generateBuildReportSchema } from "./report/schema-export.js";
41
42
  import { writeTargetsBinding } from "./targets/binding.js";
42
43
  import { CatalogAssemblyError, CatalogResolutionError } from "workspaces-effect";
43
44
 
44
- export { BuildReport as BuildReportSchema, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, JsonFormatter, MarkdownFormatter, MetaGenerationError, OutputRenderer, OutputRendererLive, ReportPipelineLive, ReportTimings, SilentFormatter, TargetGroupReport as TargetGroupReportSchema, TerminalFormatter, TsconfigResolver, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolvePortableTsconfig, resolveTargets, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
45
+ export { BuildReport as BuildReportSchema, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, DEFAULT_EXE_NODE_VERSION, EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, JsonFormatter, MarkdownFormatter, MetaGenerationError, OutputRenderer, OutputRendererLive, ReportPipelineLive, ReportTimings, SilentFormatter, TargetGroupReport as TargetGroupReportSchema, TerminalFormatter, TsconfigResolver, buildEmittedManifest, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, createEntryName, createTimer, defaultManifestTransform, deriveTargetGroupOptions, emitManifest, extractEntries, formatTime, generateBuildReportSchema, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveManifest, resolvePortableTsconfig, resolveTargets, runExeBuild, syncPublicDir, transformBin, transformExports, transformManifest, writeResolvedTsconfig, writeTargetsBinding };
@@ -112,7 +112,13 @@ function transformManifest(pkg, options = {}) {
112
112
  ...rest,
113
113
  private: isPrivate
114
114
  };
115
- if (result.exports) result.exports = transformExports(result.exports, options.dual ?? false);
115
+ if (result.exports !== void 0 && result.exports !== null) {
116
+ const original = result.exports;
117
+ const transformed = transformExports(original, options.dual ?? false);
118
+ const asMap = typeof original === "string" ? { ".": transformed } : { ...transformed };
119
+ if (!("./package.json" in asMap)) asMap["./package.json"] = "./package.json";
120
+ result.exports = asMap;
121
+ }
116
122
  if (result.bin) result.bin = transformBin(result.bin);
117
123
  if (options.transform) result = options.transform(result);
118
124
  if (result.bin) result.bin = normalizeBinPaths(result.bin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/tsdown-plugins",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Interface-only tsdown/rolldown plugin pack powering @savvy-web/bundler",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/tsdown-plugins",
@@ -24,7 +24,8 @@
24
24
  ".": {
25
25
  "types": "./index.d.ts",
26
26
  "import": "./index.js"
27
- }
27
+ },
28
+ "./package.json": "./package.json"
28
29
  },
29
30
  "dependencies": {
30
31
  "@effect/platform-node": "^0.106.0",