zshy 0.0.6 → 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.
@@ -5,7 +5,7 @@ import parseArgs from "arg";
5
5
  import { globby } from "globby";
6
6
  import { table } from "table";
7
7
  import * as ts from "typescript";
8
- import { compileProject, formatForLog, getEntryPoints, readTsconfig } from "./utils.js";
8
+ import { compileProject, emojiLog, formatForLog, getEntryPoints, readTsconfig } from "./utils.js";
9
9
  function isSourceFile(filePath) {
10
10
  return (filePath.endsWith(".ts") || filePath.endsWith(".mts") || filePath.endsWith(".cts") || filePath.endsWith(".tsx"));
11
11
  }
@@ -24,6 +24,7 @@ async function main() {
24
24
  "--verbose": Boolean,
25
25
  "--project": String,
26
26
  "--dry-run": Boolean,
27
+ // "--attw": Boolean,
27
28
  // Aliases
28
29
  "-h": "--help",
29
30
  "-p": "--project",
@@ -31,7 +32,7 @@ async function main() {
31
32
  }
32
33
  catch (error) {
33
34
  if (error instanceof Error) {
34
- console.error(`❌ ${error.message}`);
35
+ emojiLog("❌", error.message, "error");
35
36
  }
36
37
  console.error(`Use --help for usage information`);
37
38
  process.exit(1);
@@ -55,14 +56,27 @@ Examples:
55
56
  `);
56
57
  process.exit(0);
57
58
  }
58
- console.log("💎 Starting zshy build...");
59
+ const userAgent = process.env.npm_config_user_agent;
60
+ let pmExec;
61
+ if (userAgent?.startsWith("pnpm")) {
62
+ pmExec = "pnpm exec";
63
+ }
64
+ else if (userAgent?.startsWith("yarn")) {
65
+ pmExec = "yarn exec";
66
+ }
67
+ else {
68
+ pmExec = "npx";
69
+ }
70
+ emojiLog("💎", "Starting build... 🐒");
59
71
  const isVerbose = args["--verbose"];
60
72
  const isDryRun = args["--dry-run"];
73
+ const isAttw = false; // args["--attw"];
61
74
  if (isVerbose) {
62
- console.log("🗣️ Verbose mode enabled");
75
+ emojiLog("ℹ️", "Verbose mode enabled");
76
+ emojiLog("📦", `Detected package manager: ${pmExec}`);
63
77
  }
64
78
  if (isDryRun) {
65
- console.log("🔍 Dry run mode enabled - no files will be written");
79
+ emojiLog("🔍", "Dry run mode enabled - no files will be written");
66
80
  }
67
81
  ///////////////////////////////////
68
82
  /// find and read pkg json ///
@@ -79,7 +93,7 @@ Examples:
79
93
  currentDir = path.dirname(currentDir);
80
94
  }
81
95
  if (!fs.existsSync(packageJsonPath)) {
82
- console.error("❌ package.json not found in current directory or any parent directories");
96
+ emojiLog("❌", "package.json not found in current directory or any parent directories", "error");
83
97
  process.exit(1);
84
98
  }
85
99
  // read package.json and extract the "zshy" exports config
@@ -87,8 +101,8 @@ Examples:
87
101
  const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
88
102
  const pkgJsonDir = path.dirname(packageJsonPath);
89
103
  // print project root
90
- console.log(`⚙️ Detected project root: ${pkgJsonDir}`);
91
- console.log(`📦 Reading package.json from ./${path.relative(pkgJsonDir, packageJsonPath)}`);
104
+ emojiLog("⚙️", `Detected project root: ${pkgJsonDir}`);
105
+ emojiLog("📦", `Reading package.json from ./${path.relative(pkgJsonDir, packageJsonPath)}`);
92
106
  /////////////////////////////////
93
107
  /// parse zshy config ///
94
108
  /////////////////////////////////
@@ -96,7 +110,7 @@ Examples:
96
110
  const CONFIG_KEY = "zshy";
97
111
  let config;
98
112
  if (!pkgJson[CONFIG_KEY]) {
99
- console.error(`❌ No "${CONFIG_KEY}" key found in package.json`);
113
+ emojiLog("❌", `No "${CONFIG_KEY}" key found in package.json`, "error");
100
114
  process.exit(1);
101
115
  }
102
116
  if (typeof pkgJson[CONFIG_KEY] === "string") {
@@ -110,11 +124,11 @@ Examples:
110
124
  config.exports = { ".": config.exports };
111
125
  }
112
126
  else if (typeof config.exports === "undefined") {
113
- console.error(`❌ Missing "exports" key in package.json#/${CONFIG_KEY}`);
127
+ emojiLog("❌", `Missing "exports" key in package.json#/${CONFIG_KEY}`, "error");
114
128
  process.exit(1);
115
129
  }
116
130
  else if (typeof config.exports !== "object") {
117
- console.error(`❌ Invalid "exports" key in package.json#/${CONFIG_KEY}`);
131
+ emojiLog("❌", `Invalid "exports" key in package.json#/${CONFIG_KEY}`, "error");
118
132
  process.exit(1);
119
133
  }
120
134
  // Validate bin field if present
@@ -126,7 +140,7 @@ Examples:
126
140
  // Object format is valid
127
141
  }
