@rvoh/dream 1.0.4 → 1.0.5

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 (212) hide show
  1. package/CHANGELOG.md +14 -6
  2. package/dist/cjs/src/bin/helpers/sync.js +3 -1
  3. package/dist/cjs/src/cli/CliFileWriter.js +39 -0
  4. package/dist/cjs/src/cli/logger/DreamCliLogger.js +5 -0
  5. package/dist/cjs/src/decorators/field/association/shared.js +2 -2
  6. package/dist/cjs/src/dream/QueryDriver/Kysely.js +84 -34
  7. package/dist/cjs/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js +19 -0
  8. package/dist/cjs/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.js +27 -0
  9. package/dist/cjs/src/errors/associations/MissingThroughAssociationSource.js +1 -1
  10. package/dist/cjs/src/helpers/cli/SchemaBuilder.js +2 -1
  11. package/dist/cjs/src/index.js +4 -2
  12. package/dist/esm/src/bin/helpers/sync.js +3 -1
  13. package/dist/esm/src/cli/CliFileWriter.js +35 -0
  14. package/dist/esm/src/cli/logger/DreamCliLogger.js +5 -0
  15. package/dist/esm/src/decorators/field/association/shared.js +2 -2
  16. package/dist/esm/src/dream/QueryDriver/Kysely.js +84 -34
  17. package/dist/esm/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js +16 -0
  18. package/dist/esm/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.js +24 -0
  19. package/dist/esm/src/errors/associations/MissingThroughAssociationSource.js +1 -1
  20. package/dist/esm/src/helpers/cli/SchemaBuilder.js +2 -1
  21. package/dist/esm/src/index.js +1 -0
  22. package/dist/types/src/cli/CliFileWriter.d.ts +9 -0
  23. package/dist/types/src/cli/logger/DreamCliLogger.d.ts +1 -0
  24. package/dist/types/src/decorators/Decorators.d.ts +6 -6
  25. package/dist/types/src/decorators/field/association/HasMany.d.ts +3 -3
  26. package/dist/types/src/decorators/field/association/HasOne.d.ts +3 -3
  27. package/dist/types/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.d.ts +12 -0
  28. package/dist/types/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.d.ts +17 -0
  29. package/dist/types/src/index.d.ts +1 -0
  30. package/dist/types/src/types/associations/belongsTo.d.ts +3 -1
  31. package/dist/types/src/types/associations/belongsTo.ts +4 -1
  32. package/dist/types/src/types/associations/hasMany.d.ts +3 -3
  33. package/dist/types/src/types/associations/hasMany.ts +7 -3
  34. package/dist/types/src/types/associations/hasOne.d.ts +3 -3
  35. package/dist/types/src/types/associations/hasOne.ts +6 -3
  36. package/dist/types/src/types/associations/shared.d.ts +6 -6
  37. package/dist/types/src/types/associations/shared.ts +24 -6
  38. package/docs/assets/navigation.js +1 -1
  39. package/docs/assets/search.js +1 -1
  40. package/docs/classes/Benchmark.html +2 -2
  41. package/docs/classes/CalendarDate.html +2 -2
  42. package/docs/classes/CliFileWriter.html +8 -0
  43. package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
  44. package/docs/classes/Decorators.html +19 -19
  45. package/docs/classes/Dream.html +136 -136
  46. package/docs/classes/DreamApp.html +4 -4
  47. package/docs/classes/DreamBin.html +2 -2
  48. package/docs/classes/DreamCLI.html +4 -4
  49. package/docs/classes/DreamImporter.html +2 -2
  50. package/docs/classes/DreamLogos.html +2 -2
  51. package/docs/classes/DreamMigrationHelpers.html +7 -7
  52. package/docs/classes/DreamSerializerBuilder.html +8 -8
  53. package/docs/classes/DreamTransaction.html +2 -2
  54. package/docs/classes/Encrypt.html +2 -2
  55. package/docs/classes/Env.html +2 -2
  56. package/docs/classes/GlobalNameNotSet.html +3 -3
  57. package/docs/classes/NonLoadedAssociation.html +3 -3
  58. package/docs/classes/ObjectSerializerBuilder.html +8 -8
  59. package/docs/classes/Query.html +60 -60
  60. package/docs/classes/Range.html +2 -2
  61. package/docs/classes/RecordNotFound.html +3 -3
  62. package/docs/classes/ValidationError.html +3 -3
  63. package/docs/functions/DreamSerializer.html +1 -1
  64. package/docs/functions/ObjectSerializer.html +1 -1
  65. package/docs/functions/ReplicaSafe.html +1 -1
  66. package/docs/functions/STI.html +1 -1
  67. package/docs/functions/SoftDelete.html +1 -1
  68. package/docs/functions/camelize.html +1 -1
  69. package/docs/functions/capitalize.html +1 -1
  70. package/docs/functions/cloneDeepSafe.html +1 -1
  71. package/docs/functions/closeAllDbConnections.html +1 -1
  72. package/docs/functions/compact.html +1 -1
  73. package/docs/functions/dreamDbConnections.html +1 -1
  74. package/docs/functions/dreamPath.html +1 -1
  75. package/docs/functions/expandStiClasses.html +1 -1
  76. package/docs/functions/generateDream.html +1 -1
  77. package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
  78. package/docs/functions/groupBy.html +1 -1
  79. package/docs/functions/hyphenize.html +1 -1
  80. package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
  81. package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
  82. package/docs/functions/intersection.html +1 -1
  83. package/docs/functions/isDreamSerializer.html +1 -1
  84. package/docs/functions/isEmpty.html +1 -1
  85. package/docs/functions/loadRepl.html +1 -1
  86. package/docs/functions/lookupClassByGlobalName.html +1 -1
  87. package/docs/functions/normalizeUnicode.html +1 -1
  88. package/docs/functions/pascalize.html +1 -1
  89. package/docs/functions/pgErrorType.html +1 -1
  90. package/docs/functions/range-1.html +1 -1
  91. package/docs/functions/relativeDreamPath.html +1 -1
  92. package/docs/functions/round.html +1 -1
  93. package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
  94. package/docs/functions/sharedPathPrefix.html +1 -1
  95. package/docs/functions/snakeify.html +1 -1
  96. package/docs/functions/sort.html +1 -1
  97. package/docs/functions/sortBy.html +1 -1
  98. package/docs/functions/sortObjectByKey.html +1 -1
  99. package/docs/functions/sortObjectByValue.html +1 -1
  100. package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
  101. package/docs/functions/uncapitalize.html +1 -1
  102. package/docs/functions/uniq.html +1 -1
  103. package/docs/functions/untypedDb.html +1 -1
  104. package/docs/functions/validateColumn.html +1 -1
  105. package/docs/functions/validateTable.html +1 -1
  106. package/docs/interfaces/BelongsToStatement.html +2 -2
  107. package/docs/interfaces/DecoratorContext.html +2 -2
  108. package/docs/interfaces/DreamAppInitOptions.html +2 -2
  109. package/docs/interfaces/DreamAppOpts.html +2 -2
  110. package/docs/interfaces/EncryptOptions.html +2 -2
  111. package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
  112. package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
  113. package/docs/interfaces/OpenapiDescription.html +2 -2
  114. package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
  115. package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
  116. package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
  117. package/docs/interfaces/SerializerRendererOpts.html +2 -2
  118. package/docs/modules.html +1 -0
  119. package/docs/types/Camelized.html +1 -1
  120. package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
  121. package/docs/types/DateTime.html +1 -1
  122. package/docs/types/DbConnectionType.html +1 -1
  123. package/docs/types/DbTypes.html +1 -1
  124. package/docs/types/DreamAppAllowedPackageManagersEnum.html +1 -1
  125. package/docs/types/DreamAssociationMetadata.html +1 -1
  126. package/docs/types/DreamAttributes.html +1 -1
  127. package/docs/types/DreamClassAssociationAndStatement.html +1 -1
  128. package/docs/types/DreamClassColumn.html +1 -1
  129. package/docs/types/DreamColumn.html +1 -1
  130. package/docs/types/DreamColumnNames.html +1 -1
  131. package/docs/types/DreamLogLevel.html +1 -1
  132. package/docs/types/DreamLogger.html +1 -1
  133. package/docs/types/DreamModelSerializerType.html +1 -1
  134. package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
  135. package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
  136. package/docs/types/DreamParamSafeAttributes.html +1 -1
  137. package/docs/types/DreamParamSafeColumnNames.html +1 -1
  138. package/docs/types/DreamSerializable.html +1 -1
  139. package/docs/types/DreamSerializableArray.html +1 -1
  140. package/docs/types/DreamSerializerKey.html +1 -1
  141. package/docs/types/DreamSerializers.html +1 -1
  142. package/docs/types/DreamTableSchema.html +1 -1
  143. package/docs/types/DreamVirtualColumns.html +1 -1
  144. package/docs/types/EncryptAlgorithm.html +1 -1
  145. package/docs/types/HasManyStatement.html +1 -1
  146. package/docs/types/HasOneStatement.html +1 -1
  147. package/docs/types/Hyphenized.html +1 -1
  148. package/docs/types/IdType.html +1 -1
  149. package/docs/types/OpenapiAllTypes.html +1 -1
  150. package/docs/types/OpenapiFormats.html +1 -1
  151. package/docs/types/OpenapiNumberFormats.html +1 -1
  152. package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
  153. package/docs/types/OpenapiPrimitiveTypes.html +1 -1
  154. package/docs/types/OpenapiSchemaArray.html +1 -1
  155. package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
  156. package/docs/types/OpenapiSchemaBase.html +1 -1
  157. package/docs/types/OpenapiSchemaBody.html +1 -1
  158. package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
  159. package/docs/types/OpenapiSchemaCommonFields.html +1 -1
  160. package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
  161. package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
  162. package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
  163. package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
  164. package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
  165. package/docs/types/OpenapiSchemaInteger.html +1 -1
  166. package/docs/types/OpenapiSchemaNull.html +1 -1
  167. package/docs/types/OpenapiSchemaNumber.html +1 -1
  168. package/docs/types/OpenapiSchemaObject.html +1 -1
  169. package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
  170. package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
  171. package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
  172. package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  173. package/docs/types/OpenapiSchemaObjectBase.html +1 -1
  174. package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
  175. package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
  176. package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
  177. package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
  178. package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
  179. package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  180. package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  181. package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  182. package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
  183. package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
  184. package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  185. package/docs/types/OpenapiSchemaString.html +1 -1
  186. package/docs/types/OpenapiShorthandAllTypes.html +1 -1
  187. package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  188. package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
  189. package/docs/types/OpenapiTypeField.html +1 -1
  190. package/docs/types/Pascalized.html +1 -1
  191. package/docs/types/PrimaryKeyType.html +1 -1
  192. package/docs/types/RoundingPrecision.html +1 -1
  193. package/docs/types/SerializerCasing.html +1 -1
  194. package/docs/types/SimpleObjectSerializerType.html +1 -1
  195. package/docs/types/Snakeified.html +1 -1
  196. package/docs/types/Timestamp.html +1 -1
  197. package/docs/types/UpdateableAssociationProperties.html +1 -1
  198. package/docs/types/UpdateableProperties.html +1 -1
  199. package/docs/types/ValidationType.html +1 -1
  200. package/docs/types/ViewModel.html +1 -1
  201. package/docs/types/ViewModelClass.html +1 -1
  202. package/docs/types/WhereStatementForDream.html +1 -1
  203. package/docs/types/WhereStatementForDreamClass.html +1 -1
  204. package/docs/variables/DateTime-1.html +1 -1
  205. package/docs/variables/DreamAppAllowedPackageManagersEnumValues.html +1 -1
  206. package/docs/variables/DreamConst.html +1 -1
  207. package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
  208. package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
  209. package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
  210. package/docs/variables/ops.html +1 -1
  211. package/docs/variables/primaryKeyTypes.html +1 -1
  212. package/package.json +1 -1
