Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions api/infrastructure/seeders/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { seedUsers } from './user-seeder'
import { seedProjects } from './project-seeder'
import { seedUserSettings } from './user-setting-seeder'
import { seedProjectSettings } from './project-setting-seeder'
import { seedProjectMembers } from './project-member-seeder'

// ユーザーとプロジェクトを先にシード
await seedUsers()
await seedProjects()

// プロジェクトメンバーをシード
await seedProjectMembers()

// 設定データをシード
await seedUserSettings()
await seedProjectSettings()
143 changes: 143 additions & 0 deletions api/infrastructure/seeders/project-member-seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { randomUUID } from 'crypto'
import { createPrismaClient } from './seed-helper'
import { ProjectMemberEntity } from '~/domain/entities/project-member.entity'

/**
* プロジェクトメンバーシードを実行する
* 既存のプロジェクトに対して、ユーザーをメンバーとして追加する
*/
export async function seedProjectMembers(): Promise<void> {
const prisma = await createPrismaClient()

try {
console.log('📝 プロジェクトメンバーデータのシードを開始します...')

// すべてのプロジェクトを取得
const projects = await prisma.prismaProject.findMany({
where: {
deletedAt: null,
},
select: {
id: true,
login: true,
},
})

if (projects.length === 0) {
console.log('⚠️ プロジェクトが見つかりません。先にプロジェクトをシードしてください。')
return
}

// すべてのユーザーを取得
const users = await prisma.prismaUser.findMany({
where: {
deletedAt: null,
},
select: {
id: true,
login: true,
},
})

if (users.length === 0) {
console.log('⚠️ ユーザーが見つかりません。先にユーザーをシードしてください。')
return
}

// 最初のユーザーをすべてのプロジェクトのオーナーとして設定
const ownerUser = users[0]

// 残りのユーザーをプロジェクトのメンバーとして設定
const memberUsers = users.slice(1)

// 各プロジェクトについて
for (const project of projects) {
console.log(`🏢 プロジェクト '${project.login}' のメンバーをシードします...`)

// オーナーを追加
try {
const existingOwner = await prisma.prismaProjectMember.findUnique({
where: {
projectId_userId: {
projectId: project.id,
userId: ownerUser.id,
},
},
})

if (!existingOwner) {
const ownerEntity = new ProjectMemberEntity({
id: randomUUID(),
projectId: project.id,
userId: ownerUser.id,
role: 'OWNER',
createdAt: new Date(),
})

await prisma.prismaProjectMember.create({
data: {
id: ownerEntity.id,
projectId: ownerEntity.projectId,
userId: ownerEntity.userId,
role: ownerEntity.role,
createdAt: ownerEntity.createdAt,
},
})
console.log(`✅ ユーザー '${ownerUser.login}' をオーナーとして追加しました`)
} else {
console.log(`⚠️ ユーザー '${ownerUser.login}' は既にオーナーとして登録されています`)
}
} catch (error) {
console.error(`❌ オーナーの追加に失敗しました:`, (error as Error).message)
}

// 他のユーザーをランダムなロールで追加
const roles = ['ADMIN', 'MEMBER', 'VIEWER']

for (const user of memberUsers) {
try {
const existingMember = await prisma.prismaProjectMember.findUnique({
where: {
projectId_userId: {
projectId: project.id,
userId: user.id,
},
},
})

if (!existingMember) {
// ランダムなロールを選択
const role = roles[Math.floor(Math.random() * roles.length)] as 'ADMIN' | 'MEMBER' | 'VIEWER'

const memberEntity = new ProjectMemberEntity({
id: randomUUID(),
projectId: project.id,
userId: user.id,
role,
createdAt: new Date(),
})

await prisma.prismaProjectMember.create({
data: {
id: memberEntity.id,
projectId: memberEntity.projectId,
userId: memberEntity.userId,
role: memberEntity.role,
createdAt: memberEntity.createdAt,
},
})
console.log(`✅ ユーザー '${user.login}' を${role}として追加しました`)
} else {
console.log(`⚠️ ユーザー '${user.login}' は既にプロジェクトメンバーとして登録されています`)
}
} catch (error) {
console.error(`❌ メンバーの追加に失敗しました:`, (error as Error).message)
}
}
}

console.log('✨ プロジェクトメンバーデータのシードが完了しました')
} finally {
await prisma.$disconnect()
}
}
68 changes: 68 additions & 0 deletions api/infrastructure/seeders/project-seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { createPrismaClient } from './seed-helper'
import { ProjectEntity } from '~/domain/entities/project.entity'
import { NameValue } from '~/domain/values/name.value'
import { randomUUID } from 'crypto'

// シードするプロジェクトデータ
const projects = [
{
login: 'main-project',
name: 'メインプロジェクト',
},
{
login: 'test-project',
name: 'テストプロジェクト',
},
{
login: 'development',
name: '開発用プロジェクト',
},
]

/**
* プロジェクトシードを実行する
*/
export async function seedProjects(): Promise<void> {
const prisma = await createPrismaClient()

try {
console.log('📝 プロジェクトデータのシードを開始します...')

for (const project of projects) {
const entity = new ProjectEntity({
id: randomUUID(),
login: project.login,
name: new NameValue(project.name),
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
})

try {
// プロジェクトを作成 (既存のloginがあれば更新しない)
await prisma.prismaProject.upsert({
where: { login: entity.login },
update: {},
create: {
id: entity.id,
login: entity.login,
name: entity.name.value,
createdAt: entity.createdAt,
updatedAt: entity.updatedAt,
deletedAt: entity.deletedAt,
},
})
console.log(`✅ プロジェクト '${entity.login}' を作成しました`)
} catch (error) {
console.error(
`❌ プロジェクト '${entity.login}' の作成に失敗しました:`,
(error as Error).message
)
}
}

console.log('✨ プロジェクトデータのシードが完了しました')
} finally {
await prisma.$disconnect()
}
}
101 changes: 101 additions & 0 deletions api/infrastructure/seeders/project-setting-seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { randomUUID } from 'crypto'
import { createPrismaClient } from './seed-helper'
import { ProjectSettingEntity } from '~/domain/entities/project-setting.entity'

// デフォルトのプロジェクト設定データ
const defaultProjectSettings = [
{
keyBase: 'theme',
value: 'default',
},
{
keyBase: 'visibility',
value: 'private',
},
{
keyBase: 'notification',
value: 'enabled',
},
]

/**
* プロジェクト設定シードを実行する
* すべてのプロジェクトに対してデフォルト設定を適用する
*/
export async function seedProjectSettings(): Promise<void> {
const prisma = await createPrismaClient()

try {
console.log('📝 プロジェクト設定データのシードを開始します...')

// すべてのプロジェクトを取得
const projects = await prisma.prismaProject.findMany({
where: {
deletedAt: null,
},
select: {
id: true,
login: true,
},
})

if (projects.length === 0) {
console.log('⚠️ プロジェクトが見つかりません。先にプロジェクトをシードしてください。')
return
}

for (const project of projects) {
console.log(`🏢 プロジェクト '${project.login}' の設定をシードします...`)

for (const setting of defaultProjectSettings) {
try {
// プロジェクト固有のキーを生成
const key = `${project.login}:${setting.keyBase}`

// 既存の設定を確認
const existingSetting = await prisma.prismaProjectSetting.findUnique({
where: {
projectId_key: {
projectId: project.id,
key: key,
},
},
})

if (!existingSetting) {
// エンティティを作成
const entity = new ProjectSettingEntity({
id: randomUUID(),
projectId: project.id,
key: key,
value: setting.value,
createdAt: new Date(),
updatedAt: new Date(),
})

// 設定を作成
await prisma.prismaProjectSetting.create({
data: {
id: entity.id,
projectId: entity.projectId,
key: entity.key,
value: entity.value,
createdAt: entity.createdAt,
updatedAt: entity.updatedAt,
},
})
console.log(`✅ 設定 '${setting.keyBase}' を作成しました`)
} else {
console.log(`⚠️ 設定 '${setting.keyBase}' は既に存在します`)
}
} catch (error) {
console.error(`❌ 設定 '${setting.keyBase}' の作成に失敗しました:`, (error as Error).message)
}
}
}

console.log('✨ プロジェクト設定データのシードが完了しました')
} finally {
await prisma.$disconnect()
}
}
38 changes: 38 additions & 0 deletions api/infrastructure/seeders/seed-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { $ } from 'bun';
import { resolve } from 'node:path';
import { PrismaClient } from "@prisma/client";
import { PrismaLibSQL } from '@prisma/adapter-libsql';

/**
* SQLiteファイルのパスを取得する
*
* @returns Promise<string> SQLiteファイルのURL
* @throws Error SQLiteファイルが見つからない場合
*/
async function getLocalD1DatabasePath() {
// SQLiteファイルのパスを検索
const sqlitePath = await $`find .wrangler/state/v3/d1/miniflare-D1DatabaseObject -type f -name '*.sqlite' -print -quit`.text();

const trimmedPath = sqlitePath.trim();

if (!trimmedPath) {
throw new Error('SQLiteファイルが見つかりませんでした');
}

return `file://${resolve(trimmedPath)}`;
}

/**
* SQLiteデータベースに接続するPrismaClientを作成する
*
* @returns Promise<PrismaClient> PrismaClientインスタンス
*/
export async function createPrismaClient(): Promise<PrismaClient> {
const url = process.env.DATABASE_URL ?? await getLocalD1DatabasePath();

// PrismaLibSQLアダプタとPrismaClientを初期化
const adapter = new PrismaLibSQL({ url });
const prisma = new PrismaClient({ adapter });

return prisma;
}
Loading