128
142
  else {
129
- console.error(`❌ Invalid "bin" key in package.json#/${CONFIG_KEY}, expected string or object`);
143
+ emojiLog("❌", `Invalid "bin" key in package.json#/${CONFIG_KEY}, expected string or object`, "error");
130
144
  process.exit(1);
131
145
  }
132
146
  }
@@ -135,15 +149,15 @@ Examples:
135
149
  // };
136
150
  }
137
151
  else if (typeof pkgJson[CONFIG_KEY] === "undefined") {
138
- console.error(`❌ Missing "${CONFIG_KEY}" key in package.json`);
152
+ emojiLog("❌", `Missing "${CONFIG_KEY}" key in package.json`, "error");
139
153
  process.exit(1);
140
154
  }
141
155
  else {
142
- console.error(`❌ Invalid "${CONFIG_KEY}" key in package.json, expected string or object`);
156
+ emojiLog("❌", `Invalid "${CONFIG_KEY}" key in package.json, expected string or object`, "error");
143
157
  process.exit(1);
144
158
  }
145
159
  if (isVerbose) {
146
- console.log("🔧 Parsed zshy config:", formatForLog(config));
160
+ emojiLog("🔧", `Parsed zshy config: ${formatForLog(config)}`);
147
161
  }
148
162
  ///////////////////////////
149
163
  /// read tsconfig ///
@@ -155,7 +169,7 @@ Examples:
155
169
  const resolvedProjectPath = path.resolve(process.cwd(), args["--project"]);
156
170
  if (fs.existsSync(resolvedProjectPath)) {
157
171
  if (fs.statSync(resolvedProjectPath).isDirectory()) {
158
- console.error(`❌ --project must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`);
172
+ emojiLog("❌", `--project must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`, "error");
159
173
  process.exit(1);
160
174
  }
161
175
  else {
@@ -164,7 +178,7 @@ Examples:
164
178
  }
165
179
  }
166
180
  else {
167
- console.error(`❌ tsconfig.json file not found: ${resolvedProjectPath}`);
181
+ emojiLog("❌", `tsconfig.json file not found: ${resolvedProjectPath}`, "error");
168
182
  process.exit(1);
169
183
  }
170
184
  }
@@ -173,7 +187,7 @@ Examples:
173
187
  const resolvedProjectPath = path.resolve(pkgJsonDir, config.tsconfig);
174
188
  if (fs.existsSync(resolvedProjectPath)) {
175
189
  if (fs.statSync(resolvedProjectPath).isDirectory()) {
176
- console.error(`❌ zshy.tsconfig must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`);
190
+ emojiLog("❌", `zshy.tsconfig must point to a tsconfig.json file, not a directory: ${resolvedProjectPath}`, "error");
177
191
  process.exit(1);
178
192
  }
179
193
  else {
@@ -182,7 +196,7 @@ Examples:
182
196
  }
183
197
  }
