buner 1.0.2 → 1.0.4

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/bin/buner.js CHANGED
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "path";
3
3
  import { execSync, spawn } from "child_process";
4
+ import { fileURLToPath } from "url";
4
5
  import { Command } from "commander";
5
6
  import chalk from "chalk";
6
7
  import fetch from "node-fetch";
7
8
  import prompts from "prompts";
8
9
  import fs from "fs";
9
10
  import fs$1 from "fs/promises";
10
- import { fileURLToPath } from "url";
11
11
  import os from "os";
12
12
  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.2";
16
+ const version = "1.0.4";
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";
@@ -139,23 +139,26 @@ const tryGitInit = (root) => {
139
139
  };
140
140
  const excludeFiles = [
141
141
  ".git",
142
+ ".github",
143
+ ".npmrc",
142
144
  "bin",
145
+ "cli",
146
+ "xpack",
143
147
  ".vscode",
144
148
  ".build",
149
+ "node_modules",
150
+ "server.ts",
151
+ "prerender.ts",
152
+ "integration.ts",
153
+ "styles.ts",
154
+ "scripts.ts",
155
+ "states.ts",
156
+ "migrate-scss.ts",
157
+ "vite.config.ts",
158
+ "vite.cli.config.ts",
159
+ "src",
145
160
  "public/samples",
146
- "public/assets/vendors",
147
- "src/_api/!(_base.ts)",
148
- "src/_data",
149
- "src/assets/scripts/!(color-mode|main|mock-api|pl-states|root|theme-critical).entry.ts",
150
- "src/atoms",
151
- "src/mocks/avatar",
152
- "src/mocks/user",
153
- "src/molecules",
154
- "src/organisms/!(root|header|footer)/*",
155
- "src/pages/!(Root|Home).tsx",
156
- "src/templates/!(root|home)/*",
157
- "!cli",
158
- "!vite.cli.config.ts"
161
+ "public/assets/vendors"
159
162
  ];
160
163
  const copy = async (src, dest, { cwd }) => {
161
164
  const sourceFiles = await globby(src, {
@@ -166,9 +169,6 @@ const copy = async (src, dest, { cwd }) => {
166
169
  ignore: excludeFiles
167
170
  });
168
171
  const destRelativeToCwd = path.resolve(dest);
169
- await fs$1.mkdir(path.join(destRelativeToCwd, "src/atoms"), { recursive: true });
170
- await fs$1.mkdir(path.join(destRelativeToCwd, "src/molecules"), { recursive: true });
171
- await fs$1.mkdir(path.join(destRelativeToCwd, "src/mocks/example"), { recursive: true });
172
172
  return Promise.all(
173
173
  sourceFiles.map(async (p) => {
174
174
  const dirname2 = path.dirname(p);
@@ -194,11 +194,15 @@ const install = async () => {
194
194
  });
195
195
  });
196
196
  };
197
+ const writeFile = async (filePath, data) => {
198
+ await fs$1.mkdir(path.dirname(filePath), { recursive: true });
199
+ await fs$1.writeFile(filePath, data);
200
+ };
197
201
  const formatFiles = async (root) => {
198
202
  let filePath, data;
199
203
  filePath = path.join(root, "src/mocks/handlers.ts");
200
204
  data = "import { handlers } from './consts';\n\nexport { handlers };";
201
- await fs$1.writeFile(filePath, data + os.EOL);
205
+ await writeFile(filePath, data + os.EOL);
202
206
  filePath = path.join(root, "src/mocks/example/index.ts");
203
207
  data = `
204
208
  import { handlers } from '@mocks/handlers';
@@ -210,9 +214,8 @@ const formatFiles = async (root) => {
210
214
  })
211
215
  );
212
216
  `;
213
- await fs$1.writeFile(filePath, data + os.EOL);
217
+ await writeFile(filePath, data + os.EOL);
214
218
  filePath = path.join(root, "src/react-loader.tsx");
215
- await fs$1.mkdir(path.dirname(filePath), { recursive: true });
216
219
  data = [
217
220
  "import { lazy } from 'react';",
218
221
  "",
@@ -221,23 +224,23 @@ const formatFiles = async (root) => {
221
224
  "};",
222
225
  ""
223
226
  ].join("\n");
224
- await fs$1.writeFile(filePath, data);
227
+ await writeFile(filePath, data);
225
228
  filePath = path.join(root, "src/_types/atoms.d.ts");
226
- await fs$1.writeFile(
229
+ await writeFile(
227
230
  filePath,
228
231
  `
229
232
  import { BasedAtomicModel } from "./_general";
230
233
  `
231
234
  );
232
235
  filePath = path.join(root, "src/_types/molecules.d.ts");
233
- await fs$1.writeFile(
236
+ await writeFile(
234
237
  filePath,
235
238
  `
236
239
  import { BasedAtomicModel } from "./_general";
237
240
  `
238
241
  );
239
242
  filePath = path.join(root, "src/_types/organisms.d.ts");
240
- await fs$1.writeFile(
243
+ await writeFile(
241
244
  filePath,
242
245
  `
243
246
  import { BasedAtomicModel } from "./_general";
@@ -248,7 +251,7 @@ const formatFiles = async (root) => {
248
251
  `
249
252
  );
250
253
  filePath = path.join(root, "src/pages/Home.tsx");
251
- await fs$1.writeFile(
254
+ await writeFile(
252
255
  filePath,
253
256
  `
254
257
  import Template from '@templates/home/Home';
@@ -261,7 +264,7 @@ const formatFiles = async (root) => {
261
264
  `
262
265
  );
263
266
  filePath = path.join(root, "src/templates/home/Home.tsx");
264
- await fs$1.writeFile(
267
+ await writeFile(
265
268
  filePath,
266
269
  `
267
270
  import { FooterModel, HeaderModel } from '@_types/organisms';
@@ -293,7 +296,7 @@ const formatFiles = async (root) => {
293
296
  `
294
297
  );
295
298
  filePath = path.join(root, "src/organisms/header/Header.tsx");
296
- await fs$1.writeFile(
299
+ await writeFile(
297
300
  filePath,
298
301
  `
299
302
  import { getModifiers } from '@helpers/functions';
@@ -315,9 +318,9 @@ const formatFiles = async (root) => {
315
318
  `
316
319
  );
317
320
  filePath = path.join(root, "src/organisms/header/Header.scss");
318
- await fs$1.writeFile(filePath, "");
321
+ await writeFile(filePath, "");
319
322
  filePath = path.join(root, "src/organisms/footer/Footer.tsx");
320
- await fs$1.writeFile(
323
+ await writeFile(
321
324
  filePath,
322
325
  `
323
326
  import { getModifiers } from '@helpers/functions';
@@ -339,7 +342,7 @@ const formatFiles = async (root) => {
339
342
  `
340
343
  );
341
344
  filePath = path.join(root, "src/organisms/footer/Footer.scss");
342
- await fs$1.writeFile(filePath, "");
345
+ await writeFile(filePath, "");
343
346
  return ["xxx"];
344
347
  };
345
348
  const filename = fileURLToPath(import.meta.url);
@@ -353,32 +356,35 @@ const installTemplate = async (model) => {
353
356
  cwd: path.join(dirname, "..")
354
357
  });
355
358
  await formatFiles(root);
356
- const packageJson2 = JSON.parse(await fs$1.readFile("package.json", "utf8"));
357
- packageJson2.name = appName;
358
- packageJson2.description = "";
359
- packageJson2.version = "0.1.0";
360
- delete packageJson2.bin;
361
- packageJson2.scripts && Object.keys(packageJson2.scripts).map((scriptName) => {
362
- if (scriptName.startsWith("cli")) {
363
- delete packageJson2.scripts[scriptName];
364
- }
365
- });
366
- packageJson2.dependencies && Object.keys(packageJson2.dependencies).map((dependency) => {
367
- if (!dependency.startsWith("react")) {
368
- delete packageJson2.dependencies[dependency];
359
+ const packageJson$1 = {
360
+ name: appName,
361
+ description: "",
362
+ version: "0.1.0",
363
+ type: "module",
364
+ private: true,
365
+ scripts: {
366
+ start: "buner dev",
367
+ dev: "buner dev",
368
+ serve: "buner serve",
369
+ build: "buner build",
370
+ generate: "buner generate",
371
+ eshn: "buner eshn",
372
+ inte: "buner inte",
373
+ styles: "buner styles",
374
+ prerender: "buner prerender"
375
+ },
376
+ dependencies: {
377
+ buner: `^${packageJson.version}`,
378
+ react: "^19.0.0",
379
+ "react-dom": "^19.0.0",
380
+ "react-router-dom": "^7.0.0"
369
381
  }
370
- });
371
- const devDeps = Object.keys(packageJson2.devDependencies).length;
372
- if (!devDeps) delete packageJson2.devDependencies;
373
- await fs$1.writeFile(path.join(root, "package.json"), JSON.stringify(packageJson2, null, 2) + os.EOL);
382
+ };
383
+ await fs$1.writeFile(path.join(root, "package.json"), JSON.stringify(packageJson$1, null, 2) + os.EOL);
374
384
  console.log("\nInstalling dependencies:");
375
- for (const dependency in packageJson2.dependencies) {
385
+ for (const dependency in packageJson$1.dependencies) {
376
386
  console.log(`- ${cyan$1(dependency)}`);
377
387
  }
378
- if (devDeps) {
379
- console.log("\nInstalling devDependencies:");
380
- for (const dependency in packageJson2.devDependencies) console.log(`- ${cyan$1(dependency)}`);
381
- }
382
388
  await install();
383
389
  };
384
390
  const { green: green$1 } = chalk;
@@ -424,6 +430,8 @@ function validateNpmName(name2) {
424
430
  }
425
431
  const { green, yellow, bold, cyan, red } = chalk;
426
432
  const packageName = "buner";
433
+ const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
434
+ const pkg = (file) => path.join(packageDir, file);
427
435
  const run = (cmd, args = [], options = {}) => {
428
436
  return new Promise((resolve, reject) => {
429
437
  const child = spawn(cmd, args, {
@@ -510,52 +518,52 @@ program.command("dev").description("Start development mode with all watchers").a
510
518
  await run("npx", [
511
519
  "concurrently",
512
520
  "--kill-others",
513
- '"bun styles.ts --watch"',
514
- '"bun states.ts --watch"',
515
- '"cross-env scriptOnly=true npx vite build --mode development --watch"',
516
- '"bun server.ts --mode development"'
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"`
517
525
  ]);
518
526
  });
519
527
  program.command("serve").description("Start the SSR dev server").option("--mode <mode>", "server mode", "development").action(async (opts) => {
520
- await run("bun", ["server.ts", "--mode", opts.mode]);
528
+ await run("bun", [pkg("server.ts"), "--mode", opts.mode]);
521
529
  });
522
530
  program.command("build").description("Build the project (static + SSR)").action(async () => {
523
- runSync("npx vite build --outDir dist/static");
524
- runSync("npx vite build --ssr src/entry-server.tsx --outDir dist/server");
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`);
525
533
  });
526
534
  program.command("generate").description("Full static site generation (states + styles + build + prerender)").option("--mode <mode>", "build mode", "production").action(async (opts) => {
527
- runSync("bun states.ts");
528
- runSync("bun styles.ts");
535
+ runSync(`bun ${pkg("states.ts")}`);
536
+ runSync(`bun ${pkg("styles.ts")}`);
529
537
  if (opts.mode === "production") {
530
- runSync("npx vite build --outDir dist/static");
531
- runSync("npx vite build --ssr src/entry-server.tsx --outDir dist/server");
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`);
532
540
  } else {
533
- runSync(`npx vite build --outDir dist/static --mode ${opts.mode}`);
534
- runSync(`npx vite build --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
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}`);
535
543
  }
536
- runSync(`bun prerender.ts --add-hash --mode ${opts.mode}`);
544
+ runSync(`bun ${pkg("prerender.ts")} --add-hash --mode ${opts.mode}`);
537
545
  });
538
546
  program.command("eshn").description("Generate with --mode eshn").action(async () => {
539
- runSync("bun states.ts");
540
- runSync("bun styles.ts");
541
- runSync("npx vite build --outDir dist/static --mode eshn");
542
- runSync("npx vite build --ssr src/entry-server.tsx --outDir dist/server --mode eshn");
543
- runSync("bun prerender.ts --add-hash --mode eshn");
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`);
544
552
  });
545
553
  program.command("inte").description("Build and integrate with backend (styles + build + prerender + integration)").action(async () => {
546
- runSync("bun styles.ts");
547
- runSync("npx vite build --outDir dist/static");
548
- runSync("npx vite build --ssr src/entry-server.tsx --outDir dist/server");
549
- runSync("bun prerender.ts");
550
- runSync("bun integration.ts");
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")}`);
551
559
  });
552
560
  program.command("styles").description("Compile SCSS").option("--watch", "Watch for changes").action(async (opts) => {
553
- const args = ["styles.ts"];
561
+ const args = [pkg("styles.ts")];
554
562
  if (opts.watch) args.push("--watch");
555
563
  await run("bun", args);
556
564
  });
557
565
  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) => {
558
- const args = ["prerender.ts"];
566
+ const args = [pkg("prerender.ts")];
559
567
  if (opts.addHash) args.push("--add-hash");
560
568
  args.push("--mode", opts.mode);
561
569
  await run("bun", args);
package/cli/buner.ts CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import path from 'path';
4
4
  import { execSync, spawn, SpawnOptions } from 'child_process';
5
+ import { fileURLToPath } from 'url';
5
6
 
6
7
  import { Command } from 'commander';
7
8
  import chalk from 'chalk';
@@ -16,6 +17,12 @@ import { validateNpmName } from './helpers/validate-pkg.js';
16
17
  const { green, yellow, bold, cyan, red } = chalk;
17
18
  const packageName = 'buner';
18
19
 
20
+ // Package's own directory (where server.ts, styles.ts, etc. live)
21
+ const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
22
+
23
+ /** Resolve a file path relative to the buner package directory */
24
+ const pkg = (file: string) => path.join(packageDir, file);
25
+
19
26
  const run = (cmd: string, args: string[] = [], options: SpawnOptions = {}) => {
20
27
  return new Promise<void>((resolve, reject) => {
21
28
  const child = spawn(cmd, args, {
@@ -132,10 +139,10 @@ program
132
139
  await run('npx', [
133
140
  'concurrently',
134
141
  '--kill-others',
135
- '"bun styles.ts --watch"',
136
- '"bun states.ts --watch"',
137
- '"cross-env scriptOnly=true npx vite build --mode development --watch"',
138
- '"bun server.ts --mode development"',
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"`,
139
146
  ]);
140
147
  });
141
148
 
@@ -145,7 +152,7 @@ program
145
152
  .description('Start the SSR dev server')
146
153
  .option('--mode <mode>', 'server mode', 'development')
147
154
  .action(async (opts) => {
148
- await run('bun', ['server.ts', '--mode', opts.mode]);
155
+ await run('bun', [pkg('server.ts'), '--mode', opts.mode]);
149
156
  });
150
157
 
151
158
  // buner build
@@ -153,8 +160,8 @@ program
153
160
  .command('build')
154
161
  .description('Build the project (static + SSR)')
155
162
  .action(async () => {
156
- runSync('npx vite build --outDir dist/static');
157
- runSync('npx vite build --ssr src/entry-server.tsx --outDir dist/server');
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`);
158
165
  });
159
166
 
160
167
  // buner generate
@@ -163,16 +170,16 @@ program
163
170
  .description('Full static site generation (states + styles + build + prerender)')
164
171
  .option('--mode <mode>', 'build mode', 'production')
165
172
  .action(async (opts) => {
166
- runSync('bun states.ts');
167
- runSync('bun styles.ts');
173
+ runSync(`bun ${pkg('states.ts')}`);
174
+ runSync(`bun ${pkg('styles.ts')}`);
168
175
  if (opts.mode === 'production') {
169
- runSync('npx vite build --outDir dist/static');
170
- runSync('npx vite build --ssr src/entry-server.tsx --outDir dist/server');
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`);
171
178
  } else {
172
- runSync(`npx vite build --outDir dist/static --mode ${opts.mode}`);
173
- runSync(`npx vite build --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
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}`);
174
181
  }
175
- runSync(`bun prerender.ts --add-hash --mode ${opts.mode}`);
182
+ runSync(`bun ${pkg('prerender.ts')} --add-hash --mode ${opts.mode}`);
176
183
  });
177
184
 
178
185
  // buner eshn
@@ -180,11 +187,11 @@ program
180
187
  .command('eshn')
181
188
  .description('Generate with --mode eshn')
182
189
  .action(async () => {
183
- runSync('bun states.ts');
184
- runSync('bun styles.ts');
185
- runSync('npx vite build --outDir dist/static --mode eshn');
186
- runSync('npx vite build --ssr src/entry-server.tsx --outDir dist/server --mode eshn');
187
- runSync('bun prerender.ts --add-hash --mode eshn');
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`);
188
195
  });
189
196
 
190
197
  // buner inte
@@ -192,11 +199,11 @@ program
192
199
  .command('inte')
193
200
  .description('Build and integrate with backend (styles + build + prerender + integration)')
194
201
  .action(async () => {
195
- runSync('bun styles.ts');
196
- runSync('npx vite build --outDir dist/static');
197
- runSync('npx vite build --ssr src/entry-server.tsx --outDir dist/server');
198
- runSync('bun prerender.ts');
199
- runSync('bun integration.ts');
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')}`);
200
207
  });
201
208
 
202
209
  // buner styles
@@ -205,7 +212,7 @@ program
205
212
  .description('Compile SCSS')
206
213
  .option('--watch', 'Watch for changes')
207
214
  .action(async (opts) => {
208
- const args = ['styles.ts'];
215
+ const args = [pkg('styles.ts')];
209
216
 
210
217
  if (opts.watch) args.push('--watch');
211
218
  await run('bun', args);
@@ -218,7 +225,7 @@ program
218
225
  .option('--add-hash', 'Add content hashes to asset URLs')
219
226
  .option('--mode <mode>', 'build mode', 'production')
220
227
  .action(async (opts) => {
221
- const args = ['prerender.ts'];
228
+ const args = [pkg('prerender.ts')];
222
229
 
223
230
  if (opts.addHash) args.push('--add-hash');
224
231
  args.push('--mode', opts.mode);
@@ -9,23 +9,26 @@ interface CopyOption {
9
9
 
10
10
  const excludeFiles = [
11
11
  '.git',
12
+ '.github',
13
+ '.npmrc',
12
14
  'bin',
15
+ 'cli',
16
+ 'xpack',
13
17
  '.vscode',
14
18
  '.build',
19
+ 'node_modules',
20
+ 'server.ts',
21
+ 'prerender.ts',
22
+ 'integration.ts',
23
+ 'styles.ts',
24
+ 'scripts.ts',
25
+ 'states.ts',
26
+ 'migrate-scss.ts',
27
+ 'vite.config.ts',
28
+ 'vite.cli.config.ts',
29
+ 'src',
15
30
  'public/samples',
16
31
  'public/assets/vendors',
17
- 'src/_api/!(_base.ts)',
18
- 'src/_data',
19
- 'src/assets/scripts/!(color-mode|main|mock-api|pl-states|root|theme-critical).entry.ts',
20
- 'src/atoms',
21
- 'src/mocks/avatar',
22
- 'src/mocks/user',
23
- 'src/molecules',
24
- 'src/organisms/!(root|header|footer)/*',
25
- 'src/pages/!(Root|Home).tsx',
26
- 'src/templates/!(root|home)/*',
27
- '!cli',
28
- '!vite.cli.config.ts',
29
32
  ];
30
33
 
31
34
  const copy = async (src: string | string[], dest: string, { cwd }: CopyOption) => {
@@ -39,10 +42,6 @@ const copy = async (src: string | string[], dest: string, { cwd }: CopyOption) =
39
42
 
40
43
  const destRelativeToCwd = path.resolve(dest);
41
44
 
42
- await fs.mkdir(path.join(destRelativeToCwd, 'src/atoms'), { recursive: true });
43
- await fs.mkdir(path.join(destRelativeToCwd, 'src/molecules'), { recursive: true });
44
- await fs.mkdir(path.join(destRelativeToCwd, 'src/mocks/example'), { recursive: true });
45
-
46
45
  return Promise.all(
47
46
  sourceFiles.map(async (p) => {
48
47
  const dirname = path.dirname(p);
@@ -2,6 +2,11 @@ import path from 'path';
2
2
  import os from 'os';
3
3
  import fs from 'fs/promises';
4
4
 
5
+ const writeFile = async (filePath: string, data: string) => {
6
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
7
+ await fs.writeFile(filePath, data);
8
+ };
9
+
5
10
  const formatFiles = async (root: string) => {
6
11
  let filePath, data;
7
12
 
@@ -9,7 +14,7 @@ const formatFiles = async (root: string) => {
9
14
  filePath = path.join(root, 'src/mocks/handlers.ts');
10
15
  data = "import { handlers } from './consts';\n\nexport { handlers };";
11
16
 
12
- await fs.writeFile(filePath, data + os.EOL);
17
+ await writeFile(filePath, data + os.EOL);
13
18
 
14
19
  // example mock file
15
20
  filePath = path.join(root, 'src/mocks/example/index.ts');
@@ -24,11 +29,10 @@ const formatFiles = async (root: string) => {
24
29
  );
25
30
  `;
26
31
 
27
- await fs.writeFile(filePath, data + os.EOL);
32
+ await writeFile(filePath, data + os.EOL);
28
33
 
29
34
  // react loader
30
35
  filePath = path.join(root, 'src/react-loader.tsx');
31
- await fs.mkdir(path.dirname(filePath), { recursive: true });
32
36
  data = [
33
37
  "import { lazy } from 'react';",
34
38
  '',
@@ -38,12 +42,12 @@ const formatFiles = async (root: string) => {
38
42
  '',
39
43
  ].join('\n');
40
44
 
41
- await fs.writeFile(filePath, data);
45
+ await writeFile(filePath, data);
42
46
 
43
47
  // src/_types/atoms.d.ts
44
48
  filePath = path.join(root, 'src/_types/atoms.d.ts');
45
49
 
46
- await fs.writeFile(
50
+ await writeFile(
47
51
  filePath,
48
52
  `
49
53
  import { BasedAtomicModel } from "./_general";
@@ -53,7 +57,7 @@ const formatFiles = async (root: string) => {
53
57
  // src/_types/molecules.d.d.ts
54
58
  filePath = path.join(root, 'src/_types/molecules.d.ts');
55
59
 
56
- await fs.writeFile(
60
+ await writeFile(
57
61
  filePath,
58
62
  `
59
63
  import { BasedAtomicModel } from "./_general";
@@ -63,7 +67,7 @@ const formatFiles = async (root: string) => {
63
67
  // src/_types/organisms.d.ts
64
68
  filePath = path.join(root, 'src/_types/organisms.d.ts');
65
69
 
66
- await fs.writeFile(
70
+ await writeFile(
67
71
  filePath,
68
72
  `
69
73
  import { BasedAtomicModel } from "./_general";
@@ -77,7 +81,7 @@ const formatFiles = async (root: string) => {
77
81
  // pages/Home.tsx
78
82
  filePath = path.join(root, 'src/pages/Home.tsx');
79
83
 
80
- await fs.writeFile(
84
+ await writeFile(
81
85
  filePath,
82
86
  `
83
87
  import Template from '@templates/home/Home';
@@ -93,7 +97,7 @@ const formatFiles = async (root: string) => {
93
97
  // templates/home/Home.tsx
94
98
  filePath = path.join(root, 'src/templates/home/Home.tsx');
95
99
 
96
- await fs.writeFile(
100
+ await writeFile(
97
101
  filePath,
98
102
  `
99
103
  import { FooterModel, HeaderModel } from '@_types/organisms';
@@ -128,7 +132,7 @@ const formatFiles = async (root: string) => {
128
132
  // src/organisms/header/Header.tsx
129
133
  filePath = path.join(root, 'src/organisms/header/Header.tsx');
130
134
 
131
- await fs.writeFile(
135
+ await writeFile(
132
136
  filePath,
133
137
  `
134
138
  import { getModifiers } from '@helpers/functions';
@@ -153,12 +157,12 @@ const formatFiles = async (root: string) => {
153
157
  // src/organisms/header/Header.scss
154
158
  filePath = path.join(root, 'src/organisms/header/Header.scss');
155
159
 
156
- await fs.writeFile(filePath, '');
160
+ await writeFile(filePath, '');
157
161
 
158
162
  // src/organisms/footer/Footer.tsx
159
163
  filePath = path.join(root, 'src/organisms/footer/Footer.tsx');
160
164
 
161
- await fs.writeFile(
165
+ await writeFile(
162
166
  filePath,
163
167
  `
164
168
  import { getModifiers } from '@helpers/functions';
@@ -183,7 +187,7 @@ const formatFiles = async (root: string) => {
183
187
  // src/organisms/footer/Footer.scss
184
188
  filePath = path.join(root, 'src/organisms/footer/Footer.scss');
185
189
 
186
- await fs.writeFile(filePath, '');
190
+ await writeFile(filePath, '');
187
191
 
188
192
  return ['xxx'];
189
193
  };
@@ -9,6 +9,7 @@ import chalk from 'chalk';
9
9
  import { copy } from './helpers/copy.js';
10
10
  import { install } from './helpers/install.js';
11
11
  import { formatFiles } from './helpers/format-files.js';
12
+ import packageJson_ from '../package.json';
12
13
 
13
14
  export const filename = fileURLToPath(import.meta.url);
14
15
  export const dirname = path.dirname(filename);
@@ -32,30 +33,30 @@ const installTemplate = async (model: Props) => {
32
33
 
33
34
  await formatFiles(root);
34
35
 
35
- const packageJson = JSON.parse(await fs.readFile('package.json', 'utf8'));
36
-
37
- packageJson.name = appName;
38
- packageJson.description = '';
39
- packageJson.version = '0.1.0';
40
-
41
- delete packageJson.bin;
42
- packageJson.scripts &&
43
- Object.keys(packageJson.scripts).map((scriptName: string) => {
44
- if (scriptName.startsWith('cli')) {
45
- delete packageJson.scripts[scriptName];
46
- }
47
- });
48
-
49
- packageJson.dependencies &&
50
- Object.keys(packageJson.dependencies).map((dependency) => {
51
- if (!dependency.startsWith('react')) {
52
- delete packageJson.dependencies[dependency];
53
- }
54
- });
55
-
56
- const devDeps = Object.keys(packageJson.devDependencies).length;
57
-
58
- if (!devDeps) delete packageJson.devDependencies;
36
+ const packageJson = {
37
+ name: appName,
38
+ description: '',
39
+ version: '0.1.0',
40
+ type: 'module',
41
+ private: true,
42
+ scripts: {
43
+ start: 'buner dev',
44
+ dev: 'buner dev',
45
+ serve: 'buner serve',
46
+ build: 'buner build',
47
+ generate: 'buner generate',
48
+ eshn: 'buner eshn',
49
+ inte: 'buner inte',
50
+ styles: 'buner styles',
51
+ prerender: 'buner prerender',
52
+ },
53
+ dependencies: {
54
+ buner: `^${packageJson_.version}`,
55
+ react: '^19.0.0',
56
+ 'react-dom': '^19.0.0',
57
+ 'react-router-dom': '^7.0.0',
58
+ },
59
+ };
59
60
 
60
61
  await fs.writeFile(path.join(root, 'package.json'), JSON.stringify(packageJson, null, 2) + os.EOL);
61
62
 
@@ -65,12 +66,6 @@ const installTemplate = async (model: Props) => {
65
66
  console.log(`- ${cyan(dependency)}`);
66
67
  }
67
68
 
68
- if (devDeps) {
69
- console.log('\nInstalling devDependencies:');
70
-
71
- for (const dependency in packageJson.devDependencies) console.log(`- ${cyan(dependency)}`);
72
- }
73
-
74
69
  await install();
75
70
  };
76
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buner",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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",