@savvy-web/bundler 0.4.2 → 0.6.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 +2 -2
- package/config.js +4 -1
- package/index.d.ts +13 -1
- package/package.json +3 -2
- package/public/ecma.json +1 -1
- package/run.js +117 -20
package/README.md
CHANGED
|
@@ -200,7 +200,7 @@ const config = defineBuild({
|
|
|
200
200
|
});
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
Each override carries the same `format`, `bundle`, `externals`, `bundleNodeModules`, `bundledPackages` and `dtsExternals` fields as the base config. 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.
|
|
203
|
+
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.
|
|
204
204
|
|
|
205
205
|
## Loose files
|
|
206
206
|
|
|
@@ -277,7 +277,7 @@ const config = defineBuild({
|
|
|
277
277
|
- **JSX, config-first** — JSX transform is inherited from `tsconfig.json` and overridable via the `jsx` field, feeding both the dts tsconfig and the tsdown transform.
|
|
278
278
|
- **Dual-format output** — esm-only by default; set `format` to `["esm", "cjs"]` for a require-able CJS output with default-export interop, `.d.cts` declarations and dual `import`/`require` export conditions.
|
|
279
279
|
- **Dependency bundling** — declared dependencies stay external by default; `bundle`, `bundleNodeModules`, `bundledPackages` and `dtsExternals` force-inline specific packages or all node_modules into the output, inline select declarations into the `.d.ts` or hold a package out of the declaration bundle when its types cannot be inlined.
|
|
280
|
-
- **Per-entry overrides** — `overrides` pins a subset of export entries to their own format and bundling, so one entry can ship dual-format CJS in an otherwise ESM-only package without changing the rest.
|
|
280
|
+
- **Per-entry overrides** — `overrides` pins a subset of export entries to their own format and bundling, so one entry can ship dual-format CJS in an otherwise ESM-only package without changing the rest; partition-only `platform`, `css` and `outSubdir` fields also let an entry build for the browser with CSS modules into its own sub-package.
|
|
281
281
|
- **Loose files** — `looseFiles` emits standalone bundled files at literal output paths outside the exports/declaration/api-model graph, with the format inferred from the key extension; pair with `bundleNodeModules` for self-contained pnpm config-dependency pnpmfiles.
|
|
282
282
|
- **Readable prod output** — prod output is unminified by default to keep stack traces legible and pass security scanners; `minify` opts back in.
|
|
283
283
|
- **Default manifest stripping** — the published `package.json` drops build- and dev-only fields automatically; a custom `transform` replaces the default and can re-apply it via `defaultManifestTransform`.
|
package/config.js
CHANGED
|
@@ -26,14 +26,17 @@ function defineBuild(input = {}) {
|
|
|
26
26
|
function parseArgs(argv) {
|
|
27
27
|
let target = "dev";
|
|
28
28
|
let watch = false;
|
|
29
|
+
let noExe = false;
|
|
29
30
|
for (let i = 0; i < argv.length; i++) if (argv[i] === "--target") {
|
|
30
31
|
const v = argv[i + 1];
|
|
31
32
|
if (v === "dev" || v === "prod" || v === "meta" || v === "exe") target = v;
|
|
32
33
|
i++;
|
|
33
34
|
} else if (argv[i] === "--watch") watch = true;
|
|
35
|
+
else if (argv[i] === "--no-exe") noExe = true;
|
|
34
36
|
return {
|
|
35
37
|
target,
|
|
36
|
-
watch
|
|
38
|
+
watch,
|
|
39
|
+
noExe
|
|
37
40
|
};
|
|
38
41
|
}
|
|
39
42
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BuildFormat, BuildTargetGroupsOptions, 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, 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 {
|
|
@@ -10,6 +10,16 @@ interface BuildEntryOverride {
|
|
|
10
10
|
readonly bundleNodeModules?: boolean | undefined;
|
|
11
11
|
readonly bundledPackages?: ReadonlyArray<string> | undefined;
|
|
12
12
|
readonly dtsExternals?: ReadonlyArray<string> | undefined;
|
|
13
|
+
/** JS-pass platform for this partition (default "node"). Use "browser" for an RSPress runtime. */
|
|
14
|
+
readonly platform?: BuildPlatform | undefined;
|
|
15
|
+
/** CSS handling forwarded to tsdown's `css` option (JS pass only). Enables `@tsdown/css`. */
|
|
16
|
+
readonly css?: CssOptions | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Build this entry's partition into a `<group>/pkg/<outSubdir>/` subdir as an isolated sub-package
|
|
19
|
+
* (e.g. an RSPress `./runtime`). The export's built path becomes `./<outSubdir>/index.{js,d.ts}`.
|
|
20
|
+
* Exactly ONE export path may be pinned per `outSubdir` override.
|
|
21
|
+
*/
|
|
22
|
+
readonly outSubdir?: string | undefined;
|
|
13
23
|
}
|
|
14
24
|
interface OutputConfig {
|
|
15
25
|
readonly console?: {
|
|
@@ -163,6 +173,8 @@ declare function defineBuild(input?: BuildConfigInput): BuildConfig;
|
|
|
163
173
|
interface ParsedArgs {
|
|
164
174
|
readonly target: "dev" | "prod" | "meta" | "exe";
|
|
165
175
|
readonly watch: boolean;
|
|
176
|
+
/** Skip the SEA compile step of a dev/prod build (the manifest is still programmed). Used by `prepare`. */
|
|
177
|
+
readonly noExe: boolean;
|
|
166
178
|
}
|
|
167
179
|
declare function parseArgs(argv: ReadonlyArray<string>): ParsedArgs;
|
|
168
180
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/bundler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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,10 +25,11 @@
|
|
|
25
25
|
"import": "./index.js"
|
|
26
26
|
},
|
|
27
27
|
"./ecma.json": "./public/ecma.json",
|
|
28
|
+
"./tsconfig/ecma.json": "./public/ecma.json",
|
|
28
29
|
"./package.json": "./package.json"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"@savvy-web/tsdown-plugins": "0.
|
|
32
|
+
"@savvy-web/tsdown-plugins": "0.6.0",
|
|
32
33
|
"@tsdown/exe": "^0.22.1",
|
|
33
34
|
"tsdown": "^0.22.2"
|
|
34
35
|
},
|
package/public/ecma.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"sourceMap": false,
|
|
26
26
|
"strict": true,
|
|
27
27
|
"strictNullChecks": true,
|
|
28
|
-
"target": "
|
|
28
|
+
"target": "es2025",
|
|
29
29
|
"tsBuildInfoFile": "${configDir}/dist/.tsbuildinfo.lib",
|
|
30
30
|
"typeRoots": ["${configDir}/node_modules/@types", "${configDir}/types"],
|
|
31
31
|
"verbatimModuleSyntax": true,
|
package/run.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseArgs } from "./config.js";
|
|
2
|
-
import { ConfigValidator, ConfigValidatorLive, ReportPipelineLive, buildTargetGroups, createEntryName, generateMeta, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReport, resolveJsxConfig, resolveTargets, runExeBuild, writeResolvedTsconfig, writeTargetsBinding } from "@savvy-web/tsdown-plugins";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
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";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { Effect } from "effect";
|
|
6
6
|
|
|
@@ -35,9 +35,46 @@ function deriveExportPaths(entries, exportsMap) {
|
|
|
35
35
|
for (const [entryName, src] of Object.entries(entries)) out[entryName] = sourceToKey.get(src) ?? (entryName === "index" ? "." : `./${entryName}`);
|
|
36
36
|
return out;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Fast-fail validation for `outSubdir` overrides, run on EVERY target path. The dev/prod override-partition
|
|
40
|
+
* loop already validates these (and all other overrides) before building, but `--target meta` returns early
|
|
41
|
+
* (before that loop) and remaps meta dts basenames via `applySubdirMetaEntries` — which assumes validated
|
|
42
|
+
* input. Without this guard, a malformed `outSubdir` override (more than one entry, a non-canonical export
|
|
43
|
+
* path, or an export path that is not a real build entry) would silently remap a wrong/nonexistent key on the
|
|
44
|
+
* meta path. Mirrors the override loop's conditions and messages verbatim so every target path fast-fails
|
|
45
|
+
* identically. No-op when there are no overrides or none set `outSubdir`.
|
|
46
|
+
*/
|
|
47
|
+
function validateSubdirOverrides(overrides, entries, packageName) {
|
|
48
|
+
if (overrides === void 0) return;
|
|
49
|
+
for (const ov of overrides) {
|
|
50
|
+
if (ov.outSubdir === void 0) continue;
|
|
51
|
+
if (ov.entries.length !== 1) throw new Error(`overrides: outSubdir "${ov.outSubdir}" must pin exactly one export path (got ${ov.entries.length})`);
|
|
52
|
+
const exportPath = ov.entries[0];
|
|
53
|
+
if (exportPath !== "." && !exportPath.startsWith("./")) throw new Error(`overrides: entry "${exportPath}" must be a canonical export path — use "." for the root or a "./"-prefixed subpath (e.g. "./changesets/markdownlint")`);
|
|
54
|
+
const flatName = createEntryName(exportPath, false);
|
|
55
|
+
if (entries[flatName] === void 0) throw new Error(`overrides: export path "${exportPath}" (entry "${flatName}") is not a build entry of ${packageName}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* For each `outSubdir` override, point its meta entry at the isolated sub-package barrel: the dts lives
|
|
60
|
+
* at `<subdir>/index.d.ts` (not `<flatName>.d.ts`). Keyed by the stable flattened entry name so it
|
|
61
|
+
* overwrites the default `dtsBasenames[flatName] = flatName` set from the full entry map. No-op when no
|
|
62
|
+
* override sets `outSubdir`.
|
|
63
|
+
*/
|
|
64
|
+
function applySubdirMetaEntries(overrides, dtsBasenames, exportPaths) {
|
|
65
|
+
if (overrides === void 0) return;
|
|
66
|
+
for (const ov of overrides) {
|
|
67
|
+
if (ov.outSubdir === void 0) continue;
|
|
68
|
+
const exportPath = ov.entries[0];
|
|
69
|
+
if (exportPath === void 0) continue;
|
|
70
|
+
const flatName = createEntryName(exportPath, false);
|
|
71
|
+
dtsBasenames[flatName] = `${ov.outSubdir}/index`;
|
|
72
|
+
exportPaths[flatName] = exportPath;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
38
75
|
/** Run a build from a normalized config. Pure orchestration; all IO injectable. */
|
|
39
76
|
async function runBuild(config, options) {
|
|
40
|
-
const { target } = parseArgs(options.argv);
|
|
77
|
+
const { target, noExe } = parseArgs(options.argv);
|
|
41
78
|
const build = options.buildTargetGroups ?? buildTargetGroups;
|
|
42
79
|
const cwd = options.cwd;
|
|
43
80
|
const pkg = readPackageJson(cwd);
|
|
@@ -52,10 +89,6 @@ async function runBuild(config, options) {
|
|
|
52
89
|
} : {},
|
|
53
90
|
...jsx?.runtime === "classic" ? { jsx: "react" } : {}
|
|
54
91
|
})))(cwd);
|
|
55
|
-
const entries = packageJsonEntries({
|
|
56
|
-
pkg,
|
|
57
|
-
cwd
|
|
58
|
-
});
|
|
59
92
|
const exportsMap = options.readExports ? options.readExports() : pkg.exports;
|
|
60
93
|
const runGenerateMeta = options.generateMeta ?? generateMeta;
|
|
61
94
|
const publishTargets = (options.readPublishTargets ?? (() => {
|
|
@@ -76,6 +109,24 @@ async function runBuild(config, options) {
|
|
|
76
109
|
...config.meta !== void 0 && config.meta !== false ? { meta: config.meta } : {},
|
|
77
110
|
...config.looseFiles !== void 0 ? { looseFiles: config.looseFiles } : {}
|
|
78
111
|
})).pipe(Effect.provide(ConfigValidatorLive)));
|
|
112
|
+
const exeSpecs = config.exe !== void 0 ? normalizeExeOptions(config.exe, osCpuForValidate) : [];
|
|
113
|
+
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.`);
|
|
114
|
+
const exeSpec = exeSpecs[0];
|
|
115
|
+
const exeTarget = exeSpec?.targets[0];
|
|
116
|
+
const exeFileName = exeSpec && exeTarget ? computeExeFileName(exeSpec.fileName, exeTarget) : void 0;
|
|
117
|
+
const exeEntrySource = exeSpec?.entry ?? "./src/bin.ts";
|
|
118
|
+
const exeRewrite = config.exe !== void 0 && exeFileName !== void 0 ? {
|
|
119
|
+
source: exeEntrySource,
|
|
120
|
+
fileName: exeFileName,
|
|
121
|
+
dir: "bin"
|
|
122
|
+
} : void 0;
|
|
123
|
+
const entries = packageJsonEntries({
|
|
124
|
+
pkg,
|
|
125
|
+
cwd,
|
|
126
|
+
...config.exe !== void 0 ? { excludeSources: [exeEntrySource] } : {}
|
|
127
|
+
});
|
|
128
|
+
const hasJsEntries = Object.keys(entries).length > 0;
|
|
129
|
+
validateSubdirOverrides(config.overrides, entries, packageName);
|
|
79
130
|
if (target === "meta") {
|
|
80
131
|
if (config.meta === false) {
|
|
81
132
|
(options.writeOutput ?? ((o) => process.stdout.write(`${o.content}\n`)))({
|
|
@@ -88,13 +139,15 @@ async function runBuild(config, options) {
|
|
|
88
139
|
const norm = normalizeMetaOptions(config.meta ?? {});
|
|
89
140
|
const dtsBasenames = {};
|
|
90
141
|
for (const name of Object.keys(entries)) dtsBasenames[name] = name;
|
|
142
|
+
const exportPaths = deriveExportPaths(entries, exportsMap);
|
|
143
|
+
applySubdirMetaEntries(config.overrides, dtsBasenames, exportPaths);
|
|
91
144
|
await runGenerateMeta({
|
|
92
145
|
cwd,
|
|
93
146
|
packageName,
|
|
94
147
|
tsconfigPath,
|
|
95
148
|
dtsDir: join(cwd, "dist", "dev", "pkg"),
|
|
96
149
|
entries: dtsBasenames,
|
|
97
|
-
exportPaths
|
|
150
|
+
exportPaths,
|
|
98
151
|
outMetaDir: join(cwd, "dist", "dev", "meta"),
|
|
99
152
|
localPaths: norm.localPaths,
|
|
100
153
|
tsdoc: norm.tsdoc
|
|
@@ -108,22 +161,22 @@ async function runBuild(config, options) {
|
|
|
108
161
|
}
|
|
109
162
|
if (target === "exe") {
|
|
110
163
|
if (config.exe === void 0) throw new Error("`savvy build --target exe` requires an `exe` option in the build config");
|
|
111
|
-
const specs = normalizeExeOptions(config.exe, osCpuForValidate);
|
|
112
164
|
await (options.runExeBuild ?? runExeBuild)({
|
|
113
165
|
cwd,
|
|
114
166
|
outDir: join(cwd, "dist", "dev", "pkg", "bin"),
|
|
115
|
-
specs
|
|
167
|
+
specs: exeSpecs
|
|
116
168
|
});
|
|
117
169
|
(options.writeOutput ?? ((o) => process.stdout.write(`${o.content}\n`)))({
|
|
118
170
|
target: "stdout",
|
|
119
171
|
contentType: "text/plain",
|
|
120
|
-
content: `exe: compiled ${
|
|
172
|
+
content: `exe: compiled ${exeSpecs.length} binary/binaries for ${packageName}`
|
|
121
173
|
});
|
|
122
174
|
return;
|
|
123
175
|
}
|
|
124
176
|
let overridePartitions = [];
|
|
125
177
|
let baseEntries = entries;
|
|
126
178
|
let dualExports;
|
|
179
|
+
const subdirExports = /* @__PURE__ */ new Set();
|
|
127
180
|
if (config.overrides) {
|
|
128
181
|
const partitions = [];
|
|
129
182
|
const overriddenEntryNames = /* @__PURE__ */ new Set();
|
|
@@ -131,14 +184,17 @@ async function runBuild(config, options) {
|
|
|
131
184
|
const dualExportKeys = /* @__PURE__ */ new Set();
|
|
132
185
|
const exportPathByEntry = deriveExportPaths(entries, exportsMap);
|
|
133
186
|
for (const ov of config.overrides) {
|
|
187
|
+
if (ov.outSubdir !== void 0 && ov.entries.length !== 1) throw new Error(`overrides: outSubdir "${ov.outSubdir}" must pin exactly one export path (got ${ov.entries.length})`);
|
|
134
188
|
const partEntry = {};
|
|
135
189
|
for (const exportPath of ov.entries) {
|
|
136
190
|
if (exportPath !== "." && !exportPath.startsWith("./")) throw new Error(`overrides: entry "${exportPath}" must be a canonical export path — use "." for the root or a "./"-prefixed subpath (e.g. "./changesets/markdownlint")`);
|
|
137
|
-
const
|
|
138
|
-
const src = entries[
|
|
139
|
-
if (src === void 0) throw new Error(`overrides: export path "${exportPath}" (entry "${
|
|
191
|
+
const flatName = createEntryName(exportPath, false);
|
|
192
|
+
const src = entries[flatName];
|
|
193
|
+
if (src === void 0) throw new Error(`overrides: export path "${exportPath}" (entry "${flatName}") is not a build entry of ${packageName}`);
|
|
194
|
+
const entryName = ov.outSubdir !== void 0 ? "index" : flatName;
|
|
140
195
|
partEntry[entryName] = src;
|
|
141
|
-
overriddenEntryNames.add(
|
|
196
|
+
overriddenEntryNames.add(flatName);
|
|
197
|
+
if (ov.outSubdir !== void 0) subdirExports.add(exportPath);
|
|
142
198
|
if ((ov.format ?? config.format ?? ["esm"]).includes("cjs")) dualExportKeys.add(exportPath);
|
|
143
199
|
}
|
|
144
200
|
partitions.push({
|
|
@@ -148,7 +204,10 @@ async function runBuild(config, options) {
|
|
|
148
204
|
...ov.bundle !== void 0 ? { bundle: ov.bundle } : {},
|
|
149
205
|
...ov.bundleNodeModules !== void 0 ? { bundleNodeModules: ov.bundleNodeModules } : {},
|
|
150
206
|
...ov.bundledPackages !== void 0 ? { bundledPackages: ov.bundledPackages } : {},
|
|
151
|
-
...ov.dtsExternals !== void 0 ? { dtsExternals: ov.dtsExternals } : {}
|
|
207
|
+
...ov.dtsExternals !== void 0 ? { dtsExternals: ov.dtsExternals } : {},
|
|
208
|
+
...ov.platform !== void 0 ? { platform: ov.platform } : {},
|
|
209
|
+
...ov.css !== void 0 ? { css: ov.css } : {},
|
|
210
|
+
...ov.outSubdir !== void 0 ? { outSubdir: ov.outSubdir } : {}
|
|
152
211
|
});
|
|
153
212
|
}
|
|
154
213
|
const onlyBase = {};
|
|
@@ -170,7 +229,7 @@ async function runBuild(config, options) {
|
|
|
170
229
|
}],
|
|
171
230
|
resolution: void 0
|
|
172
231
|
} : deriveProdGroups(publishTargets, packageName);
|
|
173
|
-
await build({
|
|
232
|
+
if (hasJsEntries || config.exe === void 0) await build({
|
|
174
233
|
cwd,
|
|
175
234
|
version,
|
|
176
235
|
entry: config.overrides !== void 0 ? baseEntries : entries,
|
|
@@ -189,27 +248,65 @@ async function runBuild(config, options) {
|
|
|
189
248
|
...config.define !== void 0 ? { define: config.define } : {},
|
|
190
249
|
...overridePartitions.length > 0 ? { overrides: overridePartitions } : {},
|
|
191
250
|
...dualExports !== void 0 ? { dualExports } : {},
|
|
192
|
-
...
|
|
251
|
+
...subdirExports.size > 0 ? { subdirExports } : {},
|
|
252
|
+
...looseFiles !== void 0 ? { looseFiles } : {},
|
|
253
|
+
...exeRewrite !== void 0 ? { exeRewrite } : {}
|
|
193
254
|
});
|
|
194
255
|
if (target === "prod" && resolution !== void 0) writeBinding(cwd, resolution);
|
|
195
|
-
if (target === "prod" && config.meta !== false) {
|
|
256
|
+
if (target === "prod" && config.meta !== false && (config.exe === void 0 || hasJsEntries)) {
|
|
196
257
|
const metaGroupId = (groups.find((g) => g.name === packageName) ?? groups[0])?.id ?? "npm";
|
|
197
258
|
const norm = normalizeMetaOptions(config.meta ?? {});
|
|
198
259
|
const dtsBasenames = {};
|
|
199
260
|
for (const name of Object.keys(entries)) dtsBasenames[name] = name;
|
|
261
|
+
const exportPaths = deriveExportPaths(entries, exportsMap);
|
|
262
|
+
applySubdirMetaEntries(config.overrides, dtsBasenames, exportPaths);
|
|
200
263
|
await runGenerateMeta({
|
|
201
264
|
cwd,
|
|
202
265
|
packageName,
|
|
203
266
|
tsconfigPath,
|
|
204
267
|
dtsDir: join(cwd, "dist", "prod", metaGroupId, "pkg"),
|
|
205
268
|
entries: dtsBasenames,
|
|
206
|
-
exportPaths
|
|
269
|
+
exportPaths,
|
|
207
270
|
outMetaDir: join(cwd, "dist", "prod", metaGroupId, "meta"),
|
|
208
271
|
localPaths: [],
|
|
209
272
|
tsdoc: norm.tsdoc
|
|
210
273
|
});
|
|
211
274
|
}
|
|
212
275
|
if (target === "prod") for (const g of groups) removeDeclarationMaps(join(cwd, "dist", "prod", g.id, "pkg"));
|
|
276
|
+
if (config.exe !== void 0 && exeSpec !== void 0 && exeRewrite !== void 0 && exeFileName !== void 0) {
|
|
277
|
+
const runExe = options.runExeBuild ?? runExeBuild;
|
|
278
|
+
const groupOutDir = (g) => target === "dev" ? join(cwd, "dist", "dev", "pkg") : join(cwd, "dist", "prod", g.id, "pkg");
|
|
279
|
+
for (const g of groups) {
|
|
280
|
+
const outDir = groupOutDir(g);
|
|
281
|
+
if (!hasJsEntries) {
|
|
282
|
+
const manifest = await buildEmittedManifest({
|
|
283
|
+
pkg,
|
|
284
|
+
targetGroup: {
|
|
285
|
+
id: g.id,
|
|
286
|
+
name: g.name,
|
|
287
|
+
isProd: target === "prod"
|
|
288
|
+
},
|
|
289
|
+
devManifest: config.devManifest,
|
|
290
|
+
...config.transform !== void 0 ? { transform: config.transform } : {},
|
|
291
|
+
exeRewrite
|
|
292
|
+
});
|
|
293
|
+
mkdirSync(outDir, { recursive: true });
|
|
294
|
+
writeFileSync(join(outDir, "package.json"), `${JSON.stringify(manifest, null, " ")}\n`);
|
|
295
|
+
for (const file of ["LICENSE", "README.md"]) try {
|
|
296
|
+
copyFileSync(join(cwd, file), join(outDir, file));
|
|
297
|
+
} catch {}
|
|
298
|
+
}
|
|
299
|
+
if (!noExe) {
|
|
300
|
+
const binDir = join(outDir, "bin");
|
|
301
|
+
await runExe({
|
|
302
|
+
cwd,
|
|
303
|
+
outDir: binDir,
|
|
304
|
+
specs: exeSpecs
|
|
305
|
+
});
|
|
306
|
+
if (options.runExeBuild === void 0 && !existsSync(join(binDir, exeFileName))) throw new Error(`exe: expected compiled binary at ${join(binDir, exeFileName)} but it is missing — tsdown's emitted name may have drifted from computeExeFileName`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
213
310
|
const totalMs = Date.now() - startMs;
|
|
214
311
|
const reportEntries = Object.keys(entries);
|
|
215
312
|
const report = {
|