zshy 0.4.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compile.cjs +8 -8
- package/dist/compile.cjs.map +1 -1
- package/dist/compile.d.cts.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +8 -8
- package/dist/compile.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.cjs +212 -120
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.cts.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +213 -121
- package/dist/main.js.map +1 -1
- package/dist/utils.cjs +40 -6
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +8 -1
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +37 -4
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -5,8 +5,9 @@ import glob from "fast-glob";
|
|
|
5
5
|
import { table } from "table";
|
|
6
6
|
import * as ts from "typescript";
|
|
7
7
|
import { compileProject } from "./compile.js";
|
|
8
|
-
import {
|
|
8
|
+
import { formatForLog, isSourceFile, isTestFile, log, readTsconfig, relativePosix, removeExtension, setSilent, toPosix, } from "./utils.js";
|
|
9
9
|
export async function main() {
|
|
10
|
+
log.prefix = "» ";
|
|
10
11
|
///////////////////////////////////
|
|
11
12
|
/// parse command line args ///
|
|
12
13
|
///////////////////////////////////
|
|
@@ -16,6 +17,7 @@ export async function main() {
|
|
|
16
17
|
args = parseArgs({
|
|
17
18
|
"--help": Boolean,
|
|
18
19
|
"--verbose": Boolean,
|
|
20
|
+
"--silent": Boolean,
|
|
19
21
|
"--project": String,
|
|
20
22
|
"--dry-run": Boolean,
|
|
21
23
|
"--fail-threshold": String,
|
|
@@ -27,7 +29,7 @@ export async function main() {
|
|
|
27
29
|
}
|
|
28
30
|
catch (error) {
|
|
29
31
|
if (error instanceof Error) {
|
|
30
|
-
|
|
32
|
+
log.error(`❌ ${error.message}`);
|
|
31
33
|
}
|
|
32
34
|
console.error(`Use --help for usage information`);
|
|
33
35
|
process.exit(1);
|
|
@@ -41,6 +43,7 @@ Options:
|
|
|
41
43
|
-h, --help Show this help message
|
|
42
44
|
-p, --project <path> Path to tsconfig.json file
|
|
43
45
|
--verbose Enable verbose output
|
|
46
|
+
--silent Suppress all output
|
|
44
47
|
--dry-run Don't write any files, just log what would be done
|
|
45
48
|
--fail-threshold <threshold> When to exit with non-zero error code
|
|
46
49
|
"error" (default)
|
|
@@ -51,6 +54,7 @@ Examples:
|
|
|
51
54
|
zshy # Run build
|
|
52
55
|
zshy --project ./tsconfig.build.json # Use specific tsconfig file (defaults to tsconfig.json)
|
|
53
56
|
zshy --verbose # Enable verbose logging
|
|
57
|
+
zshy --silent # Suppress all output
|
|
54
58
|
zshy --dry-run # Preview changes without writing files
|
|
55
59
|
`);
|
|
56
60
|
process.exit(0);
|
|
@@ -66,37 +70,50 @@ Examples:
|
|
|
66
70
|
else {
|
|
67
71
|
pmExec = "npx";
|
|
68
72
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
// Validate that --verbose and --silent are not both passed
|
|
74
|
+
if (args["--verbose"] && args["--silent"]) {
|
|
75
|
+
log.error("❌ Cannot use both --verbose and --silent flags together");
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
// Set silent mode if --silent flag is passed
|
|
79
|
+
const isSilent = !!args["--silent"];
|
|
73
80
|
const isVerbose = !!args["--verbose"];
|
|
81
|
+
setSilent(isSilent);
|
|
82
|
+
if (!isSilent) {
|
|
83
|
+
const originalPrefix = log.prefix;
|
|
84
|
+
log.prefix = undefined;
|
|
85
|
+
log.info(` ╔═══════════════════════════════════════════════╗`);
|
|
86
|
+
log.info(` ║ zshy » the bundler-free TypeScript build tool ║`);
|
|
87
|
+
log.info(` ╚═══════════════════════════════════════════════╝`);
|
|
88
|
+
log.prefix = originalPrefix;
|
|
89
|
+
log.info("Starting build...");
|
|
90
|
+
}
|
|
74
91
|
const isDryRun = !!args["--dry-run"];
|
|
75
92
|
const failThreshold = args["--fail-threshold"] || "error"; // Default to 'error'
|
|
76
93
|
const isCjsInterop = true; // Enable CJS interop for testing
|
|
77
94
|
// Validate that the threshold value is one of the allowed values
|
|
78
95
|
if (failThreshold !== "never" && failThreshold !== "warn" && failThreshold !== "error") {
|
|
79
|
-
|
|
96
|
+
log.error(`❌ Invalid value for --fail-threshold: "${failThreshold}". Valid values are "never", "warn", or "error"`);
|
|
80
97
|
process.exit(1);
|
|
81
98
|
}
|
|
82
99
|
const isAttw = false; // args["--attw"];
|
|
83
100
|
if (isVerbose) {
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
log.info("Verbose mode enabled");
|
|
102
|
+
log.info(`Detected package manager: ${pmExec}`);
|
|
86
103
|
}
|
|
87
104
|
if (isDryRun) {
|
|
88
|
-
|
|
105
|
+
log.info("Dry run mode enabled. No files will be written or modified.");
|
|
89
106
|
}
|
|
90
107
|
// Display message about fail threshold setting
|
|
91
108
|
if (isVerbose) {
|
|
92
109
|
if (failThreshold === "never") {
|
|
93
|
-
|
|
110
|
+
log.info("Build will always succeed regardless of errors or warnings");
|
|
94
111
|
}
|
|
95
112
|
else if (failThreshold === "warn") {
|
|
96
|
-
|
|
113
|
+
log.warn("Build will fail on warnings or errors");
|
|
97
114
|
}
|
|
98
115
|
else {
|
|
99
|
-
|
|
116
|
+
log.info("Build will fail only on errors (default)");
|
|
100
117
|
}
|
|
101
118
|
}
|
|
102
119
|
///////////////////////////////////
|
|
@@ -114,7 +131,7 @@ Examples:
|
|
|
114
131
|
currentDir = path.dirname(currentDir);
|
|
115
132
|
}
|
|
116
133
|
if (!fs.existsSync(packageJsonPath)) {
|
|
117
|
-
|
|
134
|
+
log.error("❌ package.json not found in current directory or any parent directories");
|
|
118
135
|
process.exit(1);
|
|
119
136
|
}
|
|
120
137
|
// read package.json and extract the "zshy" exports config
|
|
@@ -133,8 +150,10 @@ Examples:
|
|
|
133
150
|
const pkgJsonDir = path.dirname(packageJsonPath);
|
|
134
151
|
const pkgJsonRelPath = relativePosix(pkgJsonDir, packageJsonPath);
|
|
135
152
|
// print project root
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
if (!isSilent) {
|
|
154
|
+
log.info(`Detected project root: ${pkgJsonDir}`);
|
|
155
|
+
log.info(`Reading package.json from ./${pkgJsonRelPath}`);
|
|
156
|
+
}
|
|
138
157
|
/////////////////////////////////
|
|
139
158
|
/// parse zshy config ///
|
|
140
159
|
/////////////////////////////////
|
|
@@ -142,7 +161,7 @@ Examples:
|
|
|
142
161
|
const CONFIG_KEY = "zshy";
|
|
143
162
|
let rawConfig;
|
|
144
163
|
if (!pkgJson[CONFIG_KEY]) {
|
|
145
|
-
|
|
164
|
+
log.error(`❌ No "${CONFIG_KEY}" key found in package.json`);
|
|
146
165
|
process.exit(1);
|
|
147
166
|
}
|
|
148
167
|
if (typeof pkgJson[CONFIG_KEY] === "string") {
|
|
@@ -156,11 +175,11 @@ Examples:
|
|
|
156
175
|
rawConfig.exports = { ".": rawConfig.exports };
|
|
157
176
|
}
|
|
158
177
|
else if (typeof rawConfig.exports === "undefined") {
|
|
159
|
-
|
|
178
|
+
log.error(`❌ Missing "exports" key in package.json#/${CONFIG_KEY}`);
|
|
160
179
|
process.exit(1);
|
|
161
180
|
}
|
|
162
181
|
else if (typeof rawConfig.exports !== "object") {
|
|
163
|
-
|
|
182
|
+
log.error(`❌ Invalid "exports" key in package.json#/${CONFIG_KEY}`);
|
|
164
183
|
process.exit(1);
|
|
165
184
|
}
|
|
166
185
|
// Validate bin field if present
|
|
@@ -172,7 +191,7 @@ Examples:
|
|
|
172
191
|
// Object format is valid
|
|
173
192
|
}
|
|
174
193
|
else {
|
|
175
|
-
|
|
194
|
+
log.error(`❌ Invalid "bin" key in package.json#/${CONFIG_KEY}, expected string or object`);
|
|
176
195
|
process.exit(1);
|
|
177
196
|
}
|
|
178
197
|
}
|
|
@@ -182,31 +201,31 @@ Examples:
|
|
|
182
201
|
// const { import: importCondition, require: requireCondition, ...rest } = config.conditions;
|
|
183
202
|
for (const [condition, value] of Object.entries(rawConfig.conditions)) {
|
|
184
203
|
if (value !== "esm" && value !== "cjs" && value !== "src") {
|
|
185
|
-
|
|
204
|
+
log.error(`❌ Invalid condition value "${value}" for "${condition}" in package.json#/${CONFIG_KEY}/conditions. Valid values are "esm", "cjs", "src", or null`);
|
|
186
205
|
process.exit(1);
|
|
187
206
|
}
|
|
188
207
|
}
|
|
189
208
|
}
|
|
190
209
|
else {
|
|
191
|
-
|
|
210
|
+
log.error(`❌ Invalid "conditions" key in package.json#/${CONFIG_KEY}, expected object`);
|
|
192
211
|
process.exit(1);
|
|
193
212
|
}
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
215
|
else if (typeof pkgJson[CONFIG_KEY] === "undefined") {
|
|
197
|
-
|
|
216
|
+
log.error(`❌ Missing "${CONFIG_KEY}" key in package.json`);
|
|
198
217
|
process.exit(1);
|
|
199
218
|
}
|
|
200
219
|
else {
|
|
201
|
-
|
|
220
|
+
log.error(`❌ Invalid "${CONFIG_KEY}" key in package.json, expected string or object`);
|
|
202
221
|
process.exit(1);
|
|
203
222
|
}
|
|
204
223
|
if (isVerbose) {
|
|
205
|
-
|
|
224
|
+
log.info(`Parsed zshy config: ${formatForLog(rawConfig)}`);
|
|
206
225
|
}
|
|
207
226
|
// Check for deprecated sourceDialects
|
|
208
227
|
if ("sourceDialects" in rawConfig) {
|
|
209
|
-
|
|
228
|
+
log.error('❌ The "sourceDialects" option is no longer supported. Use "conditions" instead to configure custom export conditions.');
|
|
210
229
|
process.exit(1);
|
|
211
230
|
}
|
|
212
231
|
const config = { ...rawConfig };
|
|
@@ -220,13 +239,13 @@ Examples:
|
|
|
220
239
|
const cjsConditions = Object.entries(config.conditions).filter(([_, value]) => value === "cjs");
|
|
221
240
|
if (cjsConditions.length > 0) {
|
|
222
241
|
const conditionNames = cjsConditions.map(([name]) => name).join(", ");
|
|
223
|
-
|
|
242
|
+
log.error(`❌ CJS is disabled (cjs: false) but the following conditions are set to "cjs": ${conditionNames}. Either enable CJS or change these conditions.`);
|
|
224
243
|
process.exit(1);
|
|
225
244
|
}
|
|
226
245
|
}
|
|
227
246
|
// Validate that if cjs is disabled, package.json type must be "module"
|
|
228
247
|
if (config.cjs === false && pkgJson.type !== "module") {
|
|
229
|
-
|
|
248
|
+
log.error(`❌ CJS is disabled (cjs: false) but package.json#/type is not set to "module". When disabling CommonJS builds, you must set "type": "module" in your package.json.`);
|
|
230
249
|
process.exit(1);
|
|
231
250
|
}
|
|
232
251
|
///////////////////////////
|
|
@@ -239,7 +258,7 @@ Examples:
|
|
|
239
258
|
const resolvedProjectPath = path.resolve(process.cwd(), args["--project"]);
|
|
240
259
|
if (fs.existsSync(resolvedProjectPath)) {
|
|
241
260
|
if (fs.statSync(resolvedProjectPath).isDirectory()) {
|
|
242
|
-
|
|
261
|
+
log.error(`--project must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`);
|
|
243
262
|
process.exit(1);
|
|
244
263
|
}
|
|
245
264
|
else {
|
|
@@ -248,7 +267,7 @@ Examples:
|
|
|
248
267
|
}
|
|
249
268
|
}
|
|
250
269
|
else {
|
|
251
|
-
|
|
270
|
+
log.error(`tsconfig.json file not found: ${resolvedProjectPath}`);
|
|
252
271
|
process.exit(1);
|
|
253
272
|
}
|
|
254
273
|
}
|
|
@@ -257,7 +276,7 @@ Examples:
|
|
|
257
276
|
const resolvedProjectPath = path.resolve(pkgJsonDir, config.tsconfig);
|
|
258
277
|
if (fs.existsSync(resolvedProjectPath)) {
|
|
259
278
|
if (fs.statSync(resolvedProjectPath).isDirectory()) {
|
|
260
|
-
|
|
279
|
+
log.error(`zshy.tsconfig must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`);
|
|
261
280
|
process.exit(1);
|
|
262
281
|
}
|
|
263
282
|
else {
|
|
@@ -266,7 +285,7 @@ Examples:
|
|
|
266
285
|
}
|
|
267
286
|
}
|
|
268
287
|
else {
|
|
269
|
-
|
|
288
|
+
log.error(`Tsconfig file not found: ${resolvedProjectPath}`);
|
|
270
289
|
process.exit(1);
|
|
271
290
|
}
|
|
272
291
|
}
|
|
@@ -277,10 +296,12 @@ Examples:
|
|
|
277
296
|
const _parsedConfig = readTsconfig(tsconfigPath);
|
|
278
297
|
if (!fs.existsSync(tsconfigPath)) {
|
|
279
298
|
// Check if tsconfig.json exists
|
|
280
|
-
|
|
299
|
+
log.error(`❌ tsconfig.json not found at ${toPosix(path.resolve(tsconfigPath))}`);
|
|
281
300
|
process.exit(1);
|
|
282
301
|
}
|
|
283
|
-
|
|
302
|
+
if (!isSilent) {
|
|
303
|
+
log.info(`Reading tsconfig from ./${relativePosix(pkgJsonDir, tsconfigPath)}`);
|
|
304
|
+
}
|
|
284
305
|
// if (_parsedConfig.rootDir) {
|
|
285
306
|
// console.error(
|
|
286
307
|
// `❌ rootDir is determined from your set of entrypoints; you can remove it from your tsconfig.json.`,
|
|
@@ -314,17 +335,17 @@ Examples:
|
|
|
314
335
|
};
|
|
315
336
|
if (relOutDir === "") {
|
|
316
337
|
if (!pkgJson.files) {
|
|
317
|
-
|
|
338
|
+
log.info('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.');
|
|
318
339
|
pkgJson.files = ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"];
|
|
319
340
|
}
|
|
320
341
|
else {
|
|
321
|
-
|
|
322
|
-
Ensure that your "files" in package.json
|
|
342
|
+
log.info(`You\'re building your code to the project root. This means your compiled files will be generated alongside your source files.
|
|
343
|
+
Ensure that your "files" in package.json does not include TypeScript source files, or your users may experience .d.ts resolution issues in some environments:
|
|
323
344
|
"files": ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"]`);
|
|
324
345
|
}
|
|
325
346
|
}
|
|
326
347
|
else if (!pkgJson.files) {
|
|
327
|
-
|
|
348
|
+
log.warn(`The "files" key is missing in package.json. Setting to "${relOutDir}".`);
|
|
328
349
|
pkgJson.files = [relOutDir];
|
|
329
350
|
if (relOutDir !== relDeclarationDir) {
|
|
330
351
|
pkgJson.files.push(relDeclarationDir);
|
|
@@ -334,7 +355,9 @@ Examples:
|
|
|
334
355
|
/// extract entry points ///
|
|
335
356
|
/////////////////////////////////
|
|
336
357
|
// Extract entry points from zshy exports config
|
|
337
|
-
|
|
358
|
+
if (!isSilent) {
|
|
359
|
+
log.info("Determining entrypoints...");
|
|
360
|
+
}
|
|
338
361
|
const entryPoints = [];
|
|
339
362
|
const assetEntrypoints = [];
|
|
340
363
|
const rows = [["Subpath", "Entrypoint"]];
|
|
@@ -349,13 +372,13 @@ Examples:
|
|
|
349
372
|
cleanExportPath = pkgJson.name + "/" + exportPath.slice(2);
|
|
350
373
|
}
|
|
351
374
|
else {
|
|
352
|
-
|
|
375
|
+
log.warn(`Invalid subpath export "${exportPath}" — should start with "./"`);
|
|
353
376
|
process.exit(1);
|
|
354
377
|
}
|
|
355
378
|
if (typeof sourcePath === "string") {
|
|
356
379
|
if (sourcePath.includes("*")) {
|
|
357
380
|
if (!sourcePath.endsWith("/*") && !sourcePath.endsWith("/**/*")) {
|
|
358
|
-
|
|
381
|
+
log.error(`❌ Wildcard paths should end with /* or /**/* (for deep globs): ${sourcePath}`);
|
|
359
382
|
process.exit(1);
|
|
360
383
|
}
|
|
361
384
|
let pattern;
|
|
@@ -368,16 +391,23 @@ Examples:
|
|
|
368
391
|
pattern = sourcePath.slice(0, -2) + "/*.{ts,tsx,mts,cts}";
|
|
369
392
|
}
|
|
370
393
|
if (isVerbose) {
|
|
371
|
-
|
|
394
|
+
log.info(`Matching glob: ${pattern}`);
|
|
372
395
|
}
|
|
373
396
|
const wildcardFiles = await glob(pattern, {
|
|
374
397
|
ignore: ["**/*.d.ts", "**/*.d.mts", "**/*.d.cts"],
|
|
375
398
|
cwd: pkgJsonDir,
|
|
376
399
|
});
|
|
377
|
-
|
|
378
|
-
|
|
400
|
+
// Filter out test files (__tests__ directories, .test.*, .spec.*)
|
|
401
|
+
const filteredFiles = wildcardFiles.filter((file) => !isTestFile(file));
|
|
402
|
+
entryPoints.push(...filteredFiles);
|
|
403
|
+
rows.push([`"${cleanExportPath}"`, `${sourcePath} (${filteredFiles.length} matches)`]);
|
|
379
404
|
}
|
|
380
405
|
else if (isSourceFile(sourcePath)) {
|
|
406
|
+
// Skip test files even if explicitly specified
|
|
407
|
+
if (isTestFile(sourcePath)) {
|
|
408
|
+
log.warn(`Skipping test file: ${sourcePath}`);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
381
411
|
entryPoints.push(sourcePath);
|
|
382
412
|
rows.push([`"${cleanExportPath}"`, sourcePath]);
|
|
383
413
|
}
|
|
@@ -393,32 +423,47 @@ Examples:
|
|
|
393
423
|
if (typeof config.bin === "string") {
|
|
394
424
|
// Single bin entry
|
|
395
425
|
if (isSourceFile(config.bin)) {
|
|
396
|
-
|
|
397
|
-
|
|
426
|
+
if (isTestFile(config.bin)) {
|
|
427
|
+
log.warn(`Skipping test file in bin: ${config.bin}`);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
entryPoints.push(config.bin);
|
|
431
|
+
rows.push([`bin:${pkgJson.name}`, config.bin]);
|
|
432
|
+
}
|
|
398
433
|
}
|
|
399
434
|
}
|
|
400
435
|
else {
|
|
401
436
|
// Multiple bin entries
|
|
402
437
|
for (const [binName, sourcePath] of Object.entries(config.bin)) {
|
|
403
438
|
if (typeof sourcePath === "string" && isSourceFile(sourcePath)) {
|
|
404
|
-
|
|
405
|
-
|
|
439
|
+
if (isTestFile(sourcePath)) {
|
|
440
|
+
log.warn(`Skipping test file in bin: ${sourcePath}`);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
entryPoints.push(sourcePath);
|
|
444
|
+
rows.push([`bin:${binName}`, sourcePath]);
|
|
445
|
+
}
|
|
406
446
|
}
|
|
407
447
|
}
|
|
408
448
|
}
|
|
409
449
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
lineIndex ===
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
450
|
+
if (!isSilent) {
|
|
451
|
+
const originalPrefix = log.prefix;
|
|
452
|
+
log.prefix = undefined;
|
|
453
|
+
log.info(" " +
|
|
454
|
+
table(rows, {
|
|
455
|
+
drawHorizontalLine: (lineIndex, rowCount) => {
|
|
456
|
+
return (lineIndex === 0 ||
|
|
457
|
+
lineIndex === 1 ||
|
|
458
|
+
// lineIndex === rowCount - 1 ||
|
|
459
|
+
lineIndex === rowCount);
|
|
460
|
+
},
|
|
461
|
+
})
|
|
462
|
+
.split("\n")
|
|
463
|
+
.join("\n ")
|
|
464
|
+
.trim());
|
|
465
|
+
log.prefix = originalPrefix;
|
|
466
|
+
}
|
|
422
467
|
// disallow .mts and .cts files
|
|
423
468
|
// if (entryPoints.some((ep) => ep.endsWith(".mts") || ep.endsWith(".cts"))) {
|
|
424
469
|
// emojiLog(
|
|
@@ -429,7 +474,7 @@ Examples:
|
|
|
429
474
|
// process.exit(1);
|
|
430
475
|
// }
|
|
431
476
|
if (entryPoints.length === 0) {
|
|
432
|
-
|
|
477
|
+
log.error("❌ No entry points found matching the specified patterns in package.json#/zshy exports or bin");
|
|
433
478
|
process.exit(1);
|
|
434
479
|
}
|
|
435
480
|
///////////////////////////////
|
|
@@ -462,49 +507,62 @@ Examples:
|
|
|
462
507
|
//////////////////////////////////
|
|
463
508
|
/// display resolved paths ///
|
|
464
509
|
//////////////////////////////////
|
|
465
|
-
|
|
510
|
+
if (!isSilent) {
|
|
511
|
+
log.info("Resolved build paths:");
|
|
512
|
+
}
|
|
466
513
|
const pathRows = [["Location", "Resolved path"]];
|
|
467
514
|
pathRows.push(["rootDir", relRootDir ? `./${relRootDir}` : "."]);
|
|
468
515
|
pathRows.push(["outDir", relOutDir ? `./${relOutDir}` : "."]);
|
|
469
516
|
if (relDeclarationDir !== relOutDir) {
|
|
470
517
|
pathRows.push(["declarationDir", relDeclarationDir ? `./${relDeclarationDir}` : "."]);
|
|
471
518
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
lineIndex ===
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
519
|
+
if (!isSilent) {
|
|
520
|
+
const originalPrefix = log.prefix;
|
|
521
|
+
log.prefix = undefined;
|
|
522
|
+
log.info(" " +
|
|
523
|
+
table(pathRows, {
|
|
524
|
+
drawHorizontalLine: (lineIndex, rowCount) => {
|
|
525
|
+
return (lineIndex === 0 ||
|
|
526
|
+
lineIndex === 1 ||
|
|
527
|
+
// lineIndex === rowCount - 1 ||
|
|
528
|
+
lineIndex === rowCount);
|
|
529
|
+
},
|
|
530
|
+
})
|
|
531
|
+
.split("\n")
|
|
532
|
+
.join("\n ")
|
|
533
|
+
.trim());
|
|
534
|
+
log.prefix = originalPrefix;
|
|
487
535
|
}
|
|
488
|
-
|
|
489
|
-
|
|
536
|
+
const isTypeModule = pkgJson.type === "module";
|
|
537
|
+
if (!isSilent) {
|
|
538
|
+
if (isTypeModule) {
|
|
539
|
+
log.info(`Package is an ES module (package.json#/type is "module")`);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
log.info(`Package is a CommonJS module (${pkgJson.type === "commonjs" ? 'package.json#/type is "commonjs"' : 'package.json#/type not set to "module"'})`);
|
|
543
|
+
}
|
|
490
544
|
}
|
|
491
545
|
//////////////////////////////////////////////
|
|
492
546
|
/// clean up outDir and declarationDir ///
|
|
493
547
|
//////////////////////////////////////////////
|
|
494
548
|
const prefix = isDryRun ? "[dryrun] " : "";
|
|
495
549
|
if (relRootDir.startsWith(relOutDir)) {
|
|
496
|
-
|
|
550
|
+
if (!isSilent) {
|
|
551
|
+
log.info(`${prefix}Skipping cleanup of outDir as it contains source files`);
|
|
552
|
+
}
|
|
497
553
|
}
|
|
498
554
|
else {
|
|
499
555
|
// source files are in the outDir, so skip cleanup
|
|
500
556
|
// clean up outDir and declarationDir
|
|
501
|
-
|
|
557
|
+
if (!isSilent) {
|
|
558
|
+
log.info(`${prefix}Cleaning up outDir...`);
|
|
559
|
+
}
|
|
502
560
|
if (!isDryRun) {
|
|
503
561
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
504
562
|
// // print success message in verbose mode
|
|
505
563
|
if (isVerbose) {
|
|
506
564
|
if (fs.existsSync(outDir)) {
|
|
507
|
-
|
|
565
|
+
log.error(`❌ Failed to clean up outDir: ${relOutDir}. Directory still exists.`);
|
|
508
566
|
}
|
|
509
567
|
}
|
|
510
568
|
}
|
|
@@ -513,16 +571,20 @@ Examples:
|
|
|
513
571
|
// already done
|
|
514
572
|
}
|
|
515
573
|
else if (relRootDir.startsWith(relDeclarationDir)) {
|
|
516
|
-
|
|
574
|
+
if (!isSilent) {
|
|
575
|
+
log.info(`${prefix}Skipping cleanup of declarationDir as it contains source files`);
|
|
576
|
+
}
|
|
517
577
|
}
|
|
518
578
|
else {
|
|
519
|
-
|
|
579
|
+
if (!isSilent) {
|
|
580
|
+
log.info(`${prefix}Cleaning up declarationDir...`);
|
|
581
|
+
}
|
|
520
582
|
if (!isDryRun) {
|
|
521
583
|
fs.rmSync(declarationDir, { recursive: true, force: true });
|
|
522
584
|
// // print success message in verbose mode
|
|
523
585
|
if (isVerbose) {
|
|
524
586
|
if (fs.existsSync(declarationDir)) {
|
|
525
|
-
|
|
587
|
+
log.error(`❌ Failed to clean up declarationDir: ${relDeclarationDir}. Directory still exists.`);
|
|
526
588
|
}
|
|
527
589
|
}
|
|
528
590
|
}
|
|
@@ -533,8 +595,8 @@ Examples:
|
|
|
533
595
|
const uniqueEntryPoints = [...new Set(entryPoints)];
|
|
534
596
|
// try {
|
|
535
597
|
if (isVerbose) {
|
|
536
|
-
|
|
537
|
-
|
|
598
|
+
log.info(`Resolved entrypoints: ${formatForLog(uniqueEntryPoints)}`);
|
|
599
|
+
log.info(`Resolved compilerOptions: ${formatForLog({
|
|
538
600
|
...tsconfigJson,
|
|
539
601
|
module: ts.ModuleKind[tsconfigJson.module],
|
|
540
602
|
moduleResolution: ts.ModuleResolutionKind[tsconfigJson.moduleResolution],
|
|
@@ -552,7 +614,9 @@ Examples:
|
|
|
552
614
|
const skipCjs = config.cjs === false;
|
|
553
615
|
// CJS
|
|
554
616
|
if (!skipCjs) {
|
|
555
|
-
|
|
617
|
+
if (!isSilent) {
|
|
618
|
+
log.info(`Building CJS...${isTypeModule ? ` (rewriting .ts -> .cjs/.d.cts)` : ``}`);
|
|
619
|
+
}
|
|
556
620
|
await compileProject({
|
|
557
621
|
configPath: tsconfigPath,
|
|
558
622
|
ext: isTypeModule ? "cjs" : "js",
|
|
@@ -571,10 +635,14 @@ Examples:
|
|
|
571
635
|
}, uniqueEntryPoints, buildContext);
|
|
572
636
|
}
|
|
573
637
|
else {
|
|
574
|
-
|
|
638
|
+
if (!isSilent) {
|
|
639
|
+
log.info("Skipping CJS build (cjs: false)");
|
|
640
|
+
}
|
|
575
641
|
}
|
|
576
642
|
// ESM
|
|
577
|
-
|
|
643
|
+
if (!isSilent) {
|
|
644
|
+
log.info(`Building ESM...${isTypeModule ? `` : ` (rewriting .ts -> .mjs/.d.mts)`}`);
|
|
645
|
+
}
|
|
578
646
|
await compileProject({
|
|
579
647
|
configPath: tsconfigPath,
|
|
580
648
|
ext: isTypeModule ? "js" : "mjs",
|
|
@@ -596,14 +664,16 @@ Examples:
|
|
|
596
664
|
///////////////////////////////////
|
|
597
665
|
// Copy asset entrypoints to output directory
|
|
598
666
|
if (assetEntrypoints.length > 0) {
|
|
599
|
-
|
|
667
|
+
if (!isSilent) {
|
|
668
|
+
log.info(`${prefix}Copying ${assetEntrypoints.length} asset${assetEntrypoints.length === 1 ? "" : "s"}...`);
|
|
669
|
+
}
|
|
600
670
|
for (const { sourcePath } of assetEntrypoints) {
|
|
601
671
|
const sourceFile = path.resolve(pkgJsonDir, sourcePath);
|
|
602
672
|
const relativePath = path.relative(rootDir, path.resolve(pkgJsonDir, sourcePath));
|
|
603
673
|
const destFile = path.resolve(outDir, relativePath);
|
|
604
674
|
const destDir = path.dirname(destFile);
|
|
605
675
|
if (!fs.existsSync(sourceFile)) {
|
|
606
|
-
|
|
676
|
+
log.warn(`Asset not found: ${sourcePath}`);
|
|
607
677
|
continue;
|
|
608
678
|
}
|
|
609
679
|
if (!isDryRun) {
|
|
@@ -615,7 +685,7 @@ Examples:
|
|
|
615
685
|
if (isVerbose) {
|
|
616
686
|
const relativeSource = toPosix(path.relative(pkgJsonDir, sourceFile));
|
|
617
687
|
const relativeDest = toPosix(path.relative(pkgJsonDir, destFile));
|
|
618
|
-
|
|
688
|
+
log.info(`${isDryRun ? "[dryrun] " : ""}Copied asset: ./${relativeSource} → ./${relativeDest}`);
|
|
619
689
|
}
|
|
620
690
|
}
|
|
621
691
|
}
|
|
@@ -624,26 +694,34 @@ Examples:
|
|
|
624
694
|
///////////////////////////////////
|
|
625
695
|
// Display files that were written or would be written (only in verbose mode)
|
|
626
696
|
if (isVerbose && buildContext.writtenFiles.size > 0) {
|
|
627
|
-
|
|
697
|
+
log.info(`${prefix}Writing files (${buildContext.writtenFiles.size} total)...`);
|
|
628
698
|
// Sort files by relative path for consistent display
|
|
629
699
|
const sortedFiles = [...buildContext.writtenFiles]
|
|
630
700
|
.map((file) => relativePosix(pkgJsonDir, file))
|
|
631
701
|
.sort()
|
|
632
702
|
.map((relPath) => (relPath.startsWith(".") ? relPath : `./${relPath}`));
|
|
703
|
+
// Temporarily disable prefix for individual file listings
|
|
704
|
+
const originalPrefix = log.prefix;
|
|
705
|
+
log.prefix = undefined;
|
|
633
706
|
sortedFiles.forEach((file) => {
|
|
634
|
-
|
|
707
|
+
log.info(` ${file}`);
|
|
635
708
|
});
|
|
709
|
+
log.prefix = originalPrefix;
|
|
636
710
|
}
|
|
637
711
|
///////////////////////////////
|
|
638
712
|
/// generate exports ///
|
|
639
713
|
///////////////////////////////
|
|
640
714
|
// generate package.json exports
|
|
641
715
|
if (config.noEdit) {
|
|
642
|
-
|
|
716
|
+
if (!isSilent) {
|
|
717
|
+
log.info("[noedit] Skipping modification of package.json");
|
|
718
|
+
}
|
|
643
719
|
}
|
|
644
720
|
else {
|
|
645
721
|
// Generate exports based on zshy config
|
|
646
|
-
|
|
722
|
+
if (!isSilent) {
|
|
723
|
+
log.info(`${prefix}Updating package.json...`);
|
|
724
|
+
}
|
|
647
725
|
const newExports = {};
|
|
648
726
|
if (config.exports) {
|
|
649
727
|
for (const [exportPath, sourcePath] of Object.entries(config.exports)) {
|
|
@@ -662,7 +740,7 @@ Examples:
|
|
|
662
740
|
// Handle wildcard exports
|
|
663
741
|
const finalExportPath = exportPath;
|
|
664
742
|
if (finalExportPath.includes("**")) {
|
|
665
|
-
|
|
743
|
+
log.error(`❌ Export keys cannot contain "**": ${finalExportPath}`);
|
|
666
744
|
process.exit(1);
|
|
667
745
|
}
|
|
668
746
|
// Convert deep glob patterns to simple wildcard patterns in the final export
|
|
@@ -693,8 +771,13 @@ Examples:
|
|
|
693
771
|
}
|
|
694
772
|
// Add standard conditions
|
|
695
773
|
exportObj.types = relDtsPath;
|
|
696
|
-
|
|
697
|
-
|
|
774
|
+
if (skipCjs) {
|
|
775
|
+
// ESM-only: use default condition instead of import
|
|
776
|
+
exportObj.default = relJsPath;
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
// Dual CJS/ESM: use import and require
|
|
780
|
+
exportObj.import = relJsPath;
|
|
698
781
|
exportObj.require = relJsPath;
|
|
699
782
|
}
|
|
700
783
|
newExports[finalExportPath] = exportObj;
|
|
@@ -723,8 +806,13 @@ Examples:
|
|
|
723
806
|
}
|
|
724
807
|
// Add standard conditions
|
|
725
808
|
exportObj.types = dtsPath;
|
|
726
|
-
|
|
727
|
-
|
|
809
|
+
if (skipCjs) {
|
|
810
|
+
// ESM-only: use default condition instead of import
|
|
811
|
+
exportObj.default = esmPath;
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
// Dual CJS/ESM: use import and require
|
|
815
|
+
exportObj.import = esmPath;
|
|
728
816
|
exportObj.require = cjsPath;
|
|
729
817
|
}
|
|
730
818
|
newExports[exportPath] = exportObj;
|
|
@@ -740,9 +828,9 @@ Examples:
|
|
|
740
828
|
pkgJson.types = dtsPath;
|
|
741
829
|
}
|
|
742
830
|
if (isVerbose) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
831
|
+
log.info(`Setting "main": ${formatForLog(cjsPath)}`);
|
|
832
|
+
log.info(`Setting "module": ${formatForLog(esmPath)}`);
|
|
833
|
+
log.info(`Setting "types": ${formatForLog(dtsPath)}`);
|
|
746
834
|
}
|
|
747
835
|
}
|
|
748
836
|
}
|
|
@@ -772,15 +860,15 @@ Examples:
|
|
|
772
860
|
pkgJson.types = relAssetPath;
|
|
773
861
|
}
|
|
774
862
|
if (isVerbose) {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
863
|
+
log.info(`Setting "main": ${formatForLog(relAssetPath)}`);
|
|
864
|
+
log.info(`Setting "module": ${formatForLog(relAssetPath)}`);
|
|
865
|
+
log.info(`Setting "types": ${formatForLog(relAssetPath)}`);
|
|
778
866
|
}
|
|
779
867
|
}
|
|
780
868
|
}
|
|
781
869
|
pkgJson.exports = newExports;
|
|
782
870
|
if (isVerbose) {
|
|
783
|
-
|
|
871
|
+
log.info(`Setting "exports": ${formatForLog(newExports)}`);
|
|
784
872
|
}
|
|
785
873
|
}
|
|
786
874
|
///////////////////////////////
|
|
@@ -812,14 +900,14 @@ Examples:
|
|
|
812
900
|
pkgJson.bin = newBin;
|
|
813
901
|
}
|
|
814
902
|
if (isVerbose) {
|
|
815
|
-
|
|
903
|
+
log.info(`Setting "bin": ${formatForLog(pkgJson.bin)}`);
|
|
816
904
|
}
|
|
817
905
|
}
|
|
818
906
|
if (isDryRun) {
|
|
819
907
|
///////////////////////////////
|
|
820
908
|
/// write pkg json ///
|
|
821
909
|
///////////////////////////////
|
|
822
|
-
|
|
910
|
+
log.info("[dryrun] Skipping package.json modification");
|
|
823
911
|
}
|
|
824
912
|
else {
|
|
825
913
|
fs.writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, indent) + "\n");
|
|
@@ -827,7 +915,9 @@ Examples:
|
|
|
827
915
|
}
|
|
828
916
|
if (isAttw) {
|
|
829
917
|
// run `@arethetypeswrong/cli --pack .` to check types
|
|
830
|
-
|
|
918
|
+
if (!isSilent) {
|
|
919
|
+
log.info("Checking types with @arethetypeswrong/cli...");
|
|
920
|
+
}
|
|
831
921
|
const { execFile } = await import("node:child_process");
|
|
832
922
|
const { promisify } = await import("node:util");
|
|
833
923
|
const execFileAsync = promisify(execFile);
|
|
@@ -856,39 +946,41 @@ Examples:
|
|
|
856
946
|
.map((line) => ` ${line}`)
|
|
857
947
|
.join("\n");
|
|
858
948
|
if (exitCode === 0) {
|
|
859
|
-
|
|
949
|
+
log.info(indentedOutput);
|
|
860
950
|
}
|
|
861
951
|
else {
|
|
862
|
-
|
|
863
|
-
|
|
952
|
+
log.error(indentedOutput);
|
|
953
|
+
log.warn("ATTW found issues, but the build was not affected.");
|
|
864
954
|
}
|
|
865
955
|
}
|
|
866
956
|
}
|
|
867
957
|
// Report total compilation results
|
|
868
958
|
if (buildContext.errorCount > 0 || buildContext.warningCount > 0) {
|
|
869
|
-
|
|
959
|
+
log.info(`Compilation finished with ${buildContext.errorCount} error${buildContext.errorCount === 1 ? "" : "s"} and ${buildContext.warningCount} warning${buildContext.warningCount === 1 ? "" : "s"}`);
|
|
870
960
|
// Apply threshold rules for exit code
|
|
871
961
|
if (failThreshold !== "never" && buildContext.errorCount > 0) {
|
|
872
962
|
// Both 'warn' and 'error' thresholds cause failure on errors
|
|
873
|
-
|
|
963
|
+
log.error("❌ Build completed with errors");
|
|
874
964
|
process.exit(1);
|
|
875
965
|
}
|
|
876
966
|
else if (failThreshold === "warn" && buildContext.warningCount > 0) {
|
|
877
967
|
// Only 'warn' threshold causes failure on warnings
|
|
878
|
-
|
|
968
|
+
log.warn(`Build completed with warnings (exiting with error due to --fail-threshold=warn)`);
|
|
879
969
|
process.exit(1);
|
|
880
970
|
}
|
|
881
971
|
else if (buildContext.errorCount > 0) {
|
|
882
972
|
// If we got here with errors, we're in 'never' mode
|
|
883
|
-
|
|
973
|
+
log.warn(`Build completed with errors (continuing due to --fail-threshold=never)`);
|
|
884
974
|
}
|
|
885
975
|
else {
|
|
886
976
|
// Just warnings and not failing on them
|
|
887
|
-
|
|
977
|
+
log.info(`Build complete with warnings`);
|
|
888
978
|
}
|
|
889
979
|
}
|
|
890
980
|
else {
|
|
891
|
-
|
|
981
|
+
if (!isSilent) {
|
|
982
|
+
log.info("Build complete! ✅");
|
|
983
|
+
}
|
|
892
984
|
}
|
|
893
985
|
}
|
|
894
986
|
//# sourceMappingURL=main.js.map
|