buner 1.0.4 → 1.0.5

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.
Files changed (3) hide show
  1. package/bin/buner.js +45 -32
  2. package/cli/buner.ts +51 -28
  3. package/package.json +2 -1
package/bin/buner.js CHANGED
@@ -13,18 +13,18 @@ import { globby } from "globby";
13
13
  import { exec } from "node:child_process";
14
14
  import validateProjectName from "validate-npm-package-name";
15
15
  const name = "buner";
16
- const version = "1.0.4";
16
+ const version = "1.0.5";
17
17
  const description = "Frontend build toolkit for Vite + React SSR projects — SCSS pipeline, prerender, SSR dev server, and backend integration.";
18
18
  const type = "module";
19
19
  const license = "MIT";
20
20
  const repository = { "type": "git", "url": "https://github.com/precise-alloy/buner.git" };
21
21
  const homepage = "https://www.npmjs.com/package/buner";
22
22
  const keywords = ["vite", "react", "ssr", "scss", "prerender", "frontend", "build-tool", "cli"];
23
- const bin = { "buner": "./bin/buner.js" };
23
+ const bin$1 = { "buner": "./bin/buner.js" };
24
24
  const files = ["bin", "cli", "xpack", "public", "server.ts", "prerender.ts", "integration.ts", "styles.ts", "scripts.ts", "states.ts", "migrate-scss.ts", "vite.config.ts", "index.html", "tsconfig.json", "eslint.config.mjs", "types.d.ts", ".env", ".env.development", ".env.eshn", "README.md"];
25
25
  const scripts = { "start": "bun run dev", "predev": "bun upgrade", "dev": 'concurrently --kill-others "bun styles.ts --watch" "bun states.ts --watch" "cross-env scriptOnly=true vite build --mode development --watch" "bun server.ts --mode development"', "serve": "bun server.ts", "watch": "bun server.ts", "build": "bun run build:static && bun run build:server", "build:eshn": "bun run build:static:eshn && bun run build:server:eshn", "preview": "vite preview", "build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server", "build:server:eshn": "vite build --ssr src/entry-server.tsx --outDir dist/server --mode eshn", "build:static": "vite build --outDir dist/static", "build:static:eshn": "vite build --outDir dist/static --mode eshn", "generate": "bun states.ts && bun run styles && bun run build && bun prerender.ts --add-hash", "eshn": "bun states.ts && bun run styles && bun run build:eshn && bun prerender.ts --add-hash --mode eshn", "inte": "bun run styles && bun run build && bun prerender.ts && bun integration.ts", "styles": "bun styles.ts", "format": "prettier --write .", "lint": "eslint --fix", "cli:start": "vite build -c vite.cli.config.ts --watch", "cli:build": "vite build -c vite.cli.config.ts" };
26
26
  const engines = { "node": ">=20.0.0" };
27
- const dependencies = { "@vitejs/plugin-react": "^5.1.4", "autoprefixer": "^10.4.27", "chalk": "^5.5.0", "cheerio": "^1.2.0", "chokidar": "^4.0.3", "commander": "^14.0.3", "concurrently": "^9.2.0", "cross-env": "^10.1.0", "cssnano": "^7.1.0", "debounce": "^3.0.0", "express": "^5.2.1", "glob": "^13.0.6", "globby": "^16.1.1", "js-beautify": "^1.15.4", "lodash": "^4.17.21", "magic-string": "^0.30.17", "node-fetch": "^3.3.2", "postcss": "^8.5.8", "prompts": "^2.4.2", "sass": "^1.89.2", "slash": "^5.1.0", "validate-npm-package-name": "^7.0.0", "vite": "^7.0.6" };
27
+ const dependencies = { "@vitejs/plugin-react": "^5.1.4", "autoprefixer": "^10.4.27", "chalk": "^5.5.0", "cheerio": "^1.2.0", "chokidar": "^4.0.3", "commander": "^14.0.3", "concurrently": "^9.2.0", "cross-env": "^10.1.0", "cssnano": "^7.1.0", "debounce": "^3.0.0", "express": "^5.2.1", "glob": "^13.0.6", "globby": "^16.1.1", "js-beautify": "^1.15.4", "lodash": "^4.17.21", "magic-string": "^0.30.17", "node-fetch": "^3.3.2", "postcss": "^8.5.8", "prompts": "^2.4.2", "sass": "^1.89.2", "slash": "^5.1.0", "tsx": "^4.19.0", "validate-npm-package-name": "^7.0.0", "vite": "^7.0.6" };
28
28
  const peerDependencies = { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "react-router-dom": "^6.0.0 || ^7.0.0" };
29
29
  const devDependencies = { "@eslint/compat": "^2.0.0", "@next/eslint-plugin-next": "^16.0.8", "@types/css": "^0.0.38", "@types/debounce": "^1.2.4", "@types/express": "^5.0.6", "@types/js-beautify": "^1.14.3", "@types/lodash": "^4.17.24", "@types/node": "^24.11.0", "@types/prettier": "^3.0.0", "@types/prompts": "^2.4.9", "@types/react": "^19.2.14", "@types/react-dom": "^19.1.7", "@types/validate-npm-package-name": "^4.0.2", "@typescript-eslint/eslint-plugin": "^8.50.0", "@typescript-eslint/parser": "^8.50.0", "css": "^3.0.0", "eslint": "^9.39.2", "eslint-config-next": "^16.0.8", "eslint-config-prettier": "10.1.8", "eslint-plugin-import": "2.32.0", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-node": "11.1.0", "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "7.0.1", "eslint-plugin-react-refresh": "^0.5.2", "eslint-plugin-unused-imports": "^4.4.1", "globals": "^16.3.0", "msw": "^2.12.10", "postcss-scss": "^4.0.9", "prettier": "^3.6.2", "react": "^19.2.4", "react-dom": "^19.2.4", "react-router-dom": "^7.13.1", "rollup": "^4.59.0", "svgo": "^4.0.0" };
30
30
  const msw = { "workerDirectory": "public" };
@@ -37,7 +37,7 @@ const packageJson = {
37
37
  repository,
38
38
  homepage,
39
39
  keywords,
40
- bin,
40
+ bin: bin$1,
41
41
  files,
42
42
  scripts,
43
43
  engines,
@@ -432,6 +432,20 @@ const { green, yellow, bold, cyan, red } = chalk;
432
432
  const packageName = "buner";
433
433
  const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
434
434
  const pkg = (file) => path.join(packageDir, file);
435
+ const bin = (name2) => {
436
+ const ext = process.platform === "win32" ? ".cmd" : "";
437
+ const local = path.join(packageDir, "node_modules", ".bin", name2 + ext);
438
+ try {
439
+ if (require("fs").existsSync(local)) return local;
440
+ } catch {
441
+ }
442
+ const consumerBin = path.join(process.cwd(), "node_modules", ".bin", name2 + ext);
443
+ try {
444
+ if (require("fs").existsSync(consumerBin)) return consumerBin;
445
+ } catch {
446
+ }
447
+ return name2;
448
+ };
435
449
  const run = (cmd, args = [], options = {}) => {
436
450
  return new Promise((resolve, reject) => {
437
451
  const child = spawn(cmd, args, {
@@ -515,58 +529,57 @@ For example:
515
529
  await notifyUpdate();
516
530
  });
517
531
  program.command("dev").description("Start development mode with all watchers").action(async () => {
518
- await run("npx", [
519
- "concurrently",
532
+ await run(bin("concurrently"), [
520
533
  "--kill-others",
521
- `"bun ${pkg("styles.ts")} --watch"`,
522
- `"bun ${pkg("states.ts")} --watch"`,
523
- `"cross-env scriptOnly=true npx vite build --config ${pkg("vite.config.ts")} --mode development --watch"`,
524
- `"bun ${pkg("server.ts")} --mode development"`
534
+ `"${bin("tsx")} ${pkg("styles.ts")} --watch"`,
535
+ `"${bin("tsx")} ${pkg("states.ts")} --watch"`,
536
+ `"${bin("cross-env")} scriptOnly=true ${bin("vite")} build --config ${pkg("vite.config.ts")} --mode development --watch"`,
537
+ `"${bin("tsx")} ${pkg("server.ts")} --mode development"`
525
538
  ]);
526
539
  });
527
540
  program.command("serve").description("Start the SSR dev server").option("--mode <mode>", "server mode", "development").action(async (opts) => {
528
- await run("bun", [pkg("server.ts"), "--mode", opts.mode]);
541
+ await run(bin("tsx"), [pkg("server.ts"), "--mode", opts.mode]);
529
542
  });
530
543
  program.command("build").description("Build the project (static + SSR)").action(async () => {
531
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --outDir dist/static`);
532
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
544
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --outDir dist/static`);
545
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
533
546
  });
534
547
  program.command("generate").description("Full static site generation (states + styles + build + prerender)").option("--mode <mode>", "build mode", "production").action(async (opts) => {
535
- runSync(`bun ${pkg("states.ts")}`);
536
- runSync(`bun ${pkg("styles.ts")}`);
548
+ runSync(`${bin("tsx")} ${pkg("states.ts")}`);
549
+ runSync(`${bin("tsx")} ${pkg("styles.ts")}`);
537
550
  if (opts.mode === "production") {
538
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --outDir dist/static`);
539
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
551
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --outDir dist/static`);
552
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
540
553
  } else {
541
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --outDir dist/static --mode ${opts.mode}`);
542
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
554
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --outDir dist/static --mode ${opts.mode}`);
555
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
543
556
  }
544
- runSync(`bun ${pkg("prerender.ts")} --add-hash --mode ${opts.mode}`);
557
+ runSync(`${bin("tsx")} ${pkg("prerender.ts")} --add-hash --mode ${opts.mode}`);
545
558
  });
546
559
  program.command("eshn").description("Generate with --mode eshn").action(async () => {
547
- runSync(`bun ${pkg("states.ts")}`);
548
- runSync(`bun ${pkg("styles.ts")}`);
549
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --outDir dist/static --mode eshn`);
550
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server --mode eshn`);
551
- runSync(`bun ${pkg("prerender.ts")} --add-hash --mode eshn`);
560
+ runSync(`${bin("tsx")} ${pkg("states.ts")}`);
561
+ runSync(`${bin("tsx")} ${pkg("styles.ts")}`);
562
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --outDir dist/static --mode eshn`);
563
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server --mode eshn`);
564
+ runSync(`${bin("tsx")} ${pkg("prerender.ts")} --add-hash --mode eshn`);
552
565
  });
553
566
  program.command("inte").description("Build and integrate with backend (styles + build + prerender + integration)").action(async () => {
554
- runSync(`bun ${pkg("styles.ts")}`);
555
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --outDir dist/static`);
556
- runSync(`npx vite build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
557
- runSync(`bun ${pkg("prerender.ts")}`);
558
- runSync(`bun ${pkg("integration.ts")}`);
567
+ runSync(`${bin("tsx")} ${pkg("styles.ts")}`);
568
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --outDir dist/static`);
569
+ runSync(`${bin("vite")} build --config ${pkg("vite.config.ts")} --ssr src/entry-server.tsx --outDir dist/server`);
570
+ runSync(`${bin("tsx")} ${pkg("prerender.ts")}`);
571
+ runSync(`${bin("tsx")} ${pkg("integration.ts")}`);
559
572
  });
560
573
  program.command("styles").description("Compile SCSS").option("--watch", "Watch for changes").action(async (opts) => {
561
574
  const args = [pkg("styles.ts")];
562
575
  if (opts.watch) args.push("--watch");
563
- await run("bun", args);
576
+ await run(bin("tsx"), args);
564
577
  });
565
578
  program.command("prerender").description("Pre-render HTML files").option("--add-hash", "Add content hashes to asset URLs").option("--mode <mode>", "build mode", "production").action(async (opts) => {
566
579
  const args = [pkg("prerender.ts")];
567
580
  if (opts.addHash) args.push("--add-hash");
568
581
  args.push("--mode", opts.mode);
569
- await run("bun", args);
582
+ await run(bin("tsx"), args);
570
583
  });
571
584
  program.parseAsync(process.argv).catch(async (error) => {
572
585
  console.log(red(error));
package/cli/buner.ts CHANGED
@@ -23,6 +23,30 @@ const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '.
23
23
  /** Resolve a file path relative to the buner package directory */
24
24
  const pkg = (file: string) => path.join(packageDir, file);
25
25
 
26
+ /** Resolve a binary from buner's own node_modules */
27
+ const bin = (name: string) => {
28
+ const ext = process.platform === 'win32' ? '.cmd' : '';
29
+ const local = path.join(packageDir, 'node_modules', '.bin', name + ext);
30
+
31
+ try {
32
+ if (require('fs').existsSync(local)) return local;
33
+ } catch {
34
+ // ignore
35
+ }
36
+
37
+ // Fallback: try to find it in the consumer's node_modules
38
+ const consumerBin = path.join(process.cwd(), 'node_modules', '.bin', name + ext);
39
+
40
+ try {
41
+ if (require('fs').existsSync(consumerBin)) return consumerBin;
42
+ } catch {
43
+ // ignore
44
+ }
45
+
46
+ // Last resort: rely on PATH
47
+ return name;
48
+ };
49
+
26
50
  const run = (cmd: string, args: string[] = [], options: SpawnOptions = {}) => {
27
51
  return new Promise<void>((resolve, reject) => {
28
52
  const child = spawn(cmd, args, {
@@ -136,13 +160,12 @@ program
136
160
  .command('dev')
137
161
  .description('Start development mode with all watchers')
138
162
  .action(async () => {
139
- await run('npx', [
140
- 'concurrently',
163
+ await run(bin('concurrently'), [
141
164
  '--kill-others',
142
- `"bun ${pkg('styles.ts')} --watch"`,
143
- `"bun ${pkg('states.ts')} --watch"`,
144
- `"cross-env scriptOnly=true npx vite build --config ${pkg('vite.config.ts')} --mode development --watch"`,
145
- `"bun ${pkg('server.ts')} --mode development"`,
165
+ `"${bin('tsx')} ${pkg('styles.ts')} --watch"`,
166
+ `"${bin('tsx')} ${pkg('states.ts')} --watch"`,
167
+ `"${bin('cross-env')} scriptOnly=true ${bin('vite')} build --config ${pkg('vite.config.ts')} --mode development --watch"`,
168
+ `"${bin('tsx')} ${pkg('server.ts')} --mode development"`,
146
169
  ]);
147
170
  });
148
171
 
@@ -152,7 +175,7 @@ program
152
175
  .description('Start the SSR dev server')
153
176
  .option('--mode <mode>', 'server mode', 'development')
154
177
  .action(async (opts) => {
155
- await run('bun', [pkg('server.ts'), '--mode', opts.mode]);
178
+ await run(bin('tsx'), [pkg('server.ts'), '--mode', opts.mode]);
156
179
  });
157
180
 
158
181
  // buner build
@@ -160,8 +183,8 @@ program
160
183
  .command('build')
161
184
  .description('Build the project (static + SSR)')
162
185
  .action(async () => {
163
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --outDir dist/static`);
164
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
186
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --outDir dist/static`);
187
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
165
188
  });
166
189
 
167
190
  // buner generate
@@ -170,16 +193,16 @@ program
170
193
  .description('Full static site generation (states + styles + build + prerender)')
171
194
  .option('--mode <mode>', 'build mode', 'production')
172
195
  .action(async (opts) => {
173
- runSync(`bun ${pkg('states.ts')}`);
174
- runSync(`bun ${pkg('styles.ts')}`);
196
+ runSync(`${bin('tsx')} ${pkg('states.ts')}`);
197
+ runSync(`${bin('tsx')} ${pkg('styles.ts')}`);
175
198
  if (opts.mode === 'production') {
176
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --outDir dist/static`);
177
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
199
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --outDir dist/static`);
200
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
178
201
  } else {
179
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --outDir dist/static --mode ${opts.mode}`);
180
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
202
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --outDir dist/static --mode ${opts.mode}`);
203
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
181
204
  }
182
- runSync(`bun ${pkg('prerender.ts')} --add-hash --mode ${opts.mode}`);
205
+ runSync(`${bin('tsx')} ${pkg('prerender.ts')} --add-hash --mode ${opts.mode}`);
183
206
  });
184
207
 
185
208
  // buner eshn
@@ -187,11 +210,11 @@ program
187
210
  .command('eshn')
188
211
  .description('Generate with --mode eshn')
189
212
  .action(async () => {
190
- runSync(`bun ${pkg('states.ts')}`);
191
- runSync(`bun ${pkg('styles.ts')}`);
192
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --outDir dist/static --mode eshn`);
193
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server --mode eshn`);
194
- runSync(`bun ${pkg('prerender.ts')} --add-hash --mode eshn`);
213
+ runSync(`${bin('tsx')} ${pkg('states.ts')}`);
214
+ runSync(`${bin('tsx')} ${pkg('styles.ts')}`);
215
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --outDir dist/static --mode eshn`);
216
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server --mode eshn`);
217
+ runSync(`${bin('tsx')} ${pkg('prerender.ts')} --add-hash --mode eshn`);
195
218
  });
196
219
 
197
220
  // buner inte
@@ -199,11 +222,11 @@ program
199
222
  .command('inte')
200
223
  .description('Build and integrate with backend (styles + build + prerender + integration)')
201
224
  .action(async () => {
202
- runSync(`bun ${pkg('styles.ts')}`);
203
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --outDir dist/static`);
204
- runSync(`npx vite build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
205
- runSync(`bun ${pkg('prerender.ts')}`);
206
- runSync(`bun ${pkg('integration.ts')}`);
225
+ runSync(`${bin('tsx')} ${pkg('styles.ts')}`);
226
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --outDir dist/static`);
227
+ runSync(`${bin('vite')} build --config ${pkg('vite.config.ts')} --ssr src/entry-server.tsx --outDir dist/server`);
228
+ runSync(`${bin('tsx')} ${pkg('prerender.ts')}`);
229
+ runSync(`${bin('tsx')} ${pkg('integration.ts')}`);
207
230
  });
208
231
 
209
232
  // buner styles
@@ -215,7 +238,7 @@ program
215
238
  const args = [pkg('styles.ts')];
216
239
 
217
240
  if (opts.watch) args.push('--watch');
218
- await run('bun', args);
241
+ await run(bin('tsx'), args);
219
242
  });
220
243
 
221
244
  // buner prerender
@@ -229,7 +252,7 @@ program
229
252
 
230
253
  if (opts.addHash) args.push('--add-hash');
231
254
  args.push('--mode', opts.mode);
232
- await run('bun', args);
255
+ await run(bin('tsx'), args);
233
256
  });
234
257
 
235
258
  program.parseAsync(process.argv).catch(async (error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buner",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Frontend build toolkit for Vite + React SSR projects — SCSS pipeline, prerender, SSR dev server, and backend integration.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -91,6 +91,7 @@
91
91
  "prompts": "^2.4.2",
92
92
  "sass": "^1.89.2",
93
93
  "slash": "^5.1.0",
94
+ "tsx": "^4.19.0",
94
95
  "validate-npm-package-name": "^7.0.0",
95
96
  "vite": "^7.0.6"
96
97
  },