Skip to content

test: add db seeding script#350

Open
failerko wants to merge 1 commit into
mainfrom
test/db-seed-script
Open

test: add db seeding script#350
failerko wants to merge 1 commit into
mainfrom
test/db-seed-script

Conversation

@failerko

@failerko failerko commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added a database seeding script accessible via the db:seed command. This enables consistent database initialization with sample data for development and testing purposes.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a complete database seeding system for SQLite, enabling deterministic, reproducible population of story data. It introduces a db:seed npm script that executes migrations, wipes existing data, and inserts a pre-built dataset comprising a hero story graph, filler stories, and cross-story singletons.

Changes

Database Seeding System

Layer / File(s) Summary
Seed dataset type and helpers
scripts/seed/dataset.ts
SeedStep type couples tables with type-checked rows; deterministic time constants and Zod validators provide reproducible, schema-validated entity state, story definitions, and story settings.
Hero story comprehensive data
scripts/seed/dataset.ts
Hero entries with computed kinds, chapter metadata, character/location/item/faction entities with validated state, character relationships (ally/rival/wary-of), lore records, threads with trigger/resolution links, happenings with occurrences and character awareness, branch era flips, translations, asset associations, and delta records documenting edits and progression.
Filler stories and singleton seed data
scripts/seed/dataset.ts
Filler-story generator model with optional lead entities and multiple story variations; cross-story singletons including vault calendar rows, asset metadata, pipeline run records, and application settings with provider wiring and narrative model profiles.
Seed dataset orchestration
scripts/seed/dataset.ts
buildSeedSteps() assembles hero story (definition, settings, cover asset, timing, current branch) and hero branch rows (main + fork + filler) into a strictly foreign-key-ordered array of SeedStep objects for all domain tables.
Seed script execution and registration
scripts/seed/index.ts, package.json
Seed script resolves DB path from CLI/environment/default, ensures directory, loads sqlite-vec, applies migrations, wipes data with foreign keys disabled, inserts seed steps in transaction with rollback, logs row counts, and handles errors; db:seed npm script entry invokes the TypeScript entrypoint.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A seedling grows with careful steps,
Foreign keys dance in ordered reps,
Heroes born from type-safe ground,
Fillers bloom, singletons found,
Deterministic tales, reproducible true!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a database seeding script with three new files (package.json script, dataset.ts, and index.ts) to enable deterministic DB seeding.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a database seeding script and a comprehensive mock dataset to populate the application's database. It adds a new db:seed script to package.json, defines structured seed data for stories, branches, chapters, and entities in scripts/seed/dataset.ts, and implements the execution logic in scripts/seed/index.ts using node:sqlite and Drizzle ORM. Feedback on the changes highlights a critical bug in scripts/seed/index.ts where the DatabaseSync constructor is passed an invalid option allowExtension instead of enableLoadExtension, which will cause a runtime TypeError when loading the sqlite-vec extension.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/seed/index.ts
mkdirSync(dirname(dbPath), { recursive: true })
console.log(`[seed] target DB: ${dbPath}`)

const sqlite = new DatabaseSync(dbPath, { allowExtension: true })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In Node.js node:sqlite, the option to allow loading extensions in the DatabaseSync constructor is enableLoadExtension, not allowExtension. Using allowExtension will cause the subsequent call to sqlite.enableLoadExtension(true) to throw a TypeError, silently failing to load the sqlite-vec extension.

Suggested change
const sqlite = new DatabaseSync(dbPath, { allowExtension: true })
const sqlite = new DatabaseSync(dbPath, { enableLoadExtension: true })

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/seed/dataset.ts`:
- Around line 1209-1219: The filler rows currently assign content from
REPLY_LINES for all non-opening entries, so entries where kind === 'user_action'
get AI-reply prose; update the entryRows.push call in the dataset generator to
choose content based on kind: if kind === 'user_action' pick from
ACTION_LINES[(fi + i) % ACTION_LINES.length], otherwise (for 'ai_reply') pick
from REPLY_LINES[(fi + i) % REPLY_LINES.length]; keep the existing opening
branch that uses f.title/f.description and preserve id generation via
entryId(f.key, i), branchId, and position fields.

In `@scripts/seed/index.ts`:
- Around line 46-52: The catch block leaves extension loading enabled if
sqlite.loadExtension(...) throws; change the try/catch to a try/finally (or add
a finally) so that sqlite.enableLoadExtension(false) is always called regardless
of success or error, keeping the current warning behavior in the catch (or
rethrow after finally) and ensuring sqlite.enableLoadExtension(false) runs;
update the block around sqlite.enableLoadExtension(true) /
sqlite.loadExtension(getLoadablePath()) / sqlite.enableLoadExtension(false)
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f27fd23f-a18b-401c-9977-cada63470fd8

📥 Commits

Reviewing files that changed from the base of the PR and between d99b9fc and 7683988.

📒 Files selected for processing (3)
  • package.json
  • scripts/seed/dataset.ts
  • scripts/seed/index.ts

Comment thread scripts/seed/dataset.ts
Comment on lines +1209 to +1219
const kind: NewStoryEntry['kind'] =
i === 1 ? 'opening' : i % 2 === 0 ? 'user_action' : 'ai_reply'
entryRows.push({
id: entryId(f.key, i),
branchId,
position: i,
kind,
content:
i === 1
? `[${f.title}] ${f.description ?? 'An opening scene.'}`
: `${REPLY_LINES[(fi + i) % REPLY_LINES.length]}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Populate filler user_action rows with action text.

