@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
@@ -5,11 +5,11 @@ const pluralize_esm_1 = require("pluralize-esm");
5
5
  const serializerGlobalNameFromFullyQualifiedModelName_js_1 = require("../../serializer/helpers/serializerGlobalNameFromFullyQualifiedModelName.js");
6
6
  const camelize_js_1 = require("../camelize.js");
7
7
  const globalClassNameFromFullyQualifiedModelName_js_1 = require("../globalClassNameFromFullyQualifiedModelName.js");
8
+ const pascalize_js_1 = require("../pascalize.js");
8
9
  const relativeDreamPath_js_1 = require("../path/relativeDreamPath.js");
9
10
  const snakeify_js_1 = require("../snakeify.js");
10
11
  const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
11
12
  const uniq_js_1 = require("../uniq.js");
12
- const pascalize_js_1 = require("../pascalize.js");
13
13
  function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, connectionName = 'default', }) {
14
14
  fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
15
15
  const modelClassName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
@@ -35,17 +35,19 @@ function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fully
35
35
  const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
36
36
  const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
37
37
  const associationImportStatement = importStatementForModel(fullyQualifiedModelName, fullyQualifiedAssociatedModelName);
38
- const associationName = (0, camelize_js_1.default)(associationModelName);
39
38
  if (!attributeType)
40
39
  throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
41
40
  switch (attributeType) {
42
- case 'belongs_to':
41
+ case 'belongs_to': {
43
42
  modelImportStatements.push(associationImportStatement);
43
+ const associationName = (0, camelize_js_1.default)(fullyQualifiedAssociatedModelName.split('/').pop());
44
+ const associationForeignKey = `${associationName}Id`;
44
45
  return `
45
- @deco.BelongsTo('${fullyQualifiedAssociatedModelName}'${descriptors.includes('optional') ? ', { optional: true }' : ''})
46
+ @deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${descriptors.includes('optional') ? ', optional: true' : ''} })
46
47
  public ${associationName}: ${associationModelName}${descriptors.includes('optional') ? ' | null' : ''}
47
- public ${associationName}Id: DreamColumn<${modelClassName}, '${associationName}Id'>
48
+ public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
48
49
  `;
50
+ }
49
51
  case 'has_one':
50
52
  case 'has_many':
51
53
  return '';
@@ -32,6 +32,7 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
32
32
  throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
33
33
  switch (attributeType) {
34
34
  case 'belongs_to': {
35
+ const attributeVariable = (0, camelize_js_1.default)(attributeName.split('/').pop());
35
36
  const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
36
37
  const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
37
38
  const associationFactoryImportStatement = `import create${associationModelName} from '${(0, relativeDreamPath_js_1.default)('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
@@ -21,30 +21,20 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
21
21
  // instead, we'll add a check constraint that uses the STI child class name
22
22
  const optional = userWantsThisOptional || !!stiChildClassName;
23
23
  const sqlAttributeType = getAttributeType(attributeType, descriptors);
24
- let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
25
- if (attributeName === undefined)
26
- return acc;
27
24
  if (attributeType !== undefined && ['has_one', 'has_many'].includes(attributeType))
28
25
  return acc;
29
26
  if (attributeType === 'citext')
30
27
  requireCitextExtension = true;
31
- if (stiChildClassName && !userWantsThisOptional) {
32
- checkConstraints.push(`
33
-
34
- await db.schema
35
- .alterTable('${table}')
36
- .addCheckConstraint(
37
- '${table}_not_null_${attributeName}',
38
- sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
39
- )
40
- .execute()`);
41
- }
28
+ if (nonStandardAttributeName === undefined)
29
+ return acc;
30
+ let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
42
31
  switch (attributeType) {
43
32
  case 'belongs_to':
44
33
  columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
45
34
  primaryKeyType,
46
35
  optional,
47
36
  }));
37
+ attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName.split('/').pop());
48
38
  attributeName = associationNameToForeignKey(attributeName);
49
39
  break;
50
40
  case 'enum':
@@ -78,7 +68,7 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
78
68
  break;
79
69
  }
80
70
  columnDrops.push(`.dropColumn('${attributeName}')`);
81
- if (COLUMNS_TO_INDEX.includes(attributeName)) {
71
+ if (attributeType === 'belongs_to' || COLUMNS_TO_INDEX.includes(attributeName)) {
82
72
  const indexName = `${table}_${attributeName}`;
83
73
  indexDefs.push(`await db.schema
84
74
  .createIndex('${indexName}')
@@ -87,6 +77,17 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
87
77
  .execute()`);
88
78
  indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
89
79
  }
80
+ if (stiChildClassName && !userWantsThisOptional) {
81
+ checkConstraints.push(`
82
+
83
+ await db.schema
84
+ .alterTable('${table}')
85
+ .addCheckConstraint(
86
+ '${table}_not_null_${attributeName}',
87
+ sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
88
+ )
89
+ .execute()`);
90
+ }
90
91
  return acc;
91
92
  }, { columnDefs: [], columnDrops: [], indexDefs: [], indexDrops: [] });
92
93
  if (!table) {
@@ -256,7 +257,7 @@ function generateBelongsToStr(connectionName, associationName, { primaryKeyType,
256
257
  const dbDriverClass = Query_js_1.default.dbDriverClass(connectionName);
257
258
  const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
258
259
  const references = (0, pluralize_esm_1.default)(associationName.replace(/\//g, '_').replace(/_id$/, ''));
259
- return `.addColumn('${associationNameToForeignKey(associationName)}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
260
+ return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
260
261
  }
261
262
  function generateIdStr({ primaryKeyType }) {
262
263
  switch (primaryKeyType) {
@@ -54,7 +54,7 @@ function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes =
54
54
  return '';
55
55
  if (['belongs_to', 'has_one', 'has_many'].includes(type))
56
56
  return '';
57
- return `\n ${attribute(name, type, attr, stiBaseSerializer)}`;
57
+ return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
58
58
  })
59
59
  .join('')}`;
60
60
  return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
@@ -69,9 +69,9 @@ ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerCl
69
69
  ${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}
70
70
  `;
71
71
  }
72
- function attribute(name, type, attr, stiBaseSerializer) {
72
+ function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
73
73
  if (name === 'type' && stiBaseSerializer) {
74
- return `.attribute('type', { openapi: { type: 'string', enum: [StiChildClass.sanitizedName] } })`;
74
+ return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
75
75
  }
76
76
  switch (type) {
77
77
  case 'json':
@@ -3,5 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = comparisonKey;
4
4
  const Dream_js_1 = require("../Dream.js");
5
5
  function comparisonKey(val, toKey = undefined) {
6
- return val instanceof Dream_js_1.default ? val.comparisonKey : toKey ? toKey(val) : val;
6
+ if (val instanceof Dream_js_1.default)
7
+ return val.comparisonKey;
8
+ if (toKey)
9
+ return toKey(val);
10
+ if (val === null)
11
+ return null;
12
+ if (val === undefined)
13
+ return undefined;
14
+ switch (typeof val) {
15
+ case 'number':
16
+ case 'string':
17
+ case 'bigint':
18
+ return val;
19
+ default:
20
+ return val.toString();
21
+ }
7
22
  }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = percent;
4
+ const round_js_1 = require("./round.js");
5
+ function percent(numerator, denominator, precision) {
6
+ if (!numerator || !denominator)
7
+ return 0;
8
+ const percent = (numerator / denominator) * 100;
9
+ return precision ? (0, round_js_1.default)(percent, precision) : percent;
10
+ }
@@ -17,8 +17,5 @@ const sortBy_js_1 = require("./sortBy.js");
17
17
  * ```
18
18
  */
19
19
  function sort(array) {
20
- if (typeof array[0] === 'bigint') {
21
- return (0, sortBy_js_1.default)(array, a => String(a));
22
- }
23
20
  return (0, sortBy_js_1.default)(array, a => a);
24
21
  }
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UnsupportedValueFromComparisonFunction = void 0;
4
4
  exports.default = sortBy;
5
+ const CalendarDate_js_1 = require("./CalendarDate.js");
6
+ const DateTime_js_1 = require("./DateTime.js");
5
7
  /**
6
8
  * 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
7
9
  * Returns a copy of the array sorted by the return value of the function passed as the second argument.
@@ -26,10 +28,17 @@ function sortBy(array, valueToCompare) {
26
28
  return arrayClone.sort((a, b) => {
27
29
  const aPrime = valueToCompare(a);
28
30
  const bPrime = valueToCompare(b);
29
- if (typeof aPrime === 'string' && typeof bPrime === 'string')
30
- return aPrime.localeCompare(bPrime);
31
31
  if (typeof aPrime === 'number' && typeof bPrime === 'number')
32
32
  return aPrime - bPrime;
33
+ if (typeof aPrime === 'bigint' && typeof bPrime === 'bigint')
34
+ return aPrime > bPrime ? 1 : aPrime < bPrime ? -1 : 0;
35
+ if (typeof aPrime === 'string' && typeof bPrime === 'string')
36
+ return aPrime.localeCompare(bPrime);
37
+ if (aPrime instanceof DateTime_js_1.DateTime && bPrime instanceof DateTime_js_1.DateTime)
38
+ return aPrime.valueOf() - bPrime.valueOf();
39
+ if ((aPrime instanceof DateTime_js_1.DateTime || aPrime instanceof CalendarDate_js_1.default) &&
40
+ (bPrime instanceof DateTime_js_1.DateTime || bPrime instanceof CalendarDate_js_1.default))
41
+ return (aPrime.toISO() ?? '').localeCompare(bPrime.toISO() ?? '');
33
42
  throw new UnsupportedValueFromComparisonFunction(aPrime, bPrime);
34
43
  });
35
44
  }
@@ -4,13 +4,10 @@ exports.default = uniq;
4
4
  const comparisonKey_js_1 = require("./comparisonKey.js");
5
5
  function uniq(arr, toKey = undefined) {
6
6
  const map = arr.reduce((acc, val) => {
7
- const baseKey = (0, comparisonKey_js_1.default)(val, toKey);
8
- // Prefix with underscore to ensure that the values cannot be _interpreted_ as integers.
9
- // If they can be interpreted as integers, then the keys are ordered not by the
10
- // order in which they were added, but in ascending numerical order.
11
- const key = typeof baseKey === 'string' ? baseKey : `_${baseKey}`;
12
- acc[key] ||= val;
7
+ const key = (0, comparisonKey_js_1.default)(val, toKey);
8
+ if (!acc.has(key))
9
+ acc.set(key, val);
13
10
  return acc;
14
- }, {});
15
- return Object.values(map);
11
+ }, new Map());
12
+ return [...map.values()];
16
13
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.globalClassNameFromFullyQualifiedModelName = exports.Env = exports.DreamLogos = exports.DateTime = exports.compact = exports.cloneDeepSafe = exports.generateDream = exports.capitalize = exports.camelize = exports.CalendarDate = exports.Benchmark = exports.ValidationError = exports.MissingSerializersDefinition = exports.RecordNotFound = exports.GlobalNameNotSet = exports.NotNullViolation = exports.DataTypeColumnTypeMismatch = exports.DataIncompatibleWithDatabaseField = exports.ColumnOverflow = exports.CheckConstraintViolation = exports.CreateOrFindByFailedToCreateAndFind = exports.NonLoadedAssociation = exports.Encrypt = exports.PostgresQueryDriver = exports.KyselyQueryDriver = exports.QueryDriverBase = exports.Query = exports.DreamTransaction = exports.openapiShorthandPrimitiveTypes = exports.openapiPrimitiveTypes = exports.DreamConst = exports.Dream = exports.DreamAppAllowedPackageManagersEnumValues = exports.DreamApp = exports.lookupClassByGlobalName = exports.DreamImporter = exports.Decorators = exports.STI = exports.SoftDelete = exports.ReplicaSafe = exports.validateTable = exports.validateColumn = exports.DreamMigrationHelpers = exports.untypedDb = exports.pgErrorType = exports.dreamDbConnections = exports.closeAllDbConnections = exports.DreamCLI = exports.CliFileWriter = exports.DreamBin = void 0;
4
- exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = exports.intersection = exports.hyphenize = exports.groupBy = void 0;
4
+ exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.percent = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = exports.intersection = exports.hyphenize = exports.groupBy = void 0;
5
5
  var index_js_1 = require("./bin/index.js");
6
6
  Object.defineProperty(exports, "DreamBin", { enumerable: true, get: function () { return index_js_1.default; } });
7
7
  var CliFileWriter_js_1 = require("./cli/CliFileWriter.js");
@@ -118,6 +118,8 @@ var relativeDreamPath_js_1 = require("./helpers/path/relativeDreamPath.js");
118
118
  Object.defineProperty(exports, "relativeDreamPath", { enumerable: true, get: function () { return relativeDreamPath_js_1.default; } });
119
119
  var sharedPathPrefix_js_1 = require("./helpers/path/sharedPathPrefix.js");
120
120
  Object.defineProperty(exports, "sharedPathPrefix", { enumerable: true, get: function () { return sharedPathPrefix_js_1.default; } });
121
+ var percent_js_1 = require("./helpers/percent.js");
122
+ Object.defineProperty(exports, "percent", { enumerable: true, get: function () { return percent_js_1.default; } });
121
123
  var range_js_1 = require("./helpers/range.js");
122
124
  Object.defineProperty(exports, "Range", { enumerable: true, get: function () { return range_js_1.Range; } });
123
125
  Object.defineProperty(exports, "range", { enumerable: true, get: function () { return range_js_1.default; } });
@@ -41,6 +41,7 @@ import CreateOrUpdateByFailedToCreateAndUpdate from './errors/CreateOrUpdateByFa
41
41
  import GlobalNameNotSet from './errors/dream-app/GlobalNameNotSet.js';
42
42
  import DreamMissingRequiredOverride from './errors/DreamMissingRequiredOverride.js';
43
43
  import NonExistentScopeProvidedToResort from './errors/NonExistentScopeProvidedToResort.js';
44
+ import RecordNotFound from './errors/RecordNotFound.js';
44
45
  import MissingSerializersDefinition from './errors/serializers/MissingSerializersDefinition.js';
45
46
  import CalendarDate from './helpers/CalendarDate.js';
46
47
  import cloneDeepSafe from './helpers/cloneDeepSafe.js';
@@ -3218,6 +3219,61 @@ export default class Dream {
3218
3219
  load(...args) {
3219
3220
  return new LoadBuilder(this).load(...args);
3220
3221
  }
3222
+ /**
3223
+ * If the association is already loaded on the instance, it returns the loaded value
3224
+ * immediately without making a database query. If the association is not loaded,
3225
+ * it performs a database query to fetch the association.
3226
+ *
3227
+ * If a query is performed, the association is set on the model so that future calls to
3228
+ * access this association can access the already loaded value.
3229
+ *
3230
+ * ```ts
3231
+ * // return the already loaded user if it exists or fetch it from the database otherwise
3232
+ * const user = await post.associationOrFail('user')
3233
+ * ```
3234
+ *
3235
+ * @param associationName - The name of the BelongsTo or HasOne association
3236
+ * @returns The associated model instance or null
3237
+ */
3238
+ async association(associationName) {
3239
+ if (!this.loaded(associationName)) {
3240
+ const association = this.getAssociationMetadata(associationName);
3241
+ if (association?.type === 'HasMany') {
3242
+ this[associationName] = (await this.associationQuery(associationName).all());
3243
+ }
3244
+ else {
3245
+ this[associationName] = (await this.associationQuery(associationName).first());
3246
+ }
3247
+ }
3248
+ return this[associationName];
3249
+ }
3250
+ /**
3251
+ * If the association is already loaded on the instance, it returns the loaded value
3252
+ * immediately without making a database query. If the association is not loaded,
3253
+ * it performs a database query to fetch the association.
3254
+ *
3255
+ * Unlike `association`, this method throws an exception if no associated
3256
+ * record is found, guaranteeing a non-null result.
3257
+ *
3258
+ * If a query is performed, the association is set on the model so that future calls to
3259
+ * access this association can access the already loaded value.
3260
+ *
3261
+ * ```ts
3262
+ * // return the already loaded user if it exists or fetch it from the database otherwise,
3263
+ * // throwing RecordNotFound either way if the associated model does not exist
3264
+ * const user = await post.associationOrFail('user')
3265
+ * ```
3266
+ *
3267
+ * @param associationName - The name of the BelongsTo or HasOne association
3268
+ * @returns The associated model instance (never null)
3269
+ * @throws RecordNotFound if no associated record exists
3270
+ */
3271
+ async associationOrFail(associationName) {
3272
+ const response = await this.association(associationName);
3273
+ if (this[associationName] === null)
3274
+ throw new RecordNotFound(this['sanitizedConstructorName']);
3275
+ return response;
3276
+ }
3221
3277
  /**
3222
3278
  * Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
3223
3279
  * in a DreamSerializer. This traverses the entire content tree of serializers to automatically
@@ -3278,8 +3334,8 @@ export default class Dream {
3278
3334
  * 4. the individual query becomes more complex the more associations are included
3279
3335
  * 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
3280
3336
  *
3281
- * NOTE: {@link Dream.leftJoinPreload} is often a preferrable way of achieving the
3282
- * same goal.
3337
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
3338
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
3283
3339
  *
3284
3340
  * ```ts
3285
3341
  * await user
@@ -3315,6 +3371,9 @@ export default class Dream {
3315
3371
  * This method analyzes the serializer (specified by `serializerKey` or 'default') and
3316
3372
  * automatically preloads all associations that will be needed during serialization.
3317
3373
  *
3374
+ * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
3375
+ * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
3376
+ *
3318
3377
  * ```ts
3319
3378
  * // Instead of manually specifying all associations:
3320
3379
  * await User.preload('posts', 'comments', 'replies').all()
@@ -22,6 +22,12 @@ export default class DreamBin {
22
22
  await Query.dbDriverClass(connectionName).dbDrop(connectionName);
23
23
  }
24
24
  }
25
+ static async dbEnsureAllMigrationsHaveBeenRun() {
26
+ const dreamApp = DreamApp.getOrFail();
27
+ for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
28
+ await Query.dbDriverClass(connectionName).ensureAllMigrationsHaveBeenRun(connectionName);
29
+ }
30
+ }
25
31
  static async dbMigrate() {
26
32
  const dreamApp = DreamApp.getOrFail();
27
33
  for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
@@ -32,7 +32,7 @@ ${INDENT}
32
32
  ${INDENT} - decimal:
33
33
  ${INDENT} - decimal[]:
34
34
  ${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
35
- ${INDENT}
35
+ ${INDENT}
36
36
  ${INDENT} leveraging arrays, add the "[]" suffix, e.g.: volume:decimal[]:3,2
37
37
  ${INDENT}
38
38
  ${INDENT} - enum:
@@ -71,7 +71,7 @@ export default class DreamCLI {
71
71
  .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')
72
72
  .option('--schema-only')
73
73
  .action(async (options = {}) => {
74
- await initializeDreamApp();
74
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
75
75
  await DreamBin.sync(() => { }, options);
76
76
  process.exit();
77
77
  });
@@ -93,7 +93,7 @@ export default class DreamCLI {
93
93
  .option('--connection-name <connectionName>', 'the connection name you wish to use for your migration')
94
94
  .argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
95
95
  .action(async (migrationName, columnsWithTypes, options) => {
96
- await initializeDreamApp();
96
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
97
97
  await DreamBin.generateMigration(migrationName, columnsWithTypes, options.connectionName || 'default');
98
98
  process.exit();
99
99
  });
@@ -109,7 +109,7 @@ export default class DreamCLI {
109
109
  .argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
110
110
  .argument('[columnsWithTypes...]', columnsWithTypesDescription)
111
111
  .action(async (modelName, columnsWithTypes, options) => {
112
- await initializeDreamApp();
112
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
113
113
  await DreamBin.generateDream(modelName, columnsWithTypes, options);
114
114
  process.exit();
115
115
  });
@@ -126,7 +126,7 @@ ${INDENT} to extend the Room model in src/app/models/Room: Room
126
126
  ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
127
127
  .argument('[columnsWithTypes...]', columnsWithTypesDescription)
128
128
  .action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
129
- await initializeDreamApp();
129
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
130
130
  if (extendsWord !== 'extends')
131
131
  throw new Error('Expecting: `<child-name> extends <parent-name> <columns-and-types>');
132
132
  await DreamBin.generateStiChild(childModelName, parentModelName, columnsWithTypes, options);
@@ -137,16 +137,24 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
137
137
  .description('creates a new database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
138
138
  .action(async () => {
139
139
  EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
140
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
140
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
141
141
  await DreamBin.dbCreate();
142
142
  process.exit();
143
143
  });
144
+ program
145
+ .command('db:integrity-check')
146
+ .description('db:integrity-check fails if migrations need to be run')
147
+ .action(async () => {
148
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
149
+ await DreamBin.dbEnsureAllMigrationsHaveBeenRun();
150
+ process.exit();
151
+ });
144
152
  program
145
153
  .command('db:migrate')
146
154
  .description('db:migrate runs any outstanding database migrations')
147
155
  .option('--skip-sync', 'skips syncing local schema after running migrations')
148
156
  .action(async ({ skipSync }) => {
149
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
157
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
150
158
  await DreamBin.dbMigrate();
151
159
  if (EnvInternal.isDevelopmentOrTest && !skipSync) {
152
160
  await DreamBin.sync(onSync);
@@ -159,7 +167,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
159
167
  .option('--steps <number>', 'number of steps back to travel', myParseInt, 1)
160
168
  .option('--skip-sync', 'skips syncing local schema after running migrations')
161
169
  .action(async ({ steps, skipSync }) => {
162
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
170
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
163
171
  await DreamBin.dbRollback({ steps });
164
172
  if (EnvInternal.isDevelopmentOrTest && !skipSync) {
165
173
  await DreamBin.sync(onSync);
@@ -171,7 +179,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
171
179
  .description('drops the database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
172
180
  .action(async () => {
173
181
  EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
174
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
182
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
175
183
  await DreamBin.dbDrop();
176
184
  process.exit();
177
185
  });
@@ -180,11 +188,11 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
180
188
  .description('runs db:drop (safely), then db:create, db:migrate, and db:seed')
181
189
  .action(async () => {
182
190
  EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
183
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
191
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
184
192
  await DreamBin.dbDrop();
185
193
  await DreamBin.dbCreate();
186
194
  EnvInternal.unsetBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
187
- await initializeDreamApp({ bypassModelIntegrityCheck: true });
195
+ await initializeDreamApp({ bypassDreamIntegrityChecks: true });
188
196
  await DreamBin.dbMigrate();
189
197
  await DreamBin.sync(onSync);
190
198
  await seedDb();
@@ -1,5 +1,24 @@
1
1
  import { sql } 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 async renameTable(db, from, to) {
19
+ await db.schema.alterTable(from).renameTo(to).execute();
20
+ await sql `ALTER SEQUENCE ${from}_id_seq RENAME TO ${to}_id_seq`.execute(db);
21
+ }
3
22
  /**
4
23
  * Unique indexes cannot be populated by the same value even within a transaction,
5
24
  * but deferrable unique constraints can.
@@ -20,14 +20,14 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
20
20
  * }
21
21
  * ```
22
22
  *
23
- * @param opts.foreignKey - A custom column name to use for the foreign key.
23
+ * @param opts.on - A custom column name to use for joining associations on.
24
24
  * @param opts.optional - Whether or not this association is optional. Defaults to false.
25
25
  * @param opts.polymorphic - If true, this association will be treated as a polymorphic association.
26
26
  * @param opts.primaryKeyOverride - A custom column name to use for the primary key.
27
27
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
28
28
  */
29
29
  export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
30
- const { foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
30
+ const { on: foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
31
31
  return function (_, context) {
32
32
  const key = context.name;
33
33
  context.addInitializer(function () {
@@ -20,7 +20,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
20
20
  *
21
21
  * @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
22
22
  * @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.
23
- * @param opts.foreignKey - A custom column name to use for the foreign key.
23
+ * @param opts.on - A custom column name to use for joining associations on.
24
24
  * @param opts.and - An and-clause to be applied when this association is loaded
25
25
  * @param opts.andNot - A not and-clause to be applied when this association is loaded
26
26
  * @param opts.andAny - An andAny clause to be applied when this association is loaded
@@ -34,7 +34,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
34
34
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
35
35
  */
36
36
  export default function HasMany(globalAssociationNameOrNames, opts = {}) {
37
- const { dependent, distinct, foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
37
+ const { dependent, distinct, on: foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
38
38
  return function (_, context) {
39
39
  const key = context.name;
40
40
  context.addInitializer(function () {
@@ -19,7 +19,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
19
19
  * ```
20
20
  *
21
21
  * @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
22
- * @param opts.foreignKey - A custom column name to use for the foreign key.
22
+ * @param opts.on - A custom column name to use for joining associations on.
23
23
  * @param opts.and - An and-clause to be applied when this association is loaded
24
24
  * @param opts.andNot - A not and-clause to be applied when this association is loaded
25
25
  * @param opts.andAny - An andAny clause to be applied when this association is loaded
@@ -32,7 +32,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
32
32
  * @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
33
33
  */
34
34
  export default function HasOne(globalAssociationNameOrNames, opts = {}) {
35
- const { dependent, foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
35
+ const { dependent, on: foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
36
36
  return function (_, context) {
37
37
  const key = context.name;
38
38
  context.addInitializer(function () {
@@ -1215,7 +1215,10 @@ export default class Query {
1215
1215
  const recordCount = await this.count();
1216
1216
  const pageSize = opts.pageSize || DreamApp.getOrFail().paginationPageSize;
1217
1217
  const pageCount = Math.ceil(recordCount / pageSize);
1218
- const results = await this
1218
+ const query = this.orderStatements.length
1219
+ ? this
1220
+ : this.order({ [this.namespacedPrimaryKey]: 'asc' });
1221
+ const results = await query
1219
1222
  .limit(pageSize)
1220
1223
  .offset((page - 1) * pageSize)
1221
1224
  .all();
@@ -20,6 +20,12 @@ export default class QueryDriverBase {
20
20
  this.connectionOverride = query['originalOpts'].connection;
21
21
  this.innerJoinDreamClasses = Object.freeze(query['originalOpts'].innerJoinDreamClasses || []);
22
22
  }
23
+ // eslint-disable-next-line @typescript-eslint/require-await
24
+ static async ensureAllMigrationsHaveBeenRun(
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
+ connectionName) {
27
+ throw new Error('override ensureAllMigrationsHaveBeenRun in child class');
28
+ }
23
29
  /**
24
30
  * migrate the database. Must respond to the NODE_ENV value.
25
31
  */
@@ -13,7 +13,7 @@ import { CliFileWriter } from '../../cli/CliFileWriter.js';
13
13
  import DreamCLI from '../../cli/index.js';
14
14
  import { CHECK_VIOLATION, COLUMN_OVERFLOW, INVALID_INPUT_SYNTAX, NOT_NULL_VIOLATION, pgErrorType, } from '../../db/errors.js';
15
15
  import syncDbTypesFiles from '../../db/helpers/syncDbTypesFiles.js';
16
- import _db from '../../db/index.js';
16
+ import { default as _db } from '../../db/index.js';
17
17
  import associationToGetterSetterProp from '../../decorators/field/association/associationToGetterSetterProp.js';
18
18
  import PackageManager from '../../dream-app/helpers/PackageManager.js';
19
19
  import DreamApp from '../../dream-app/index.js';
@@ -64,6 +64,7 @@ import softDeleteDream from '../internal/softDeleteDream.js';
64
64
  import sqlResultToDreamInstance from '../internal/sqlResultToDreamInstance.js';
65
65
  import Query from '../Query.js';
66
66
  import QueryDriverBase from './Base.js';
67
+ import checkForNeedToBeRunMigrations from './helpers/kysely/checkForNeedToBeRunMigrations.js';
67
68
  import runMigration from './helpers/kysely/runMigration.js';
68
69
  export default class KyselyQueryDriver extends QueryDriverBase {
69
70
  // ATTENTION FRED
@@ -100,6 +101,14 @@ export default class KyselyQueryDriver extends QueryDriverBase {
100
101
  }),
101
102
  });
102
103
  }
104
+ static async ensureAllMigrationsHaveBeenRun(connectionName) {
105
+ const migrationsNeedToBeRun = await checkForNeedToBeRunMigrations({
106
+ connectionName,
107
+ dialectProvider: this.dialectProvider(connectionName, 'primary'),
108
+ });
109
+ if (migrationsNeedToBeRun)
110
+ throw new Error(`Migrations need to be run on ${connectionName} database`);
111
+ }
103
112
  /**
104
113
  * migrate the database. Must respond to the NODE_ENV value.
105
114
  */
@@ -694,9 +703,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
694
703
  return orderByDirection(direction);
695
704
  }
696
705
  buildUpdate(attributes) {
697
- let kyselyQuery = this.dbFor('update')
698
- .updateTable(this.query['tableName'])
699
- .set(attributes);
706
+ let kyselyQuery = this.dbFor('update').updateTable(this.query['tableName']);
707
+ kyselyQuery = kyselyQuery.set(attributes);
700
708
  kyselyQuery = this.conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery);
701
709
  const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
702
710
  return new this.constructor(results.clone).buildCommon(results.kyselyQuery);