184
198
  else {
185
- console.error(`❌ Tsconfig file not found: ${resolvedProjectPath}`);
199
+ emojiLog("❌", `Tsconfig file not found: ${resolvedProjectPath}`, "error");
186
200
  process.exit(1);
187
201
  }
188
202
  }
@@ -193,10 +207,10 @@ Examples:
193
207
  const _parsedConfig = readTsconfig(tsconfigPath);
194
208
  if (!fs.existsSync(tsconfigPath)) {
195
209
  // Check if tsconfig.json exists
196
- console.error(`❌ tsconfig.json not found at ${path.resolve(tsconfigPath)}`);
210
+ emojiLog("❌", `tsconfig.json not found at ${path.resolve(tsconfigPath)}`, "error");
197
211
  process.exit(1);
198
212
  }
199
- console.log(`📁 Reading tsconfig from ./${path.relative(pkgJsonDir, tsconfigPath)}`);
213
+ emojiLog("📁", `Reading tsconfig from ./${path.relative(pkgJsonDir, tsconfigPath)}`);
200
214
  // if (_parsedConfig.rootDir) {
201
215
  // console.error(
202
216
  // `❌ rootDir is determined from your set of entrypoints; you can remove it from your tsconfig.json.`,
@@ -217,31 +231,31 @@ Examples:
217
231
  const relDeclarationDir = path.relative(pkgJsonDir, declarationDir);
218
232
  // clean up outDir and declarationDir
219
233
  if (relOutDir !== "") {
220
- console.log(`🗑️ Cleaning up outDir...`);
234
+ emojiLog("🗑️", `Cleaning up outDir...`);
221
235
  fs.rmSync(outDir, { recursive: true, force: true });
222
236
  // // print success mesage in verbose mode
223
237
  if (isVerbose) {
224
238
  if (fs.existsSync(outDir)) {
225
- console.error(`❌ Failed to clean up outDir: ${relOutDir}. Directory still exists.`);
239
+ emojiLog("❌", `Failed to clean up outDir: ${relOutDir}. Directory still exists.`, "error");
226
240
  }
227
241
  }
228
242
  }
229
243
  else {
230
- console.log(`🗑️ Skipping cleanup of outDir as it contains source files`);
244
+ emojiLog("🗑️", `Skipping cleanup of outDir as it contains source files`);
231
245
  }
232
246
  if (relDeclarationDir !== relOutDir && relDeclarationDir !== "") {
233
- console.log(`🗑️ Cleaning up declarationDir...`);
247
+ emojiLog("🗑️", `Cleaning up declarationDir...`);
234
248
  fs.rmSync(declarationDir, { recursive: true, force: true });
235
249
  // // print success mesage in verbose mode
236
250
  if (isVerbose) {
237
251
  if (fs.existsSync(declarationDir)) {
238
- console.error(`❌ Failed to clean up declarationDir: ${relDeclarationDir}. Directory still exists.`);
252
+ emojiLog("❌", `Failed to clean up declarationDir: ${relDeclarationDir}. Directory still exists.`, "error");
239
253
  }
240
254
  }
241
255
  }
242
256
  else {
243
257
  if (isVerbose)
244
- console.log(`🗑️ Skipping cleanup of declarationDir as it contains source files`);
258
+ emojiLog("🗑️", `Skipping cleanup of declarationDir as it contains source files`);
245
259
  }
246
260
  const tsconfigJson = {
247
261
  ..._parsedConfig,
@@ -256,11 +270,11 @@ Examples:
256
270
  };
