zshy 0.0.4 → 0.0.6

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/out/utils.cjs CHANGED
@@ -33,12 +33,16 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.formatForLog = formatForLog;
36
37
  exports.getEntryPoints = getEntryPoints;
37
38
  exports.readTsconfig = readTsconfig;
38
39
  exports.compileProject = compileProject;
39
- const globby_1 = require("globby");
40
40
  const path = __importStar(require("node:path"));
41
+ const globby_1 = require("globby");
41
42
  const ts = __importStar(require("typescript"));
43
+ function formatForLog(data) {
44
+ return JSON.stringify(data, null, 2).split("\n").join("\n ");
45
+ }
42
46
  // Get entry points using the same logic as esbuild.mts
43
47
  async function getEntryPoints(patterns) {
44
48
  const results = [];
@@ -57,22 +61,27 @@ async function getEntryPoints(patterns) {
57
61
  function readTsconfig(tsconfigPath) {
58
62
  // Read and parse tsconfig.json
59
63
  const configPath = path.resolve(tsconfigPath);
64
+ const configDir = path.dirname(configPath);
60
65
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
61
66
  if (configFile.error) {
62
67
  console.error("Error reading tsconfig.json:", ts.formatDiagnostic(configFile.error, {
63
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
68
+ getCurrentDirectory: () => configDir,
64
69
  getCanonicalFileName: (fileName) => fileName,
65
70
  getNewLine: () => ts.sys.newLine,
66
71
  }));
67
72
  process.exit(1);
68
73
  }
69
- // Parse the config
70
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath));
74
+ // Parse the config with explicit base path
75
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, {
76
+ ...ts.sys,
77
+ // Override getCurrentDirectory to use the tsconfig directory
78
+ getCurrentDirectory: () => configDir,
79
+ }, configDir);
71
80
  if (parsedConfig.errors.length > 0) {
72
81
  console.error("❌ Error parsing tsconfig.json:");
73
82
  for (const error of parsedConfig.errors) {
74
83
  console.error(ts.formatDiagnostic(error, {
75
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
84
+ getCurrentDirectory: () => configDir,
76
85
  getCanonicalFileName: (fileName) => fileName,
77
86
  getNewLine: () => ts.sys.newLine,
78
87
  }));
@@ -80,54 +89,49 @@ function readTsconfig(tsconfigPath) {
80
89
  process.exit(1);
81
90
  }
82
91
  if (!parsedConfig.options) {
83
- throw new Error("❌ Error reading tsconfig.json#compilerOptions");
92
+ throw new Error("❌ Error reading tsconfig.json#/compilerOptions");
84
93
  }
85
94
  return parsedConfig.options;
86
95
  }
87
96
  async function compileProject(config, entryPoints) {
88
- const exts = [];
89
- // exts.push(config.jsExtension ?? ".js");
90
- // exts.push(config.dtsExtension ?? ".d.ts");
91
- // console.log(
92
- // `🧱 Building${
93
- // config.mode === "ts"
94
- // ? ".js/.d.ts"
95
- // : config.mode === "mts"
96
- // ? ".mjs/.d.ts"
97
- // : ".cjs/.d.ts"
98
- // }...`,
99
- // );
97
+ // Deduplicate entry points before compilation
98
+ const uniqueEntryPoints = [...new Set(entryPoints)];
99
+ // Track files that would be written
100
+ const writtenFiles = [];
100
101
  // Create compiler host
101
102
  const host = ts.createCompilerHost(config.compilerOptions);
102
103
  const originalWriteFile = host.writeFile;
103
104
  const jsExt = config.mode === "mts" ? ".mjs" : config.mode === "cts" ? ".cjs" : ".js";
104
- const dtsExt = config.mode === "mts"
105
- ? ".d.mts"
106
- : config.mode === "cts"
107
- ? ".d.cts"
108
- : ".d.ts";
105
+ const dtsExt = config.mode === "mts" ? ".d.mts" : config.mode === "cts" ? ".d.cts" : ".d.ts";
109
106
  host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
110
107
  // Transform output file extensions
111
108
  let outputFileName = fileName;
112
109
  const processedData = data;
113
- // if (config.jsExtension) {
114
110
  if (fileName.endsWith(".js")) {
115
111
  outputFileName = fileName.replace(/\.js$/, jsExt);
116
112
  }
117
- // }
118
- // if (config.dtsExtension) {
119
113
  if (fileName.endsWith(".d.ts")) {
120
114
  outputFileName = fileName.replace(/\.d\.ts$/, dtsExt);
121
115
  }
122
- // }
123
- // console.log(` ${outputFileName}`);
124
- if (originalWriteFile) {
116
+ // Track the file that would be written
117
+ writtenFiles.push(outputFileName);
118
+ if (!config.dryRun && originalWriteFile) {
125
119
  originalWriteFile(outputFileName, processedData, writeByteOrderMark, onError, sourceFiles);
126
120
  }
127
121
  };
128
- // Create the TypeScript program using entry points
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
+ // Create the TypeScript program using unique entry points
129
133
  const program = ts.createProgram({
130
- rootNames: entryPoints,
134
+ rootNames: uniqueEntryPoints,
131
135
  options: config.compilerOptions,
132
136
  host,
133
137
  });
@@ -135,9 +139,7 @@ async function compileProject(config, entryPoints) {
135
139
  const extensionRewriteTransformer = (context) => {
136
140
  return (sourceFile) => {
137
141
  const visitor = (node) => {
138
- if (ts.isImportDeclaration(node) &&
139
- node.moduleSpecifier &&
140
- ts.isStringLiteral(node.moduleSpecifier)) {
142
+ if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
141
143
  const originalText = node.moduleSpecifier.text;
142
144
  if (originalText.endsWith(".js")) {
143
145
  const newText = originalText.slice(0, -3) + jsExt;
@@ -156,9 +158,7 @@ async function compileProject(config, entryPoints) {
156
158
  }
157
159
  }
158
160
  // Handle export declarations
159
- if (ts.isExportDeclaration(node) &&
160
- node.moduleSpecifier &&
161
- ts.isStringLiteral(node.moduleSpecifier)) {
161
+ if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
162
162
  const originalText = node.moduleSpecifier.text;
163
163
  if (originalText.endsWith(".js")) {
164
164
  const newText = originalText.slice(0, -3) + jsExt;
@@ -174,23 +174,19 @@ async function compileProject(config, entryPoints) {
174
174
  }
175
175
  }
176
176
  // Handle dynamic imports
177
- if (ts.isCallExpression(node) &&
178
- node.expression.kind === ts.SyntaxKind.ImportKeyword) {
177
+ if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
179
178
  const arg = node.arguments[0];
180
179
  if (ts.isStringLiteral(arg)) {
181
180
  const originalText = arg.text;
182
181
  if (originalText.endsWith(".js")) {
183
182
  const newText = originalText.slice(0, -3) + jsExt;
184
- // console.log(`Rewriting dynamic import from ${originalText} to
185
- // ${newText}`);
186
183
  return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
187
184
  ts.factory.createStringLiteral(newText),
188
185
  ...node.arguments.slice(1),
189
186
  ]);
190
187
  }
191
188
  // if dynamic import is extensionless, add .js extension
192
- if (originalText.startsWith("./") ||
193
- originalText.startsWith("../")) {
189
+ if (originalText.startsWith("./") || originalText.startsWith("../")) {
194
190
  const hasExtension = path.extname(originalText) !== "";
195
191
  if (!hasExtension) {
196
192
  const newText = originalText + jsExt;
@@ -212,30 +208,25 @@ async function compileProject(config, entryPoints) {
212
208
  if (diagnostics.length > 0) {
213
209
  const errorCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error).length;
214
210
  const warningCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Warning).length;
215
- console.log(`⚠️ Found ${errorCount} errors and ${warningCount} warnings`);
216
- // Only show first 5 errors to avoid overwhelming output
217
- const firstErrors = diagnostics
218
- .filter((d) => d.category === ts.DiagnosticCategory.Error)
219
- .slice(0, 5);
220
- if (firstErrors.length > 0) {
221
- console.log("First few compilation errors:");
222
- for (const diagnostic of firstErrors) {
223
- console.error(ts.formatDiagnostic(diagnostic, {
224
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
225
- getCanonicalFileName: (fileName) => fileName,
226
- getNewLine: () => ts.sys.newLine,
227
- }));
228
- }
229
- if (errorCount > 5) {
230
- console.log(`... and ${errorCount - 5} more errors`);
231
- }
211
+ if (errorCount > 0 || warningCount > 0) {
212
+ console.log(`⚠️ Found ${errorCount} error(s) and ${warningCount} warning(s)`);
213
+ console.log();
214
+ }
215
+ // Format diagnostics with color and context like tsc, keeping original order
216
+ const formatHost = {
217
+ getCurrentDirectory: () => process.cwd(),
218
+ getCanonicalFileName: (fileName) => fileName,
219
+ getNewLine: () => ts.sys.newLine,
220
+ };
221
+ // Keep errors and warnings intermixed in their original order
222
+ const relevantDiagnostics = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error || d.category === ts.DiagnosticCategory.Warning);
223
+ if (relevantDiagnostics.length > 0) {
224
+ console.log(ts.formatDiagnosticsWithColorAndContext(relevantDiagnostics, formatHost));
232
225
  }
233
226
  }
234
227
  // emit the files
235
228
  const emitResult = program.emit(undefined, undefined, undefined, undefined, {
236
- before: [
237
- extensionRewriteTransformer,
238
- ],
229
+ before: [extensionRewriteTransformer],
239
230
  afterDeclarations: [extensionRewriteTransformer],
240
231
  });
241
232
  if (emitResult.emitSkipped) {
@@ -247,13 +238,21 @@ async function compileProject(config, entryPoints) {
247
238
  }
248
239
  // Report any emit diagnostics
249
240
  if (emitResult.diagnostics.length > 0) {
250
- console.error("❌ Errors detected during emit:");
251
- for (const diagnostic of emitResult.diagnostics) {
252
- console.error(ts.formatDiagnostic(diagnostic, {
253
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
254
- getCanonicalFileName: (fileName) => fileName,
255
- getNewLine: () => ts.sys.newLine,
256
- }));
241
+ const emitErrors = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error);
242
+ 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:`);
244
+ console.log();
245
+ const formatHost = {
246
+ getCurrentDirectory: () => process.cwd(),
247
+ getCanonicalFileName: (fileName) => fileName,
248
+ getNewLine: () => ts.sys.newLine,
249
+ };
250
+ // Keep errors and warnings intermixed in their original order
251
+ const relevantEmitDiagnostics = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error || d.category === ts.DiagnosticCategory.Warning);
252
+ if (relevantEmitDiagnostics.length > 0) {
253
+ console.log(ts.formatDiagnosticsWithColorAndContext(relevantEmitDiagnostics, formatHost));
257
254
  }
258
255
  }
256
+ // Return the list of files that were written or would be written
257
+ return writtenFiles;
259
258
  }
package/out/utils.d.cts CHANGED
@@ -1,9 +1,13 @@
1
1
  import * as ts from "typescript";
2
+ export declare function formatForLog(data: unknown): string;
2
3
  export interface ProjectOptions {
3
4
  configPath: string;
4
5
  compilerOptions: ts.CompilerOptions & Required<Pick<ts.CompilerOptions, "module" | "moduleResolution" | "outDir">>;
5
6
  mode: "cts" | "ts" | "mts";
7
+ verbose?: boolean;
8
+ dryRun?: boolean;
9
+ packageRoot?: string;
6
10
  }
7
11
  export declare function getEntryPoints(patterns: string[]): Promise<string[]>;
8
12
  export declare function readTsconfig(tsconfigPath: string): ts.CompilerOptions;
9
- export declare function compileProject(config: ProjectOptions, entryPoints: string[]): Promise<void>;
13
+ export declare function compileProject(config: ProjectOptions, entryPoints: string[]): Promise<string[]>;
package/out/utils.d.ts CHANGED
@@ -1,9 +1,13 @@
1
1
  import * as ts from "typescript";
2
+ export declare function formatForLog(data: unknown): string;
2
3
  export interface ProjectOptions {
3
4
  configPath: string;
4
5
  compilerOptions: ts.CompilerOptions & Required<Pick<ts.CompilerOptions, "module" | "moduleResolution" | "outDir">>;
5
6
  mode: "cts" | "ts" | "mts";
7
+ verbose?: boolean;
8
+ dryRun?: boolean;
9
+ packageRoot?: string;
6
10
  }
7
11
  export declare function getEntryPoints(patterns: string[]): Promise<string[]>;
8
12
  export declare function readTsconfig(tsconfigPath: string): ts.CompilerOptions;
9
- export declare function compileProject(config: ProjectOptions, entryPoints: string[]): Promise<void>;
13
+ export declare function compileProject(config: ProjectOptions, entryPoints: string[]): Promise<string[]>;
package/out/utils.js CHANGED
@@ -1,6 +1,9 @@
1
- import { globby } from "globby";
2
1
  import * as path from "node:path";
2
+ import { globby } from "globby";
3
3
  import * as ts from "typescript";
4
+ export function formatForLog(data) {
5
+ return JSON.stringify(data, null, 2).split("\n").join("\n ");
6
+ }
4
7
  // Get entry points using the same logic as esbuild.mts
5
8
  export async function getEntryPoints(patterns) {
6
9
  const results = [];
@@ -19,22 +22,27 @@ export async function getEntryPoints(patterns) {
19
22
  export function readTsconfig(tsconfigPath) {
20
23
  // Read and parse tsconfig.json
21
24
  const configPath = path.resolve(tsconfigPath);
25
+ const configDir = path.dirname(configPath);
22
26
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
23
27
  if (configFile.error) {
24
28
  console.error("Error reading tsconfig.json:", ts.formatDiagnostic(configFile.error, {
25
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
29
+ getCurrentDirectory: () => configDir,
26
30
  getCanonicalFileName: (fileName) => fileName,
27
31
  getNewLine: () => ts.sys.newLine,
28
32
  }));
29
33
  process.exit(1);
30
34
  }
31
- // Parse the config
32
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath));
35
+ // Parse the config with explicit base path
36
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, {
37
+ ...ts.sys,
38
+ // Override getCurrentDirectory to use the tsconfig directory
39
+ getCurrentDirectory: () => configDir,
40
+ }, configDir);
33
41
  if (parsedConfig.errors.length > 0) {
34
42
  console.error("❌ Error parsing tsconfig.json:");
35
43
  for (const error of parsedConfig.errors) {
36
44
  console.error(ts.formatDiagnostic(error, {
37
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
45
+ getCurrentDirectory: () => configDir,
38
46
  getCanonicalFileName: (fileName) => fileName,
39
47
  getNewLine: () => ts.sys.newLine,
40
48
  }));
@@ -42,54 +50,49 @@ export function readTsconfig(tsconfigPath) {
42
50
  process.exit(1);
43
51
  }
44
52
  if (!parsedConfig.options) {
45
- throw new Error("❌ Error reading tsconfig.json#compilerOptions");
53
+ throw new Error("❌ Error reading tsconfig.json#/compilerOptions");
46
54
  }
47
55
  return parsedConfig.options;
48
56
  }
49
57
  export async function compileProject(config, entryPoints) {
50
- const exts = [];
51
- // exts.push(config.jsExtension ?? ".js");
52
- // exts.push(config.dtsExtension ?? ".d.ts");
53
- // console.log(
54
- // `🧱 Building${
55
- // config.mode === "ts"
56
- // ? ".js/.d.ts"
57
- // : config.mode === "mts"
58
- // ? ".mjs/.d.ts"
59
- // : ".cjs/.d.ts"
60
- // }...`,
61
- // );
58
+ // Deduplicate entry points before compilation
59
+ const uniqueEntryPoints = [...new Set(entryPoints)];
60
+ // Track files that would be written
61
+ const writtenFiles = [];
62
62
  // Create compiler host
63
63
  const host = ts.createCompilerHost(config.compilerOptions);
64
64
  const originalWriteFile = host.writeFile;
65
65
  const jsExt = config.mode === "mts" ? ".mjs" : config.mode === "cts" ? ".cjs" : ".js";
66
- const dtsExt = config.mode === "mts"
67
- ? ".d.mts"
68
- : config.mode === "cts"
69
- ? ".d.cts"
70
- : ".d.ts";
66
+ const dtsExt = config.mode === "mts" ? ".d.mts" : config.mode === "cts" ? ".d.cts" : ".d.ts";
71
67
  host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
72
68
  // Transform output file extensions
73
69
  let outputFileName = fileName;
74
70
  const processedData = data;
75
- // if (config.jsExtension) {
76
71
  if (fileName.endsWith(".js")) {
77
72
  outputFileName = fileName.replace(/\.js$/, jsExt);
78
73
  }
79
- // }
80
- // if (config.dtsExtension) {
81
74
  if (fileName.endsWith(".d.ts")) {
82
75
  outputFileName = fileName.replace(/\.d\.ts$/, dtsExt);
83
76
  }
84
- // }
85
- // console.log(` ${outputFileName}`);
86
- if (originalWriteFile) {
77
+ // Track the file that would be written
78
+ writtenFiles.push(outputFileName);
79
+ if (!config.dryRun && originalWriteFile) {
87
80
  originalWriteFile(outputFileName, processedData, writeByteOrderMark, onError, sourceFiles);
88
81
  }
89
82
  };
90
- // Create the TypeScript program using entry points
83
+ if (config.verbose) {
84
+ console.log(`🗣️ Resolved entrypoints: ${formatForLog(uniqueEntryPoints)}`);
85
+ console.log(`🗣️ Resolved compilerOptions: ${formatForLog({
86
+ ...config.compilerOptions,
87
+ // resolve enum values to strings for better logging
88
+ module: ts.ModuleKind[config.compilerOptions.module],
89
+ moduleResolution: ts.ModuleResolutionKind[config.compilerOptions.moduleResolution],
90
+ target: ts.ScriptTarget[config.compilerOptions.target],
91
+ })}`);
92
+ }
93
+ // Create the TypeScript program using unique entry points
91
94
  const program = ts.createProgram({
92
- rootNames: entryPoints,
95
+ rootNames: uniqueEntryPoints,
93
96
  options: config.compilerOptions,
94
97
  host,
95
98
  });
@@ -97,9 +100,7 @@ export async function compileProject(config, entryPoints) {
97
100
  const extensionRewriteTransformer = (context) => {
98
101
  return (sourceFile) => {
99
102
  const visitor = (node) => {
100
- if (ts.isImportDeclaration(node) &&
101
- node.moduleSpecifier &&
102
- ts.isStringLiteral(node.moduleSpecifier)) {
103
+ if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
103
104
  const originalText = node.moduleSpecifier.text;
104
105
  if (originalText.endsWith(".js")) {
105
106
  const newText = originalText.slice(0, -3) + jsExt;
@@ -118,9 +119,7 @@ export async function compileProject(config, entryPoints) {
118
119
  }
119
120
  }
120
121
  // Handle export declarations
121
- if (ts.isExportDeclaration(node) &&
122
- node.moduleSpecifier &&
123
- ts.isStringLiteral(node.moduleSpecifier)) {
122
+ if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
124
123
  const originalText = node.moduleSpecifier.text;
125
124
  if (originalText.endsWith(".js")) {
126
125
  const newText = originalText.slice(0, -3) + jsExt;
@@ -136,23 +135,19 @@ export async function compileProject(config, entryPoints) {
136
135
  }
137
136
  }
138
137
  // Handle dynamic imports
139
- if (ts.isCallExpression(node) &&
140
- node.expression.kind === ts.SyntaxKind.ImportKeyword) {
138
+ if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
141
139
  const arg = node.arguments[0];
142
140
  if (ts.isStringLiteral(arg)) {
143
141
  const originalText = arg.text;
144
142
  if (originalText.endsWith(".js")) {
145
143
  const newText = originalText.slice(0, -3) + jsExt;
146
- // console.log(`Rewriting dynamic import from ${originalText} to
147
- // ${newText}`);
148
144
  return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
149
145
  ts.factory.createStringLiteral(newText),
150
146
  ...node.arguments.slice(1),
151
147
  ]);
152
148
  }
153
149
  // if dynamic import is extensionless, add .js extension
154
- if (originalText.startsWith("./") ||
155
- originalText.startsWith("../")) {
150
+ if (originalText.startsWith("./") || originalText.startsWith("../")) {
156
151
  const hasExtension = path.extname(originalText) !== "";
157
152
  if (!hasExtension) {
158
153
  const newText = originalText + jsExt;
@@ -174,30 +169,25 @@ export async function compileProject(config, entryPoints) {
174
169
  if (diagnostics.length > 0) {
175
170
  const errorCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error).length;
176
171
  const warningCount = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Warning).length;
177
- console.log(`⚠️ Found ${errorCount} errors and ${warningCount} warnings`);
178
- // Only show first 5 errors to avoid overwhelming output
179
- const firstErrors = diagnostics
180
- .filter((d) => d.category === ts.DiagnosticCategory.Error)
181
- .slice(0, 5);
182
- if (firstErrors.length > 0) {
183
- console.log("First few compilation errors:");
184
- for (const diagnostic of firstErrors) {
185
- console.error(ts.formatDiagnostic(diagnostic, {
186
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
187
- getCanonicalFileName: (fileName) => fileName,
188
- getNewLine: () => ts.sys.newLine,
189
- }));
190
- }
191
- if (errorCount > 5) {
192
- console.log(`... and ${errorCount - 5} more errors`);
193
- }
172
+ if (errorCount > 0 || warningCount > 0) {
173
+ console.log(`⚠️ Found ${errorCount} error(s) and ${warningCount} warning(s)`);
174
+ console.log();
175
+ }
176
+ // Format diagnostics with color and context like tsc, keeping original order
177
+ const formatHost = {
178
+ getCurrentDirectory: () => process.cwd(),
179
+ getCanonicalFileName: (fileName) => fileName,
180
+ getNewLine: () => ts.sys.newLine,
181
+ };
182
+ // Keep errors and warnings intermixed in their original order
183
+ const relevantDiagnostics = diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error || d.category === ts.DiagnosticCategory.Warning);
184
+ if (relevantDiagnostics.length > 0) {
185
+ console.log(ts.formatDiagnosticsWithColorAndContext(relevantDiagnostics, formatHost));
194
186
  }
195
187
  }
196
188
  // emit the files
197
189
  const emitResult = program.emit(undefined, undefined, undefined, undefined, {
198
- before: [
199
- extensionRewriteTransformer,
200
- ],
190
+ before: [extensionRewriteTransformer],
201
191
  afterDeclarations: [extensionRewriteTransformer],
202
192
  });
203
193
  if (emitResult.emitSkipped) {
@@ -209,13 +199,21 @@ export async function compileProject(config, entryPoints) {
209
199
  }
210
200
  // Report any emit diagnostics
211
201
  if (emitResult.diagnostics.length > 0) {
212
- console.error("❌ Errors detected during emit:");
213
- for (const diagnostic of emitResult.diagnostics) {
214
- console.error(ts.formatDiagnostic(diagnostic, {
215
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
216
- getCanonicalFileName: (fileName) => fileName,
217
- getNewLine: () => ts.sys.newLine,
218
- }));
202
+ const emitErrors = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error);
203
+ const emitWarnings = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Warning);
204
+ console.error(`❌ Found ${emitErrors.length} error(s) and ${emitWarnings.length} warning(s) during emit:`);
205
+ console.log();
206
+ const formatHost = {
207
+ getCurrentDirectory: () => process.cwd(),
208
+ getCanonicalFileName: (fileName) => fileName,
209
+ getNewLine: () => ts.sys.newLine,
210
+ };
211
+ // Keep errors and warnings intermixed in their original order
212
+ const relevantEmitDiagnostics = emitResult.diagnostics.filter((d) => d.category === ts.DiagnosticCategory.Error || d.category === ts.DiagnosticCategory.Warning);
213
+ if (relevantEmitDiagnostics.length > 0) {
214
+ console.log(ts.formatDiagnosticsWithColorAndContext(relevantEmitDiagnostics, formatHost));
219
215
  }
220
216
  }
217
+ // Return the list of files that were written or would be written
218
+ return writtenFiles;
221
219
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "zshy",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
+ "type": "module",
4
5
  "description": "Gold-standard build tool for TypeScript libraries",
5
6
  "keywords": [
6
7
  "typescript",
@@ -31,10 +32,7 @@
31
32
  "url": "https://github.com/sponsors/colinhacks"
32
33
  },
33
34
  "module": "./out/index.js",
34
- "type": "module",
35
- "bin": {
36
- "zshy": "./out/index.js"
37
- },
35
+ "bin": "./out/index.cjs",
38
36
  "devDependencies": {
39
37
  "@arethetypeswrong/cli": "^0.18.2",
40
38
  "@biomejs/biome": "^2.0.5",
@@ -42,7 +40,8 @@
42
40
  "@types/react": "^19.1.8",
43
41
  "react": "^19.1.0",
44
42
  "tsx": "^4.20.3",
45
- "typescript": ">5.5.0"
43
+ "typescript": "^5.8.3",
44
+ "vitest": "^2.1.5"
46
45
  },
47
46
  "peerDependencies": {
48
47
  "typescript": ">5.5.0"
@@ -53,18 +52,18 @@
53
52
  "table": "^6.9.0"
54
53
  },
55
54
  "scripts": {
56
- "build": "tsx src/index.ts"
55
+ "build": "tsx src/index.ts",
56
+ "test": "vitest run",
57
+ "clean": "git clean -qxdf . -e node_modules"
57
58
  },
58
59
  "zshy": {
59
60
  "exports": {
60
- ".": "./src/index.ts",
61
- "./utils": "./src/utils.ts",
62
- "./plugins/*": "./src/plugins/*"
61
+ ".": "./src/index.ts"
63
62
  },
63
+ "bin": "./src/index.ts",
64
64
  "sourceDialects": [
65
65
  "@zod/source"
66
- ],
67
- "tsconfig": "./tsconfig.build.json"
66
+ ]
68
67
  },
69
68
  "main": "./out/index.cjs",
70
69
  "types": "./out/index.d.cts",
@@ -74,17 +73,6 @@
74
73
  "types": "./out/index.d.cts",
75
74
  "import": "./out/index.js",
76
75
  "require": "./out/index.cjs"
77
- },
78
- "./utils": {
79
- "@zod/source": "./src/utils.ts",
80
- "types": "./out/utils.d.cts",
81
- "import": "./out/utils.js",
82
- "require": "./out/utils.cjs"
83
- },
84
- "./plugins/*": {
85
- "@zod/source": "./src/plugins/*",
86
- "import": "./out/src/plugins/*",
87
- "require": "./out/src/plugins/*"
88
76
  }
89
77
  },
90
78
  "files": [
package/out/plugins/a.cjs DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.a = void 0;
4
- exports.a = "a";
@@ -1 +0,0 @@
1
- export declare const a = "a";
@@ -1 +0,0 @@
1
- export declare const a = "a";
package/out/plugins/a.js DELETED
@@ -1 +0,0 @@
1
- export const a = "a";
package/out/plugins/b.cjs DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.b = void 0;
4
- exports.b = "b";
@@ -1 +0,0 @@
1
- export declare const b = "b";
@@ -1 +0,0 @@
1
- export declare const b = "b";
package/out/plugins/b.js DELETED
@@ -1 +0,0 @@
1
- export const b = "b";