bunup 0.9.1 → 0.9.3

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 CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  <!-- markdownlint-disable-next-line no-alt-text -->
8
8
 
9
+
9
10
  ![Logo](https://raw.githubusercontent.com/arshad-yaseen/bunup/refs/heads/main/docs/public/logo.svg)
10
11
 
11
12
  ![Bunup](https://raw.githubusercontent.com/arshad-yaseen/bunup/refs/heads/main/assets/bunup-title.svg)
@@ -38,3 +39,10 @@ To get started, visit the [documentation](https://bunup.dev).
38
39
  For guidelines on contributing, please read the [contributing guide](../../CONTRIBUTING.md).
39
40
 
40
41
  We welcome contributions from the community to enhance Bunup's capabilities and make it even more powerful.
42
+
43
+ ![Sponsors](https://cdn.jsdelivr.net/gh/arshad-yaseen/static/sponsors.svg)
44
+
45
+ <div align="center">
46
+
47
+ ![______ 🐈‍⬛ _____________](assets/cat-footer.svg)
48
+ </div>
package/dist/cli/index.js CHANGED
@@ -2,12 +2,9 @@
2
2
  // @bun
3
3
  import {
4
4
  build,
5
- createBuildOptions
6
- } from "../shared/chunk-f8vey9gb.js";
7
- import"../shared/chunk-g6c05fxa.js";
8
- import {
5
+ createBuildOptions,
9
6
  processLoadedConfigs
10
- } from "../shared/chunk-295440tx.js";
7
+ } from "../shared/chunk-7vsq500x.js";
11
8
  import {
12
9
  BunupCLIError,
13
10
  BunupWatchError,
@@ -21,14 +18,13 @@ import {
21
18
  logger,
22
19
  parseErrorMessage,
23
20
  setSilent
24
- } from "../shared/chunk-sfjfqxjy.js";
21
+ } from "../shared/chunk-yrc9t3ye.js";
25
22
 
26
23
  // src/cli/index.ts
27
24
  import { loadConfig } from "coffi";
28
25
  import pc3 from "picocolors";
29
- import { exec } from "tinyexec";
30
26
  // package.json
31
- var version = "0.9.1";
27
+ var version = "0.9.3";
32
28
 
33
29
  // src/watch.ts
34
30
  import path from "path";
@@ -325,13 +321,6 @@ var OPTION_DEFINITIONS = {
325
321
  type: "string",
326
322
  category: "build"
327
323
  },
328
- onSuccess: {
329
- flags: ["onSuccess"],
330
- handler: handlers.string("onSuccess"),
331
- description: "Command to execute after a successful build",
332
- type: "string",
333
- category: "development"
334
- },
335
324
  filter: {
336
325
  flags: ["filter"],
337
326
  handler: handlers.array("filter"),
@@ -367,6 +356,13 @@ var OPTION_DEFINITIONS = {
367
356
  type: "string|boolean",
368
357
  category: "development"
369
358
  },
359
+ onSuccess: {
360
+ flags: ["onSuccess"],
361
+ handler: handlers.string("onSuccess"),
362
+ description: "Command to run after the build process completes",
363
+ type: "string",
364
+ category: "utility"
365
+ },
370
366
  help: {
371
367
  flags: ["h", "help"],
372
368
  handler: handlers.showHelp,
@@ -481,16 +477,6 @@ var parseCliOptions = (argv) => {
481
477
  // src/cli/index.ts
482
478
  async function main(args = Bun.argv.slice(2)) {
483
479
  const cliOptions = parseCliOptions(args);
484
- if (cliOptions.new) {
485
- const { newProject } = await import("../shared/chunk-j0x1xdhb.js");
486
- await newProject();
487
- return;
488
- }
489
- if (cliOptions.init) {
490
- const { init } = await import("../shared/chunk-s6wnc2s1.js");
491
- await init();
492
- return;
493
- }
494
480
  setSilent(cliOptions.silent);
495
481
  const cwd = process.cwd();
496
482
  const { config, filepath } = await loadConfig({
@@ -534,14 +520,6 @@ async function main(args = Bun.argv.slice(2)) {
534
520
  verticalSpace: true
535
521
  });
536
522
  }
537
- if (cliOptions.onSuccess) {
538
- logger.info(`Running command: ${cliOptions.onSuccess}`, {
539
- muted: true
540
- });
541
- await exec(cliOptions.onSuccess, [], {
542
- nodeOptions: { shell: true, stdio: "inherit" }
543
- });
544
- }
545
523
  if (!cliOptions.watch) {
546
524
  process.exit(process.exitCode ?? 0);
547
525
  }
@@ -549,11 +527,8 @@ async function main(args = Bun.argv.slice(2)) {
549
527
  function removeCliOnlyOptions(options) {
550
528
  return {
551
529
  ...options,
552
- onSuccess: undefined,
553
530
  config: undefined,
554
- filter: undefined,
555
- new: undefined,
556
- init: undefined
531
+ filter: undefined
557
532
  };
558
533
  }
559
534
  main().catch((error) => handleErrorAndExit(error));
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Arrayable, BuildOptions, DefineConfigItem, DefineWorkspaceItem, Plugin, WithOptional } from "./shared/chunk-25dcyfg9";
1
+ import { Arrayable, BuildOptions, DefineConfigItem, DefineWorkspaceItem, Plugin, WithOptional } from "./shared/chunk-wpey1xte";
2
2
  declare function build(partialOptions: Partial<BuildOptions>, rootDir?: string): Promise<void>;
3
3
  declare function defineConfig(options: Arrayable<DefineConfigItem>): Arrayable<DefineConfigItem>;
4
4
  declare function defineWorkspace(options: WithOptional<DefineWorkspaceItem, "config">[], sharedOptions?: DefineConfigItem): DefineWorkspaceItem[];
package/dist/index.js CHANGED
@@ -1,10 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  build
4
- } from "./shared/chunk-f8vey9gb.js";
5
- import"./shared/chunk-g6c05fxa.js";
6
- import"./shared/chunk-295440tx.js";
7
- import"./shared/chunk-sfjfqxjy.js";
4
+ } from "./shared/chunk-7vsq500x.js";
5
+ import"./shared/chunk-yrc9t3ye.js";
8
6
  // src/define.ts
9
7
  function defineConfig(options) {
10
8
  return options;
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BuildContext, BunupPlugin, MaybePromise, Plugin } from "./shared/chunk-25dcyfg9";
1
+ import { BuildContext, BunupPlugin, MaybePromise, Plugin } from "./shared/chunk-wpey1xte";
2
2
  /**
3
3
  * A plugin that copies files and directories to the output directory.
4
4
  *
package/dist/plugins.js CHANGED
@@ -1,16 +1,14 @@
1
1
  // @bun
2
- import {
3
- getPackageForPlugin
4
- } from "./shared/chunk-g6c05fxa.js";
5
2
  import {
6
3
  CSS_RE,
7
4
  JS_DTS_RE,
8
5
  JS_TS_RE,
9
6
  cleanPath,
10
7
  formatListWithAnd,
8
+ getPackageForPlugin,
11
9
  isDirectoryPath,
12
10
  logger
13
- } from "./shared/chunk-sfjfqxjy.js";
11
+ } from "./shared/chunk-yrc9t3ye.js";
14
12
 
15
13
  // src/plugins/built-in/copy.ts
16
14
  import { basename, join } from "path";
@@ -1,18 +1,11 @@
1
- import {
2
- filterBunupBunPlugins,
3
- filterBunupPlugins,
4
- runPluginBuildDoneHooks,
5
- runPluginBuildStartHooks
6
- } from "./chunk-g6c05fxa.js";
7
- import {
8
- loadPackageJson
9
- } from "./chunk-295440tx.js";
10
1
  import {
11
2
  BunupBuildError,
12
3
  BunupDTSBuildError,
13
4
  cleanOutDir,
14
5
  cleanPath,
15
6
  ensureArray,
7
+ filterBunupBunPlugins,
8
+ filterBunupPlugins,
16
9
  formatFileSize,
17
10
  getDefaultDtsExtention,
18
11
  getDefaultOutputExtension,
@@ -23,15 +16,85 @@ import {
23
16
  logTable,
24
17
  logger,
25
18
  parseErrorMessage,
19
+ runPluginBuildDoneHooks,
20
+ runPluginBuildStartHooks,
26
21
  setSilent,
27
22
  silent
28
- } from "./chunk-sfjfqxjy.js";
23
+ } from "./chunk-yrc9t3ye.js";
29
24
 
30
- // src/build.ts
25
+ // src/loaders.ts
31
26
  import path from "path";
27
+ import { loadConfig } from "coffi";
28
+ async function processLoadedConfigs(config, cwd, filter) {
29
+ return Array.isArray(config) && "root" in config[0] ? config.filter((c) => filter ? filter.includes(c.name) : true).map((c) => ({
30
+ rootDir: path.resolve(cwd, c.root),
31
+ options: addField(c.config, "name", c.name)
32
+ })) : [
33
+ {
34
+ rootDir: cwd,
35
+ options: config
36
+ }
37
+ ];
38
+ }
39
+ function addField(objectOrArray, field, value) {
40
+ return Array.isArray(objectOrArray) ? objectOrArray.map((o) => ({ ...o, [field]: value })) : { ...objectOrArray, [field]: value };
41
+ }
42
+ async function loadPackageJson(cwd = process.cwd()) {
43
+ const { config, filepath } = await loadConfig({
44
+ name: "package",
45
+ cwd,
46
+ extensions: [".json"]
47
+ });
48
+ return {
49
+ data: config,
50
+ path: filepath
51
+ };
52
+ }
53
+
54
+ // src/build.ts
55
+ import path2 from "path";
32
56
  import pc2 from "picocolors";
33
57
  import { generateDts, logIsolatedDeclarationErrors } from "typeroll";
34
58
 
59
+ // src/helpers/on-success.ts
60
+ import { exec } from "tinyexec";
61
+ import treeKill from "tree-kill";
62
+ async function executeOnSuccess(onSuccess, options, signal) {
63
+ if (typeof onSuccess === "function") {
64
+ const result = await onSuccess(options);
65
+ if (typeof result === "function") {
66
+ signal.addEventListener("abort", () => {
67
+ result();
68
+ });
69
+ }
70
+ } else {
71
+ const command = typeof onSuccess === "string" ? onSuccess : onSuccess.cmd;
72
+ const spawnOptions = typeof onSuccess === "object" && "options" in onSuccess ? onSuccess.options : {};
73
+ logger.info(`Running command: ${command}`, {
74
+ muted: true
75
+ });
76
+ const proc = exec(command, [], {
77
+ timeout: spawnOptions?.timeout,
78
+ nodeOptions: {
79
+ shell: true,
80
+ stdio: "inherit",
81
+ env: spawnOptions?.env,
82
+ cwd: spawnOptions?.cwd
83
+ }
84
+ });
85
+ proc.then(({ exitCode }) => {
86
+ if (exitCode) {
87
+ process.exitCode = exitCode;
88
+ }
89
+ });
90
+ signal.addEventListener("abort", () => {
91
+ if (typeof proc.pid === "number") {
92
+ treeKill(proc.pid, spawnOptions?.killSignal ?? "SIGTERM");
93
+ }
94
+ });
95
+ }
96
+ }
97
+
35
98
  // src/plugins/internal/report.ts
36
99
  import pc from "picocolors";
37
100
  function report() {
@@ -187,13 +250,13 @@ function getResolvedEnv(env) {
187
250
  function getPackageDepsPatterns(packageJson) {
188
251
  return getPackageDeps(packageJson).map((dep) => new RegExp(`^${dep}($|\\/|\\\\)`));
189
252
  }
190
- function matchesPattern(path, pattern) {
191
- return typeof pattern === "string" ? pattern === path : pattern.test(path);
253
+ function matchesPattern(path2, pattern) {
254
+ return typeof pattern === "string" ? pattern === path2 : pattern.test(path2);
192
255
  }
193
- function isExternal(path, options, packageJson) {
256
+ function isExternal(path2, options, packageJson) {
194
257
  const packageDepsPatterns = getPackageDepsPatterns(packageJson);
195
- const matchesExternalPattern = packageDepsPatterns.some((pattern) => pattern.test(path)) || options.external?.some((pattern) => matchesPattern(path, pattern));
196
- const isExcludedFromExternal = options.noExternal?.some((pattern) => matchesPattern(path, pattern));
258
+ const matchesExternalPattern = packageDepsPatterns.some((pattern) => pattern.test(path2)) || options.external?.some((pattern) => matchesPattern(path2, pattern));
259
+ const isExcludedFromExternal = options.noExternal?.some((pattern) => matchesPattern(path2, pattern));
197
260
  return matchesExternalPattern && !isExcludedFromExternal;
198
261
  }
199
262
 
@@ -217,7 +280,12 @@ function externalOptionPlugin(options, packageJson) {
217
280
  }
218
281
 
219
282
  // src/build.ts
283
+ var ac = null;
220
284
  async function build(partialOptions, rootDir = process.cwd()) {
285
+ if (ac) {
286
+ ac.abort();
287
+ }
288
+ ac = new AbortController;
221
289
  const buildOutput = {
222
290
  files: []
223
291
  };
@@ -329,7 +397,7 @@ async function build(partialOptions, rootDir = process.cwd()) {
329
397
  identifier: options.name
330
398
  });
331
399
  }
332
- const fullPath = path.join(rootDir, relativePathToRootDir);
400
+ const fullPath = path2.join(rootDir, relativePathToRootDir);
333
401
  await Bun.write(fullPath, file.dts);
334
402
  buildOutput.files.push({
335
403
  fullPath,
@@ -351,7 +419,7 @@ async function build(partialOptions, rootDir = process.cwd()) {
351
419
  rootDir
352
420
  });
353
421
  if (options.onSuccess) {
354
- await options.onSuccess(options);
422
+ await executeOnSuccess(options.onSuccess, options, ac.signal);
355
423
  }
356
424
  }
357
425
  function getRelativePathToRootDir(filePath, rootDir) {
@@ -361,4 +429,4 @@ function getRelativePathToOutputDir(relativePathToRootDir, outDir) {
361
429
  return cleanPath(relativePathToRootDir).replace(`${cleanPath(outDir)}/`, "");
362
430
  }
363
431
 
364
- export { createBuildOptions, build };
432
+ export { processLoadedConfigs, createBuildOptions, build };
@@ -101,6 +101,35 @@ type Format = "esm" | "cjs" | "iife";
101
101
  type Target = "bun" | "node" | "browser";
102
102
  type External = (string | RegExp)[];
103
103
  type Env = "inline" | "disable" | `${string}*` | Record<string, string>;
104
+ type OnSuccess = ((options: Partial<BuildOptions>) => MaybePromise<void> | (() => void)) | string | {
105
+ /**
106
+ * The shell command to execute after a successful build
107
+ */
108
+ cmd: string
109
+ /**
110
+ * Additional options for the command execution
111
+ */
112
+ options?: {
113
+ /**
114
+ * Working directory for the command
115
+ */
116
+ cwd?: string
117
+ /**
118
+ * Environment variables to pass to the command
119
+ * @default process.env
120
+ */
121
+ env?: Record<string, string | undefined>
122
+ /**
123
+ * Maximum time in milliseconds the command is allowed to run
124
+ */
125
+ timeout?: number
126
+ /**
127
+ * Signal to use when killing the process
128
+ * @default 'SIGTERM'
129
+ */
130
+ killSignal?: NodeJS.Signals | number
131
+ }
132
+ };
104
133
  interface BuildOptions {
105
134
  /**
106
135
  * Name of the build configuration
@@ -224,15 +253,27 @@ interface BuildOptions {
224
253
  /**\\n\\t* Define global constants for the build\\n\\t* These values will be replaced at build time\\n\\t*\\n\\t* @see https://bun.sh/docs/bundler#define\\n\\t*\\n\\t* @example\\n\\t* define: {\\n\\t* 'process.env.NODE_ENV': '"production"',\\n\\t* 'PACKAGE_VERSION': '"1.0.0"'\\n\\t* }\\n\\t*/
225
254
  define?: Define;
226
255
  /**
227
- * A callback function that runs after the build process completes
228
- * This can be used for custom post-build operations like copying files,
229
- * running additional tools, or logging build information
256
+ * A callback or command to run after a successful build.
257
+ *
258
+ * If a function is provided, it can optionally return a cleanup function
259
+ * that will be called when the operation is cancelled.
230
260
  *
231
- * If watch mode is enabled, this callback runs after each rebuild
261
+ * @example
262
+ * onSuccess: (options) => {
263
+ * const server = startServer();
264
+ * return () => server.close();
265
+ * }
266
+ *
267
+ * @example
268
+ * onSuccess: "echo Build completed!"
232
269
  *
233
- * @param options The build options that were used
270
+ * @example
271
+ * onSuccess: {
272
+ * cmd: "bun run dist/server.js",
273
+ * options: { env: { ...process.env, FOO: "bar" } }
274
+ * }
234
275
  */
235
- onSuccess?: (options: Partial<BuildOptions>) => MaybePromise<void>;
276
+ onSuccess?: OnSuccess;
236
277
  /**\\n\\t* A banner to be added to the final bundle, this can be a directive like "use client" for react or a comment block such as a license for the code.\\n\\t*\\n\\t* @see https://bun.sh/docs/bundler#banner\\n\\t*\\n\\t* @example\\n\\t* banner: '"use client";'\\n\\t*/
237
278
  banner?: string;
238
279
  /**
@@ -163,7 +163,12 @@ function logTable(columns, data, footer) {
163
163
  console.log(footerRow);
164
164
  }
165
165
  }
166
- var link = (url) => pc.underline(pc.cyan(url));
166
+ var link = (url, label) => {
167
+ if (!label) {
168
+ label = url;
169
+ }
170
+ return `\x1B]8;;${url}\x07${pc.underline(pc.cyan(label))}\x1B]8;;\x07`;
171
+ };
167
172
  var logger = Logger.getInstance();
168
173
 
169
174
  // src/errors.ts
@@ -251,7 +256,8 @@ var handleError = (error, context) => {
251
256
  }
252
257
  const knownError = KNOWN_ERRORS.find((error2) => error2.pattern.test(errorMessage) && (error2.errorType === errorType || !error2.errorType));
253
258
  if (!knownError && errorType) {
254
- console.error(`${pc2.red(errorType)} ${contextPrefix}${errorMessage}`);
259
+ console.error(`
260
+ ${pc2.red(errorType)} ${contextPrefix}${errorMessage}`);
255
261
  }
256
262
  if (knownError) {
257
263
  console.log(`
@@ -260,7 +266,19 @@ var handleError = (error, context) => {
260
266
  console.log(`
261
267
  `);
262
268
  } else {
263
- console.error(pc2.dim(pc2.white("If you think this is a bug, please open an issue at: ") + link("https://github.com/arshad-yaseen/bunup/issues/new")));
269
+ const issueUrl = new URL("https://github.com/arshad-yaseen/bunup/issues/new");
270
+ issueUrl.searchParams.set("title", `[${errorType}] Error encountered`);
271
+ issueUrl.searchParams.set("body", `## Error Details
272
+
273
+ **Error Type:** ${errorType}
274
+ **Error Message:** ${errorMessage}
275
+
276
+ ## Additional Context
277
+
278
+ <!-- Please provide any additional context about what you were trying to do when the error occurred -->`);
279
+ console.error(pc2.white(`
280
+ If you think this is a bug, please `) + link(issueUrl.toString(), "open an issue") + ` with details about this error
281
+ `);
264
282
  }
265
283
  };
266
284
  var handleErrorAndExit = (error, context) => {
@@ -269,7 +287,6 @@ var handleErrorAndExit = (error, context) => {
269
287
  };
270
288
 
271
289
  // src/utils.ts
272
- import fsSync from "fs";
273
290
  import fs from "fs/promises";
274
291
  import path, { normalize } from "path";
275
292
 
@@ -429,14 +446,6 @@ function cleanPath(path2) {
429
446
  function isDirectoryPath(filePath) {
430
447
  return path.extname(filePath) === "";
431
448
  }
432
- function pathExistsSync(filePath) {
433
- try {
434
- fsSync.accessSync(filePath);
435
- return true;
436
- } catch {
437
- return false;
438
- }
439
- }
440
449
  function formatListWithAnd(arr) {
441
450
  return new Intl.ListFormat("en", {
442
451
  style: "long",
@@ -469,4 +478,44 @@ function isTypeScriptFile(path2) {
469
478
  return TS_RE.test(path2);
470
479
  }
471
480
 
472
- export { __toESM, __require, silent, setSilent, logTable, link, logger, BunupBuildError, BunupDTSBuildError, BunupCLIError, BunupWatchError, BunupPluginError, parseErrorMessage, handleError, handleErrorAndExit, JS_TS_RE, JS_DTS_RE, CSS_RE, ensureArray, getDefaultOutputExtension, getDefaultDtsExtention, formatTime, getPackageDeps, formatFileSize, getShortFilePath, cleanOutDir, cleanPath, isDirectoryPath, pathExistsSync, formatListWithAnd, getFilesFromGlobs, isTypeScriptFile };
481
+ // src/plugins/utils.ts
482
+ import pc3 from "picocolors";
483
+ function filterBunupBunPlugins(plugins) {
484
+ if (!plugins)
485
+ return [];
486
+ return plugins.filter((p2) => p2.type === "bun");
487
+ }
488
+ function filterBunupPlugins(plugins) {
489
+ if (!plugins)
490
+ return [];
491
+ return plugins.filter((p2) => p2.type === "bunup");
492
+ }
493
+ async function runPluginBuildStartHooks(bunupPlugins, options) {
494
+ if (!bunupPlugins)
495
+ return;
496
+ for (const plugin of bunupPlugins) {
497
+ if (plugin.hooks.onBuildStart) {
498
+ await plugin.hooks.onBuildStart(options);
499
+ }
500
+ }
501
+ }
502
+ async function runPluginBuildDoneHooks(bunupPlugins, options, output, meta) {
503
+ if (!bunupPlugins)
504
+ return;
505
+ for (const plugin of bunupPlugins) {
506
+ if (plugin.hooks.onBuildDone) {
507
+ await plugin.hooks.onBuildDone({ options, output, meta });
508
+ }
509
+ }
510
+ }
511
+ async function getPackageForPlugin(name, pluginName) {
512
+ let pkg;
513
+ try {
514
+ pkg = await import(name);
515
+ } catch {
516
+ throw new BunupPluginError(`[${pc3.cyan(name)}] is required for the ${pluginName} plugin. Please install it with: ${pc3.blue(`bun add ${name} --dev`)}`);
517
+ }
518
+ return pkg;
519
+ }
520
+
521
+ export { __toESM, __require, silent, setSilent, logTable, logger, BunupBuildError, BunupDTSBuildError, BunupCLIError, BunupWatchError, parseErrorMessage, handleError, handleErrorAndExit, JS_TS_RE, JS_DTS_RE, CSS_RE, ensureArray, getDefaultOutputExtension, getDefaultDtsExtention, formatTime, getPackageDeps, formatFileSize, getShortFilePath, cleanOutDir, cleanPath, isDirectoryPath, formatListWithAnd, getFilesFromGlobs, isTypeScriptFile, filterBunupBunPlugins, filterBunupPlugins, runPluginBuildStartHooks, runPluginBuildDoneHooks, getPackageForPlugin };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bunup",
3
3
  "description": "⚡ A blazing-fast build tool for your libraries built with Bun.",
4
- "version": "0.9.1",
4
+ "version": "0.9.3",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -46,25 +46,23 @@
46
46
  "bunup": "dist/cli/index.js"
47
47
  },
48
48
  "dependencies": {
49
- "@clack/prompts": "^0.10.1",
50
49
  "chokidar": "^4.0.3",
51
50
  "coffi": "^0.1.31",
52
51
  "fast-deep-equal": "^3.1.3",
53
- "giget": "^2.0.0",
54
52
  "picocolors": "^1.1.1",
55
- "replace-in-file": "^8.3.0",
56
53
  "tinyexec": "^1.0.1",
57
- "typeroll": "^0.6.21"
54
+ "tree-kill": "^1.2.2",
55
+ "typeroll": "^0.6.22"
58
56
  },
59
57
  "devDependencies": {
60
58
  "@babel/types": "^7.28.2",
61
59
  "@biomejs/biome": "2.0.0",
62
60
  "@types/bun": "^1.2.19",
63
- "bumpp": "^10.2.1",
61
+ "bumpp": "^10.2.2",
64
62
  "husky": "^9.1.7",
65
63
  "lightningcss": "^1.30.1",
66
64
  "lint-staged": "^15.5.2",
67
- "typescript": "^5.8.3"
65
+ "typescript": "^5.9.2"
68
66
  },
69
67
  "peerDependencies": {
70
68
  "typescript": ">=4.5.0",
@@ -1,30 +0,0 @@
1
- // src/loaders.ts
2
- import path from "path";
3
- import { loadConfig } from "coffi";
4
- async function processLoadedConfigs(config, cwd, filter) {
5
- return Array.isArray(config) && "root" in config[0] ? config.filter((c) => filter ? filter.includes(c.name) : true).map((c) => ({
6
- rootDir: path.resolve(cwd, c.root),
7
- options: addField(c.config, "name", c.name)
8
- })) : [
9
- {
10
- rootDir: cwd,
11
- options: config
12
- }
13
- ];
14
- }
15
- function addField(objectOrArray, field, value) {
16
- return Array.isArray(objectOrArray) ? objectOrArray.map((o) => ({ ...o, [field]: value })) : { ...objectOrArray, [field]: value };
17
- }
18
- async function loadPackageJson(cwd = process.cwd()) {
19
- const { config, filepath } = await loadConfig({
20
- name: "package",
21
- cwd,
22
- extensions: [".json"]
23
- });
24
- return {
25
- data: config,
26
- path: filepath
27
- };
28
- }
29
-
30
- export { processLoadedConfigs, loadPackageJson };
@@ -1,25 +0,0 @@
1
- import {
2
- logger
3
- } from "./chunk-sfjfqxjy.js";
4
-
5
- // src/cli/utils.ts
6
- import pc from "picocolors";
7
- function displayBunupGradientArt() {
8
- const art = `
9
- \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
10
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
11
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
12
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D
13
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551
14
- \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D
15
- `.trim();
16
- const lines = art.split(`
17
- `);
18
- logger.space();
19
- for (const line of lines) {
20
- console.log(pc.cyan(line));
21
- }
22
- logger.space();
23
- }
24
-
25
- export { displayBunupGradientArt };
@@ -1,45 +0,0 @@
1
- import {
2
- BunupPluginError
3
- } from "./chunk-sfjfqxjy.js";
4
-
5
- // src/plugins/utils.ts
6
- import pc from "picocolors";
7
- function filterBunupBunPlugins(plugins) {
8
- if (!plugins)
9
- return [];
10
- return plugins.filter((p) => p.type === "bun");
11
- }
12
- function filterBunupPlugins(plugins) {
13
- if (!plugins)
14
- return [];
15
- return plugins.filter((p) => p.type === "bunup");
16
- }
17
- async function runPluginBuildStartHooks(bunupPlugins, options) {
18
- if (!bunupPlugins)
19
- return;
20
- for (const plugin of bunupPlugins) {
21
- if (plugin.hooks.onBuildStart) {
22
- await plugin.hooks.onBuildStart(options);
23
- }
24
- }
25
- }
26
- async function runPluginBuildDoneHooks(bunupPlugins, options, output, meta) {
27
- if (!bunupPlugins)
28
- return;
29
- for (const plugin of bunupPlugins) {
30
- if (plugin.hooks.onBuildDone) {
31
- await plugin.hooks.onBuildDone({ options, output, meta });
32
- }
33
- }
34
- }
35
- async function getPackageForPlugin(name, pluginName) {
36
- let pkg;
37
- try {
38
- pkg = await import(name);
39
- } catch {
40
- throw new BunupPluginError(`[${pc.cyan(name)}] is required for the ${pluginName} plugin. Please install it with: ${pc.blue(`bun add ${name} --dev`)}`);
41
- }
42
- return pkg;
43
- }
44
-
45
- export { filterBunupBunPlugins, filterBunupPlugins, runPluginBuildStartHooks, runPluginBuildDoneHooks, getPackageForPlugin };
@@ -1,156 +0,0 @@
1
- // @bun
2
- import {
3
- displayBunupGradientArt
4
- } from "./chunk-b17s55p9.js";
5
- import {
6
- link,
7
- pathExistsSync
8
- } from "./chunk-sfjfqxjy.js";
9
-
10
- // src/cli/new.ts
11
- import { renameSync } from "fs";
12
- import path from "path";
13
- import {
14
- cancel,
15
- confirm,
16
- intro,
17
- outro,
18
- select,
19
- tasks,
20
- text
21
- } from "@clack/prompts";
22
- import { downloadTemplate } from "giget";
23
- import pc from "picocolors";
24
- import { replaceInFile } from "replace-in-file";
25
- var TEMPLATE_OWNER = "arshad-yaseen";
26
- var TEMPLATE_REPO = "bunup-new";
27
- var GITHUB_USERNAME_PLACEHOLDER = "username";
28
- var GITHUB_REPO_PLACEHOLDER = "repo-name";
29
- var MONOREPO_FIRST_PACKAGE_NAME_PLACEHOLDER = "package-1";
30
- var MONOREPO_PACKAGES_DIR = "packages";
31
- var TEMPLATES = [
32
- {
33
- type: "typescript",
34
- defaultName: "my-ts-lib",
35
- name: "Typescript Library",
36
- dir: "ts-lib",
37
- monorepoDir: "ts-lib-monorepo"
38
- },
39
- {
40
- type: "react",
41
- defaultName: "my-react-lib",
42
- name: "React Library",
43
- dir: "react-lib"
44
- }
45
- ];
46
- async function newProject() {
47
- displayBunupGradientArt();
48
- intro(pc.bgCyan(pc.black(" Scaffold a new project with Bunup ")));
49
- const selectedTemplateDir = await select({
50
- message: "Select a template",
51
- options: TEMPLATES.map((template2) => ({
52
- value: template2.dir,
53
- label: pc.blue(template2.name)
54
- }))
55
- });
56
- const template = TEMPLATES.find((t) => t.dir === selectedTemplateDir);
57
- if (!template) {
58
- cancel("Invalid template");
59
- process.exit(1);
60
- }
61
- const hasMonorepo = template.monorepoDir !== undefined;
62
- const projectName = await text({
63
- message: "Enter the project name",
64
- placeholder: template.defaultName,
65
- defaultValue: template.defaultName,
66
- validate: (value) => {
67
- if (!value) {
68
- return "Project name is required";
69
- }
70
- if (value.includes(" ")) {
71
- return "Project name cannot contain spaces";
72
- }
73
- if (pathExistsSync(getProjectPath(value))) {
74
- return "Project already exists";
75
- }
76
- }
77
- });
78
- const projectPath = getProjectPath(projectName);
79
- let useMonorepo = false;
80
- let monorepoFirstPackageName;
81
- if (hasMonorepo) {
82
- useMonorepo = await confirm({
83
- message: "Do you want to create a monorepo?",
84
- initialValue: false
85
- });
86
- if (useMonorepo) {
87
- monorepoFirstPackageName = await text({
88
- message: "Enter the name of the first package",
89
- placeholder: MONOREPO_FIRST_PACKAGE_NAME_PLACEHOLDER,
90
- defaultValue: MONOREPO_FIRST_PACKAGE_NAME_PLACEHOLDER
91
- });
92
- }
93
- }
94
- const githubRepoInfo = await text({
95
- message: "GitHub username and repo name (username/repo):",
96
- placeholder: `${GITHUB_USERNAME_PLACEHOLDER}/${GITHUB_REPO_PLACEHOLDER}`,
97
- defaultValue: `${GITHUB_USERNAME_PLACEHOLDER}/${GITHUB_REPO_PLACEHOLDER}`
98
- });
99
- const [githubUsername, githubRepoName] = githubRepoInfo.split("/");
100
- await tasks([
101
- {
102
- title: "Downloading template",
103
- task: async () => {
104
- const templatePath = useMonorepo ? template.monorepoDir : template.dir;
105
- await downloadTemplate(`github:${TEMPLATE_OWNER}/${TEMPLATE_REPO}/${templatePath}`, {
106
- dir: projectPath
107
- });
108
- return "Template downloaded";
109
- }
110
- },
111
- {
112
- title: "Making the project yours",
113
- task: async () => {
114
- await replaceInFile({
115
- files: path.join(projectPath, "**/*"),
116
- from: [
117
- new RegExp(GITHUB_REPO_PLACEHOLDER, "g"),
118
- new RegExp(GITHUB_USERNAME_PLACEHOLDER, "g"),
119
- new RegExp(template.defaultName, "g")
120
- ],
121
- to: [githubRepoName, githubUsername, projectName],
122
- ignore: ["node_modules", "dist", "bun.lock"]
123
- });
124
- if (useMonorepo && monorepoFirstPackageName) {
125
- await replaceInFile({
126
- files: path.join(projectPath, "**/*"),
127
- from: [new RegExp(MONOREPO_FIRST_PACKAGE_NAME_PLACEHOLDER, "g")],
128
- to: [monorepoFirstPackageName],
129
- ignore: ["node_modules", "dist", "bun.lock"]
130
- });
131
- renameSync(path.join(projectPath, MONOREPO_PACKAGES_DIR, MONOREPO_FIRST_PACKAGE_NAME_PLACEHOLDER), path.join(projectPath, MONOREPO_PACKAGES_DIR, monorepoFirstPackageName));
132
- }
133
- }
134
- }
135
- ]);
136
- outro(`
137
- ${pc.green("\u2728 Project scaffolded successfully! \u2728")}
138
-
139
- ${pc.bold("Ready to launch your awesome new project?")}
140
-
141
- ${pc.cyan("cd")} ${projectName}
142
- ${pc.cyan("bun install")}
143
- ${pc.cyan("bun run dev")}${pc.dim(" (watch mode for development)")}${template.type === "react" ? `
144
- ${pc.cyan("bun run dev:test")} ${pc.dim("(preview components in a test Next.js app)")} ` : ""}
145
-
146
- ${pc.dim("Learn more:")} ${link("https://bunup.dev/docs")}
147
-
148
- ${pc.yellow("Happy coding!")} \uD83D\uDE80
149
- `);
150
- }
151
- function getProjectPath(projectName) {
152
- return path.join(process.cwd(), projectName);
153
- }
154
- export {
155
- newProject
156
- };
@@ -1,341 +0,0 @@
1
- // @bun
2
- import {
3
- loadPackageJson
4
- } from "./chunk-295440tx.js";
5
- import {
6
- displayBunupGradientArt
7
- } from "./chunk-b17s55p9.js";
8
- import {
9
- formatListWithAnd,
10
- link
11
- } from "./chunk-sfjfqxjy.js";
12
-
13
- // src/cli/init.ts
14
- import fs from "fs";
15
- import path from "path";
16
- import {
17
- confirm,
18
- intro,
19
- log,
20
- multiselect,
21
- outro,
22
- select,
23
- tasks,
24
- text
25
- } from "@clack/prompts";
26
- import pc from "picocolors";
27
- import { exec } from "tinyexec";
28
- async function init() {
29
- displayBunupGradientArt();
30
- intro(pc.bgCyan(pc.black(" Initialize bunup in an existing project ")));
31
- const { path: packageJsonPath } = await loadPackageJson();
32
- if (!packageJsonPath) {
33
- log.error("package.json not found");
34
- process.exit(1);
35
- }
36
- const shouldSetupWorkspace = await promptForWorkspace();
37
- if (shouldSetupWorkspace) {
38
- await initializeWorkspace(packageJsonPath);
39
- } else {
40
- await initializeSinglePackage(packageJsonPath);
41
- }
42
- await tasks([
43
- {
44
- title: "Installing bunup",
45
- task: async () => {
46
- await installBunup();
47
- return "Bunup installed";
48
- }
49
- }
50
- ]);
51
- showSuccessOutro(shouldSetupWorkspace);
52
- }
53
- async function promptForWorkspace() {
54
- return await confirm({
55
- message: "Do you want to setup a Bunup workspace? (for building multiple packages with one command)",
56
- initialValue: false
57
- });
58
- }
59
- async function initializeWorkspace(packageJsonPath) {
60
- const workspacePackages = await collectWorkspacePackages();
61
- const configMethod = await selectWorkspaceConfigurationMethod();
62
- await generateWorkspaceConfiguration(configMethod, workspacePackages);
63
- await handleWorkspaceBuildScripts(packageJsonPath);
64
- }
65
- async function initializeSinglePackage(packageJsonPath) {
66
- const entryFiles = await collectEntryFiles();
67
- const outputFormats = await selectOutputFormats();
68
- const configMethod = await selectConfigurationMethod();
69
- await generateConfiguration(configMethod, entryFiles, outputFormats, packageJsonPath);
70
- await handleBuildScripts(packageJsonPath, entryFiles, outputFormats, configMethod);
71
- }
72
- async function collectWorkspacePackages() {
73
- const packages = [];
74
- while (true) {
75
- const packageName = await text({
76
- message: packages.length > 0 ? "Enter the next package name:" : "Enter the first package name:",
77
- placeholder: "core",
78
- validate: (value) => {
79
- if (!value)
80
- return "Package name is required";
81
- if (packages.some((pkg) => pkg.name === value))
82
- return "Package name already exists";
83
- }
84
- });
85
- const packageRoot = await text({
86
- message: `Enter the root directory for "${packageName}":`,
87
- placeholder: `packages/${packageName}`,
88
- defaultValue: `packages/${packageName}`,
89
- validate: (value) => {
90
- if (!value)
91
- return "Package root is required";
92
- if (!fs.existsSync(value))
93
- return "Package root directory does not exist";
94
- if (!fs.statSync(value).isDirectory())
95
- return "Package root must be a directory";
96
- }
97
- });
98
- const entryFiles = await collectEntryFilesForPackage(packageRoot, packageName);
99
- const outputFormats = await selectOutputFormats();
100
- packages.push({
101
- name: packageName,
102
- root: packageRoot,
103
- entryFiles,
104
- outputFormats
105
- });
106
- const shouldAddMore = await confirm({
107
- message: "Do you want to add another package?",
108
- initialValue: true
109
- });
110
- if (!shouldAddMore)
111
- break;
112
- }
113
- return packages;
114
- }
115
- async function collectEntryFilesForPackage(packageRoot, packageName) {
116
- const entryFiles = [];
117
- while (true) {
118
- const entryFile = await text({
119
- message: entryFiles.length > 0 ? `Where is the next entry file for "${packageName}"? (relative to ${packageRoot})` : `Where is the entry file for "${packageName}"? (relative to ${packageRoot})`,
120
- placeholder: "src/index.ts",
121
- defaultValue: "src/index.ts",
122
- validate: (value) => {
123
- if (!value)
124
- return "Entry file is required";
125
- const fullPath = path.join(packageRoot, value);
126
- if (!fs.existsSync(fullPath))
127
- return `Entry file does not exist at ${fullPath}`;
128
- if (!fs.statSync(fullPath).isFile())
129
- return "Entry file must be a file";
130
- if (entryFiles.includes(value))
131
- return "You have already added this entry file";
132
- }
133
- });
134
- entryFiles.push(entryFile);
135
- const shouldAddMore = await confirm({
136
- message: "Do you want to add another entry file for this package?",
137
- initialValue: false
138
- });
139
- if (!shouldAddMore)
140
- break;
141
- }
142
- return entryFiles;
143
- }
144
- async function collectEntryFiles() {
145
- const entryFiles = [];
146
- while (true) {
147
- const entryFile = await text({
148
- message: entryFiles.length > 0 ? "Where is your next entry file?" : "Where is your entry file?",
149
- placeholder: "src/index.ts",
150
- defaultValue: "src/index.ts",
151
- validate: (value) => {
152
- if (!value)
153
- return "Entry file is required";
154
- if (!fs.existsSync(value))
155
- return "Entry file does not exist";
156
- if (!fs.statSync(value).isFile())
157
- return "Entry file must be a file";
158
- if (entryFiles.includes(value))
159
- return "You have already added this entry file";
160
- }
161
- });
162
- entryFiles.push(entryFile);
163
- const shouldAddMore = await confirm({
164
- message: "Do you want to add another entry file?",
165
- initialValue: false
166
- });
167
- if (!shouldAddMore)
168
- break;
169
- }
170
- return entryFiles;
171
- }
172
- async function selectOutputFormats() {
173
- return await multiselect({
174
- message: "Select the output formats",
175
- options: [
176
- { value: "esm", label: "ESM (.mjs)" },
177
- { value: "cjs", label: "CommonJS (.cjs)" },
178
- { value: "iife", label: "IIFE (.global.js)" }
179
- ],
180
- initialValues: ["esm", "cjs"]
181
- });
182
- }
183
- async function selectWorkspaceConfigurationMethod() {
184
- return await select({
185
- message: "How would you like to configure your workspace?",
186
- options: [
187
- { value: "ts", label: "bunup.config.ts", hint: "Recommended" },
188
- { value: "js", label: "bunup.config.js" }
189
- ],
190
- initialValue: "ts"
191
- });
192
- }
193
- async function selectConfigurationMethod() {
194
- return await select({
195
- message: "How would you like to configure Bunup?",
196
- options: [
197
- { value: "ts", label: "bunup.config.ts", hint: "Recommended" },
198
- { value: "js", label: "bunup.config.js" },
199
- { value: "json", label: 'package.json "bunup" property' },
200
- {
201
- value: "none",
202
- label: "No config file",
203
- hint: "Configure via CLI only"
204
- }
205
- ],
206
- initialValue: "ts"
207
- });
208
- }
209
- async function generateWorkspaceConfiguration(configMethod, workspacePackages) {
210
- const configContent = createWorkspaceConfigFileContent(workspacePackages);
211
- await Bun.write(`bunup.config.${configMethod}`, configContent);
212
- }
213
- async function generateConfiguration(configMethod, entryFiles, outputFormats, packageJsonPath) {
214
- if (configMethod === "none") {
215
- log.info("If you need more control (such as adding plugins or customizing output), you can always create a config file later.");
216
- return;
217
- }
218
- if (configMethod === "ts" || configMethod === "js") {
219
- await Bun.write(`bunup.config.${configMethod}`, createConfigFileContent(entryFiles, outputFormats));
220
- } else if (configMethod === "json") {
221
- const { data: packageJsonConfig } = await loadPackageJson();
222
- const updatedConfig = {
223
- ...packageJsonConfig,
224
- bunup: createPackageJsonConfig(entryFiles, outputFormats)
225
- };
226
- await Bun.write(packageJsonPath, JSON.stringify(updatedConfig, null, 2));
227
- }
228
- }
229
- async function handleWorkspaceBuildScripts(packageJsonPath) {
230
- const { data: packageJsonConfig } = await loadPackageJson();
231
- const existingScripts = packageJsonConfig?.scripts ?? {};
232
- const newScripts = createWorkspaceBuildScripts();
233
- const conflictingScripts = Object.keys(newScripts).filter((script) => existingScripts[script]);
234
- if (conflictingScripts.length > 0) {
235
- const shouldOverride = await confirm({
236
- message: `The ${formatListWithAnd(conflictingScripts)} ${conflictingScripts.length > 1 ? "scripts already exist" : "script already exists"} in package.json. Override ${conflictingScripts.length > 1 ? "them" : "it"}?`,
237
- initialValue: true
238
- });
239
- if (!shouldOverride) {
240
- log.info("Skipped adding build scripts to avoid conflicts.");
241
- return;
242
- }
243
- }
244
- const updatedConfig = {
245
- ...packageJsonConfig,
246
- scripts: { ...existingScripts, ...newScripts }
247
- };
248
- await Bun.write(packageJsonPath, JSON.stringify(updatedConfig, null, 2));
249
- }
250
- async function handleBuildScripts(packageJsonPath, entryFiles, outputFormats, configMethod) {
251
- const { data: packageJsonConfig } = await loadPackageJson();
252
- const existingScripts = packageJsonConfig?.scripts ?? {};
253
- const newScripts = createBuildScripts(entryFiles, outputFormats, configMethod);
254
- const conflictingScripts = Object.keys(newScripts).filter((script) => existingScripts[script]);
255
- if (conflictingScripts.length > 0) {
256
- const shouldOverride = await confirm({
257
- message: `The ${formatListWithAnd(conflictingScripts)} ${conflictingScripts.length > 1 ? "scripts already exist" : "script already exists"} in package.json. Override ${conflictingScripts.length > 1 ? "them" : "it"}?`,
258
- initialValue: true
259
- });
260
- if (!shouldOverride) {
261
- log.info("Skipped adding build scripts to avoid conflicts.");
262
- return;
263
- }
264
- }
265
- const updatedConfig = {
266
- ...packageJsonConfig,
267
- scripts: { ...existingScripts, ...newScripts }
268
- };
269
- await Bun.write(packageJsonPath, JSON.stringify(updatedConfig, null, 2));
270
- }
271
- function createWorkspaceConfigFileContent(workspacePackages) {
272
- const packagesConfig = workspacePackages.map((pkg) => {
273
- return ` {
274
- name: '${pkg.name}',
275
- root: '${pkg.root}',
276
- config: {
277
- entry: [${pkg.entryFiles.map((file) => `'${file}'`).join(", ")}],
278
- format: [${pkg.outputFormats.map((format) => `'${format}'`).join(", ")}],
279
- },
280
- }`;
281
- }).join(`,
282
- `);
283
- return `import { defineWorkspace } from 'bunup'
284
-
285
- export default defineWorkspace([
286
- ${packagesConfig}
287
- ])
288
- `;
289
- }
290
- function createConfigFileContent(entryFiles, outputFormats) {
291
- return `import { defineConfig } from 'bunup'
292
-
293
- export default defineConfig({
294
- entry: [${entryFiles.map((file) => `'${file}'`).join(", ")}],
295
- format: [${outputFormats.map((format) => `'${format}'`).join(", ")}],
296
- })
297
- `;
298
- }
299
- function createPackageJsonConfig(entryFiles, outputFormats) {
300
- return {
301
- entry: entryFiles,
302
- format: outputFormats
303
- };
304
- }
305
- function createWorkspaceBuildScripts() {
306
- return {
307
- build: "bunup",
308
- dev: "bunup --watch"
309
- };
310
- }
311
- function createBuildScripts(entryFiles, outputFormats, configMethod) {
312
- const cliOptions = configMethod === "none" ? ` ${entryFiles.join(" ")} --format ${outputFormats.join(",")}` : "";
313
- return {
314
- build: `bunup${cliOptions}`,
315
- dev: `bunup${cliOptions} --watch`
316
- };
317
- }
318
- function showSuccessOutro(isWorkspace) {
319
- const buildCommand = isWorkspace ? `${pc.cyan("bun run build")} - Build all packages in your workspace` : `${pc.cyan("bun run build")} - Build your library`;
320
- const devCommand = isWorkspace ? `${pc.cyan("bun run dev")} - Start development mode (watches all packages)` : `${pc.cyan("bun run dev")} - Start development mode`;
321
- const filterCommand = isWorkspace ? `${pc.cyan("bunup --filter core,utils")} - Build specific packages` : "";
322
- outro(`
323
- ${pc.green("\u2728 Bunup initialized successfully! \u2728")}
324
-
325
- ${buildCommand}
326
- ${devCommand}${isWorkspace ? `
327
- ${filterCommand}` : ""}
328
-
329
- ${pc.dim("Learn more:")} ${link("https://bunup.dev/docs")}
330
-
331
- ${pc.yellow("Happy building!")} \uD83D\uDE80
332
- `);
333
- }
334
- async function installBunup() {
335
- await exec("bun add -d bunup", [], {
336
- nodeOptions: { shell: true, stdio: "pipe" }
337
- });
338
- }
339
- export {
340
- init
341
- };