257
271
  if (relOutDir === "") {
258
272
  if (!pkgJson.files) {
259
- console.log('⚠️ 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.');
273
+ 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.');
260
274
  pkgJson.files = ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"];
261
275
  }
262
276
  else {
263
- console.warn(`⚠️ You're building your code to the project root. This means your compiled files will be generated alongside your source files.
277
+ console.warn(`⚠️ You\'re building your code to the project root. This means your compiled files will be generated alongside your source files.
264
278
  ➜ Ensure that your "files" in package.json excludes TypeScript source files, or your users may experience .d.ts resolution issues in some environments:
265
279
 
266
280
  "files": ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts"],
@@ -269,7 +283,7 @@ Examples:
269
283
  }
270
284
  else {
271
285
  if (!pkgJson.files) {
272
- console.log(`⚠️ The "files" key is missing in package.json. Setting to "${relOutDir}".`);
286
+ emojiLog("⚠️", `The "files" key is missing in package.json. Setting to "${relOutDir}".`);
273
287
  pkgJson.files = [relOutDir];
274
288
  if (relOutDir !== relDeclarationDir) {
275
289
  pkgJson.files.push(relDeclarationDir);
@@ -280,7 +294,7 @@ Examples:
280
294
  /// extract entry points ///
281
295
  /////////////////////////////////
282
296
  // Extract entry points from zshy exports config
283
- console.log("➡️ Determining entrypoints...");
297
+ emojiLog("➡️", "Determining entrypoints...");
284
298
  const entryPatterns = [];
285
299
  const rows = [["Subpath", "Entrypoint"]];
286
300
  for (const [exportPath, sourcePath] of Object.entries(config.exports)) {
@@ -294,13 +308,13 @@ Examples:
294
308
  cleanExportPath = pkgJson.name + "/" + exportPath.slice(2);
295
309
  }
296
310
  else {
297
- console.error(`⚠️ Invalid subpath export "${exportPath}" — should start with "./"`);
311
+ emojiLog("⚠️", `Invalid subpath export "${exportPath}" — should start with "./"`, "warn");
298
312
  process.exit(1);
299
313
  }
300
314
  if (typeof sourcePath === "string") {
301
315
  if (sourcePath.includes("*")) {
302
316
  if (!sourcePath.endsWith("/*")) {
303
- console.error(`❌ Wildcard paths should not contain file extensions: ${sourcePath}`);
317
+ emojiLog("❌", `Wildcard paths should not contain file extensions: ${sourcePath}`, "error");
304
318
  process.exit(1);
305
319
  }
306
320
  const pattern = sourcePath.slice(0, -2) + "/*.{ts,tsx,mts,cts}";
@@ -356,11 +370,11 @@ Examples:
356
370
  const entryPoints = await getEntryPoints(entryPatterns);
357
371
  // disallow .mts and .cts files
358
372
  if (entryPoints.some((ep) => ep.endsWith(".mts") || ep.endsWith(".cts"))) {
359
- console.error("❌ Source files with .mts or .cts extensions are not supported. Please use regular .ts files.");
373
+ emojiLog("❌", "Source files with .mts or .cts extensions are not supported. Please use regular .ts files.", "error");
360
374
  process.exit(1);
361
375
  }
362
376
  if (entryPoints.length === 0) {
363
- console.error("❌ No entry points found matching the specified patterns in package.json#/zshy exports");
377
+ emojiLog("❌", "No entry points found matching the specified patterns in package.json#/zshy exports", "error");
364
378
  process.exit(1);
365
379
  }
366
380
  ///////////////////////////////
@@ -391,7 +405,7 @@ Examples:
391
405
  }
392
406
  const relRootDir = path.relative(pkgJsonDir, rootDir);
393
407
  // Display resolved paths table
394
- console.log("🔧 Resolved build paths:");
408
+ emojiLog("🔧", "Resolved build paths:");
395
409
  const pathRows = [["Location", "Resolved path"]];
396
410
  // pathRows.push([
397
411
  // "package.json",
@@ -417,19 +431,29 @@ Examples:
417
431
  .trim());
418
432
  const isTypeModule = pkgJson.type === "module";
419
433
  if (isTypeModule) {
420
- console.log(`🟨 Package is an ES module (package.json#/type is \"module\")`);
434
+ emojiLog("🟨", `Package is an ES module (package.json#/type is "module")`);
421
435
  }
422
436
  else {
423
- console.log(`🐢 Package is a CommonJS module (${pkgJson.type === "commonjs" ? 'package.json#/type is "commonjs"' : 'package.json#/type not set to "module"'})`);
437
+ emojiLog("🐢", `Package is a CommonJS module (${pkgJson.type === "commonjs" ? 'package.json#/type is "commonjs"' : 'package.json#/type not set to "module"'})`);
424
438
  }
425
439
  ///////////////////////////////
426
440
  /// compile tsc ///
427
441
  ///////////////////////////////
442
+ const uniqueEntryPoints = [...new Set(entryPoints)];
428
443
  try {
444
+ if (isVerbose) {
445
+ emojiLog("→", `Resolved entrypoints: ${formatForLog(uniqueEntryPoints)}`);
446
+ emojiLog("→", `Resolved compilerOptions: ${formatForLog({
447
+ ...tsconfigJson,
448
+ module: ts.ModuleKind[tsconfigJson.module],
449
+ moduleResolution: ts.ModuleResolutionKind[tsconfigJson.moduleResolution],
450
+ target: ts.ScriptTarget[tsconfigJson.target],
451
+ })}`);
452
+ }
429
453
  // Track all written files
430
454
  const allWrittenFiles = [];
431
455
  // CJS
432
- console.log(`🧱 Building CJS...${isTypeModule ? ` (rewriting .ts -> .cjs/.d.cts)` : ``}`);
456
+ emojiLog("🧱", `Building CJS...${isTypeModule ? ` (rewriting .ts -> .cjs/.d.cts)` : ``}`);
433
457
  const cjsFiles = await compileProject({
434
458
  configPath: tsconfigPath,
435
459
  mode: isTypeModule ? "cts" : "ts",
@@ -442,10 +466,10 @@ Examples:
442
466
  moduleResolution: ts.ModuleResolutionKind.Node10,
443
467
  outDir,
444
468
  },
445
- }, entryPoints);
469
+ }, uniqueEntryPoints);
446
470
  allWrittenFiles.push(...cjsFiles);
447
471
  // ESM
448
- console.log(`🧱 Building ESM...${isTypeModule ? `` : ` (rewriting .ts -> .mjs/.d.mts)`}`);
472
+ emojiLog("🧱", `Building ESM...${isTypeModule ? `` : ` (rewriting .ts -> .mjs/.d.mts)`}`);
449
473
  const esmFiles = await compileProject({
450
474
  configPath: tsconfigPath,
451
475
  mode: isTypeModule ? "ts" : "mts",
@@ -458,28 +482,28 @@ Examples:
458
482
  moduleResolution: ts.ModuleResolutionKind.Bundler,
459
483
  outDir,
460
484
  },
461
- }, entryPoints);
485
+ }, uniqueEntryPoints);
462
486
  allWrittenFiles.push(...esmFiles);
