Skip to content

Commit 9fd0d55

Browse files
committed
feat(publish): improve package publishing with version checks and better error handling
- Replace shell command execution with Bun.spawn for better process control - Add version check to skip already published packages - Enhance error handling with detailed error messages - Track and report publish results (published/skipped/failed) - Improve logging with emojis and version information
1 parent 5424f87 commit 9fd0d55

File tree

1 file changed

+63
-6
lines changed

1 file changed

+63
-6
lines changed

scripts/publish.ts

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,16 @@ const log = (msg: string) => console.log(`[publish] ${msg}`);
3838
const run = async (cmd: string, cwd = repoRoot) => {
3939
log(cmd);
4040
// Invoke via bash -lc to support full command strings while still streaming output.
41-
await $`bash -lc ${cmd}`.cwd(cwd);
41+
const proc = Bun.spawn(['bash', '-lc', cmd], {
42+
cwd,
43+
stdout: 'inherit', // Stream stdout directly to console
44+
stderr: 'inherit', // Stream stderr directly to console
45+
});
46+
47+
const exitCode = await proc.exited;
48+
if (exitCode !== 0) {
49+
throw new Error(`Command failed with exit code ${exitCode}: ${cmd}`);
50+
}
4251
};
4352

4453
log(`version: ${version}`);
@@ -87,7 +96,24 @@ if (hostPkg) {
8796
}
8897
}
8998

90-
const publishPackage = async (dir: string, displayName: string) => {
99+
const publishPackage = async (dir: string, displayName: string): Promise<'published' | 'skipped'> => {
100+
// Check if this version is already published
101+
const pkgJson = JSON.parse(await Bun.file(join(dir, 'package.json')).text());
102+
const pkgName = pkgJson.name;
103+
const pkgVersion = pkgJson.version;
104+
105+
try {
106+
const { stdout } = await $`npm view ${pkgName}@${pkgVersion} version 2>/dev/null`.quiet().nothrow();
107+
const publishedVersion = stdout.toString().trim();
108+
109+
if (publishedVersion === pkgVersion) {
110+
log(`⏭️ Skipping ${displayName}@${pkgVersion} (already published)`);
111+
return 'skipped';
112+
}
113+
} catch {
114+
// Package not published yet, continue
115+
}
116+
91117
const publishCmd = [
92118
'npm publish',
93119
`--access public`,
@@ -98,17 +124,48 @@ const publishPackage = async (dir: string, displayName: string) => {
98124
.filter(Boolean)
99125
.join(' ');
100126

101-
await run(publishCmd, dir);
102-
log(`${dryRun ? 'Dry-run' : 'Published'} ${displayName}`);
127+
log(`📦 Publishing ${displayName}@${pkgVersion}...`);
128+
129+
try {
130+
await run(publishCmd, dir);
131+
log(`✅ ${dryRun ? 'Dry-run' : 'Published'} ${displayName}@${pkgVersion}`);
132+
return 'published';
133+
} catch (error) {
134+
console.error(`❌ Failed to publish ${displayName}@${pkgVersion}`);
135+
console.error(`Error details:`, error);
136+
throw error; // Re-throw to stop the script
137+
}
103138
};
104139

140+
const publishResults = { published: [] as string[], skipped: [] as string[], failed: [] as string[] };
141+
105142
log('Publishing platform packages...');
106143
for (const { name, dir } of platformPackages) {
107-
await publishPackage(dir, name);
144+
try {
145+
const result = await publishPackage(dir, name);
146+
if (result === 'skipped') {
147+
publishResults.skipped.push(name);
148+
} else {
149+
publishResults.published.push(name);
150+
}
151+
} catch (error) {
152+
publishResults.failed.push(name);
153+
throw error; // Stop on first failure
154+
}
108155
}
109156

110157
log('Publishing meta package...');
111-
await publishPackage(repoRoot, pkg.name);
158+
try {
159+
const result = await publishPackage(repoRoot, pkg.name);
160+
if (result === 'skipped') {
161+
publishResults.skipped.push(pkg.name);
162+
} else {
163+
publishResults.published.push(pkg.name);
164+
}
165+
} catch (error) {
166+
publishResults.failed.push(pkg.name);
167+
throw error;
168+
}
112169

113170
if (!dryRun) {
114171
const major = version.split('.')[0];

0 commit comments

Comments
 (0)