create-meridian-app 0.1.17 → 0.1.19

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.
@@ -19,7 +19,8 @@ function renderPackageJson(vars) {
19
19
  build: "meridian build",
20
20
  start: "node --import tsx/esm src/main.ts",
21
21
  "db:migrate": "meridian db:migrate",
22
- "db:generate": "meridian db:generate"
22
+ "db:generate": "meridian db:generate",
23
+ ...vars.seedDemo ? { "seed:demo": "node --import tsx/esm src/scripts/seed-demo.ts" } : {}
23
24
  },
24
25
  dependencies: {
25
26
  "@meridianjs/framework": "latest",
@@ -115,20 +116,21 @@ function renderOptionalModuleBlock(id, vars) {
115
116
  resolve: "@meridianjs/email-ses",
116
117
  options: {
117
118
  fromAddress: process.env.EMAIL_FROM ?? "noreply@example.com",
118
- region: process.env.AWS_REGION ?? "us-east-1",
119
- accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
120
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "",
119
+ region: process.env.AWS_SES_REGION ?? "us-east-1",
120
+ accessKeyId: process.env.AWS_SES_ACCESS_KEY_ID ?? "",
121
+ secretAccessKey: process.env.AWS_SES_SECRET_ACCESS_KEY ?? "",
121
122
  },
122
123
  },`;
123
124
  case "storage-s3":
124
125
  return ` {
125
126
  resolve: "@meridianjs/storage-s3",
126
127
  options: {
127
- bucket: process.env.S3_BUCKET ?? "",
128
- region: process.env.AWS_REGION ?? "us-east-1",
129
- accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
130
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "",
131
- // endpoint: process.env.S3_ENDPOINT, // uncomment for R2 / MinIO
128
+ bucket: process.env.AWS_S3_BUCKET ?? "",
129
+ region: process.env.AWS_S3_REGION ?? "us-east-1",
130
+ accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID ?? "",
131
+ secretAccessKey: process.env.AWS_S3_SECRET_ACCESS_KEY ?? "",
132
+ // cloudfrontUrl: process.env.AWS_CLOUDFRONT_URL, // optional, for generating public URLs
133
+ // endpoint: process.env.AWS_S3_ENDPOINT, // uncomment for R2 / MinIO
132
134
  },
133
135
  },`;
134
136
  }
@@ -245,15 +247,18 @@ GOOGLE_CLIENT_SECRET=`);
245
247
  }
246
248
  if (mods.includes("storage-s3")) {
247
249
  sections.push(`# File storage (S3 / compatible)
248
- S3_BUCKET=
249
- # S3_ENDPOINT= # uncomment for R2 / MinIO`);
250
+ AWS_S3_BUCKET=
251
+ AWS_S3_REGION=us-east-1
252
+ AWS_S3_ACCESS_KEY_ID=
253
+ AWS_S3_SECRET_ACCESS_KEY=
254
+ # AWS_CLOUDFRONT_URL= # optional, for generating public URLs
255
+ # AWS_S3_ENDPOINT= # uncomment for R2 / MinIO`);
250
256
  }
251
- const hasAws = mods.includes("email-ses") || mods.includes("storage-s3");
252
- if (hasAws) {
253
- sections.push(`# AWS credentials (used by ${[mods.includes("email-ses") ? "SES" : "", mods.includes("storage-s3") ? "S3" : ""].filter(Boolean).join(" + ")})
254
- AWS_REGION=us-east-1
255
- AWS_ACCESS_KEY_ID=
256
- AWS_SECRET_ACCESS_KEY=`);
257
+ if (mods.includes("email-ses")) {
258
+ sections.push(`# Email \u2014 AWS SES credentials
259
+ AWS_SES_REGION=us-east-1
260
+ AWS_SES_ACCESS_KEY_ID=
261
+ AWS_SES_SECRET_ACCESS_KEY=`);
257
262
  }
258
263
  const optionalEnv = sections.length > 0 ? "\n" + sections.join("\n\n") : "";
259
264
  return `# Copy this file to .env and fill in your values
@@ -500,6 +505,570 @@ function renderRoute(methods) {
500
505
  ${handlers.join("\n\n")}
501
506
  `;
502
507
  }