463
487
  ///////////////////////////////////
464
488
  /// display written files ///
465
489
  ///////////////////////////////////
466
490
  // Display files that were written or would be written (only in verbose mode)
467
491
  if (isVerbose && allWrittenFiles.length > 0) {
468
- console.log(`📜 ${isDryRun ? "[dryrun] " : ""}Writing files... (${allWrittenFiles.length} total):`);
492
+ emojiLog("📜", `${isDryRun ? "[dryrun] " : ""}Writing files (${allWrittenFiles.length} total)...`);
469
493
  // Sort files by relative path for consistent display
470
494
  const sortedFiles = [...allWrittenFiles]
471
495
  .map((file) => path.relative(pkgJsonDir, file))
472
496
  .sort()
473
497
  .map((relPath) => (relPath.startsWith(".") ? relPath : `./${relPath}`));
474
498
  sortedFiles.forEach((file) => {
475
- console.log(` ${file}`);
499
+ console.log(` ${file}`);
476
500
  });
477
501
  }
478
502
  ///////////////////////////////
479
503
  /// generate exports ///
480
504
  ///////////////////////////////
481
505
  // generate package.json exports
482
- console.log("📦 Updating package.json#/exports...");
506
+ emojiLog("📦", `${isDryRun ? "[dryrun] " : ""}Updating package.json#/exports...`);
483
507
  // Generate exports based on zshy config
484
508
  const newExports = {};
485
509
  const sourceDialects = config.sourceDialects || [];