Line 1216 currently feeds every non-opening filler entry from REPLY_LINES, so rows marked kind === 'user_action' are seeded with AI-reply prose instead of user-action text. That makes the dataset less representative for any UI or tests that branch on entry kind.

Suggested fix
       entryRows.push({
         id: entryId(f.key, i),
         branchId,
         position: i,
         kind,
         content:
           i === 1
             ? `[${f.title}] ${f.description ?? 'An opening scene.'}`
-            : `${REPLY_LINES[(fi + i) % REPLY_LINES.length]}`,
+            : kind === 'user_action'
+              ? ACTION_LINES[(fi + i) % ACTION_LINES.length]
+              : `${REPLY_LINES[(fi + i) % REPLY_LINES.length]} ${REPLY_BEATS[(fi + i) % REPLY_BEATS.length]}`,
         chapterId: null,
         metadata: entryMetadataSchema.parse({
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/seed/dataset.ts` around lines 1209 - 1219, The filler rows currently
assign content from REPLY_LINES for all non-opening entries, so entries where
kind === 'user_action' get AI-reply prose; update the entryRows.push call in the
dataset generator to choose content based on kind: if kind === 'user_action'
pick from ACTION_LINES[(fi + i) % ACTION_LINES.length], otherwise (for
'ai_reply') pick from REPLY_LINES[(fi + i) % REPLY_LINES.length]; keep the
existing opening branch that uses f.title/f.description and preserve id
generation via entryId(f.key, i), branchId, and position fields.

Comment thread scripts/seed/index.ts
Comment on lines +46 to +52
sqlite.enableLoadExtension(true)
sqlite.loadExtension(getLoadablePath())
sqlite.enableLoadExtension(false)
} catch (err) {
// Non-fatal: no current migration needs sqlite-vec (test-db migrates without it).
console.warn('[seed] sqlite-vec load skipped:', (err as Error).message)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable extension loading in the failure path as well.

If sqlite.loadExtension(...) throws, enableLoadExtension(false) is never reached, so extension loading stays enabled for the rest of the run. Keep it disabled in a finally block to avoid widening attack surface.

Suggested fix
   try {
     sqlite.enableLoadExtension(true)
     sqlite.loadExtension(getLoadablePath())
-    sqlite.enableLoadExtension(false)
   } catch (err) {
     // Non-fatal: no current migration needs sqlite-vec (test-db migrates without it).
     console.warn('[seed] sqlite-vec load skipped:', (err as Error).message)
+  } finally {
+    sqlite.enableLoadExtension(false)
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sqlite.enableLoadExtension(true)
sqlite.loadExtension(getLoadablePath())
sqlite.enableLoadExtension(false)
} catch (err) {
// Non-fatal: no current migration needs sqlite-vec (test-db migrates without it).
console.warn('[seed] sqlite-vec load skipped:', (err as Error).message)
}
try {
sqlite.enableLoadExtension(true)
sqlite.loadExtension(getLoadablePath())
} catch (err) {
// Non-fatal: no current migration needs sqlite-vec (test-db migrates without it).
console.warn('[seed] sqlite-vec load skipped:', (err as Error).message)
} finally {
sqlite.enableLoadExtension(false)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/seed/index.ts` around lines 46 - 52, The catch block leaves extension
loading enabled if sqlite.loadExtension(...) throws; change the try/catch to a
try/finally (or add a finally) so that sqlite.enableLoadExtension(false) is
always called regardless of success or error, keeping the current warning
behavior in the catch (or rethrow after finally) and ensuring
sqlite.enableLoadExtension(false) runs; update the block around
sqlite.enableLoadExtension(true) / sqlite.loadExtension(getLoadablePath()) /
sqlite.enableLoadExtension(false) accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant