bunki 0.5.3 → 0.6.1
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/README.md +133 -513
- package/dist/cli.js +172 -128
- package/dist/index.js +133 -96
- package/dist/site-generator.d.ts +8 -0
- package/dist/types.d.ts +10 -0
- package/dist/utils/css-processor.d.ts +2 -1
- package/dist/utils/file-utils.d.ts +140 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -23766,9 +23766,9 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
23766
23766
|
if (this.fsw.closed || this.checkIgnored(path4))
|
|
23767
23767
|
return;
|
|
23768
23768
|
if (event === EV_UNLINK) {
|
|
23769
|
-
const
|
|
23770
|
-
if (
|
|
23771
|
-
this.fsw._remove(parent, item,
|
|
23769
|
+
const isDirectory2 = info.type === FSEVENT_TYPE_DIRECTORY;
|
|
23770
|
+
if (isDirectory2 || watchedDir.has(item)) {
|
|
23771
|
+
this.fsw._remove(parent, item, isDirectory2);
|
|
23772
23772
|
}
|
|
23773
23773
|
} else {
|
|
23774
23774
|
if (event === EV_ADD) {
|
|
@@ -24550,13 +24550,13 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
24550
24550
|
const it = Number.parseInt(st.toString(8)[0], 10);
|
|
24551
24551
|
return Boolean(4 & it);
|
|
24552
24552
|
}
|
|
24553
|
-
_remove(directory, item,
|
|
24553
|
+
_remove(directory, item, isDirectory2) {
|
|
24554
24554
|
const path4 = sysPath.join(directory, item);
|
|
24555
24555
|
const fullPath = sysPath.resolve(path4);
|
|
24556
|
-
|
|
24556
|
+
isDirectory2 = isDirectory2 != null ? isDirectory2 : this._watched.has(path4) || this._watched.has(fullPath);
|
|
24557
24557
|
if (!this._throttle("remove", path4, 100))
|
|
24558
24558
|
return;
|
|
24559
|
-
if (!
|
|
24559
|
+
if (!isDirectory2 && !this.options.useFsEvents && this._watched.size === 1) {
|
|
24560
24560
|
this.add(directory, item, true);
|
|
24561
24561
|
}
|
|
24562
24562
|
const wp = this._getWatchedDir(path4);
|
|
@@ -24578,7 +24578,7 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
24578
24578
|
}
|
|
24579
24579
|
this._watched.delete(path4);
|
|
24580
24580
|
this._watched.delete(fullPath);
|
|
24581
|
-
const eventName =
|
|
24581
|
+
const eventName = isDirectory2 ? EV_UNLINK_DIR : EV_UNLINK;
|
|
24582
24582
|
if (wasTracked && !this._isIgnored(path4))
|
|
24583
24583
|
this._emit(eventName, path4);
|
|
24584
24584
|
if (!this.options.useFsEvents) {
|
|
@@ -26000,6 +26000,7 @@ var require_slugify = __commonJS((exports, module) => {
|
|
|
26000
26000
|
// src/utils/file-utils.ts
|
|
26001
26001
|
var {Glob } = globalThis.Bun;
|
|
26002
26002
|
import path from "path";
|
|
26003
|
+
import { mkdir } from "fs/promises";
|
|
26003
26004
|
async function findFilesByPattern(pattern, directory, absolute = true) {
|
|
26004
26005
|
const glob = new Glob(pattern);
|
|
26005
26006
|
const files = [];
|
|
@@ -26012,8 +26013,20 @@ async function findFilesByPattern(pattern, directory, absolute = true) {
|
|
|
26012
26013
|
return files;
|
|
26013
26014
|
}
|
|
26014
26015
|
async function fileExists(filePath) {
|
|
26015
|
-
|
|
26016
|
-
|
|
26016
|
+
try {
|
|
26017
|
+
const file = Bun.file(filePath);
|
|
26018
|
+
return await file.exists();
|
|
26019
|
+
} catch {
|
|
26020
|
+
return false;
|
|
26021
|
+
}
|
|
26022
|
+
}
|
|
26023
|
+
async function isDirectory(dirPath) {
|
|
26024
|
+
try {
|
|
26025
|
+
const stat = await Bun.file(dirPath).stat();
|
|
26026
|
+
return stat?.isDirectory() ?? false;
|
|
26027
|
+
} catch {
|
|
26028
|
+
return false;
|
|
26029
|
+
}
|
|
26017
26030
|
}
|
|
26018
26031
|
async function readFileAsText(filePath) {
|
|
26019
26032
|
try {
|
|
@@ -26030,18 +26043,33 @@ async function readFileAsText(filePath) {
|
|
|
26030
26043
|
function getBaseFilename(filePath, extension = ".md") {
|
|
26031
26044
|
return path.basename(filePath, extension);
|
|
26032
26045
|
}
|
|
26033
|
-
async function
|
|
26046
|
+
async function createDir(dirPath) {
|
|
26034
26047
|
try {
|
|
26035
|
-
await
|
|
26036
|
-
} catch (error) {
|
|
26048
|
+
await mkdir(dirPath, { recursive: true });
|
|
26049
|
+
} catch (error) {
|
|
26050
|
+
if (await isDirectory(dirPath)) {
|
|
26051
|
+
return;
|
|
26052
|
+
}
|
|
26053
|
+
if (await fileExists(dirPath)) {
|
|
26054
|
+
throw new Error(`Path exists but is not a directory: ${dirPath}`);
|
|
26055
|
+
}
|
|
26056
|
+
console.error(`Error creating directory ${dirPath}:`, error);
|
|
26057
|
+
throw error;
|
|
26058
|
+
}
|
|
26059
|
+
}
|
|
26060
|
+
async function ensureDir(dirPath) {
|
|
26061
|
+
return createDir(dirPath);
|
|
26037
26062
|
}
|
|
26038
26063
|
async function copyFile(sourcePath, targetPath) {
|
|
26039
26064
|
try {
|
|
26040
26065
|
const sourceFile = Bun.file(sourcePath);
|
|
26041
|
-
|
|
26042
|
-
|
|
26066
|
+
if (!await sourceFile.exists()) {
|
|
26067
|
+
throw new Error(`Source file does not exist: ${sourcePath}`);
|
|
26068
|
+
}
|
|
26069
|
+
await Bun.write(targetPath, sourceFile);
|
|
26043
26070
|
} catch (error) {
|
|
26044
26071
|
console.error(`Error copying file from ${sourcePath} to ${targetPath}:`, error);
|
|
26072
|
+
throw error;
|
|
26045
26073
|
}
|
|
26046
26074
|
}
|
|
26047
26075
|
|
|
@@ -30576,7 +30604,7 @@ function getDefaultConfig() {
|
|
|
30576
30604
|
return base;
|
|
30577
30605
|
}
|
|
30578
30606
|
async function createDefaultConfig(configPath = DEFAULT_CONFIG_FILE) {
|
|
30579
|
-
if (await configExists()) {
|
|
30607
|
+
if (await configExists(configPath)) {
|
|
30580
30608
|
console.log(`Config file already exists`);
|
|
30581
30609
|
return false;
|
|
30582
30610
|
}
|
|
@@ -30775,15 +30803,6 @@ async function processCSS(options2) {
|
|
|
30775
30803
|
} catch (error) {
|
|
30776
30804
|
throw new Error(`CSS input file not found: ${inputPath}`);
|
|
30777
30805
|
}
|
|
30778
|
-
let postcssConfigExists = false;
|
|
30779
|
-
try {
|
|
30780
|
-
await fs2.promises.access(postcssConfigPath);
|
|
30781
|
-
postcssConfigExists = true;
|
|
30782
|
-
} catch (error) {
|
|
30783
|
-
if (verbose) {
|
|
30784
|
-
console.log(`PostCSS config not found at ${postcssConfigPath}, will fallback to simple copy`);
|
|
30785
|
-
}
|
|
30786
|
-
}
|
|
30787
30806
|
const outputDirPath = path4.dirname(outputPath);
|
|
30788
30807
|
await fs2.promises.mkdir(outputDirPath, { recursive: true });
|
|
30789
30808
|
if (verbose) {
|
|
@@ -30792,71 +30811,33 @@ async function processCSS(options2) {
|
|
|
30792
30811
|
console.log(`Output: ${outputPath}`);
|
|
30793
30812
|
console.log(`Config: ${postcssConfigPath}`);
|
|
30794
30813
|
}
|
|
30795
|
-
|
|
30796
|
-
|
|
30797
|
-
|
|
30798
|
-
|
|
30799
|
-
|
|
30800
|
-
|
|
30801
|
-
|
|
30802
|
-
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
30809
|
-
cwd: projectRoot
|
|
30814
|
+
await runPostCSS(inputPath, outputPath, postcssConfigPath, projectRoot, verbose);
|
|
30815
|
+
}
|
|
30816
|
+
function runPostCSS(inputPath, outputPath, configPath, projectRoot, verbose) {
|
|
30817
|
+
return new Promise((resolve, reject) => {
|
|
30818
|
+
const args = ["postcss", inputPath, "-o", outputPath, "--config", configPath];
|
|
30819
|
+
const postcss = spawn("bunx", args, {
|
|
30820
|
+
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
30821
|
+
cwd: projectRoot
|
|
30822
|
+
});
|
|
30823
|
+
let errorOutput = "";
|
|
30824
|
+
if (!verbose) {
|
|
30825
|
+
postcss.stderr?.on("data", (data) => {
|
|
30826
|
+
errorOutput += data.toString();
|
|
30810
30827
|
});
|
|
30811
|
-
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
30828
|
+
}
|
|
30829
|
+
postcss.on("close", (code) => {
|
|
30830
|
+
if (code === 0) {
|
|
30831
|
+
if (verbose)
|
|
30832
|
+
console.log("\u2705 CSS build completed successfully!");
|
|
30833
|
+
return resolve();
|
|
30816
30834
|
}
|
|
30817
|
-
|
|
30818
|
-
if (code === 0) {
|
|
30819
|
-
if (verbose)
|
|
30820
|
-
console.log("\u2705 CSS build completed successfully!");
|
|
30821
|
-
return resolve();
|
|
30822
|
-
}
|
|
30823
|
-
if (/module is not defined in ES module scope/i.test(errorOutput) && configPathToUse.endsWith(".js")) {
|
|
30824
|
-
const cjsPath = configPathToUse.replace(/\.js$/, ".cjs");
|
|
30825
|
-
try {
|
|
30826
|
-
if (!fs2.existsSync(cjsPath)) {
|
|
30827
|
-
const original = await fs2.promises.readFile(configPathToUse, "utf-8");
|
|
30828
|
-
await fs2.promises.writeFile(cjsPath, original, "utf-8");
|
|
30829
|
-
if (verbose) {
|
|
30830
|
-
console.log(`Retrying PostCSS with converted CommonJS config at ${cjsPath}`);
|
|
30831
|
-
}
|
|
30832
|
-
}
|
|
30833
|
-
return resolve(runPostCSS(cjsPath));
|
|
30834
|
-
} catch (e) {
|
|
30835
|
-
if (verbose)
|
|
30836
|
-
console.warn("CJS fallback failed, copying CSS.");
|
|
30837
|
-
await fs2.promises.copyFile(inputPath, outputPath);
|
|
30838
|
-
return resolve();
|
|
30839
|
-
}
|
|
30840
|
-
}
|
|
30841
|
-
if (verbose) {
|
|
30842
|
-
console.warn(`PostCSS failed (code ${code}). Falling back to simple copy. Error: ${errorOutput.trim()}`);
|
|
30843
|
-
}
|
|
30844
|
-
try {
|
|
30845
|
-
await fs2.promises.copyFile(inputPath, outputPath);
|
|
30846
|
-
resolve();
|
|
30847
|
-
} catch (copyErr) {
|
|
30848
|
-
reject(new Error(`CSS build failed with code ${code} and fallback copy also failed: ${copyErr.message}`));
|
|
30849
|
-
}
|
|
30850
|
-
});
|
|
30851
|
-
postcss.on("error", (err) => {
|
|
30852
|
-
if (verbose) {
|
|
30853
|
-
console.warn(`Failed to start PostCSS process (${err.message}). Falling back to copy.`);
|
|
30854
|
-
}
|
|
30855
|
-
fs2.promises.copyFile(inputPath, outputPath).then(() => resolve()).catch((copyErr) => reject(new Error(`Failed to start PostCSS and fallback copy failed: ${copyErr.message}`)));
|
|
30856
|
-
});
|
|
30835
|
+
reject(new Error(`PostCSS failed with exit code ${code}: ${errorOutput.trim()}`));
|
|
30857
30836
|
});
|
|
30858
|
-
|
|
30859
|
-
|
|
30837
|
+
postcss.on("error", (err) => {
|
|
30838
|
+
reject(new Error(`Failed to start PostCSS: ${err.message}`));
|
|
30839
|
+
});
|
|
30840
|
+
});
|
|
30860
30841
|
}
|
|
30861
30842
|
function getDefaultCSSConfig() {
|
|
30862
30843
|
return {
|
|
@@ -31210,29 +31191,85 @@ class SiteGenerator {
|
|
|
31210
31191
|
console.log("Copied public files to site (including extensionless & dotfiles)");
|
|
31211
31192
|
}
|
|
31212
31193
|
}
|
|
31194
|
+
extractFirstImageUrl(html) {
|
|
31195
|
+
const imgRegex = /<img[^>]+src=["']([^"']+)["']/;
|
|
31196
|
+
const match = html.match(imgRegex);
|
|
31197
|
+
return match ? match[1] : null;
|
|
31198
|
+
}
|
|
31199
|
+
escapeXml(text) {
|
|
31200
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
31201
|
+
}
|
|
31213
31202
|
async generateRSSFeed() {
|
|
31214
31203
|
const posts = this.site.posts.slice(0, 15);
|
|
31215
31204
|
const config = this.options.config;
|
|
31205
|
+
const now = this.getPacificDate(new Date);
|
|
31206
|
+
const latestPostDate = posts.length > 0 ? posts[0].date : now.toISOString();
|
|
31207
|
+
const lastBuildDate = this.formatRSSDate(latestPostDate);
|
|
31216
31208
|
const rssItems = posts.map((post) => {
|
|
31217
31209
|
const postUrl = `${config.baseUrl}${post.url}`;
|
|
31218
31210
|
const pubDate = this.formatRSSDate(post.date);
|
|
31219
|
-
|
|
31211
|
+
const featuredImage = this.extractFirstImageUrl(post.html);
|
|
31212
|
+
const categoryTags = post.tags.map((tag) => ` <category>${this.escapeXml(tag)}</category>`).join(`
|
|
31213
|
+
`);
|
|
31214
|
+
let itemXml = ` <item>
|
|
31220
31215
|
<title><![CDATA[${post.title}]]></title>
|
|
31221
31216
|
<link>${postUrl}</link>
|
|
31222
|
-
<guid>${postUrl}</guid>
|
|
31223
|
-
<pubDate>${pubDate}</pubDate
|
|
31224
|
-
|
|
31217
|
+
<guid isPermaLink="true">${postUrl}</guid>
|
|
31218
|
+
<pubDate>${pubDate}</pubDate>`;
|
|
31219
|
+
if (config.authorEmail && config.authorName) {
|
|
31220
|
+
itemXml += `
|
|
31221
|
+
<author>${config.authorEmail} (${config.authorName})</author>`;
|
|
31222
|
+
} else if (config.authorEmail) {
|
|
31223
|
+
itemXml += `
|
|
31224
|
+
<author>${config.authorEmail}</author>`;
|
|
31225
|
+
}
|
|
31226
|
+
itemXml += `
|
|
31227
|
+
<description><![CDATA[${post.excerpt}]]></description>`;
|
|
31228
|
+
if (post.tags.length > 0) {
|
|
31229
|
+
itemXml += `
|
|
31230
|
+
${categoryTags}`;
|
|
31231
|
+
}
|
|
31232
|
+
itemXml += `
|
|
31233
|
+
<content:encoded><![CDATA[${post.html}]]></content:encoded>`;
|
|
31234
|
+
if (featuredImage) {
|
|
31235
|
+
const absoluteImageUrl = featuredImage.startsWith("http") ? featuredImage : `${config.baseUrl}${featuredImage}`;
|
|
31236
|
+
itemXml += `
|
|
31237
|
+
<media:thumbnail url="${this.escapeXml(absoluteImageUrl)}" />`;
|
|
31238
|
+
}
|
|
31239
|
+
itemXml += `
|
|
31225
31240
|
</item>`;
|
|
31241
|
+
return itemXml;
|
|
31226
31242
|
}).join(`
|
|
31227
31243
|
`);
|
|
31228
|
-
|
|
31229
|
-
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
31230
|
-
<channel>
|
|
31244
|
+
let channelXml = ` <channel>
|
|
31231
31245
|
<title><![CDATA[${config.title}]]></title>
|
|
31232
|
-
<description><![CDATA[${config.description}]]></description>
|
|
31233
31246
|
<link>${config.baseUrl}</link>
|
|
31234
|
-
<
|
|
31235
|
-
|
|
31247
|
+
<description><![CDATA[${config.description}]]></description>`;
|
|
31248
|
+
const language = config.rssLanguage || "en-US";
|
|
31249
|
+
channelXml += `
|
|
31250
|
+
<language>${language}</language>`;
|
|
31251
|
+
if (config.authorEmail && config.authorName) {
|
|
31252
|
+
channelXml += `
|
|
31253
|
+
<managingEditor>${config.authorEmail} (${config.authorName})</managingEditor>`;
|
|
31254
|
+
} else if (config.authorEmail) {
|
|
31255
|
+
channelXml += `
|
|
31256
|
+
<managingEditor>${config.authorEmail}</managingEditor>`;
|
|
31257
|
+
}
|
|
31258
|
+
if (config.webMaster) {
|
|
31259
|
+
channelXml += `
|
|
31260
|
+
<webMaster>${config.webMaster}</webMaster>`;
|
|
31261
|
+
}
|
|
31262
|
+
if (config.copyright) {
|
|
31263
|
+
channelXml += `
|
|
31264
|
+
<copyright><![CDATA[${config.copyright}]]></copyright>`;
|
|
31265
|
+
}
|
|
31266
|
+
channelXml += `
|
|
31267
|
+
<pubDate>${this.formatRSSDate(latestPostDate)}</pubDate>
|
|
31268
|
+
<lastBuildDate>${lastBuildDate}</lastBuildDate>
|
|
31269
|
+
<atom:link href="${config.baseUrl}/feed.xml" rel="self" type="application/rss+xml" />`;
|
|
31270
|
+
const rssContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
31271
|
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/">
|
|
31272
|
+
${channelXml}
|
|
31236
31273
|
${rssItems}
|
|
31237
31274
|
</channel>
|
|
31238
31275
|
</rss>`;
|
package/dist/site-generator.d.ts
CHANGED
|
@@ -16,6 +16,14 @@ export declare class SiteGenerator {
|
|
|
16
16
|
private generateStylesheet;
|
|
17
17
|
private fallbackCSSGeneration;
|
|
18
18
|
private copyStaticAssets;
|
|
19
|
+
/**
|
|
20
|
+
* Extract the first image URL from HTML content
|
|
21
|
+
*/
|
|
22
|
+
private extractFirstImageUrl;
|
|
23
|
+
/**
|
|
24
|
+
* Escape special characters in XML text to prevent CDATA issues
|
|
25
|
+
*/
|
|
26
|
+
private escapeXml;
|
|
19
27
|
private generateRSSFeed;
|
|
20
28
|
private generateSitemap;
|
|
21
29
|
private generateSitemapIndex;
|
package/dist/types.d.ts
CHANGED
|
@@ -58,6 +58,16 @@ export interface SiteConfig {
|
|
|
58
58
|
maxTagsOnHomepage?: number;
|
|
59
59
|
/** Optional list of domains to exclude from nofollow attribute. Links to these domains will have follow attribute. */
|
|
60
60
|
noFollowExceptions?: string[];
|
|
61
|
+
/** RSS feed language code (default: en-US) */
|
|
62
|
+
rssLanguage?: string;
|
|
63
|
+
/** Author name for RSS feed (used in managingEditor field) */
|
|
64
|
+
authorName?: string;
|
|
65
|
+
/** Author email for RSS feed (used in managingEditor field) */
|
|
66
|
+
authorEmail?: string;
|
|
67
|
+
/** Web master email for RSS feed (optional) */
|
|
68
|
+
webMaster?: string;
|
|
69
|
+
/** Copyright statement for RSS feed (e.g., "Copyright © 2025 Your Site Name") */
|
|
70
|
+
copyright?: string;
|
|
61
71
|
/** Additional custom configuration options */
|
|
62
72
|
[key: string]: any;
|
|
63
73
|
}
|
|
@@ -10,7 +10,8 @@ export interface CSSProcessorOptions {
|
|
|
10
10
|
verbose?: boolean;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Process CSS using PostCSS
|
|
13
|
+
* Process CSS using PostCSS directly
|
|
14
|
+
* Throws on error - no fallback
|
|
14
15
|
*/
|
|
15
16
|
export declare function processCSS(options: CSSProcessorOptions): Promise<void>;
|
|
16
17
|
/**
|
|
@@ -1,6 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find files matching a glob pattern in a directory
|
|
3
|
+
* @param pattern - Glob pattern to match (e.g., "*.md", "**\/\*.ts")
|
|
4
|
+
* @param directory - Directory to search in
|
|
5
|
+
* @param absolute - Return absolute paths (default: true)
|
|
6
|
+
* @returns Array of matching file paths
|
|
7
|
+
*/
|
|
1
8
|
export declare function findFilesByPattern(pattern: string, directory: string, absolute?: boolean): Promise<string[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a file exists using Bun's native API
|
|
11
|
+
*
|
|
12
|
+
* Note: BunFile.exists() only checks for files, not directories.
|
|
13
|
+
* Use isDirectory() to check if a path is a directory.
|
|
14
|
+
*
|
|
15
|
+
* @param filePath - Path to file
|
|
16
|
+
* @returns True if file exists, false if not or if path is a directory
|
|
17
|
+
*
|
|
18
|
+
* @see isDirectory - Use this to check if a path is a directory
|
|
19
|
+
*/
|
|
2
20
|
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a path is a file (not a directory)
|
|
23
|
+
* @param filePath - Path to check
|
|
24
|
+
* @returns True if path is a file
|
|
25
|
+
*/
|
|
26
|
+
export declare function isFile(filePath: string): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a path is a directory
|
|
29
|
+
* @param dirPath - Path to check
|
|
30
|
+
* @returns True if path is a directory
|
|
31
|
+
*/
|
|
32
|
+
export declare function isDirectory(dirPath: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Read file as text using Bun's native API
|
|
35
|
+
* @param filePath - Path to file
|
|
36
|
+
* @returns File contents or null if file doesn't exist
|
|
37
|
+
*/
|
|
3
38
|
export declare function readFileAsText(filePath: string): Promise<string | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Read file as binary buffer using Bun's native API
|
|
41
|
+
* @param filePath - Path to file
|
|
42
|
+
* @returns File contents as Uint8Array or null if file doesn't exist
|
|
43
|
+
*/
|
|
44
|
+
export declare function readFileAsBuffer(filePath: string): Promise<Uint8Array | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Write text to a file
|
|
47
|
+
* @param filePath - Path to file
|
|
48
|
+
* @param content - Text content to write
|
|
49
|
+
*/
|
|
50
|
+
export declare function writeFile(filePath: string, content: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Write binary data to a file
|
|
53
|
+
* @param filePath - Path to file
|
|
54
|
+
* @param data - Binary data to write
|
|
55
|
+
*/
|
|
56
|
+
export declare function writeFileBuffer(filePath: string, data: Uint8Array | ArrayBuffer): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Get base filename without extension
|
|
59
|
+
* @param filePath - Path to file
|
|
60
|
+
* @param extension - Extension to remove (default: ".md")
|
|
61
|
+
* @returns Base filename
|
|
62
|
+
*/
|
|
4
63
|
export declare function getBaseFilename(filePath: string, extension?: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Create a directory (creates parent directories if needed)
|
|
66
|
+
* @param dirPath - Path to create
|
|
67
|
+
*/
|
|
68
|
+
export declare function createDir(dirPath: string): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Ensure a directory exists (alias for createDir)
|
|
71
|
+
* @param dirPath - Path to ensure exists
|
|
72
|
+
*/
|
|
5
73
|
export declare function ensureDir(dirPath: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Copy a file from source to target using Bun's zero-copy file-to-file operation
|
|
76
|
+
*
|
|
77
|
+
* This uses Bun.write(target, BunFile) which performs a zero-copy operation at the kernel level.
|
|
78
|
+
* Similar to `cat source > target` but much faster than reading into memory and writing back.
|
|
79
|
+
*
|
|
80
|
+
* @param sourcePath - Source file path
|
|
81
|
+
* @param targetPath - Target file path
|
|
82
|
+
*/
|
|
6
83
|
export declare function copyFile(sourcePath: string, targetPath: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Delete a file using Bun's native API
|
|
86
|
+
* @param filePath - Path to file
|
|
87
|
+
*/
|
|
88
|
+
export declare function deleteFile(filePath: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Get file size in bytes
|
|
91
|
+
* @param filePath - Path to file
|
|
92
|
+
* @returns File size or null if file doesn't exist
|
|
93
|
+
*/
|
|
94
|
+
export declare function getFileSize(filePath: string): Promise<number | null>;
|
|
95
|
+
/**
|
|
96
|
+
* Get file modification time
|
|
97
|
+
* @param filePath - Path to file
|
|
98
|
+
* @returns Modification time as number (ms since epoch) or null if file doesn't exist
|
|
99
|
+
*/
|
|
100
|
+
export declare function getFileMtime(filePath: string): Promise<number | null>;
|
|
101
|
+
/**
|
|
102
|
+
* List files in a directory
|
|
103
|
+
* @param dirPath - Directory path
|
|
104
|
+
* @param recursive - Include subdirectories (default: false)
|
|
105
|
+
* @returns Array of file paths
|
|
106
|
+
*/
|
|
107
|
+
export declare function listDir(dirPath: string, recursive?: boolean): Promise<string[]>;
|
|
108
|
+
/**
|
|
109
|
+
* Create a buffered file writer for incremental writes
|
|
110
|
+
*
|
|
111
|
+
* Useful for streaming writes or building large files incrementally without loading
|
|
112
|
+
* everything into memory. Uses a buffered sink with configurable watermark.
|
|
113
|
+
*
|
|
114
|
+
* Zero-copy streaming to disk with backpressure handling.
|
|
115
|
+
*
|
|
116
|
+
* @param filePath - Path to file
|
|
117
|
+
* @param highWaterMark - Buffer size in bytes (default: 1MB)
|
|
118
|
+
* @returns Bun file writer object with write(), flush(), and end() methods
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const writer = createFileWriter("./output.txt");
|
|
123
|
+
* writer.write("Line 1\n");
|
|
124
|
+
* writer.write("Line 2\n");
|
|
125
|
+
* writer.write("Line 3\n");
|
|
126
|
+
* await writer.flush();
|
|
127
|
+
* await writer.end();
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function createFileWriter(filePath: string, highWaterMark?: number): Bun.FileSink;
|
|
131
|
+
/**
|
|
132
|
+
* Write a file to stdout using zero-copy streaming
|
|
133
|
+
*
|
|
134
|
+
* Similar to `cat file.txt` command. Uses Bun's zero-copy mechanism to stream
|
|
135
|
+
* the file content directly to stdout without loading into memory.
|
|
136
|
+
*
|
|
137
|
+
* @param filePath - Path to file to output
|
|
138
|
+
* @returns Promise that resolves when file is written to stdout
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* // CLI tool: output file contents
|
|
143
|
+
* await writeToStdout("./dist/index.html");
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare function writeToStdout(filePath: string): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bunki",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "An opinionated static site generator built with Bun featuring PostCSS integration and modern web development workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"README.md"
|
|
85
85
|
],
|
|
86
86
|
"engines": {
|
|
87
|
-
"bun": ">=1.
|
|
87
|
+
"bun": ">=1.3.0",
|
|
88
88
|
"node": ">=18.0.0"
|
|
89
89
|
},
|
|
90
90
|
"engineStrict": true,
|