create-blitzpack 0.1.11 → 0.1.13

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 (2) hide show
  1. package/dist/index.js +91 -123
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -386,17 +386,54 @@ async function getProjectOptions(providedName, flags = {}) {
386
386
  };
387
387
  }
388
388
  async function promptFeatureSelection() {
389
+ let cancelled = false;
390
+ const { setupType } = await prompts(
391
+ {
392
+ type: "select",
393
+ name: "setupType",
394
+ message: "Setup type:",
395
+ choices: [
396
+ {
397
+ title: "Recommended",
398
+ description: "all features included",
399
+ value: "recommended"
400
+ },
401
+ {
402
+ title: "Customize",
403
+ description: "choose features",
404
+ value: "customize"
405
+ }
406
+ ],
407
+ initial: 0,
408
+ hint: "- Use arrow-keys, Enter to submit"
409
+ },
410
+ {
411
+ onCancel: () => {
412
+ cancelled = true;
413
+ }
414
+ }
415
+ );
416
+ if (cancelled) {
417
+ return null;
418
+ }
419
+ if (setupType === "recommended") {
420
+ return {
421
+ testing: true,
422
+ admin: true,
423
+ uploads: true
424
+ };
425
+ }
389
426
  const featureChoices = OPTIONAL_FEATURES.map((feature) => ({
390
- title: `${feature.name} ${chalk3.dim(`(${feature.description})`)}`,
427
+ title: feature.name,
428
+ description: feature.description,
391
429
  value: feature.key,
392
- selected: true
430
+ selected: false
393
431
  }));
394
- let cancelled = false;
395
432
  const { selectedFeatures } = await prompts(
396
433
  {
397
434
  type: "multiselect",
398
435
  name: "selectedFeatures",
399
- message: "Include optional features:",
436
+ message: "Select features to include:",
400
437
  choices: featureChoices,
401
438
  hint: "- Space to toggle, Enter to confirm",
402
439
  instructions: false
@@ -525,6 +562,43 @@ var TESTING_ROOT_DEVDEPS = [
525
562
  ];
526
563
  var TESTING_APP_DEVDEPS = ["vitest", "vite-tsconfig-paths"];
527
564
  var UPLOADS_API_DEPS = ["@aws-sdk/client-s3", "sharp"];
565
+ var MARKER_FILES = [
566
+ "apps/api/src/app.ts",
567
+ "apps/api/src/plugins/services.ts",
568
+ "apps/api/prisma/schema.prisma"
569
+ ];
570
+ function stripFeatureBlocks(content, disabledFeatures) {
571
+ const lines = content.split("\n");
572
+ const result = [];
573
+ let skipUntilEnd = false;
574
+ let currentFeature = null;
575
+ for (const line of lines) {
576
+ const featureStart = line.match(/\/\/\s*@feature\s+(\w+)/);
577
+ const featureEnd = line.match(/\/\/\s*@endfeature/);
578
+ if (featureStart) {
579
+ const feature = featureStart[1];
580
+ if (disabledFeatures.includes(feature)) {
581
+ skipUntilEnd = true;
582
+ currentFeature = feature;
583
+ }
584
+ continue;
585
+ }
586
+ if (featureEnd) {
587
+ if (skipUntilEnd) {
588
+ skipUntilEnd = false;
589
+ currentFeature = null;
590
+ }
591
+ continue;
592
+ }
593
+ if (!skipUntilEnd) {
594
+ result.push(line);
595
+ }
596
+ }
597
+ return result.join("\n");
598
+ }
599
+ function cleanEmptyLines(content) {
600
+ return content.replace(/\n{3,}/g, "\n\n");
601
+ }
528
602
  function transformPackageJson(content, vars, filePath, features) {
529
603
  const pkg = JSON.parse(content);
530
604
  if (filePath === "package.json") {
@@ -656,15 +730,22 @@ async function transformFiles(targetDir, vars, features) {
656
730
  await applyFeatureTransforms(targetDir, features);
657
731
  }
658
732
  async function applyFeatureTransforms(targetDir, features) {
733
+ const disabledFeatures = [];
734
+ if (!features.testing) disabledFeatures.push("testing");
735
+ if (!features.admin) disabledFeatures.push("admin");
736
+ if (!features.uploads) disabledFeatures.push("uploads");
737
+ for (const relativePath of MARKER_FILES) {
738
+ const filePath = path3.join(targetDir, relativePath);
739
+ if (await fs2.pathExists(filePath)) {
740
+ let content = await fs2.readFile(filePath, "utf-8");
741
+ content = stripFeatureBlocks(content, disabledFeatures);
742
+ content = cleanEmptyLines(content);
743
+ await fs2.writeFile(filePath, content);
744
+ }
745
+ }
659
746
  if (!features.testing) {
660
747
  await transformForNoTesting(targetDir);
661
748
  }
662
- if (!features.admin) {
663
- await transformForNoAdmin(targetDir);
664
- }
665
- if (!features.uploads) {
666
- await transformForNoUploads(targetDir);
667
- }
668
749
  }
669
750
  async function transformForNoTesting(targetDir) {
670
751
  const turboPath = path3.join(targetDir, "turbo.json");
@@ -683,119 +764,6 @@ async function transformForNoTesting(targetDir) {
683
764
  await fs2.writeFile(huskyPath, "pnpm typecheck\n");
684
765
  }
685
766
  }
686
- async function transformForNoAdmin(targetDir) {
687
- const appPath = path3.join(targetDir, "apps/api/src/app.ts");
688
- if (await fs2.pathExists(appPath)) {
689
- let content = await fs2.readFile(appPath, "utf-8");
690
- content = content.replace(
691
- /import { metricsService } from '@\/services\/metrics\.service';\n/,
692
- ""
693
- );
694
- content = content.replace(
695
- /const { default: statsRoutes } = await import\('@\/routes\/stats\.js'\);\n/,
696
- ""
697
- );
698
- content = content.replace(
699
- /const { default: metricsRoutes } = await import\('@\/routes\/metrics\.js'\);\n/,
700
- ""
701
- );
702
- content = content.replace(
703
- /const { default: adminSessionsRoutes } = await import\(\n\s*'@\/routes\/admin-sessions\.js'\n\s*\);\n/,
704
- ""
705
- );
706
- content = content.replace(/metricsService\.start\(\);\n\n/, "");
707
- content = content.replace(
708
- /\s*metricsService\.recordRequest\(responseTime, reply\.statusCode\);\n/,
709
- ""
710
- );
711
- content = content.replace(/\s*await app\.register\(statsRoutes\);/g, "");
712
- content = content.replace(/\s*await app\.register\(metricsRoutes\);/g, "");
713
- content = content.replace(
714
- /\s*await app\.register\(adminSessionsRoutes\);/g,
715
- ""
716
- );
717
- await fs2.writeFile(appPath, content);
718
- }
719
- const servicesPath = path3.join(targetDir, "apps/api/src/plugins/services.ts");
720
- if (await fs2.pathExists(servicesPath)) {
721
- let content = await fs2.readFile(servicesPath, "utf-8");
722
- content = content.replace(
723
- /import { StatsService } from '@\/services\/stats\.service';\n/,
724
- ""
725
- );
726
- content = content.replace(
727
- /\s*const statsService = new StatsService\(app\.prisma, app\.logger\);/,
728
- ""
729
- );
730
- content = content.replace(
731
- /\s*app\.decorate\('statsService', statsService\);/,
732
- ""
733
- );
734
- content = content.replace(/\s*statsService: StatsService;/, "");
735
- await fs2.writeFile(servicesPath, content);
736
- }
737
- }
738
- async function transformForNoUploads(targetDir) {
739
- const appPath = path3.join(targetDir, "apps/api/src/app.ts");
740
- if (await fs2.pathExists(appPath)) {
741
- let content = await fs2.readFile(appPath, "utf-8");
742
- content = content.replace(
743
- /const { default: uploadsRoutes } = await import\('@\/routes\/uploads\.js'\);\n/,
744
- ""
745
- );
746
- content = content.replace(
747
- /const { default: uploadsServeRoutes } = await import\(\n\s*'@\/routes\/uploads-serve\.js'\n\s*\);\n/,
748
- ""
749
- );
750
- content = content.replace(
751
- /await app\.register\(uploadsServeRoutes\);\n\n/,
752
- ""
753
- );
754
- content = content.replace(/\s*await app\.register\(uploadsRoutes\);/g, "");
755
- await fs2.writeFile(appPath, content);
756
- }
757
- const servicesPath = path3.join(targetDir, "apps/api/src/plugins/services.ts");
758
- if (await fs2.pathExists(servicesPath)) {
759
- let content = await fs2.readFile(servicesPath, "utf-8");
760
- content = content.replace(
761
- /import { FileStorageService } from '@\/services\/file-storage\.service';\n/,
762
- ""
763
- );
764
- content = content.replace(
765
- /import { UploadsService } from '@\/services\/uploads\.service';\n/,
766
- ""
767
- );
768
- content = content.replace(
769
- /\s*const fileStorageService = new FileStorageService\(env, app\.logger\);/,
770
- ""
771
- );
772
- content = content.replace(
773
- /\s*const uploadsService = new UploadsService\(\n\s*app\.prisma,\n\s*fileStorageService,\n\s*app\.logger\n\s*\);/,
774
- ""
775
- );
776
- content = content.replace(
777
- /\s*app\.decorate\('fileStorageService', fileStorageService\);/,
778
- ""
779
- );
780
- content = content.replace(
781
- /\s*app\.decorate\('uploadsService', uploadsService\);/,
782
- ""
783
- );
784
- content = content.replace(/\s*fileStorageService: FileStorageService;/, "");
785
- content = content.replace(/\s*uploadsService: UploadsService;/, "");
786
- await fs2.writeFile(servicesPath, content);
787
- }
788
- const schemaPath = path3.join(targetDir, "apps/api/prisma/schema.prisma");
789
- if (await fs2.pathExists(schemaPath)) {
790
- let content = await fs2.readFile(schemaPath, "utf-8");
791
- content = content.replace(/\s*uploads\s+Upload\[\]/, "");
792
- content = content.replace(
793
- /\n\nmodel Upload \{[\s\S]*?@@map\("uploads"\)\n\}/,
794
- ""
795
- );
796
- await fs2.writeFile(schemaPath, content);
797
- }
798
- }
799
767
 
800
768
  // src/commands/create.ts
801
769
  var ENV_FILES = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-blitzpack",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Create a new Blitzpack project - full-stack TypeScript monorepo with Next.js and Fastify",
5
5
  "type": "module",
6
6
  "bin": {