Skip to content

Fix the unreachable unknown-database-type guard (#1091) - #1092

Open
gangster wants to merge 1 commit into
shift-org:mainfrom
gangster:config-db-type-guard
Open

Fix the unreachable unknown-database-type guard (#1091)#1092
gangster wants to merge 1 commit into
shift-org:mainfrom
gangster:config-db-type-guard

Conversation

@gangster

@gangster gangster commented Aug 5, 2026

Copy link
Copy Markdown

Fixes #1091.

!name in config parses as (!name) in config, so the guard tested whether the boolean false was a key of the config object. It never is, so the throw was unreachable for every input, and an unrecognised --db value failed two lines later instead:

$ npm test --db=postgres
TypeError: config[name] is not a function
npm error code 7
-  if (!name in config) {
+  if (!Object.hasOwn(config, name)) {
     throw new Error(`unknown database type '${dbType}'`)
   }

Why Object.hasOwn rather than !(name in config)

The minimal correction fixes the precedence but leaves a second hole, because in walks the prototype chain and config is a plain object literal. On current main:

$ npm_config_db=toString node -e "require('./app/config.js')"
no error. db config = {"type":"toString","connect":"[object Object]","debug":false}

config.toString(parts) returns the string "[object Object]", which is passed on as the connection settings and fails somewhere less obvious in db.js. !(name in config) would not catch that; hasOwn does, at the same length. Same bug class as #1089.

Verification

Unknown types now produce the intended message:

--db=postgres      Error: unknown database type 'postgres'
--db=toString      Error: unknown database type 'toString'
--db=constructor   Error: unknown database type 'constructor'
--db=banana        Error: unknown database type 'banana'

Valid types are unchanged:

--db= resolves to
sqlite type=sqlite connect={"name":":memory:"}
mysql type=mysql connect={"host":"db","port":3306,...}
sqlite:../bin/events.db type=sqlite connect={"name":".../bin/events.db"}
(none) type=mysql

The sqlite:<path> row is the one worth noting: the guard sits immediately after dbType.split(':'), so it confirms the parts handling still works.

npm test is 53/53, and npm test --db=sqlite also passes.

No test

config.js reads the environment at require time and exports a plain object, so there is no seam to assert against without exporting getDatabaseConfig for testing. That is the house pattern elsewhere (calEventValidator, ical.js), but it widens the module's surface for a one-line fix, so I left it alone and verified manually as above. Happy to add it if you would rather have the coverage.

Object.hasOwn needs Node 16.9+; docker-compose.yml pins node:24.15.0-slim.

'!name in config' parses as '(!name) in config', which tests whether
the boolean false is a key of the config object. It never is, so the
throw was dead code for every input. An unrecognised --db value
instead failed two lines later with "TypeError: config[name] is not a
function", pointing at the wrong line.

Use Object.hasOwn rather than the minimal '!(name in config)': plain
'in' walks the prototype chain, so --db=toString would have passed the
guard and handed config.toString(parts), the string "[object Object]",
on as the connection settings.

Unknown types now report "unknown database type '<name>'" as intended.
sqlite, mysql, sqlite:<path> and the no-argument default are
unchanged.
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.

Unknown --db values report a TypeError instead of the intended error

1 participant