@dbarrett24/tsdown-config 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +39 -1
- package/dist/index.js +87 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import { UserConfig } from "tsdown";
|
|
2
2
|
|
|
3
|
+
//#region entryManifest.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Published-source support for the Evolve UI MCP.
|
|
6
|
+
*
|
|
7
|
+
* The MCP indexes design-system *sources* at runtime, so every publishable library ships
|
|
8
|
+
* `src/**` and an `evolve-ui.entries.json` manifest inside `dist/` (the tarball root). The
|
|
9
|
+
* manifest is generated from the same entry maps tsdown consumes, so the published subpaths
|
|
10
|
+
* it lists can never drift from the real build entries.
|
|
11
|
+
*/
|
|
12
|
+
/** Manifest filename at the package (tarball) root. */
|
|
13
|
+
declare const ENTRY_MANIFEST_FILENAME = "evolve-ui.entries.json";
|
|
14
|
+
/** Which entry map an entry came from; the MCP scanner uses it to classify barrels. */
|
|
15
|
+
type EntryManifestSource = 'clientEntries' | 'entries';
|
|
16
|
+
type EntryManifestEntry = {
|
|
17
|
+
/** Entry key, which is also the published subpath. */exportName: string; /** Entry file as written in the build config, relative to the package root. */
|
|
18
|
+
filePath: string;
|
|
19
|
+
source: EntryManifestSource;
|
|
20
|
+
};
|
|
21
|
+
type EntryManifest = {
|
|
22
|
+
entries: EntryManifestEntry[];
|
|
23
|
+
package: string;
|
|
24
|
+
schemaVersion: 1;
|
|
25
|
+
};
|
|
26
|
+
/** Whether a path relative to `src/` belongs in the published source copy. */
|
|
27
|
+
declare const shouldShipSource: (relativePath: string) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Copy the shippable subset of `sourceDir` into `targetDir`, preserving structure. A missing
|
|
30
|
+
* source directory is a no-op so packages without `src/` still build.
|
|
31
|
+
*/
|
|
32
|
+
declare const copySources: (sourceDir: string, targetDir: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Build the manifest from the same entry maps handed to tsdown. When a key appears in both
|
|
35
|
+
* maps, `clientEntries` wins — matching how the build merges them into one `entry` object.
|
|
36
|
+
*/
|
|
37
|
+
declare const buildEntryManifest: (packageName: string, entries: Record<string, string>, clientEntries?: Record<string, string>) => EntryManifest;
|
|
38
|
+
/** Write the manifest into `targetDir` (the dist/tarball root). */
|
|
39
|
+
declare const writeEntryManifest: (packageName: string, entries: Record<string, string>, clientEntries?: Record<string, string>, targetDir?: string) => void;
|
|
40
|
+
//#endregion
|
|
3
41
|
//#region index.d.ts
|
|
4
42
|
declare const makeConfig: (entries: Record<string, string>, clientEntries?: Record<string, string>, optionOverrides?: Partial<UserConfig>) => UserConfig;
|
|
5
43
|
declare const defaultConfigObject: {
|
|
@@ -16,5 +54,5 @@ declare const defaultConfigObject: {
|
|
|
16
54
|
};
|
|
17
55
|
};
|
|
18
56
|
//#endregion
|
|
19
|
-
export { defaultConfigObject, makeConfig };
|
|
57
|
+
export { ENTRY_MANIFEST_FILENAME, type EntryManifest, type EntryManifestEntry, type EntryManifestSource, buildEntryManifest, copySources, defaultConfigObject, makeConfig, shouldShipSource, writeEntryManifest };
|
|
20
58
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,88 @@ import { merge } from "es-toolkit";
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { defineConfig } from "tsdown";
|
|
6
|
+
//#region entryManifest.ts
|
|
7
|
+
/**
|
|
8
|
+
* Published-source support for the Evolve UI MCP.
|
|
9
|
+
*
|
|
10
|
+
* The MCP indexes design-system *sources* at runtime, so every publishable library ships
|
|
11
|
+
* `src/**` and an `evolve-ui.entries.json` manifest inside `dist/` (the tarball root). The
|
|
12
|
+
* manifest is generated from the same entry maps tsdown consumes, so the published subpaths
|
|
13
|
+
* it lists can never drift from the real build entries.
|
|
14
|
+
*/
|
|
15
|
+
/** Manifest filename at the package (tarball) root. */
|
|
16
|
+
const ENTRY_MANIFEST_FILENAME = "evolve-ui.entries.json";
|
|
17
|
+
/**
|
|
18
|
+
* Inclusion allowlist for the source copy: the MCP scanner only ever reads TS/TSX, and an
|
|
19
|
+
* allowlist cannot silently ship whatever new file type lands in `src/` later.
|
|
20
|
+
*/
|
|
21
|
+
const SHIPPABLE_EXTENSIONS = [".ts", ".tsx"];
|
|
22
|
+
const EXCLUDED_NAME_INFIXES = [
|
|
23
|
+
".spec.",
|
|
24
|
+
".test.",
|
|
25
|
+
".stories."
|
|
26
|
+
];
|
|
27
|
+
const EXCLUDED_DIRECTORY_NAMES = /* @__PURE__ */ new Set(["__mocks__", "__snapshots__"]);
|
|
28
|
+
/** Whether a path relative to `src/` belongs in the published source copy. */
|
|
29
|
+
const shouldShipSource = (relativePath) => {
|
|
30
|
+
const segments = relativePath.split(/[\\/]/);
|
|
31
|
+
if (segments.some((segment) => EXCLUDED_DIRECTORY_NAMES.has(segment))) return false;
|
|
32
|
+
const fileName = segments[segments.length - 1] ?? "";
|
|
33
|
+
if (!SHIPPABLE_EXTENSIONS.some((extension) => fileName.endsWith(extension))) return false;
|
|
34
|
+
return !EXCLUDED_NAME_INFIXES.some((infix) => fileName.includes(infix));
|
|
35
|
+
};
|
|
36
|
+
const copyDirectory = (sourceDir, targetDir, relativePrefix) => {
|
|
37
|
+
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
38
|
+
const relativePath = relativePrefix.length === 0 ? entry.name : `${relativePrefix}/${entry.name}`;
|
|
39
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
40
|
+
const targetPath = path.join(targetDir, entry.name);
|
|
41
|
+
if (entry.isDirectory()) {
|
|
42
|
+
if (!EXCLUDED_DIRECTORY_NAMES.has(entry.name)) copyDirectory(sourcePath, targetPath, relativePath);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (entry.isFile() && shouldShipSource(relativePath)) {
|
|
46
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
47
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Copy the shippable subset of `sourceDir` into `targetDir`, preserving structure. A missing
|
|
53
|
+
* source directory is a no-op so packages without `src/` still build.
|
|
54
|
+
*/
|
|
55
|
+
const copySources = (sourceDir, targetDir) => {
|
|
56
|
+
if (!fs.existsSync(sourceDir)) return;
|
|
57
|
+
copyDirectory(sourceDir, targetDir, "");
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Build the manifest from the same entry maps handed to tsdown. When a key appears in both
|
|
61
|
+
* maps, `clientEntries` wins — matching how the build merges them into one `entry` object.
|
|
62
|
+
*/
|
|
63
|
+
const buildEntryManifest = (packageName, entries, clientEntries = {}) => {
|
|
64
|
+
const manifestEntries = [];
|
|
65
|
+
for (const [exportName, filePath] of Object.entries(entries)) if (!(exportName in clientEntries)) manifestEntries.push({
|
|
66
|
+
exportName,
|
|
67
|
+
filePath,
|
|
68
|
+
source: "entries"
|
|
69
|
+
});
|
|
70
|
+
for (const [exportName, filePath] of Object.entries(clientEntries)) manifestEntries.push({
|
|
71
|
+
exportName,
|
|
72
|
+
filePath,
|
|
73
|
+
source: "clientEntries"
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
entries: manifestEntries,
|
|
77
|
+
package: packageName,
|
|
78
|
+
schemaVersion: 1
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Write the manifest into `targetDir` (the dist/tarball root). */
|
|
82
|
+
const writeEntryManifest = (packageName, entries, clientEntries = {}, targetDir = "dist") => {
|
|
83
|
+
const manifest = buildEntryManifest(packageName, entries, clientEntries);
|
|
84
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
85
|
+
fs.writeFileSync(path.join(targetDir, ENTRY_MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 4)}\n`);
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
6
88
|
//#region workspace-specifier.ts
|
|
7
89
|
/**
|
|
8
90
|
* Resolution of pnpm workspace protocol specifiers for the emitted `dist/package.json`.
|
|
@@ -163,7 +245,11 @@ const makeConfigObject = (entries, clientEntries = {}, optionOverrides = {}) =>
|
|
|
163
245
|
...optionOverrides,
|
|
164
246
|
onSuccess: async (config, signal) => {
|
|
165
247
|
if (typeof optionOverrides.onSuccess === "function") await optionOverrides.onSuccess(config, signal);
|
|
248
|
+
const packageName = JSON.parse(fs.readFileSync("package.json").toString()).name;
|
|
249
|
+
if (typeof packageName !== "string" || packageName.length === 0) throw new Error("tsdown-config: package.json has no \"name\" to write into the entry manifest");
|
|
166
250
|
await copyPackageJson();
|
|
251
|
+
copySources("src", "dist/src");
|
|
252
|
+
writeEntryManifest(packageName, entries, clientEntries, "dist");
|
|
167
253
|
fillDuplicateDts({
|
|
168
254
|
...entries,
|
|
169
255
|
...clientEntries
|
|
@@ -173,6 +259,6 @@ const makeConfigObject = (entries, clientEntries = {}, optionOverrides = {}) =>
|
|
|
173
259
|
};
|
|
174
260
|
};
|
|
175
261
|
//#endregion
|
|
176
|
-
export { defaultConfigObject, makeConfig };
|
|
262
|
+
export { ENTRY_MANIFEST_FILENAME, buildEntryManifest, copySources, defaultConfigObject, makeConfig, shouldShipSource, writeEntryManifest };
|
|
177
263
|
|
|
178
264
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED