@rvoh/dream 2.3.1 → 2.3.3

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 (234) hide show
  1. package/dist/cjs/src/bin/index.js +9 -2
  2. package/dist/cjs/src/cli/index.js +12 -3
  3. package/dist/cjs/src/dream/Query.js +9 -1
  4. package/dist/cjs/src/dream-app/index.js +6 -0
  5. package/dist/cjs/src/helpers/cli/generateDream.js +16 -21
  6. package/dist/cjs/src/helpers/cli/generateDreamContent.js +2 -2
  7. package/dist/cjs/src/helpers/cli/generateFactory.js +8 -22
  8. package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -2
  9. package/dist/cjs/src/helpers/cli/generateMigration.js +18 -26
  10. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +27 -2
  11. package/dist/cjs/src/helpers/cli/generateSerializer.js +10 -23
  12. package/dist/cjs/src/helpers/cli/generateSerializerContent.js +5 -7
  13. package/dist/cjs/src/helpers/cli/generateUnitSpec.js +7 -21
  14. package/dist/cjs/src/helpers/cli/modelClassNameFrom.js +15 -0
  15. package/dist/cjs/src/helpers/cli/writeGeneratedFile.js +26 -0
  16. package/dist/esm/src/bin/index.js +9 -2
  17. package/dist/esm/src/cli/index.js +12 -3
  18. package/dist/esm/src/dream/Query.js +9 -1
  19. package/dist/esm/src/dream-app/index.js +6 -0
  20. package/dist/esm/src/helpers/cli/generateDream.js +16 -21
  21. package/dist/esm/src/helpers/cli/generateDreamContent.js +2 -2
  22. package/dist/esm/src/helpers/cli/generateFactory.js +8 -22
  23. package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -2
  24. package/dist/esm/src/helpers/cli/generateMigration.js +18 -26
  25. package/dist/esm/src/helpers/cli/generateMigrationContent.js +27 -2
  26. package/dist/esm/src/helpers/cli/generateSerializer.js +10 -23
  27. package/dist/esm/src/helpers/cli/generateSerializerContent.js +5 -7
  28. package/dist/esm/src/helpers/cli/generateUnitSpec.js +7 -21
  29. package/dist/esm/src/helpers/cli/modelClassNameFrom.js +15 -0
  30. package/dist/esm/src/helpers/cli/writeGeneratedFile.js +26 -0
  31. package/dist/types/src/bin/index.d.ts +5 -0
  32. package/dist/types/src/cli/index.d.ts +11 -0
  33. package/dist/types/src/dream-app/index.d.ts +2 -0
  34. package/dist/types/src/helpers/cli/generateDream.d.ts +9 -6
  35. package/dist/types/src/helpers/cli/generateDreamContent.d.ts +3 -0
  36. package/dist/types/src/helpers/cli/generateFactory.d.ts +2 -1
  37. package/dist/types/src/helpers/cli/generateFactoryContent.d.ts +3 -1
  38. package/dist/types/src/helpers/cli/generateMigration.d.ts +8 -1
  39. package/dist/types/src/helpers/cli/generateSerializer.d.ts +2 -1
  40. package/dist/types/src/helpers/cli/generateSerializerContent.d.ts +3 -1
  41. package/dist/types/src/helpers/cli/modelClassNameFrom.d.ts +9 -0
  42. package/dist/types/src/helpers/cli/writeGeneratedFile.d.ts +18 -0
  43. package/dist/types/src/helpers/compact.d.ts +2 -2
  44. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +10 -10
  45. package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +10 -10
  46. package/dist/types/src/serializer/helpers/inferSerializerFromDreamOrViewModel.d.ts +1 -1
  47. package/dist/types/src/types/serializer.d.ts +1 -1
  48. package/dist/types/src/types/serializer.ts +1 -3
  49. package/docs/assets/search.js +1 -1
  50. package/docs/classes/db.DreamMigrationHelpers.html +9 -9
  51. package/docs/classes/db.KyselyQueryDriver.html +32 -32
  52. package/docs/classes/db.PostgresQueryDriver.html +33 -33
  53. package/docs/classes/db.QueryDriverBase.html +31 -31
  54. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  55. package/docs/classes/errors.ColumnOverflow.html +3 -3
  56. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  57. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  58. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  59. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  60. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  61. package/docs/classes/errors.InvalidClockTime.html +2 -2
  62. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  63. package/docs/classes/errors.InvalidDateTime.html +2 -2
  64. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  65. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  66. package/docs/classes/errors.NotNullViolation.html +3 -3
  67. package/docs/classes/errors.RecordNotFound.html +3 -3
  68. package/docs/classes/errors.ValidationError.html +3 -3
  69. package/docs/classes/index.CalendarDate.html +33 -33
  70. package/docs/classes/index.ClockTime.html +32 -32
  71. package/docs/classes/index.ClockTimeTz.html +35 -35
  72. package/docs/classes/index.DateTime.html +71 -71
  73. package/docs/classes/index.Decorators.html +19 -19
  74. package/docs/classes/index.Dream.html +116 -116
  75. package/docs/classes/index.DreamApp.html +10 -5
  76. package/docs/classes/index.DreamTransaction.html +2 -2
  77. package/docs/classes/index.Env.html +2 -2
  78. package/docs/classes/index.Query.html +56 -56
  79. package/docs/classes/system.CliFileWriter.html +2 -2
  80. package/docs/classes/system.DreamBin.html +2 -2
  81. package/docs/classes/system.DreamCLI.html +9 -5
  82. package/docs/classes/system.DreamImporter.html +2 -2
  83. package/docs/classes/system.DreamLogos.html +2 -2
  84. package/docs/classes/system.DreamSerializerBuilder.html +10 -10
  85. package/docs/classes/system.ObjectSerializerBuilder.html +10 -10
  86. package/docs/classes/system.PathHelpers.html +3 -3
  87. package/docs/classes/utils.Encrypt.html +2 -2
  88. package/docs/classes/utils.Range.html +2 -2
  89. package/docs/functions/db.closeAllDbConnections.html +1 -1
  90. package/docs/functions/db.dreamDbConnections.html +1 -1
  91. package/docs/functions/db.untypedDb.html +1 -1
  92. package/docs/functions/db.validateColumn.html +1 -1
  93. package/docs/functions/db.validateTable.html +1 -1
  94. package/docs/functions/errors.pgErrorType.html +1 -1
  95. package/docs/functions/index.DreamSerializer.html +1 -1
  96. package/docs/functions/index.ObjectSerializer.html +1 -1
  97. package/docs/functions/index.ReplicaSafe.html +1 -1
  98. package/docs/functions/index.STI.html +1 -1
  99. package/docs/functions/index.SoftDelete.html +1 -1
  100. package/docs/functions/utils.camelize.html +1 -1
  101. package/docs/functions/utils.capitalize.html +1 -1
  102. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  103. package/docs/functions/utils.compact.html +2 -2
  104. package/docs/functions/utils.groupBy.html +1 -1
  105. package/docs/functions/utils.hyphenize.html +1 -1
  106. package/docs/functions/utils.intersection.html +1 -1
  107. package/docs/functions/utils.isEmpty.html +1 -1
  108. package/docs/functions/utils.normalizeUnicode.html +1 -1
  109. package/docs/functions/utils.pascalize.html +1 -1
  110. package/docs/functions/utils.percent.html +1 -1
  111. package/docs/functions/utils.range-1.html +1 -1
  112. package/docs/functions/utils.round.html +1 -1
  113. package/docs/functions/utils.sanitizeString.html +1 -1
  114. package/docs/functions/utils.snakeify.html +1 -1
  115. package/docs/functions/utils.sort.html +1 -1
  116. package/docs/functions/utils.sortBy.html +1 -1
  117. package/docs/functions/utils.sortObjectByKey.html +1 -1
  118. package/docs/functions/utils.sortObjectByValue.html +1 -1
  119. package/docs/functions/utils.uncapitalize.html +1 -1
  120. package/docs/functions/utils.uniq.html +1 -1
  121. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  122. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  123. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  124. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  125. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  126. package/docs/interfaces/types.DecoratorContext.html +2 -2
  127. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  128. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  129. package/docs/interfaces/types.DurationObject.html +2 -2
  130. package/docs/interfaces/types.EncryptOptions.html +2 -2
  131. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  132. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  133. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  134. package/docs/modules/db.html +1 -1
  135. package/docs/modules/errors.html +1 -1
  136. package/docs/modules/index.html +1 -1
  137. package/docs/modules/openapi.html +1 -1
  138. package/docs/modules/system.html +1 -1
  139. package/docs/modules/types.html +1 -1
  140. package/docs/modules/utils.html +1 -1
  141. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  142. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  143. package/docs/types/openapi.OpenapiFormats.html +1 -1
  144. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  145. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  146. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  148. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  153. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
  154. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
  155. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
  156. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +1 -1
  157. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
  158. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  159. package/docs/types/openapi.OpenapiSchemaNull.html +1 -1
  160. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  161. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  162. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  163. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  164. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  165. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  166. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  167. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  168. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  169. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  170. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  171. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  172. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  173. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  174. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  175. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
  176. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
  177. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  178. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  179. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  180. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  181. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  182. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  183. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  184. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  185. package/docs/types/types.CalendarDateObject.html +1 -1
  186. package/docs/types/types.Camelized.html +1 -1
  187. package/docs/types/types.ClockTimeObject.html +1 -1
  188. package/docs/types/types.DbConnectionType.html +1 -1
  189. package/docs/types/types.DbTypes.html +1 -1
  190. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  191. package/docs/types/types.DreamAttributes.html +1 -1
  192. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  193. package/docs/types/types.DreamClassColumn.html +1 -1
  194. package/docs/types/types.DreamColumn.html +1 -1
  195. package/docs/types/types.DreamColumnNames.html +1 -1
  196. package/docs/types/types.DreamLogLevel.html +1 -1
  197. package/docs/types/types.DreamLogger.html +1 -1
  198. package/docs/types/types.DreamModelSerializerType.html +1 -1
  199. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  200. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  201. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  202. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  203. package/docs/types/types.DreamSerializable.html +1 -1
  204. package/docs/types/types.DreamSerializableArray.html +1 -1
  205. package/docs/types/types.DreamSerializerKey.html +1 -1
  206. package/docs/types/types.DreamSerializers.html +1 -1
  207. package/docs/types/types.DreamVirtualColumns.html +1 -1
  208. package/docs/types/types.DurationUnit.html +1 -1
  209. package/docs/types/types.EncryptAlgorithm.html +1 -1
  210. package/docs/types/types.HasManyStatement.html +1 -1
  211. package/docs/types/types.HasOneStatement.html +1 -1
  212. package/docs/types/types.Hyphenized.html +1 -1
  213. package/docs/types/types.Pascalized.html +1 -1
  214. package/docs/types/types.PrimaryKeyType.html +1 -1
  215. package/docs/types/types.RoundingPrecision.html +1 -1
  216. package/docs/types/types.SerializerCasing.html +1 -1
  217. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  218. package/docs/types/types.Snakeified.html +1 -1
  219. package/docs/types/types.StrictInterface.html +1 -1
  220. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  221. package/docs/types/types.UpdateableProperties.html +1 -1
  222. package/docs/types/types.ValidationType.html +1 -1
  223. package/docs/types/types.ViewModel.html +1 -1
  224. package/docs/types/types.ViewModelClass.html +1 -1
  225. package/docs/types/types.WeekdayName.html +1 -1
  226. package/docs/types/types.WhereStatementForDream.html +1 -1
  227. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  228. package/docs/variables/index.DreamConst.html +1 -1
  229. package/docs/variables/index.ops.html +1 -1
  230. package/docs/variables/openapi.openapiPrimitiveTypes-1.html +1 -1
  231. package/docs/variables/openapi.openapiShorthandPrimitiveTypes-1.html +1 -1
  232. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  233. package/docs/variables/system.primaryKeyTypes.html +1 -1
  234. package/package.json +13 -11
