@rvoh/dream 2.9.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/dist/cjs/src/dream/QueryDriver/Kysely.js +7 -8
  2. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +1 -1
  3. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/runMigration.js +1 -1
  4. package/dist/cjs/src/dream-app/index.js +14 -6
  5. package/dist/cjs/src/errors/dream-app/MissingDbSslDirective.js +29 -0
  6. package/dist/cjs/src/helpers/comparisonKey.js +2 -0
  7. package/dist/esm/src/dream/QueryDriver/Kysely.js +7 -8
  8. package/dist/esm/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +1 -1
  9. package/dist/esm/src/dream/QueryDriver/helpers/kysely/runMigration.js +1 -1
  10. package/dist/esm/src/dream-app/index.js +14 -6
  11. package/dist/esm/src/errors/dream-app/MissingDbSslDirective.js +29 -0
  12. package/dist/esm/src/helpers/comparisonKey.js +2 -0
  13. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +8 -9
  14. package/dist/types/src/dream-app/index.d.ts +23 -15
  15. package/dist/types/src/errors/dream-app/MissingDbSslDirective.d.ts +6 -0
  16. package/dist/types/src/helpers/comparisonKey.d.ts +1 -1
  17. package/docs/classes/db.DreamMigrationHelpers.html +9 -9
  18. package/docs/classes/db.KyselyQueryDriver.html +32 -32
  19. package/docs/classes/db.PostgresQueryDriver.html +33 -33
  20. package/docs/classes/db.QueryDriverBase.html +31 -31
  21. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  22. package/docs/classes/errors.ColumnOverflow.html +3 -3
  23. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  24. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  25. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  26. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  27. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  28. package/docs/classes/errors.InvalidClockTime.html +2 -2
  29. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  30. package/docs/classes/errors.InvalidDateTime.html +2 -2
  31. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  32. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  33. package/docs/classes/errors.NotNullViolation.html +3 -3
  34. package/docs/classes/errors.RecordNotFound.html +3 -3
  35. package/docs/classes/errors.ValidationError.html +3 -3
  36. package/docs/classes/index.CalendarDate.html +33 -33
  37. package/docs/classes/index.ClockTime.html +32 -32
  38. package/docs/classes/index.ClockTimeTz.html +35 -35
  39. package/docs/classes/index.DateTime.html +86 -86
  40. package/docs/classes/index.Decorators.html +19 -19
  41. package/docs/classes/index.Dream.html +118 -118
  42. package/docs/classes/index.DreamApp.html +5 -5
  43. package/docs/classes/index.DreamTransaction.html +2 -2
  44. package/docs/classes/index.Env.html +2 -2
  45. package/docs/classes/index.Query.html +56 -56
  46. package/docs/classes/system.CliFileWriter.html +4 -4
  47. package/docs/classes/system.DreamBin.html +2 -2
  48. package/docs/classes/system.DreamCLI.html +7 -7
  49. package/docs/classes/system.DreamImporter.html +2 -2
  50. package/docs/classes/system.DreamLogos.html +2 -2
  51. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  52. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  53. package/docs/classes/system.PathHelpers.html +3 -3
  54. package/docs/classes/utils.Encrypt.html +3 -3
  55. package/docs/classes/utils.Range.html +2 -2
  56. package/docs/functions/db.closeAllDbConnections.html +1 -1
  57. package/docs/functions/db.dreamDbConnections.html +1 -1
  58. package/docs/functions/db.untypedDb.html +1 -1
  59. package/docs/functions/db.validateColumn.html +1 -1
  60. package/docs/functions/db.validateTable.html +1 -1
  61. package/docs/functions/errors.pgErrorType.html +1 -1
  62. package/docs/functions/index.DreamSerializer.html +1 -1
  63. package/docs/functions/index.ObjectSerializer.html +1 -1
  64. package/docs/functions/index.ReplicaSafe.html +1 -1
  65. package/docs/functions/index.STI.html +1 -1
  66. package/docs/functions/index.SoftDelete.html +1 -1
  67. package/docs/functions/utils.camelize.html +1 -1
  68. package/docs/functions/utils.capitalize.html +1 -1
  69. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  70. package/docs/functions/utils.compact.html +1 -1
  71. package/docs/functions/utils.groupBy.html +1 -1
  72. package/docs/functions/utils.hyphenize.html +1 -1
  73. package/docs/functions/utils.intersection.html +1 -1
  74. package/docs/functions/utils.isEmpty.html +1 -1
  75. package/docs/functions/utils.normalizeUnicode.html +1 -1
  76. package/docs/functions/utils.pascalize.html +1 -1
  77. package/docs/functions/utils.percent.html +1 -1
  78. package/docs/functions/utils.range.html +1 -1
  79. package/docs/functions/utils.round.html +1 -1
  80. package/docs/functions/utils.sanitizeString.html +1 -1
  81. package/docs/functions/utils.snakeify.html +1 -1
  82. package/docs/functions/utils.sort.html +1 -1
  83. package/docs/functions/utils.sortBy.html +1 -1
  84. package/docs/functions/utils.sortObjectByKey.html +1 -1
  85. package/docs/functions/utils.sortObjectByValue.html +1 -1
  86. package/docs/functions/utils.uncapitalize.html +1 -1
  87. package/docs/functions/utils.uniq.html +1 -1
  88. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  89. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  90. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  91. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  92. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  93. package/docs/interfaces/types.DecoratorContext.html +2 -2
  94. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  95. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  96. package/docs/interfaces/types.DurationObject.html +2 -2
  97. package/docs/interfaces/types.EncryptOptions.html +2 -2
  98. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  99. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  100. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  101. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  102. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  103. package/docs/types/openapi.OpenapiFormats.html +1 -1
  104. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  105. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  106. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  107. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  108. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  109. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  110. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  111. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  112. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  113. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  114. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  115. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  116. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  117. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  118. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  119. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  120. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  121. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  122. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  123. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  124. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  125. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  126. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  127. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  128. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  129. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  130. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  131. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  132. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  133. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  134. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  135. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  136. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  137. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  138. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  139. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  140. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  141. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  142. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  143. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  144. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  145. package/docs/types/types.CalendarDateObject.html +1 -1
  146. package/docs/types/types.Camelized.html +1 -1
  147. package/docs/types/types.ClockTimeObject.html +1 -1
  148. package/docs/types/types.DbConnectionType.html +1 -1
  149. package/docs/types/types.DbTypes.html +1 -1
  150. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  151. package/docs/types/types.DreamAttributes.html +1 -1
  152. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  153. package/docs/types/types.DreamClassColumn.html +1 -1
  154. package/docs/types/types.DreamColumn.html +1 -1
  155. package/docs/types/types.DreamColumnNames.html +1 -1
  156. package/docs/types/types.DreamLogLevel.html +1 -1
  157. package/docs/types/types.DreamLogger.html +2 -2
  158. package/docs/types/types.DreamModelSerializerType.html +1 -1
  159. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  160. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  161. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  162. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  163. package/docs/types/types.DreamSerializable.html +1 -1
  164. package/docs/types/types.DreamSerializableArray.html +1 -1
  165. package/docs/types/types.DreamSerializerKey.html +1 -1
  166. package/docs/types/types.DreamSerializers.html +1 -1
  167. package/docs/types/types.DreamVirtualColumns.html +1 -1
  168. package/docs/types/types.DurationUnit.html +1 -1
  169. package/docs/types/types.EncryptAlgorithm.html +1 -1
  170. package/docs/types/types.HasManyStatement.html +1 -1
  171. package/docs/types/types.HasOneStatement.html +1 -1
  172. package/docs/types/types.Hyphenized.html +1 -1
  173. package/docs/types/types.Pascalized.html +1 -1
  174. package/docs/types/types.PrimaryKeyType.html +1 -1
  175. package/docs/types/types.RoundingPrecision.html +1 -1
  176. package/docs/types/types.SerializerCasing.html +1 -1
  177. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  178. package/docs/types/types.Snakeified.html +1 -1
  179. package/docs/types/types.StrictInterface.html +1 -1
  180. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  181. package/docs/types/types.UpdateableProperties.html +1 -1
  182. package/docs/types/types.ValidationType.html +1 -1
  183. package/docs/types/types.ViewModel.html +2 -2
  184. package/docs/types/types.ViewModelClass.html +1 -1
  185. package/docs/types/types.WeekdayName.html +1 -1
  186. package/docs/types/types.WhereStatementForDream.html +1 -1
  187. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  188. package/docs/variables/index.DreamConst.html +1 -1
  189. package/docs/variables/index.ops.html +1 -1
  190. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  191. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  192. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  193. package/docs/variables/system.primaryKeyTypes.html +1 -1
  194. package/package.json +5 -5