508
+ function renderSeedScript() {
509
+ return `import "dotenv/config"
510
+ import path from "node:path"
511
+ import { fileURLToPath } from "node:url"
512
+ import { bootstrap } from "@meridianjs/framework"
513
+
514
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
515
+ const rootDir = path.resolve(__dirname, "../..")
516
+
517
+ async function main() {
518
+ console.log()
519
+ console.log(" Seeding demo data...")
520
+
521
+ const app = await bootstrap({ rootDir })
522
+ const { container } = app
523
+
524
+ const workspaceService = container.resolve("workspaceModuleService") as any
525
+ const projectService = container.resolve("projectModuleService") as any
526
+ const issueService = container.resolve("issueModuleService") as any
527
+ const sprintService = container.resolve("sprintModuleService") as any
528
+ const userService = container.resolve("userModuleService") as any
529
+
530
+ // Optional author for comments
531
+ const [users] = await userService.listAndCountUsers({}, { limit: 1 })
532
+ const authorId: string | null = users[0]?.id ?? null
533
+ if (!authorId) {
534
+ console.log(" \u2139 No users found \u2014 comments will be skipped.")
535
+ console.log(" Create a user first, then re-run 'npm run seed:demo' to seed comments.")
536
+ }
537
+
538
+ const now = new Date()
539
+ const future = (days: number) => new Date(now.getTime() + days * 86_400_000)
540
+
541
+ // \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
542
+
543
+ async function seedStatuses(projectId: string) {
544
+ const defaults = [
545
+ { name: "Backlog", color: "#94a3b8", position: 0 },
546
+ { name: "Todo", color: "#64748b", position: 1 },
547
+ { name: "In Progress", color: "#6366f1", position: 2 },
548
+ { name: "In Review", color: "#f59e0b", position: 3 },
549
+ { name: "Done", color: "#10b981", position: 4 },
550
+ { name: "Cancelled", color: "#ef4444", position: 5 },
551
+ ]
552
+ for (const s of defaults) {
553
+ await projectService.createProjectStatus({ project_id: projectId, ...s })
554
+ }
555
+ }
556
+
557
+ async function seedComment(issueId: string, body: string) {
558
+ if (!authorId) return
559
+ await issueService.createComment({ issue_id: issueId, author_id: authorId, body })
560
+ }
561
+
562
+ // \u2500\u2500 Workspace 1: Acme Corp \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
563
+
564
+ const acme = await workspaceService.createWorkspace({ name: "Acme Corp", slug: "acme-corp" })
565
+
566
+ // Project A: Website Redesign
567
+ const siteProject = await projectService.createProject({
568
+ workspace_id: acme.id,
569
+ name: "Website Redesign",
570
+ identifier: "SITE",
571
+ color: "#6366f1",
572
+ })
573
+ await seedStatuses(siteProject.id)
574
+ const siteSprint = await sprintService.createSprint({
575
+ project_id: siteProject.id,
576
+ name: "Sprint 1",
577
+ start_date: now,
578
+ end_date: future(14),
579
+ })
580
+ await sprintService.startSprint(siteSprint.id)
581
+
582
+ const siteHero = await issueService.createIssueInProject({
583
+ project_id: siteProject.id,
584
+ title: "Redesign homepage hero section",
585
+ type: "feature",
586
+ priority: "high",
587
+ status: "In Progress",
588
+ sprint_id: siteSprint.id,
589
+ })
590
+ await issueService.createIssueInProject({
591
+ project_id: siteProject.id,
592
+ title: "Design hero animation",
593
+ type: "task",
594
+ priority: "medium",
595
+ status: "Todo",
596
+ parent_id: siteHero.id,
597
+ })
598
+ await issueService.createIssueInProject({
599
+ project_id: siteProject.id,
600
+ title: "Write hero copy",
601
+ type: "task",
602
+ priority: "low",
603
+ status: "Todo",
604
+ parent_id: siteHero.id,
605
+ })
606
+ await issueService.createIssueInProject({
607
+ project_id: siteProject.id,
608
+ title: "Fix broken navigation links",
609
+ type: "bug",
610
+ priority: "urgent",
611
+ status: "Done",
612
+ })
613
+ await issueService.createIssueInProject({
614
+ project_id: siteProject.id,
615
+ title: "Implement contact form",
616
+ type: "feature",
617
+ priority: "medium",
618
+ status: "In Progress",
619
+ })
620
+ await issueService.createIssueInProject({
621
+ project_id: siteProject.id,
622
+ title: "Optimize images for web",
623
+ type: "task",
624
+ priority: "low",
625
+ status: "Todo",
626
+ })
627
+ await issueService.createIssueInProject({
628
+ project_id: siteProject.id,
629
+ title: "Add SEO meta tags",
630
+ type: "task",
631
+ priority: "medium",
632
+ status: "Backlog",
633
+ })
634
+ await issueService.createIssueInProject({
635
+ project_id: siteProject.id,
636
+ title: "Set up Google Analytics",
637
+ type: "task",
638
+ priority: "high",
639
+ status: "Todo",
640
+ sprint_id: siteSprint.id,
641
+ })
642
+ await seedComment(siteHero.id, "Started working on the hero section mockups in Figma.")
643
+ await seedComment(siteHero.id, "Using a full-width video background for the hero. Need sign-off from marketing.")
644
+
645
+ // Project B: Mobile App
646
+ const appProject = await projectService.createProject({
647
+ workspace_id: acme.id,
648
+ name: "Mobile App",
649
+ identifier: "APP",
650
+ color: "#f59e0b",
651
+ })
652
+ await seedStatuses(appProject.id)
653
+ const appSprint = await sprintService.createSprint({
654
+ project_id: appProject.id,
655
+ name: "Sprint 1",
656
+ start_date: now,
657
+ end_date: future(14),
658
+ })
659
+ await sprintService.startSprint(appSprint.id)
660
+
661
+ const appPush = await issueService.createIssueInProject({
662
+ project_id: appProject.id,
663
+ title: "Implement push notifications",
664
+ type: "feature",
665
+ priority: "high",
666
+ status: "In Progress",
667
+ sprint_id: appSprint.id,
668
+ })
669
+ await issueService.createIssueInProject({
670
+ project_id: appProject.id,
671
+ title: "iOS push setup",
672
+ type: "task",
673
+ priority: "medium",
674
+ status: "Todo",
675
+ parent_id: appPush.id,
676
+ })
677
+ await issueService.createIssueInProject({
678
+ project_id: appProject.id,
679
+ title: "Android push setup",
680
+ type: "task",
681
+ priority: "medium",
682
+ status: "Todo",
683
+ parent_id: appPush.id,
684
+ })
685
+ const appCrash = await issueService.createIssueInProject({
686
+ project_id: appProject.id,
687
+ title: "Fix crash on login screen",
688
+ type: "bug",
689
+ priority: "urgent",
690
+ status: "In Review",
691
+ })
692
+ await issueService.createIssueInProject({
693
+ project_id: appProject.id,
694
+ title: "Add dark mode support",
695
+ type: "feature",
696
+ priority: "medium",
697
+ status: "Todo",
698
+ })
699
+ await issueService.createIssueInProject({
700
+ project_id: appProject.id,
701
+ title: "Improve app launch time",
702
+ type: "task",
703
+ priority: "high",
704
+ status: "In Progress",
705
+ })
706
+ await issueService.createIssueInProject({
707
+ project_id: appProject.id,
708
+ title: "Write onboarding flow",
709
+ type: "story",
710
+ priority: "medium",
711
+ status: "Backlog",
712
+ })
713
+ await issueService.createIssueInProject({
714
+ project_id: appProject.id,
715
+ title: "Accessibility audit",
716
+ type: "task",
717
+ priority: "low",
718
+ status: "Todo",
719
+ sprint_id: appSprint.id,
720
+ })
721
+ await seedComment(appCrash.id, "Crash is reproducible on iOS 17.2 with biometric login enabled.")
722
+ await seedComment(appCrash.id, "Root cause: null pointer on the auth token refresh callback. Fix in progress.")
723
+
724
+ // \u2500\u2500 Workspace 2: Starlight Labs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
725
+
726
+ const starlight = await workspaceService.createWorkspace({ name: "Starlight Labs", slug: "starlight-labs" })
727
+
728
+ // Project C: Product Roadmap
729
+ const roadmapProject = await projectService.createProject({
730
+ workspace_id: starlight.id,
731
+ name: "Product Roadmap",
732
+ identifier: "STAR",
733
+ color: "#10b981",
734
+ })
735
+ await seedStatuses(roadmapProject.id)
736
+ const roadmapSprint = await sprintService.createSprint({
737
+ project_id: roadmapProject.id,
738
+ name: "Sprint 1",
739
+ start_date: now,
740
+ end_date: future(21),
741
+ })
742
+ await sprintService.startSprint(roadmapSprint.id)
743
+
744
+ const roadmapOkr = await issueService.createIssueInProject({
745
+ project_id: roadmapProject.id,
746
+ title: "Define Q2 OKRs",
747
+ type: "epic",
748
+ priority: "high",
749
+ status: "In Progress",
750
+ sprint_id: roadmapSprint.id,
751
+ })
752
+ await issueService.createIssueInProject({
753
+ project_id: roadmapProject.id,
754
+ title: "Engineering OKRs",
755
+ type: "task",
756
+ priority: "high",
757
+ status: "Todo",
758
+ parent_id: roadmapOkr.id,
759
+ })
760
+ await issueService.createIssueInProject({
761
+ project_id: roadmapProject.id,
762
+ title: "Product OKRs",
763
+ type: "task",
764
+ priority: "high",
765
+ status: "Todo",
766
+ parent_id: roadmapOkr.id,
767
+ })
768
+ await issueService.createIssueInProject({
769
+ project_id: roadmapProject.id,
770
+ title: "User research interviews",
771
+ type: "task",
772
+ priority: "medium",
773
+ status: "Done",
774
+ })
775
+ await issueService.createIssueInProject({
776
+ project_id: roadmapProject.id,
777
+ title: "Competitive analysis",
778
+ type: "task",
779
+ priority: "medium",
780
+ status: "In Review",
781
+ })
782
+ await issueService.createIssueInProject({
783
+ project_id: roadmapProject.id,
784
+ title: "Draft product spec v1",
785
+ type: "feature",
786
+ priority: "high",
787
+ status: "In Progress",
788
+ })
789
+ await issueService.createIssueInProject({
790
+ project_id: roadmapProject.id,
791
+ title: "Roadmap review with stakeholders",
792
+ type: "task",
793
+ priority: "medium",
794
+ status: "Todo",
795
+ })
796
+ await issueService.createIssueInProject({
797
+ project_id: roadmapProject.id,
798
+ title: "Prioritize feature backlog",
799
+ type: "task",
800
+ priority: "low",
801
+ status: "Backlog",
802
+ sprint_id: roadmapSprint.id,
803
+ })
804
+ await seedComment(roadmapOkr.id, "Synced with leadership \u2014 focus areas are retention and activation for Q2.")
805
+ await seedComment(roadmapOkr.id, "First draft of engineering OKRs shared in Notion. Review by EOW.")
806
+
807
+ // Project D: Marketing Site
808
+ const mktProject = await projectService.createProject({
809
+ workspace_id: starlight.id,
810
+ name: "Marketing Site",
811
+ identifier: "MKT",
812
+ color: "#ec4899",
813
+ })
814
+ await seedStatuses(mktProject.id)
815
+ const mktSprint = await sprintService.createSprint({
816
+ project_id: mktProject.id,
817
+ name: "Sprint 1",
818
+ start_date: now,
819
+ end_date: future(7),
820
+ })
821
+ await sprintService.startSprint(mktSprint.id)
822
+
823
+ const mktPricing = await issueService.createIssueInProject({
824
+ project_id: mktProject.id,
825
+ title: "Redesign pricing page",
826
+ type: "feature",
827
+ priority: "high",
828
+ status: "In Progress",
829
+ sprint_id: mktSprint.id,
830
+ })
831
+ await issueService.createIssueInProject({
832
+ project_id: mktProject.id,
833
+ title: "Update pricing copy",
834
+ type: "task",
835
+ priority: "medium",
836
+ status: "Todo",
837
+ parent_id: mktPricing.id,
838
+ })
839
+ await issueService.createIssueInProject({
840
+ project_id: mktProject.id,
841
+ title: "A/B test variants",
842
+ type: "task",
843
+ priority: "low",
844
+ status: "Backlog",
845
+ parent_id: mktPricing.id,
846
+ })
847
+ await issueService.createIssueInProject({
848
+ project_id: mktProject.id,
849
+ title: "Fix mobile layout issues",
850
+ type: "bug",
851
+ priority: "urgent",
852
+ status: "In Review",
853
+ })
854
+ await issueService.createIssueInProject({
855
+ project_id: mktProject.id,
856
+ title: "Improve page load score",
857
+ type: "task",
858
+ priority: "high",
859
+ status: "Todo",
860
+ })
861
+ await issueService.createIssueInProject({
862
+ project_id: mktProject.id,
863
+ title: "Add blog section",
864
+ type: "feature",
865
+ priority: "medium",
866
+ status: "Backlog",
867
+ })
868
+ await issueService.createIssueInProject({
869
+ project_id: mktProject.id,
870
+ title: "Set up Hotjar",
871
+ type: "task",
872
+ priority: "low",
873
+ status: "Todo",
874
+ })
875
+ await issueService.createIssueInProject({
876
+ project_id: mktProject.id,
877
+ title: "Write 3 launch blog posts",
878
+ type: "task",
879
+ priority: "medium",
880
+ status: "In Progress",
881
+ sprint_id: mktSprint.id,
882
+ })
883
+ await seedComment(mktPricing.id, "New pricing tiers approved by sales. Updating the copy now.")
884
+ await seedComment(mktPricing.id, "Design review scheduled for Thursday. Figma link shared in Slack.")
885
+
886
+ // \u2500\u2500 Workspace 3: DevOps Team \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
887
+
888
+ const devops = await workspaceService.createWorkspace({ name: "DevOps Team", slug: "devops-team" })
889
+
890
+ // Project E: Infrastructure
891
+ const infraProject = await projectService.createProject({
892
+ workspace_id: devops.id,
893
+ name: "Infrastructure",
894
+ identifier: "INFRA",
895
+ color: "#64748b",
896
+ })
897
+ await seedStatuses(infraProject.id)
898
+ const infraSprint = await sprintService.createSprint({
899
+ project_id: infraProject.id,
900
+ name: "Sprint 1",
901
+ start_date: now,
902
+ end_date: future(14),
903
+ })
904
+ await sprintService.startSprint(infraSprint.id)
905
+
906
+ const infraEks = await issueService.createIssueInProject({
907
+ project_id: infraProject.id,
908
+ title: "Migrate to EKS",
909
+ type: "epic",
910
+ priority: "high",
911
+ status: "In Progress",
912
+ sprint_id: infraSprint.id,
913
+ })
914
+ await issueService.createIssueInProject({
915
+ project_id: infraProject.id,
916
+ title: "Set up EKS cluster",
917
+ type: "task",
918
+ priority: "high",
919
+ status: "In Progress",
920
+ parent_id: infraEks.id,
921
+ })
922
+ await issueService.createIssueInProject({
923
+ project_id: infraProject.id,
924
+ title: "Migrate services",
925
+ type: "task",
926
+ priority: "high",
927
+ status: "Todo",
928
+ parent_id: infraEks.id,
929
+ })
930
+ await issueService.createIssueInProject({
931
+ project_id: infraProject.id,
932
+ title: "Implement secrets rotation",
933
+ type: "feature",
934
+ priority: "urgent",
935
+ status: "In Review",
936
+ })
937
+ await issueService.createIssueInProject({
938
+ project_id: infraProject.id,
939
+ title: "Add CloudWatch dashboards",
940
+ type: "task",
941
+ priority: "medium",
942
+ status: "Todo",
943
+ })
944
+ await issueService.createIssueInProject({
945
+ project_id: infraProject.id,
946
+ title: "Reduce AWS costs by 20%",
947
+ type: "task",
948
+ priority: "high",
949
+ status: "Backlog",
950
+ })
951
+ await issueService.createIssueInProject({
952
+ project_id: infraProject.id,
953
+ title: "Set up Datadog APM",
954
+ type: "feature",
955
+ priority: "medium",
956
+ status: "Todo",
957
+ sprint_id: infraSprint.id,
958
+ })
959
+ await issueService.createIssueInProject({
960
+ project_id: infraProject.id,
961
+ title: "Document runbooks",
962
+ type: "task",
963
+ priority: "low",
964
+ status: "Backlog",
965
+ })
966
+ await seedComment(infraEks.id, "EKS cluster provisioned in us-east-1. Starting service migration next week.")
967
+ await seedComment(infraEks.id, "Need to resolve IAM role issues before migrating the auth service.")
968
+
969
+ // Project F: CI/CD Pipeline
970
+ const cicdProject = await projectService.createProject({
971
+ workspace_id: devops.id,
972
+ name: "CI/CD Pipeline",
973
+ identifier: "CICD",
974
+ color: "#8b5cf6",
975
+ })
976
+ await seedStatuses(cicdProject.id)
977
+ const cicdSprint = await sprintService.createSprint({
978
+ project_id: cicdProject.id,
979
+ name: "Sprint 1",
980
+ start_date: now,
981
+ end_date: future(14),
982
+ })
983
+ await sprintService.startSprint(cicdSprint.id)
984
+
985
+ const cicdMatrix = await issueService.createIssueInProject({
986
+ project_id: cicdProject.id,
987
+ title: "Add matrix builds for Node 18/20",
988
+ type: "feature",
989
+ priority: "high",
990
+ status: "In Progress",
991
+ sprint_id: cicdSprint.id,
992
+ })
993
+ await issueService.createIssueInProject({
994
+ project_id: cicdProject.id,
995
+ title: "Node 18 build config",
996
+ type: "task",
997
+ priority: "medium",
998
+ status: "Done",
999
+ parent_id: cicdMatrix.id,
1000
+ })
1001
+ await issueService.createIssueInProject({
1002
+ project_id: cicdProject.id,
1003
+ title: "Node 20 build config",
1004
+ type: "task",
1005
+ priority: "medium",
1006
+ status: "In Progress",
1007
+ parent_id: cicdMatrix.id,
1008
+ })
1009
+ await issueService.createIssueInProject({
1010
+ project_id: cicdProject.id,
1011
+ title: "Flaky test investigation",
1012
+ type: "bug",
1013
+ priority: "high",
1014
+ status: "In Review",
1015
+ })
1016
+ await issueService.createIssueInProject({
1017
+ project_id: cicdProject.id,
1018
+ title: "Add deploy preview environments",
1019
+ type: "feature",
1020
+ priority: "medium",
1021
+ status: "Todo",
1022
+ })
1023
+ await issueService.createIssueInProject({
1024
+ project_id: cicdProject.id,
1025
+ title: "Cache npm dependencies",
1026
+ type: "task",
1027
+ priority: "medium",
1028
+ status: "Done",
1029
+ sprint_id: cicdSprint.id,
1030
+ })
1031
+ await issueService.createIssueInProject({
1032
+ project_id: cicdProject.id,
1033
+ title: "Rollback automation",
1034
+ type: "feature",
1035
+ priority: "high",
1036
+ status: "Backlog",
1037
+ })
1038
+ await issueService.createIssueInProject({
1039
+ project_id: cicdProject.id,
1040
+ title: "Pipeline documentation",
1041
+ type: "task",
1042
+ priority: "low",
1043
+ status: "Todo",
1044
+ })
1045
+ await seedComment(cicdMatrix.id, "Matrix strategy configured. Both Node 18 and 20 now tested on every PR.")
1046
+ await seedComment(cicdMatrix.id, "Node 20 build is failing on the integration test step \u2014 investigating.")
1047
+
1048
+ console.log()
1049
+ console.log(" \u2713 Demo data seeded successfully!")
1050
+ console.log()
1051
+ console.log(" Seeded:")
1052
+ console.log(" 3 workspaces (Acme Corp, Starlight Labs, DevOps Team)")
1053
+ console.log(" 6 projects (Website Redesign, Mobile App, Product Roadmap, Marketing Site, Infrastructure, CI/CD Pipeline)")
1054
+ console.log(" 6 sprints (1 per project, all active)")
1055
+ console.log(" 50+ issues (with child issues and various statuses)")
1056
+ if (authorId) {
1057
+ console.log(" 12 comments (2 per featured issue)")
1058
+ }
1059
+ console.log()
1060
+
1061
+ process.exit(0)
1062
+ }
1063
+
1064
+ main().catch((err) => {
1065
+ console.error()
1066
+ console.error(" \u2716 Seeding failed:", err.message)
1067
+ console.error()
1068
+ process.exit(1)
1069
+ })
1070
+ `;
1071
+ }
503
1072
 
