@rvoh/dream 1.9.4 → 1.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 (262) hide show
  1. package/dist/cjs/src/Dream.js +61 -2
  2. package/dist/cjs/src/bin/index.js +6 -0
  3. package/dist/cjs/src/cli/index.js +19 -11
  4. package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +19 -0
  5. package/dist/cjs/src/decorators/field/association/BelongsTo.js +2 -2
  6. package/dist/cjs/src/decorators/field/association/HasMany.js +2 -2
  7. package/dist/cjs/src/decorators/field/association/HasOne.js +2 -2
  8. package/dist/cjs/src/dream/Query.js +4 -1
  9. package/dist/cjs/src/dream/QueryDriver/Base.js +6 -0
  10. package/dist/cjs/src/dream/QueryDriver/Kysely.js +11 -3
  11. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +27 -0
  12. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.js +11 -0
  13. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/runMigration.js +11 -13
  14. package/dist/cjs/src/dream/internal/orderByDirection.js +2 -3
  15. package/dist/cjs/src/dream/internal/undestroyDream.js +2 -2
  16. package/dist/cjs/src/dream-app/index.js +4 -4
  17. package/dist/cjs/src/errors/associations/InvalidComputedForeignKey.js +3 -4
  18. package/dist/cjs/src/helpers/cli/SchemaBuilder.js +30 -23
  19. package/dist/cjs/src/helpers/cli/generateDreamContent.js +7 -5
  20. package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -0
  21. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +17 -16
  22. package/dist/cjs/src/helpers/cli/generateSerializerContent.js +3 -3
  23. package/dist/cjs/src/helpers/comparisonKey.js +16 -1
  24. package/dist/cjs/src/helpers/percent.js +10 -0
  25. package/dist/cjs/src/helpers/sort.js +0 -3
  26. package/dist/cjs/src/helpers/sortBy.js +11 -2
  27. package/dist/cjs/src/helpers/uniq.js +5 -8
  28. package/dist/cjs/src/index.js +3 -1
  29. package/dist/esm/src/Dream.js +61 -2
  30. package/dist/esm/src/bin/index.js +6 -0
  31. package/dist/esm/src/cli/index.js +19 -11
  32. package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +19 -0
  33. package/dist/esm/src/decorators/field/association/BelongsTo.js +2 -2
  34. package/dist/esm/src/decorators/field/association/HasMany.js +2 -2
  35. package/dist/esm/src/decorators/field/association/HasOne.js +2 -2
  36. package/dist/esm/src/dream/Query.js +4 -1
  37. package/dist/esm/src/dream/QueryDriver/Base.js +6 -0
  38. package/dist/esm/src/dream/QueryDriver/Kysely.js +12 -4
  39. package/dist/esm/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +24 -0
  40. package/dist/esm/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.js +8 -0
  41. package/dist/esm/src/dream/QueryDriver/helpers/kysely/runMigration.js +3 -5
  42. package/dist/esm/src/dream/internal/orderByDirection.js +2 -3
  43. package/dist/esm/src/dream/internal/undestroyDream.js +2 -2
  44. package/dist/esm/src/dream-app/index.js +4 -4
  45. package/dist/esm/src/errors/associations/InvalidComputedForeignKey.js +3 -4
  46. package/dist/esm/src/helpers/cli/SchemaBuilder.js +30 -23
  47. package/dist/esm/src/helpers/cli/generateDreamContent.js +7 -5
  48. package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -0
  49. package/dist/esm/src/helpers/cli/generateMigrationContent.js +17 -16
  50. package/dist/esm/src/helpers/cli/generateSerializerContent.js +3 -3
  51. package/dist/esm/src/helpers/comparisonKey.js +16 -1
  52. package/dist/esm/src/helpers/percent.js +7 -0
  53. package/dist/esm/src/helpers/sort.js +0 -3
  54. package/dist/esm/src/helpers/sortBy.js +11 -2
  55. package/dist/esm/src/helpers/uniq.js +5 -8
  56. package/dist/esm/src/index.js +1 -0
  57. package/dist/types/src/Dream.d.ts +46 -4
  58. package/dist/types/src/bin/index.d.ts +1 -0
  59. package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +16 -0
  60. package/dist/types/src/decorators/field/sortable/helpers/setPosition.d.ts +1 -1
  61. package/dist/types/src/dream/QueryDriver/Base.d.ts +1 -0
  62. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +3 -2
  63. package/dist/types/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.d.ts +9 -0
  64. package/dist/types/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.d.ts +1 -0
  65. package/dist/types/src/dream/internal/orderByDirection.d.ts +2 -1
  66. package/dist/types/src/dream-app/index.d.ts +2 -2
  67. package/dist/types/src/helpers/comparisonKey.d.ts +1 -1
  68. package/dist/types/src/helpers/percent.d.ts +2 -0
  69. package/dist/types/src/helpers/sort.d.ts +3 -1
  70. package/dist/types/src/helpers/sortBy.d.ts +4 -0
  71. package/dist/types/src/index.d.ts +1 -0
  72. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +1 -1
  73. package/dist/types/src/types/associations/belongsTo.d.ts +2 -2
  74. package/dist/types/src/types/associations/belongsTo.ts +2 -2
  75. package/dist/types/src/types/associations/shared.d.ts +2 -2
  76. package/dist/types/src/types/associations/shared.ts +2 -2
  77. package/dist/types/src/types/dream.d.ts +17 -4
  78. package/dist/types/src/types/dream.ts +38 -13
  79. package/dist/types/src/types/serializer.d.ts +1 -1
  80. package/dist/types/src/types/serializer.ts +1 -1
  81. package/dist/types/src/types/variadic.ts +4 -0
  82. package/docs/assets/navigation.js +1 -1
  83. package/docs/assets/search.js +1 -1
  84. package/docs/classes/Benchmark.html +2 -2
  85. package/docs/classes/CalendarDate.html +2 -2
  86. package/docs/classes/CheckConstraintViolation.html +3 -3
  87. package/docs/classes/CliFileWriter.html +2 -2
  88. package/docs/classes/ColumnOverflow.html +3 -3
  89. package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
  90. package/docs/classes/DataIncompatibleWithDatabaseField.html +3 -3
  91. package/docs/classes/DataTypeColumnTypeMismatch.html +3 -3
  92. package/docs/classes/Decorators.html +19 -19
  93. package/docs/classes/Dream.html +201 -174
  94. package/docs/classes/DreamApp.html +4 -4
  95. package/docs/classes/DreamBin.html +3 -2
  96. package/docs/classes/DreamCLI.html +4 -4
  97. package/docs/classes/DreamImporter.html +2 -2
  98. package/docs/classes/DreamLogos.html +2 -2
  99. package/docs/classes/DreamMigrationHelpers.html +19 -8
  100. package/docs/classes/DreamSerializerBuilder.html +13 -13
  101. package/docs/classes/DreamTransaction.html +2 -2
  102. package/docs/classes/Encrypt.html +2 -2
  103. package/docs/classes/Env.html +2 -2
  104. package/docs/classes/GlobalNameNotSet.html +3 -3
  105. package/docs/classes/KyselyQueryDriver.html +31 -30
  106. package/docs/classes/MissingSerializersDefinition.html +3 -3
  107. package/docs/classes/NonLoadedAssociation.html +3 -3
  108. package/docs/classes/NotNullViolation.html +3 -3
  109. package/docs/classes/ObjectSerializerBuilder.html +8 -8
  110. package/docs/classes/PostgresQueryDriver.html +32 -31
  111. package/docs/classes/Query.html +53 -53
  112. package/docs/classes/QueryDriverBase.html +30 -29
  113. package/docs/classes/Range.html +2 -2
  114. package/docs/classes/RecordNotFound.html +3 -3
  115. package/docs/classes/ValidationError.html +3 -3
  116. package/docs/functions/DreamSerializer.html +1 -1
  117. package/docs/functions/ObjectSerializer.html +1 -1
  118. package/docs/functions/ReplicaSafe.html +1 -1
  119. package/docs/functions/STI.html +1 -1
  120. package/docs/functions/SoftDelete.html +1 -1
  121. package/docs/functions/camelize.html +1 -1
  122. package/docs/functions/capitalize.html +1 -1
  123. package/docs/functions/cloneDeepSafe.html +1 -1
  124. package/docs/functions/closeAllDbConnections.html +1 -1
  125. package/docs/functions/compact.html +1 -1
  126. package/docs/functions/dreamDbConnections.html +1 -1
  127. package/docs/functions/dreamPath.html +1 -1
  128. package/docs/functions/expandStiClasses.html +1 -1
  129. package/docs/functions/generateDream.html +1 -1
  130. package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
  131. package/docs/functions/groupBy.html +1 -1
  132. package/docs/functions/hyphenize.html +1 -1
  133. package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
  134. package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
  135. package/docs/functions/intersection.html +1 -1
  136. package/docs/functions/isDreamSerializer.html +1 -1
  137. package/docs/functions/isEmpty.html +1 -1
  138. package/docs/functions/loadRepl.html +1 -1
  139. package/docs/functions/lookupClassByGlobalName.html +1 -1
  140. package/docs/functions/normalizeUnicode.html +1 -1
  141. package/docs/functions/pascalize.html +1 -1
  142. package/docs/functions/percent.html +1 -0
  143. package/docs/functions/pgErrorType.html +1 -1
  144. package/docs/functions/range-1.html +1 -1
  145. package/docs/functions/relativeDreamPath.html +1 -1
  146. package/docs/functions/round.html +1 -1
  147. package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
  148. package/docs/functions/sharedPathPrefix.html +1 -1
  149. package/docs/functions/snakeify.html +1 -1
  150. package/docs/functions/sort.html +1 -1
  151. package/docs/functions/sortBy.html +1 -1
  152. package/docs/functions/sortObjectByKey.html +1 -1
  153. package/docs/functions/sortObjectByValue.html +1 -1
  154. package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
  155. package/docs/functions/uncapitalize.html +1 -1
  156. package/docs/functions/uniq.html +1 -1
  157. package/docs/functions/untypedDb.html +1 -1
  158. package/docs/functions/validateColumn.html +1 -1
  159. package/docs/functions/validateTable.html +1 -1
  160. package/docs/interfaces/BelongsToStatement.html +2 -2
  161. package/docs/interfaces/DecoratorContext.html +2 -2
  162. package/docs/interfaces/DreamAppInitOptions.html +2 -2
  163. package/docs/interfaces/DreamAppOpts.html +2 -2
  164. package/docs/interfaces/EncryptOptions.html +2 -2
  165. package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
  166. package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
  167. package/docs/interfaces/OpenapiDescription.html +2 -2
  168. package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
  169. package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
  170. package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
  171. package/docs/interfaces/SerializerRendererOpts.html +2 -2
  172. package/docs/modules.html +1 -0
  173. package/docs/types/Camelized.html +1 -1
  174. package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
  175. package/docs/types/DateTime.html +1 -1
  176. package/docs/types/DbConnectionType.html +1 -1
  177. package/docs/types/DbTypes.html +1 -1
  178. package/docs/types/DreamAppAllowedPackageManagersEnum.html +1 -1
  179. package/docs/types/DreamAssociationMetadata.html +1 -1
  180. package/docs/types/DreamAttributes.html +1 -1
  181. package/docs/types/DreamClassAssociationAndStatement.html +1 -1
  182. package/docs/types/DreamClassColumn.html +1 -1
  183. package/docs/types/DreamColumn.html +1 -1
  184. package/docs/types/DreamColumnNames.html +1 -1
  185. package/docs/types/DreamLogLevel.html +1 -1
  186. package/docs/types/DreamLogger.html +1 -1
  187. package/docs/types/DreamModelSerializerType.html +1 -1
  188. package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
  189. package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
  190. package/docs/types/DreamParamSafeAttributes.html +1 -1
  191. package/docs/types/DreamParamSafeColumnNames.html +1 -1
  192. package/docs/types/DreamSerializable.html +1 -1
  193. package/docs/types/DreamSerializableArray.html +1 -1
  194. package/docs/types/DreamSerializerKey.html +1 -1
  195. package/docs/types/DreamSerializers.html +1 -1
  196. package/docs/types/DreamVirtualColumns.html +1 -1
  197. package/docs/types/EncryptAlgorithm.html +1 -1
  198. package/docs/types/HasManyStatement.html +1 -1
  199. package/docs/types/HasOneStatement.html +1 -1
  200. package/docs/types/Hyphenized.html +1 -1
  201. package/docs/types/OpenapiAllTypes.html +1 -1
  202. package/docs/types/OpenapiFormats.html +1 -1
  203. package/docs/types/OpenapiNumberFormats.html +1 -1
  204. package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
  205. package/docs/types/OpenapiPrimitiveTypes.html +1 -1
  206. package/docs/types/OpenapiSchemaArray.html +1 -1
  207. package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
  208. package/docs/types/OpenapiSchemaBase.html +1 -1
  209. package/docs/types/OpenapiSchemaBody.html +1 -1
  210. package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
  211. package/docs/types/OpenapiSchemaCommonFields.html +1 -1
  212. package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
  213. package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
  214. package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
  215. package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
  216. package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
  217. package/docs/types/OpenapiSchemaInteger.html +1 -1
  218. package/docs/types/OpenapiSchemaNull.html +1 -1
  219. package/docs/types/OpenapiSchemaNumber.html +1 -1
  220. package/docs/types/OpenapiSchemaObject.html +1 -1
  221. package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
  222. package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
  223. package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
  224. package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  225. package/docs/types/OpenapiSchemaObjectBase.html +1 -1
  226. package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
  227. package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
  228. package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
  229. package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
  230. package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
  231. package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  232. package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  233. package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  234. package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
  235. package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
  236. package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  237. package/docs/types/OpenapiSchemaString.html +1 -1
  238. package/docs/types/OpenapiShorthandAllTypes.html +1 -1
  239. package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  240. package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
  241. package/docs/types/OpenapiTypeField.html +1 -1
  242. package/docs/types/Pascalized.html +1 -1
  243. package/docs/types/RoundingPrecision.html +1 -1
  244. package/docs/types/SerializerCasing.html +1 -1
  245. package/docs/types/SimpleObjectSerializerType.html +1 -1
  246. package/docs/types/Snakeified.html +1 -1
  247. package/docs/types/UpdateableAssociationProperties.html +1 -1
  248. package/docs/types/UpdateableProperties.html +1 -1
  249. package/docs/types/ValidationType.html +1 -1
  250. package/docs/types/ViewModel.html +1 -1
  251. package/docs/types/ViewModelClass.html +1 -1
  252. package/docs/types/WhereStatementForDream.html +1 -1
  253. package/docs/types/WhereStatementForDreamClass.html +1 -1
  254. package/docs/variables/DateTime-1.html +1 -1
  255. package/docs/variables/DreamAppAllowedPackageManagersEnumValues.html +1 -1
  256. package/docs/variables/DreamConst.html +1 -1
  257. package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
  258. package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
  259. package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
  260. package/docs/variables/ops.html +1 -1
  261. package/docs/variables/primaryKeyTypes.html +1 -1
  262. package/package.json +5 -5
@@ -43,6 +43,7 @@ const CreateOrUpdateByFailedToCreateAndUpdate_js_1 = require("./errors/CreateOrU
43
43
  const GlobalNameNotSet_js_1 = require("./errors/dream-app/GlobalNameNotSet.js");
44
44
  const DreamMissingRequiredOverride_js_1 = require("./errors/DreamMissingRequiredOverride.js");
45
45
  const NonExistentScopeProvidedToResort_js_1 = require("./errors/NonExistentScopeProvidedToResort.js");
46
+ const RecordNotFound_js_1 = require("./errors/RecordNotFound.js");
46
47
  const MissingSerializersDefinition_js_1 = require("./errors/serializers/MissingSerializersDefinition.js");
47
48
  const CalendarDate_js_1 = require("./helpers/CalendarDate.js");
48
49
  const cloneDeepSafe_js_1 = require("./helpers/cloneDeepSafe.js");
@@ -3220,6 +3221,61 @@ class Dream {
3220
3221
  load(...args) {
3221
3222
  return new LoadBuilder_js_1.default(this).load(...args);
3222
3223
  }
3224
+ /**
3225
+ * If the association is already loaded on the instance, it returns the loaded value
3226
+ * immediately without making a database query. If the association is not loaded,
3227
+ * it performs a database query to fetch the association.
3228
+ *
3229
+ * If a query is performed, the association is set on the model so that future calls to
3230
+ * access this association can access the already loaded value.
3231
+ *
3232
+ * ```ts
3233
+ * // return the already loaded user if it exists or fetch it from the database otherwise
3234
+ * const user = await post.associationOrFail('user')
3235
+ * ```
3236
+ *
3237
+ * @param associationName - The name of the BelongsTo or HasOne association
3238
+ * @returns The associated model instance or null
3239
+ */
3240
+ async association(associationName) {
3241
+ if (!this.loaded(associationName)) {
3242
+ const association = this.getAssociationMetadata(associationName);
3243
+ if (association?.type === 'HasMany') {
3244
+ this[associationName] = (await this.associationQuery(associationName).all());
3245
+ }
3246
+ else {
3247
+ this[associationName] = (await this.associationQuery(associationName).first());
3248
+ }
3249
+ }
3250
+ return this[associationName];
3251
+ }
3252
+ /**
3253
+ * If the association is already loaded on the instance, it returns the loaded value
3254
+ * immediately without making a database query. If the association is not loaded,
3255
+ * it performs a database query to fetch the association.
3256
+ *
3257
+ * Unlike `association`, this method throws an exception if no associated
3258
+ * record is found, guaranteeing a non-null result.
3259
+ *
3260
+ * If a query is performed, the association is set on the model so that future calls to
3261
+ * access this association can access the already loaded value.
3262
+ *
3263
+ * ```ts
3264
+ * // return the already loaded user if it exists or fetch it from the database otherwise,
3265
+ * // throwing RecordNotFound either way if the associated model does not exist
3266
+ * const user = await post.associationOrFail('user')
3267
+ * ```
3268
+ *
3269
+ * @param associationName - The name of the BelongsTo or HasOne association
3270
+ * @returns The associated model instance (never null)
3271
+ * @throws RecordNotFound if no associated record exists
3272
+ */
3273
+ async associationOrFail(associationName) {
3274
+ const response = await this.association(associationName);
3275
+ if (this[associationName] === null)
3276
+ throw new RecordNotFound_js_1.default(this['sanitizedConstructorName']);
3277
+ return response;
3278
+ }
3223
3279
  /**
3224
3280
  * Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
3225
3281
  * in a DreamSerializer. This traverses the entire content tree of serializers to automatically
@@ -3280,8 +3336,8 @@ class Dream {
3280
3336
  * 4. the individual query becomes more complex the more associations are included
3281
3337
  * 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.load(...).findEach(...)` avoids instantiating massive amounts of data at once
3282
3338
  *
3283
- * NOTE: {@link Dream.leftJoinPreload} is often a preferrable way of achieving the
3284
- * same goal.
3339
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
3340
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
3285
3341
  *
3286
3342
  * ```ts
3287
3343
  * await user
@@ -3317,6 +3373,9 @@ class Dream {
3317
3373
  * This method analyzes the serializer (specified by `serializerKey` or 'default') and
3318
3374
  * automatically preloads all associations that will be needed during serialization.
3319
3375
  *
3376
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
3377
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
3378
+ *
3320
3379
  * ```ts
3321
3380
  * // Instead of manually specifying all associations:
3322
3381
  * await User.preload('posts', 'comments', 'replies').all()
@@ -24,6 +24,12 @@ class DreamBin {
24
24
  await Query_js_1.default.dbDriverClass(connectionName).dbDrop(connectionName);
25
25
  }
26
26
  }
27
+ static async dbEnsureAllMigrationsHaveBeenRun() {
28
+ const dreamApp = index_js_2.default.getOrFail();
29
+ for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
30
+ await Query_js_1.default.dbDriverClass(connectionName).ensureAllMigrationsHaveBeenRun(connectionName);
31
+ }
32
+ }
27
33
  static async dbMigrate() {
28
34
  const dreamApp = index_js_2.default.getOrFail();
29
35
  for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
@@ -34,7 +34,7 @@ ${INDENT}
34
34
  ${INDENT} - decimal:
35
35
  ${INDENT} - decimal[]:
36
36
  ${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
37
- ${INDENT}
37
+ ${INDENT}
38
38
  ${INDENT} leveraging arrays, add the "[]" suffix, e.g.: volume:decimal[]:3,2
39
39
  ${INDENT}
40
40
  ${INDENT} - enum:
@@ -73,7 +73,7 @@ class DreamCLI {
73
73
  .description('sync introspects your database, updating your schema to reflect, and then syncs the new schema with the installed dream node module, allowing it provide your schema to the underlying kysely integration')
74
74
  .option('--schema-only')
75
75
  .action(async (options = {}) => {
76
- await initializeDreamApp();
76
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
77
77
  await index_js_1.default.sync(() => { }, options);
78
78
  process.exit();
79
79
  });
@@ -95,7 +95,7 @@ class DreamCLI {
95
95
  .option('--connection-name <connectionName>', 'the connection name you wish to use for your migration')
96
96
  .argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
97
97
  .action(async (migrationName, columnsWithTypes, options) => {
98
- await initializeDreamApp();
98
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
99
99
  await index_js_1.default.generateMigration(migrationName, columnsWithTypes, options.connectionName || 'default');
100
100
  process.exit();
101
101
  });
@@ -111,7 +111,7 @@ class DreamCLI {
111
111
  .argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
112
112
  .argument('[columnsWithTypes...]', columnsWithTypesDescription)
113
113
  .action(async (modelName, columnsWithTypes, options) => {
114
- await initializeDreamApp();
114
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
115
115
  await index_js_1.default.generateDream(modelName, columnsWithTypes, options);
116
116
  process.exit();
117
117
  });
@@ -128,7 +128,7 @@ ${INDENT} to extend the Room model in src/app/models/Room: Room
128
128
  ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
129
129
  .argument('[columnsWithTypes...]', columnsWithTypesDescription)
130
130
  .action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
131
- await initializeDreamApp();
131
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
132
132
  if (extendsWord !== 'extends')
133
133
  throw new Error('Expecting: `<child-name> extends <parent-name> <columns-and-types>');
134
134
  await index_js_1.default.generateStiChild(childModelName, parentModelName, columnsWithTypes, options);
@@ -139,16 +139,24 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
139
139
  .description('creates a new database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
140
140
  .action(async () => {
141
141
  EnvInternal_js_1.default.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
142
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
142
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
143
143
  await index_js_1.default.dbCreate();
144
144
  process.exit();
145
145
  });
146
+ program
147
+ .command('db:integrity-check')
148
+ .description('db:integrity-check fails if migrations need to be run')
149
+ .action(async () => {
150
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
151
+ await index_js_1.default.dbEnsureAllMigrationsHaveBeenRun();
152
+ process.exit();
153
+ });
146
154
  program
147
155
  .command('db:migrate')
148
156
  .description('db:migrate runs any outstanding database migrations')
149
157
  .option('--skip-sync', 'skips syncing local schema after running migrations')
150
158
  .action(async ({ skipSync }) => {
151
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
159
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
152
160
  await index_js_1.default.dbMigrate();
153
161
  if (EnvInternal_js_1.default.isDevelopmentOrTest && !skipSync) {
154
162
  await index_js_1.default.sync(onSync);
@@ -161,7 +169,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
161
169
  .option('--steps <number>', 'number of steps back to travel', myParseInt, 1)
162
170
  .option('--skip-sync', 'skips syncing local schema after running migrations')
163
171
  .action(async ({ steps, skipSync }) => {
164
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
172
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
165
173
  await index_js_1.default.dbRollback({ steps });
166
174
  if (EnvInternal_js_1.default.isDevelopmentOrTest && !skipSync) {
167
175
  await index_js_1.default.sync(onSync);
@@ -173,7 +181,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
173
181
  .description('drops the database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
174
182
  .action(async () => {
175
183
  EnvInternal_js_1.default.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
176
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
184
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
177
185
  await index_js_1.default.dbDrop();
178
186
  process.exit();
179
187
  });
@@ -182,11 +190,11 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
182
190
  .description('runs db:drop (safely), then db:create, db:migrate, and db:seed')
183
191
  .action(async () => {
184
192
  EnvInternal_js_1.default.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
185
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
193
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
186
194
  await index_js_1.default.dbDrop();
187
195
  await index_js_1.default.dbCreate();
188
196
  EnvInternal_js_1.default.unsetBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
189
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
197
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
190
198
  await index_js_1.default.dbMigrate();
191
199
  await index_js_1.default.sync(onSync);
192
200
  await seedDb();
@@ -2,6 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const kysely_1 = require("kysely");
4
4
  class DreamMigrationHelpers {
5
+ /**
6
+ * Rename a table and its associated primary key sequence.
7
+ *
8
+ * This method renames both the table and its primary key sequence to keep them
9
+ * in sync. When PostgreSQL creates a table with a serial or bigserial primary key,
10
+ * it automatically creates a sequence named `{tablename}_id_seq`. If you only rename
11
+ * the table, the sequence keeps the old name, which can cause confusion and issues.
12
+ *
13
+ * This method is only suitable for tables that have a serial or bigserial primary
14
+ * key column named 'id'.
15
+ *
16
+ * @param db - The Kysely database object passed into the migration up/down function
17
+ * @param from - The current name of the table to rename
18
+ * @param to - The new name for the table
19
+ */
20
+ static async renameTable(db, from, to) {
21
+ await db.schema.alterTable(from).renameTo(to).execute();
22
+ await (0, kysely_1.sql) `ALTER SEQUENCE ${from}_id_seq RENAME TO ${to}_id_seq`.execute(db);
23
+ }
5
24
  /**
6
25
  * Unique indexes cannot be populated by the same value even within a transaction,
7
26
  * but deferrable unique constraints can.
@@ -23,14 +23,14 @@ const shared_js_1 = require("./shared.js");
23
23
  * }
24
24
  * ```
25
25
  *
26
- * @param opts.foreignKey - A custom column name to use for the foreign key.
26
+ * @param opts.on - A custom column name to use for joining associations on.
27
27
  * @param opts.optional - Whether or not this association is optional. Defaults to false.
28
28
  * @param opts.polymorphic - If true, this association will be treated as a polymorphic association.
29
29
  * @param opts.primaryKeyOverride - A custom column name to use for the primary key.
30
30
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
31
31
  */
32
32
  function BelongsTo(globalAssociationNameOrNames, opts = {}) {
33
- const { foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
33
+ const { on: foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
34
34
  return function (_, context) {
35
35
  const key = context.name;
36
36
  context.addInitializer(function () {
@@ -23,7 +23,7 @@ const shared_js_1 = require("./shared.js");
23
23
  *
24
24
  * @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
25
25
  * @param opts.distinct - Can be a column name, or else a boolean. If a column name, a distinct clause will be applied to the column. If true, a distinct clause will be applied to the primary key.
26
- * @param opts.foreignKey - A custom column name to use for the foreign key.
26
+ * @param opts.on - A custom column name to use for joining associations on.
27
27
  * @param opts.and - An and-clause to be applied when this association is loaded
28
28
  * @param opts.andNot - A not and-clause to be applied when this association is loaded
29
29
  * @param opts.andAny - An andAny clause to be applied when this association is loaded
@@ -37,7 +37,7 @@ const shared_js_1 = require("./shared.js");
37
37
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
38
38
  */
39
39
  function HasMany(globalAssociationNameOrNames, opts = {}) {
40
- const { dependent, distinct, foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
40
+ const { dependent, distinct, on: foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
41
41
  return function (_, context) {
42
42
  const key = context.name;
43
43
  context.addInitializer(function () {
@@ -22,7 +22,7 @@ const shared_js_1 = require("./shared.js");
22
22
  * ```
23
23
  *
24
24
  * @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
25
- * @param opts.foreignKey - A custom column name to use for the foreign key.
25
+ * @param opts.on - A custom column name to use for joining associations on.
26
26
  * @param opts.and - An and-clause to be applied when this association is loaded
27
27
  * @param opts.andNot - A not and-clause to be applied when this association is loaded
28
28
  * @param opts.andAny - An andAny clause to be applied when this association is loaded
@@ -35,7 +35,7 @@ const shared_js_1 = require("./shared.js");
35
35
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
36
36
  */
37
37
  function HasOne(globalAssociationNameOrNames, opts = {}) {
38
- const { dependent, foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
38
+ const { dependent, on: foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
39
39
  return function (_, context) {
40
40
  const key = context.name;
41
41
  context.addInitializer(function () {
@@ -1217,7 +1217,10 @@ class Query {
1217
1217
  const recordCount = await this.count();
1218
1218
  const pageSize = opts.pageSize || index_js_1.default.getOrFail().paginationPageSize;
1219
1219
  const pageCount = Math.ceil(recordCount / pageSize);
1220
- const results = await this
1220
+ const query = this.orderStatements.length
1221
+ ? this
1222
+ : this.order({ [this.namespacedPrimaryKey]: 'asc' });
1223
+ const results = await query
1221
1224
  .limit(pageSize)
1222
1225
  .offset((page - 1) * pageSize)
1223
1226
  .all();
@@ -22,6 +22,12 @@ class QueryDriverBase {
22
22
  this.connectionOverride = query['originalOpts'].connection;
23
23
  this.innerJoinDreamClasses = Object.freeze(query['originalOpts'].innerJoinDreamClasses || []);
24
24
  }
25
+ // eslint-disable-next-line @typescript-eslint/require-await
26
+ static async ensureAllMigrationsHaveBeenRun(
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28
+ connectionName) {
29
+ throw new Error('override ensureAllMigrationsHaveBeenRun in child class');
30
+ }
25
31
  /**
26
32
  * migrate the database. Must respond to the NODE_ENV value.
27
33
  */
@@ -66,6 +66,7 @@ const softDeleteDream_js_1 = require("../internal/softDeleteDream.js");
66
66
  const sqlResultToDreamInstance_js_1 = require("../internal/sqlResultToDreamInstance.js");
67
67
  const Query_js_1 = require("../Query.js");
68
68
  const Base_js_1 = require("./Base.js");
69
+ const checkForNeedToBeRunMigrations_js_1 = require("./helpers/kysely/checkForNeedToBeRunMigrations.js");
69
70
  const runMigration_js_1 = require("./helpers/kysely/runMigration.js");
70
71
  class KyselyQueryDriver extends Base_js_1.default {
71
72
  // ATTENTION FRED
@@ -102,6 +103,14 @@ class KyselyQueryDriver extends Base_js_1.default {
102
103
  }),
103
104
  });
104
105
  }
106
+ static async ensureAllMigrationsHaveBeenRun(connectionName) {
107
+ const migrationsNeedToBeRun = await (0, checkForNeedToBeRunMigrations_js_1.default)({
108
+ connectionName,
109
+ dialectProvider: this.dialectProvider(connectionName, 'primary'),
110
+ });
111
+ if (migrationsNeedToBeRun)
112
+ throw new Error(`Migrations need to be run on ${connectionName} database`);
113
+ }
105
114
  /**
106
115
  * migrate the database. Must respond to the NODE_ENV value.
107
116
  */
@@ -696,9 +705,8 @@ class KyselyQueryDriver extends Base_js_1.default {
696
705
  return (0, orderByDirection_js_1.default)(direction);
697
706
  }
698
707
  buildUpdate(attributes) {
699
- let kyselyQuery = this.dbFor('update')
700
- .updateTable(this.query['tableName'])
701
- .set(attributes);
708
+ let kyselyQuery = this.dbFor('update').updateTable(this.query['tableName']);
709
+ kyselyQuery = kyselyQuery.set(attributes);
702
710
  kyselyQuery = this.conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery);
703
711
  const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
704
712
  return new this.constructor(results.clone).buildCommon(results.kyselyQuery);
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = checkForNeedToBeRunMigrations;
4
+ const kysely_1 = require("kysely");
5
+ const fs = require("node:fs/promises");
6
+ const path = require("node:path");
7
+ const DreamDbConnection_js_1 = require("../../../../db/DreamDbConnection.js");
8
+ const index_js_1 = require("../../../../db/index.js");
9
+ const migrationFolderPath_js_1 = require("./migrationFolderPath.js");
10
+ async function checkForNeedToBeRunMigrations({ connectionName, dialectProvider, }) {
11
+ const migrationFolder = (0, migrationFolderPath_js_1.default)(connectionName);
12
+ // Ensure the migration folder exists
13
+ await fs.mkdir(migrationFolder, { recursive: true });
14
+ const kyselyDb = (0, index_js_1.default)(connectionName, 'primary', dialectProvider);
15
+ const migrator = new kysely_1.Migrator({
16
+ db: kyselyDb,
17
+ allowUnorderedMigrations: true,
18
+ provider: new kysely_1.FileMigrationProvider({
19
+ fs,
20
+ path,
21
+ migrationFolder,
22
+ }),
23
+ });
24
+ const result = (await migrator.getMigrations()).some(migrationInfo => !migrationInfo.executedAt);
25
+ await (0, DreamDbConnection_js_1.closeAllConnectionsForConnectionName)(connectionName);
26
+ return result;
27
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = migrationFolderPath;
4
+ const path = require("node:path");
5
+ const index_js_1 = require("../../../../dream-app/index.js");
6
+ function migrationFolderPath(connectionName) {
7
+ const dreamApp = index_js_1.default.getOrFail();
8
+ return connectionName === 'default'
9
+ ? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
10
+ : path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
11
+ }
@@ -4,19 +4,17 @@ exports.default = runMigration;
4
4
  const kysely_1 = require("kysely");
5
5
  const fs = require("node:fs/promises");
6
6
  const path = require("node:path");
7
+ const index_js_1 = require("../../../../cli/index.js");
7
8
  const colorize_js_1 = require("../../../../cli/logger/loggable/colorize.js");
8
9
  const DreamDbConnection_js_1 = require("../../../../db/DreamDbConnection.js");
9
- const index_js_1 = require("../../../../db/index.js");
10
- const index_js_2 = require("../../../../dream-app/index.js");
11
- const index_js_3 = require("../../../../cli/index.js");
10
+ const index_js_2 = require("../../../../db/index.js");
11
+ const index_js_3 = require("../../../../dream-app/index.js");
12
+ const migrationFolderPath_js_1 = require("./migrationFolderPath.js");
12
13
  async function runMigration({ connectionName, mode = 'migrate', dialectProvider, }) {
13
- const dreamApp = index_js_2.default.getOrFail();
14
- const migrationFolder = connectionName === 'default'
15
- ? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
16
- : path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
14
+ const migrationFolder = (0, migrationFolderPath_js_1.default)(connectionName);
17
15
  // Ensure the migration folder exists
18
16
  await fs.mkdir(migrationFolder, { recursive: true });
19
- const kyselyDb = (0, index_js_1.default)(connectionName, 'primary', dialectProvider);
17
+ const kyselyDb = (0, index_js_2.default)(connectionName, 'primary', dialectProvider);
20
18
  const migrator = new kysely_1.Migrator({
21
19
  db: kyselyDb,
22
20
  allowUnorderedMigrations: true,
@@ -80,8 +78,8 @@ async function rollback(migrator) {
80
78
  }
81
79
  async function handleError(error, mode) {
82
80
  await (0, DreamDbConnection_js_1.closeAllDbConnections)();
83
- index_js_2.default.logWithLevel('error', `failed to ${migratedActionCurrentTense(mode)}`);
84
- index_js_2.default.logWithLevel('error', error);
81
+ index_js_3.default.logWithLevel('error', `failed to ${migratedActionCurrentTense(mode)}`);
82
+ index_js_3.default.logWithLevel('error', error);
85
83
  process.exit(1);
86
84
  }
87
85
  function migratedActionCurrentTense(mode) {
@@ -93,12 +91,12 @@ function migratedActionPastTense(mode) {
93
91
  function logResults(results, mode) {
94
92
  results?.forEach(it => {
95
93
  if (it.status === 'Success') {
96
- index_js_3.default.logger.logContinueProgress((0, colorize_js_1.default)(`[db]`, { color: 'cyan' }) +
94
+ index_js_1.default.logger.logContinueProgress((0, colorize_js_1.default)(`[db]`, { color: 'cyan' }) +
97
95
  ` migration "${it.migrationName}" was ${migratedActionPastTense(mode)} successfully`, { logPrefixColor: 'cyan' });
98
96
  }
99
97
  else if (it.status === 'Error') {
100
- index_js_3.default.logger.logContinueProgress(JSON.stringify(it, null, 2));
101
- index_js_3.default.logger.logContinueProgress((0, colorize_js_1.default)(`failed to ${migratedActionCurrentTense(mode)} migration "${it.migrationName}"`, {
98
+ index_js_1.default.logger.logContinueProgress(JSON.stringify(it, null, 2));
99
+ index_js_1.default.logger.logContinueProgress((0, colorize_js_1.default)(`failed to ${migratedActionCurrentTense(mode)} migration "${it.migrationName}"`, {
102
100
  color: 'redBright',
103
101
  }));
104
102
  }
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = orderByDirection;
4
- const kysely_1 = require("kysely");
5
4
  function orderByDirection(dir) {
6
5
  switch (dir) {
7
6
  case 'asc':
8
7
  case null:
9
- return (0, kysely_1.sql) `asc nulls first`;
8
+ return (obj) => obj.asc().nullsFirst();
10
9
  case 'desc':
11
- return (0, kysely_1.sql) `desc nulls last`;
10
+ return (obj) => obj.desc().nullsLast();
12
11
  default: {
13
12
  // protection so that if a new OrderDir is ever added, this will throw a type error at build time
14
13
  const _never = dir;
@@ -52,8 +52,8 @@ async function undestroyDreamWithTransaction(dream, txn, options) {
52
52
  * deleting by one of the beforeDestroy model hooks
53
53
  */
54
54
  async function doUndestroyDream(dream, txn) {
55
- let query = txn.kyselyTransaction
56
- .updateTable(dream.table)
55
+ const updateStatement = txn.kyselyTransaction.updateTable(dream.table);
56
+ let query = updateStatement
57
57
  .where(dream['_primaryKey'], '=', dream.primaryKeyValue())
58
58
  .set({ [dream['_deletedAtField']]: null });
59
59
  const dreamClass = dream.constructor;
@@ -4,6 +4,7 @@ exports.GeneratorImportStyles = exports.DreamAppAllowedPackageManagersEnumValues
4
4
  const util = require("node:util");
5
5
  const validateTable_js_1 = require("../db/validators/validateTable.js");
6
6
  const Query_js_1 = require("../dream/Query.js");
7
+ const Postgres_js_1 = require("../dream/QueryDriver/Postgres.js");
7
8
  const index_js_1 = require("../encrypt/index.js");
8
9
  const DreamAppInitMissingCallToLoadModels_js_1 = require("../errors/dream-app/DreamAppInitMissingCallToLoadModels.js");
9
10
  const DreamAppInitMissingMissingProjectRoot_js_1 = require("../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js");
@@ -13,7 +14,6 @@ const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
13
14
  const cache_js_1 = require("./cache.js");
14
15
  const importModels_js_1 = require("./helpers/importers/importModels.js");
15
16
  const importSerializers_js_1 = require("./helpers/importers/importSerializers.js");
16
- const Postgres_js_1 = require("../dream/QueryDriver/Postgres.js");
17
17
  // this needs to be done top-level to ensure proper configuration
18
18
  DateTime_js_1.Settings.defaultZone = 'UTC';
19
19
  class DreamApp {
@@ -43,7 +43,7 @@ class DreamApp {
43
43
  await plugin(dreamApp);
44
44
  }
45
45
  dreamApp.validateAppBuildIntegrity({
46
- bypassModelIntegrityCheck: opts.bypassModelIntegrityCheck || false,
46
+ bypassDreamIntegrityChecks: opts.bypassDreamIntegrityChecks || false,
47
47
  });
48
48
  return dreamApp;
49
49
  }
@@ -54,14 +54,14 @@ class DreamApp {
54
54
  * that would render it in an invalid state
55
55
  *
56
56
  */
57
- validateAppBuildIntegrity({ bypassModelIntegrityCheck }) {
57
+ validateAppBuildIntegrity({ bypassDreamIntegrityChecks }) {
58
58
  if (!this.projectRoot)
59
59
  throw new DreamAppInitMissingMissingProjectRoot_js_1.default();
60
60
  if (!this.loadedModels)
61
61
  throw new DreamAppInitMissingCallToLoadModels_js_1.default();
62
62
  if (this.encryption?.columns?.current)
63
63
  DreamApp.checkKey('columns', this.encryption.columns.current.key, this.encryption.columns.current.algorithm);
64
- if (!bypassModelIntegrityCheck)
64
+ if (!bypassDreamIntegrityChecks)
65
65
  this.validateApplicationModels();
66
66
  }
67
67
  /**
@@ -17,11 +17,10 @@ class InvalidComputedForeignKey extends Error {
17
17
  }
18
18
  get message() {
19
19
  return `
20
- Add an explicit foreignKey declaration to this association declaration:
20
+ Add an explicit \`on\` declaration to this association definition:
21
21
  Dream class: ${this.dreamClass.sanitizedName}
22
22
  Association: ${this.partialAssociation.as}
23
- Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}.
24
- `;
23
+ Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}.`;
25
24
  }
26
25
  }
27
26
  exports.InvalidComputedForeignKey = InvalidComputedForeignKey;
@@ -53,7 +52,7 @@ function checkForeignKey(explicitForeignKey, computedForeignKey, dreamClass, par
53
52
  table = dreamClass.table;
54
53
  else
55
54
  table = (0, shared_js_1.modelCBtoSingleDreamClass)(dreamClass, partialAssociation).table;
56
- const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns);
55
+ const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns ?? {});
57
56
  const validForeignKey = tableColumns.includes(computedForeignKey);
58
57
  if (validForeignKey)
59
58
  return;
@@ -7,6 +7,7 @@ const dbTypesFilenameForConnection_js_1 = require("../../db/helpers/dbTypesFilen
7
7
  const index_js_1 = require("../../dream-app/index.js");
8
8
  const constants_js_1 = require("../../dream/constants.js");
9
9
  const Query_js_1 = require("../../dream/Query.js");
10
+ const InvalidComputedForeignKey_js_1 = require("../../errors/associations/InvalidComputedForeignKey.js");
10
11
  const FailedToIdentifyAssociation_js_1 = require("../../errors/schema-builder/FailedToIdentifyAssociation.js");
11
12
  const camelize_js_1 = require("../camelize.js");
12
13
  const compact_js_1 = require("../compact.js");
@@ -265,33 +266,39 @@ may need to update the table getter in the corresponding Dream.
265
266
  this.hasForeignKeyError = true;
266
267
  // console.error(err)
267
268
  }
268
- tableAssociationData[associationName] ||= {
269
- tables: [],
270
- type: associationMetaData.type,
271
- polymorphic: associationMetaData.polymorphic,
272
- foreignKey,
273
- foreignKeyTypeColumn: associationMetaData.polymorphic
274
- ? associationMetaData?.foreignKeyTypeField?.() || null
275
- : null,
276
- optional,
277
- where,
278
- };
279
- if (foreignKey)
280
- tableAssociationData[associationName]['foreignKey'] = foreignKey;
281
- if (Array.isArray(dreamClassOrClasses)) {
282
- const tables = dreamClassOrClasses.map(dreamClass => dreamClass.table);
269
+ try {
270
+ tableAssociationData[associationName] ||= {
271
+ tables: [],
272
+ type: associationMetaData.type,
273
+ polymorphic: associationMetaData.polymorphic,
274
+ foreignKey,
275
+ foreignKeyTypeColumn: associationMetaData.polymorphic
276
+ ? associationMetaData?.foreignKeyTypeField?.() || null
277
+ : null,
278
+ optional,
279
+ where,
280
+ };
281
+ if (foreignKey)
282
+ tableAssociationData[associationName]['foreignKey'] = foreignKey;
283
+ if (Array.isArray(dreamClassOrClasses)) {
284
+ const tables = dreamClassOrClasses.map(dreamClass => dreamClass.table);
285
+ tableAssociationData[associationName].tables = [
286
+ ...tableAssociationData[associationName].tables,
287
+ ...tables,
288
+ ];
289
+ }
290
+ else {
291
+ tableAssociationData[associationName].tables.push(dreamClassOrClasses.table);
292
+ }
293
+ // guarantee unique
283
294
  tableAssociationData[associationName].tables = [
284
- ...tableAssociationData[associationName].tables,
285
- ...tables,
295
+ ...new Set(tableAssociationData[associationName].tables),
286
296
  ];
287
297
  }
288
- else {
289
- tableAssociationData[associationName].tables.push(dreamClassOrClasses.table);
298
+ catch (error) {
299
+ if (!(error instanceof InvalidComputedForeignKey_js_1.ExplicitForeignKeyRequired || error instanceof InvalidComputedForeignKey_js_1.InvalidComputedForeignKey))
300
+ throw error;
290
301
  }
291
- // guarantee unique
292
- tableAssociationData[associationName].tables = [
293
- ...new Set(tableAssociationData[associationName].tables),
294
- ];
295
302
  }
296
303
  }
297
304
  return Object.keys(tableAssociationData)