@@ -497,13 +521,6 @@ Examples:
497
521
  if (typeof sourcePath === "string") {
498
522
  if (sourcePath.endsWith("/*")) {
499
523
  // Handle wildcard exports
500
- // const relSourcePath =
501
- // "./" +
502
- // path.relative(
503
- // pkgJsonDir,
504
- // path.resolve(outDir, sourcePath.slice(0, -2)),
505
- // ) +
506
- // "/*";
507
524
  newExports[exportPath] = {
508
525
  types: relDtsPath,
509
526
  import: relJsPath,
@@ -517,7 +534,7 @@ Examples:
517
534
  }
518
535
  }
519
536
  else if (isSourceFile(sourcePath)) {
520
- const esmPath = removeExtension(relJsPath) + (isTypeModule ? `.js` : `.mjs`); // ./v4/index.js or ./v4/index.mjs
537
+ const esmPath = removeExtension(relJsPath) + (isTypeModule ? `.js` : `.mjs`);
521
538
  const cjsPath = removeExtension(relJsPath) + (isTypeModule ? `.cjs` : `.js`);
522
539
  const dtsPath = removeExtension(relDtsPath) + (isTypeModule ? `.d.cts` : `.d.ts`); // ./
523
540
  newExports[exportPath] = {
@@ -538,17 +555,20 @@ Examples:
538
555
  }
539
556
  }
540
557
  else {
541
- console.error(`❌ Invalid entrypoint: ${sourcePath}`);
558
+ emojiLog("❌", `Invalid entrypoint: ${sourcePath}`, "error");
542
559
  process.exit();
543
560
  }
544
561
  }
545
562
  }
563
+ if (isVerbose) {
564
+ emojiLog("🔧", `Generated "exports": ${formatForLog(newExports)}`);
565
+ }
546
566
  ///////////////////////////////
547
567
  /// generate bin ///
548
568
  ///////////////////////////////
549
569
  // Generate bin field based on zshy bin config
550
570
  if (config.bin) {
551
- console.log("📦 Updating package.json#/bin...");
571
+ emojiLog("📦", `${isDryRun ? "[dryrun] " : ""}Updating package.json#/bin...`);
552
572
  const newBin = {};
553
573
  // Convert config.bin to object format for processing
554
574
  const binEntries = typeof config.bin === "string" ? [[pkgJson.name, config.bin]] : Object.entries(config.bin);
@@ -566,49 +586,74 @@ Examples:
566
586
  // If original config.bin was a string, output as string
567
587
  if (typeof config.bin === "string") {
568
588
  pkgJson.bin = Object.values(newBin)[0];
569
- if (isVerbose) {
570
- console.log(`🗣️ Updated package.json#/bin: "${Object.values(newBin)[0]}"`);
571
- }
572
589
  }
573
590
  else {
574
591
  // Output as object
575
592
  pkgJson.bin = newBin;
576
- if (isVerbose) {
577
- console.log("🗣️ Updated package.json#/bin: " + formatForLog(newBin));
578
- }
579
593
  }
580
594
  }
595
+ if (isVerbose) {
596
+ emojiLog("🔧", `Generated "bin": ${formatForLog(pkgJson.bin)}`);
597
+ }
581
598
  ///////////////////////////////
582
599
  /// write pkg json ///
583
600
  ///////////////////////////////
584
601
  // Update package.json with new exports
585
602
  pkgJson.exports = newExports;
586
603
  if (isDryRun) {
587
- console.log("🔍 Skipping package.json modification (dry-run)");
604
+ emojiLog("📦", "[dryrun] Skipping package.json modification");
588
605
  }
589
606
  else {
590
607
  fs.writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
591
608
  }
