@dbarrett24/tsdown-config 1.1.0 → 1.1.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/dist/index.js +53 -16
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readWantedLockfile } from "@pnpm/lockfile-file";
|
|
2
2
|
import { merge } from "es-toolkit";
|
|
3
|
+
import * as fs$1 from "fs";
|
|
3
4
|
import fs from "fs";
|
|
4
5
|
import path from "path";
|
|
5
6
|
import { defineConfig } from "tsdown";
|
|
@@ -85,6 +86,50 @@ const writeEntryManifest = (packageName, entries, clientEntries = {}, targetDir
|
|
|
85
86
|
fs.writeFileSync(path.join(targetDir, ENTRY_MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 4)}\n`);
|
|
86
87
|
};
|
|
87
88
|
//#endregion
|
|
89
|
+
//#region json-file.ts
|
|
90
|
+
/**
|
|
91
|
+
* The one way this repo turns JSON text into a typed value.
|
|
92
|
+
*
|
|
93
|
+
* A bare `JSON.parse(...)` returns `any`, so `JSON.parse(text).name` compiles whether or not the
|
|
94
|
+
* file has a `name` — which is how the entry manifest once shipped `package: undefined` (PR #55).
|
|
95
|
+
* The caller states the shape it relies on as a type guard, and a mismatch throws an error naming
|
|
96
|
+
* the file and the failed expectation.
|
|
97
|
+
*
|
|
98
|
+
* This is the single generic core (`isJsonObject`, `parseJson`, `readJsonFile`). `scripts/lib/json-file.ts`
|
|
99
|
+
* imports it and adds only the guards scripts/ itself needs; do not copy it. Kept in its own
|
|
100
|
+
* dependency-free module (like `workspace-specifier.ts`) so it unit-tests without loading tsdown.
|
|
101
|
+
*
|
|
102
|
+
* `pnpm check-json-parse` fails on a bare `JSON.parse` anywhere in scope, and exempts this file
|
|
103
|
+
* because it is where the one permitted `JSON.parse` lives.
|
|
104
|
+
*/
|
|
105
|
+
const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
106
|
+
const isString = (value) => typeof value === "string";
|
|
107
|
+
const isOptional = (value, guard) => value === void 0 || guard(value);
|
|
108
|
+
const isStringRecord = (value) => isJsonObject(value) && Object.values(value).every(isString);
|
|
109
|
+
const isSourceManifest = (value) => isJsonObject(value) && isString(value.name) && isString(value.version) && isOptional(value.dependencies, isStringRecord) && isOptional(value.peerDependencies, isStringRecord) && isOptional(value.publishConfig, (v) => isJsonObject(v) && isOptional(v.access, isString)) && isOptional(value.bin, isStringRecord) && isOptional(value.scripts, (v) => isJsonObject(v) && isOptional(v.postinstall, isString));
|
|
110
|
+
/** A manifest that declares a string `version`, which is all a workspace dependency lookup needs. */
|
|
111
|
+
const hasStringVersion = (value) => isJsonObject(value) && isString(value.version);
|
|
112
|
+
/**
|
|
113
|
+
* Parse JSON text and check it against `guard`.
|
|
114
|
+
*
|
|
115
|
+
* @param source what the text came from (a path, or a description such as `WebSocket frame`); it
|
|
116
|
+
* leads the error message
|
|
117
|
+
* @param expectation what the guard checks, for the error message (e.g. `a package.json object`)
|
|
118
|
+
*/
|
|
119
|
+
const parseJson = (text, source, guard, expectation = "the expected shape") => {
|
|
120
|
+
let parsed;
|
|
121
|
+
try {
|
|
122
|
+
parsed = JSON.parse(text);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
125
|
+
throw new Error(`${source}: not valid JSON (${reason})`);
|
|
126
|
+
}
|
|
127
|
+
if (!guard(parsed)) throw new Error(`${source}: parsed JSON is not ${expectation}`);
|
|
128
|
+
return parsed;
|
|
129
|
+
};
|
|
130
|
+
/** Read `filePath` as UTF-8 JSON and check it against `guard`; errors name `filePath`. */
|
|
131
|
+
const readJsonFile = (filePath, guard, expectation = "the expected shape") => parseJson(fs$1.readFileSync(filePath, "utf-8"), filePath, guard, expectation);
|
|
132
|
+
//#endregion
|
|
88
133
|
//#region workspace-specifier.ts
|
|
89
134
|
/**
|
|
90
135
|
* Resolution of pnpm workspace protocol specifiers for the emitted `dist/package.json`.
|
|
@@ -120,7 +165,7 @@ const makeConfig = (entries, clientEntries, optionOverrides) => {
|
|
|
120
165
|
return defineConfig(makeConfigObject(entries, clientEntries, optionOverrides));
|
|
121
166
|
};
|
|
122
167
|
const copyPackageJson = async () => {
|
|
123
|
-
const packageJSON =
|
|
168
|
+
const packageJSON = readJsonFile("package.json", isSourceManifest, "a package.json manifest");
|
|
124
169
|
const newPackageJSON = {};
|
|
125
170
|
newPackageJSON.name = packageJSON.name;
|
|
126
171
|
newPackageJSON.dependencies = packageJSON.dependencies;
|
|
@@ -177,21 +222,13 @@ const copyPackageJson = async () => {
|
|
|
177
222
|
const packageName = process.cwd().split(path.sep).slice(-2).join("/");
|
|
178
223
|
const lockfile_package_list = (await readWantedLockfile("../..", { ignoreIncompatible: true }))?.importers?.[packageName];
|
|
179
224
|
const merged_deps = merge(lockfile_package_list?.dependencies ?? {}, lockfile_package_list?.devDependencies ?? {});
|
|
180
|
-
for (const
|
|
181
|
-
const [dep,
|
|
182
|
-
|
|
183
|
-
const package_path = merged_deps?.[dep].version.replace(/(?:link:|\/dist)/g, "") + "/package.json";
|
|
184
|
-
const packageJSON = JSON.parse(fs.readFileSync(package_path).toString());
|
|
185
|
-
newPackageJSON.peerDependencies[dep] = resolveWorkspaceSpecifier(version, packageJSON.version);
|
|
186
|
-
}
|
|
225
|
+
for (const [dep, version] of Object.entries(packageJSON.peerDependencies ?? {})) if (isWorkspaceSpecifier(version)) {
|
|
226
|
+
const packageJSON = readJsonFile(merged_deps?.[dep].version.replace(/(?:link:|\/dist)/g, "") + "/package.json", hasStringVersion, "a package.json with a string \"version\"");
|
|
227
|
+
newPackageJSON.peerDependencies[dep] = resolveWorkspaceSpecifier(version, packageJSON.version);
|
|
187
228
|
}
|
|
188
|
-
for (const
|
|
189
|
-
const [dep,
|
|
190
|
-
|
|
191
|
-
const package_path = merged_deps?.[dep].version.replace(/(?:link:|\/dist)/g, "") + "/package.json";
|
|
192
|
-
const packageJSON = JSON.parse(fs.readFileSync(package_path).toString());
|
|
193
|
-
newPackageJSON.dependencies[dep] = resolveWorkspaceSpecifier(version, packageJSON.version);
|
|
194
|
-
}
|
|
229
|
+
for (const [dep, version] of Object.entries(packageJSON.dependencies ?? {})) if (isWorkspaceSpecifier(version)) {
|
|
230
|
+
const packageJSON = readJsonFile(merged_deps?.[dep].version.replace(/(?:link:|\/dist)/g, "") + "/package.json", hasStringVersion, "a package.json with a string \"version\"");
|
|
231
|
+
newPackageJSON.dependencies[dep] = resolveWorkspaceSpecifier(version, packageJSON.version);
|
|
195
232
|
}
|
|
196
233
|
fs.writeFileSync("dist/package.json", formatEmittedPackageJson(newPackageJSON));
|
|
197
234
|
};
|
|
@@ -245,7 +282,7 @@ const makeConfigObject = (entries, clientEntries = {}, optionOverrides = {}) =>
|
|
|
245
282
|
...optionOverrides,
|
|
246
283
|
onSuccess: async (config, signal) => {
|
|
247
284
|
if (typeof optionOverrides.onSuccess === "function") await optionOverrides.onSuccess(config, signal);
|
|
248
|
-
const packageName =
|
|
285
|
+
const packageName = readJsonFile("package.json", isJsonObject, "a package.json object").name;
|
|
249
286
|
if (typeof packageName !== "string" || packageName.length === 0) throw new Error("tsdown-config: package.json has no \"name\" to write into the entry manifest");
|
|
250
287
|
await copyPackageJson();
|
|
251
288
|
copySources("src", "dist/src");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dbarrett24/tsdown-config",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Shared tsdown configuration for building component libraries (publish-from-dist with generated wildcard exports)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"lint-fix": "pnpm lint-oxlint-fix && pnpm lint-oxfmt-fix",
|
|
56
56
|
"lint-oxfmt": "oxfmt --config ../../.oxfmtrc.json --check \"*.ts\"",
|
|
57
57
|
"lint-oxfmt-fix": "oxfmt --config ../../.oxfmtrc.json --write \"*.ts\"",
|
|
58
|
-
"lint-oxlint": "oxlint index.ts tsdown.config.ts workspace-specifier.ts",
|
|
59
|
-
"lint-oxlint-fix": "oxlint --fix index.ts tsdown.config.ts workspace-specifier.ts",
|
|
58
|
+
"lint-oxlint": "oxlint index.ts json-file.ts tsdown.config.ts workspace-specifier.ts",
|
|
59
|
+
"lint-oxlint-fix": "oxlint --fix index.ts json-file.ts tsdown.config.ts workspace-specifier.ts",
|
|
60
60
|
"ts-check": "tsc --noEmit",
|
|
61
61
|
"test": "jest --passWithNoTests"
|
|
62
62
|
}
|