@@ -1,12 +1,14 @@
1
1
  import { sql, } from 'kysely';
2
2
  import pluralize from 'pluralize-esm';
3
3
  import writeSyncFile from '../../bin/helpers/sync.js';
4
+ import { CliFileWriter } from '../../cli/CliFileWriter.js';
4
5
  import DreamCLI from '../../cli/index.js';
5
6
  import _db from '../../db/index.js';
6
7
  import associationToGetterSetterProp from '../../decorators/field/association/associationToGetterSetterProp.js';
7
8
  import PackageManager from '../../dream-app/helpers/PackageManager.js';
8
9
  import DreamApp from '../../dream-app/index.js';
9
- import CannotAssociateThroughPolymorphic from '../../errors/associations/CannotAssociateThroughPolymorphic.js';
10
+ import ArrayTargetsIncompatibleWithThroughAssociation from '../../errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js';
11
+ import CannotAssociateThroughMultiplePolymorphics from '../../errors/associations/CannotAssociateThroughMultiplePolymorphics.js';
10
12
  import CannotJoinPolymorphicBelongsToError from '../../errors/associations/CannotJoinPolymorphicBelongsToError.js';
11
13
  import JoinAttemptedOnMissingAssociation from '../../errors/associations/JoinAttemptedOnMissingAssociation.js';
