@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
@@ -0,0 +1,24 @@
1
+ import { FileMigrationProvider, Migrator } from 'kysely';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import { closeAllConnectionsForConnectionName } from '../../../../db/DreamDbConnection.js';
5
+ import db from '../../../../db/index.js';
6
+ import migrationFolderPath from './migrationFolderPath.js';
7
+ export default async function checkForNeedToBeRunMigrations({ connectionName, dialectProvider, }) {
8
+ const migrationFolder = migrationFolderPath(connectionName);
9
+ // Ensure the migration folder exists
10
+ await fs.mkdir(migrationFolder, { recursive: true });
11
+ const kyselyDb = db(connectionName, 'primary', dialectProvider);
12
+ const migrator = new Migrator({
13
+ db: kyselyDb,
14
+ allowUnorderedMigrations: true,
15
+ provider: new FileMigrationProvider({
16
+ fs,
17
+ path,
18
+ migrationFolder,
19
+ }),
20
+ });
21
+ const result = (await migrator.getMigrations()).some(migrationInfo => !migrationInfo.executedAt);
22
+ await closeAllConnectionsForConnectionName(connectionName);
23
+ return result;
24
+ }
@@ -0,0 +1,8 @@
1
+ import * as path from 'node:path';
2
+ import DreamApp from '../../../../dream-app/index.js';
3
+ export default function migrationFolderPath(connectionName) {
4
+ const dreamApp = DreamApp.getOrFail();
5
+ return connectionName === 'default'
6
+ ? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
7
+ : path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
8
+ }
@@ -1,16 +1,14 @@
1
1
  import { FileMigrationProvider, Migrator } from 'kysely';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import * as path from 'node:path';
4
+ import DreamCLI from '../../../../cli/index.js';
4
5
  import colorize from '../../../../cli/logger/loggable/colorize.js';
5
6
  import { closeAllConnectionsForConnectionName, closeAllDbConnections, } from '../../../../db/DreamDbConnection.js';
6
7
  import db from '../../../../db/index.js';
7
8
  import DreamApp from '../../../../dream-app/index.js';
