@savvy-web/tsdown-plugins 0.12.0 → 1.0.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/LICENSE +21 -0
- package/README.md +1 -0
- package/build/build-target-groups.js +2 -2
- package/build/sync-public.js +60 -34
- package/dts/relative-imports.js +32 -0
- package/entry/ambient-dts.js +102 -0
- package/index.d.ts +155 -75
- package/index.js +5 -3
- package/manifest/transform.js +20 -3
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Savvy Web Strategy, LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -41,6 +41,7 @@ export default defineConfig({
|
|
|
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
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
|
+
- **Ambient `.d.ts` exports** — `extractAmbientDts` and `classifyDtsExport` pick the types-only, hand-authored declaration exports out of a package's `exports` map; `transformExports` rewrites each to a key-derived `{ types }` pointer and `copyAmbientDts` copies the source declaration verbatim into every target dir, preserving its extension. `findRelativeSpecifiers` rejects a non-self-contained declaration and `mixedDtsExportError` rejects an export that mixes a hand-authored `types` with a runtime source.
|
|
44
45
|
- **Catalog resolution** — `resolveManifest` resolves `catalog:` and `workspace:` specifiers against the workspace, delegating to `workspaces-effect`'s `CatalogResolver`.
|
|
45
46
|
- **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
47
|
- **JSX resolution** — `resolveJsxConfig` and `readTsconfigJsx` derive the effective JSX transform from a package's tsconfig, with an explicit override winning.
|
|
@@ -6,7 +6,7 @@ import { createTimer } from "../report/timer.js";
|
|
|
6
6
|
import { createTsdownLogger } from "../report/tsdown-logger.js";
|
|
7
7
|
import { cjsDefaultInterop } from "./cjs-default-interop.js";
|
|
8
8
|
import { nodeBuiltinDefaultInterop } from "./node-builtin-default-interop.js";
|
|
9
|
-
import {
|
|
9
|
+
import { copyPublicDir } from "./sync-public.js";
|
|
10
10
|
import { deriveDeclarationsPassOptions, deriveDtsPassOptions, deriveTargetGroupOptions, outDirFor } from "./target-groups.js";
|
|
11
11
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { dirname, isAbsolute, join } from "node:path";
|
|
@@ -140,7 +140,6 @@ async function buildTargetGroups(options) {
|
|
|
140
140
|
...metricsPlugins(group.id, "js")
|
|
141
141
|
]
|
|
142
142
|
}));
|
|
143
|
-
if (isBase) syncPublicDir(publicDir, join(js.outDir, "public"));
|
|
144
143
|
const dtsNeverBundle = [...partExternals ?? [], ...partDtsExternals ?? []];
|
|
145
144
|
if (Object.keys(dts.entry).length === 0) continue;
|
|
146
145
|
const dtsDeps = dtsNeverBundle.length > 0 || partBundleNodeModules || dts.bundledPackages ? { deps: {
|
|
@@ -302,6 +301,7 @@ async function buildTargetGroups(options) {
|
|
|
302
301
|
]
|
|
303
302
|
}));
|
|
304
303
|
}
|
|
304
|
+
copyPublicDir(publicDir, outDirFor(options.cwd, group.id));
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
|
package/build/sync-public.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigValidationError } from "../errors.js";
|
|
2
|
+
import { findRelativeSpecifiers } from "../dts/relative-imports.js";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
4
|
import { dirname, join, relative } from "node:path";
|
|
3
5
|
|
|
4
6
|
//#region src/build/sync-public.ts
|
|
@@ -17,52 +19,76 @@ function sameBytes(a, b) {
|
|
|
17
19
|
if (statSync(a).size !== statSync(b).size) return false;
|
|
18
20
|
return readFileSync(a).equals(readFileSync(b));
|
|
19
21
|
}
|
|
20
|
-
/**
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (readdirSync(sub).length === 0) rmSync(sub, {
|
|
27
|
-
recursive: true,
|
|
28
|
-
force: true
|
|
29
|
-
});
|
|
30
|
-
}
|
|
22
|
+
/** Throw the standard public-asset collision error for a destination-relative path. */
|
|
23
|
+
function throwPublicCollision(rel) {
|
|
24
|
+
throw new ConfigValidationError({
|
|
25
|
+
path: `public/${rel}`,
|
|
26
|
+
reason: `public asset "${rel}" collides with a built output at the package root — rename or remove it`
|
|
27
|
+
});
|
|
31
28
|
}
|
|
32
29
|
/**
|
|
33
|
-
*
|
|
30
|
+
* Copy the CONTENTS of `sourceDir` into `outDir`, additively.
|
|
34
31
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
* Each `sourceDir/<rel>` copies to `outDir/<rel>` — only the `public/` directory itself is dropped;
|
|
33
|
+
* the substructure under it is preserved (`public/tsconfig/ecma.json` becomes `<pkg>/tsconfig/ecma.json`,
|
|
34
|
+
* NOT `<pkg>/ecma.json`). The published manifest mirrors this drop via `transformExports`, which strips
|
|
35
|
+
* a leading `public/` from export values. This function NEVER deletes: `outDir` is the shared package
|
|
36
|
+
* root that the JS/dts passes own, so deleting "files not in source" would wipe the build product.
|
|
37
|
+
* Stale-asset pruning on a non-clean rebuild is therefore out of scope (a full build's `clean: true` handles it).
|
|
37
38
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* The byte-diff keeps unchanged files (and their timestamps) untouched, so a large copied asset
|
|
44
|
-
* tree — e.g. the mcp markdown corpus — is not rewritten on every build.
|
|
39
|
+
* Collision guard: when a destination already exists, identical bytes mean a prior copy of the same
|
|
40
|
+
* asset (skipped); anything else — differing bytes, a directory where a file is needed, or a file
|
|
41
|
+
* where a parent directory is needed — means a built output occupies that path, so it throws
|
|
42
|
+
* {@link ConfigValidationError} rather than clobbering it or surfacing a raw fs error.
|
|
45
43
|
* @public
|
|
46
44
|
*/
|
|
47
|
-
function
|
|
45
|
+
function copyPublicDir(sourceDir, outDir) {
|
|
48
46
|
if (!existsSync(sourceDir)) return;
|
|
49
|
-
|
|
50
|
-
cpSync(sourceDir, targetDir, { recursive: true });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const sourceFiles = listFilesRel(sourceDir);
|
|
54
|
-
const sourceSet = new Set(sourceFiles);
|
|
55
|
-
for (const rel of sourceFiles) {
|
|
47
|
+
for (const rel of listFilesRel(sourceDir)) {
|
|
56
48
|
const src = join(sourceDir, rel);
|
|
57
|
-
const dst = join(
|
|
49
|
+
const dst = join(outDir, rel);
|
|
50
|
+
if (existsSync(dst)) {
|
|
51
|
+
if (statSync(dst).isFile() && sameBytes(src, dst)) continue;
|
|
52
|
+
throwPublicCollision(rel);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
56
|
+
copyFileSync(src, dst);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
const code = err.code;
|
|
59
|
+
if (code === "ENOTDIR" || code === "EEXIST" || code === "EISDIR") throwPublicCollision(rel);
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Copy each ambient `.d.ts` export's source verbatim into `outDir/<outName>`, byte-stable (an
|
|
66
|
+
* unchanged file keeps its timestamp). The copy is NOT compiled or bundled, so the build owns two
|
|
67
|
+
* fast-fail checks: the source must exist, and it must be self-contained — a relative
|
|
68
|
+
* import/export/reference would not resolve once the file is flattened to the package root.
|
|
69
|
+
*
|
|
70
|
+
* Throws {@link ConfigValidationError} on a missing source or any relative specifier.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
function copyAmbientDts(options) {
|
|
74
|
+
for (const a of options.ambient) {
|
|
75
|
+
const src = join(options.srcCwd, a.source);
|
|
76
|
+
if (!existsSync(src)) throw new ConfigValidationError({
|
|
77
|
+
path: `exports."${a.exportKey}"`,
|
|
78
|
+
reason: `ambient .d.ts source not found: ${a.source}`
|
|
79
|
+
});
|
|
80
|
+
const relativeSpecifiers = findRelativeSpecifiers(readFileSync(src, "utf-8"), a.source);
|
|
81
|
+
if (relativeSpecifiers.length > 0) throw new ConfigValidationError({
|
|
82
|
+
path: `exports."${a.exportKey}"`,
|
|
83
|
+
reason: `ambient .d.ts "${a.source}" has relative import(s) [${relativeSpecifiers.join(", ")}] that cannot resolve after a verbatim copy — use bare package specifiers or self-contained declare module/global blocks`
|
|
84
|
+
});
|
|
85
|
+
const dst = join(options.outDir, a.outName);
|
|
58
86
|
if (!existsSync(dst) || !sameBytes(src, dst)) {
|
|
59
87
|
mkdirSync(dirname(dst), { recursive: true });
|
|
60
88
|
copyFileSync(src, dst);
|
|
61
89
|
}
|
|
62
90
|
}
|
|
63
|
-
for (const rel of listFilesRel(targetDir)) if (!sourceSet.has(rel)) rmSync(join(targetDir, rel), { force: true });
|
|
64
|
-
pruneEmptyDirs(targetDir);
|
|
65
91
|
}
|
|
66
92
|
|
|
67
93
|
//#endregion
|
|
68
|
-
export {
|
|
94
|
+
export { copyAmbientDts, copyPublicDir };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
//#region src/dts/relative-imports.ts
|
|
4
|
+
const isRelative = (s) => s.startsWith("./") || s.startsWith("../");
|
|
5
|
+
/**
|
|
6
|
+
* Find every relative module specifier in a declaration source: static `import`/`export … from`,
|
|
7
|
+
* `import("…")` type nodes, and `/// <reference path="…" />`. Pure parsing — no I/O.
|
|
8
|
+
*
|
|
9
|
+
* A non-empty result means the file is NOT self-contained and would break when copied verbatim to a
|
|
10
|
+
* flattened output location, so the ambient-copy step rejects it.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
function findRelativeSpecifiers(source, fileName = "ambient.d.ts") {
|
|
14
|
+
const sf = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
15
|
+
const found = /* @__PURE__ */ new Set();
|
|
16
|
+
for (const ref of sf.referencedFiles) if (isRelative(ref.fileName)) found.add(ref.fileName);
|
|
17
|
+
const visit = (node) => {
|
|
18
|
+
if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier !== void 0 && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
19
|
+
if (isRelative(node.moduleSpecifier.text)) found.add(node.moduleSpecifier.text);
|
|
20
|
+
} else if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteral(node.argument.literal)) {
|
|
21
|
+
if (isRelative(node.argument.literal.text)) found.add(node.argument.literal.text);
|
|
22
|
+
} else if (ts.isImportEqualsDeclaration(node) && ts.isExternalModuleReference(node.moduleReference) && ts.isStringLiteral(node.moduleReference.expression)) {
|
|
23
|
+
if (isRelative(node.moduleReference.expression.text)) found.add(node.moduleReference.expression.text);
|
|
24
|
+
}
|
|
25
|
+
ts.forEachChild(node, visit);
|
|
26
|
+
};
|
|
27
|
+
visit(sf);
|
|
28
|
+
return [...found];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { findRelativeSpecifiers };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ConfigValidationError } from "../errors.js";
|
|
2
|
+
import { createEntryName } from "./extract.js";
|
|
3
|
+
|
|
4
|
+
//#region src/entry/ambient-dts.ts
|
|
5
|
+
const DECLARATION_EXTS = [
|
|
6
|
+
".d.ts",
|
|
7
|
+
".d.cts",
|
|
8
|
+
".d.mts"
|
|
9
|
+
];
|
|
10
|
+
/** The declaration-file extension of a path, or undefined when it is not a declaration file. @public */
|
|
11
|
+
function declarationExt(p) {
|
|
12
|
+
return DECLARATION_EXTS.find((e) => p.endsWith(e));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Classify an export value:
|
|
16
|
+
* - `ambient` — a types-only declaration source (bare `.d.ts` string, or `{ types: "*.d.ts" }` with no runtime source).
|
|
17
|
+
* - `mixed` — a declaration `types` AND a compilable runtime source (`import`/`require`/`default` → `.ts`/`.tsx`).
|
|
18
|
+
* - `none` — anything else (normal runtime export, json, etc.).
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
function classifyDtsExport(value) {
|
|
22
|
+
if (typeof value === "string") return declarationExt(value) !== void 0 ? {
|
|
23
|
+
kind: "ambient",
|
|
24
|
+
source: value
|
|
25
|
+
} : { kind: "none" };
|
|
26
|
+
if (value && typeof value === "object") {
|
|
27
|
+
const o = value;
|
|
28
|
+
const typesVal = typeof o.types === "string" ? o.types : void 0;
|
|
29
|
+
const typesIsDecl = typesVal !== void 0 && declarationExt(typesVal) !== void 0;
|
|
30
|
+
const hasRuntime = Object.entries(o).some(([k, v]) => k !== "types" && typeof v === "string" && declarationExt(v) === void 0);
|
|
31
|
+
if (typesIsDecl) return hasRuntime ? { kind: "mixed" } : {
|
|
32
|
+
kind: "ambient",
|
|
33
|
+
source: typesVal
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return { kind: "none" };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Output basename (including the preserved declaration extension) for an ambient export, derived
|
|
40
|
+
* from the export KEY — consistent with how JS entries are named. @public
|
|
41
|
+
*/
|
|
42
|
+
function ambientOutName(exportKey, source, exportsAsIndexes = false) {
|
|
43
|
+
const ext = declarationExt(source) ?? ".d.ts";
|
|
44
|
+
return `${createEntryName(exportKey, exportsAsIndexes)}${ext}`;
|
|
45
|
+
}
|
|
46
|
+
/** The shared mixed-export error (Decision 2), used by both the extractor and the manifest transform. @public */
|
|
47
|
+
function mixedDtsExportError(exportKey) {
|
|
48
|
+
return new ConfigValidationError({
|
|
49
|
+
path: `exports."${exportKey}"`,
|
|
50
|
+
reason: "an export with a runtime source (import/require/default) cannot also hand-author its `types` as a .d.ts; the bundler generates types from the source"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Extract the types-only `.d.ts` exports from a package's `exports` map. Pure.
|
|
55
|
+
* Throws {@link ConfigValidationError} on a mixed export (Decision 2) or an ambient-vs-ambient
|
|
56
|
+
* output-name collision. @public
|
|
57
|
+
*/
|
|
58
|
+
function extractAmbientDts(pkg, options = {}) {
|
|
59
|
+
const exports = pkg.exports;
|
|
60
|
+
if (!exports || typeof exports !== "object") return [];
|
|
61
|
+
const exportsAsIndexes = options.exportsAsIndexes ?? false;
|
|
62
|
+
const out = [];
|
|
63
|
+
const byName = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
65
|
+
if (key === "./package.json" || key.endsWith(".json")) continue;
|
|
66
|
+
if (declarationExt(key) !== void 0) continue;
|
|
67
|
+
const cls = classifyDtsExport(value);
|
|
68
|
+
if (cls.kind === "none") continue;
|
|
69
|
+
if (cls.kind === "mixed") throw mixedDtsExportError(key);
|
|
70
|
+
const outName = ambientOutName(key, cls.source, exportsAsIndexes);
|
|
71
|
+
const prev = byName.get(outName);
|
|
72
|
+
if (prev !== void 0) throw new ConfigValidationError({
|
|
73
|
+
path: `exports."${key}"`,
|
|
74
|
+
reason: `ambient .d.ts export flattens to "${outName}", colliding with export key "${prev}". Rename one so each produces a distinct file.`
|
|
75
|
+
});
|
|
76
|
+
byName.set(outName, key);
|
|
77
|
+
out.push({
|
|
78
|
+
exportKey: key,
|
|
79
|
+
source: cls.source,
|
|
80
|
+
outName
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Throw {@link ConfigValidationError} if any ambient output name collides with a JS build-entry name.
|
|
87
|
+
* The JS entry names carry no extension, so each ambient `outName` is compared with its declaration
|
|
88
|
+
* extension stripped. @public
|
|
89
|
+
*/
|
|
90
|
+
function assertNoEntryCollisions(jsEntryNames, ambient) {
|
|
91
|
+
const js = new Set(jsEntryNames);
|
|
92
|
+
for (const a of ambient) {
|
|
93
|
+
const base = a.outName.replace(/\.d\.(ts|cts|mts)$/, "");
|
|
94
|
+
if (js.has(base)) throw new ConfigValidationError({
|
|
95
|
+
path: `exports."${a.exportKey}"`,
|
|
96
|
+
reason: `ambient .d.ts export "${a.outName}" collides with the JS build entry "${base}". Rename the export so each produces a distinct output.`
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { ambientOutName, assertNoEntryCollisions, classifyDtsExport, declarationExt, extractAmbientDts, mixedDtsExportError };
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Find every relative module specifier in a declaration source: static `import`/`export … from`,
|
|
3
|
+
* `import("…")` type nodes, and `/// <reference path="…" />`. Pure parsing — no I/O.
|
|
4
|
+
*
|
|
5
|
+
* A non-empty result means the file is NOT self-contained and would break when copied verbatim to a
|
|
6
|
+
* flattened output location, so the ambient-copy step rejects it.
|
|
7
|
+
* @public
|
|
8
|
+
*/import { CatalogAssemblyError, CatalogResolutionError, ManifestLike, ManifestLike as ManifestLike$1 } from "workspaces-effect";
|
|
2
9
|
import { Plugin } from "rolldown";
|
|
3
10
|
import { Context, Effect, Layer, Schema } from "effect";
|
|
4
11
|
import { JsxEmit, ModuleDetectionKind, ModuleKind, ModuleResolutionKind, NewLineKind, ParsedCommandLine, ScriptTarget } from "typescript";
|
|
@@ -762,23 +769,156 @@ declare function nodeBuiltinDefaultInterop(): Plugin;
|
|
|
762
769
|
*/
|
|
763
770
|
declare function removeDeclarationMaps(pkgDir: string): string[];
|
|
764
771
|
//#endregion
|
|
772
|
+
//#region src/errors.d.ts
|
|
773
|
+
declare const MetaGenerationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
774
|
+
readonly _tag: "MetaGenerationError";
|
|
775
|
+
} & Readonly<A>;
|
|
776
|
+
/**
|
|
777
|
+
* API Extractor meta generation failed for an entry.
|
|
778
|
+
*
|
|
779
|
+
* @public
|
|
780
|
+
*/
|
|
781
|
+
declare class MetaGenerationError extends MetaGenerationError_base<{
|
|
782
|
+
readonly entry: string;
|
|
783
|
+
readonly reason: string;
|
|
784
|
+
}> {
|
|
785
|
+
get message(): string;
|
|
786
|
+
}
|
|
787
|
+
declare const ConfigValidationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
788
|
+
readonly _tag: "ConfigValidationError";
|
|
789
|
+
} & Readonly<A>;
|
|
790
|
+
/**
|
|
791
|
+
* A savvy.build.ts or publishConfig.targets config is structurally invalid; raised before any build work.
|
|
792
|
+
*
|
|
793
|
+
* @public
|
|
794
|
+
*/
|
|
795
|
+
declare class ConfigValidationError extends ConfigValidationError_base<{
|
|
796
|
+
readonly path: string;
|
|
797
|
+
readonly reason: string;
|
|
798
|
+
}> {
|
|
799
|
+
get message(): string;
|
|
800
|
+
}
|
|
801
|
+
//#endregion
|
|
802
|
+
//#region src/entry/extract.d.ts
|
|
803
|
+
/** @public */
|
|
804
|
+
interface PackageJsonLike {
|
|
805
|
+
readonly exports?: unknown;
|
|
806
|
+
readonly bin?: unknown;
|
|
807
|
+
}
|
|
808
|
+
/** @public */
|
|
809
|
+
interface ExtractOptions {
|
|
810
|
+
readonly exportsAsIndexes?: boolean | undefined;
|
|
811
|
+
/** Source paths to NOT turn into JS build entries (e.g. an exe entry compiled as a SEA). */
|
|
812
|
+
readonly excludeSources?: ReadonlyArray<string> | undefined;
|
|
813
|
+
}
|
|
814
|
+
/** @public */
|
|
815
|
+
interface ExtractResult {
|
|
816
|
+
/** entry name to TS source path */
|
|
817
|
+
readonly entries: Record<string, string>;
|
|
818
|
+
/** entry name to original export key (for downstream output-map alignment) */
|
|
819
|
+
readonly exportPaths: Record<string, string>;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Map an export key to the tsdown entry name (the emitted output basename).
|
|
823
|
+
*
|
|
824
|
+
* `.` becomes `index`; otherwise the leading `./` is stripped and, unless
|
|
825
|
+
* `exportsAsIndexes` is set, nested slashes are flattened to dashes
|
|
826
|
+
* (e.g. `./changesets/markdownlint` to `changesets-markdownlint`). The manifest
|
|
827
|
+
* transform reuses this so the declared output path always matches the emitted file.
|
|
828
|
+
*
|
|
829
|
+
* @internal
|
|
830
|
+
*/
|
|
831
|
+
declare const createEntryName: (exportKey: string, exportsAsIndexes: boolean) => string;
|
|
832
|
+
/** @public */
|
|
833
|
+
declare function extractEntries(pkg: PackageJsonLike, options?: ExtractOptions): ExtractResult;
|
|
834
|
+
//#endregion
|
|
835
|
+
//#region src/entry/ambient-dts.d.ts
|
|
836
|
+
/** The declaration-file extension of a path, or undefined when it is not a declaration file. @public */
|
|
837
|
+
declare function declarationExt(p: string): ".d.ts" | ".d.cts" | ".d.mts" | undefined;
|
|
838
|
+
/** Classification of a single export value for ambient-.d.ts handling. @public */
|
|
839
|
+
type DtsExportClass = {
|
|
840
|
+
readonly kind: "ambient";
|
|
841
|
+
readonly source: string;
|
|
842
|
+
} | {
|
|
843
|
+
readonly kind: "mixed";
|
|
844
|
+
} | {
|
|
845
|
+
readonly kind: "none";
|
|
846
|
+
};
|
|
847
|
+
/**
|
|
848
|
+
* Classify an export value:
|
|
849
|
+
* - `ambient` — a types-only declaration source (bare `.d.ts` string, or `{ types: "*.d.ts" }` with no runtime source).
|
|
850
|
+
* - `mixed` — a declaration `types` AND a compilable runtime source (`import`/`require`/`default` → `.ts`/`.tsx`).
|
|
851
|
+
* - `none` — anything else (normal runtime export, json, etc.).
|
|
852
|
+
* @public
|
|
853
|
+
*/
|
|
854
|
+
declare function classifyDtsExport(value: unknown): DtsExportClass;
|
|
855
|
+
/**
|
|
856
|
+
* Output basename (including the preserved declaration extension) for an ambient export, derived
|
|
857
|
+
* from the export KEY — consistent with how JS entries are named. @public
|
|
858
|
+
*/
|
|
859
|
+
declare function ambientOutName(exportKey: string, source: string, exportsAsIndexes?: boolean): string;
|
|
860
|
+
/** The shared mixed-export error (Decision 2), used by both the extractor and the manifest transform. @public */
|
|
861
|
+
declare function mixedDtsExportError(exportKey: string): ConfigValidationError;
|
|
862
|
+
/** One ambient `.d.ts` export resolved for copy + manifest. @public */
|
|
863
|
+
interface AmbientDtsEntry {
|
|
864
|
+
readonly exportKey: string;
|
|
865
|
+
readonly source: string;
|
|
866
|
+
readonly outName: string;
|
|
867
|
+
}
|
|
868
|
+
/** @public */
|
|
869
|
+
interface ExtractAmbientOptions {
|
|
870
|
+
readonly exportsAsIndexes?: boolean | undefined;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Extract the types-only `.d.ts` exports from a package's `exports` map. Pure.
|
|
874
|
+
* Throws {@link ConfigValidationError} on a mixed export (Decision 2) or an ambient-vs-ambient
|
|
875
|
+
* output-name collision. @public
|
|
876
|
+
*/
|
|
877
|
+
declare function extractAmbientDts(pkg: PackageJsonLike, options?: ExtractAmbientOptions): ReadonlyArray<AmbientDtsEntry>;
|
|
878
|
+
/**
|
|
879
|
+
* Throw {@link ConfigValidationError} if any ambient output name collides with a JS build-entry name.
|
|
880
|
+
* The JS entry names carry no extension, so each ambient `outName` is compared with its declaration
|
|
881
|
+
* extension stripped. @public
|
|
882
|
+
*/
|
|
883
|
+
declare function assertNoEntryCollisions(jsEntryNames: ReadonlyArray<string>, ambient: ReadonlyArray<AmbientDtsEntry>): void;
|
|
884
|
+
//#endregion
|
|
765
885
|
//#region src/build/sync-public.d.ts
|
|
766
886
|
/**
|
|
767
|
-
*
|
|
887
|
+
* Copy the CONTENTS of `sourceDir` into `outDir`, additively.
|
|
768
888
|
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
889
|
+
* Each `sourceDir/<rel>` copies to `outDir/<rel>` — only the `public/` directory itself is dropped;
|
|
890
|
+
* the substructure under it is preserved (`public/tsconfig/ecma.json` becomes `<pkg>/tsconfig/ecma.json`,
|
|
891
|
+
* NOT `<pkg>/ecma.json`). The published manifest mirrors this drop via `transformExports`, which strips
|
|
892
|
+
* a leading `public/` from export values. This function NEVER deletes: `outDir` is the shared package
|
|
893
|
+
* root that the JS/dts passes own, so deleting "files not in source" would wipe the build product.
|
|
894
|
+
* Stale-asset pruning on a non-clean rebuild is therefore out of scope (a full build's `clean: true` handles it).
|
|
771
895
|
*
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
*
|
|
775
|
-
*
|
|
896
|
+
* Collision guard: when a destination already exists, identical bytes mean a prior copy of the same
|
|
897
|
+
* asset (skipped); anything else — differing bytes, a directory where a file is needed, or a file
|
|
898
|
+
* where a parent directory is needed — means a built output occupies that path, so it throws
|
|
899
|
+
* {@link ConfigValidationError} rather than clobbering it or surfacing a raw fs error.
|
|
900
|
+
* @public
|
|
901
|
+
*/
|
|
902
|
+
declare function copyPublicDir(sourceDir: string, outDir: string): void;
|
|
903
|
+
/** @public */
|
|
904
|
+
interface CopyAmbientDtsOptions {
|
|
905
|
+
/** The ambient exports to copy (from `extractAmbientDts`). */
|
|
906
|
+
readonly ambient: ReadonlyArray<AmbientDtsEntry>;
|
|
907
|
+
/** Package root the `source` paths are relative to. */
|
|
908
|
+
readonly srcCwd: string;
|
|
909
|
+
/** The built package dir to copy into (e.g. `dist/dev/pkg`). */
|
|
910
|
+
readonly outDir: string;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Copy each ambient `.d.ts` export's source verbatim into `outDir/<outName>`, byte-stable (an
|
|
914
|
+
* unchanged file keeps its timestamp). The copy is NOT compiled or bundled, so the build owns two
|
|
915
|
+
* fast-fail checks: the source must exist, and it must be self-contained — a relative
|
|
916
|
+
* import/export/reference would not resolve once the file is flattened to the package root.
|
|
776
917
|
*
|
|
777
|
-
*
|
|
778
|
-
* tree — e.g. the mcp markdown corpus — is not rewritten on every build.
|
|
918
|
+
* Throws {@link ConfigValidationError} on a missing source or any relative specifier.
|
|
779
919
|
* @public
|
|
780
920
|
*/
|
|
781
|
-
declare function
|
|
921
|
+
declare function copyAmbientDts(options: CopyAmbientDtsOptions): void;
|
|
782
922
|
//#endregion
|
|
783
923
|
//#region src/catalog/resolve-catalogs.d.ts
|
|
784
924
|
/**
|
|
@@ -817,36 +957,6 @@ interface NextVersions {
|
|
|
817
957
|
*/
|
|
818
958
|
declare function resolveNextVersions(cwd: string): Promise<NextVersions>;
|
|
819
959
|
//#endregion
|
|
820
|
-
//#region src/errors.d.ts
|
|
821
|
-
declare const MetaGenerationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
822
|
-
readonly _tag: "MetaGenerationError";
|
|
823
|
-
} & Readonly<A>;
|
|
824
|
-
/**
|
|
825
|
-
* API Extractor meta generation failed for an entry.
|
|
826
|
-
*
|
|
827
|
-
* @public
|
|
828
|
-
*/
|
|
829
|
-
declare class MetaGenerationError extends MetaGenerationError_base<{
|
|
830
|
-
readonly entry: string;
|
|
831
|
-
readonly reason: string;
|
|
832
|
-
}> {
|
|
833
|
-
get message(): string;
|
|
834
|
-
}
|
|
835
|
-
declare const ConfigValidationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
836
|
-
readonly _tag: "ConfigValidationError";
|
|
837
|
-
} & Readonly<A>;
|
|
838
|
-
/**
|
|
839
|
-
* A savvy.build.ts or publishConfig.targets config is structurally invalid; raised before any build work.
|
|
840
|
-
*
|
|
841
|
-
* @public
|
|
842
|
-
*/
|
|
843
|
-
declare class ConfigValidationError extends ConfigValidationError_base<{
|
|
844
|
-
readonly path: string;
|
|
845
|
-
readonly reason: string;
|
|
846
|
-
}> {
|
|
847
|
-
get message(): string;
|
|
848
|
-
}
|
|
849
|
-
//#endregion
|
|
850
960
|
//#region src/exe/config.d.ts
|
|
851
961
|
/**
|
|
852
962
|
* Default Node runtime embedded in the SEA (parity with the vitest-agent reference).
|
|
@@ -1172,6 +1282,9 @@ declare function renderReexportStub(options: {
|
|
|
1172
1282
|
readonly baseSpecifier: string;
|
|
1173
1283
|
}): string;
|
|
1174
1284
|
//#endregion
|
|
1285
|
+
//#region src/dts/relative-imports.d.ts
|
|
1286
|
+
declare function findRelativeSpecifiers(source: string, fileName?: string): string[];
|
|
1287
|
+
//#endregion
|
|
1175
1288
|
//#region src/dts/resolved-tsconfig.d.ts
|
|
1176
1289
|
/** @public */
|
|
1177
1290
|
interface ResolvedTsconfigOptions {
|
|
@@ -1220,39 +1333,6 @@ declare function writeResolvedTsconfig(options: ResolvedTsconfigOptions): string
|
|
|
1220
1333
|
*/
|
|
1221
1334
|
declare function writeDtsEmitTsconfig(resolvedTsconfigPath: string): string;
|
|
1222
1335
|
//#endregion
|
|
1223
|
-
//#region src/entry/extract.d.ts
|
|
1224
|
-
/** @public */
|
|
1225
|
-
interface PackageJsonLike {
|
|
1226
|
-
readonly exports?: unknown;
|
|
1227
|
-
readonly bin?: unknown;
|
|
1228
|
-
}
|
|
1229
|
-
/** @public */
|
|
1230
|
-
interface ExtractOptions {
|
|
1231
|
-
readonly exportsAsIndexes?: boolean | undefined;
|
|
1232
|
-
/** Source paths to NOT turn into JS build entries (e.g. an exe entry compiled as a SEA). */
|
|
1233
|
-
readonly excludeSources?: ReadonlyArray<string> | undefined;
|
|
1234
|
-
}
|
|
1235
|
-
/** @public */
|
|
1236
|
-
interface ExtractResult {
|
|
1237
|
-
/** entry name to TS source path */
|
|
1238
|
-
readonly entries: Record<string, string>;
|
|
1239
|
-
/** entry name to original export key (for downstream output-map alignment) */
|
|
1240
|
-
readonly exportPaths: Record<string, string>;
|
|
1241
|
-
}
|
|
1242
|
-
/**
|
|
1243
|
-
* Map an export key to the tsdown entry name (the emitted output basename).
|
|
1244
|
-
*
|
|
1245
|
-
* `.` becomes `index`; otherwise the leading `./` is stripped and, unless
|
|
1246
|
-
* `exportsAsIndexes` is set, nested slashes are flattened to dashes
|
|
1247
|
-
* (e.g. `./changesets/markdownlint` to `changesets-markdownlint`). The manifest
|
|
1248
|
-
* transform reuses this so the declared output path always matches the emitted file.
|
|
1249
|
-
*
|
|
1250
|
-
* @internal
|
|
1251
|
-
*/
|
|
1252
|
-
declare const createEntryName: (exportKey: string, exportsAsIndexes: boolean) => string;
|
|
1253
|
-
/** @public */
|
|
1254
|
-
declare function extractEntries(pkg: PackageJsonLike, options?: ExtractOptions): ExtractResult;
|
|
1255
|
-
//#endregion
|
|
1256
1336
|
//#region src/entry/package-json-entries.d.ts
|
|
1257
1337
|
/** @public */
|
|
1258
1338
|
interface PackageJsonEntriesOptions extends ExtractOptions {
|
|
@@ -1798,5 +1878,5 @@ declare function resolveTargets(options: {
|
|
|
1798
1878
|
baseName: string;
|
|
1799
1879
|
}): TargetResolution;
|
|
1800
1880
|
//#endregion
|
|
1801
|
-
export { BuildCollector, BuildCollectorTag, type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildIssues, 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 DiagnosticEntry, type DiagnosticInput, type DualExports, type EmitManifestOptions, type EmittedFile, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeRewrite, 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 ModuleExportNames, type NextVersions, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PassKind, type PassReport, type PkgOsCpu, type PlainDiagnostic, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type ReexportBarrelAnalysis, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, type RunMetaPassOptions, 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 TsdownLogger, type ValidationInput, type WarningSuppressionRule, analyzeReexportBarrel, applySubdirMetaEntries, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, collectExportNames, computeExeFileName, createEntryName, createTimer, createTsdownLogger, defaultManifestTransform, deriveExportPaths, deriveTargetGroupOptions, emitManifest, extractEntries, flattenIssues, formatTime, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReexportStub, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, runMetaPass, serializeIssues,
|
|
1881
|
+
export { type AmbientDtsEntry, BuildCollector, BuildCollectorTag, type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildIssues, type BuildPlatform, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, CatalogResolutionError, CiAnnotationsFormatter, ConfigValidationError, ConfigValidator, ConfigValidatorLive, type CopyAmbientDtsOptions, type CssOptions, DEFAULT_EXE_NODE_VERSION, type DeriveOptions, type DerivedTsdownOptions, type DiagnosticEntry, type DiagnosticInput, type DtsExportClass, type DualExports, type EmitManifestOptions, type EmittedFile, type EntryOverride, type Environment, EnvironmentDetector, EnvironmentDetectorLive, type ExeBuild, type ExeConfig, type ExeRewrite, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, ExecutorResolver, ExecutorResolverLive, type ExtractAmbientOptions, 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 ModuleExportNames, type NextVersions, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OutputFormat, OutputRenderer, OutputRendererLive, type PackageJsonEntriesOptions, type PackageJsonLike, type PassKind, type PassReport, type PkgOsCpu, type PlainDiagnostic, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type ReexportBarrelAnalysis, type RenderReportOptions, type RenderedOutput, ReportPipelineLive, ReportTimings, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, type RunMetaPassOptions, 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 TsdownLogger, type ValidationInput, type WarningSuppressionRule, ambientOutName, analyzeReexportBarrel, applySubdirMetaEntries, assertNoEntryCollisions, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, classifyDtsExport, collectExportNames, computeExeFileName, copyAmbientDts, copyPublicDir, createEntryName, createTimer, createTsdownLogger, declarationExt, defaultManifestTransform, deriveExportPaths, deriveTargetGroupOptions, emitManifest, extractAmbientDts, extractEntries, findRelativeSpecifiers, flattenIssues, formatTime, generateMeta, isTargetObject, mixedDtsExportError, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReexportStub, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, runMetaPass, serializeIssues, transformBin, transformExports, transformManifest, writeDtsEmitTsconfig, writeIssuesArtifact, writeResolvedTsconfig, writeTargetsBinding };
|
|
1802
1882
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { analyzeReexportBarrel, collectExportNames, renderReexportStub } from "./dts/reexport-stub.js";
|
|
2
2
|
import { buildResolvedTsconfig, writeDtsEmitTsconfig, writeResolvedTsconfig } from "./dts/resolved-tsconfig.js";
|
|
3
3
|
import { resolveManifest } from "./catalog/resolve-catalogs.js";
|
|
4
|
+
import { ConfigValidationError, MetaGenerationError } from "./errors.js";
|
|
4
5
|
import { createEntryName, extractEntries } from "./entry/extract.js";
|
|
6
|
+
import { ambientOutName, assertNoEntryCollisions, classifyDtsExport, declarationExt, extractAmbientDts, mixedDtsExportError } from "./entry/ambient-dts.js";
|
|
5
7
|
import { defaultManifestTransform, normalizeBinPaths, transformBin, transformExports, transformManifest } from "./manifest/transform.js";
|
|
6
8
|
import { buildEmittedManifest, emitManifest } from "./manifest/emit-manifest.js";
|
|
7
9
|
import { buildMetricsPlugin } from "./report/metrics-plugin.js";
|
|
@@ -9,10 +11,10 @@ import { createTimer, formatTime } from "./report/timer.js";
|
|
|
9
11
|
import { createTsdownLogger } from "./report/tsdown-logger.js";
|
|
10
12
|
import { cjsDefaultInterop } from "./build/cjs-default-interop.js";
|
|
11
13
|
import { nodeBuiltinDefaultInterop } from "./build/node-builtin-default-interop.js";
|
|
12
|
-
import {
|
|
14
|
+
import { findRelativeSpecifiers } from "./dts/relative-imports.js";
|
|
15
|
+
import { copyAmbientDts, copyPublicDir } from "./build/sync-public.js";
|
|
13
16
|
import { deriveTargetGroupOptions } from "./build/target-groups.js";
|
|
14
17
|
import { buildTargetGroups } from "./build/build-target-groups.js";
|
|
15
|
-
import { ConfigValidationError, MetaGenerationError } from "./errors.js";
|
|
16
18
|
import { normalizeLooseFiles } from "./build/loose-files.js";
|
|
17
19
|
import { removeDeclarationMaps } from "./build/strip-maps.js";
|
|
18
20
|
import { resolveNextVersions } from "./changesets/next-versions.js";
|
|
@@ -50,4 +52,4 @@ import { ReportPipelineLive, renderReport } from "./report/pipeline.js";
|
|
|
50
52
|
import { writeTargetsBinding } from "./targets/binding.js";
|
|
51
53
|
import { CatalogAssemblyError, CatalogResolutionError } from "workspaces-effect";
|
|
52
54
|
|
|
53
|
-
export { BuildCollector, BuildCollectorTag, 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, analyzeReexportBarrel, applySubdirMetaEntries, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, collectExportNames, computeExeFileName, createEntryName, createTimer, createTsdownLogger, defaultManifestTransform, deriveExportPaths, deriveTargetGroupOptions, emitManifest, extractEntries, flattenIssues, formatTime, generateMeta, isTargetObject, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReexportStub, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, runMetaPass, serializeIssues,
|
|
55
|
+
export { BuildCollector, BuildCollectorTag, 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, ambientOutName, analyzeReexportBarrel, applySubdirMetaEntries, assertNoEntryCollisions, buildEmittedManifest, buildMetricsPlugin, buildResolvedTsconfig, buildTargetGroups, cjsDefaultInterop, classifyDtsExport, collectExportNames, computeExeFileName, copyAmbientDts, copyPublicDir, createEntryName, createTimer, createTsdownLogger, declarationExt, defaultManifestTransform, deriveExportPaths, deriveTargetGroupOptions, emitManifest, extractAmbientDts, extractEntries, findRelativeSpecifiers, flattenIssues, formatTime, generateMeta, isTargetObject, mixedDtsExportError, nodeBuiltinDefaultInterop, normalizeBinPaths, normalizeExeOptions, normalizeLooseFiles, normalizeMetaOptions, packageJsonEntries, readTsconfigJsx, removeDeclarationMaps, renderReexportStub, renderReport, resolveJsxConfig, resolveManifest, resolveNextVersions, resolvePortableTsconfig, resolveTargets, rewriteMetaVersions, runExeBuild, runMetaPass, serializeIssues, transformBin, transformExports, transformManifest, writeDtsEmitTsconfig, writeIssuesArtifact, writeResolvedTsconfig, writeTargetsBinding };
|
package/manifest/transform.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createEntryName } from "../entry/extract.js";
|
|
2
|
+
import { ambientOutName, classifyDtsExport, mixedDtsExportError } from "../entry/ambient-dts.js";
|
|
2
3
|
import sortPackageJson from "sort-package-json";
|
|
3
4
|
|
|
4
5
|
//#region src/manifest/transform.ts
|
|
@@ -83,6 +84,16 @@ const tsConditions = (exportKey, dual, subdirExports) => ({
|
|
|
83
84
|
...dual ? { require: toBuiltCjs(exportKey, subdirExports) } : {}
|
|
84
85
|
});
|
|
85
86
|
/**
|
|
87
|
+
* A `./public/<path>` export value points into the staged `public/` dir, whose CONTENTS `copyPublicDir`
|
|
88
|
+
* copies into the package root (only the `public/` segment is dropped; substructure is kept). So the
|
|
89
|
+
* published manifest value drops that same `public/` segment: `./public/tsconfig/ecma.json` becomes
|
|
90
|
+
* `./tsconfig/ecma.json`, resolving the file copyPublicDir placed at `<pkg>/tsconfig/ecma.json`.
|
|
91
|
+
* Non-strings and non-public values pass through unchanged.
|
|
92
|
+
*/
|
|
93
|
+
function stripPublicPrefix(value) {
|
|
94
|
+
return typeof value === "string" && value.startsWith("./public/") ? `./${value.slice(9)}` : value;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
86
97
|
* Rewrite an exports map: TS string targets become a types/import conditions object.
|
|
87
98
|
* Each TS condition also gets a `require` entry when `dual` is `true` (uniform) or when
|
|
88
99
|
* the export key is in the `dual` Set (per-entry).
|
|
@@ -95,12 +106,18 @@ const tsConditions = (exportKey, dual, subdirExports) => ({
|
|
|
95
106
|
* @public
|
|
96
107
|
*/
|
|
97
108
|
function transformExports(exports, dual = false, subdirExports) {
|
|
98
|
-
if (typeof exports === "string") return isTs(exports) ? tsConditions(".", isDualKey(dual, "."), subdirExports) : exports;
|
|
109
|
+
if (typeof exports === "string") return isTs(exports) ? tsConditions(".", isDualKey(dual, "."), subdirExports) : stripPublicPrefix(exports);
|
|
99
110
|
if (exports && typeof exports === "object") {
|
|
100
111
|
const out = {};
|
|
101
112
|
for (const [key, value] of Object.entries(exports)) {
|
|
102
|
-
if (key === "./package.json" || key.endsWith(".json")) {
|
|
103
|
-
out[key] = value;
|
|
113
|
+
if (key === "./package.json" || key.endsWith(".json") || isDeclarationFile(key)) {
|
|
114
|
+
out[key] = stripPublicPrefix(value);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const cls = classifyDtsExport(value);
|
|
118
|
+
if (cls.kind === "mixed") throw mixedDtsExportError(key);
|
|
119
|
+
if (cls.kind === "ambient") {
|
|
120
|
+
out[key] = { types: `./${ambientOutName(key, cls.source)}` };
|
|
104
121
|
continue;
|
|
105
122
|
}
|
|
106
123
|
if (typeof value === "string" && isTs(value)) out[key] = tsConditions(key, isDualKey(dual, key), subdirExports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/tsdown-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
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",
|
|
@@ -43,6 +43,6 @@
|
|
|
43
43
|
"workspaces-effect": "^1.2.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"effect": "
|
|
46
|
+
"effect": "^3.21.0"
|
|
47
47
|
}
|
|
48
48
|
}
|