@rvoh/dream 2.17.1 → 2.18.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 (233) hide show
  1. package/dist/cjs/src/cli/index.js +17 -10
  2. package/dist/cjs/src/dream/Query.js +15 -2
  3. package/dist/cjs/src/dream/QueryDriver/Kysely.js +77 -2
  4. package/dist/cjs/src/dream-app/index.js +13 -16
  5. package/dist/cjs/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +7 -2
  6. package/dist/cjs/src/errors/MaxRecursiveStringCaseDepthExceeded.js +14 -0
  7. package/dist/cjs/src/errors/dream-app/DreamAppInitInvalidEncryptionKey.js +27 -0
  8. package/dist/cjs/src/helpers/cli/generateDreamContent.js +13 -6
  9. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +18 -12
  10. package/dist/cjs/src/helpers/cli/validateStiChildColumns.js +7 -0
  11. package/dist/cjs/src/helpers/stringCasing.js +16 -4
  12. package/dist/esm/src/cli/index.js +17 -10
  13. package/dist/esm/src/dream/Query.js +15 -2
  14. package/dist/esm/src/dream/QueryDriver/Kysely.js +77 -2
  15. package/dist/esm/src/dream-app/index.js +13 -16
  16. package/dist/esm/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +7 -2
  17. package/dist/esm/src/errors/MaxRecursiveStringCaseDepthExceeded.js +14 -0
  18. package/dist/esm/src/errors/dream-app/DreamAppInitInvalidEncryptionKey.js +27 -0
  19. package/dist/esm/src/helpers/cli/generateDreamContent.js +13 -6
  20. package/dist/esm/src/helpers/cli/generateMigrationContent.js +18 -12
  21. package/dist/esm/src/helpers/cli/validateStiChildColumns.js +7 -0
  22. package/dist/esm/src/helpers/stringCasing.js +16 -4
  23. package/dist/types/src/cli/index.d.ts +2 -1
  24. package/dist/types/src/dream/Query.d.ts +9 -0
  25. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +37 -0
  26. package/dist/types/src/dream-app/index.d.ts +4 -2
  27. package/dist/types/src/errors/MaxRecursiveStringCaseDepthExceeded.d.ts +5 -0
  28. package/dist/types/src/errors/dream-app/DreamAppInitInvalidEncryptionKey.d.ts +8 -0
  29. package/dist/types/src/helpers/cli/validateStiChildColumns.d.ts +1 -0
  30. package/docs/assets/hierarchy.js +1 -1
  31. package/docs/assets/search.js +1 -1
  32. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  33. package/docs/classes/db.KyselyQueryDriver.html +34 -34
  34. package/docs/classes/db.PostgresQueryDriver.html +35 -35
  35. package/docs/classes/db.QueryDriverBase.html +33 -33
  36. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  37. package/docs/classes/errors.ColumnOverflow.html +3 -3
  38. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  39. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  40. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  41. package/docs/classes/errors.DecryptionError.html +2 -2
  42. package/docs/classes/errors.DecryptionParseError.html +2 -2
  43. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  44. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  45. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  46. package/docs/classes/errors.InvalidClockTime.html +2 -2
  47. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  48. package/docs/classes/errors.InvalidDateTime.html +2 -2
  49. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  50. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  51. package/docs/classes/errors.NotNullViolation.html +3 -3
  52. package/docs/classes/errors.RecordNotFound.html +3 -3
  53. package/docs/classes/errors.ValidationError.html +3 -3
  54. package/docs/classes/index.CalendarDate.html +33 -33
  55. package/docs/classes/index.ClockTime.html +32 -32
  56. package/docs/classes/index.ClockTimeTz.html +35 -35
  57. package/docs/classes/index.DateTime.html +86 -86
  58. package/docs/classes/index.Decorators.html +19 -19
  59. package/docs/classes/index.Dream.html +118 -118
  60. package/docs/classes/index.DreamApp.html +11 -10
  61. package/docs/classes/index.DreamTransaction.html +2 -2
  62. package/docs/classes/index.Env.html +2 -2
  63. package/docs/classes/index.Query.html +57 -57
  64. package/docs/classes/system.CliFileWriter.html +4 -4
  65. package/docs/classes/system.DreamBin.html +2 -2
  66. package/docs/classes/system.DreamCLI.html +7 -7
  67. package/docs/classes/system.DreamImporter.html +2 -2
  68. package/docs/classes/system.DreamLogos.html +2 -2
  69. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  70. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  71. package/docs/classes/system.PathHelpers.html +3 -3
  72. package/docs/classes/utils.Encrypt.html +3 -3
  73. package/docs/classes/utils.Range.html +2 -2
  74. package/docs/functions/db.closeAllDbConnections.html +1 -1
  75. package/docs/functions/db.dreamDbConnections.html +1 -1
  76. package/docs/functions/db.untypedDb.html +1 -1
  77. package/docs/functions/db.validateColumn.html +1 -1
  78. package/docs/functions/db.validateTable.html +1 -1
  79. package/docs/functions/errors.pgErrorType.html +1 -1
  80. package/docs/functions/index.DreamSerializer.html +1 -1
  81. package/docs/functions/index.ObjectSerializer.html +1 -1
  82. package/docs/functions/index.ReplicaSafe.html +1 -1
  83. package/docs/functions/index.STI.html +1 -1
  84. package/docs/functions/index.SoftDelete.html +1 -1
  85. package/docs/functions/utils.camelize.html +1 -1
  86. package/docs/functions/utils.capitalize.html +1 -1
  87. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  88. package/docs/functions/utils.compact.html +1 -1
  89. package/docs/functions/utils.groupBy.html +1 -1
  90. package/docs/functions/utils.hyphenize.html +1 -1
  91. package/docs/functions/utils.intersection.html +1 -1
  92. package/docs/functions/utils.isEmpty.html +1 -1
  93. package/docs/functions/utils.normalizeUnicode.html +1 -1
  94. package/docs/functions/utils.pascalize.html +1 -1
  95. package/docs/functions/utils.percent.html +1 -1
  96. package/docs/functions/utils.range.html +1 -1
  97. package/docs/functions/utils.round.html +1 -1
  98. package/docs/functions/utils.sanitizeString.html +1 -1
  99. package/docs/functions/utils.snakeify.html +1 -1
  100. package/docs/functions/utils.sort.html +1 -1
  101. package/docs/functions/utils.sortBy.html +1 -1
  102. package/docs/functions/utils.sortObjectByKey.html +1 -1
  103. package/docs/functions/utils.sortObjectByValue.html +1 -1
  104. package/docs/functions/utils.uncapitalize.html +1 -1
  105. package/docs/functions/utils.uniq.html +1 -1
  106. package/docs/hierarchy.html +1 -1
  107. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  108. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  109. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  110. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  111. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  112. package/docs/interfaces/types.DecoratorContext.html +2 -2
  113. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  114. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  115. package/docs/interfaces/types.DreamDbConfig.html +5 -5
  116. package/docs/interfaces/types.DurationObject.html +2 -2
  117. package/docs/interfaces/types.EncryptOptions.html +2 -2
  118. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  119. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  120. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  121. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  122. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  123. package/docs/types/openapi.OpenapiFormats.html +1 -1
  124. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  125. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  126. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  127. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  128. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  129. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  130. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  131. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  132. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  133. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  134. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  135. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  136. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  137. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  138. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  139. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  140. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  141. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  142. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  143. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  144. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  145. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  146. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  148. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  153. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  154. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  155. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  156. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  157. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  158. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  159. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  160. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  161. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  162. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  163. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  164. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  165. package/docs/types/types.CalendarDateObject.html +1 -1
  166. package/docs/types/types.Camelized.html +1 -1
  167. package/docs/types/types.ClockTimeObject.html +1 -1
  168. package/docs/types/types.DbConnectionType.html +1 -1
  169. package/docs/types/types.DbTypes.html +1 -1
  170. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  171. package/docs/types/types.DreamAttributes.html +1 -1
  172. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  173. package/docs/types/types.DreamClassColumn.html +1 -1
  174. package/docs/types/types.DreamColumn.html +1 -1
  175. package/docs/types/types.DreamColumnNames.html +1 -1
  176. package/docs/types/types.DreamLogLevel.html +1 -1
  177. package/docs/types/types.DreamLogger.html +2 -2
  178. package/docs/types/types.DreamModelSerializerType.html +1 -1
  179. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  180. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  181. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  182. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  183. package/docs/types/types.DreamSerializable.html +1 -1
  184. package/docs/types/types.DreamSerializableArray.html +1 -1
  185. package/docs/types/types.DreamSerializerKey.html +1 -1
  186. package/docs/types/types.DreamSerializers.html +1 -1
  187. package/docs/types/types.DreamVirtualColumns.html +1 -1
  188. package/docs/types/types.DurationUnit.html +1 -1
  189. package/docs/types/types.EncryptAlgorithm.html +1 -1
  190. package/docs/types/types.HasManyStatement.html +1 -1
  191. package/docs/types/types.HasOneStatement.html +1 -1
  192. package/docs/types/types.Hyphenized.html +1 -1
  193. package/docs/types/types.Pascalized.html +1 -1
  194. package/docs/types/types.PrimaryKeyType.html +1 -1
  195. package/docs/types/types.RoundingPrecision.html +1 -1
  196. package/docs/types/types.SerializerCasing.html +1 -1
  197. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  198. package/docs/types/types.Snakeified.html +1 -1
  199. package/docs/types/types.StrictInterface.html +1 -1
  200. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  201. package/docs/types/types.UpdateableProperties.html +1 -1
  202. package/docs/types/types.ValidationType.html +1 -1
  203. package/docs/types/types.ViewModel.html +2 -2
  204. package/docs/types/types.ViewModelClass.html +1 -1
  205. package/docs/types/types.WeekdayName.html +1 -1
  206. package/docs/types/types.WhereStatementForDream.html +1 -1
  207. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  208. package/docs/variables/index.DreamConst.html +1 -1
  209. package/docs/variables/index.ops.html +1 -1
  210. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  211. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  212. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  213. package/docs/variables/system.primaryKeyTypes.html +1 -1
  214. package/package.json +1 -1
  215. /package/dist/types/src/types/{types/associations → associations}/belongsTo.ts +0 -0
  216. /package/dist/types/src/types/{types/associations → associations}/hasMany.ts +0 -0
  217. /package/dist/types/src/types/{types/associations → associations}/hasOne.ts +0 -0
  218. /package/dist/types/src/types/{types/associations → associations}/shared.ts +0 -0
  219. /package/dist/types/src/types/{types/calendardate.ts → calendardate.ts} +0 -0
  220. /package/dist/types/src/types/{types/clocktime.ts → clocktime.ts} +0 -0
  221. /package/dist/types/src/types/{types/datetime.ts → datetime.ts} +0 -0
  222. /package/dist/types/src/types/{types/db.ts → db.ts} +0 -0
  223. /package/dist/types/src/types/{types/dream.ts → dream.ts} +0 -0
  224. /package/dist/types/src/types/{types/lifecycle.ts → lifecycle.ts} +0 -0
  225. /package/dist/types/src/types/{types/logger.ts → logger.ts} +0 -0
  226. /package/dist/types/src/types/{types/moduleDeclarations → moduleDeclarations}/luxon.d.ts +0 -0
  227. /package/dist/types/src/types/{types/openapi.ts → openapi.ts} +0 -0
  228. /package/dist/types/src/types/{types/query.ts → query.ts} +0 -0
  229. /package/dist/types/src/types/{types/recursiveSerialization.ts → recursiveSerialization.ts} +0 -0
  230. /package/dist/types/src/types/{types/serializer.ts → serializer.ts} +0 -0
  231. /package/dist/types/src/types/{types/utils.ts → utils.ts} +0 -0
  232. /package/dist/types/src/types/{types/validation.ts → validation.ts} +0 -0
  233. /package/dist/types/src/types/{types/variadic.ts → variadic.ts} +0 -0