8
- import DreamCLI from '../../../../cli/index.js';
9
+ import migrationFolderPath from './migrationFolderPath.js';
9
10
  export default async function runMigration({ connectionName, mode = 'migrate', dialectProvider, }) {
10
- const dreamApp = DreamApp.getOrFail();
11
- const migrationFolder = connectionName === 'default'
12
- ? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
13
- : path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
11
+ const migrationFolder = migrationFolderPath(connectionName);
14
12
  // Ensure the migration folder exists
15
13
  await fs.mkdir(migrationFolder, { recursive: true });
16
14
  const kyselyDb = db(connectionName, 'primary', dialectProvider);
@@ -1,11 +1,10 @@
1
- import { sql } from 'kysely';
2
1
  export default function orderByDirection(dir) {
3
2
  switch (dir) {
4
3
  case 'asc':
5
4
  case null:
6
- return sql `asc nulls first`;
5
+ return (obj) => obj.asc().nullsFirst();
7
6
  case 'desc':
8
- return sql `desc nulls last`;
7
+ return (obj) => obj.desc().nullsLast();
9
8
  default: {
10
9
  // protection so that if a new OrderDir is ever added, this will throw a type error at build time
11
10
  const _never = dir;
@@ -49,8 +49,8 @@ async function undestroyDreamWithTransaction(dream, txn, options) {
49
49
  * deleting by one of the beforeDestroy model hooks
50
50
  */
51
51
  async function doUndestroyDream(dream, txn) {
52
- let query = txn.kyselyTransaction
53
- .updateTable(dream.table)
52
+ const updateStatement = txn.kyselyTransaction.updateTable(dream.table);
53
+ let query = updateStatement
54
54
  .where(dream['_primaryKey'], '=', dream.primaryKeyValue())
55
55
  .set({ [dream['_deletedAtField']]: null });
56
56
  const dreamClass = dream.constructor;
@@ -1,6 +1,7 @@
1
1
  import * as util from 'node:util';
2
2
  import validateTable from '../db/validators/validateTable.js';
3
3
  import Query from '../dream/Query.js';
4
+ import PostgresQueryDriver from '../dream/QueryDriver/Postgres.js';
4
5
  import Encrypt from '../encrypt/index.js';
5
6
  import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppInitMissingCallToLoadModels.js';
6
7
  import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
@@ -10,7 +11,6 @@ import EnvInternal from '../helpers/EnvInternal.js';
10
11
  import { cacheDreamApp, getCachedDreamAppOrFail } from './cache.js';
11
12
  import importModels, { getModelsOrFail } from './helpers/importers/importModels.js';
12
13
  import importSerializers, { getSerializersOrFail, setCachedSerializers, } from './helpers/importers/importSerializers.js';
13
- import PostgresQueryDriver from '../dream/QueryDriver/Postgres.js';
14
14
  // this needs to be done top-level to ensure proper configuration
15
15
  Settings.defaultZone = 'UTC';
16
16
  export default class DreamApp {
@@ -40,7 +40,7 @@ export default class DreamApp {
40
40
  await plugin(dreamApp);
41
41
  }
42
42
  dreamApp.validateAppBuildIntegrity({
43
- bypassModelIntegrityCheck: opts.bypassModelIntegrityCheck || false,
43
+ bypassDreamIntegrityChecks: opts.bypassDreamIntegrityChecks || false,
44
44
  });
45
45
  return dreamApp;
46
46
  }
@@ -51,14 +51,14 @@ export default class DreamApp {
51
51
  * that would render it in an invalid state
52
52
  *
53
53
  */
54
- validateAppBuildIntegrity({ bypassModelIntegrityCheck }) {
54
+ validateAppBuildIntegrity({ bypassDreamIntegrityChecks }) {
55
55
  if (!this.projectRoot)
56
56
  throw new DreamAppInitMissingMissingProjectRoot();
57
57
  if (!this.loadedModels)
58
58
  throw new DreamAppInitMissingCallToLoadModels();
59
59
  if (this.encryption?.columns?.current)
60
60
  DreamApp.checkKey('columns', this.encryption.columns.current.key, this.encryption.columns.current.algorithm);
61
- if (!bypassModelIntegrityCheck)
61
+ if (!bypassDreamIntegrityChecks)
62
62
  this.validateApplicationModels();
63
63
  }
64
64
  /**
@@ -13,11 +13,10 @@ export class InvalidComputedForeignKey extends Error {
13
13
  }
14
14
  get message() {
15
15
  return `
16
- Add an explicit foreignKey declaration to this association declaration:
16
+ Add an explicit \`on\` declaration to this association definition:
17
17
  Dream class: ${this.dreamClass.sanitizedName}
18
18
  Association: ${this.partialAssociation.as}
19
- Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}.
20
- `;
19
+ Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}.`;
21
20
  }
22
21
  }
23
22
  export class ExplicitForeignKeyRequired extends Error {
@@ -47,7 +46,7 @@ export function checkForeignKey(explicitForeignKey, computedForeignKey, dreamCla
47
46
  table = dreamClass.table;
48
47
  else
49
48
  table = modelCBtoSingleDreamClass(dreamClass, partialAssociation).table;
50
- const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns);
49
+ const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns ?? {});
51
50
  const validForeignKey = tableColumns.includes(computedForeignKey);
52
51
  if (validForeignKey)
53
52
  return;
@@ -5,6 +5,7 @@ import dbTypesFilenameForConnection from '../../db/helpers/dbTypesFilenameForCon
5
5
  import DreamApp from '../../dream-app/index.js';
6
6
  import { DreamConst } from '../../dream/constants.js';
7
7
  import Query from '../../dream/Query.js';
8
+ import { ExplicitForeignKeyRequired, InvalidComputedForeignKey, } from '../../errors/associations/InvalidComputedForeignKey.js';
8
9
  import FailedToIdentifyAssociation from '../../errors/schema-builder/FailedToIdentifyAssociation.js';
9
10
  import camelize from '../camelize.js';
10
11
  import compact from '../compact.js';
@@ -263,33 +264,39 @@ may need to update the table getter in the corresponding Dream.
263
264
  this.hasForeignKeyError = true;
264
265
  // console.error(err)
265
266
  }
266
- tableAssociationData[associationName] ||= {
267
- tables: [],
268
- type: associationMetaData.type,
269
- polymorphic: associationMetaData.polymorphic,
270
- foreignKey,
271
- foreignKeyTypeColumn: associationMetaData.polymorphic
272
- ? associationMetaData?.foreignKeyTypeField?.() || null
273
- : null,
274
- optional,
275
- where,
276
- };
277
- if (foreignKey)
278
- tableAssociationData[associationName]['foreignKey'] = foreignKey;
279
- if (Array.isArray(dreamClassOrClasses)) {
280
- const tables = dreamClassOrClasses.map(dreamClass => dreamClass.table);
267
+ try {
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);
283
+ tableAssociationData[associationName].tables = [
284
+ ...tableAssociationData[associationName].tables,
285
+ ...tables,
286
+ ];
287
+ }
288
+ else {
289
+ tableAssociationData[associationName].tables.push(dreamClassOrClasses.table);
290
+ }
291
+ // guarantee unique
281
292
  tableAssociationData[associationName].tables = [
282
- ...tableAssociationData[associationName].tables,
283
- ...tables,
293
+ ...new Set(tableAssociationData[associationName].tables),
284
294
  ];
285
295
  }
286
- else {
287
- tableAssociationData[associationName].tables.push(dreamClassOrClasses.table);
296
+ catch (error) {
297
+ if (!(error instanceof ExplicitForeignKeyRequired || error instanceof InvalidComputedForeignKey))
298
+ throw error;
288
299
  }
289
- // guarantee unique
290
- tableAssociationData[associationName].tables = [
291
- ...new Set(tableAssociationData[associationName].tables),
292
- ];
293
300
  }
294
301
  }
295
302
  return Object.keys(tableAssociationData)
@@ -2,11 +2,11 @@ import pluralize from 'pluralize-esm';
2
2
  import serializerGlobalNameFromFullyQualifiedModelName from '../../serializer/helpers/serializerGlobalNameFromFullyQualifiedModelName.js';
3
3
  import camelize from '../camelize.js';
4
4
  import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
5
+ import pascalize from '../pascalize.js';
5
6
  import relativeDreamPath from '../path/relativeDreamPath.js';
6
7
  import snakeify from '../snakeify.js';
7
8
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
8
9
  import uniq from '../uniq.js';
9
- import pascalize from '../pascalize.js';
10
10
  export default function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, connectionName = 'default', }) {
11
11
  fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
12
12
  const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
@@ -32,17 +32,19 @@ export default function generateDreamContent({ fullyQualifiedModelName, columnsW
32
32
  const fullyQualifiedAssociatedModelName = standardizeFullyQualifiedModelName(attributeName);
33
33
  const associationModelName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedAssociatedModelName);
34
34
  const associationImportStatement = importStatementForModel(fullyQualifiedModelName, fullyQualifiedAssociatedModelName);
35
- const associationName = camelize(associationModelName);
36
35
  if (!attributeType)
37
36
  throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
38
37
  switch (attributeType) {
39
- case 'belongs_to':
38
+ case 'belongs_to': {
40
39
  modelImportStatements.push(associationImportStatement);
40
+ const associationName = camelize(fullyQualifiedAssociatedModelName.split('/').pop());
41
+ const associationForeignKey = `${associationName}Id`;
41
42
  return `
42
- @deco.BelongsTo('${fullyQualifiedAssociatedModelName}'${descriptors.includes('optional') ? ', { optional: true }' : ''})
43
+ @deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${descriptors.includes('optional') ? ', optional: true' : ''} })
43
44
  public ${associationName}: ${associationModelName}${descriptors.includes('optional') ? ' | null' : ''}
44
- public ${associationName}Id: DreamColumn<${modelClassName}, '${associationName}Id'>
45
+ public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
45
46
  `;
47
+ }
46
48
  case 'has_one':
47
49
  case 'has_many':
48
50
  return '';
@@ -29,6 +29,7 @@ export default function generateFactoryContent({ fullyQualifiedModelName, column
29
29
  throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
30
30
  switch (attributeType) {
31
31
  case 'belongs_to': {
32
+ const attributeVariable = camelize(attributeName.split('/').pop());
32
33
  const fullyQualifiedAssociatedModelName = standardizeFullyQualifiedModelName(attributeName);
33
34
  const associationModelName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedAssociatedModelName);
34
35
  const associationFactoryImportStatement = `import create${associationModelName} from '${relativeDreamPath('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
@@ -17,30 +17,20 @@ export default function generateMigrationContent({ connectionName = 'default', t
17
17
  // instead, we'll add a check constraint that uses the STI child class name
18
18
  const optional = userWantsThisOptional || !!stiChildClassName;
19
19
  const sqlAttributeType = getAttributeType(attributeType, descriptors);
20
- let attributeName = snakeify(nonStandardAttributeName);
21
- if (attributeName === undefined)
22
- return acc;
23
20
  if (attributeType !== undefined && ['has_one', 'has_many'].includes(attributeType))
24
21
  return acc;
25
22
  if (attributeType === 'citext')
26
23
  requireCitextExtension = true;
27
- if (stiChildClassName && !userWantsThisOptional) {
28
- checkConstraints.push(`
29
-
30
- await db.schema
31
- .alterTable('${table}')
32
- .addCheckConstraint(
33
- '${table}_not_null_${attributeName}',
34
- sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
35
- )
36
- .execute()`);
37
- }
24
+ if (nonStandardAttributeName === undefined)
25
+ return acc;
26
+ let attributeName = snakeify(nonStandardAttributeName);
38
27
  switch (attributeType) {
39
28
  case 'belongs_to':
40
29
  columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
41
30
  primaryKeyType,
42
31
  optional,
43
32
  }));
33
+ attributeName = snakeify(nonStandardAttributeName.split('/').pop());
44
34
  attributeName = associationNameToForeignKey(attributeName);
45
35
  break;
46
36
  case 'enum':
@@ -74,7 +64,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
74
64
  break;
75
65
  }
76
66
  columnDrops.push(`.dropColumn('${attributeName}')`);
77
- if (COLUMNS_TO_INDEX.includes(attributeName)) {
67
+ if (attributeType === 'belongs_to' || COLUMNS_TO_INDEX.includes(attributeName)) {
78
68
  const indexName = `${table}_${attributeName}`;
79
69
  indexDefs.push(`await db.schema
80
70
  .createIndex('${indexName}')
@@ -83,6 +73,17 @@ export default function generateMigrationContent({ connectionName = 'default', t
83
73
  .execute()`);
84
74
  indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
85
75
  }
76
+ if (stiChildClassName && !userWantsThisOptional) {
77
+ checkConstraints.push(`
78
+
79
+ await db.schema
80
+ .alterTable('${table}')
81
+ .addCheckConstraint(
82
+ '${table}_not_null_${attributeName}',
83
+ sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
84
+ )
85
+ .execute()`);
86
+ }
86
87
  return acc;
87
88
  }, { columnDefs: [], columnDrops: [], indexDefs: [], indexDrops: [] });
88
89
  if (!table) {
@@ -252,7 +253,7 @@ function generateBelongsToStr(connectionName, associationName, { primaryKeyType,
252
253
  const dbDriverClass = Query.dbDriverClass(connectionName);
253
254
  const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
254
255
  const references = pluralize(associationName.replace(/\//g, '_').replace(/_id$/, ''));
255
- return `.addColumn('${associationNameToForeignKey(associationName)}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
256
+ return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
256
257
  }
257
258
  function generateIdStr({ primaryKeyType }) {
258
259
  switch (primaryKeyType) {
@@ -51,7 +51,7 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
51
51
  return '';
52
52
  if (['belongs_to', 'has_one', 'has_many'].includes(type))
53
53
  return '';
54
- return `\n ${attribute(name, type, attr, stiBaseSerializer)}`;
54
+ return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
55
55
  })
56
56
  .join('')}`;
57
57
  return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
@@ -66,9 +66,9 @@ ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerCl
66
66
  ${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}
67
67
  `;
68
68
  }
69
- function attribute(name, type, attr, stiBaseSerializer) {
69
+ function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
70
70
  if (name === 'type' && stiBaseSerializer) {
71
- return `.attribute('type', { openapi: { type: 'string', enum: [StiChildClass.sanitizedName] } })`;
71
+ return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
72
72
  }
73
73
  switch (type) {
74
74
  case 'json':
@@ -1,4 +1,19 @@
1
1
  import Dream from '../Dream.js';
2
2
  export default function comparisonKey(val, toKey = undefined) {
3
- return val instanceof Dream ? val.comparisonKey : toKey ? toKey(val) : val;
3
+ if (val instanceof Dream)
4
+ return val.comparisonKey;
5
+ if (toKey)
6
+ return toKey(val);
7
+ if (val === null)
8
+ return null;
9
+ if (val === undefined)
10
+ return undefined;
11
+ switch (typeof val) {
12
+ case 'number':
13
+ case 'string':
14
+ case 'bigint':
15
+ return val;
16
+ default:
17
+ return val.toString();
18
+ }
4
19
  }
@@ -0,0 +1,7 @@
1
+ import round from './round.js';
2
+ export default function percent(numerator, denominator, precision) {
3
+ if (!numerator || !denominator)
4
+ return 0;
5
+ const percent = (numerator / denominator) * 100;
6
+ return precision ? round(percent, precision) : percent;
7
+ }
@@ -14,8 +14,5 @@ import sortBy from './sortBy.js';
14
14
  * ```
15
15
  */
16
16
  export default function sort(array) {
17
- if (typeof array[0] === 'bigint') {
18
- return sortBy(array, a => String(a));
19
- }
20
17
  return sortBy(array, a => a);
21
18
  }
@@ -1,3 +1,5 @@
1
+ import CalendarDate from './CalendarDate.js';
2
+ import { DateTime } from './DateTime.js';
1
3
  /**
2
4
  * Returns a copy of the array, sorted by the value returned by calling the function in the second argument on each element in the array
3
5
  * Returns a copy of the array sorted by the return value of the function passed as the second argument.
@@ -22,10 +24,17 @@ export default function sortBy(array, valueToCompare) {
22
24
  return arrayClone.sort((a, b) => {
23
25
  const aPrime = valueToCompare(a);
24
26
  const bPrime = valueToCompare(b);
25
- if (typeof aPrime === 'string' && typeof bPrime === 'string')
26
- return aPrime.localeCompare(bPrime);
27
27
  if (typeof aPrime === 'number' && typeof bPrime === 'number')
28
28
  return aPrime - bPrime;
29
+ if (typeof aPrime === 'bigint' && typeof bPrime === 'bigint')
30
+ return aPrime > bPrime ? 1 : aPrime < bPrime ? -1 : 0;
31
+ if (typeof aPrime === 'string' && typeof bPrime === 'string')
32
+ return aPrime.localeCompare(bPrime);
33
+ if (aPrime instanceof DateTime && bPrime instanceof DateTime)
34
+ return aPrime.valueOf() - bPrime.valueOf();
35
+ if ((aPrime instanceof DateTime || aPrime instanceof CalendarDate) &&
36
+ (bPrime instanceof DateTime || bPrime instanceof CalendarDate))
37
+ return (aPrime.toISO() ?? '').localeCompare(bPrime.toISO() ?? '');
29
38
  throw new UnsupportedValueFromComparisonFunction(aPrime, bPrime);
30
39
  });
31
40
  }
@@ -1,13 +1,10 @@
1
1
  import comparisonKey from './comparisonKey.js';
2
2
  export default function uniq(arr, toKey = undefined) {
3
3
  const map = arr.reduce((acc, val) => {
4
- const baseKey = comparisonKey(val, toKey);
5
- // Prefix with underscore to ensure that the values cannot be _interpreted_ as integers.
6
- // If they can be interpreted as integers, then the keys are ordered not by the
7
- // order in which they were added, but in ascending numerical order.
8
- const key = typeof baseKey === 'string' ? baseKey : `_${baseKey}`;
9
- acc[key] ||= val;
4
+ const key = comparisonKey(val, toKey);
5
+ if (!acc.has(key))
6
+ acc.set(key, val);
10
7
  return acc;
11
- }, {});
12
- return Object.values(map);
8
+ }, new Map());
9
+ return [...map.values()];
13
10
  }
@@ -54,6 +54,7 @@ export { default as pascalize } from './helpers/pascalize.js';
54
54
  export { default as dreamPath } from './helpers/path/dreamPath.js';
55
55
  export { default as relativeDreamPath } from './helpers/path/relativeDreamPath.js';
56
56
  export { default as sharedPathPrefix } from './helpers/path/sharedPathPrefix.js';
57
+ export { default as percent } from './helpers/percent.js';
57
58
  export { Range, default as range } from './helpers/range.js';
58
59
  export { default as round } from './helpers/round.js';
59
60
  export { default as snakeify } from './helpers/snakeify.js';
@@ -8,7 +8,7 @@ import LoadBuilder from './dream/LoadBuilder.js';
8
8
  import Query from './dream/Query.js';
9
9
  import { PassthroughOnClause, WhereStatement } from './types/associations/shared.js';
10
10
  import { AssociationTableNames, DbConnectionType } from './types/db.js';
11
- import { AllDefaultScopeNames, AssociationNameToDream, AttributeKeys, CreateOrFindByExtraOpts, DefaultOrNamedScopeName, DreamAssociationNames, DreamAssociationNamesWithoutRequiredOnClauses, DreamAttributes, DreamColumnNames, DreamParamSafeColumnNames, DreamPrimaryKeyType, DreamSerializerKey, GlobalModelNames, GlobalSerializerName, JoinAndStatements, NextPreloadArgumentType, OrderDir, PassthroughColumnNames, PluckEachArgs, PrimaryKeyForFind, TableColumnNames, UpdateableAssociationProperties, UpdateableProperties, UpdateablePropertiesForClass, UpdateOrCreateByExtraOpts } from './types/dream.js';
11
+ import { AllDefaultScopeNames, AssociationNameToDream, AttributeKeys, CreateOrFindByExtraOpts, DefaultOrNamedScopeName, DreamAssociationNames, DreamAssociationNamesWithoutRequiredOnClauses, DreamAttributes, DreamBelongsToAssociationNames, DreamColumnNames, DreamHasManyAssociationNames, DreamHasOneAssociationNames, DreamModelAssociationNames, DreamParamSafeColumnNames, DreamPrimaryKeyType, DreamSerializerKey, GlobalModelNames, GlobalSerializerName, JoinAndStatements, OrderDir, PassthroughColumnNames, PluckEachArgs, PrimaryKeyForFind, TableColumnNames, UpdateableAssociationProperties, UpdateableProperties, UpdateablePropertiesForClass, UpdateOrCreateByExtraOpts } from './types/dream.js';
12
12
  import { BaseModelColumnTypes, DefaultQueryTypeOptions, FindEachOpts, LoadForModifierFn, PaginatedDreamQueryOptions, PaginatedDreamQueryResult, QueryWithJoinedAssociationsType, QueryWithJoinedAssociationsTypeAndNoPreload } from './types/query.js';
13
13
  import { DreamModelSerializerType, SimpleObjectSerializerType } from './types/serializer.js';
14
14
  import { ValidationType } from './types/validation.js';
@@ -2343,6 +2343,45 @@ export default class Dream {
2343
2343
  * @returns A chainable LoadBuilder instance
2344
2344
  */
2345
2345
  load<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs<DB, Schema, TableName, Arr>]): LoadBuilder<I>;
2346
+ /**
2347
+ * If the association is already loaded on the instance, it returns the loaded value
2348
+ * immediately without making a database query. If the association is not loaded,
2349
+ * it performs a database query to fetch the association.
2350
+ *
2351
+ * If a query is performed, the association is set on the model so that future calls to
2352
+ * access this association can access the already loaded value.
2353
+ *
2354
+ * ```ts
2355
+ * // return the already loaded user if it exists or fetch it from the database otherwise
2356
+ * const user = await post.associationOrFail('user')
2357
+ * ```
2358
+ *
2359
+ * @param associationName - The name of the BelongsTo or HasOne association
2360
+ * @returns The associated model instance or null
2361
+ */
2362
+ association<I extends Dream, AssociationName extends DreamBelongsToAssociationNames<I> | DreamHasOneAssociationNames<I> | DreamHasManyAssociationNames<I>, ReturnType extends AssociationName extends DreamHasManyAssociationNames<I> ? AssociationNameToDream<I, AssociationName>[] : AssociationNameToDream<I, AssociationName> | null>(this: I, associationName: AssociationName): Promise<ReturnType>;
2363
+ /**
2364
+ * If the association is already loaded on the instance, it returns the loaded value
2365
+ * immediately without making a database query. If the association is not loaded,
2366
+ * it performs a database query to fetch the association.
2367
+ *
2368
+ * Unlike `association`, this method throws an exception if no associated
2369
+ * record is found, guaranteeing a non-null result.
2370
+ *
2371
+ * If a query is performed, the association is set on the model so that future calls to
2372
+ * access this association can access the already loaded value.
2373
+ *
2374
+ * ```ts
2375
+ * // return the already loaded user if it exists or fetch it from the database otherwise,
2376
+ * // throwing RecordNotFound either way if the associated model does not exist
2377
+ * const user = await post.associationOrFail('user')
2378
+ * ```
2379
+ *
2380
+ * @param associationName - The name of the BelongsTo or HasOne association
2381
+ * @returns The associated model instance (never null)
2382
+ * @throws RecordNotFound if no associated record exists
2383
+ */
2384
+ associationOrFail<I extends Dream, AssociationName extends DreamBelongsToAssociationNames<I> | DreamHasOneAssociationNames<I> | DreamHasManyAssociationNames<I>, ReturnType extends AssociationName extends DreamHasManyAssociationNames<I> ? AssociationNameToDream<I, AssociationName>[] : AssociationNameToDream<I, AssociationName>>(this: I, associationName: AssociationName): Promise<ReturnType>;
2346
2385
  /**
2347
2386
  * Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
2348
2387
  * in a DreamSerializer. This traverses the entire content tree of serializers to automatically
@@ -2401,8 +2440,8 @@ export default class Dream {
2401
2440
  * 4. the individual query becomes more complex the more associations are included
2402
2441
  * 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
2403
2442
  *
2404
- * NOTE: {@link Dream.leftJoinPreload} is often a preferrable way of achieving the
2405
- * same goal.
2443
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
2444
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
2406
2445
  *
2407
2446
  * ```ts
2408
2447
  * await user
@@ -2436,6 +2475,9 @@ export default class Dream {
2436
2475
  * This method analyzes the serializer (specified by `serializerKey` or 'default') and
2437
2476
  * automatically preloads all associations that will be needed during serialization.
2438
2477
  *
2478
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
2479
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
2480
+ *
2439
2481
  * ```ts
2440
2482
  * // Instead of manually specifying all associations:
2441
2483
  * await User.preload('posts', 'comments', 'replies').all()
@@ -2488,7 +2530,7 @@ export default class Dream {
2488
2530
  * @param associationName - the association name you wish to check the loading of
2489
2531
  * @returns A boolean
2490
2532
  */
2491
- loaded<I extends Dream, TableName extends I['table'], Schema extends I['schema'], AssociationName extends NextPreloadArgumentType<Schema, TableName>>(this: I, associationName: AssociationName): boolean;
2533
+ loaded<I extends Dream, TableName extends I['table'], Schema extends I['schema'], AssociationName extends DreamModelAssociationNames<Schema, TableName>>(this: I, associationName: AssociationName): boolean;
2492
2534
  /**
2493
2535
  * Reloads an instance, refreshing all it's attribute values
2494
2536
  * to those in the database.
@@ -4,6 +4,7 @@ export default class DreamBin {
4
4
  }): Promise<void>;
5
5
  static dbCreate(): Promise<void>;
6
6
  static dbDrop(): Promise<void>;
7
+ static dbEnsureAllMigrationsHaveBeenRun(): Promise<void>;
7
8
  static dbMigrate(): Promise<void>;
8
9
  static dbRollback(opts: {
9
10
  steps: number;
@@ -1,5 +1,21 @@
1
1
  import { Kysely } from 'kysely';
2
2
  export default class DreamMigrationHelpers {
3
+ /**
4
+ * Rename a table and its associated primary key sequence.
5
+ *
6
+ * This method renames both the table and its primary key sequence to keep them
7
+ * in sync. When PostgreSQL creates a table with a serial or bigserial primary key,
8
+ * it automatically creates a sequence named `{tablename}_id_seq`. If you only rename
9
+ * the table, the sequence keeps the old name, which can cause confusion and issues.
10
+ *
11
+ * This method is only suitable for tables that have a serial or bigserial primary
12
+ * key column named 'id'.
13
+ *
14
+ * @param db - The Kysely database object passed into the migration up/down function
15
+ * @param from - The current name of the table to rename
16
+ * @param to - The new name for the table
17
+ */
18
+ static renameTable(db: Kysely<any>, from: string, to: string): Promise<void>;
3
19
  /**
4
20
  * Unique indexes cannot be populated by the same value even within a transaction,
5
21
  * but deferrable unique constraints can.
@@ -12,5 +12,5 @@ export default function setPosition({ position, previousPosition, dream, positio
12
12
  scope: string | string[] | undefined;
13
13
  txn: DreamTransaction<any> | undefined;
14
14
  }): Promise<void>;
15
- export declare function applySortableScopesToQuery<QB extends UpdateQueryBuilder<any, string, string, any> | SelectQueryBuilder<any, any, any>>(dream: Dream, kyselyQuery: QB, whereValueCB: (column: string) => any, scope?: string | string[]): QB;
15
+ export declare function applySortableScopesToQuery<QB extends UpdateQueryBuilder<any, any, any, any> | SelectQueryBuilder<any, any, any>>(dream: Dream, kyselyQuery: QB, whereValueCB: (column: string) => any, scope?: string | string[]): QB;
16
16
  export declare function getPostgresQueryDriver(connectionName: string): typeof PostgresQueryDriver;
@@ -20,6 +20,7 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
20
20
  */
21
21
  protected readonly innerJoinDreamClasses: readonly (typeof Dream)[];
22
22
  constructor(query: Query<DreamInstance, any>);
23
+ static ensureAllMigrationsHaveBeenRun(connectionName: string): Promise<void>;
23
24
  /**
24
25
  * migrate the database. Must respond to the NODE_ENV value.
25
26
  */
@@ -1,4 +1,4 @@
1
- import { DeleteQueryBuilder, Kysely, Transaction as KyselyTransaction, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
1
+ import { DeleteQueryBuilder, Kysely, Transaction as KyselyTransaction, OrderByItemBuilder, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
2
2
  import { DialectProviderCb } from '../../db/DreamDbConnection.js';
3
3
  import Dream from '../../Dream.js';
4
4
  import { SchemaBuilderInformationSchemaRow } from '../../helpers/cli/SchemaBuilder.js';
@@ -13,6 +13,7 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
13
13
  dbFor(sqlCommandType: SqlCommandType): Kysely<DreamInstance['DB']> | KyselyTransaction<DreamInstance['DB']>;
14
14
  static dbFor<I extends Dream>(connectionName: string, dbConnectionType: DbConnectionType, dreamTransaction?: DreamTransaction<I> | null): Kysely<I['DB']> | KyselyTransaction<I['DB']>;
15
15
  static dialectProvider(connectionName: string, dbConnectionType: DbConnectionType): DialectProviderCb;
16
+ static ensureAllMigrationsHaveBeenRun(connectionName: string): Promise<void>;
16
17
  /**
17
18
  * migrate the database. Must respond to the NODE_ENV value.
18
19
  */
@@ -266,7 +267,7 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
266
267
  }>;
267
268
  private buildDelete;
268
269
  private buildSelect;
269
- orderByDirection(direction: OrderDir | null): import("kysely").RawBuilder<unknown>;
270
+ orderByDirection(direction: OrderDir | null): (obj: OrderByItemBuilder) => OrderByItemBuilder;
270
271
  private buildUpdate;
271
272
  /**
272
273
  * @internal
@@ -0,0 +1,9 @@
1
+ import { DialectProviderCb } from '../../../../db/DreamDbConnection.js';
2
+ type MigrationModes = 'migrate' | 'rollback';
3
+ interface MigrationOpts {
4
+ connectionName: string;
5
+ dialectProvider: DialectProviderCb;
6
+ mode?: MigrationModes;
7
+ }
8
+ export default function checkForNeedToBeRunMigrations({ connectionName, dialectProvider, }: MigrationOpts): Promise<boolean>;
9
+ export {};
@@ -0,0 +1 @@
1
+ export default function migrationFolderPath(connectionName: string): string;