@b9g/libuild 0.1.18 → 0.1.19

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/CHANGELOG.md CHANGED
@@ -2,13 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.1.18] - 2025-12-01
5
+ ## [0.1.19] - 2025-12-08
6
6
 
7
- ### Changed
8
- - **prepublishOnly guards** - Replaced `private: true` with `prepublishOnly` script guards as the standard publish protection mechanism. Dist packages now include helpful error messages when accidentally publishing from wrong directory. The `private` field is now properly copied to dist/ for actual private packages, enabling libuild to work with private packages while maintaining publish protection.
7
+ ### Added
8
+ - **Ambient .d.ts exports** - Ambient TypeScript declaration files (*.d.ts) in src/ are now automatically added to the exports map, making them discoverable and importable by consumers.
9
+ - **Triple-slash references for ambient types** - Generated .d.ts files now include triple-slash reference directives to ambient .d.ts files, ensuring TypeScript can find ambient type declarations.
9
10
 
10
11
  ### Fixed
11
- - **Private package publishing** - Fixed bug where packages marked with `private: true` could still be published via `libuild publish`. npm now correctly handles private package rejection.
12
+ - **Hard fail on invalid workspace package.json** - Invalid JSON in workspace dependencies now causes build to fail immediately with clear error instead of silently continuing with a warning.
13
+
14
+ ## [0.1.18] - 2025-12-02
15
+
16
+ ### Changed
17
+ - **BREAKING: Scripts not copied to dist** - Scripts field is no longer copied to dist/package.json as they don't work correctly in the dist context (can't reference other scripts that were filtered out). This fixes the issue where prepublishOnly guards would block `libuild publish`. Users who need install scripts (postinstall, etc.) can manually add them to dist/package.json if needed.
18
+ - **prepublishOnly guards for root** - Root package.json gets `prepublishOnly` guard (via `--save`) to prevent accidental publishing from root directory.
19
+ - **Copy private field** - The `private` field is now properly copied from root to dist/, enabling actual private packages to work with libuild while npm prevents their publication.
12
20
 
13
21
  ## [0.1.17] - 2025-11-25
14
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/libuild",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Zero-config library builds",
5
5
  "keywords": [
6
6
  "build",
package/src/libuild.cjs CHANGED
@@ -212788,6 +212788,7 @@ ${diagnostics}`,
212788
212788
  });
212789
212789
  }
212790
212790
  await addTripleSlashReferences(tsFiles, options.outDir);
212791
+ await addAmbientReferences(tsFiles, options.outDir, options.rootDir);
212791
212792
  });
212792
212793
  }
212793
212794
  };
@@ -212822,6 +212823,29 @@ ${content}`;
212822
212823
  await FS2.writeFile(jsPath, modifiedContent);
212823
212824
  }
212824
212825
  }
212826
+ async function addAmbientReferences(tsFiles, outDir, rootDir) {
212827
+ let ambientFiles = [];
212828
+ try {
212829
+ const files = await FS2.readdir(rootDir);
212830
+ ambientFiles = files.filter((f) => f.endsWith(".d.ts"));
212831
+ } catch {
212832
+ return;
212833
+ }
212834
+ if (ambientFiles.length === 0)
212835
+ return;
212836
+ for (const tsFile of tsFiles) {
212837
+ const baseName = Path2.basename(tsFile, Path2.extname(tsFile));
212838
+ const dtsPath = Path2.join(outDir, `${baseName}.d.ts`);
212839
+ const dtsExists = await FS2.access(dtsPath).then(() => true).catch(() => false);
212840
+ if (!dtsExists)
212841
+ continue;
212842
+ const content = await FS2.readFile(dtsPath, "utf-8");
212843
+ const references = ambientFiles.map((ambientFile) => `/// <reference path="./${ambientFile}" />`).join("\n");
212844
+ const modifiedContent = `${references}
212845
+ ${content}`;
212846
+ await FS2.writeFile(dtsPath, modifiedContent);
212847
+ }
212848
+ }
212825
212849
 
212826
212850
  // src/libuild.ts
