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.
- package/dist/{chunk-HSKUQA7V.js → chunk-LNDCRXEG.js} +603 -18
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
119
|
-
accessKeyId: process.env.
|
|
120
|
-
secretAccessKey: process.env.
|
|
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.
|
|
128
|
-
region: process.env.
|
|
129
|
-
accessKeyId: process.env.
|
|
130
|
-
secretAccessKey: process.env.
|
|
131
|
-
//
|
|
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
|
-
|
|
249
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
package/dist/index.js
CHANGED