@savvy-web/tsdown-plugins 0.4.1 → 0.5.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 +1 -1
- package/build/build-target-groups.js +16 -6
- package/build/target-groups.js +1 -1
- package/entry/extract.js +2 -1
- package/index.d.ts +42 -3
- package/manifest/emit-manifest.js +4 -2
- package/manifest/transform.js +17 -13
- package/meta/tsconfig-resolver.js +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ export default defineConfig({
|
|
|
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. The `define` option forwards compile-time global replacements to both passes, merged with an auto-injected `process.env.__PACKAGE_VERSION__` constant.
|
|
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. A per-entry override partition can also set `platform` (the JS-pass target, `"browser"` for a client bundle), `css` (forwarded to tsdown's `css` option for `@tsdown/css`) and `outSubdir` (build the partition into an isolated `<group>/pkg/<subdir>/` sub-package). The `define` option forwards compile-time global replacements to both passes, merged with an auto-injected `process.env.__PACKAGE_VERSION__` constant.
|
|
51
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.
|
|
52
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.
|
|
53
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.
|
|
@@ -3,7 +3,7 @@ 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
5
|
import { deriveDtsPassOptions, deriveTargetGroupOptions, outDirFor } from "./target-groups.js";
|
|
6
|
-
import { join } from "node:path";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
7
|
|
|
8
8
|
//#region src/build/build-target-groups.ts
|
|
9
9
|
/**
|
|
@@ -55,27 +55,36 @@ async function buildTargetGroups(options) {
|
|
|
55
55
|
...part.format !== void 0 ? { format: part.format } : {},
|
|
56
56
|
...options.minify !== void 0 ? { minify: options.minify } : {},
|
|
57
57
|
...options.jsx !== void 0 ? { jsx: options.jsx } : {},
|
|
58
|
-
...options.define !== void 0 ? { define: options.define } : {}
|
|
58
|
+
...options.define !== void 0 ? { define: options.define } : {},
|
|
59
|
+
...part.platform !== void 0 ? { platform: part.platform } : {}
|
|
59
60
|
};
|
|
60
61
|
const js = deriveTargetGroupOptions(deriveInput);
|
|
61
62
|
const dts = deriveDtsPassOptions(deriveInput);
|
|
63
|
+
const partOutDir = part.outSubdir !== void 0 ? join(js.outDir, part.outSubdir) : js.outDir;
|
|
62
64
|
const targetGroup = {
|
|
63
65
|
id: group.id,
|
|
64
66
|
name: group.name,
|
|
65
67
|
isProd: js.isProd
|
|
66
68
|
};
|
|
69
|
+
const srcDir = dirname(Object.values(part.entry)[0] ?? "");
|
|
70
|
+
const jsEntry = part.outSubdir !== void 0 ? [
|
|
71
|
+
`${srcDir}/**/*.{ts,tsx,mts,cts}`,
|
|
72
|
+
`!${srcDir}/**/*.{test,spec}.{ts,tsx,mts,cts}`,
|
|
73
|
+
`!${srcDir}/**/*.d.{ts,cts,mts}`
|
|
74
|
+
] : js.entry;
|
|
67
75
|
const manifestPlugin = isBase ? emitManifest({
|
|
68
76
|
targetGroup,
|
|
69
77
|
devManifest: options.devManifest,
|
|
70
78
|
transform: options.transform,
|
|
71
79
|
sourceDir: options.cwd,
|
|
72
|
-
dual: options.dualExports ?? js.format.includes("cjs")
|
|
80
|
+
dual: options.dualExports ?? js.format.includes("cjs"),
|
|
81
|
+
...options.subdirExports !== void 0 ? { subdirExports: options.subdirExports } : {}
|
|
73
82
|
}) : void 0;
|
|
74
83
|
await build({
|
|
75
84
|
config: false,
|
|
76
85
|
cwd: options.cwd,
|
|
77
|
-
entry:
|
|
78
|
-
outDir:
|
|
86
|
+
entry: jsEntry,
|
|
87
|
+
outDir: partOutDir,
|
|
79
88
|
format: js.format,
|
|
80
89
|
platform: js.platform,
|
|
81
90
|
sourcemap: js.sourcemap,
|
|
@@ -85,6 +94,7 @@ async function buildTargetGroups(options) {
|
|
|
85
94
|
fixedExtension: js.fixedExtension,
|
|
86
95
|
dts: js.dts,
|
|
87
96
|
define: js.define,
|
|
97
|
+
...part.css !== void 0 ? { css: part.css } : {},
|
|
88
98
|
...partExternals?.length || partBundleNodeModules || partBundle?.length ? { deps: {
|
|
89
99
|
...partExternals?.length ? { neverBundle: partExternals } : {},
|
|
90
100
|
...partBundle?.length ? { alwaysBundle: partBundle } : {},
|
|
@@ -104,7 +114,7 @@ async function buildTargetGroups(options) {
|
|
|
104
114
|
config: false,
|
|
105
115
|
cwd: options.cwd,
|
|
106
116
|
entry: dts.entry,
|
|
107
|
-
outDir:
|
|
117
|
+
outDir: partOutDir,
|
|
108
118
|
format: dts.format,
|
|
109
119
|
platform: dts.platform,
|
|
110
120
|
sourcemap: dts.sourcemap,
|
package/build/target-groups.js
CHANGED
package/entry/extract.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/entry/extract.ts
|
|
2
|
-
const
|
|
2
|
+
const isDeclarationFile = (p) => p.endsWith(".d.ts") || p.endsWith(".d.cts") || p.endsWith(".d.mts");
|
|
3
|
+
const isTypeScriptFile = (p) => !isDeclarationFile(p) && (p.endsWith(".ts") || p.endsWith(".tsx"));
|
|
3
4
|
/** /dist/*.js to /src/*.ts; otherwise unchanged. */
|
|
4
5
|
const resolveToTypeScript = (p) => p.endsWith(".js") && p.includes("/dist/") ? p.replace("/dist/", "/src/").replace(/\.js$/, ".ts") : p;
|
|
5
6
|
/** Resolve an export value to a source path: import || default || types (NOT require). */
|
package/index.d.ts
CHANGED
|
@@ -74,8 +74,11 @@ declare function defaultManifestTransform({
|
|
|
74
74
|
*
|
|
75
75
|
* The output path is derived from the export KEY via the shared entry-name function,
|
|
76
76
|
* never from the source path, so the manifest target always matches the emitted file.
|
|
77
|
+
*
|
|
78
|
+
* Export keys in `subdirExports` are built into an isolated `<key>/index.*` subdir (e.g. an
|
|
79
|
+
* RSPress `./runtime`), so their conditions gain an `/index` segment.
|
|
77
80
|
*/
|
|
78
|
-
declare function transformExports(exports: unknown, dual?: DualExports): unknown;
|
|
81
|
+
declare function transformExports(exports: unknown, dual?: DualExports, subdirExports?: ReadonlySet<string>): unknown;
|
|
79
82
|
/** Rewrite bin: TS targets to bin/[command].js (string to bin/cli.js); strip leading ./ otherwise. */
|
|
80
83
|
declare function transformBin(bin: unknown): unknown;
|
|
81
84
|
/** FINAL guard: strip leading ./ from bin paths (npm 11.x drops ./-prefixed bins). */
|
|
@@ -85,6 +88,8 @@ interface TransformManifestOptions {
|
|
|
85
88
|
readonly transform?: ((pkg: Json) => Json) | undefined;
|
|
86
89
|
/** Which exports emit dual import/require conditions. boolean = uniform; Set = per-export-key. */
|
|
87
90
|
readonly dual?: DualExports | undefined;
|
|
91
|
+
/** Export keys built into a `<key>/index.*` subdir (e.g. an RSPress `./runtime`). */
|
|
92
|
+
readonly subdirExports?: ReadonlySet<string> | undefined;
|
|
88
93
|
}
|
|
89
94
|
/** Apply the full standard manifest transform (excluding catalog resolution, done upstream). */
|
|
90
95
|
declare function transformManifest(pkg: Json, options?: TransformManifestOptions): Json;
|
|
@@ -106,6 +111,8 @@ interface BuildEmittedManifestOptions {
|
|
|
106
111
|
}) => Json) | undefined;
|
|
107
112
|
/** Which exports emit dual import/require conditions. boolean (uniform) or a Set of export keys (per-entry). */
|
|
108
113
|
readonly dual?: DualExports | undefined;
|
|
114
|
+
/** Export keys built into a `<key>/index.*` subdir (e.g. an RSPress `./runtime`). */
|
|
115
|
+
readonly subdirExports?: ReadonlySet<string> | undefined;
|
|
109
116
|
}
|
|
110
117
|
/** Compute the final manifest bytes for a TargetGroup (catalog resolution + standard transforms). */
|
|
111
118
|
declare function buildEmittedManifest(options: BuildEmittedManifestOptions): Promise<Json>;
|
|
@@ -120,6 +127,8 @@ interface EmitManifestOptions {
|
|
|
120
127
|
readonly sourceDir: string;
|
|
121
128
|
/** Which exports emit dual import/require conditions. boolean (uniform) or a Set of export keys (per-entry). */
|
|
122
129
|
readonly dual?: DualExports | undefined;
|
|
130
|
+
/** Export keys built into a `<key>/index.*` subdir (e.g. an RSPress `./runtime`). */
|
|
131
|
+
readonly subdirExports?: ReadonlySet<string> | undefined;
|
|
123
132
|
}
|
|
124
133
|
/** Rolldown plugin: emit the transformed package.json + LICENSE/README into the output pkg/ root. */
|
|
125
134
|
declare function emitManifest(options: EmitManifestOptions): Plugin;
|
|
@@ -129,6 +138,8 @@ declare function emitManifest(options: EmitManifestOptions): Plugin;
|
|
|
129
138
|
type TargetGroupId = string;
|
|
130
139
|
/** An output module format the build can emit. */
|
|
131
140
|
type BuildFormat = "esm" | "cjs";
|
|
141
|
+
/** Bundling platform for the JS pass. Defaults to "node". Use "browser" for web runtime partitions. */
|
|
142
|
+
type BuildPlatform = "node" | "browser" | "neutral";
|
|
132
143
|
/** A prod/dev group to build: its folder id and the resolved package name its manifest carries. */
|
|
133
144
|
interface BuildGroupSpec {
|
|
134
145
|
readonly id: TargetGroupId;
|
|
@@ -142,6 +153,8 @@ interface DeriveOptions {
|
|
|
142
153
|
readonly tsconfigPath: string;
|
|
143
154
|
readonly devManifest: "preserve" | "resolve";
|
|
144
155
|
readonly externals?: ReadonlyArray<string>;
|
|
156
|
+
/** JS-pass platform. Defaults to "node"; set "browser" for an RSPress runtime partition. */
|
|
157
|
+
readonly platform?: BuildPlatform | undefined;
|
|
145
158
|
/** Output formats to emit. Defaults to esm-only when unset. */
|
|
146
159
|
readonly format?: ReadonlyArray<BuildFormat> | undefined;
|
|
147
160
|
/** Minify prod output (prod groups only; dev is never minified). Defaults to false. */
|
|
@@ -188,7 +201,7 @@ interface DerivedTsdownOptions {
|
|
|
188
201
|
readonly unbundle: true;
|
|
189
202
|
/** JS pass starts fresh; it owns the outDir before the dts pass appends to it. */
|
|
190
203
|
readonly clean: true;
|
|
191
|
-
readonly platform:
|
|
204
|
+
readonly platform: BuildPlatform;
|
|
192
205
|
/**
|
|
193
206
|
* Controls output file extensions. Always false for this builder.
|
|
194
207
|
*
|
|
@@ -270,6 +283,19 @@ declare function normalizeLooseFiles(files: LooseFiles): ReadonlyArray<Normalize
|
|
|
270
283
|
//#region src/build/build-target-groups.d.ts
|
|
271
284
|
/** Signature compatible with tsdown's `build(inlineConfig)`. */
|
|
272
285
|
type TsdownBuild = (config: Record<string, unknown>) => Promise<unknown>;
|
|
286
|
+
/**
|
|
287
|
+
* CSS handling for a partition's JS pass, forwarded VERBATIM to tsdown's `css` option (consumed
|
|
288
|
+
* by `@tsdown/css`). Structurally typed so tsdown-plugins takes no dependency on `@tsdown/css`.
|
|
289
|
+
* The package whose runtime is built must install `@tsdown/css`; tsdown loads it lazily.
|
|
290
|
+
*/
|
|
291
|
+
interface CssOptions {
|
|
292
|
+
readonly modules?: boolean | {
|
|
293
|
+
readonly localsConvention?: string;
|
|
294
|
+
readonly namedExport?: boolean;
|
|
295
|
+
readonly [k: string]: unknown;
|
|
296
|
+
};
|
|
297
|
+
readonly [k: string]: unknown;
|
|
298
|
+
}
|
|
273
299
|
/**
|
|
274
300
|
* One entry partition built with its own format + bundling posture, layered into the
|
|
275
301
|
* SAME outDir as the base build (clean:false). Anything omitted falls back to the base
|
|
@@ -283,6 +309,17 @@ interface EntryOverride {
|
|
|
283
309
|
readonly bundleNodeModules?: boolean | undefined;
|
|
284
310
|
readonly bundledPackages?: ReadonlyArray<string> | undefined;
|
|
285
311
|
readonly dtsExternals?: ReadonlyArray<string> | undefined;
|
|
312
|
+
/** JS-pass platform for this partition. Defaults to the base "node". Use "browser" for a web runtime. */
|
|
313
|
+
readonly platform?: BuildPlatform | undefined;
|
|
314
|
+
/** CSS handling forwarded to tsdown's `css` option (JS pass only). Enables `@tsdown/css`. */
|
|
315
|
+
readonly css?: CssOptions | undefined;
|
|
316
|
+
/**
|
|
317
|
+
* Build this partition into `<groupOutDir>/<outSubdir>/` instead of the shared group root.
|
|
318
|
+
* Isolates a sub-package (e.g. an RSPress `./runtime`) so its bundleless per-file output cannot
|
|
319
|
+
* collide with the base partition's output and its barrel path is deterministic. The partition's
|
|
320
|
+
* entry should be `{ index: <barrel source> }` so it emits `<outSubdir>/index.js` + `<outSubdir>/index.d.ts`.
|
|
321
|
+
*/
|
|
322
|
+
readonly outSubdir?: string | undefined;
|
|
286
323
|
}
|
|
287
324
|
interface BuildTargetGroupsOptions {
|
|
288
325
|
readonly cwd: string;
|
|
@@ -375,6 +412,8 @@ interface BuildTargetGroupsOptions {
|
|
|
375
412
|
* `format`-includes-cjs behavior.
|
|
376
413
|
*/
|
|
377
414
|
readonly dualExports?: DualExports | undefined;
|
|
415
|
+
/** Export keys built into a `<key>/index.*` subdir (e.g. an RSPress `./runtime`). */
|
|
416
|
+
readonly subdirExports?: ReadonlySet<string> | undefined;
|
|
378
417
|
/** Injectable for tests; defaults to tsdown's build. */
|
|
379
418
|
readonly build?: TsdownBuild;
|
|
380
419
|
}
|
|
@@ -1509,5 +1548,5 @@ declare function resolveTargets(options: {
|
|
|
1509
1548
|
baseName: string;
|
|
1510
1549
|
}): TargetResolution;
|
|
1511
1550
|
//#endregion
|
|
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 };
|
|
1551
|
+
export { type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildPlatform, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, type CssOptions, 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 };
|
|
1513
1552
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -19,7 +19,8 @@ async function buildEmittedManifest(options) {
|
|
|
19
19
|
pkg: p,
|
|
20
20
|
targetGroup
|
|
21
21
|
}) : void 0,
|
|
22
|
-
dual: options.dual ?? false
|
|
22
|
+
dual: options.dual ?? false,
|
|
23
|
+
subdirExports: options.subdirExports
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
/** Rolldown plugin: emit the transformed package.json + LICENSE/README into the output pkg/ root. */
|
|
@@ -33,7 +34,8 @@ function emitManifest(options) {
|
|
|
33
34
|
targetGroup: options.targetGroup,
|
|
34
35
|
devManifest: options.devManifest ?? "preserve",
|
|
35
36
|
transform: options.transform,
|
|
36
|
-
dual: options.dual
|
|
37
|
+
dual: options.dual,
|
|
38
|
+
subdirExports: options.subdirExports
|
|
37
39
|
});
|
|
38
40
|
this.emitFile({
|
|
39
41
|
type: "asset",
|
package/manifest/transform.js
CHANGED
|
@@ -50,15 +50,16 @@ const stripLeadingDotSlash = (p) => p.startsWith("./") ? p.slice(2) : p;
|
|
|
50
50
|
* always matches the file tsdown emits. The build never sets exportsAsIndexes, so the
|
|
51
51
|
* manifest mirrors the flat (false) naming here.
|
|
52
52
|
*/
|
|
53
|
-
const toBuiltJs = (exportKey) => `./${createEntryName(exportKey, false)}.js`;
|
|
54
|
-
const toBuiltDts = (exportKey) => toBuiltJs(exportKey).replace(/\.js$/, ".d.ts");
|
|
55
|
-
const toBuiltCjs = (exportKey) => toBuiltJs(exportKey).replace(/\.js$/, ".cjs");
|
|
56
|
-
const
|
|
53
|
+
const toBuiltJs = (exportKey, subdirExports) => subdirExports?.has(exportKey) ? `./${createEntryName(exportKey, false)}/index.js` : `./${createEntryName(exportKey, false)}.js`;
|
|
54
|
+
const toBuiltDts = (exportKey, subdirExports) => toBuiltJs(exportKey, subdirExports).replace(/\.js$/, ".d.ts");
|
|
55
|
+
const toBuiltCjs = (exportKey, subdirExports) => toBuiltJs(exportKey, subdirExports).replace(/\.js$/, ".cjs");
|
|
56
|
+
const isDeclarationFile = (p) => p.endsWith(".d.ts") || p.endsWith(".d.cts") || p.endsWith(".d.mts");
|
|
57
|
+
const isTs = (p) => !isDeclarationFile(p) && (p.endsWith(".ts") || p.endsWith(".tsx"));
|
|
57
58
|
/** Build the conditions object for a TS export target (adds require when dual-format). */
|
|
58
|
-
const tsConditions = (exportKey, dual) => ({
|
|
59
|
-
types: toBuiltDts(exportKey),
|
|
60
|
-
import: toBuiltJs(exportKey),
|
|
61
|
-
...dual ? { require: toBuiltCjs(exportKey) } : {}
|
|
59
|
+
const tsConditions = (exportKey, dual, subdirExports) => ({
|
|
60
|
+
types: toBuiltDts(exportKey, subdirExports),
|
|
61
|
+
import: toBuiltJs(exportKey, subdirExports),
|
|
62
|
+
...dual ? { require: toBuiltCjs(exportKey, subdirExports) } : {}
|
|
62
63
|
});
|
|
63
64
|
/**
|
|
64
65
|
* Rewrite an exports map: TS string targets become a types/import conditions object.
|
|
@@ -67,9 +68,12 @@ const tsConditions = (exportKey, dual) => ({
|
|
|
67
68
|
*
|
|
68
69
|
* The output path is derived from the export KEY via the shared entry-name function,
|
|
69
70
|
* never from the source path, so the manifest target always matches the emitted file.
|
|
71
|
+
*
|
|
72
|
+
* Export keys in `subdirExports` are built into an isolated `<key>/index.*` subdir (e.g. an
|
|
73
|
+
* RSPress `./runtime`), so their conditions gain an `/index` segment.
|
|
70
74
|
*/
|
|
71
|
-
function transformExports(exports, dual = false) {
|
|
72
|
-
if (typeof exports === "string") return isTs(exports) ? tsConditions(".", isDualKey(dual, ".")) : exports;
|
|
75
|
+
function transformExports(exports, dual = false, subdirExports) {
|
|
76
|
+
if (typeof exports === "string") return isTs(exports) ? tsConditions(".", isDualKey(dual, "."), subdirExports) : exports;
|
|
73
77
|
if (exports && typeof exports === "object") {
|
|
74
78
|
const out = {};
|
|
75
79
|
for (const [key, value] of Object.entries(exports)) {
|
|
@@ -77,8 +81,8 @@ function transformExports(exports, dual = false) {
|
|
|
77
81
|
out[key] = value;
|
|
78
82
|
continue;
|
|
79
83
|
}
|
|
80
|
-
if (typeof value === "string" && isTs(value)) out[key] = tsConditions(key, isDualKey(dual, key));
|
|
81
|
-
else out[key] = transformExports(value, dual);
|
|
84
|
+
if (typeof value === "string" && isTs(value)) out[key] = tsConditions(key, isDualKey(dual, key), subdirExports);
|
|
85
|
+
else out[key] = transformExports(value, dual, subdirExports);
|
|
82
86
|
}
|
|
83
87
|
return out;
|
|
84
88
|
}
|
|
@@ -114,7 +118,7 @@ function transformManifest(pkg, options = {}) {
|
|
|
114
118
|
};
|
|
115
119
|
if (result.exports !== void 0 && result.exports !== null) {
|
|
116
120
|
const original = result.exports;
|
|
117
|
-
const transformed = transformExports(original, options.dual ?? false);
|
|
121
|
+
const transformed = transformExports(original, options.dual ?? false, options.subdirExports);
|
|
118
122
|
const asMap = typeof original === "string" ? { ".": transformed } : { ...transformed };
|
|
119
123
|
if (!("./package.json" in asMap)) asMap["./package.json"] = "./package.json";
|
|
120
124
|
result.exports = asMap;
|
|
@@ -97,6 +97,7 @@ var TsconfigResolver = class TsconfigResolver {
|
|
|
97
97
|
[ScriptTarget.ES2022, "es2022"],
|
|
98
98
|
[ScriptTarget.ES2023, "es2023"],
|
|
99
99
|
[ScriptTarget.ES2024, "es2024"],
|
|
100
|
+
[ScriptTarget.ES2025, "es2025"],
|
|
100
101
|
[ScriptTarget.ESNext, "esnext"],
|
|
101
102
|
[ScriptTarget.JSON, "json"]
|
|
102
103
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/tsdown-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@effect/platform-node": "^0.107.0",
|
|
32
|
-
"@microsoft/api-extractor": "^7.58.
|
|
32
|
+
"@microsoft/api-extractor": "^7.58.9",
|
|
33
33
|
"@microsoft/tsdoc": "^0.16.0",
|
|
34
34
|
"@microsoft/tsdoc-config": "^0.18.1",
|
|
35
35
|
"deep-equal": "^2.2.3",
|
|
36
|
-
"json-schema-effect": "^0.2.
|
|
36
|
+
"json-schema-effect": "^0.2.4",
|
|
37
37
|
"picocolors": "^1.1.1",
|
|
38
38
|
"sort-package-json": "^4.0.0",
|
|
39
39
|
"std-env": "^4.1.0",
|