592
- // console.log("✅ Updating package.json#/exports");
593
- if (isVerbose) {
594
- console.log(`🗣️ Updated package.json#/exports: ${formatForLog(newExports)}`);
609
+ if (isAttw) {
610
+ // run `@arethetypeswrong/cli --pack .` to check types
611
+ emojiLog("🔍", "Checking types with @arethetypeswrong/cli...");
612
+ const { execFile } = await import("node:child_process");
613
+ const { promisify } = await import("node:util");
614
+ const execFileAsync = promisify(execFile);
615
+ const [cmd, ...args] = `${pmExec} @arethetypeswrong/cli --pack ${pkgJsonDir}`.split(" ");
616
+ console.dir([cmd, ...args], { depth: null });
617
+ let stdout = "";
618
+ let stderr = "";
619
+ let exitCode = 0;
620
+ try {
621
+ const result = await execFileAsync(cmd, args, {
622
+ cwd: pkgJsonDir,
623
+ encoding: "utf-8",
624
+ });
625
+ stdout = result.stdout;
626
+ stderr = result.stderr;
627
+ }
628
+ catch (error) {
629
+ stdout = error.stdout || "";
630
+ stderr = error.stderr || "";
631
+ exitCode = error.code || 1;
632
+ }
633
+ const output = stdout || stderr;
634
+ if (output) {
635
+ const indentedOutput = output
636
+ .split("\n")
637
+ .map((line) => ` ${line}`)
638
+ .join("\n");
639
+ if (exitCode === 0) {
640
+ console.log(indentedOutput);
641
+ }
642
+ else {
643
+ console.error(indentedOutput);
644
+ emojiLog("⚠️", "ATTW found issues, but the build was not affected.", "warn");
645
+ }
646
+ }
595
647
  }
596
- // // run `@arethetypeswrong/cli --pack .` to check types
597
- // console.log("🔍 Checking types with @arethetypeswrong/cli...");
598
- // const { execSync } = await import("node:child_process");
599
- // execSync(`npx @arethetypeswrong/cli --pack ${pkgJsonDir}`, {
600
- // stdio: "inherit",
601
- // cwd: pkgJsonDir,
602
- // });
603
- console.log("🎉 Build complete!");
648
+ emojiLog("🎉", "Build complete! ✅");
604
649
  }
605
650
  catch (error) {
606
- console.error("❌ Build failed:", error);
651
+ emojiLog("❌", `Build failed: ${error}`, "error");
607
652
  process.exit(1);
608
653
  }
609
654
  }
610
655
  // Run the script
611
656
  main().catch((error) => {
612
- console.error("❌ Script failed:", error);
657
+ emojiLog("❌", `Script failed: ${error}`, "error");
613
658
  process.exit(1);
614
659
  });
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.formatForLog = formatForLog;
37
+ exports.emojiLog = emojiLog;
37
38
  exports.getEntryPoints = getEntryPoints;
38
39
  exports.readTsconfig = readTsconfig;
39
40
  exports.compileProject = compileProject;
@@ -43,6 +44,9 @@ const ts = __importStar(require("typescript"));
43
44
  function formatForLog(data) {
44
45
  return JSON.stringify(data, null, 2).split("\n").join("\n ");
45
46
  }
47
+ function emojiLog(_emoji, content, level = "log") {
48
+ console[level]("→ " + content);
49
+ }
46
50
  // Get entry points using the same logic as esbuild.mts
47
51
  async function getEntryPoints(patterns) {
48
52
  const results = [];
@@ -51,7 +55,7 @@ async function getEntryPoints(patterns) {
51
55
  ignore: ["**/*.d.ts"],
52
56
  });
53
57
  if (!pattern.endsWith("/*") && _results.length === 0) {
54
- console.error(`❌ File does not exist: ${pattern}`);
58
+ emojiLog("❌", `File does not exist: ${pattern}`, "error");
55
59
  process.exit(1);
56
60
  }
57
61
  results.push(..._results);
@@ -78,7 +82,7 @@ function readTsconfig(tsconfigPath) {
78
82
  getCurrentDirectory: () => configDir,
79
83
  }, configDir);
