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/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 isDirectory = info.type === FSEVENT_TYPE_DIRECTORY;
23770
- if (isDirectory || watchedDir.has(item)) {
23771
- this.fsw._remove(parent, item, isDirectory);
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, isDirectory) {
24553
+ _remove(directory, item, isDirectory2) {
24554
24554
  const path4 = sysPath.join(directory, item);
24555
24555
  const fullPath = sysPath.resolve(path4);
24556
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path4) || this._watched.has(fullPath);
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 (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
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 = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
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
- const file = Bun.file(filePath);
26016
- return await file.exists();
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 ensureDir(dirPath) {
26046
+ async function createDir(dirPath) {
26034
26047
  try {
26035
- await Bun.write(`${dirPath}/.gitkeep`, "");
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
- const content = await sourceFile.arrayBuffer();
26042
- await Bun.write(targetPath, content);
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
- if (!postcssConfigExists) {
30796
- await fs2.promises.copyFile(inputPath, outputPath);
30797
- if (verbose)
30798
- console.log("Copied CSS without PostCSS config");
30799
- return;
30800
- }
30801
- const runPostCSS = (configPathToUse) => {
30802
- return new Promise((resolve, reject) => {
30803
- const args = ["postcss", inputPath, "-o", outputPath];
30804
- if (configPathToUse && fs2.existsSync(configPathToUse)) {
30805
- args.push("--config", configPathToUse);
30806
- }
30807
- const postcss = spawn("bunx", args, {
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
- let errorOutput = "";
30812
- if (!verbose) {
30813
- postcss.stderr?.on("data", (data) => {
30814
- errorOutput += data.toString();
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
- postcss.on("close", async (code) => {
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
- await runPostCSS(postcssConfigPath);
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
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
- return ` <item>
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
- <description><![CDATA[${post.excerpt}]]></description>
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
- const rssContent = `<?xml version="1.0" encoding="UTF-8"?>
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
- <atom:link href="${config.baseUrl}/feed.xml" rel="self" type="application/rss+xml" />
31235
- <lastBuildDate>${this.formatRSSDate(this.getPacificDate(new Date).toISOString())}</lastBuildDate>
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>`;
@@ -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.5.3",
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.2.21",
87
+ "bun": ">=1.3.0",
88
88
  "node": ">=18.0.0"
89
89
  },
90
90
  "engineStrict": true,