@@ -14,6 +14,7 @@ import DreamCLI from '../../cli/index.js';
14
14
  import { CHECK_VIOLATION, COLUMN_OVERFLOW, INVALID_INPUT_SYNTAX, NOT_NULL_VIOLATION, pgErrorType, } from '../../db/errors.js';
15
15
  import syncDbTypesFiles from '../../db/helpers/syncDbTypesFiles.js';
16
16
  import { default as _db } from '../../db/index.js';
17
+ import validateColumn from '../../db/validators/validateColumn.js';
17
18
  import associationToGetterSetterProp from '../../decorators/field/association/associationToGetterSetterProp.js';
18
19
  import PackageManager from '../../dream-app/helpers/PackageManager.js';
19
20
  import DreamApp from '../../dream-app/index.js';
@@ -551,6 +552,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
551
552
  // that can exceed 63 bytes. Short aliases like "pluck0" avoid this entirely.
552
553
  const shortAliases = [];
553
554
  fields.forEach((field, index) => {
555
+ this.validatePlainColumn(this.dreamClass, field);
554
556
  const shortAlias = `pluck${index}`;
555
557
  shortAliases.push(shortAlias);
556
558
  // namespace the selection so that when plucking the same column name from
@@ -719,6 +721,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
719
721
  });
720
722
  if (this.query['orderStatements'].length && !bypassOrder) {
721
723
  this.query['orderStatements'].forEach(orderStatement => {
724
+ this.validatePlainColumn(this.dreamClass, orderStatement.column);
722
725
  kyselyQuery = kyselyQuery.orderBy(this.namespaceColumn(orderStatement.column), this.orderByDirection(orderStatement.direction));
723
726
  });
724
727
  }
@@ -1034,6 +1037,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1034
1037
  if (query['whereStatements'].length ||
1035
1038
  query['whereNotStatements'].length ||
1036
1039
  query['whereAnyStatements'].length) {
1040
+ this.validateBaseWhereStatementColumns(query);
1037
1041
  kyselyQuery = kyselyQuery.where((eb) => eb.and([
1038
1042
  ...this.aliasWhereStatements(query['whereStatements'], query['baseSqlAlias']).map(whereStatement => this.whereStatementToExpressionWrapper(this.dreamClass, eb, whereStatement, {
1039
1043
  disallowSimilarityOperator: false,
@@ -1368,6 +1372,66 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1368
1372
  namespaceColumn(column, alias = this.query['baseSqlAlias']) {
1369
1373
  return namespaceColumn(column, alias);
1370
1374
  }
1375
+ /**
1376
+ * @internal
1377
+ *
1378
+ * Defense-in-depth (DREAM-SQLI-01): when a runtime column identifier is a
1379
+ * plain, un-namespaced column name, validate it against the owning model's
1380
+ * compiled schema so an unknown identifier throws a Dream `InvalidColumnName`
1381
+ * error before it reaches the database (rather than surfacing as a raw
1382
+ * Postgres error or a silent blind-ordering side-channel).
1383
+ *
1384
+ * Only bare identifiers are validated. Namespaced / table-aliased /
1385
+ * association-namespaced identifiers (anything containing a `.`) are left on
1386
+ * their existing path, because the segment before the `.` may be an
1387
+ * association alias or table alias rather than a schema table name, and
1388
+ * validating those safely is not possible here without risking rejection of
1389
+ * currently-valid input.
1390
+ */
1391
+ validatePlainColumn(dreamClass, column) {
1392
+ if (typeof column !== 'string')
1393
+ return;
1394
+ if (column.includes('.'))
1395
+ return;
1396
+ validateColumn(dreamClass.prototype.schema, dreamClass.table, column);
1397
+ }
1398
+ /**
1399
+ * @internal
1400
+ *
1401
+ * Defense-in-depth (DREAM-SQLI-01) for the base model's dynamic `where` keys.
1402
+ * These are the un-namespaced keys the developer passed to `where` /
1403
+ * `whereNot` / `whereAny` on the root query (validated here, before
1404
+ * `aliasWhereStatement` namespaces them with the base alias). Only plain
1405
+ * column keys are validated. Deliberately skips:
1406
+ * - namespaced keys (contain a `.`) — the developer explicitly namespaced
1407
+ * them (e.g. `{ 'users.email': ... }` or a joined table), and the prefix
1408
+ * may be an association/table alias rather than a schema table name;
1409
+ * - association-name keys (e.g. `where({ user: userInstance })`), which are
1410
+ * resolved to foreign keys, not columns;
1411
+ * - `DreamConst.passthrough` / `DreamConst.required` sentinel values, whose
1412
+ * keys are resolved elsewhere.
1413
+ *
1414
+ * Join-and / association where statements (which target other tables and are
1415
+ * pre-namespaced) are left on their existing path.
1416
+ */
1417
+ validateBaseWhereStatementColumns(query) {
1418
+ const dreamClass = query['dreamClass'];
1419
+ const whereStatements = [
1420
+ ...query['whereStatements'],
1421
+ ...query['whereNotStatements'],
1422
+ ...query['whereAnyStatements'].flat(),
1423
+ ];
1424
+ whereStatements.forEach(whereStatement => Object.keys(whereStatement).forEach(attr => {
1425
+ if (attr.includes('.'))
1426
+ return;
1427
+ const val = whereStatement[attr];
1428
+ if (val === DreamConst.passthrough || val === DreamConst.required)
1429
+ return;
1430
+ if (dreamClass.associationNames.includes(attr))
1431
+ return;
1432
+ validateColumn(dreamClass.prototype.schema, dreamClass.table, attr);
1433
+ }));
1434
+ }
1371
1435
  /**
1372
1436
  * @internal
1373
1437
  *
@@ -1924,8 +1988,19 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1924
1988
  scopesQuery = tempQuery;
1925
1989
  }
1926
1990
  }
1927
- if (scopesQuery['whereStatements'].length) {
1928
- join = join.on((eb) => eb.and(scopesQuery['whereStatements'].flatMap(whereStatement => this.whereStatementToExpressionWrapper(dreamClass, eb, this.aliasWhereStatement(whereStatement, tableNameOrAlias), { disallowSimilarityOperator: false }))));
1991
+ if (scopesQuery['whereStatements'].length ||
1992
+ scopesQuery['whereNotStatements'].length ||
1993
+ scopesQuery['whereAnyStatements'].length) {
1994
+ // Mirror the base-table clause logic in QueryDriverBase#buildCommon so that default
1995
+ // scopes expressed with whereNot(...)/whereAny(...) — not just where(...) — cross into
1996
+ // association loads (preload/join/leftJoinPreload/innerJoin). Without the whereNot/whereAny
1997
+ // branches below, such default scopes are silently dropped on association loads, leaking
1998
+ // rows the app intended to hide.
1999
+ join = join.on((eb) => eb.and([
2000
+ ...scopesQuery['whereStatements'].map(whereStatement => this.whereStatementToExpressionWrapper(dreamClass, eb, this.aliasWhereStatement(whereStatement, tableNameOrAlias), { disallowSimilarityOperator: false })),
2001
+ ...scopesQuery['whereNotStatements'].map(whereNotStatement => this.whereStatementToExpressionWrapper(dreamClass, eb, this.aliasWhereStatement(whereNotStatement, tableNameOrAlias), { negate: true })),
2002
+ ...scopesQuery['whereAnyStatements'].map(whereAnyStatements => eb.or(whereAnyStatements.map(whereAnyStatement => this.whereStatementToExpressionWrapper(dreamClass, eb, this.aliasWhereStatement(whereAnyStatement, tableNameOrAlias))))),
2003
+ ]));
1929
2004
  }
1930
2005
  return join;
1931
2006
  }
@@ -4,6 +4,7 @@ import validateTable from '../db/validators/validateTable.js';
4
4
  import Query from '../dream/Query.js';
5
5
  import PostgresQueryDriver from '../dream/QueryDriver/Postgres.js';
6
6
  import Encrypt from '../encrypt/index.js';
7
+ import DreamAppInitInvalidEncryptionKey from '../errors/dream-app/DreamAppInitInvalidEncryptionKey.js';
7
8
  import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppInitMissingCallToLoadModels.js';
8
9
  import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
9
10
  import DreamAppInitMissingPackageManager from '../errors/dream-app/DreamAppInitMissingPackageManager.js';
@@ -119,7 +120,9 @@ export default class DreamApp {
119
120
  if (!this.loadedModels)
120
121
  throw new DreamAppInitMissingCallToLoadModels();
121
122
  if (this.encryption?.columns?.current)
122
- DreamApp.checkKey('columns', this.encryption.columns.current.key, this.encryption.columns.current.algorithm);
123
+ DreamApp.checkKey('columns', 'current', this.encryption.columns.current.key, this.encryption.columns.current.algorithm);
124
+ if (this.encryption?.columns?.legacy)
125
+ DreamApp.checkKey('columns', 'legacy', this.encryption.columns.legacy.key, this.encryption.columns.legacy.algorithm);
123
126
  if (!DreamAppAllowedPackageManagersEnumValues.includes(this.packageManager) &&
124
127
  !EnvInternal.boolean('DREAM_BYPASS_PACKAGE_MANAGER_CHECK'))
125
128
  throw new DreamAppInitMissingPackageManager();
@@ -148,22 +151,9 @@ export default class DreamApp {
148
151
  await dbDriverClass.setDatabaseTypeParsers(connectionName);
149
152
  }
150
153
  }
151
- static checkKey(encryptionIdentifier, key, algorithm) {
154
+ static checkKey(encryptionIdentifier, keyType, key, algorithm) {
152
155
  if (!Encrypt.validateKey(key, algorithm))
153
- // eslint-disable-next-line no-console
154
- console.warn(`
155
- Your current key value for ${encryptionIdentifier} encryption is invalid.
156
- Try setting it to something valid, like:
157
- ${Encrypt.generateKey(algorithm)}
158
-
159
- This was done by calling:
160
- Encrypt.generateKey('${algorithm}'
161
-
162
- A new key can also be generated from the CLI:
163
- % pnpm psy g:encryption-key
164
- OR
165
- % pnpm psy g:encryption-key --algorithm=aes-256-gcm
166
- `);
156
+ throw new DreamAppInitInvalidEncryptionKey(encryptionIdentifier, keyType, algorithm);
167
157
  }
168
158
  /**
169
159
  * Returns the cached dream application if it has been set.
@@ -218,6 +208,10 @@ A new key can also be generated from the CLI:
218
208
  get paginationPageSize() {
219
209
  return this._paginationPageSize;
220
210
  }
211
+ _paginationMaxPageSize = 200;
212
+ get paginationMaxPageSize() {
213
+ return this._paginationMaxPageSize;
214
+ }
221
215
  _primaryKeyType = 'bigint';
222
216
  get primaryKeyType() {
223
217
  return this._primaryKeyType;
@@ -495,6 +489,9 @@ A new key can also be generated from the CLI:
495
489
  case 'paginationPageSize':
496
490
  this._paginationPageSize = options;
497
491
  break;
492
+ case 'paginationMaxPageSize':
493
+ this._paginationMaxPageSize = options;
494
+ break;
498
495
  default: {
499
496
  // protection so that if a new ApplyOpt is ever added, this will throw a type error at build time
500
497
  const _never = applyOption;
@@ -23,8 +23,13 @@ export default function decryptAESGCM(algorithm, encrypted, key) {
23
23
  try {
24
24
  return JSON.parse(plaintext);
25
25
  }
26
- catch (cause) {
27
- throw Object.assign(new DecryptionParseError(), { cause });
26
+ catch {
27
+ // Intentionally drop the underlying SyntaxError as `cause`: its message embeds a
28
+ // snippet of the just-decrypted plaintext (e.g. `Unexpected token 'x', "secret..." is
29
+ // not valid JSON`). Carrying it would leak decrypted plaintext into any logger that
30
+ // serializes `error.cause`. DecryptionParseError's own message is generic and
31
+ // plaintext-free, which is all callers need to diagnose an encrypted-format mismatch.
32
+ throw new DecryptionParseError();
28
33
  }
29
34
  }
30
35
  function unpackPayloadOrFail(payload) {
@@ -0,0 +1,14 @@
1
+ export default class MaxRecursiveStringCaseDepthExceeded extends Error {
2
+ maxDepth;
3
+ constructor(maxDepth) {
4
+ super();
5
+ this.maxDepth = maxDepth;
6
+ }
7
+ get message() {
8
+ return `
9
+ Maximum recursion depth (${this.maxDepth}) exceeded while string-casing an object.
10
+ The input is nested more deeply than Dream will process, which usually means it is
11
+ malformed or maliciously deeply-nested rather than legitimate application data.
12
+ `;
13
+ }
14
+ }
@@ -0,0 +1,27 @@
1
+ import Encrypt from '../../encrypt/index.js';
2
+ export default class DreamAppInitInvalidEncryptionKey extends Error {
3
+ encryptionIdentifier;
4
+ keyType;
5
+ algorithm;
6
+ constructor(encryptionIdentifier, keyType, algorithm) {
7
+ super();
8
+ this.encryptionIdentifier = encryptionIdentifier;
9
+ this.keyType = keyType;
10
+ this.algorithm = algorithm;
11
+ }
12
+ get message() {
13
+ return `
14
+ Your ${this.keyType} key value for ${this.encryptionIdentifier} encryption is invalid.
15
+ Try setting it to something valid, like:
16
+ ${Encrypt.generateKey(this.algorithm)}
17
+
18
+ This was done by calling:
19
+ Encrypt.generateKey('${this.algorithm}')
20
+
21
+ A new key can also be generated from the CLI:
22
+ % pnpm psy g:encryption-key
23
+ OR
24
+ % pnpm psy g:encryption-key --algorithm=aes-256-gcm
25
+ `;
26
+ }
27
+ }
@@ -8,6 +8,7 @@ import snakeify from '../snakeify.js';
8
8
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
9
9
  import uniq from '../uniq.js';
10
10
  import parseAttribute from './parseAttribute.js';
11
+ import validateStiChildColumns from './validateStiChildColumns.js';
11
12
  /**
12
13
  * Column names that are automatically emitted by the model generator (and
13
14
  * the migration generator). When the user passes any of these explicitly,
@@ -26,6 +27,8 @@ export function filterAutoGeneratedTimestampColumns(columnsWithTypes) {
26
27
  }
27
28
  export default function generateDreamContent(options) {
28
29
  const config = createModelConfig(options);
30
+ if (config.isSTI)
31
+ validateStiChildColumns(options.columnsWithTypes);
29
32
  // SoftDelete is incompatible with STI children, so it's only applied to
30
33
  // non-STI-child models.
31
34
  const includeSoftDelete = !config.isSTI && !!options.softDelete;
@@ -59,15 +62,19 @@ export default function generateDreamContent(options) {
59
62
  includeDeletedAt: includeSoftDelete || hasExplicitDeletedAt,
60
63
  });
61
64
  const decoBlock = decoratorsInUse
62
- ? `const deco = new Decorators<typeof ${config.modelClassName}>()`
63
- : `// Uncomment when adding decorators (@deco.BelongsTo, @deco.Validates, etc.):
65
+ ? `const deco = new Decorators<typeof ${config.modelClassName}>()
66
+
67
+ `
68
+ : config.isSTI
69
+ ? ''
70
+ : `// Uncomment when adding decorators (@deco.BelongsTo, @deco.Validates, etc.):
64
71
  // import { Decorators } from '@rvoh/dream'
65
- // const deco = new Decorators<typeof ${config.modelClassName}>()`;
66
- return `${importSection}
72
+ // const deco = new Decorators<typeof ${config.modelClassName}>()
67
73
 
68
- ${decoBlock}
74
+ `;
75
+ return `${importSection}
69
76
 
70
- ${classDeclaration}
77
+ ${decoBlock}${classDeclaration}
71
78
  ${tableMethod}${serializersMethod}${fieldsSection}
72
79
  }
73
80
  `.replace(/^\s*$/gm, '');
@@ -8,7 +8,8 @@ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFu
8
8
  import snakeify from '../snakeify.js';
9
9
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
10
10
  const STI_TYPE_COLUMN_NAME = 'type';
11
- const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
11
+ const DELETED_AT_COLUMN_NAME = 'deleted_at';
12
+ const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME, DELETED_AT_COLUMN_NAME];
12
13
  export default function generateMigrationContent({ connectionName = 'default', table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', stiChildClassName, softDelete = false, } = {}) {
13
14
  const altering = createOrAlter === 'alter';
14
15
  let requireCitextExtension = false;
@@ -25,8 +26,8 @@ export default function generateMigrationContent({ connectionName = 'default', t
25
26
  return name !== 'created_at' && name !== 'updated_at' && name !== 'deleted_at';
26
27
  });
27
28
  const emitDeletedAtColumn = !altering && (softDelete || userExplicitlyPassedDeletedAt);
28
- const { columnDefs, columnDrops, indexDefs, indexDrops } = processedColumnsWithTypes.reduce((acc, attributeDeclaration) => {
29
- const { columnDefs, columnDrops, indexDefs, indexDrops } = acc;
29
+ const { columnDefs, columnDrops, indexDefs } = processedColumnsWithTypes.reduce((acc, attributeDeclaration) => {
30
+ const { columnDefs, columnDrops, indexDefs } = acc;
30
31
  const [rawSegmentOne, _attributeType, ...descriptors] = attributeDeclaration.split(':');
31
32
  if (!rawSegmentOne)
32
33
  return acc;
@@ -129,13 +130,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
129
130
  }
130
131
  columnDrops.push(`.dropColumn('${attributeName}')`);
131
132
  if (processedAttrType === 'belongsto' || COLUMNS_TO_INDEX.includes(attributeName)) {
132
- const indexName = `${table}_${attributeName}`;
133
- indexDefs.push(`await db.schema
134
- .createIndex('${indexName}')
135
- .on('${table}')
136
- .column('${attributeName}')
137
- .execute()`);
138
- indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
133
+ indexDefs.push(columnIndexStatement(table, attributeName));
139
134
  }
140
135
  if (stiChildClassName && !userWantsThisOptional && !arrayAttribute && !isBooleanColumn) {
141
136
  checkConstraints.push(`
@@ -149,7 +144,10 @@ export default function generateMigrationContent({ connectionName = 'default', t
149
144
  .execute()`);
150
145
  }
151
146
  return acc;
152
- }, { columnDefs: [], columnDrops: [], indexDefs: [], indexDrops: [] });
147
+ }, { columnDefs: [], columnDrops: [], indexDefs: [] });
148
+ if (emitDeletedAtColumn) {
149
+ indexDefs.push(columnIndexStatement(table, DELETED_AT_COLUMN_NAME));
150
+ }
153
151
  if (!table) {
154
152
  return `\
155
153
  import { Kysely, sql } from 'kysely'
@@ -196,7 +194,7 @@ ${citextExtension}${generateEnumStatements(columnsWithTypes)} await db.schema
196
194
 
197
195
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
196
  export async function down(db: Kysely<any>): Promise<void> {
199
- ${indexDrops.join(newlineIndent)}${indexDrops.length ? newlineIndent : ''}${altering
197
+ ${altering
200
198
  ? `await db.schema${newlineDoubleIndent}.alterTable('${table}')${columnDropLines}.execute()`
201
199
  : `await db.schema.dropTable('${table}').execute()`}${generateEnumDropStatements(columnsWithTypes)}
202
200
  }\
@@ -393,6 +391,14 @@ function lookupReferencesTable(snakeAssociationName, originalAssociationName) {
393
391
  function associationNameToForeignKey(associationName) {
394
392
  return snakeify(associationName.replace(/\//g, '_').replace(/_id$/, '') + '_id');
395
393
  }
394
+ function columnIndexStatement(table, attributeName) {
395
+ const indexName = `${table}_${attributeName}`;
396
+ return `await db.schema
397
+ .createIndex('${indexName}')
398
+ .on('${table}')
399
+ .column('${attributeName}')
400
+ .execute()`;
401
+ }
396
402
  export function optionalFromDescriptors(descriptors) {
397
403
  const optional = descriptors.at(-1) === 'optional';
398
404
  if (optional)
@@ -0,0 +1,7 @@
1
+ import parseAttribute from './parseAttribute.js';
2
+ export default function validateStiChildColumns(columnsWithTypes) {
3
+ const belongsToColumns = columnsWithTypes.filter(columnWithType => parseAttribute(columnWithType)?.normalizedAttributeType === 'belongsto');
4
+ if (belongsToColumns.length) {
5
+ throw new Error(`STI children cannot declare belongs_to associations. Declare associations on the STI parent instead. Unsupported columns: ${belongsToColumns.join(', ')}`);
6
+ }
7
+ }
@@ -1,22 +1,34 @@
1
1
  import Dream from '../Dream.js';
2
+ import MaxRecursiveStringCaseDepthExceeded from '../errors/MaxRecursiveStringCaseDepthExceeded.js';
2
3
  import BaseClockTime from '../utils/datetime/BaseClockTime.js';
3
4
  import CalendarDate from '../utils/datetime/CalendarDate.js';
4
5
  import { DateTime } from '../utils/datetime/DateTime.js';
5
6
  import isObject from './isObject.js';
7
+ // Maximum object-nesting depth `recursiveStringCase` will traverse. Each nesting
8
+ // level recurses once, so without a cap a deeply-nested input (e.g. a malicious
9
+ // ~480KB JSON body under the request size limit) exhausts the call stack and
10
+ // surfaces as an uncontrolled `RangeError` (500). The cap sits far below the
11
+ // point at which this recursion overflows the stack (measured ~2,000+ levels)
12
+ // while remaining far above any legitimate nesting depth, so real application
13
+ // data — request params, serializer output, config objects — is never affected.
14
+ const MAX_RECURSIVE_STRING_CASE_DEPTH = 500;
6
15
  export default function stringCase(target, stringCaser) {
7
16
  if (typeof target === 'string')
8
17
  return stringCaser(target);
9
- return recursiveStringCase(target, stringCaser);
18
+ return recursiveStringCase(target, stringCaser, 0);
10
19
  }
11
- function recursiveStringCase(target, stringCaser) {
20
+ function recursiveStringCase(target, stringCaser, depth) {
12
21
  if (target === null)
13
22
  return null;
14
23
  if (target === undefined)
15
24
  return undefined;
16
25
  if (typeof target === 'string')
17
26
  return target;
27
+ if (depth >= MAX_RECURSIVE_STRING_CASE_DEPTH) {
28
+ throw new MaxRecursiveStringCaseDepthExceeded(MAX_RECURSIVE_STRING_CASE_DEPTH);
29
+ }
18
30
  if (Array.isArray(target))
19
- return target.map(s => recursiveStringCase(s, stringCaser));
31
+ return target.map(s => recursiveStringCase(s, stringCaser, depth + 1));
20
32
  if (isObject(target)) {
21
33
  if (target instanceof DateTime ||
22
34
  target instanceof CalendarDate ||
@@ -25,7 +37,7 @@ function recursiveStringCase(target, stringCaser) {
25
37
  return target;
26
38
  }
27
39
  return Object.keys(target).reduce((stringCasedObject, targetKey) => {
28
- stringCasedObject[stringCaser(targetKey)] = recursiveStringCase(target[targetKey], stringCaser);
40
+ stringCasedObject[stringCaser(targetKey)] = recursiveStringCase(target[targetKey], stringCaser, depth + 1);
29
41
  return stringCasedObject;
30
42
  }, {});
31
43
  }
@@ -14,7 +14,8 @@ export type SpawnOptions = Omit<NodeSpawnOptions, 'shell'> & {
14
14
  args?: string[];
15
15
  };
16
16
  export declare const CLI_INDENT = " ";
17
- export declare const baseColumnsWithTypesDescription = "space separated snake-case (except for belongs_to model name, which may take an @alias suffix to rename the FK) properties like this:\n title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to\n \n all properties default to not nullable; null can be allowed by appending ':optional':\n subtitle:string:optional\n \n supported types:\n - uuid:\n - uuid[]:\n a column optimized for storing UUIDs\n \n - citext:\n - citext[]:\n case insensitive text (indexes and queries are automatically case insensitive)\n \n - encrypted:\n encrypted text (used in conjunction with the @deco.Encrypted decorator)\n \n - string:\n - string[]:\n varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional\n \n - text\n - text[]\n - date\n - date[]\n - datetime\n - datetime[]\n - time\n - time[]\n - timetz\n - timetz[]\n - integer\n - integer[]\n \n - decimal:\n - decimal[]:\n precision,scale is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: volume:decimal[]:3,2\n \n - enum:\n - enum[]:\n include the enum name to automatically create the enum:\n type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional\n \n omit the enum values to leverage an existing enum (omits the enum type creation):\n type:enum:room_types or type:enum:room_types:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: type:enum[]:room_types:bathroom,kitchen,bedroom";
17
+ export declare const baseColumnsWithTypesDescription = "space separated snake-case properties like this:\n title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal\n \n all properties default to not nullable; null can be allowed by appending ':optional':\n subtitle:string:optional\n \n supported types:\n - uuid:\n - uuid[]:\n a column optimized for storing UUIDs\n \n - citext:\n - citext[]:\n case insensitive text (indexes and queries are automatically case insensitive)\n \n - encrypted:\n encrypted text (used in conjunction with the @deco.Encrypted decorator)\n \n - string:\n - string[]:\n varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional\n \n - text\n - text[]\n - date\n - date[]\n - datetime\n - datetime[]\n - time\n - time[]\n - timetz\n - timetz[]\n - integer\n - integer[]\n \n - decimal:\n - decimal[]:\n precision,scale is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: volume:decimal[]:3,2\n \n - enum:\n - enum[]:\n include the enum name to automatically create the enum:\n type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional\n \n omit the enum values to leverage an existing enum (omits the enum type creation):\n type:enum:room_types or type:enum:room_types:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: type:enum[]:room_types:bathroom,kitchen,bedroom";
18
+ export declare const columnsWithTypesDescriptionForStiChild: string;
18
19
  export default class DreamCLI {
19
20
  /**
20
21
  * Starts the Dream console
@@ -846,6 +846,15 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
846
846
  static dbDriverClass<T extends Dream>(connectionName: string): typeof QueryDriverBase<T>;
847
847
  dbDriverInstance(query?: Query<DreamInstance, any>): QueryDriverBase<DreamInstance>;
848
848
  get connectionName(): any;
849
+ /**
850
+ * @internal
851
+ *
852
+ * Resolves the effective page size for a pagination request: applies the
853
+ * configured default when no page size is requested, and clamps the result to
854
+ * the configured maximum (`paginationMaxPageSize`, default 200) so that a
855
+ * forwarded, attacker-controlled `pageSize` cannot force a full-table load.
856
+ */
857
+ private clampedPaginationPageSize;
849
858
  /**
850
859
  * Paginates the results of your query, accepting a pageSize and page argument,
851
860
  * which it uses to segment your query into pages, leveraging limit and offset
@@ -362,6 +362,43 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
362
362
  * @returns A string
363
363
  */
364
364
  private namespaceColumn;
365
+ /**
366
+ * @internal
367
+ *
368
+ * Defense-in-depth (DREAM-SQLI-01): when a runtime column identifier is a
369
+ * plain, un-namespaced column name, validate it against the owning model's
370
+ * compiled schema so an unknown identifier throws a Dream `InvalidColumnName`
371
+ * error before it reaches the database (rather than surfacing as a raw
372
+ * Postgres error or a silent blind-ordering side-channel).
373
+ *
374
+ * Only bare identifiers are validated. Namespaced / table-aliased /
375
+ * association-namespaced identifiers (anything containing a `.`) are left on
376
+ * their existing path, because the segment before the `.` may be an
377
+ * association alias or table alias rather than a schema table name, and
378
+ * validating those safely is not possible here without risking rejection of
379
+ * currently-valid input.
380
+ */
381
+ private validatePlainColumn;
382
+ /**
383
+ * @internal
384
+ *
385
+ * Defense-in-depth (DREAM-SQLI-01) for the base model's dynamic `where` keys.
386
+ * These are the un-namespaced keys the developer passed to `where` /
387
+ * `whereNot` / `whereAny` on the root query (validated here, before
388
+ * `aliasWhereStatement` namespaces them with the base alias). Only plain
389
+ * column keys are validated. Deliberately skips:
390
+ * - namespaced keys (contain a `.`) — the developer explicitly namespaced
391
+ * them (e.g. `{ 'users.email': ... }` or a joined table), and the prefix
392
+ * may be an association/table alias rather than a schema table name;
393
+ * - association-name keys (e.g. `where({ user: userInstance })`), which are
394
+ * resolved to foreign keys, not columns;
395
+ * - `DreamConst.passthrough` / `DreamConst.required` sentinel values, whose
396
+ * keys are resolved elsewhere.
397
+ *
398
+ * Join-and / association where statements (which target other tables and are
399
+ * pre-namespaced) are left on their existing path.
400
+ */
401
+ private validateBaseWhereStatementColumns;
365
402
  /**
366
403
  * @internal
367
404
  *
@@ -118,6 +118,8 @@ export default class DreamApp {
118
118
  get unicodeNormalization(): UnicodeNormalizationForm;
119
119
  private _paginationPageSize;
120
120
  get paginationPageSize(): number;
121
+ private _paginationMaxPageSize;
122
+ get paginationMaxPageSize(): number;
121
123
  private _primaryKeyType;
122
124
  get primaryKeyType(): LegacyCompatiblePrimaryKeyType;
123
125
  private _projectRoot;
@@ -219,7 +221,7 @@ export default class DreamApp {
219
221
  private requireTestDatabaseClaimSupport;
220
222
  load<RT extends 'models' | 'serializers'>(resourceType: RT, resourcePath: string, importCb: (path: string) => Promise<any>): Promise<void>;
221
223
  plugin(cb: (app: DreamApp) => void | Promise<void>): void;
222
- set<ApplyOpt extends DreamAppSetOption>(applyOption: ApplyOpt, options: ApplyOpt extends 'bypassDeprecationChecks' ? boolean : ApplyOpt extends 'db' ? DreamDbCredentialOptions | string : ApplyOpt extends 'encryption' ? DreamAppEncryptionOptions : ApplyOpt extends 'primaryKeyType' ? LegacyCompatiblePrimaryKeyType : ApplyOpt extends 'importExtension' ? GeneratorImportStyle : ApplyOpt extends 'logger' ? DreamLogger : ApplyOpt extends 'projectRoot' ? string : ApplyOpt extends 'inflections' ? () => void | Promise<void> : ApplyOpt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : ApplyOpt extends 'paths' ? DreamDirectoryPaths : ApplyOpt extends 'parallelTests' ? number : ApplyOpt extends 'unicodeNormalization' ? UnicodeNormalizationForm : ApplyOpt extends 'paginationPageSize' ? number : never, secondaryOptions?: ApplyOpt extends 'db' ? DreamDbCredentialOptions : never): void;
224
+ set<ApplyOpt extends DreamAppSetOption>(applyOption: ApplyOpt, options: ApplyOpt extends 'bypassDeprecationChecks' ? boolean : ApplyOpt extends 'db' ? DreamDbCredentialOptions | string : ApplyOpt extends 'encryption' ? DreamAppEncryptionOptions : ApplyOpt extends 'primaryKeyType' ? LegacyCompatiblePrimaryKeyType : ApplyOpt extends 'importExtension' ? GeneratorImportStyle : ApplyOpt extends 'logger' ? DreamLogger : ApplyOpt extends 'projectRoot' ? string : ApplyOpt extends 'inflections' ? () => void | Promise<void> : ApplyOpt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : ApplyOpt extends 'paths' ? DreamDirectoryPaths : ApplyOpt extends 'parallelTests' ? number : ApplyOpt extends 'unicodeNormalization' ? UnicodeNormalizationForm : ApplyOpt extends 'paginationPageSize' ? number : ApplyOpt extends 'paginationMaxPageSize' ? number : never, secondaryOptions?: ApplyOpt extends 'db' ? DreamDbCredentialOptions : never): void;
223
225
  on<T extends DreamHookEventType>(hookEventType: T, cb: T extends 'db:log' ? (event: KyselyLogEvent) => void : T extends 'repl:start' ? (context: Context) => void | Promise<void> : never): void;
224
226
  }
225
227
  export type DreamHookEventType = 'db:log' | 'repl:start';
@@ -232,7 +234,7 @@ export interface DreamAppOpts {
232
234
  serializerCasing?: DreamSerializerCasing;
233
235
  parallelTests: number | undefined;
234
236
  }
235
- export type DreamAppSetOption = 'bypassDeprecationChecks' | 'db' | 'encryption' | 'inflections' | 'importExtension' | 'logger' | 'paths' | 'primaryKeyType' | 'projectRoot' | 'serializerCasing' | 'parallelTests' | 'unicodeNormalization' | 'paginationPageSize' | 'packageManager';
237
+ export type DreamAppSetOption = 'bypassDeprecationChecks' | 'db' | 'encryption' | 'inflections' | 'importExtension' | 'logger' | 'paths' | 'primaryKeyType' | 'projectRoot' | 'serializerCasing' | 'parallelTests' | 'unicodeNormalization' | 'paginationPageSize' | 'paginationMaxPageSize' | 'packageManager';
236
238
  export interface DreamDirectoryPaths {
237
239
  models?: string;
238
240
  serializers?: string;
@@ -0,0 +1,5 @@
1
+ export default class MaxRecursiveStringCaseDepthExceeded extends Error {
2
+ private maxDepth;
3
+ constructor(maxDepth: number);
4
+ get message(): string;
5
+ }
@@ -0,0 +1,8 @@
1
+ import { EncryptAlgorithm } from '../../encrypt/index.js';
2
+ export default class DreamAppInitInvalidEncryptionKey extends Error {
3
+ private encryptionIdentifier;
4
+ private keyType;
5
+ private algorithm;
6
+ constructor(encryptionIdentifier: 'columns', keyType: 'current' | 'legacy', algorithm: EncryptAlgorithm);
7
+ get message(): string;
8
+ }
@@ -0,0 +1 @@
1
+ export default function validateStiChildColumns(columnsWithTypes: string[]): void;
@@ -1 +1 @@
1
- window.hierarchyData = "eJyVksFOAyEQht9lzlgLtmTL0TYmxlg1MXpoeqC7U5eUhQbYmk3TdzfYC9bq0hOEzM/3McwenLXBg1hQzimhlC4JOFxrLIOyxoPYA6U0LkY2CAJeWnTdzKkdulvpEQhslKlAUFYQaJ0GAaWW3qO/rlaDk+pBHRoN5FgBAoKvrmL86nhAoKyVrhwaEAvG2fJAgHGW0B86j7pLbu3h/6q/xICOhjQqxDVxeLY+fDj0+RZnEj0ekcrZOKFOayw3U2t8cFKZ8KaslvGL/kOjc9b5wV/RHIfRTepgdduYpx26tbafOeQfgRweTzs9k0Hem9I2WxnUSuO7CnU8W0mPdwp1laHQe8dFE8HZmMSmEMqLIaF8UnwPCC+GJ9qv3RaPr4+7R+UbGco60/d8OKd9kyLxmNswb7W+ZFROI33Mw+ELlqZu/Q=="
1
+ window.hierarchyData = "eJyVksFOwzAMht/F5zCajqVVjmxCQogBEoLDtEPWejRamkxJOlRNe3cUdglj0OzkyPLv/7PjPVhjvAO+oIyVhFK6JGBxrbDy0mgHfA+U0hC0aBE4vHRo+5mVO7S3wiEQ2EhdA6d5SaCzCjhUSjiH7rpejU6qR41vFZBjBXDwrr4K8qtjgkDVSFVb1MAXOcuXBwI5yyP3h96h6qOuA/6/6i8hoDdZGRBCjBiejfMfFl06xRnFAEdwZeN48mmD1WZqtPNWSO3fpFEifNF/1mitsW70lzSFYZLFDEZ1rX7aoV0r85ni/EOQ4sfiTc+EF/e6Mu1WeLlS+C59E3Ir4fBOoqoTEAZ7XHQRbJyTsBRCWVkQWmST7wNhZXGC/dpv8Th9eD1K1wpfNYm858UJ6yuyScQxN37eKXXJqZxKhjwPhy/b2G8J"