12
14
  import MissingRequiredAssociationAndClause from '../../errors/associations/MissingRequiredAssociationAndClause.js';
@@ -92,33 +94,41 @@ export default class KyselyQueryDriver extends QueryDriverBase {
92
94
  await generateMigration({ migrationName, columnsWithTypes });
93
95
  }
94
96
  static async sync(onSync, options = {}) {
95
- if (!options?.schemaOnly) {
96
- DreamCLI.logger.logStartProgress('writing db schema...');
97
- await writeSyncFile();
98
- DreamCLI.logger.logEndProgress();
99
- }
100
- DreamCLI.logger.logStartProgress('building dream schema...');
101
- const schemaBuilder = new SchemaBuilder();
102
- await schemaBuilder.build();
103
- DreamCLI.logger.logEndProgress();
104
- if (schemaBuilder.hasForeignKeyError && !options?.schemaOnly) {
105
- DreamCLI.logger.logStartProgress('triggering resync to correct for foreign key errors...');
106
- // TODO: make this customizable to enable dream apps to separate
107
- const cliCmd = EnvInternal.boolean('DREAM_CORE_DEVELOPMENT') ? 'dream' : 'psy';
108
- await DreamCLI.spawn(PackageManager.runCmd(`${cliCmd} sync --schema-only`), {
109
- onStdout: str => {
110
- DreamCLI.logger.logContinueProgress(`${str}`, {
111
- logPrefix: ' ├ [resync]',
112
- logPrefixColor: 'blue',
113
- });
114
- },
97
+ try {
98
+ if (!options?.schemaOnly) {
99
+ await DreamCLI.logger.logProgress('writing db schema...', async () => {
100
+ await writeSyncFile();
101
+ });
102
+ }
103
+ const schemaBuilder = new SchemaBuilder();
104
+ await DreamCLI.logger.logProgress('building dream schema...', async () => {
105
+ await schemaBuilder.build();
115
106
  });
116
- DreamCLI.logger.logEndProgress();
107
+ if (schemaBuilder.hasForeignKeyError && !options?.schemaOnly) {
108
+ await DreamCLI.logger.logProgress('triggering resync to correct for foreign key errors...', async () => {
109
+ // TODO: make this customizable to enable dream apps to separate
110
+ const cliCmd = EnvInternal.boolean('DREAM_CORE_DEVELOPMENT') ? 'dream' : 'psy';
111
+ await DreamCLI.spawn(PackageManager.runCmd(`${cliCmd} sync --schema-only`), {
112
+ onStdout: str => {
113
+ DreamCLI.logger.logContinueProgress(`${str}`, {
114
+ logPrefix: ' ├ [resync]',
115
+ logPrefixColor: 'blue',
116
+ });
117
+ },
118
+ });
119
+ });
120
+ }
121
+ if (!options?.schemaOnly) {
122
+ // intentionally leaving logs off here, since it allows other
123
+ // onSync handlers to determine their own independent logging approach
124
+ await onSync();
125
+ }
117
126
  }
118
- if (!options?.schemaOnly) {
119
- // intentionally leaving logs off here, since it allows other
120
- // onSync handlers to determine their own independent logging approach
121
- await onSync();
127
+ catch (error) {
128
+ console.error(error);
129
+ await DreamCLI.logger.logProgress('sync failed, reverting file contents...', async () => {
130
+ await CliFileWriter.revert();
131
+ });
122
132
  }
123
133
  }
124
134
  /**
@@ -1087,6 +1097,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1087
1097
  currentAssociationTableOrAlias,
1088
1098
  joinAndStatements,
1089
1099
  joinType,
1100
+ baseThroughAssociation: undefined,
1101
+ polymorphicCount: { count: 0 },
1090
1102
  });
1091
1103
  query = results.query;
1092
1104
  const association = results.association;
@@ -1282,7 +1294,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1282
1294
  * the `through` association are only added when the recursion returns
1283
1295
  * back to the association that kicked off the through associations.
1284
1296
  */
1285
- joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, }) {
1297
+ joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, baseThroughAssociation, polymorphicCount, }) {
1286
1298
  if (association.type === 'BelongsTo' || !association.through) {
1287
1299
  return {
1288
1300
  query,
@@ -1305,6 +1317,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1305
1317
  currentAssociationTableOrAlias: association.through,
1306
1318
  throughAssociations,
1307
1319
  joinType,
1320
+ baseThroughAssociation,
1321
+ polymorphicCount,
1308
1322
  });
1309
1323
  // The through association has both a `through` and a `source`. The `source`
1310
1324
  // is the association on the model that has now been joined. In our example,
@@ -1320,6 +1334,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1320
1334
  previousAssociationTableOrAlias: throughAssociation.as,
1321
1335
  throughAssociations,
1322
1336
  joinType,
1337
+ baseThroughAssociation,
1338
+ polymorphicCount,
1323
1339
  });
