zshy 0.0.5 → 0.0.7
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 +257 -87
- package/dist/index.cjs +697 -0
- package/dist/index.js +659 -0
- package/{out → dist}/utils.cjs +33 -38
- package/{out → dist}/utils.d.cts +6 -1
- package/{out → dist}/utils.d.ts +6 -1
- package/{out → dist}/utils.js +31 -38
- package/package.json +19 -30
- package/out/index.cjs +0 -481
- package/out/index.js +0 -443
- package/out/plugins/a.cjs +0 -4
- package/out/plugins/a.d.cts +0 -1
- package/out/plugins/a.d.ts +0 -1
- package/out/plugins/a.js +0 -1
- package/out/plugins/b.cjs +0 -4
- package/out/plugins/b.d.cts +0 -1
- package/out/plugins/b.d.ts +0 -1
- package/out/plugins/b.js +0 -1
- /package/{out → dist}/index.d.cts +0 -0
- /package/{out → dist}/index.d.ts +0 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path/posix"));
|
|
42
|
+
const arg_1 = __importDefault(require("arg"));
|
|
43
|
+
const globby_1 = require("globby");
|
|
44
|
+
const table_1 = require("table");
|
|
45
|
+
const ts = __importStar(require("typescript"));
|
|
46
|
+
const utils_1 = require("./utils.cjs");
|
|
47
|
+
function isSourceFile(filePath) {
|
|
48
|
+
return (filePath.endsWith(".ts") || filePath.endsWith(".mts") || filePath.endsWith(".cts") || filePath.endsWith(".tsx"));
|
|
49
|
+
}
|
|
50
|
+
function removeExtension(filePath) {
|
|
51
|
+
return filePath.split(".").slice(0, -1).join(".") || filePath;
|
|
52
|
+
}
|
|
53
|
+
async function main() {
|
|
54
|
+
///////////////////////////////////
|
|
55
|
+
/// parse command line args ///
|
|
56
|
+
///////////////////////////////////
|
|
57
|
+
// Parse command line arguments using arg library
|
|
58
|
+
let args;
|
|
59
|
+
try {
|
|
60
|
+
args = (0, arg_1.default)({
|
|
61
|
+
"--help": Boolean,
|
|
62
|
+
"--verbose": Boolean,
|
|
63
|
+
"--project": String,
|
|
64
|
+
"--dry-run": Boolean,
|
|
65
|
+
// "--attw": Boolean,
|
|
66
|
+
// Aliases
|
|
67
|
+
"-h": "--help",
|
|
68
|
+
"-p": "--project",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error instanceof Error) {
|
|
73
|
+
(0, utils_1.emojiLog)("❌", error.message, "error");
|
|
74
|
+
}
|
|
75
|
+
console.error(`Use --help for usage information`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
// Handle help flag
|
|
79
|
+
if (args["--help"]) {
|
|
80
|
+
console.log(`
|
|
81
|
+
Usage: zshy [options]
|
|
82
|
+
|
|
83
|
+
Options:
|
|
84
|
+
-h, --help Show this help message
|
|
85
|
+
-p, --project <path> Path to tsconfig.json file
|
|
86
|
+
--verbose Enable verbose output
|
|
87
|
+
--dry-run Don't write any files, just log what would be done
|
|
88
|
+
|
|
89
|
+
Examples:
|
|
90
|
+
zshy # Run build
|
|
91
|
+
zshy --project ./tsconfig.build.json # Use specific tsconfig file (defaults to tsconfig.json)
|
|
92
|
+
zshy --verbose # Enable verbose logging
|
|
93
|
+
zshy --dry-run # Preview changes without writing files
|
|
94
|
+
`);
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
98
|
+
let pmExec;
|
|
99
|
+
if (userAgent?.startsWith("pnpm")) {
|
|
100
|
+
pmExec = "pnpm exec";
|
|
101
|
+
}
|
|
102
|
+
else if (userAgent?.startsWith("yarn")) {
|
|
103
|
+
pmExec = "yarn exec";
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
pmExec = "npx";
|
|
107
|
+
}
|
|
108
|
+
(0, utils_1.emojiLog)("💎", "Starting build... 🐒");
|
|
109
|
+
const isVerbose = args["--verbose"];
|
|
110
|
+
const isDryRun = args["--dry-run"];
|
|
111
|
+
const isAttw = false; // args["--attw"];
|
|
112
|
+
if (isVerbose) {
|
|
113
|
+
(0, utils_1.emojiLog)("ℹ️", "Verbose mode enabled");
|
|
114
|
+
(0, utils_1.emojiLog)("📦", `Detected package manager: ${pmExec}`);
|
|
115
|
+
}
|
|
116
|
+
if (isDryRun) {
|
|
117
|
+
(0, utils_1.emojiLog)("🔍", "Dry run mode enabled - no files will be written");
|
|
118
|
+
}
|
|
119
|
+
///////////////////////////////////
|
|
120
|
+
/// find and read pkg json ///
|
|
121
|
+
///////////////////////////////////
|
|
122
|
+
// Find package.json by scanning up the file system
|
|
123
|
+
let packageJsonPath = "./package.json";
|
|
124
|
+
let currentDir = process.cwd();
|
|
125
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
126
|
+
const candidatePath = path.join(currentDir, "package.json");
|
|
127
|
+
if (fs.existsSync(candidatePath)) {
|
|
128
|
+
packageJsonPath = candidatePath;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
currentDir = path.dirname(currentDir);
|
|
132
|
+
}
|
|
133
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
134
|
+
(0, utils_1.emojiLog)("❌", "package.json not found in current directory or any parent directories", "error");
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
// read package.json and extract the "zshy" exports config
|
|
138
|
+
// console.log("📦 Extracting entry points from package.json exports...");
|
|
139
|
+
const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
140
|
+
const pkgJsonDir = path.dirname(packageJsonPath);
|
|
141
|
+
// print project root
|
|
142
|
+
(0, utils_1.emojiLog)("⚙️", `Detected project root: ${pkgJsonDir}`);
|
|
143
|
+
(0, utils_1.emojiLog)("📦", `Reading package.json from ./${path.relative(pkgJsonDir, packageJsonPath)}`);
|
|
144
|
+
/////////////////////////////////
|
|
145
|
+
/// parse zshy config ///
|
|
146
|
+
/////////////////////////////////
|
|
147
|
+
// const pkgJson = JSON.parse(fs.readFileSync("./package.json", "utf-8"));
|
|
148
|
+
const CONFIG_KEY = "zshy";
|
|
149
|
+
let config;
|
|
150
|
+
if (!pkgJson[CONFIG_KEY]) {
|
|
151
|
+
(0, utils_1.emojiLog)("❌", `No "${CONFIG_KEY}" key found in package.json`, "error");
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
if (typeof pkgJson[CONFIG_KEY] === "string") {
|
|
155
|
+
config = {
|
|
156
|
+
exports: { ".": pkgJson[CONFIG_KEY] },
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
else if (typeof pkgJson[CONFIG_KEY] === "object") {
|
|
160
|
+
config = { ...pkgJson[CONFIG_KEY] };
|
|
161
|
+
if (typeof config.exports === "string") {
|
|
162
|
+
config.exports = { ".": config.exports };
|
|
163
|
+
}
|
|
164
|
+
else if (typeof config.exports === "undefined") {
|
|
165
|
+
(0, utils_1.emojiLog)("❌", `Missing "exports" key in package.json#/${CONFIG_KEY}`, "error");
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
else if (typeof config.exports !== "object") {
|
|
169
|
+
(0, utils_1.emojiLog)("❌", `Invalid "exports" key in package.json#/${CONFIG_KEY}`, "error");
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
// Validate bin field if present
|
|
173
|
+
if (config.bin !== undefined) {
|
|
174
|
+
if (typeof config.bin === "string") {
|
|
175
|
+
// Keep string format - we'll handle this in entry point extraction
|
|
176
|
+
}
|
|
177
|
+
else if (typeof config.bin === "object" && config.bin !== null) {
|
|
178
|
+
// Object format is valid
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
(0, utils_1.emojiLog)("❌", `Invalid "bin" key in package.json#/${CONFIG_KEY}, expected string or object`, "error");
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// {
|
|
186
|
+
// exports: { ".": pkgJson[CONFIG_KEY].exports },
|
|
187
|
+
// };
|
|
188
|
+
}
|
|
189
|
+
else if (typeof pkgJson[CONFIG_KEY] === "undefined") {
|
|
190
|
+
(0, utils_1.emojiLog)("❌", `Missing "${CONFIG_KEY}" key in package.json`, "error");
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
(0, utils_1.emojiLog)("❌", `Invalid "${CONFIG_KEY}" key in package.json, expected string or object`, "error");
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
if (isVerbose) {
|
|
198
|
+
(0, utils_1.emojiLog)("🔧", `Parsed zshy config: ${(0, utils_1.formatForLog)(config)}`);
|
|
199
|
+
}
|
|
200
|
+
///////////////////////////
|
|
201
|
+
/// read tsconfig ///
|
|
202
|
+
///////////////////////////
|
|
203
|
+
// Determine tsconfig.json path
|
|
204
|
+
let tsconfigPath;
|
|
205
|
+
if (args["--project"]) {
|
|
206
|
+
// CLI flag takes priority
|
|
207
|
+
const resolvedProjectPath = path.resolve(process.cwd(), args["--project"]);
|
|
208
|
+
if (fs.existsSync(resolvedProjectPath)) {
|
|
209
|
+
if (fs.statSync(resolvedProjectPath).isDirectory()) {
|
|
210
|
+
(0, utils_1.emojiLog)("❌", `--project must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`, "error");
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Use the file directly
|
|
215
|
+
tsconfigPath = resolvedProjectPath;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
(0, utils_1.emojiLog)("❌", `tsconfig.json file not found: ${resolvedProjectPath}`, "error");
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
else if (config.tsconfig) {
|
|
224
|
+
// Fallback to package.json config
|
|
225
|
+
const resolvedProjectPath = path.resolve(pkgJsonDir, config.tsconfig);
|
|
226
|
+
if (fs.existsSync(resolvedProjectPath)) {
|
|
227
|
+
if (fs.statSync(resolvedProjectPath).isDirectory()) {
|
|
228
|
+
(0, utils_1.emojiLog)("❌", `zshy.tsconfig must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`, "error");
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
// Use the file directly
|
|
233
|
+
tsconfigPath = resolvedProjectPath;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
(0, utils_1.emojiLog)("❌", `Tsconfig file not found: ${resolvedProjectPath}`, "error");
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// Default to tsconfig.json in the package.json directory
|
|
243
|
+
tsconfigPath = path.join(pkgJsonDir, "tsconfig.json");
|
|
244
|
+
}
|
|
245
|
+
const _parsedConfig = (0, utils_1.readTsconfig)(tsconfigPath);
|
|
246
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
247
|
+
// Check if tsconfig.json exists
|
|
248
|
+
(0, utils_1.emojiLog)("❌", `tsconfig.json not found at ${path.resolve(tsconfigPath)}`, "error");
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
(0, utils_1.emojiLog)("📁", `Reading tsconfig from ./${path.relative(pkgJsonDir, tsconfigPath)}`);
|
|
252
|
+
// if (_parsedConfig.rootDir) {
|
|
253
|
+
// console.error(
|
|
254
|
+
// `❌ rootDir is determined from your set of entrypoints; you can remove it from your tsconfig.json.`,
|
|
255
|
+
// );
|
|
256
|
+
// process.exit(1);
|
|
257
|
+
// }
|
|
258
|
+
// if (_parsedConfig.declarationDir) {
|
|
259
|
+
// console.error(
|
|
260
|
+
// `❌ declarationDir is not supported in zshy; you should remove it from your tsconfig.json.`,
|
|
261
|
+
// );
|
|
262
|
+
// process.exit(1);
|
|
263
|
+
// }
|
|
264
|
+
// set/override compiler options
|
|
265
|
+
delete _parsedConfig.customConditions; // can't be set for CommonJS builds
|
|
266
|
+
const outDir = path.resolve(pkgJsonDir, _parsedConfig?.outDir || "./dist");
|
|
267
|
+
const relOutDir = path.relative(pkgJsonDir, outDir);
|
|
268
|
+
const declarationDir = path.resolve(pkgJsonDir, _parsedConfig?.declarationDir || relOutDir);
|
|
269
|
+
const relDeclarationDir = path.relative(pkgJsonDir, declarationDir);
|
|
270
|
+
// clean up outDir and declarationDir
|
|
271
|
+
if (relOutDir !== "") {
|
|
272
|
+
(0, utils_1.emojiLog)("🗑️", `Cleaning up outDir...`);
|
|
273
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
274
|
+
// // print success mesage in verbose mode
|
|
275
|
+
if (isVerbose) {
|
|
276
|
+
if (fs.existsSync(outDir)) {
|
|
277
|
+
(0, utils_1.emojiLog)("❌", `Failed to clean up outDir: ${relOutDir}. Directory still exists.`, "error");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
(0, utils_1.emojiLog)("🗑️", `Skipping cleanup of outDir as it contains source files`);
|
|
283
|
+
}
|
|
284
|
+
if (relDeclarationDir !== relOutDir && relDeclarationDir !== "") {
|
|
285
|
+
(0, utils_1.emojiLog)("🗑️", `Cleaning up declarationDir...`);
|
|
286
|
+
fs.rmSync(declarationDir, { recursive: true, force: true });
|
|
287
|
+
// // print success mesage in verbose mode
|
|
288
|
+
if (isVerbose) {
|
|
289
|
+
if (fs.existsSync(declarationDir)) {
|
|
290
|
+
(0, utils_1.emojiLog)("❌", `Failed to clean up declarationDir: ${relDeclarationDir}. Directory still exists.`, "error");
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
if (isVerbose)
|
|
296
|
+
(0, utils_1.emojiLog)("🗑️", `Skipping cleanup of declarationDir as it contains source files`);
|
|
297
|
+
}
|
|
298
|
+
const tsconfigJson = {
|
|
299
|
+
..._parsedConfig,
|
|
300
|
+
outDir,
|
|
301
|
+
target: _parsedConfig.target ?? ts.ScriptTarget.ES2020, // ensure compatible target for CommonJS
|
|
302
|
+
skipLibCheck: true, // skip library checks to reduce errors
|
|
303
|
+
declaration: true,
|
|
304
|
+
noEmit: false,
|
|
305
|
+
emitDeclarationOnly: false,
|
|
306
|
+
rewriteRelativeImportExtensions: true,
|
|
307
|
+
verbatimModuleSyntax: false,
|
|
308
|
+
};
|
|
309
|
+
if (relOutDir === "") {
|
|
310
|
+
if (!pkgJson.files) {
|
|
311
|
+
(0, utils_1.emojiLog)("⚠️", 'You\'re building your code to the project root. This means your compiled files will be generated alongside your source files.\n ➜ Setting "files" in package.json to exclude TypeScript source from the published package.');
|
|
312
|
+
pkgJson.files = ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"];
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
console.warn(`⚠️ You\'re building your code to the project root. This means your compiled files will be generated alongside your source files.
|
|
316
|
+
➜ Ensure that your "files" in package.json excludes TypeScript source files, or your users may experience .d.ts resolution issues in some environments:
|
|
317
|
+
|
|
318
|
+
"files": ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"],
|
|
319
|
+
`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
if (!pkgJson.files) {
|
|
324
|
+
(0, utils_1.emojiLog)("⚠️", `The "files" key is missing in package.json. Setting to "${relOutDir}".`);
|
|
325
|
+
pkgJson.files = [relOutDir];
|
|
326
|
+
if (relOutDir !== relDeclarationDir) {
|
|
327
|
+
pkgJson.files.push(relDeclarationDir);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/////////////////////////////////
|
|
332
|
+
/// extract entry points ///
|
|
333
|
+
/////////////////////////////////
|
|
334
|
+
// Extract entry points from zshy exports config
|
|
335
|
+
(0, utils_1.emojiLog)("➡️", "Determining entrypoints...");
|
|
336
|
+
const entryPatterns = [];
|
|
337
|
+
const rows = [["Subpath", "Entrypoint"]];
|
|
338
|
+
for (const [exportPath, sourcePath] of Object.entries(config.exports)) {
|
|
339
|
+
if (exportPath.includes("package.json"))
|
|
340
|
+
continue;
|
|
341
|
+
let cleanExportPath;
|
|
342
|
+
if (exportPath === ".") {
|
|
343
|
+
cleanExportPath = pkgJson.name;
|
|
344
|
+
}
|
|
345
|
+
else if (exportPath.startsWith("./")) {
|
|
346
|
+
cleanExportPath = pkgJson.name + "/" + exportPath.slice(2);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
(0, utils_1.emojiLog)("⚠️", `Invalid subpath export "${exportPath}" — should start with "./"`, "warn");
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
if (typeof sourcePath === "string") {
|
|
353
|
+
if (sourcePath.includes("*")) {
|
|
354
|
+
if (!sourcePath.endsWith("/*")) {
|
|
355
|
+
(0, utils_1.emojiLog)("❌", `Wildcard paths should not contain file extensions: ${sourcePath}`, "error");
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
const pattern = sourcePath.slice(0, -2) + "/*.{ts,tsx,mts,cts}";
|
|
359
|
+
const wildcardFiles = await (0, globby_1.globby)([pattern], {
|
|
360
|
+
ignore: ["**/*.d.ts"],
|
|
361
|
+
cwd: pkgJsonDir,
|
|
362
|
+
deep: 1,
|
|
363
|
+
});
|
|
364
|
+
entryPatterns.push(...wildcardFiles);
|
|
365
|
+
rows.push([`"${cleanExportPath}"`, `${sourcePath} (${wildcardFiles.length} matches)`]);
|
|
366
|
+
}
|
|
367
|
+
else if (isSourceFile(sourcePath)) {
|
|
368
|
+
entryPatterns.push(sourcePath);
|
|
369
|
+
rows.push([`"${cleanExportPath}"`, sourcePath]);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Extract bin entry points from zshy bin config
|
|
374
|
+
if (config.bin) {
|
|
375
|
+
if (typeof config.bin === "string") {
|
|
376
|
+
// Single bin entry
|
|
377
|
+
if (isSourceFile(config.bin)) {
|
|
378
|
+
entryPatterns.push(config.bin);
|
|
379
|
+
rows.push([`bin:${pkgJson.name}`, config.bin]);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
// Multiple bin entries
|
|
384
|
+
for (const [binName, sourcePath] of Object.entries(config.bin)) {
|
|
385
|
+
if (typeof sourcePath === "string" && isSourceFile(sourcePath)) {
|
|
386
|
+
entryPatterns.push(sourcePath);
|
|
387
|
+
rows.push([`bin:${binName}`, sourcePath]);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
console.log(" " +
|
|
393
|
+
(0, table_1.table)(rows, {
|
|
394
|
+
drawHorizontalLine: (lineIndex, rowCount) => {
|
|
395
|
+
return (lineIndex === 0 ||
|
|
396
|
+
lineIndex === 1 ||
|
|
397
|
+
// lineIndex === rowCount - 1 ||
|
|
398
|
+
lineIndex === rowCount);
|
|
399
|
+
},
|
|
400
|
+
})
|
|
401
|
+
.split("\n")
|
|
402
|
+
.join("\n ")
|
|
403
|
+
.trim());
|
|
404
|
+
///////////////////////////////
|
|
405
|
+
/// compute entry points ///
|
|
406
|
+
///////////////////////////////
|
|
407
|
+
// compute entry points
|
|
408
|
+
const entryPoints = await (0, utils_1.getEntryPoints)(entryPatterns);
|
|
409
|
+
// disallow .mts and .cts files
|
|
410
|
+
if (entryPoints.some((ep) => ep.endsWith(".mts") || ep.endsWith(".cts"))) {
|
|
411
|
+
(0, utils_1.emojiLog)("❌", "Source files with .mts or .cts extensions are not supported. Please use regular .ts files.", "error");
|
|
412
|
+
process.exit(1);
|
|
413
|
+
}
|
|
414
|
+
if (entryPoints.length === 0) {
|
|
415
|
+
(0, utils_1.emojiLog)("❌", "No entry points found matching the specified patterns in package.json#/zshy exports", "error");
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
///////////////////////////////
|
|
419
|
+
/// compute root dir ///
|
|
420
|
+
///////////////////////////////
|
|
421
|
+
// Compute common ancestor directory for all entry points
|
|
422
|
+
let rootDir;
|
|
423
|
+
if (tsconfigJson.rootDir) {
|
|
424
|
+
rootDir = path.resolve(tsconfigPath, tsconfigJson.rootDir);
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
// compute rootDir from entrypoints
|
|
428
|
+
rootDir =
|
|
429
|
+
entryPoints.length > 0
|
|
430
|
+
? entryPoints.reduce((common, entryPoint) => {
|
|
431
|
+
const entryDir = path.dirname(path.resolve(entryPoint));
|
|
432
|
+
const commonDir = path.resolve(common);
|
|
433
|
+
// Find the longest common path
|
|
434
|
+
const entryParts = entryDir.split(path.sep);
|
|
435
|
+
const commonParts = commonDir.split(path.sep);
|
|
436
|
+
let i = 0;
|
|
437
|
+
while (i < entryParts.length && i < commonParts.length && entryParts[i] === commonParts[i]) {
|
|
438
|
+
i++;
|
|
439
|
+
}
|
|
440
|
+
return commonParts.slice(0, i).join(path.sep) || path.sep;
|
|
441
|
+
}, path.dirname(path.resolve(entryPoints[0])))
|
|
442
|
+
: process.cwd();
|
|
443
|
+
}
|
|
444
|
+
const relRootDir = path.relative(pkgJsonDir, rootDir);
|
|
445
|
+
// Display resolved paths table
|
|
446
|
+
(0, utils_1.emojiLog)("🔧", "Resolved build paths:");
|
|
447
|
+
const pathRows = [["Location", "Resolved path"]];
|
|
448
|
+
// pathRows.push([
|
|
449
|
+
// "package.json",
|
|
450
|
+
// `./${path.relative(pkgJsonDir, packageJsonPath)}`,
|
|
451
|
+
// ]);
|
|
452
|
+
// pathRows.push(["tsconfig", `./${path.relative(pkgJsonDir, tsconfigPath)}`]);
|
|
453
|
+
pathRows.push(["rootDir", relRootDir ? `./${relRootDir}` : "."]);
|
|
454
|
+
pathRows.push(["outDir", relOutDir ? `./${relOutDir}` : "."]);
|
|
455
|
+
if (relDeclarationDir !== relOutDir) {
|
|
456
|
+
pathRows.push(["declarationDir", relDeclarationDir ? `./${relDeclarationDir}` : "."]);
|
|
457
|
+
}
|
|
458
|
+
console.log(" " +
|
|
459
|
+
(0, table_1.table)(pathRows, {
|
|
460
|
+
drawHorizontalLine: (lineIndex, rowCount) => {
|
|
461
|
+
return (lineIndex === 0 ||
|
|
462
|
+
lineIndex === 1 ||
|
|
463
|
+
// lineIndex === rowCount - 1 ||
|
|
464
|
+
lineIndex === rowCount);
|
|
465
|
+
},
|
|
466
|
+
})
|
|
467
|
+
.split("\n")
|
|
468
|
+
.join("\n ")
|
|
469
|
+
.trim());
|
|
470
|
+
const isTypeModule = pkgJson.type === "module";
|
|
471
|
+
if (isTypeModule) {
|
|
472
|
+
(0, utils_1.emojiLog)("🟨", `Package is an ES module (package.json#/type is "module")`);
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
(0, utils_1.emojiLog)("🐢", `Package is a CommonJS module (${pkgJson.type === "commonjs" ? 'package.json#/type is "commonjs"' : 'package.json#/type not set to "module"'})`);
|
|
476
|
+
}
|
|
477
|
+
///////////////////////////////
|
|
478
|
+
/// compile tsc ///
|
|
479
|
+
///////////////////////////////
|
|
480
|
+
const uniqueEntryPoints = [...new Set(entryPoints)];
|
|
481
|
+
try {
|
|
482
|
+
if (isVerbose) {
|
|
483
|
+
(0, utils_1.emojiLog)("→", `Resolved entrypoints: ${(0, utils_1.formatForLog)(uniqueEntryPoints)}`);
|
|
484
|
+
(0, utils_1.emojiLog)("→", `Resolved compilerOptions: ${(0, utils_1.formatForLog)({
|
|
485
|
+
...tsconfigJson,
|
|
486
|
+
module: ts.ModuleKind[tsconfigJson.module],
|
|
487
|
+
moduleResolution: ts.ModuleResolutionKind[tsconfigJson.moduleResolution],
|
|
488
|
+
target: ts.ScriptTarget[tsconfigJson.target],
|
|
489
|
+
})}`);
|
|
490
|
+
}
|
|
491
|
+
// Track all written files
|
|
492
|
+
const allWrittenFiles = [];
|
|
493
|
+
// CJS
|
|
494
|
+
(0, utils_1.emojiLog)("🧱", `Building CJS...${isTypeModule ? ` (rewriting .ts -> .cjs/.d.cts)` : ``}`);
|
|
495
|
+
const cjsFiles = await (0, utils_1.compileProject)({
|
|
496
|
+
configPath: tsconfigPath,
|
|
497
|
+
mode: isTypeModule ? "cts" : "ts",
|
|
498
|
+
verbose: isVerbose,
|
|
499
|
+
dryRun: isDryRun,
|
|
500
|
+
packageRoot: pkgJsonDir,
|
|
501
|
+
compilerOptions: {
|
|
502
|
+
...tsconfigJson,
|
|
503
|
+
module: ts.ModuleKind.CommonJS,
|
|
504
|
+
moduleResolution: ts.ModuleResolutionKind.Node10,
|
|
505
|
+
outDir,
|
|
506
|
+
},
|
|
507
|
+
}, uniqueEntryPoints);
|
|
508
|
+
allWrittenFiles.push(...cjsFiles);
|
|
509
|
+
// ESM
|
|
510
|
+
(0, utils_1.emojiLog)("🧱", `Building ESM...${isTypeModule ? `` : ` (rewriting .ts -> .mjs/.d.mts)`}`);
|
|
511
|
+
const esmFiles = await (0, utils_1.compileProject)({
|
|
512
|
+
configPath: tsconfigPath,
|
|
513
|
+
mode: isTypeModule ? "ts" : "mts",
|
|
514
|
+
verbose: isVerbose,
|
|
515
|
+
dryRun: isDryRun,
|
|
516
|
+
packageRoot: pkgJsonDir,
|
|
517
|
+
compilerOptions: {
|
|
518
|
+
...tsconfigJson,
|
|
519
|
+
module: ts.ModuleKind.ESNext,
|
|
520
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
521
|
+
outDir,
|
|
522
|
+
},
|
|
523
|
+
}, uniqueEntryPoints);
|
|
524
|
+
allWrittenFiles.push(...esmFiles);
|
|
525
|
+
///////////////////////////////////
|
|
526
|
+
/// display written files ///
|
|
527
|
+
///////////////////////////////////
|
|
528
|
+
// Display files that were written or would be written (only in verbose mode)
|
|
529
|
+
if (isVerbose && allWrittenFiles.length > 0) {
|
|
530
|
+
(0, utils_1.emojiLog)("📜", `${isDryRun ? "[dryrun] " : ""}Writing files (${allWrittenFiles.length} total)...`);
|
|
531
|
+
// Sort files by relative path for consistent display
|
|
532
|
+
const sortedFiles = [...allWrittenFiles]
|
|
533
|
+
.map((file) => path.relative(pkgJsonDir, file))
|
|
534
|
+
.sort()
|
|
535
|
+
.map((relPath) => (relPath.startsWith(".") ? relPath : `./${relPath}`));
|
|
536
|
+
sortedFiles.forEach((file) => {
|
|
537
|
+
console.log(` ${file}`);
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
///////////////////////////////
|
|
541
|
+
/// generate exports ///
|
|
542
|
+
///////////////////////////////
|
|
543
|
+
// generate package.json exports
|
|
544
|
+
(0, utils_1.emojiLog)("📦", `${isDryRun ? "[dryrun] " : ""}Updating package.json#/exports...`);
|
|
545
|
+
// Generate exports based on zshy config
|
|
546
|
+
const newExports = {};
|
|
547
|
+
const sourceDialects = config.sourceDialects || [];
|
|
548
|
+
for (const [exportPath, sourcePath] of Object.entries(config.exports)) {
|
|
549
|
+
if (exportPath.includes("package.json")) {
|
|
550
|
+
newExports[exportPath] = sourcePath;
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
const absSourcePath = path.resolve(pkgJsonDir, sourcePath);
|
|
554
|
+
const relSourcePath = path.relative(rootDir, absSourcePath);
|
|
555
|
+
const absJsPath = path.resolve(outDir, relSourcePath);
|
|
556
|
+
const absDtsPath = path.resolve(declarationDir, relSourcePath);
|
|
557
|
+
const relJsPath = "./" + path.relative(pkgJsonDir, absJsPath);
|
|
558
|
+
const relDtsPath = "./" + path.relative(pkgJsonDir, absDtsPath);
|
|
559
|
+
if (typeof sourcePath === "string") {
|
|
560
|
+
if (sourcePath.endsWith("/*")) {
|
|
561
|
+
// Handle wildcard exports
|
|
562
|
+
newExports[exportPath] = {
|
|
563
|
+
types: relDtsPath,
|
|
564
|
+
import: relJsPath,
|
|
565
|
+
require: relJsPath,
|
|
566
|
+
};
|
|
567
|
+
for (const sd of sourceDialects) {
|
|
568
|
+
newExports[exportPath] = {
|
|
569
|
+
[sd]: sourcePath,
|
|
570
|
+
...newExports[exportPath],
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
else if (isSourceFile(sourcePath)) {
|
|
575
|
+
const esmPath = removeExtension(relJsPath) + (isTypeModule ? `.js` : `.mjs`);
|
|
576
|
+
const cjsPath = removeExtension(relJsPath) + (isTypeModule ? `.cjs` : `.js`);
|
|
577
|
+
const dtsPath = removeExtension(relDtsPath) + (isTypeModule ? `.d.cts` : `.d.ts`); // ./
|
|
578
|
+
newExports[exportPath] = {
|
|
579
|
+
types: dtsPath,
|
|
580
|
+
import: esmPath,
|
|
581
|
+
require: cjsPath,
|
|
582
|
+
};
|
|
583
|
+
if (exportPath === ".") {
|
|
584
|
+
pkgJson.main = cjsPath;
|
|
585
|
+
pkgJson.module = esmPath;
|
|
586
|
+
pkgJson.types = dtsPath;
|
|
587
|
+
}
|
|
588
|
+
for (const sd of sourceDialects) {
|
|
589
|
+
newExports[exportPath] = {
|
|
590
|
+
[sd]: sourcePath,
|
|
591
|
+
...newExports[exportPath],
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
(0, utils_1.emojiLog)("❌", `Invalid entrypoint: ${sourcePath}`, "error");
|
|
597
|
+
process.exit();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (isVerbose) {
|
|
602
|
+
(0, utils_1.emojiLog)("🔧", `Generated "exports": ${(0, utils_1.formatForLog)(newExports)}`);
|
|
603
|
+
}
|
|
604
|
+
///////////////////////////////
|
|
605
|
+
/// generate bin ///
|
|
606
|
+
///////////////////////////////
|
|
607
|
+
// Generate bin field based on zshy bin config
|
|
608
|
+
if (config.bin) {
|
|
609
|
+
(0, utils_1.emojiLog)("📦", `${isDryRun ? "[dryrun] " : ""}Updating package.json#/bin...`);
|
|
610
|
+
const newBin = {};
|
|
611
|
+
// Convert config.bin to object format for processing
|
|
612
|
+
const binEntries = typeof config.bin === "string" ? [[pkgJson.name, config.bin]] : Object.entries(config.bin);
|
|
613
|
+
for (const [binName, sourcePath] of binEntries) {
|
|
614
|
+
if (typeof sourcePath === "string" && isSourceFile(sourcePath)) {
|
|
615
|
+
const absSourcePath = path.resolve(pkgJsonDir, sourcePath);
|
|
616
|
+
const relSourcePath = path.relative(rootDir, absSourcePath);
|
|
617
|
+
const absJsPath = path.resolve(outDir, relSourcePath);
|
|
618
|
+
const relJsPath = "./" + path.relative(pkgJsonDir, absJsPath);
|
|
619
|
+
// Use CommonJS entrypoint for bin
|
|
620
|
+
const binPath = removeExtension(relJsPath) + (isTypeModule ? `.cjs` : `.js`);
|
|
621
|
+
newBin[binName] = binPath;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
// If original config.bin was a string, output as string
|
|
625
|
+
if (typeof config.bin === "string") {
|
|
626
|
+
pkgJson.bin = Object.values(newBin)[0];
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
// Output as object
|
|
630
|
+
pkgJson.bin = newBin;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (isVerbose) {
|
|
634
|
+
(0, utils_1.emojiLog)("🔧", `Generated "bin": ${(0, utils_1.formatForLog)(pkgJson.bin)}`);
|
|
635
|
+
}
|
|
636
|
+
///////////////////////////////
|
|
637
|
+
/// write pkg json ///
|
|
638
|
+
///////////////////////////////
|
|
639
|
+
// Update package.json with new exports
|
|
640
|
+
pkgJson.exports = newExports;
|
|
641
|
+
if (isDryRun) {
|
|
642
|
+
(0, utils_1.emojiLog)("📦", "[dryrun] Skipping package.json modification");
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
646
|
+
}
|
|
647
|
+
if (isAttw) {
|
|
648
|
+
// run `@arethetypeswrong/cli --pack .` to check types
|
|
649
|
+
(0, utils_1.emojiLog)("🔍", "Checking types with @arethetypeswrong/cli...");
|
|
650
|
+
const { execFile } = await Promise.resolve().then(() => __importStar(require("node:child_process")));
|
|
651
|
+
const { promisify } = await Promise.resolve().then(() => __importStar(require("node:util")));
|
|
652
|
+
const execFileAsync = promisify(execFile);
|
|
653
|
+
const [cmd, ...args] = `${pmExec} @arethetypeswrong/cli --pack ${pkgJsonDir}`.split(" ");
|
|
654
|
+
console.dir([cmd, ...args], { depth: null });
|
|
655
|
+
let stdout = "";
|
|
656
|
+
let stderr = "";
|
|
657
|
+
let exitCode = 0;
|
|
658
|
+
try {
|
|
659
|
+
const result = await execFileAsync(cmd, args, {
|
|
660
|
+
cwd: pkgJsonDir,
|
|
661
|
+
encoding: "utf-8",
|
|
662
|
+
});
|
|
663
|
+
stdout = result.stdout;
|
|
664
|
+
stderr = result.stderr;
|
|
665
|
+
}
|
|
666
|
+
catch (error) {
|
|
667
|
+
stdout = error.stdout || "";
|
|
668
|
+
stderr = error.stderr || "";
|
|
669
|
+
exitCode = error.code || 1;
|
|
670
|
+
}
|
|
671
|
+
const output = stdout || stderr;
|
|
672
|
+
if (output) {
|
|
673
|
+
const indentedOutput = output
|
|
674
|
+
.split("\n")
|
|
675
|
+
.map((line) => ` ${line}`)
|
|
676
|
+
.join("\n");
|
|
677
|
+
if (exitCode === 0) {
|
|
678
|
+
console.log(indentedOutput);
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
console.error(indentedOutput);
|
|
682
|
+
(0, utils_1.emojiLog)("⚠️", "ATTW found issues, but the build was not affected.", "warn");
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
(0, utils_1.emojiLog)("🎉", "Build complete! ✅");
|
|
687
|
+
}
|
|
688
|
+
catch (error) {
|
|
689
|
+
(0, utils_1.emojiLog)("❌", `Build failed: ${error}`, "error");
|
|
690
|
+
process.exit(1);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
// Run the script
|
|
694
|
+
main().catch((error) => {
|
|
695
|
+
(0, utils_1.emojiLog)("❌", `Script failed: ${error}`, "error");
|
|
696
|
+
process.exit(1);
|
|
697
|
+
});
|