80
84
  if (parsedConfig.errors.length > 0) {
81
- console.error("❌ Error parsing tsconfig.json:");
85
+ emojiLog("❌", "Error parsing tsconfig.json:", "error");
82
86
  for (const error of parsedConfig.errors) {
83
87
  console.error(ts.formatDiagnostic(error, {
84
88
  getCurrentDirectory: () => configDir,
@@ -89,13 +93,13 @@ function readTsconfig(tsconfigPath) {
89
93
  process.exit(1);
90
94
  }
91
95
  if (!parsedConfig.options) {
92
- throw new Error("❌ Error reading tsconfig.json#/compilerOptions");
96
+ emojiLog("❌", "Error reading tsconfig.json#/compilerOptions", "error");
97
+ process.exit(1);
93
98
  }
94
99
  return parsedConfig.options;
95
100
  }
96
101
  async function compileProject(config, entryPoints) {
97
102
  // Deduplicate entry points before compilation
98
- const uniqueEntryPoints = [...new Set(entryPoints)];
99
103
  // Track files that would be written
100
104
  const writtenFiles = [];
101
105
  // Create compiler host
@@ -119,19 +123,9 @@ async function compileProject(config, entryPoints) {
119
123
  originalWriteFile(outputFileName, processedData, writeByteOrderMark, onError, sourceFiles);
120
124
  }
121
125
  };
122
- if (config.verbose) {
123
- console.log(`🗣️ Resolved entrypoints: ${formatForLog(uniqueEntryPoints)}`);
124
- console.log(`🗣️ Resolved compilerOptions: ${formatForLog({
125
- ...config.compilerOptions,
126
- // resolve enum values to strings for better logging
127
- module: ts.ModuleKind[config.compilerOptions.module],
128
- moduleResolution: ts.ModuleResolutionKind[config.compilerOptions.moduleResolution],
129
- target: ts.ScriptTarget[config.compilerOptions.target],
130
- })}`);
131
- }
132
126
  // Create the TypeScript program using unique entry points
133
127
  const program = ts.createProgram({
134
- rootNames: uniqueEntryPoints,
128
+ rootNames: entryPoints,
135
129
  options: config.compilerOptions,
136
130
  host,
137
131
  });
@@ -209,7 +203,7 @@ async function compileProject(config, entryPoints) {
209
203
  const errorCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error).length;
210
204
  const warningCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Warning).length;
211
205
  if (errorCount > 0 || warningCount > 0) {
212
- console.log(`⚠️ Found ${errorCount} error(s) and ${warningCount} warning(s)`);
206
+ emojiLog("⚠️", `Found ${errorCount} error(s) and ${warningCount} warning(s)`, "warn");
213
207
  console.log();
214
208
  }
215
209
  // Format diagnostics with color and context like tsc, keeping original order
@@ -230,7 +224,7 @@ async function compileProject(config, entryPoints) {
230
224
  afterDeclarations: [extensionRewriteTransformer],
231
225
  });
232
226
  if (emitResult.emitSkipped) {
233
- console.error("❌ Emit was skipped due to errors");
227
+ emojiLog("❌", "Emit was skipped due to errors", "error");
234
228
  }
235
229
  else {
236
230
  // console.log(`✅ Emitted ${config.jsExtension} and ${config.dtsExtension}
@@ -240,7 +234,7 @@ async function compileProject(config, entryPoints) {
240
234
  if (emitResult.diagnostics.length > 0) {
241
235
  const emitErrors = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error);
242
236
  const emitWarnings = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Warning);
243
- console.error(`❌ Found ${emitErrors.length} error(s) and ${emitWarnings.length} warning(s) during emit:`);
237
+ emojiLog("❌", `Found ${emitErrors.length} error(s) and ${emitWarnings.length} warning(s) during emit:`, "error");
244
238
  console.log();
245
239
  const formatHost = {
246
240
  getCurrentDirectory: () => process.cwd(),
@@ -1,5 +1,6 @@
1
1
  import * as ts from "typescript";
2
2
  export declare function formatForLog(data: unknown): string;
3
+ export declare function emojiLog(_emoji: string, content: string, level?: "log" | "warn" | "error"): void;
3
4
  export interface ProjectOptions {
4
5
  configPath: string;
5
6
  compilerOptions: ts.CompilerOptions & Required<Pick<ts.CompilerOptions, "module" | "moduleResolution" | "outDir">>;
@@ -1,5 +1,6 @@
1
1
  import * as ts from "typescript";
2
2
  export declare function formatForLog(data: unknown): string;
3
+ export declare function emojiLog(_emoji: string, content: string, level?: "log" | "warn" | "error"): void;
3
4
  export interface ProjectOptions {
4
5
  configPath: string;
5
6
  compilerOptions: ts.CompilerOptions & Required<Pick<ts.CompilerOptions, "module" | "moduleResolution" | "outDir">>;