@@ -2047,15 +2047,14 @@ const associationStringToAssociationAndMaybeAlias = function ({ dreamClass, asso
2047
2047
  * Resolve the value passed to `pg.Pool`'s `ssl` field for a given credential.
2048
2048
  *
2049
2049
  * Precedence:
2050
- * 1. If `connectionConf.ssl` is set (boolean or `tls.ConnectionOptions`),
2051
- * pass it straight through to `pg`. This is the verified-TLS path —
2052
- * apps configure `{ rejectUnauthorized: true, ca: <bundle> }` for
2053
- * authenticated TLS against a private PKI, or `true` to use Node's
2054
- * default verification against the system CA store.
2055
- * 2. Else if `connectionConf.useSsl` is `true`, fall back to
2050
+ * 1. If `connectionConf.ssl` is set (object or explicit `false`), pass it
2051
+ * straight through to `pg`.
2052
+ * 2. Else if `connectionConf.useSsl` is `true` (deprecated), fall back to
2056
2053
  * `{ rejectUnauthorized: false }` — encrypted but **not** authenticated.
2057
- * Preserved for back-compat; new code should set `ssl` explicitly.
2058
- * 3. Else disable TLS.
2054
+ *
2055
+ * `assertDbCredentialTlsDirective` (in `dream-app`) throws at
2056
+ * `app.set('db', ...)` time when both `ssl` and `useSsl` are unset, so this
2057
+ * resolver never sees the "neither directive" state.
2059
2058
  */
2060
2059
  export function resolvePostgresSsl(connectionConf) {
2061
2060
  if (connectionConf.ssl !== undefined)
@@ -1,4 +1,4 @@
1
- import { FileMigrationProvider, Migrator } from 'kysely';
1
+ import { FileMigrationProvider, Migrator } from 'kysely/migration';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import { closeAllConnectionsForConnectionName } from '../../../../db/DreamDbConnection.js';
4
4
  import db from '../../../../db/index.js';
@@ -1,4 +1,4 @@
1
- import { FileMigrationProvider, Migrator } from 'kysely';
1
+ import { FileMigrationProvider, Migrator } from 'kysely/migration';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import DreamCLI from '../../../../cli/index.js';
4
4
  import colorize from '../../../../cli/logger/loggable/colorize.js';
@@ -6,6 +6,7 @@ import Encrypt from '../encrypt/index.js';
6
6
  import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppInitMissingCallToLoadModels.js';
7
7
  import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
8
8
  import DreamAppInitMissingPackageManager from '../errors/dream-app/DreamAppInitMissingPackageManager.js';
9
+ import MissingDbSslDirective from '../errors/dream-app/MissingDbSslDirective.js';
9
10
  import autogeneratedFileDisclaimer from '../helpers/cli/autoGeneratedFileDisclaimer.js';
10
11
  import modelClassNameFrom from '../helpers/cli/modelClassNameFrom.js';
11
12
  import EnvInternal from '../helpers/EnvInternal.js';
@@ -345,14 +346,16 @@ A new key can also be generated from the CLI:
345
346
  case 'bypassDeprecationChecks':
346
347
  this._bypassDeprecationChecks = options;
347
348
  break;
348
- case 'db':
349
- if (typeof options === 'string') {
350
- this._dbCredentials[options] = secondaryOptions;
351
- }
352
- else {
353
- this._dbCredentials['default'] = options;
349
+ case 'db': {
350
+ const connectionName = typeof options === 'string' ? options : 'default';
351
+ const credentialOptions = (typeof options === 'string' ? secondaryOptions : options);
352
+ assertDbCredentialTlsDirective(credentialOptions.primary, connectionName, 'primary');
353
+ if (credentialOptions.replica) {
354
+ assertDbCredentialTlsDirective(credentialOptions.replica, connectionName, 'replica');
354
355
  }
356
+ this._dbCredentials[connectionName] = credentialOptions;
355
357
  break;
358
+ }
356
359
  case 'encryption':
357
360
  this._encryption = options;
358
361
  break;
@@ -412,6 +415,11 @@ A new key can also be generated from the CLI:
412
415
  }
413
416
  }
414
417
  }
418
+ function assertDbCredentialTlsDirective(credential, connectionName, credentialKey) {
419
+ if (credential.ssl === undefined && !credential.useSsl) {
420
+ throw new MissingDbSslDirective(connectionName, credentialKey);
421
+ }
422
+ }
415
423
  function loggerArgToString(arg) {
416
424
  if (typeof arg === 'string')
417
425
  return arg;
@@ -0,0 +1,29 @@
1
+ export default class MissingDbSslDirective extends Error {
2
+ connectionName;
3
+ credentialKey;
4
+ constructor(connectionName, credentialKey) {
5
+ super();
6
+ this.connectionName = connectionName;
7
+ this.credentialKey = credentialKey;
8
+ }
9
+ get message() {
10
+ return `
11
+ DreamApp refused to register a db credential without an explicit TLS
12
+ directive. Every \`SingleDbCredential\` passed to \`app.set('db', ...)\`
13
+ must set one of:
14
+
15
+ ssl: { rejectUnauthorized: true } // verified TLS (system CA)
16
+ ssl: { rejectUnauthorized: true, ca: <pem> } // verified TLS (private CA)
17
+ ssl: { rejectUnauthorized: false } // unverified TLS
18
+ ssl: false // TLS disabled
19
+ useSsl: true // legacy, deprecated
20
+
21
+ Omitting the directive used to silently disable TLS. Throwing here
22
+ turns the safety question into a deliberate decision at the call
23
+ site, so a credential cannot reach production with TLS off by accident.
24
+
25
+ connection: ${this.connectionName}
26
+ credential: ${this.credentialKey}
27
+ `;
28
+ }
29
+ }
@@ -13,6 +13,8 @@ export default function comparisonKey(val, toKey = undefined) {
13
13
  case 'string':
14
14
  case 'bigint':
15
15
  return val;
16
+ case 'function':
17
+ return val;
16
18
  default:
17
19
  return val.toString();
18
20
  }
@@ -2047,15 +2047,14 @@ const associationStringToAssociationAndMaybeAlias = function ({ dreamClass, asso
2047
2047
  * Resolve the value passed to `pg.Pool`'s `ssl` field for a given credential.
2048
2048
  *
2049
2049
  * Precedence:
2050
- * 1. If `connectionConf.ssl` is set (boolean or `tls.ConnectionOptions`),
2051
- * pass it straight through to `pg`. This is the verified-TLS path —
2052
- * apps configure `{ rejectUnauthorized: true, ca: <bundle> }` for
2053
- * authenticated TLS against a private PKI, or `true` to use Node's
2054
- * default verification against the system CA store.
2055
- * 2. Else if `connectionConf.useSsl` is `true`, fall back to
2050
+ * 1. If `connectionConf.ssl` is set (object or explicit `false`), pass it
2051
+ * straight through to `pg`.
2052
+ * 2. Else if `connectionConf.useSsl` is `true` (deprecated), fall back to
2056
2053
  * `{ rejectUnauthorized: false }` — encrypted but **not** authenticated.
2057
- * Preserved for back-compat; new code should set `ssl` explicitly.
2058
- * 3. Else disable TLS.
2054
+ *
2055
+ * `assertDbCredentialTlsDirective` (in `dream-app`) throws at
2056
+ * `app.set('db', ...)` time when both `ssl` and `useSsl` are unset, so this
2057
+ * resolver never sees the "neither directive" state.
2059
2058
  */
2060
2059
  export function resolvePostgresSsl(connectionConf) {
2061
2060
  if (connectionConf.ssl !== undefined)
@@ -1,4 +1,4 @@
1
- import { FileMigrationProvider, Migrator } from 'kysely';
1
+ import { FileMigrationProvider, Migrator } from 'kysely/migration';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import { closeAllConnectionsForConnectionName } from '../../../../db/DreamDbConnection.js';
4
4
  import db from '../../../../db/index.js';
@@ -1,4 +1,4 @@
1
- import { FileMigrationProvider, Migrator } from 'kysely';
1
+ import { FileMigrationProvider, Migrator } from 'kysely/migration';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import DreamCLI from '../../../../cli/index.js';
4
4
  import colorize from '../../../../cli/logger/loggable/colorize.js';
@@ -6,6 +6,7 @@ import Encrypt from '../encrypt/index.js';
6
6
  import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppInitMissingCallToLoadModels.js';
7
7
  import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
8
8
  import DreamAppInitMissingPackageManager from '../errors/dream-app/DreamAppInitMissingPackageManager.js';
9
+ import MissingDbSslDirective from '../errors/dream-app/MissingDbSslDirective.js';
9
10
  import autogeneratedFileDisclaimer from '../helpers/cli/autoGeneratedFileDisclaimer.js';
10
11
  import modelClassNameFrom from '../helpers/cli/modelClassNameFrom.js';
11
12
  import EnvInternal from '../helpers/EnvInternal.js';
@@ -345,14 +346,16 @@ A new key can also be generated from the CLI:
345
346
  case 'bypassDeprecationChecks':
346
347
  this._bypassDeprecationChecks = options;
347
348
  break;
348
- case 'db':
349
- if (typeof options === 'string') {
350
- this._dbCredentials[options] = secondaryOptions;
351
- }
352
- else {
353
- this._dbCredentials['default'] = options;
349
+ case 'db': {
350
+ const connectionName = typeof options === 'string' ? options : 'default';
351
+ const credentialOptions = (typeof options === 'string' ? secondaryOptions : options);
352
+ assertDbCredentialTlsDirective(credentialOptions.primary, connectionName, 'primary');
353
+ if (credentialOptions.replica) {
354
+ assertDbCredentialTlsDirective(credentialOptions.replica, connectionName, 'replica');
354
355
  }
356
+ this._dbCredentials[connectionName] = credentialOptions;
355
357
  break;
358
+ }
356
359
  case 'encryption':
357
360
  this._encryption = options;
358
361
  break;
@@ -412,6 +415,11 @@ A new key can also be generated from the CLI:
412
415
  }
413
416
  }
414
417
  }
418
+ function assertDbCredentialTlsDirective(credential, connectionName, credentialKey) {
419
+ if (credential.ssl === undefined && !credential.useSsl) {
420
+ throw new MissingDbSslDirective(connectionName, credentialKey);
421
+ }
422
+ }
415
423
  function loggerArgToString(arg) {
416
424
  if (typeof arg === 'string')
417
425
  return arg;
@@ -0,0 +1,29 @@
1
+ export default class MissingDbSslDirective extends Error {
2
+ connectionName;
3
+ credentialKey;
4
+ constructor(connectionName, credentialKey) {
5
+ super();
6
+ this.connectionName = connectionName;
7
+ this.credentialKey = credentialKey;
8
+ }
9
+ get message() {
10
+ return `
11
+ DreamApp refused to register a db credential without an explicit TLS
12
+ directive. Every \`SingleDbCredential\` passed to \`app.set('db', ...)\`
13
+ must set one of:
14
+
15
+ ssl: { rejectUnauthorized: true } // verified TLS (system CA)
16
+ ssl: { rejectUnauthorized: true, ca: <pem> } // verified TLS (private CA)
17
+ ssl: { rejectUnauthorized: false } // unverified TLS
18
+ ssl: false // TLS disabled
19
+ useSsl: true // legacy, deprecated
20
+
21
+ Omitting the directive used to silently disable TLS. Throwing here
22
+ turns the safety question into a deliberate decision at the call
23
+ site, so a credential cannot reach production with TLS off by accident.
24
+
25
+ connection: ${this.connectionName}
26
+ credential: ${this.credentialKey}
27
+ `;
28
+ }
29
+ }
@@ -13,6 +13,8 @@ export default function comparisonKey(val, toKey = undefined) {
13
13
  case 'string':
14
14
  case 'bigint':
15
15
  return val;
16
+ case 'function':
17
+ return val;
16
18
  default:
17
19
  return val.toString();
18
20
  }
@@ -473,14 +473,13 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
473
473
  * Resolve the value passed to `pg.Pool`'s `ssl` field for a given credential.
474
474
  *
475
475
  * Precedence:
476
- * 1. If `connectionConf.ssl` is set (boolean or `tls.ConnectionOptions`),
477
- * pass it straight through to `pg`. This is the verified-TLS path —
478
- * apps configure `{ rejectUnauthorized: true, ca: <bundle> }` for
479
- * authenticated TLS against a private PKI, or `true` to use Node's
480
- * default verification against the system CA store.
481
- * 2. Else if `connectionConf.useSsl` is `true`, fall back to
476
+ * 1. If `connectionConf.ssl` is set (object or explicit `false`), pass it
477
+ * straight through to `pg`.
478
+ * 2. Else if `connectionConf.useSsl` is `true` (deprecated), fall back to
482
479
  * `{ rejectUnauthorized: false }` — encrypted but **not** authenticated.
483
- * Preserved for back-compat; new code should set `ssl` explicitly.
484
- * 3. Else disable TLS.
480
+ *
481
+ * `assertDbCredentialTlsDirective` (in `dream-app`) throws at
482
+ * `app.set('db', ...)` time when both `ssl` and `useSsl` are unset, so this
483
+ * resolver never sees the "neither directive" state.
485
484
  */
486
- export declare function resolvePostgresSsl(connectionConf: SingleDbCredential): boolean | TlsConnectionOptions;
485
+ export declare function resolvePostgresSsl(connectionConf: SingleDbCredential): TlsConnectionOptions | false;
@@ -213,27 +213,35 @@ export interface SingleDbCredential {
213
213
  /**
214
214
  * @deprecated Use `ssl` instead.
215
215
  *
216
- * The legacy boolean opt-in for Postgres TLS. When `true` (and `ssl` is not
216
+ * Legacy boolean opt-in for Postgres TLS. When `true` (and `ssl` is not
217
217
  * set), Dream connects with `{ rejectUnauthorized: false }` — TLS is on but
218
- * the server certificate is not verified. The new `ssl` field accepts a
219
- * full `tls.ConnectionOptions` object so callers can opt into verified TLS
220
- * (`ssl: { rejectUnauthorized: true, ca: readFileSync('ca.pem') }`) or use
221
- * Node's defaults (`ssl: true`). This field is preserved for back-compat
222
- * and will be removed in a future major version.
218
+ * the server certificate is not verified. Preserved for back-compat and
219
+ * will be removed in a future major version. New code should set `ssl`
220
+ * directly.
223
221
  */
224
222
  useSsl?: boolean;
225
223
  /**
226
- * Optional explicit TLS configuration passed straight through to `pg.Pool`'s
227
- * `ssl` field. Takes precedence over the deprecated `useSsl` when provided.
224
+ * TLS configuration passed straight through to `pg.Pool`'s `ssl` field.
225
+ * Takes precedence over the deprecated `useSsl` when provided.
228
226
  *
229
- * - `true` lets `pg` use Node's defaults (verified TLS against the system CA).
230
- * - `false` disables TLS.
231
- * - An object is `tls.ConnectionOptions` set `rejectUnauthorized: true` plus
232
- * a `ca` bundle for verified TLS against a private PKI; set
233
- * `rejectUnauthorized: false` only if you accept opportunistic-TLS-without-
234
- * authentication (the historical default produced by `useSsl: true` alone).
227
+ * Set `rejectUnauthorized: true` (Node's own default) for verified TLS
228
+ * against the system CA store — the right choice for managed providers that
229
+ * present a public-CA-signed certificate (Supabase, Neon, Render, Azure
230
+ * Database for PostgreSQL on Flexible Server, etc.).
231
+ *
232
+ * For providers that present a private-CA certificate (AWS RDS,
233
+ * GCP Cloud SQL), add a `ca` bundle:
234
+ * `ssl: { rejectUnauthorized: true, ca: readFileSync('rds-ca.pem') }`.
235
+ *
236
+ * For providers that present a self-signed certificate (Heroku Hobby,
237
+ * some local docker images), set `rejectUnauthorized: false` — encrypted
238
+ * but unauthenticated.
239
+ *
240
+ * Set `false` to disable TLS entirely. Omitting `ssl` (and `useSsl`) throws
241
+ * at `app.set('db', ...)` time so the safety question is a deliberate
242
+ * decision at the call site rather than a silent default.
235
243
  */
236
- ssl?: boolean | TlsConnectionOptions;
244
+ ssl?: TlsConnectionOptions | false;
237
245
  }
238
246
  export type DreamLogger = {
239
247
  info: (...args: any[]) => void;
@@ -0,0 +1,6 @@
1
+ export default class MissingDbSslDirective extends Error {
2
+ private connectionName;
3
+ private credentialKey;
4
+ constructor(connectionName: string, credentialKey: 'primary' | 'replica');
5
+ get message(): string;
6
+ }
@@ -1 +1 @@
1
- export default function comparisonKey<ElementType>(val: ElementType, toKey?: ((a: ElementType) => string | number | bigint) | undefined): number | string | bigint | null | undefined;
1
+ export default function comparisonKey<ElementType>(val: ElementType, toKey?: ((a: ElementType) => string | number | bigint) | undefined): number | string | bigint | null | undefined | ((...args: any[]) => any);