1324
1340
  }
1325
1341
  else {
@@ -1349,7 +1365,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1349
1365
  });
1350
1366
  const throughClass = throughAssociation.modelCB();
1351
1367
  if (Array.isArray(throughClass))
1352
- throw new CannotAssociateThroughPolymorphic({
1368
+ throw new ArrayTargetsIncompatibleWithThroughAssociation({
1353
1369
  dreamClass,
1354
1370
  association,
1355
1371
  });
@@ -1373,18 +1389,23 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1373
1389
  * the `through` association are only added when the recursion returns
1374
1390
  * back to the association that kicked off the through associations.
1375
1391
  */
1376
- applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinAndStatements = {}, throughAssociations = [], joinType, }) {
1392
+ applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinAndStatements = {}, throughAssociations = [], joinType, baseThroughAssociation, polymorphicCount, }) {
1377
1393
  const { name, alias } = extractAssociationMetadataFromAssociationName(currentAssociationTableOrAlias);
1378
1394
  const joinAndStatement = joinAndStatements[currentAssociationTableOrAlias];
1379
1395
  previousAssociationTableOrAlias = extractAssociationMetadataFromAssociationName(previousAssociationTableOrAlias).alias;
1380
1396
  currentAssociationTableOrAlias = alias;
1381
1397
  let association = dreamClass['getAssociationMetadata'](name);
1398
+ if (association?.polymorphic)
1399
+ polymorphicCount.count++;
1382
1400
  if (!association) {
1383
1401
  throw new JoinAttemptedOnMissingAssociation({
1384
1402
  dreamClass,
1385
1403
  associationName: currentAssociationTableOrAlias,
1386
1404
  });
1387
1405
  }
1406
+ baseThroughAssociation ??= association.through
1407
+ ? association
1408
+ : undefined;
1388
1409
  const results = this.joinsBridgeThroughAssociations({
1389
1410
  query,
1390
1411
  dreamClass,
@@ -1392,11 +1413,23 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1392
1413
  previousAssociationTableOrAlias,
1393
1414
  throughAssociations,
1394
1415
  joinType,
1416
+ baseThroughAssociation,
1417
+ polymorphicCount,
1395
1418
  });
1396
1419
  query = results.query;
1397
1420
  dreamClass = results.dreamClass;
1398
1421
  association = results.association;
1422
+ if (association?.polymorphic)
1423
+ polymorphicCount.count++;
1399
1424
  const timeToApplyThroughAssociations = throughAssociations.length && throughAssociations[0]?.source === association.as;
1425
+ const baseThroughAssociationToApply = association.polymorphic ? baseThroughAssociation : undefined;
1426
+ if (baseThroughAssociationToApply && polymorphicCount.count > 1)
1427
+ throw new CannotAssociateThroughMultiplePolymorphics({
1428
+ dreamClass,
1429
+ association,
1430
+ innerJoinStatements: this.query['innerJoinStatements'],
1431
+ leftJoinStatements: this.query['leftJoinStatements'],
1432
+ });
1400
1433
  const originalPreviousAssociationTableOrAlias = previousAssociationTableOrAlias;
1401
1434
  previousAssociationTableOrAlias = results.previousAssociationTableOrAlias;
1402
1435
  const throughClass = results.throughClass;
@@ -1434,19 +1467,34 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1434
1467
  });
1435
1468
  }
1436
1469
  if (association.type === 'BelongsTo') {
1437
- if (Array.isArray(association.modelCB()))
1470
+ if (!baseThroughAssociationToApply && Array.isArray(association.modelCB()))
1438
1471
  throw new CannotJoinPolymorphicBelongsToError({
1439
1472
  dreamClass,
1440
1473
  association,
1441
1474
  innerJoinStatements: this.query['innerJoinStatements'],
1442
1475
  leftJoinStatements: this.query['leftJoinStatements'],
1443
1476
  });
1444
- const to = association.modelCB().table;
1477
+ const to = (baseThroughAssociationToApply ?? association).modelCB().table;
1445
1478
  const joinTableExpression = currentAssociationTableOrAlias === to
1446
1479
  ? currentAssociationTableOrAlias
1447
1480
  : `${to} as ${currentAssociationTableOrAlias}`;
1448
1481
  query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
1449
- join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(), currentAssociationTableOrAlias));
1482
+ join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(undefined, {
1483
+ associatedClassOverride: baseThroughAssociationToApply?.modelCB(),
1484
+ }), currentAssociationTableOrAlias));
1485
+ if (baseThroughAssociationToApply) {
1486
+ /**
1487
+ * At this point, all `through` associations have been bridged and a
1488
+ * real association has been reached that is a polymorphic BelongsTo (it
1489
+ * is polymorphic and has an array of target models). Join with that
1490
+ * table conditionally based on the polymorphic foreign key type,
1491
+ * namespaced to the name of that association (which we know from the
1492
+ * target of the final `through` association)
1493
+ */
1494
+ join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement({
1495
+ [association.foreignKeyTypeField()]: baseThroughAssociationToApply.modelCB().sanitizedName,
1496
+ }, throughAssociations.at(-1).through)));
1497
+ }
1450
1498
  if (timeToApplyThroughAssociations) {
1451
1499
  throughAssociations.forEach((throughAssociation) => {
1452
1500
  join = this.applyAssociationAndStatementsToJoinStatement({
@@ -1462,6 +1510,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1462
1510
  join,
1463
1511
  tableNameOrAlias: currentAssociationTableOrAlias,
1464
1512
  association,
1513
+ throughAssociatedClassOverride: baseThroughAssociationToApply?.modelCB(),
1465
1514
  });
1466
1515
  join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
1467
1516
  return join;
@@ -1503,6 +1552,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1503
1552
  join,
1504
1553
  tableNameOrAlias: currentAssociationTableOrAlias,
1505
1554
  association,
1555
+ throughAssociatedClassOverride: baseThroughAssociationToApply?.modelCB(),
1506
1556
  });
1507
1557
  join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
1508
1558
  return join;
@@ -1592,9 +1642,9 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1592
1642
  if (missingRequiredWhereStatements.length)
1593
1643
  throw new MissingRequiredAssociationAndClause(association, missingRequiredWhereStatements[0]);
1594
1644
  }
