Fix config read crash when database connection is a string

The readDatabaseConfig function would crash when trying to read
sub-keys of backend.database.connection when the value is a plain
string (e.g. ':memory:' for better-sqlite3). Guard by checking the
raw value type before attempting to read structured connection keys.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-04-30 11:50:58 +02:00
parent be7e4eb48b
commit d7e22c23c4
2 changed files with 19 additions and 1 deletions
@@ -87,6 +87,7 @@ describe('runBackend', () => {
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => undefined,
getOptionalString: () => undefined,
getOptionalNumber: () => undefined,
});
@@ -184,6 +185,7 @@ describe('runBackend', () => {
it('should start embedded DB and inject all defaults when no user connection config is provided', async () => {
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => undefined,
getOptionalString: (key: string) =>
key === 'backend.database.client' ? 'embedded-postgres' : undefined,
getOptionalNumber: () => undefined,
@@ -232,6 +234,7 @@ describe('runBackend', () => {
};
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => ({ host: '0.0.0.0', port: 15432 }),
getOptionalString: (key: string) => {
const val = configValues[key];
return typeof val === 'string' ? val : undefined;
@@ -288,6 +291,12 @@ describe('runBackend', () => {
};
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => ({
host: '0.0.0.0',
port: 15432,
user: 'myuser',
password: 'mypass',
}),
getOptionalString: (key: string) => {
const val = configValues[key];
return typeof val === 'string' ? val : undefined;
@@ -328,6 +337,7 @@ describe('runBackend', () => {
it('should resolve config paths relative to targetDir', async () => {
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => undefined,
getOptionalString: () => undefined,
getOptionalNumber: () => undefined,
});
@@ -346,9 +356,10 @@ describe('runBackend', () => {
);
});
it('should not start embedded DB for other database clients', async () => {
it('should not start embedded DB for other database clients with a string connection', async () => {
mockToConfig.mockResolvedValue({
close: jest.fn(),
getOptional: () => ':memory:',
getOptionalString: (key: string) =>
key === 'backend.database.client' ? 'better-sqlite3' : undefined,
getOptionalNumber: () => undefined,
@@ -252,6 +252,13 @@ async function readDatabaseConfig(
return undefined;
}
// Only read structured connection config if the value is an object;
// it can also be a plain string (e.g. ':memory:' for better-sqlite3).
const rawConnection = config.getOptional('backend.database.connection');
if (typeof rawConnection === 'string' || rawConnection === undefined) {
return { client };
}
const host = config.getOptionalString('backend.database.connection.host');
const port = config.getOptionalNumber('backend.database.connection.port');
const user = config.getOptionalString('backend.database.connection.user');