feat(seed): ~5x richer demo data via deterministic generators
Rewrite scripts/seed-demo.ts as a thin orchestrator over a new scripts/seed/ module (rng, pools, helpers, content, schedule, logs, generators). Scales demo data from 6 users/3 projects to ~30 users/15 projects with ~5-8x per-table content (~6.8x total rows) via a seeded mulberry32 PRNG for full reproducibility (incl. bcrypt salts and file/URL identifiers). FK-safe ordering, real captured IDs for activity logs, enum pools typed against lib/types. Preserves canonical login credentials and projects.
This commit is contained in:
70
scripts/seed/logs.ts
Normal file
70
scripts/seed/logs.ts
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 通知とアクティビティログの生成器。アクティビティログは実IDを参照する。
|
||||
*/
|
||||
import type { SqliteDatabase } from '@/lib/db/sqlite';
|
||||
import { chance, pick, randInt, type Rng } from './rng';
|
||||
import { ACTIVITY_ACTIONS, NOTIF_TEMPLATES } from './pools';
|
||||
import { type ActivityContext, insert, now } from './helpers';
|
||||
|
||||
export function seedNotifications(
|
||||
db: SqliteDatabase,
|
||||
rng: Rng,
|
||||
projectId: number,
|
||||
memberIds: number[]
|
||||
): void {
|
||||
const count = randInt(rng, 3, 5);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const t = pick(rng, NOTIF_TEMPLATES);
|
||||
insert(
|
||||
db,
|
||||
`INSERT INTO notifications (user_id, project_id, type, title, body, read_at, created_at)
|
||||
VALUES (@userId, @projectId, @type, @title, @body, @readAt, @createdAt)`,
|
||||
{
|
||||
userId: pick(rng, memberIds),
|
||||
projectId,
|
||||
type: t.type,
|
||||
title: t.title,
|
||||
body: t.body,
|
||||
readAt: chance(rng, 0.3) ? now() : null,
|
||||
createdAt: now(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function seedActivityLogs(
|
||||
db: SqliteDatabase,
|
||||
rng: Rng,
|
||||
projectId: number,
|
||||
memberIds: number[],
|
||||
ctx: ActivityContext
|
||||
): void {
|
||||
const targetsByType: Record<string, number[]> = {
|
||||
thread: ctx.threadIds,
|
||||
comment: ctx.commentIds,
|
||||
todo: ctx.todoIds,
|
||||
file: ctx.fileIds,
|
||||
meeting: ctx.meetingIds,
|
||||
note: ctx.noteIds,
|
||||
milestone: ctx.milestoneIds,
|
||||
};
|
||||
const count = randInt(rng, 8, 12);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const a = pick(rng, ACTIVITY_ACTIONS);
|
||||
const pool = targetsByType[a.targetType] ?? [];
|
||||
if (pool.length === 0) continue;
|
||||
insert(
|
||||
db,
|
||||
`INSERT INTO activity_logs (project_id, actor_id, action, target_type, target_id, metadata_json, created_at)
|
||||
VALUES (@projectId, @actorId, @action, @targetType, @targetId, NULL, @createdAt)`,
|
||||
{
|
||||
projectId,
|
||||
actorId: pick(rng, memberIds),
|
||||
action: a.action,
|
||||
targetType: a.targetType,
|
||||
targetId: pick(rng, pool),
|
||||
createdAt: now(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user