1595
- conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, }) {
1645
+ conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, throughAssociatedClassOverride, }) {
1596
1646
  let scopesQuery = new Query(this.dreamInstance);
1597
- const associationClass = association.modelCB();
1647
+ const associationClass = throughAssociatedClassOverride ?? association.modelCB();
1598
1648
  const associationScopes = associationClass['scopes'].default;
1599
1649
  for (const scope of associationScopes) {
1600
1650
  if (!shouldBypassDefaultScope(scope.method, {
@@ -0,0 +1,16 @@
1
+ export default class ArrayTargetsIncompatibleWithThroughAssociation extends Error {
2
+ dreamClass;
3
+ association;
4
+ constructor({ dreamClass, association, }) {
5
+ super();
6
+ this.dreamClass = dreamClass;
7
+ this.association = association;
8
+ }
9
+ get message() {
10
+ return `
11
+ Through associations may not define an array of targets:
12
+ Dream class: ${this.dreamClass.sanitizedName}
13
+ Association: ${this.association.as}
14
+ `;
15
+ }
16
+ }
@@ -0,0 +1,24 @@
1
+ export default class CannotAssociateThroughMultiplePolymorphics extends Error {
2
+ dreamClass;
3
+ association;
4
+ innerJoinStatements;
5
+ leftJoinStatements;
6
+ constructor({ dreamClass, association, innerJoinStatements, leftJoinStatements, }) {
7
+ super();
8
+ this.dreamClass = dreamClass;
9
+ this.association = association;
10
+ this.innerJoinStatements = innerJoinStatements;
11
+ this.leftJoinStatements = leftJoinStatements;
12
+ }
13
+ get message() {
14
+ return `
15
+ Cannot associate through multiple polymorphic associations if one of them is a BelongsTo:
16
+ Dream class: ${this.dreamClass.sanitizedName}
17
+ Association: ${this.association.as}
18
+ Inner Join statements:
19
+ ${JSON.stringify(this.innerJoinStatements, null, 2)}
20
+ Left Join statements:
21
+ ${JSON.stringify(this.leftJoinStatements, null, 2)}
22
+ `;
23
+ }
24
+ }
@@ -14,7 +14,7 @@ export default class MissingThroughAssociationSource extends Error {
14
14
 
15
15
  \`${this.dreamClass.sanitizedName}\` association \`${this.association.through}\` points to \`${this.throughClass.sanitizedName}\`.
16
16
 
17
- Dream expects association \`${this.association.source}\` to be defiend on \`${this.throughClass.sanitizedName}\`, but \`${this.throughClass.sanitizedName}\` does not define association \`${this.association.source}\`.
17
+ Dream expects association \`${this.association.source}\` to be defined on \`${this.throughClass.sanitizedName}\`, but \`${this.throughClass.sanitizedName}\` does not define association \`${this.association.source}\`.
18
18
 
19
19
  There are two possible fixes:
20
20
 
@@ -1,6 +1,7 @@
1
1
  import { sql } from 'kysely';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import * as path from 'node:path';
4
+ import { CliFileWriter } from '../../cli/CliFileWriter.js';
4
5
  import { isPrimitiveDataType } from '../../db/dataTypes.js';
5
6
  import _db from '../../db/index.js';
6
7
  import DreamApp from '../../dream-app/index.js';
@@ -49,7 +50,7 @@ export const globalSchema = {
49
50
  // ${schemaConstContent}
50
51
  // `
51
52
  const schemaPath = path.join(dreamApp.projectRoot, dreamApp.paths.types, 'dream.ts');
52
- await fs.writeFile(schemaPath, newSchemaFileContents);
53
+ await CliFileWriter.write(schemaPath, newSchemaFileContents);
53
54
  }
54
55
  globalModelNames() {
55
56
  const dreamApp = DreamApp.getOrFail();
@@ -1,4 +1,5 @@
1
1
  export { default as DreamBin } from './bin/index.js';
2
+ export { CliFileWriter } from './cli/CliFileWriter.js';
2
3
  export { default as DreamCLI } from './cli/index.js';
3
4
  export { closeAllDbConnections, dreamDbConnections } from './db/DreamDbConnection.js';
4
5
  export { pgErrorType } from './db/errors.js';
@@ -0,0 +1,9 @@
1
+ export declare class CliFileWriter {
2
+ static write(filepath: string, contents: string): Promise<void>;
3
+ static revert(): Promise<void>;
4
+ static cache(filepath: string): Promise<void>;
5
+ private fileCache;
6
+ write(filepath: string, contents: string): Promise<void>;
7
+ revert(): Promise<void>;
8
+ cache(filepath: string): Promise<void>;
9
+ }
@@ -1,6 +1,7 @@
1
1
  import { DreamCliLoggerLogOpts } from '../../types/logger.js';
2
2
  export default class DreamCliLogger {
3
3
  log(text: string, { logPrefix, logPrefixColor, logPrefixBgColor }?: DreamCliLoggerLogOpts): void;
4
+ logProgress(text: string, cb: () => void | Promise<void>, { logPrefix, logPrefixColor, logPrefixBgColor }?: DreamCliLoggerLogOpts): Promise<void>;
4
5
  logStartProgress(text: string, { logPrefix, logPrefixColor, logPrefixBgColor }?: DreamCliLoggerLogOpts): void;
5
6
  logContinueProgress(text: string, { logPrefix, logPrefixColor, logPrefixBgColor }?: DreamCliLoggerLogOpts): void;
6
7
  logEndProgress(text?: string, { logPrefix, logPrefixColor, logPrefixBgColor }?: DreamCliLoggerLogOpts): void;
@@ -9,12 +9,12 @@ import { ValidationType } from '../types/validation.js';
9
9
  export default class Decorators<TD extends typeof Dream, T extends Dream = InstanceType<TD>> {
10
10
  BelongsTo<const AssociationGlobalNameOrNames extends keyof GlobalModelNameTableMap<T> | (keyof GlobalModelNameTableMap<T>)[]>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalNameOrNames, options?: NonPolymorphicBelongsToOptions<T, AssociationGlobalNameOrNames>): any;
11
11
  BelongsTo<const AssociationGlobalNameOrNames extends keyof GlobalModelNameTableMap<T> | (keyof GlobalModelNameTableMap<T>)[]>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalNameOrNames, options?: PolymorphicBelongsToOptions<T, AssociationGlobalNameOrNames>): any;
12
- HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasManyOptions<T, AssociationGlobalName>): any;
13
- HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasManyThroughOptions<T, AssociationGlobalName>): any;
14
- HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: PolymorphicHasManyOptions<T, AssociationGlobalName>): any;
15
- HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasOneOptions<T, AssociationGlobalName>): any;
16
- HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasOneThroughOptions<T, AssociationGlobalName>): any;
17
- HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: PolymorphicHasOneOptions<T, AssociationGlobalName>): any;
12
+ HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasManyOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
13
+ HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasManyThroughOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
14
+ HasMany<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: PolymorphicHasManyOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
15
+ HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasOneOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
16
+ HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: HasOneThroughOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
17
+ HasOne<const AssociationGlobalName extends keyof GlobalModelNameTableMap<T>, const ThroughAssociationName extends keyof T['schema'][T['table']]['associations']>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalName, options?: PolymorphicHasOneOptions<T, AssociationGlobalName, ThroughAssociationName>): any;
18
18
  /**
19
19
  * The Encrypted decorator automatically encrypts (upon setting)
20
20
  * and decrypts (upon getting) so that the encrypted value is
@@ -1,6 +1,6 @@
1
1
  import Dream from '../../../Dream.js';
2
2
  import { HasManyOptions, HasManyThroughOptions, PolymorphicHasManyOptions } from '../../../types/associations/hasMany.js';
3
3
  import { GlobalModelNameTableMap } from '../../../types/dream.js';
4
- export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasManyOptions<BaseInstance, AssociationGlobalName>): any;
5
- export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasManyThroughOptions<BaseInstance, AssociationGlobalName>): any;
6
- export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationNameOrNames: AssociationGlobalName, opts?: PolymorphicHasManyOptions<BaseInstance, AssociationGlobalName>): any;
4
+ export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasManyOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
5
+ export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasManyThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
6
+ export default function HasMany<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationNameOrNames: AssociationGlobalName, opts?: PolymorphicHasManyOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
@@ -1,6 +1,6 @@
1
1
  import Dream from '../../../Dream.js';
2
2
  import { HasOneOptions, HasOneThroughOptions, PolymorphicHasOneOptions } from '../../../types/associations/hasOne.js';
3
3
  import { GlobalModelNameTableMap } from '../../../types/dream.js';
4
- export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationName: AssociationGlobalName, opts?: HasOneOptions<BaseInstance, AssociationGlobalName>): any;
5
- export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasOneThroughOptions<BaseInstance, AssociationGlobalName>): any;
6
- export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>>(globalAssociationNameOrNames: AssociationGlobalName, opts?: PolymorphicHasOneOptions<BaseInstance, AssociationGlobalName>): any;
4
+ export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationName: AssociationGlobalName, opts?: HasOneOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
5
+ export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationNameOrNames: AssociationGlobalName, opts?: HasOneThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
6
+ export default function HasOne<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']>(globalAssociationNameOrNames: AssociationGlobalName, opts?: PolymorphicHasOneOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>): any;
@@ -0,0 +1,12 @@
1
+ import Dream from '../../Dream.js';
2
+ import { HasManyStatement } from '../../types/associations/hasMany.js';
3
+ import { HasOneStatement } from '../../types/associations/hasOne.js';
4
+ export default class ArrayTargetsIncompatibleWithThroughAssociation extends Error {
5
+ dreamClass: typeof Dream;
6
+ association: HasManyStatement<any, any, any, any> | HasOneStatement<any, any, any, any>;
7
+ constructor({ dreamClass, association, }: {
8
+ dreamClass: typeof Dream;
9
+ association: HasOneStatement<any, any, any, any> | HasManyStatement<any, any, any, any>;
10
+ });
11
+ get message(): string;
12
+ }
@@ -0,0 +1,17 @@
1
+ import Dream from '../../Dream.js';
2
+ import { BelongsToStatement } from '../../types/associations/belongsTo.js';
3
+ import { HasManyStatement } from '../../types/associations/hasMany.js';
4
+ import { HasOneStatement } from '../../types/associations/hasOne.js';
5
+ export default class CannotAssociateThroughMultiplePolymorphics extends Error {
6
+ dreamClass: typeof Dream;
7
+ association: HasManyStatement<any, any, any, any> | HasOneStatement<any, any, any, any> | BelongsToStatement<any, any, any, any>;
8
+ innerJoinStatements: any;
9
+ leftJoinStatements: any;
10
+ constructor({ dreamClass, association, innerJoinStatements, leftJoinStatements, }: {
11
+ dreamClass: typeof Dream;
12
+ association: HasManyStatement<any, any, any, any> | HasOneStatement<any, any, any, any> | BelongsToStatement<any, any, any, any>;
13
+ innerJoinStatements: any;
14
+ leftJoinStatements: any;
15
+ });
16
+ get message(): string;
17
+ }
@@ -1,4 +1,5 @@
1
1
  export { default as DreamBin } from './bin/index.js';
2
+ export { CliFileWriter } from './cli/CliFileWriter.js';
2
3
  export { default as DreamCLI } from './cli/index.js';
3
4
  export { closeAllDbConnections, dreamDbConnections } from './db/DreamDbConnection.js';
4
5
  export { pgErrorType } from './db/errors.js';
@@ -6,7 +6,9 @@ export interface BelongsToStatement<BaseInstance extends Dream, DB, Schema, Tabl
6
6
  globalAssociationNameOrNames: string[];
7
7
  type: 'BelongsTo';
8
8
  as: string;
9
- primaryKey: (associationInstance?: Dream) => keyof DB[TableName] & string;
9
+ primaryKey: (associationInstance?: Dream | undefined, opts?: {
10
+ associatedClassOverride?: typeof Dream | undefined;
11
+ }) => keyof DB[TableName] & string;
10
12
  primaryKeyValue: (associationInstance: Dream | null) => any;
11
13
  primaryKeyOverride?: (keyof DB[TableName] & string) | null;
12
14
  foreignKey: () => DreamColumnNames<BaseInstance> & string;
@@ -19,7 +19,10 @@ export interface BelongsToStatement<
19
19
  globalAssociationNameOrNames: string[]
20
20
  type: 'BelongsTo'
21
21
  as: string
22
- primaryKey: (associationInstance?: Dream) => keyof DB[TableName] & string
22
+ primaryKey: (
23
+ associationInstance?: Dream | undefined,
24
+ opts?: { associatedClassOverride?: typeof Dream | undefined }
25
+ ) => keyof DB[TableName] & string
23
26
  primaryKeyValue: (associationInstance: Dream | null) => any
24
27
  primaryKeyOverride?: (keyof DB[TableName] & string) | null
25
28
  foreignKey: () => DreamColumnNames<BaseInstance> & string
@@ -10,7 +10,7 @@ interface HasManyOnlyOptions<BaseInstance extends Dream, AssociationGlobalNameOr
10
10
  distinct?: TableColumnNames<BaseInstance['DB'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']> | boolean;
11
11
  order?: OrderStatement<BaseInstance['DB'], BaseInstance['schema'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']> | OrderStatement<BaseInstance['DB'], BaseInstance['schema'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']>[];
12
12
  }
13
- export type HasManyOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = HasOptions<BaseInstance, AssociationGlobalName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
14
- export type PolymorphicHasManyOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = PolymorphicHasOptions<BaseInstance, AssociationGlobalName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
15
- export type HasManyThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = HasThroughOptions<BaseInstance, AssociationGlobalName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
13
+ export type HasManyOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = HasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
14
+ export type PolymorphicHasManyOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = PolymorphicHasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
15
+ export type HasManyThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = HasThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>;
16
16
  export {};
@@ -65,16 +65,20 @@ interface HasManyOnlyOptions<
65
65
  export type HasManyOptions<
66
66
  BaseInstance extends Dream,
67
67
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
68
- > = HasOptions<BaseInstance, AssociationGlobalName> & HasManyOnlyOptions<BaseInstance, AssociationGlobalName>
68
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
69
+ > = HasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> &
70
+ HasManyOnlyOptions<BaseInstance, AssociationGlobalName>
69
71
 
70
72
  export type PolymorphicHasManyOptions<
71
73
  BaseInstance extends Dream,
72
74
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
73
- > = PolymorphicHasOptions<BaseInstance, AssociationGlobalName> &
75
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
76
+ > = PolymorphicHasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> &
74
77
  HasManyOnlyOptions<BaseInstance, AssociationGlobalName>
75
78
 
76
79
  export type HasManyThroughOptions<
77
80
  BaseInstance extends Dream,
78
81
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
79
- > = HasThroughOptions<BaseInstance, AssociationGlobalName> &
82
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
83
+ > = HasThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName> &
80
84
  HasManyOnlyOptions<BaseInstance, AssociationGlobalName>
@@ -3,6 +3,6 @@ import { AssociationTableNames } from '../db.js';
3
3
  import { GlobalModelNameTableMap } from '../dream.js';
4
4
  import { HasOptions, HasStatement, HasThroughOptions, PolymorphicHasOptions } from './shared.js';
5
5
  export type HasOneStatement<BaseInstance extends Dream, DB, Schema, ForeignTableName extends AssociationTableNames<DB, Schema> & keyof DB> = HasStatement<BaseInstance, DB, Schema, ForeignTableName, 'HasOne'>;
6
- export type HasOneOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = HasOptions<BaseInstance, AssociationGlobalName>;
7
- export type PolymorphicHasOneOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = PolymorphicHasOptions<BaseInstance, AssociationGlobalName>;
8
- export type HasOneThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = HasThroughOptions<BaseInstance, AssociationGlobalName>;
6
+ export type HasOneOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = HasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>;
7
+ export type PolymorphicHasOneOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = PolymorphicHasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>;
8
+ export type HasOneThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = HasThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>;
@@ -13,14 +13,17 @@ export type HasOneStatement<
13
13
  export type HasOneOptions<
14
14
  BaseInstance extends Dream,
15
15
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
16
- > = HasOptions<BaseInstance, AssociationGlobalName>
16
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
17
+ > = HasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>
17
18
 
18
19
  export type PolymorphicHasOneOptions<
19
20
  BaseInstance extends Dream,
20
21
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
21
- > = PolymorphicHasOptions<BaseInstance, AssociationGlobalName>
22
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
23
+ > = PolymorphicHasOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>
22
24
 
23
25
  export type HasOneThroughOptions<
24
26
  BaseInstance extends Dream,
25
27
  AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>,
26
- > = HasThroughOptions<BaseInstance, AssociationGlobalName>
28
+ ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'],
29
+ > = HasThroughOptions<BaseInstance, AssociationGlobalName, ThroughAssociationName>
@@ -68,7 +68,7 @@ export interface HasStatement<BaseInstance extends Dream, DB, Schema, ForeignTab
68
68
  type: HasType;
69
69
  withoutDefaultScopes?: DefaultScopeName<BaseInstance>[];
70
70
  }
71
- interface HasOptionsBase<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, AssociationTableName = TableNameForGlobalModelName<BaseInstance, AssociationGlobalName & keyof GlobalModelNameTableMap<BaseInstance>>> {
71
+ interface HasOptionsBase<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations'], ForeignTableName extends BaseInstance['schema'][BaseInstance['table']]['associations'][ThroughAssociationName]['tables'][number] = BaseInstance['schema'][BaseInstance['table']]['associations'][ThroughAssociationName]['tables'][number], AssociationTableName = TableNameForGlobalModelName<BaseInstance, AssociationGlobalName & keyof GlobalModelNameTableMap<BaseInstance>>> {
72
72
  dependent?: DependentOptions;
73
73
  foreignKey?: TableColumnNames<BaseInstance['DB'], AssociationTableName & keyof BaseInstance['DB']>;
74
74
  and?: OnStatementForAssociationDefinition<BaseInstance['DB'], BaseInstance['schema'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']>;
@@ -79,17 +79,17 @@ interface HasOptionsBase<BaseInstance extends Dream, AssociationGlobalName exten
79
79
  primaryKeyOverride?: DreamColumnNames<BaseInstance> | null;
80
80
  selfAnd?: SelfOnStatement<BaseInstance, BaseInstance['DB'], BaseInstance['schema'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']>;
81
81
  selfAndNot?: SelfOnStatement<BaseInstance, BaseInstance['DB'], BaseInstance['schema'], AssociationTableName & AssociationTableNames<BaseInstance['DB'], BaseInstance['schema']> & keyof BaseInstance['DB']>;
82
- source?: string;
83
- through?: keyof BaseInstance['schema'][BaseInstance['table']]['associations'];
82
+ source?: keyof BaseInstance['schema'][ForeignTableName]['associations'];
83
+ through?: ThroughAssociationName;
84
84
  withoutDefaultScopes?: DefaultScopeNameForTable<BaseInstance['schema'], AssociationTableName & keyof BaseInstance['DB']>[];
85
85
  }
86
86
  export type PolymorphicOption = 'polymorphic';
87
87
  export type ForeignKeyOption = 'foreignKey';
88
88
  type ThroughIncompatibleOptions = 'dependent' | 'primaryKeyOverride' | 'withoutDefaultScopes' | ForeignKeyOption | PolymorphicOption;
89
89
  type ThroughOnlyOptions = 'through' | 'source' | 'preloadThroughColumns';
90
- export type HasOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = Omit<HasOptionsBase<BaseInstance, AssociationGlobalName>, ThroughOnlyOptions | PolymorphicOption>;
91
- export type PolymorphicHasOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = HasOptionsBase<BaseInstance, AssociationGlobalName> & Required<Pick<HasOptionsBase<BaseInstance, AssociationGlobalName>, PolymorphicOption | ForeignKeyOption>>;
92
- export type HasThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>> = Omit<HasOptionsBase<BaseInstance, AssociationGlobalName>, ThroughIncompatibleOptions>;
90
+ export type HasOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = Omit<HasOptionsBase<BaseInstance, AssociationGlobalName, ThroughAssociationName>, ThroughOnlyOptions | PolymorphicOption>;
91
+ export type PolymorphicHasOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = HasOptionsBase<BaseInstance, AssociationGlobalName, ThroughAssociationName> & Required<Pick<HasOptionsBase<BaseInstance, AssociationGlobalName, ThroughAssociationName>, PolymorphicOption | ForeignKeyOption>>;
92
+ export type HasThroughOptions<BaseInstance extends Dream, AssociationGlobalName extends keyof GlobalModelNameTableMap<BaseInstance>, ThroughAssociationName extends keyof BaseInstance['schema'][BaseInstance['table']]['associations']> = Omit<HasOptionsBase<BaseInstance, AssociationGlobalName, ThroughAssociationName>, ThroughIncompatibleOptions>;
93
93
  export interface AssociationStatementsMap {
94
94
  belongsTo: readonly BelongsToStatement<any, any, any, any>[] | BelongsToStatement<any, any, any, any>[];
95
95
  hasMany: readonly HasManyStatement<any, any, any, any>[] | HasManyStatement<any, any, any, any>[];