212827
212851
  function generateRuntimeBanner(pkg) {
@@ -213391,18 +213415,14 @@ async function resolveWorkspaceVersion(packageName, workspaceSpec, cwd) {
213391
213415
  `./${packageBaseName}/package.json`
213392
213416
  ];
213393
213417
  for (const pkgPath of possiblePaths) {
213394
- try {
213395
- const resolvedPath = Path3.resolve(cwd, pkgPath);
213396
- if (await fileExists(resolvedPath)) {
213397
- const pkgContent = await FS3.readFile(resolvedPath, "utf-8");
213398
- const pkgJson = JSON.parse(pkgContent);
213399
- if (pkgJson.name === packageName) {
213400
- console.info(` Resolved workspace:* dependency "${packageName}" to ^${pkgJson.version}`);
213401
- return `^${pkgJson.version}`;
213402
- }
213418
+ const resolvedPath = Path3.resolve(cwd, pkgPath);
213419
+ if (await fileExists(resolvedPath)) {
213420
+ const pkgContent = await FS3.readFile(resolvedPath, "utf-8");
213421
+ const pkgJson = JSON.parse(pkgContent);
213422
+ if (pkgJson.name === packageName) {
213423
+ console.info(` Resolved workspace:* dependency "${packageName}" to ^${pkgJson.version}`);
213424
+ return `^${pkgJson.version}`;
213403
213425
  }
213404
- } catch {
213405
- continue;
213406
213426
  }
213407
213427
  }
213408
213428
  console.warn(`\u26A0\uFE0F WARNING: Could not resolve workspace dependency "${packageName}" - keeping as workspace:*`);
@@ -213791,10 +213811,22 @@ async function build2(cwd, save = false) {
213791
213811
  });
213792
213812
  }
213793
213813
  const autoDiscoveredFiles = [];
213814
+ const ambientDtsFiles = [];
213815
+ if (await fileExists(srcDir)) {
213816
+ const srcFiles = await FS3.readdir(srcDir);
213817
+ ambientDtsFiles.push(...srcFiles.filter((f) => f.endsWith(".d.ts")));
213818
+ }
213794
213819
  console.info(" Generating package.json...");
213795
213820
  const cleanedPkg = await cleanPackageJSON(pkg, mainEntry, options, cwd, distDir);
213796
213821
  const exportsResult = await generateExports(entries, mainEntry, options, pkg.exports, distDir, allBinEntries);
213797
213822
  cleanedPkg.exports = fixExportsForDist(exportsResult.exports);
213823
+ for (const dtsFile of ambientDtsFiles) {
213824
+ const baseName = Path3.basename(dtsFile, ".d.ts");
213825
+ const exportKey = `./${baseName}.d.ts`;
213826
+ if (!cleanedPkg.exports[exportKey]) {
213827
+ cleanedPkg.exports[exportKey] = `./src/${dtsFile}`;
213828
+ }
213829
+ }
213798
213830
  if (exportsResult.staleExports.length > 0) {
213799
213831
  console.warn(`\u26A0\uFE0F WARNING: Found ${exportsResult.staleExports.length} stale export(s) pointing to missing src/ files:`);
213800
213832
  for (const staleExport of exportsResult.staleExports) {
@@ -213827,16 +213859,12 @@ async function build2(cwd, save = false) {
213827
213859
  await FS3.copyFile(srcPath, Path3.join(distDir, file));
213828
213860
  }
213829
213861
  }
213830
- if (await fileExists(srcDir)) {
213831
- const srcFiles = await FS3.readdir(srcDir);
213832
- const ambientDtsFiles = srcFiles.filter((f) => f.endsWith(".d.ts"));
213833
- if (ambientDtsFiles.length > 0) {
213834
- console.info(` Copying ${ambientDtsFiles.length} ambient .d.ts file(s)...`);
213835
- for (const dtsFile of ambientDtsFiles) {
213836
- const srcPath = Path3.join(srcDir, dtsFile);
213837
- const destPath = Path3.join(distSrcDir, dtsFile);
213838
- await FS3.copyFile(srcPath, destPath);
213839
- }
213862
+ if (ambientDtsFiles.length > 0) {
213863
+ console.info(` Copying ${ambientDtsFiles.length} ambient .d.ts file(s)...`);
213864
+ for (const dtsFile of ambientDtsFiles) {
213865
+ const srcPath = Path3.join(srcDir, dtsFile);
213866
+ const destPath = Path3.join(distSrcDir, dtsFile);
213867
+ await FS3.copyFile(srcPath, destPath);
213840
213868
  }
213841
213869
  }
213842
213870
  const commonFiles = ["README.md", "LICENSE", "CHANGELOG.md", "COPYING", "AUTHORS"];
package/src/libuild.js CHANGED
@@ -181,6 +181,7 @@ ${diagnostics}`,
181
181
  });
182
182
  }
183
183
  await addTripleSlashReferences(tsFiles, options.outDir);
184
+ await addAmbientReferences(tsFiles, options.outDir, options.rootDir);
184
185
  });
185
186
  }
186
187
  };
@@ -215,6 +216,29 @@ ${content}`;
215
216
  await FS2.writeFile(jsPath, modifiedContent);
216
217
  }
217
218
  }
219
+ async function addAmbientReferences(tsFiles, outDir, rootDir) {
220
+ let ambientFiles = [];
221
+ try {
222
+ const files = await FS2.readdir(rootDir);
223
+ ambientFiles = files.filter((f) => f.endsWith(".d.ts"));
224
+ } catch {
225
+ return;
226
+ }
227
+ if (ambientFiles.length === 0)
228
+ return;
229
+ for (const tsFile of tsFiles) {
230
+ const baseName = Path2.basename(tsFile, Path2.extname(tsFile));
231
+ const dtsPath = Path2.join(outDir, `${baseName}.d.ts`);
232
+ const dtsExists = await FS2.access(dtsPath).then(() => true).catch(() => false);
233
+ if (!dtsExists)
234
+ continue;
235
+ const content = await FS2.readFile(dtsPath, "utf-8");
236
+ const references = ambientFiles.map((ambientFile) => `/// <reference path="./${ambientFile}" />`).join("\n");
237
+ const modifiedContent = `${references}
238
+ ${content}`;
239
+ await FS2.writeFile(dtsPath, modifiedContent);
240
+ }
241
+ }
218
242
 
219
243
  // src/libuild.ts
220
244
  function generateRuntimeBanner(pkg) {
@@ -784,18 +808,14 @@ async function resolveWorkspaceVersion(packageName, workspaceSpec, cwd) {
784
808
  `./${packageBaseName}/package.json`
785
809
  ];
786
810
  for (const pkgPath of possiblePaths) {
787
- try {
788
- const resolvedPath = Path3.resolve(cwd, pkgPath);
789
- if (await fileExists(resolvedPath)) {
790
- const pkgContent = await FS3.readFile(resolvedPath, "utf-8");
791
- const pkgJson = JSON.parse(pkgContent);
792
- if (pkgJson.name === packageName) {
793
- console.info(` Resolved workspace:* dependency "${packageName}" to ^${pkgJson.version}`);
794
- return `^${pkgJson.version}`;
795
- }
811
+ const resolvedPath = Path3.resolve(cwd, pkgPath);
812
+ if (await fileExists(resolvedPath)) {
813
+ const pkgContent = await FS3.readFile(resolvedPath, "utf-8");
814
+ const pkgJson = JSON.parse(pkgContent);
815
+ if (pkgJson.name === packageName) {
816
+ console.info(` Resolved workspace:* dependency "${packageName}" to ^${pkgJson.version}`);
817
+ return `^${pkgJson.version}`;
796
818
  }
797
- } catch {
798
- continue;
799
819
  }
800
820
  }
801
821
  console.warn(`\u26A0\uFE0F WARNING: Could not resolve workspace dependency "${packageName}" - keeping as workspace:*`);
@@ -1184,10 +1204,22 @@ async function build2(cwd, save = false) {
1184
1204
  });
1185
1205
  }
1186
1206
  const autoDiscoveredFiles = [];
1207
+ const ambientDtsFiles = [];
1208
+ if (await fileExists(srcDir)) {
1209
+ const srcFiles = await FS3.readdir(srcDir);
1210
+ ambientDtsFiles.push(...srcFiles.filter((f) => f.endsWith(".d.ts")));
1211
+ }
1187
1212
  console.info(" Generating package.json...");
1188
1213
  const cleanedPkg = await cleanPackageJSON(pkg, mainEntry, options, cwd, distDir);
1189
1214
  const exportsResult = await generateExports(entries, mainEntry, options, pkg.exports, distDir, allBinEntries);
1190
1215
  cleanedPkg.exports = fixExportsForDist(exportsResult.exports);
1216
+ for (const dtsFile of ambientDtsFiles) {
1217
+ const baseName = Path3.basename(dtsFile, ".d.ts");
1218
+ const exportKey = `./${baseName}.d.ts`;
1219
+ if (!cleanedPkg.exports[exportKey]) {
1220
+ cleanedPkg.exports[exportKey] = `./src/${dtsFile}`;
1221
+ }
1222
+ }
1191
1223
  if (exportsResult.staleExports.length > 0) {
1192
1224
  console.warn(`\u26A0\uFE0F WARNING: Found ${exportsResult.staleExports.length} stale export(s) pointing to missing src/ files:`);
1193
1225
  for (const staleExport of exportsResult.staleExports) {
@@ -1220,16 +1252,12 @@ async function build2(cwd, save = false) {
1220
1252
  await FS3.copyFile(srcPath, Path3.join(distDir, file));
1221
1253
  }
1222
1254
  }
1223
- if (await fileExists(srcDir)) {
1224
- const srcFiles = await FS3.readdir(srcDir);
1225
- const ambientDtsFiles = srcFiles.filter((f) => f.endsWith(".d.ts"));
1226
- if (ambientDtsFiles.length > 0) {
1227
- console.info(` Copying ${ambientDtsFiles.length} ambient .d.ts file(s)...`);
1228
- for (const dtsFile of ambientDtsFiles) {
1229
- const srcPath = Path3.join(srcDir, dtsFile);
1230
- const destPath = Path3.join(distSrcDir, dtsFile);
1231
- await FS3.copyFile(srcPath, destPath);
1232
- }
1255
+ if (ambientDtsFiles.length > 0) {
1256
+ console.info(` Copying ${ambientDtsFiles.length} ambient .d.ts file(s)...`);
1257
+ for (const dtsFile of ambientDtsFiles) {
1258
+ const srcPath = Path3.join(srcDir, dtsFile);
1259
+ const destPath = Path3.join(distSrcDir, dtsFile);
1260
+ await FS3.copyFile(srcPath, destPath);
1233
1261
  }
1234
1262
  }
1235
1263
  const commonFiles = ["README.md", "LICENSE", "CHANGELOG.md", "COPYING", "AUTHORS"];