@@ -20,6 +20,8 @@ import ops from '../ops/index.js';
20
20
  import computedPaginatePage from './internal/computedPaginatePage.js';
21
21
  import convertDreamClassAndAssociationNameTupleArrayToPreloadArgs from './internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js';
22
22
  import extractNestedPaths from './internal/extractNestedPaths.js';
23
+ // Cache for extractNestedPaths results, keyed by "${sanitizedName}:${serializerKey}"
24
+ const extractedNestedPathsCache = new Map();
23
25
  export default class Query {
24
26
  /**
25
27
  * @internal
@@ -524,7 +526,13 @@ export default class Query {
524
526
  * @returns A Query with all serialization associations preloaded
525
527
  */
526
528
  preloadFor(serializerKey, modifierFn) {
527
- const preloadArgs = extractNestedPaths(this.dreamClass['serializationMap'](serializerKey));
529
+ const cacheKey = `${this.dreamClass.sanitizedName}:${serializerKey ?? 'default'}`;
530
+ let preloadArgs = extractedNestedPathsCache.get(cacheKey);
531
+ if (!preloadArgs) {
532
+ // Cache miss - compute and store
533
+ preloadArgs = extractNestedPaths(this.dreamClass['serializationMap'](serializerKey));
534
+ extractedNestedPathsCache.set(cacheKey, preloadArgs);
535
+ }
528
536
  let query = this;
529
537
  preloadArgs.forEach(dreamClassAndAssociationNameTupleArray => {
530
538
  query = query.preload(...convertDreamClassAndAssociationNameTupleArrayToPreloadArgs(dreamClassAndAssociationNameTupleArray, modifierFn));
@@ -7,6 +7,7 @@ import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppIni
7
7
  import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
8
8
  import DreamAppInitMissingPackageManager from '../errors/dream-app/DreamAppInitMissingPackageManager.js';
9
9
  import autogeneratedFileDisclaimer from '../helpers/cli/autoGeneratedFileDisclaimer.js';
10
+ import modelClassNameFrom from '../helpers/cli/modelClassNameFrom.js';
10
11
  import EnvInternal from '../helpers/EnvInternal.js';
11
12
  import globalClassNameFromFullyQualifiedModelName from '../helpers/globalClassNameFromFullyQualifiedModelName.js';
12
13
  import absoluteDreamPath from '../helpers/path/absoluteDreamPath.js';
@@ -87,6 +88,7 @@ export default class DreamApp {
87
88
  static get system() {
88
89
  return {
89
90
  globalClassNameFromFullyQualifiedModelName,
91
+ modelClassNameFrom,
90
92
  absoluteDreamPath,
91
93
  dreamPath,
92
94
  standardizeFullyQualifiedModelName,
@@ -412,6 +414,10 @@ function loggerArgToString(arg) {
412
414
  return arg;
413
415
  if (typeof arg === 'boolean')
414
416
  return arg;
417
+ if (arg === null)
418
+ return 'null';
419
+ if (arg === undefined)
420
+ return 'undefined';
415
421
  if (arg instanceof DateTime || arg instanceof CalendarDate || arg instanceof BaseClockTime) {
416
422
  return arg.toISO();
417
423
  }
@@ -1,39 +1,31 @@
1
- import * as fs from 'node:fs/promises';
2
- import DreamCLI from '../../cli/index.js';
3
- import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
4
- import dreamPath from '../path/dreamPath.js';
5
1
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
6
2
  import generateDreamContent from './generateDreamContent.js';
7
3
  import generateFactory from './generateFactory.js';
8
4
  import generateMigration from './generateMigration.js';
9
5
  import generateSerializer from './generateSerializer.js';
10
6
  import generateUnitSpec from './generateUnitSpec.js';
7
+ import modelClassNameFrom from './modelClassNameFrom.js';
8
+ import writeGeneratedFile from './writeGeneratedFile.js';
11
9
  export default async function generateDream({ fullyQualifiedModelName, columnsWithTypes, options, fullyQualifiedParentName, }) {
12
10
  fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
13
- const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(dreamPath('models'), `${fullyQualifiedModelName}.ts`);
14
- try {
15
- DreamCLI.logger.log(`[dream] generating dream: ${relFilePath}`);
16
- await fs.mkdir(absDirPath, { recursive: true });
17
- await fs.writeFile(absFilePath, generateDreamContent({
11
+ const modelClassName = modelClassNameFrom(fullyQualifiedModelName, options.modelName);
12
+ await writeGeneratedFile({
13
+ dreamPathKey: 'models',
14
+ fileName: `${fullyQualifiedModelName}.ts`,
15
+ content: generateDreamContent({
18
16
  fullyQualifiedModelName,
19
17
  columnsWithTypes,
20
18
  fullyQualifiedParentName,
21
19
  serializer: options.serializer,
22
20
  includeAdminSerializers: options.includeAdminSerializers,
23
21
  connectionName: options.connectionName,
24
- }));
25
- }
26
- catch (error) {
27
- throw new Error(`
28
- Something happened while trying to create the Dream file:
29
- ${relFilePath}
30
-
31
- Does this file already exist? Here is the error that was raised:
32
- ${error.message}
33
- `);
34
- }
22
+ tableName: options.tableName,
23
+ modelClassName,
24
+ }),
25
+ logLabel: 'dream',
26
+ });
35
27
  await generateUnitSpec({ fullyQualifiedModelName });
36
- await generateFactory({ fullyQualifiedModelName, columnsWithTypes });
28
+ await generateFactory({ fullyQualifiedModelName, columnsWithTypes, modelClassName });
37
29
  if (options.serializer)
38
30
  await generateSerializer({
39
31
  fullyQualifiedModelName,
@@ -41,6 +33,7 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
41
33
  fullyQualifiedParentName,
42
34
  stiBaseSerializer: options.stiBaseSerializer,
43
35
  includeAdminSerializers: options.includeAdminSerializers,
36
+ modelClassName,
44
37
  });
45
38
  const isSTI = !!fullyQualifiedParentName;
46
39
  if (columnsWithTypes.length || !isSTI) {
@@ -50,6 +43,8 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
50
43
  columnsWithTypes,
51
44
  fullyQualifiedModelName,
52
45
  fullyQualifiedParentName,
46
+ tableName: options.tableName,
47
+ modelClassName,
53
48
  });
54
49
  }
55
50
  }
@@ -31,7 +31,7 @@ ${tableMethod}${serializersMethod}${fieldsSection}
31
31
  }
32
32
  export function createModelConfig(options) {
33
33
  const fullyQualifiedModelName = standardizeFullyQualifiedModelName(options.fullyQualifiedModelName);
34
- const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
34
+ const modelClassName = options.modelClassName;
35
35
  const isSTI = !!options.fullyQualifiedParentName;
36
36
  let parentModelClassName;
37
37
  if (isSTI) {
@@ -40,7 +40,7 @@ export function createModelConfig(options) {
40
40
  }
41
41
  const connectionName = options.connectionName || 'default';
42
42
  const applicationModelName = connectionName === 'default' ? 'ApplicationModel' : `${pascalize(connectionName)}ApplicationModel`;
43
- const tableName = snakeify(pluralize(fullyQualifiedModelName.replace(/\//g, '_')));
43
+ const tableName = options.tableName || snakeify(pluralize(fullyQualifiedModelName.replace(/\//g, '_')));
44
44
  return {
45
45
  fullyQualifiedModelName,
46
46
  modelClassName,
@@ -1,24 +1,10 @@
1
- import * as fs from 'node:fs/promises';
2
- import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
3
- import dreamPath from '../path/dreamPath.js';
4
- import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
5
1
  import generateFactoryContent from './generateFactoryContent.js';
6
- import DreamCLI from '../../cli/index.js';
7
- export default async function generateFactory({ fullyQualifiedModelName, columnsWithTypes, }) {
8
- fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
9
- const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(dreamPath('factories'), `${fullyQualifiedModelName}Factory.ts`);
10
- try {
11
- DreamCLI.logger.log(`[dream] generating factory: ${relFilePath}`);
12
- await fs.mkdir(absDirPath, { recursive: true });
13
- await fs.writeFile(absFilePath, generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes }));
14
- }
15
- catch (error) {
16
- throw new Error(`
17
- Something happened while trying to create the spec file:
18
- ${relFilePath}
19
-
20
- Does this file already exist? Here is the error that was raised:
21
- ${error.message}
22
- `);
23
- }
2
+ import writeGeneratedFile from './writeGeneratedFile.js';
3
+ export default async function generateFactory({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }) {
4
+ await writeGeneratedFile({
5
+ dreamPathKey: 'factories',
6
+ fileName: `${fullyQualifiedModelName}Factory.ts`,
7
+ content: generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, modelClassName }),
8
+ logLabel: 'factory',
9
+ });
24
10
  }
@@ -4,7 +4,7 @@ import absoluteDreamPath from '../path/absoluteDreamPath.js';
4
4
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
5
5
  import uniq from '../uniq.js';
6
6
  import { optionalFromDescriptors } from './generateMigrationContent.js';
7
- export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, }) {
7
+ export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }) {
8
8
  fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
9
9
  const dreamTypeImports = ['UpdateableProperties'];
10
10
  const dreamImports = [];
@@ -129,7 +129,6 @@ export default function generateFactoryContent({ fullyQualifiedModelName, column
129
129
  }
130
130
  }
131
131
  const relativePath = absoluteDreamPath('models', fullyQualifiedModelName);
132
- const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
133
132
  return `\
134
133
  ${nodeImports.length ? `import { ${uniq(nodeImports).join(', ')} } from 'node:crypto'\n` : ''}${dreamImports.length ? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n` : ''}import { ${uniq(dreamTypeImports).join(', ')} } from '@rvoh/dream/types'
135
134
  import ${modelClassName} from '${relativePath}'${additionalImports.length ? '\n' + uniq(additionalImports).join('\n') : ''}
@@ -1,4 +1,3 @@
1
- import * as fs from 'node:fs/promises';
2
1
  import * as path from 'node:path';
3
2
  import pluralize from 'pluralize-esm';
4
3
  import generateMigrationContent from '../cli/generateMigrationContent.js';
@@ -6,52 +5,45 @@ import primaryKeyType from '../db/primaryKeyType.js';
6
5
  import hyphenize from '../hyphenize.js';
7
6
  import migrationVersion from '../migrationVersion.js';
8
7
  import pascalizePath from '../pascalizePath.js';
9
- import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
10
8
  import dreamPath from '../path/dreamPath.js';
11
9
  import snakeify from '../snakeify.js';
12
10
  import generateStiMigrationContent from './generateStiMigrationContent.js';
13
- import DreamCLI from '../../cli/index.js';
14
- export default async function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, }) {
15
- const { relFilePath, absFilePath } = connectionName === 'default'
16
- ? dreamFileAndDirPaths(path.join(dreamPath('db'), 'migrations'), `${migrationVersion()}-${hyphenize(migrationName).replace(/\//g, '-')}.ts`)
17
- : dreamFileAndDirPaths(path.join(dreamPath('db'), 'migrations', connectionName), `${migrationVersion()}-${hyphenize(migrationName).replace(/\//g, '-')}.ts`);
11
+ import writeGeneratedFile from './writeGeneratedFile.js';
12
+ export default async function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, tableName: explicitTableName, modelClassName, }) {
13
+ const migrationsBasePath = connectionName === 'default'
14
+ ? path.join(dreamPath('db'), 'migrations')
15
+ : path.join(dreamPath('db'), 'migrations', connectionName);
16
+ const fileName = `${migrationVersion()}-${hyphenize(migrationName).replace(/\//g, '-')}.ts`;
18
17
  const isSTI = !!fullyQualifiedParentName;
19
- let finalContent = '';
18
+ let content = '';
20
19
  if (isSTI) {
21
- finalContent = generateStiMigrationContent({
20
+ content = generateStiMigrationContent({
22
21
  table: snakeify(pluralize(pascalizePath(fullyQualifiedParentName))),
23
22
  columnsWithTypes,
24
23
  primaryKeyType: primaryKeyType(connectionName),
25
- stiChildClassName: pascalizePath(fullyQualifiedModelName),
24
+ stiChildClassName: modelClassName || pascalizePath(fullyQualifiedModelName),
26
25
  });
27
26
  }
28
27
  else if (fullyQualifiedModelName) {
29
- finalContent = generateMigrationContent({
30
- table: snakeify(pluralize(pascalizePath(fullyQualifiedModelName))),
28
+ content = generateMigrationContent({
29
+ table: explicitTableName || snakeify(pluralize(pascalizePath(fullyQualifiedModelName))),
31
30
  columnsWithTypes,
32
31
  primaryKeyType: primaryKeyType(connectionName),
33
32
  });
34
33
  }
35
34
  else {
36
35
  const tableName = migrationName.match(/-to-(.+)$/)?.[1];
37
- finalContent = generateMigrationContent({
36
+ content = generateMigrationContent({
38
37
  table: tableName ? pluralize(snakeify(tableName)) : '<table-name>',
39
38
  columnsWithTypes,
40
39
  primaryKeyType: primaryKeyType(connectionName),
41
40
  createOrAlter: 'alter',
42
41
  });
43
42
  }
44
- try {
45
- DreamCLI.logger.log(`[dream] generating migration: ${relFilePath}`);
46
- await fs.writeFile(absFilePath, finalContent);
47
- }
48
- catch (error) {
49
- throw new Error(`
50
- Something happened while trying to create the migration file:
51
- ${relFilePath}
52
-
53
- Does this file already exist? Here is the error that was raised:
54
- ${error.message}
55
- `);
56
- }
43
+ await writeGeneratedFile({
44
+ basePath: migrationsBasePath,
45
+ fileName,
46
+ content,
47
+ logLabel: 'migration',
48
+ });
57
49
  }
@@ -1,9 +1,12 @@
1
1
  import pluralize from 'pluralize-esm';
2
+ import lookupModelByGlobalName from '../../dream-app/helpers/lookupModelByGlobalName.js';
2
3
  import Query from '../../dream/Query.js';
3
4
  import InvalidDecimalFieldPassedToGenerator from '../../errors/InvalidDecimalFieldPassedToGenerator.js';
4
5
  import camelize from '../camelize.js';
5
6
  import compact from '../compact.js';
7
+ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
6
8
  import snakeify from '../snakeify.js';
9
+ import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
7
10
  const STI_TYPE_COLUMN_NAME = 'type';
8
11
  const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
9
12
  export default function generateMigrationContent({ connectionName = 'default', table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', stiChildClassName, } = {}) {
@@ -43,6 +46,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
43
46
  columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
44
47
  primaryKeyType,
45
48
  omitInlineNonNull,
49
+ originalAssociationName: nonStandardAttributeName,
46
50
  }));
47
51
  attributeName = snakeify(nonStandardAttributeName.split('/').pop());
48
52
  attributeName = associationNameToForeignKey(attributeName);
@@ -279,10 +283,10 @@ function attributeTypeString(attributeType) {
279
283
  }
280
284
  }
281
285
  }
282
- function generateBelongsToStr(connectionName, associationName, { primaryKeyType, omitInlineNonNull: optional = false, }) {
286
+ function generateBelongsToStr(connectionName, associationName, { primaryKeyType, omitInlineNonNull: optional = false, originalAssociationName, }) {
283
287
  const dbDriverClass = Query.dbDriverClass(connectionName);
284
288
  const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
285
- const references = pluralize(associationName.replace(/\//g, '_').replace(/_id$/, ''));
289
+ const references = lookupReferencesTable(associationName, originalAssociationName);
286
290
  return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
287
291
  }
288
292
  function generateIdStr({ primaryKeyType }) {
@@ -312,6 +316,27 @@ function generateIdStr({ primaryKeyType }) {
312
316
  return `.addColumn('id', '${primaryKeyType}', col => col.primaryKey())`;
313
317
  }
314
318
  }
319
+ /**
320
+ * Determines the referenced table name for a belongs_to association.
321
+ * First tries to look up the actual model to get its table name (handles
322
+ * custom table name overrides). Falls back to deriving the table name
323
+ * from the association string if the model isn't found.
324
+ */
325
+ function lookupReferencesTable(snakeAssociationName, originalAssociationName) {
326
+ if (originalAssociationName) {
327
+ try {
328
+ const globalName = globalClassNameFromFullyQualifiedModelName(standardizeFullyQualifiedModelName(originalAssociationName));
329
+ const model = lookupModelByGlobalName(globalName);
330
+ if (model?.table) {
331
+ return model.table;
332
+ }
333
+ }
334
+ catch {
335
+ // Model not found or DreamApp not initialized — fall through to string derivation
336
+ }
337
+ }
338
+ return pluralize(snakeAssociationName.replace(/\//g, '_').replace(/_id$/, ''));
339
+ }
315
340
  function associationNameToForeignKey(associationName) {
316
341
  return snakeify(associationName.replace(/\//g, '_').replace(/_id$/, '') + '_id');
317
342
  }
@@ -1,30 +1,17 @@
1
- import * as fs from 'node:fs/promises';
2
- import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
3
- import dreamPath from '../path/dreamPath.js';
4
- import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
5
1
  import generateSerializerContent from './generateSerializerContent.js';
6
- import DreamCLI from '../../cli/index.js';
7
- export default async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
8
- fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
9
- const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(dreamPath('serializers'), `${fullyQualifiedModelName}Serializer.ts`);
10
- try {
11
- DreamCLI.logger.log(`[dream] generating serializer: ${relFilePath}`);
12
- await fs.mkdir(absDirPath, { recursive: true });
13
- await fs.writeFile(absFilePath, generateSerializerContent({
2
+ import writeGeneratedFile from './writeGeneratedFile.js';
3
+ export default async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, modelClassName, }) {
4
+ await writeGeneratedFile({
5
+ dreamPathKey: 'serializers',
6
+ fileName: `${fullyQualifiedModelName}Serializer.ts`,
7
+ content: generateSerializerContent({
14
8
  fullyQualifiedModelName,
15
9
  columnsWithTypes,
16
10
  fullyQualifiedParentName,
17
11
  stiBaseSerializer,
18
12
  includeAdminSerializers,
19
- }));
20
- }
21
- catch (error) {
22
- throw new Error(`
23
- Something happened while trying to create the serializer file:
24
- ${relFilePath}
25
-
26
- Does this file already exist? Here is the error that was raised:
27
- ${error.message}
28
- `);
29
- }
13
+ modelClassName,
14
+ }),
15
+ logLabel: 'serializer',
16
+ });
30
17
  }
@@ -4,7 +4,7 @@ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFu
4
4
  import absoluteDreamPath from '../path/absoluteDreamPath.js';
5
5
  import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
6
6
  import uniq from '../uniq.js';
7
- export default function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
7
+ export default function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, modelClassName, }) {
8
8
  fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
9
9
  const additionalImports = [];
10
10
  const dreamImports = [];
@@ -16,8 +16,7 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
16
16
  else {
17
17
  dreamImports.push('DreamSerializer');
18
18
  }
19
- const relatedModelImport = importStatementForModel(fullyQualifiedModelName);
20
- const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
19
+ const relatedModelImport = importStatementForModel(modelClassName, fullyQualifiedModelName);
21
20
  const modelInstanceName = camelize(modelClassName);
22
21
  const modelSerializerSignature = stiBaseSerializer
23
22
  ? `<T extends ${modelClassName}>(StiChildClass: typeof ${modelClassName}, ${modelInstanceName}: T)`
@@ -94,10 +93,9 @@ function importStatementForSerializer(originModelName, destinationModelName) {
94
93
  const importFrom = absoluteDreamPath('serializers', destinationModelName);
95
94
  return `import { ${defaultSerializer}, ${summarySerializer} } from '${importFrom}'\n`;
96
95
  }
97
- function importStatementForModel(originModelName, destinationModelName = originModelName) {
98
- const modelName = globalClassNameFromFullyQualifiedModelName(destinationModelName);
99
- const importFrom = absoluteDreamPath('models', destinationModelName);
100
- return `import ${modelName} from '${importFrom}'\n`;
96
+ function importStatementForModel(modelClassName, fullyQualifiedModelName) {
97
+ const importFrom = absoluteDreamPath('models', fullyQualifiedModelName);
98
+ return `import ${modelClassName} from '${importFrom}'\n`;
101
99
  }
102
100
  function fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName) {
103
101
  return fullyQualifiedModelName.replace(/\//g, '');
@@ -1,24 +1,10 @@
1
- import * as fs from 'node:fs/promises';
2
- import DreamCLI from '../../cli/index.js';
3
- import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
4
- import dreamPath from '../path/dreamPath.js';
5
- import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
6
1
  import generateUnitSpecContent from './generateUnitSpecContent.js';
2
+ import writeGeneratedFile from './writeGeneratedFile.js';
7
3
  export default async function generateUnitSpec({ fullyQualifiedModelName, }) {
8
- fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
9
- const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(dreamPath('modelSpecs'), `${fullyQualifiedModelName}.spec.ts`);
10
- try {
11
- DreamCLI.logger.log(`[dream] generating spec: ${relFilePath}`);
12
- await fs.mkdir(absDirPath, { recursive: true });
13
- await fs.writeFile(absFilePath, generateUnitSpecContent({ fullyQualifiedModelName }));
14
- }
15
- catch (error) {
16
- throw new Error(`
17
- Something happened while trying to create the spec file:
18
- ${relFilePath}
19
-
20
- Does this file already exist? Here is the error that was raised:
21
- ${error.message}
22
- `);
23
- }
4
+ await writeGeneratedFile({
5
+ dreamPathKey: 'modelSpecs',
6
+ fileName: `${fullyQualifiedModelName}.spec.ts`,
7
+ content: generateUnitSpecContent({ fullyQualifiedModelName }),
8
+ logLabel: 'spec',
9
+ });
24
10
  }
@@ -0,0 +1,15 @@
1
+ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
2
+ import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
3
+ /**
4
+ * Returns the model class name, either from an explicit override or derived
5
+ * from the fully qualified model name.
6
+ *
7
+ * @param fullyQualifiedModelName - e.g. "Room/Kitchen"
8
+ * @param modelNameOverride - optional explicit class name, e.g. "Kitchen"
9
+ * @returns The model class name, e.g. "RoomKitchen" (derived) or "Kitchen" (override)
10
+ */
11
+ export default function modelClassNameFrom(fullyQualifiedModelName, modelNameOverride) {
12
+ if (modelNameOverride)
13
+ return modelNameOverride;
14
+ return globalClassNameFromFullyQualifiedModelName(standardizeFullyQualifiedModelName(fullyQualifiedModelName));
15
+ }
@@ -0,0 +1,26 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import DreamCLI from '../../cli/index.js';
3
+ import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
4
+ import dreamPath from '../path/dreamPath.js';
5
+ /**
6
+ * Common file-writing helper used by all Dream generators.
7
+ * Handles directory creation, file writing, logging, and error wrapping.
8
+ */
9
+ export default async function writeGeneratedFile({ dreamPathKey, basePath, fileName, content, logLabel, }) {
10
+ const resolvedBasePath = basePath ?? dreamPath(dreamPathKey);
11
+ const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(resolvedBasePath, fileName);
12
+ try {
13
+ DreamCLI.logger.log(`[dream] generating ${logLabel}: ${relFilePath}`);
14
+ await fs.mkdir(absDirPath, { recursive: true });
15
+ await fs.writeFile(absFilePath, content);
16
+ }
17
+ catch (error) {
18
+ throw new Error(`
19
+ Something happened while trying to create the ${logLabel} file:
20
+ ${relFilePath}
21
+
22
+ Does this file already exist? Here is the error that was raised:
23
+ ${error.message}
24
+ `);
25
+ }
26
+ }
@@ -13,10 +13,15 @@ export default class DreamBin {
13
13
  serializer: boolean;
14
14
  stiBaseSerializer: boolean;
15
15
  connectionName: string;
16
+ tableName?: string;
17
+ adminSerializers?: boolean;
18
+ modelName?: string;
16
19
  }): Promise<void>;
17
20
  static generateStiChild(fullyQualifiedModelName: string, fullyQualifiedParentName: string, columnsWithTypes: string[], options: {
18
21
  serializer: boolean;
19
22
  connectionName: string;
23
+ adminSerializers?: boolean;
24
+ modelName?: string;
20
25
  }): Promise<void>;
21
26
  static generateMigration(migrationName: string, columnsWithTypes: string[], connectionName: string): Promise<void>;
22
27
  private static buildDocs;
@@ -2,6 +2,8 @@ import { SpawnOptions } from 'child_process';
2
2
  import { Command } from 'commander';
3
3
  import DreamApp, { DreamAppInitOptions } from '../dream-app/index.js';
4
4
  import DreamCliLogger from './logger/DreamCliLogger.js';
5
+ export declare const CLI_INDENT = " ";
6
+ export declare const baseColumnsWithTypesDescription = "space separated snake-case (except for belongs_to model name) properties like this:\n title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to\n \n all properties default to not nullable; null can be allowed by appending ':optional':\n subtitle:string:optional\n \n supported types:\n - uuid:\n - uuid[]:\n a column optimized for storing UUIDs\n \n - citext:\n - citext[]:\n case insensitive text (indexes and queries are automatically case insensitive)\n \n - string:\n - string[]:\n varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional\n \n - text\n - text[]\n - date\n - date[]\n - datetime\n - datetime[]\n - time\n - time[]\n - timetz\n - timetz[]\n - integer\n - integer[]\n \n - decimal:\n - decimal[]:\n precision,scale is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: volume:decimal[]:3,2\n \n - enum:\n - enum[]:\n include the enum name to automatically create the enum:\n type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional\n \n omit the enum values to leverage an existing enum (omits the enum type creation):\n type:enum:room_types or type:enum:room_types:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: type:enum[]:room_types:bathroom,kitchen,bedroom";
5
7
  export default class DreamCLI {
6
8
  /**
7
9
  * Starts the Dream console
@@ -17,6 +19,9 @@ export default class DreamCLI {
17
19
  }): void;
18
20
  /**
19
21
  * @internal
22
+ *
23
+ * Called by Psychic (and other consumers) to programmatically generate a
24
+ * Dream model with all associated files.
20
25
  */
21
26
  static generateDream(opts: {
22
27
  fullyQualifiedModelName: string;
@@ -26,6 +31,12 @@ export default class DreamCLI {
26
31
  serializer: boolean;
27
32
  stiBaseSerializer: boolean;
28
33
  includeAdminSerializers: boolean;
34
+ tableName?: string | undefined;
35
+ /**
36
+ * Optional model class name override. If provided, generators use it
37
+ * instead of deriving the class name from the fully qualified model name.
38
+ */
39
+ modelName?: string | undefined;
29
40
  };
30
41
  fullyQualifiedParentName?: string | undefined;
31
42
  }): Promise<void>;
@@ -4,6 +4,7 @@ import Dream from '../Dream.js';
4
4
  import QueryDriverBase from '../dream/QueryDriver/Base.js';
5
5
  import { EncryptOptions } from '../encrypt/index.js';
6
6
  import autogeneratedFileDisclaimer from '../helpers/cli/autoGeneratedFileDisclaimer.js';
7
+ import modelClassNameFrom from '../helpers/cli/modelClassNameFrom.js';
7
8
  import globalClassNameFromFullyQualifiedModelName from '../helpers/globalClassNameFromFullyQualifiedModelName.js';
8
9
  import absoluteDreamPath from '../helpers/path/absoluteDreamPath.js';
9
10
  import dreamPath from '../helpers/path/dreamPath.js';
@@ -56,6 +57,7 @@ export default class DreamApp {
56
57
  */
57
58
  static get system(): {
58
59
  globalClassNameFromFullyQualifiedModelName: typeof globalClassNameFromFullyQualifiedModelName;
60
+ modelClassNameFrom: typeof modelClassNameFrom;
59
61
  absoluteDreamPath: typeof absoluteDreamPath;
60
62
  dreamPath: typeof dreamPath;
61
63
  standardizeFullyQualifiedModelName: typeof standardizeFullyQualifiedModelName;
@@ -1,11 +1,14 @@
1
+ export interface GenerateDreamOptions {
2
+ connectionName: string;
3
+ serializer: boolean;
4
+ stiBaseSerializer: boolean;
5
+ includeAdminSerializers: boolean;
6
+ tableName?: string | undefined;
7
+ modelName?: string | undefined;
8
+ }
1
9
  export default function generateDream({ fullyQualifiedModelName, columnsWithTypes, options, fullyQualifiedParentName, }: {
2
10
  fullyQualifiedModelName: string;
3
11
  columnsWithTypes: string[];
4
- options: {
5
- connectionName: string;
6
- serializer: boolean;
7
- stiBaseSerializer: boolean;
8
- includeAdminSerializers: boolean;
9
- };
12
+ options: GenerateDreamOptions;
10
13
  fullyQualifiedParentName?: string | undefined;
11
14
  }): Promise<void>;
@@ -5,6 +5,9 @@ interface GenerateDreamContentOptions {
5
5
  connectionName?: string;
6
6
  serializer: boolean;
7
7
  includeAdminSerializers: boolean;
8
+ tableName?: string | undefined;
9
+ /** Model class name, computed once via modelClassNameFrom in the orchestrator. */
10
+ modelClassName: string;
8
11
  }
9
12
  export interface ModelConfig {
10
13
  fullyQualifiedModelName: string;
@@ -1,4 +1,5 @@
1
- export default function generateFactory({ fullyQualifiedModelName, columnsWithTypes, }: {
1
+ export default function generateFactory({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }: {
2
2
  fullyQualifiedModelName: string;
3
3
  columnsWithTypes: string[];
4
+ modelClassName: string;
4
5
  }): Promise<void>;
@@ -1,4 +1,6 @@
1
- export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, }: {
1
+ export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }: {
2
2
  fullyQualifiedModelName: string;
3
3
  columnsWithTypes: string[];
4
+ /** Model class name, computed once via modelClassNameFrom in the orchestrator. */
5
+ modelClassName: string;
4
6
  }): string;
@@ -1,7 +1,14 @@
1
- export default function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, }: {
1
+ export default function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, tableName: explicitTableName, modelClassName, }: {
2
2
  migrationName: string;
3
3
  columnsWithTypes: string[];
4
4
  connectionName: string;
5
5
  fullyQualifiedModelName?: string | undefined;
6
6
  fullyQualifiedParentName?: string | undefined;
7
+ tableName?: string | undefined;
8
+ /**
9
+ * Model class name, computed once via modelClassNameFrom in the orchestrator.
10
+ * Required when generating a migration for a model (especially STI children).
11
+ * Omitted for standalone `g:migration` commands.
12
+ */
13
+ modelClassName?: string | undefined;
7
14
  }): Promise<void>;
@@ -1,7 +1,8 @@
1
- export default function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }: {
1
+ export default function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, modelClassName, }: {
2
2
  fullyQualifiedModelName: string;
3
3
  columnsWithTypes: string[];
4
4
  fullyQualifiedParentName?: string | undefined;
5
5
  stiBaseSerializer: boolean;
6
6
  includeAdminSerializers: boolean;
7
+ modelClassName: string;
7
8
  }): Promise<void>;