504
1073
  // src/utils.ts
505
1074
  import path from "path";
@@ -637,6 +1206,12 @@ async function runNew(projectName) {
637
1206
  ],
638
1207
  hint: "none selected = add manually later"
639
1208
  },
1209
+ {
1210
+ type: "confirm",
1211
+ name: "seedDemo",
1212
+ message: "Include a demo data seed script?",
1213
+ initial: false
1214
+ },
640
1215
  {
641
1216
  type: "confirm",
642
1217
  name: "installDeps",
@@ -652,7 +1227,8 @@ async function runNew(projectName) {
652
1227
  httpPort: answers.httpPort,
653
1228
  dashboard: answers.dashboard,
654
1229
  dashboardPort: answers.dashboardPort ?? 5174,
655
- optionalModules: answers.optionalModules ?? []
1230
+ optionalModules: answers.optionalModules ?? [],
1231
+ seedDemo: answers.seedDemo ?? false
656
1232
  };
657
1233
  const spinner = ora("Scaffolding project...").start();
658
1234
  try {
@@ -676,6 +1252,12 @@ async function runNew(projectName) {
676
1252
  renderAdminWidgetsIndex()
677
1253
  );
678
1254
  }
1255
+ if (vars.seedDemo) {
1256
+ await writeFile(
1257
+ path2.join(targetDir, "src", "scripts", "seed-demo.ts"),
1258
+ renderSeedScript()
1259
+ );
1260
+ }
679
1261
  spinner.succeed("Scaffolded project files");
680
1262
  } catch (err) {
681
1263
  spinner.fail("Failed to scaffold project files");
@@ -699,6 +1281,9 @@ async function runNew(projectName) {
699
1281
  }
700
1282
  console.log(` ${chalk.dim("cp")} .env.example .env ${chalk.dim("# fill in your DATABASE_URL")}`);
701
1283
  console.log(` ${chalk.cyan("npm run db:migrate")}`);
1284
+ if (vars.seedDemo) {
1285
+ console.log(` ${chalk.cyan("npm run seed:demo")} ${chalk.dim("# optional: load demo data")}`);
1286
+ }
702
1287
  console.log(` ${chalk.cyan("npm run dev")}`);
703
1288
  console.log();
704
1289
  }
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  toKebabCase,
15
15
  toPascalCase,
16
16
  writeFile
17
- } from "./chunk-HSKUQA7V.js";
17
+ } from "./chunk-LNDCRXEG.js";
18
18
 
19
19
  // src/cli.ts
20
20
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runNew
4
- } from "./chunk-HSKUQA7V.js";
4
+ } from "./chunk-LNDCRXEG.js";
5
5
 
6
6
  // src/index.ts
7
7
  var projectName = process.argv[2];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-meridian-app",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Create a new Meridian project or manage an existing one",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",